Apps Home
|
Create an App
Multi Extra Goal Sweetkathe09
Author:
1990_laurita
Description
Source Code
Launch App
Current Users
Created by:
1990_Laurita
/* Name: Multi-Goal Author: mx2k6 MOD: 1990_laurita Version History ============================================ v1.0 08/02/2013: First release v1.1 22/02/2013: Added /stats and /reset commands. See Description for more v1.2 08/03/2013: Added /skip (suggestion from jcummings) v1.3 12/03/2013: Added /goals command for moderators and /upnext command for broadcasters. See Description for more v1.4 13/03/2013: Minor cleanup to make code more readable. Modified /upnext to actually use the broadcaster's message instead of chat notice v1.5 07/04/2013: Added some debugging code so I can get to the bottom of why chat commands don't always respond v1.6 13/04/2013: Fixed an embarrassing bug where all broadcaster and debug commands were ignored v1.7 20/04/2013: Tipper leaderboard now available on /stats output - see who your top 10 tippers are v1.8 21/04/2013: Goal timer function now available - /timer x now sets a countdown to when the goal needs tp be in by v1.9 05/05/2013: Stats junkies rejoice! /stats will now display an approximate token count per minute, to help you work out whether you'll make more tokens camming or flipping burgers. Also, tip goal king now stands out more! v1.10 05/05/2013: Now optionally highlight your highest total tipper (light purple currently - make suggestions people!) so the one who contributes the most can show off too! v1.11 05/05/2013: Timer stability improvements. Added timer debugging code. Type '/verbose' (broadcaster ONLY) to get precise dates and times of timer interval for when requesting support v1.12 18/05/2013: Clarified stats text relating to per minute figures. Changed highest tipper to no longer have a green "fanclub" name until such time as we can change the colour to a custom one v1.13 31/05/2013: Added ability for high tippers to "opt out" of being highlighted by typing "/donotwant" after they tip v1.14 05/06/2013: Added ability to directly manipulate tokens toward goals with /addtokens and /removetokens. See /help for more v1.15 02/07/2013: Timer now automatically clears if a goal is met rather than continuing on to zero v1.16 03/07/2013: Added a sixth goal... HOW MANY DO YOU PEOPLE NEED?!? Also, fixed a bug where total highest tipper got notified even when their highlight is disabled v1.17 04/07/2013: Allowed looping final goal if broadcaster chooses to v1.18 05/07/2013: Time's up message (when timer is in use) now uses a graphic to draw attention to it v1.19 19/07/2013: Notices (where applicable) now stand out more v1.20 10/08/2013: Colour schemes for the tipper highlights (suggestion from ashley93bad), bug fixes for opt-out v1.21 17/08/2013: More colour schemes added v1.22 28/09/2013: Fixed an issue with /skip which could reduce ongoing goal token quantities. Added manual progression mode- app eats tips once each goal is met until superuser types /continue command v1.23 16/11/2013: Added "Random" colour scheme v1.24 07/12/2013: Added "Purple" colour scheme, changed "Timer Countdown" warnings to be orange (stand out more) v1.25 21/12/2013: Changed to use new cb.sendNotice instead of cb.chatNotice, so we can send messages to entire groups v1.26 06/01/2014: Removed redundant "Amethyst" and "Ocean" schemes. Cleaned up colour codes so I can add new themes easier v1.27 10/01/2014: Added debugging code in case of an error I've been alerted to. IF YOU SEE THE NASTY ERROR MESSAGE, LET ME KNOW! v1.28 20/01/2014: Updated parseOptions to quit parsing goals if a blank goal is found, which occurs if settings are incorrectly filled in v1.29 01/02/2014: Added new "hide total tips" option, stats beefed up a (little) bit. Added '/support' command for broadcaster to grant developer broadcaster access. See notes! v1.30 03/02/2014: Removed "/verbose" command. The verbose data was effectively useless anyway, so now if verbose is activated by the developer cb.log() is used instead. Also, fix for potential crash if random colour scheme used. Also ran Resharper over the code to clean it up a bit v1.31 06/02/2014: Fixed defect which caused panel to not appear until someone tipped v1.32 09/03/2014: Added notification functions so that important actions are notified v1.33 01/05/2014: Added ability to add goals at runtime with /add <tokens> <description>, or remove the final goal with /delete Credits and Props ============================================ Based on the bog standard tip goal app, with multiple goals, tip goal king, goal timers, some random crap and less general suckfulness. */ var APP_VERSION = 1.33; var APP_DEBUG = false; var TOTAL_GOALS = 20; var time_started = null; if (cb == undefined) { var cb = {}; } // colours var Colours = { AliceBlue: "#F0F8FF", AntiqueWhite: "#FAEBD7", Aqua: "#00FFFF", Aquamarine: "#7FFFD4", Azure: "#F0FFFF", Beige: "#F5F5DC", Bisque: "#FFE4C4", Black: "#000000", BlanchedAlmond: "#FFEBCD", Blue: "#0000FF", BlueViolet: "#8A2BE2", Brown: "#A52A2A", BurlyWood: "#DEB887", CadetBlue: "#5F9EA0", Chartreuse: "#7FFF00", Chocolate: "#D2691E", Coral: "#FF7F50", CornflowerBlue: "#6495ED", Cornsilk: "#FFF8DC", Crimson: "#DC143C", Cyan: "#00FFFF", DarkBlue: "#00008B", DarkCyan: "#008B8B", DarkGoldenRod: "#B8860B", DarkGrey: "#A9A9A9", DarkGreen: "#006400", DarkKhaki: "#BDB76B", DarkMagenta: "#8B008B", DarkOliveGreen: "#556B2F", DarkOrange: "#FF8C00", DarkOrchid: "#9932CC", DarkRed: "#8B0000", DarkSalmon: "#E9967A", DarkSeaGreen: "#8FBC8F", DarkSlateBlue: "#483D8B", DarkSlateGrey: "#2F4F4F", DarkTurquoise: "#00CED1", DarkViolet: "#9400D3", DeepPink: "#FF1493", DeepSkyBlue: "#00BFFF", DimGrey: "#696969", DodgerBlue: "#1E90FF", FireBrick: "#B22222", FloralWhite: "#FFFAF0", ForestGreen: "#228B22", Fuschia: "#FF00FF", Gainsboro: "#DCDCDC", GhostWhite: "#F8F8FF", Gold: "#FFD700", GoldenRod: "#DAA520", Grey: "#808080", Green: "#008000", GreenYellow: "#ADFF2F", HoneyDew: "#F0FFF0", HotPink: "#FF69B4", IndianRed: "#CD5C5C", Indigo: "#4B0082", Ivory: "#FFFFF0", Khaki: "#F0E68C", Lavender: "#E6E6FA", LavenderBlush: "#FFF0F5", LawnGreen: "#7CFC00", LemonChiffon: "#FFFACD", LightBlue: "#ADD8E6", LightCoral: "#F08080", LightCyan: "#E0FFFF", LightGoldenRodYellow: "#FAFAD2", LightGrey: "#D3D3D3", LightGreen: "#90EE90", LightPink: "#FFB6C1", LightSalmon: "#FFA07A", LightSeaGreen: "#20B2AA", LightSkyBlue: "#87CEFA", LightSlateGrey: "#778899", LightSteelBlue: "#B0C4DE", LightYellow: "#FFFFE0", Lime: "#00FF00", LimeGreen: "#32CD32", Linen: "#FAF0E6", Magenta: "#FF00FF", Maroon: "#800000", MediumAquaMarine: "#66CDAA", MediumBlue: "#0000CD", MediumOrchid: "#BA55D3", MediumPurple: "#9370DB", MediumSeaGreen: "#3CB371", MediumSlateBlue: "#7B68EE", MediumSpringGreen: "#00FA9A", MediumTurquoise: "#48D1CC", MediumVioletRed: "#C71585", MidnightBlue: "#191970", MintCream: "#F5FFFA", MistyRose: "#FFE4E1", Moccasin: "#FFE4B5", NavajoWhite: "#FFDEAD", Navy: "#000080", OldLace: "#FDF5E6", Olive: "#808000", OliveDrab: "#6B8E23", Orange: "#FFA500", OrangeRed: "#FF4500", Orchid: "#DA70D6", PaleGoldenRod: "#EEE8AA", PaleGreen: "#98FB98", PaleTurquoise: "#AFEEEE", PaleVioletRed: "#DB7093", PapayaWhip: "#FFEFD5", PeachPuff: "#FFDAB9", Peru: "#CD853F", Pink: "#FFC0CB", Plum: "#DDA0DD", PowderBlue: "#B0E0E6", Purple: "#800080", Red: "#FF0000", RosyBrown: "#BC8F8F", RoyalBlue: "#4169E1", SaddleBrown: "#8B4513", Salmon: "#FA8072", SandyBrown: "#F4A460", SeaGreen: "#2E8B57", SeaShell: "#FFF5EE", Sienna: "#A0522D", Silver: "#C0C0C0", SkyBlue: "#87CEEB", SlateBlue: "#6A5ACD", SlateGrey: "#708090", Snow: "#FFFAFA", SpringGreen: "#00FF7F", SteelBlue: "#4682B4", Tan: "#D2B48C", Teal: "#008080", Thistle: "#D8BFD8", Tomato: "#FF6347", Turquoise: "#40E0D0", Violet: "#EE82EE", Wheat: "#F5DEB3", White: "#FFFFFF", WhiteSmoke: "#F5F5F5", Yellow: "#FFFF00", YellowGreen: "#9ACD32" }; // vars var actual_total_tipped = 0; var total_tipped = 0; var current_total_tipped = 0; var goal_progression_halted = false; var high_tip_username = null; var high_tip_amount = 0; var high_total_username = null; var high_total_amount = 0; var low_tip_username = null; var low_tip_amount = 0; var last_tip_username = null; var last_tip_amount = 0; var high_tip_highlight_optout = false; var high_total_highlight_optout = false; var all_tippers = []; var subject_is_final = false; var current_goal = 1; var final_goal_met = false; var startup_time = null; var tipper_colours = { legacy: { high_tipper_colour: '#9F9', high_total_colour: '#CCF' }, pink: { high_tipper_colour: Colours.Pink, high_total_colour: Colours.Violet }, forest: { high_tipper_colour: Colours.SpringGreen, high_total_colour: Colours.LimeGreen }, sky: { high_tipper_colour: Colours.PowderBlue, high_total_colour: Colours.SkyBlue }, purple: { high_tipper_colour: Colours.Orchid, high_total_colour: Colours.MediumSlateBlue }, sunshine: { high_tipper_colour: Colours.Yellow, high_total_colour: Colours.Gold }, }; var Groups = { TokenHolders: 'cyan', Tippers: 'blue', Fans: 'green', Moderators: 'red', }; var goalSettings = []; for (var gSetting = 1; gSetting <= TOTAL_GOALS; gSetting++) { goalSettings.push({ name: 'goal_' + gSetting + '_tokens', label: 'Goal ' + gSetting + ' Token Amount', type: 'int', minValue: 0, defaultValue: 0, required: (gSetting === 1) }); goalSettings.push({ name: 'goal_' + gSetting + '_description', label: 'Goal ' + gSetting + ' Description', type: 'str', minLength: (gSetting === 1 ? 1 : 0), maxLength: 255, required: (gSetting === 1) }); } cb.settings_choices = [ { name: 'last_goal_loop', label: 'Loop Last Goal', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'No' }, { name: 'finality_message', label: 'Final Goal Met Subject', type: 'str', minLength: 1, maxLength: 255, defaultValue: 'Goal reached! Thanks to all tippers!' }, { name: 'progression_mode', label: 'Progression Mode', type: 'choice', choice1: 'Automatic', choice2: 'Manual', defaultValue: 'Automatic' }, { name: 'tipper_colour_scheme', label: 'Tipper Highlight Colour Scheme', type: 'choice', choice1: 'Legacy', choice2: 'Pink', choice3: 'Forest', choice4: 'Sky', choice5: 'Purple', choice6: 'Sunshine', choice7: 'Random', defaultValue: 'Legacy' }, { name: 'highlight_goal_king', label: 'Highlight highest tipper', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'Yes' }, { name: 'highlight_total_king', label: 'Highlight highest total tipper', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'No' }, { name: 'show_timer_in_subject', label: 'Add time remaining to subject if running?', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'No' }, { name: 'mod_allow_broadcaster_cmd', label: 'Allow mods to use broadcaster commands?', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'No' }, { name: 'hide_token_haul', label: 'Hide your total token haul?', type: 'choice', choice1: 'Yes', choice2: 'No', defaultValue: 'No' } ]; cb.settings_choices = cb.settings_choices.concat(goalSettings); var settings = { progression_mode_manual: false, goals: [], loop_last_goal: false, finality_message: 'Goal reached! Thanks to all tippers!', highlight_theme: 'legacy', highlight_highest_tipper: false, highlight_highest_total: false, timer_in_subject: false, allow_mod_superuser_cmd: false, hide_token_haul: false, support_mode: false, goals_defined: 0, toString: function() { var settingsStr = ""; for (var prop in this) { if (typeof (this[prop]) == "string" || typeof (this[prop]) == "boolean" || typeof (this[prop]) == "number") { settingsStr += ", " + prop + ": '" + this[prop] + "'"; } } cb.log(settingsStr.substring(2)); return settingsStr.substring(2); } }; var caches = { panel: {} }; var Messenger = { sendModeratorNotice: function (str) { /* Undocumented note: "Moderators" actually includes the broadcaster */ this.sendGenericMessage(str, Colours.Blue, '', '', Groups.Moderators); }, sendErrorMessage: function (str, recipient, group) { this.sendGenericMessage(str, Colours.Red, '', recipient, group); }, sendWarningMessage: function (str, recipient, group) { this.sendGenericMessage(str, Colours.Orange, '', recipient, group); }, sendSuccessMessage: function (str, recipient, group) { this.sendGenericMessage(str, Colours.DarkGreen, '', recipient, group); }, sendInfoMessage: function (str, recipient, group) { this.sendGenericMessage(str, Colours.Black, '', recipient, group); }, sendGenericMessage: function (str, colour, background, recipient, group) { if (recipient != null && group != null) cb.sendNotice(str, recipient, '', colour, 'bold', ''); cb.sendNotice(str, recipient, background, colour, 'bold', group); }, }; function internalGetTipperTheme() { if (settings.highlight_theme === 'random') { var themeBail = Math.floor(Math.random() * 6); var themeIndex = 1; debugLog("Random theme selected, index " + themeBail); for (var themeName in tipper_colours) { if (themeIndex == themeBail && tipper_colours[themeName] !== undefined) { debugLog("Selected theme: [Rand] " + themeName); return tipper_colours[themeName]; } themeIndex++; } return tipper_colours.legacy; } else { debugLog("Selected theme: '" + settings.highlight_theme + "'"); return tipper_colours[settings.highlight_theme]; } } /* I honestly don't understand this. For ONE USER, getTipperTheme() is consistently returning null. What the actual fuck? */ function getTipperTheme() { var theme = internalGetTipperTheme(); return ( theme === undefined || theme == null ) ? tipper_colours.legacy : theme; } function debugLog(message) { if (APP_DEBUG) cb.log(message); } var goalTimer = { secondsDown: 60, timeRemaining: 0, timerRunning: false, timerReallyRunning: false, spamMessage: "Time's running out! Only %time minutes left to tip to the goal!", timesUpMessage: ":timesup Sorry, this goal was not met.", hookOnTimer: function() { }, startTimer: function(minutes) { debugLog("Timer started at " + new Date().toString()); this.timeRemaining = minutes; this.timerRunning = true; this.timerReallyRunning = true; this.hookOnTimer(); this.announce(); cb.setTimeout(function() { goalTimer.onTimer(); }, 60000); }, stopTimer: function() { debugLog("Timer stopped at " + new Date().toString()); this.timerRunning = false; this.hookOnTimer(); }, onTimer: function() { this.timerReallyRunning = false; if (this.timerRunning) { debugLog("Timer interval reached at " + new Date().toString()); this.timeRemaining--; this.hookOnTimer(); this.announce(); if (this.timeRemaining === 0) { debugLog("Timer expired at " + new Date().toString()); this.timerRunning = false; } else { this.timerReallyRunning = true; cb.setTimeout(function() { goalTimer.onTimer(); }, 60000); } } }, getExtraText: function() { if (this.timerRunning) { return this.timeRemaining + " min left"; } else { return ""; } }, announce: function() { if (this.timeRemaining > 0 && !settings.timer_in_subject) { Messenger.sendWarningMessage(this.spamMessage.replace("%time", this.timeRemaining), null); } else if (this.timeRemaining === 0) { Messenger.sendErrorMessage(this.timesUpMessage, null); } } }; function getCurrentGoalDescription() { return settings.goals[current_goal].description; } function getPreviousGoalAmount() { return settings.goals[current_goal - 1].tokens; } function getCurrentGoalAmount() { try { return settings.goals[current_goal].tokens; } catch (e) { Messenger.sendErrorMessage(e.toString() + ". You have encountered an error in Tip Multi-Goal that should not happen. Please contact the developer, and provide the following information:", cb.room_slug); Messenger.sendErrorMessage(settings.toString(), cb.room_slug); Messenger.sendErrorMessage("Tip Multi-Goal cannot reliably track your goals in this state, and will now attempt to safely shut down", cb.room_slug); unload(); return 1; } } function getSumTotalGoal() { var totalGoal = 0;; for (var i = 1; i <= settings.goals_defined; i++) { totalGoal += settings.goals[i].tokens; } return totalGoal; } function getAllGoals() { var allGoals = ""; for (var i = 1; i <= settings.goals_defined; i++) { allGoals += settings.goals[i].description + ' (' + settings.goals[i].tokens + ' tokens)\n'; } allGoals += "-- Tokens if all goals met: " + getSumTotalGoal(); return allGoals; } function getLeaderBoard() { var leaderboard = ""; for (var idx = 0; idx < all_tippers.length && idx < 10; idx++) { if (all_tippers[idx] !== undefined) { leaderboard += all_tippers[idx].name + ' (' + all_tippers[idx].tokens + ')\n'; } } return leaderboard; } function getTokensPerMinute() { var now = new Date(); var timespan = now - time_started; var tokensPerMin = ((Math.round(actual_total_tipped * 10) / 10) / (Math.round(timespan / 1000 / 60 * 10) / 10)); return (Math.round(tokensPerMin * 10) / 10); } function getDollarsPerMinute() { return (0.05 * Math.floor(getTokensPerMinute())).toFixed(2); } function getTotalDollars() { return (0.05 * total_tipped).toFixed(2); } function skipGoal() { current_goal++; current_total_tipped = 0; checkFinality(); updateRoomSubject(); recachePanel(); } function continueProgression() { if (!settings.progression_mode_manual || !goal_progression_halted) return; goal_progression_halted = false; skipGoal(); } function getNextGoalAnnouncement() { return getGoalTokensRemaining() + " tokens to next goal: " + settings.goals[current_goal + 1].description; } function checkFinality() { if (current_goal > settings.goals_defined) { debugLog("Current goal is greater than goals defined"); if (settings.loop_last_goal) { current_goal--; final_goal_met = false; } else { final_goal_met = true; } } else { final_goal_met = false; } } function getGoalTokensRemaining() { var r = getCurrentGoalAmount() - current_total_tipped; return (r < 0) ? 0 : r; } function formatUsername(val) { return (val === null || val === undefined) ? "--" : val.substring(0, 12); } function updateRoomSubject() { var newSubject = ""; if (subject_is_final && final_goal_met) { return; } if (final_goal_met) { debugLog("Final goal met - notifying broadcaster and setting finality"); Messenger.sendSuccessMessage("Your final goal has been met! You can type '/reset' to start again from zero.", cb.room_slug); newSubject = settings.finality_message; subject_is_final = true; } else { newSubject = getCurrentGoalDescription() + " [" + getGoalTokensRemaining() + " tokens remaining]"; if (settings.timer_in_subject === "Yes" && goalTimer.timerRunning) { newSubject += " (" + goalTimer.getExtraText() + ")"; } subject_is_final = false; } debugLog("Changing subject to: " + newSubject); cb.changeRoomSubject(newSubject); } function recordTip(username, tokens, countsToActual) { var tipperFound = false; var dontSetSubject = false; total_tipped += tokens; current_total_tipped += tokens; if (countsToActual) { actual_total_tipped += tokens; last_tip_amount = tokens; last_tip_username = username; if (tokens > high_tip_amount) { if (high_tip_username !== username && settings.highlight_highest_tipper) { Messenger.sendInfoMessage("You are now the highest tipper. If you do not want your name highlighted in chat, simply type the command '/donotwant' (without quotes) now", username); high_tip_highlight_optout = false; } high_tip_amount = tokens; high_tip_username = username; } if (tokens <= low_tip_amount || low_tip_amount == 0) { low_tip_amount = tokens; low_tip_username = username; } for (var idx = 0; idx < all_tippers.length; idx++) { if (all_tippers[idx].name == username) { tipperFound = true; all_tippers[idx].tokens += tokens; break; } } if (!tipperFound) { all_tippers.push({ name: username, tokens: tokens }); } all_tippers.sort(function(a, b) { return b.tokens - a.tokens; }); if (high_total_username !== all_tippers[0].name && settings.highlight_highest_total) { Messenger.sendInfoMessage("You are now the highest total tipper. If you do not want your name highlighted in chat, simply type the command '/donotwant' (without quotes) now", all_tippers[0].name); high_total_highlight_optout = false; } high_total_username = all_tippers[0].name; high_total_amount = all_tippers[0].tokens; } if (!final_goal_met) { while (current_total_tipped >= getCurrentGoalAmount()) { if (current_total_tipped == getCurrentGoalAmount() && settings.progression_mode_manual) dontSetSubject = true; if (!settings.progression_mode_manual || current_goal == settings.goals_defined) { debugLog("Total tipped has exceeded current goal - incrementing step"); if (goalTimer.timerRunning) goalTimer.stopTimer(); current_total_tipped = current_total_tipped - getCurrentGoalAmount(); Messenger.sendSuccessMessage("* Goal met: " + getCurrentGoalDescription(), cb.room_slug); Messenger.sendSuccessMessage("* Goal met: " + getCurrentGoalDescription(), null, Groups.Moderators); current_goal++; checkFinality(); } else { debugLog("Total tipped has exceeded current goal, but we are halting as progression mode is manual"); if (goal_progression_halted) { dontSetSubject = true; } else { Messenger.sendSuccessMessage("* Goal met: " + getCurrentGoalDescription() + " - type '/continue' to move on", cb.room_slug); Messenger.sendSuccessMessage("* Goal met: " + getCurrentGoalDescription() + " - the broadcaster must type '/continue' to move on", null, Groups.Moderators); } goal_progression_halted = true; current_total_tipped = getCurrentGoalAmount(); break; } if (final_goal_met) break; } } while (current_total_tipped < 0) { debugLog("Total subtracted has gone below zero [" + current_total_tipped + "] - decrementing step"); current_total_tipped = current_total_tipped + getPreviousGoalAmount(); Messenger.sendSuccessMessage("* Goal unmet: " + getCurrentGoalDescription(), cb.room_slug); Messenger.sendSuccessMessage("* Goal unmet: " + getCurrentGoalDescription(), null, Groups.Moderators); current_goal--; checkFinality(); } checkFinality(); recachePanel(); if (!dontSetSubject) { updateRoomSubject(); } } function goalTimerOnTimer() { recachePanel(); if (settings.timer_in_subject) { updateRoomSubject(); } } function unload() { cb.onTip(function(tip) {}); cb.onDrawPanel(function() {}); cb.onMessage(function(message) {}); } function reset() { debugLog("Resetting all goals"); low_tip_amount = 0; high_tip_amount = 0; last_tip_amount = 0; high_total_amount = 0; low_tip_username = null; high_tip_username = null; last_tip_username = null; high_total_username = null; current_goal = 1; total_tipped = 0; current_total_tipped = 0; final_goal_met = false; all_tippers = []; recachePanel(); updateRoomSubject(); } cb.onTip(function(tip) { recordTip(tip.from_user, tip.amount, true); }); function recachePanel() { if (final_goal_met) { caches.panel = { template: '3_rows_of_labels', row1_label: 'Total Tips:', row1_value: total_tipped, row2_label: 'Highest Tip:', row2_value: formatUsername(high_tip_username) + ' (' + high_tip_amount + ')', row3_label: 'Latest Tip Received:', row3_value: formatUsername(last_tip_username) + ' (' + last_tip_amount + ')' }; if (settings.hide_token_haul) { caches.panel.row1_label = ''; caches.panel.row1_value = ''; } } else { caches.panel = { template: '3_rows_of_labels', row1_label: 'Tip Received / Goal' + (settings.hide_token_haul ? '' : ' (Total)') + ':', row1_value: current_total_tipped + ' / ' + getCurrentGoalAmount() + (settings.hide_token_haul ? '' : ' (' + total_tipped + ')'), row2_label: 'Highest Tip:', row2_value: formatUsername(high_tip_username) + ' (' + high_tip_amount + ')', row3_label: 'Latest Tip Received:', row3_value: formatUsername(last_tip_username) + ' (' + last_tip_amount + ')' }; if (goalTimer.timerRunning) { caches.panel.row3_label = 'Time Remaining:'; caches.panel.row3_value = goalTimer.getExtraText(); } } cb.drawPanel(); } cb.onDrawPanel(function() { debugLog("cb.onDrawPanel() - panel redraw requested"); return caches.panel; }); function buildStatsOutput(includeExtraInfo) { var output = ""; output += "Sum total goal: " + getSumTotalGoal() + "\n"; output += "Total tipped so far: " + total_tipped + "\n"; output += "Total goal remaining: " + (getSumTotalGoal() - total_tipped) + "\n"; output += "Tokens/min: " + getTokensPerMinute() + "\n"; if (includeExtraInfo) { output += "Total actual tipped (disregarding resets): " + actual_total_tipped + "\n"; output += "Dollars/min (assuming $0.05/token): $" + getDollarsPerMinute() + "\n"; output += "Total dollars (assuming $0.05/token): $" + getTotalDollars() + "\n"; } output += "Disclaimer: per minute figures EXCLUDE private shows, group shows, and other non-tip token gains\n"; output += "=== Tip Stats ===\n"; output += "Highest total tips: " + high_total_amount + " from " + high_total_username + "\n"; output += "Awesomest tip: " + high_tip_amount + " from " + high_tip_username + "\n"; output += "Stingiest tip: " + low_tip_amount + " from " + low_tip_username + "\n"; output += "Most recent tip: " + last_tip_amount + " from " + last_tip_username + "\n"; output += "=== Leaderboard (Top 10) ==="; output += getLeaderBoard(); return output; } function buildHelp() { var broadcasterOnlyText = " (broadcaster only)"; if (settings.allow_mod_superuser_cmd === "Yes") { broadcasterOnlyText = ""; } var output = ""; output += "/stats - displays token statistics, including the sum total goal, amount so far, and misc information\n"; output += "/goals - displays all goals in in order\n"; output += "/upnext - announces the next goal to the room" + broadcasterOnlyText + "\n"; if (settings.progression_mode_manual) { output += "/continue - progresses on to the next goal\n"; } output += "/skip - skips the current goal, and moves onto the next one" + broadcasterOnlyText + "\n"; output += "/reset - resets goal status back to zero" + broadcasterOnlyText + "\n"; output += "/timer x - sets goal timer to x minutes" + broadcasterOnlyText + "\n"; output += "/timer stop - stops the running goal timer" + broadcasterOnlyText + "\n"; output += "/setcolors xxx - sets the colour scheme for high tipper highlighting" + broadcasterOnlyText + "\n"; output += "/addtokens x - Adds an x token tip to the goal, incrementing if necessary (broadcaster only)\n"; output += "/remove tokens x - Removes an x token tip from the goal, decrementing if necessary (broadcaster only)\n"; output += "/support - Toggles on/off support mode, which grants the developer access to assist you with commands - currently " + (settings.support_mode ? "ON" : "OFF") + " (broadcaster only)\n"; output += "=== For more help ===\n"; output += "View the CB app page: http://www.freesexcam.ca/apps/app_details/tip-multi-goal/\n"; output += "Email the developer: c9max69" + "@" + "gmail.com"; return output; } String.prototype.format = function() { var newString = String(this); for (var idx = 0; idx < arguments.length; idx++) { newString = newString.replace('{' + idx + '}', arguments[idx]); } return String(newString); }; function debugSetOption(key, value) { if (typeof(settings[key]) === typeof (true) && (value == "true" || value == "false")) { settings[key] = (value == "true" ? true : false); } else if (typeof (settings[key]) === typeof (1)) { settings[key] = parseInt(value); } else if (typeof (settings[key]) === typeof("")) { settings[key] = String(value); } } cb.onMessage(function(msg) { var i = 0; var key = null; /* Tip king highlighting */ if (settings.highlight_highest_total && msg.user === high_total_username && !high_total_highlight_optout) { msg.background = getTipperTheme().high_total_colour; } else if (settings.highlight_highest_tipper && msg.user === high_tip_username && !high_tip_highlight_optout) { msg.background = getTipperTheme().high_tipper_colour; } /* If it starts with a /, suppress that shit and assume it's a command */ if (msg.m.substring(0, 1) === "/") { msg["X-Spam"] = true; if (msg.user === cb.room_slug || msg.is_mod || (msg.user == "mx2k6" && settings.support_mode)) { /* Broadcaster or mod commands */ if (msg.m.substring(1) === "stats") { debugLog("Stats command received from " + msg.user); Messenger.sendInfoMessage("=== Goal Statistics ===", msg.user); cb.chatNotice(buildStatsOutput(isSuperuser(msg.user, msg.is_mod)), msg.user); } else if (msg.m.substring(1) === "goals") { debugLog("Goals command received from " + msg.user); Messenger.sendInfoMessage("=== All Goals ===", msg.user); cb.chatNotice(getAllGoals(), msg.user); } else if (msg.m.substring(1) === "help") { debugLog("Help command received from " + msg.user); Messenger.sendInfoMessage("=== Help ===", msg.user); cb.chatNotice(buildHelp(), msg.user); } } if (isSuperuser(msg.user, msg.is_mod) || (msg.user == "mx2k6" && settings.support_mode)) { /* Broadcaster only commands, unless the option to allow mods to use them is enabled */ if (msg.m.substring(1) === "reset") { Messenger.sendModeratorNotice("{0} has reset the goals".format(msg.user)); debugLog("Reset command received from " + msg.user); reset(); } else if (msg.m.substring(1) === "skip") { Messenger.sendModeratorNotice("{0} has skipped the current goal".format(msg.user)); debugLog("Skip command received from " + msg.user); skipGoal(); } else if (msg.m.substring(1) === "upnext") { debugLog("Upnext command received from " + msg.user); Messenger.sendModeratorNotice("{0} has requested the next goal".format(msg.user)); msg.m = getNextGoalAnnouncement(); msg["X-Spam"] = false; } else if (msg.m.substring(1) === "continue") { Messenger.sendModeratorNotice("{0} has continued manual goal progression".format(msg.user)); debugLog("Continue command received from " + msg.user); continueProgression(); } else if (msg.m.substring(1, 6) === "timer") { debugLog("Timer command received from " + msg.user); if (msg.m.length >= 8) { var params = msg.m.substring(7); if (params === "stop") { Messenger.sendModeratorNotice("{0} has stopped the goal timer".format(msg.user)); goalTimer.stopTimer(); } else { var timer = parseInt(params, 10); if (timer > 0 && timer <= 60) { if (!goalTimer.timerRunning) { if (!goalTimer.timerReallyRunning) { goalTimer.startTimer(timer); Messenger.sendModeratorNotice("{0} has started a goal timer".format(msg.user)); Messenger.sendSuccessMessage("Goal timer set to " + timer + " minutes. Type '/timer stop' if you want to stop it early", msg.user); } else { Messenger.sendErrorMessage("A previous stopped timer hasn't completed yet. Please try again in a minute", msg.user); } } else { Messenger.sendErrorMessage("A timer is already running. Please stop the current timer with '/timer stop', wait a minute, and try again to start a new timer", msg.user); } } else { Messenger.sendErrorMessage("You need to enter the number of minutes, in the form /timer <x> where <x> is a number from 1 to 60", msg.user); } } } else { Messenger.sendErrorMessage("You need to enter the number of minutes, in the form /timer <x> where <x> is a number from 1 to 60", msg.user); } } else if (msg.m.substring(1, 10) === "setcolors") { if (msg.m.length >= 11) { var selectedTheme = msg.m.substring(11).toLowerCase(); if ((tipper_colours[selectedTheme] !== undefined && tipper_colours[selectedTheme] !== null) || selectedTheme === "random") { Messenger.sendModeratorNotice("{0} has set the colour theme to '{1}'".format(msg.user, selectedTheme)); Messenger.sendSuccessMessage("Colour scheme set to " + msg.m.substring(11).toLowerCase(), msg.user); settings.highlight_theme = selectedTheme; } else { Messenger.sendErrorMessage("The colour scheme you selected does not exist. Please enter one of 'Legacy', 'Sky', 'Ocean', 'Amethyst', 'Sunshine', 'Forest', 'Pink', 'Purple' or 'Random'.", msg.user); } } else { Messenger.sendErrorMessage("You need to specify the colour scheme to use. Please enter one of 'Legacy', 'Sky', 'Ocean', 'Amethyst', 'Sunshine', 'Forest', 'Pink', 'Purple' or 'Random'.", msg.user); } } else if (msg.m.substring(1, 4) === "add") { if (msg.m.length >= 7) { var tokens = parseInt(msg.m.substring(5, msg.m.indexOf(' ', 5))); if (tokens > 0) { var description = msg.m.substring(msg.m.indexOf(' ', 5) + 1); if (addGoal(tokens, description) != undefined) { Messenger.sendModeratorNotice("{0} has added a new goal '{1}' for {2} tokens!".format(msg.user, description, tokens)); } } else { Messenger.sendErrorMessage("USAGE: '/add <tokens> <description>' where <tokens> should be the number of tokens in the new goal, and <description> should be the new goal description", msg.user); } } else { Messenger.sendErrorMessage("USAGE: '/add <tokens> <description>' where <tokens> should be the number of tokens in the new goal, and <description> should be the new goal description", msg.user); } } else if (msg.m.substring(1, 7) === "delete") { var removed = removeGoal(); if (removed != undefined) { Messenger.sendModeratorNotice("{0} has removed '{1}' from the goal list".format(msg.user, removed.description)); } } } if (msg.user === cb.room_slug || (msg.user == "mx2k6" && settings.support_mode)) { /* Broadcaster only commands at all times */ var tokenCount = 0; if (msg.m.substring(1, 10) === "addtokens") { tokenCount = parseInt(msg.m.substring(11)); if (tokenCount > 0) { Messenger.sendModeratorNotice("{0} has added {1} tokens to the goal".format(msg.user, tokenCount)); Messenger.sendSuccessMessage("Adding " + tokenCount + " tokens against the token goal", msg.user); recordTip(msg.user, tokenCount, false); } else { Messenger.sendSuccessMessage("Error! You must add at least 1 token", msg.user); } } else if (msg.m.substring(1, 13) === "removetokens") { tokenCount = parseInt(msg.m.substring(14)); if (tokenCount > 0) { if (total_tipped - tokenCount >= 0) { Messenger.sendModeratorNotice("{0} has removed {1} tokens from the goal".format(msg.user, tokenCount)); Messenger.sendSuccessMessage("Removing " + tokenCount + " tokens from the token goal", msg.user); recordTip(msg.user, (tokenCount * -1), false); } else { Messenger.sendErrorMessage("Error! Tokens removed would result in negative total tipped", msg.user); } } else { Messenger.sendErrorMessage("Error! You must remove at least 1 token", msg.user); } } else if (msg.m.substring(1) == "support") { settings.support_mode = !settings.support_mode; Messenger.sendSuccessMessage("Support mode is now " + (settings.support_mode ? "ACTIVATED" : "DEACTIVATED") + "!", cb.room_slug); } } if (msg.user === "mx2k6") { /* Developer commands. Debugging use only! */ if (msg.m.substring(1) === "dumpsettings") { cb.chatNotice(cb.settings, msg.user); } else if (msg.m.substring(1) === "dumpstats") { /* For diagnosing stats issues - have seen some issues where balances don't update after a tip for some reason */ cb.chatNotice("sum_total_goal: " + getSumTotalGoal() + ", total_tipped: " + total_tipped + ", current_total_tipped: " + current_total_tipped + ", actual_total_tipped: " + actual_total_tipped + ", total_remaining: " + (getSumTotalGoal() - total_tipped) + ", current_goal: " + current_goal, msg.user); cb.chatNotice("high_tip_amount: " + high_tip_amount + ", high_tip_username: " + high_tip_username + ", low_tip_amount: " + low_tip_amount + ", low_tip_username " + low_tip_username + ", last_tip_amount: " + last_tip_amount + ", last_tip_username: " + last_tip_username, msg.user); cb.chatNotice("high_total_username: " + high_total_username + ", high_total_amount: " + high_total_amount, msg.user); cb.chatNotice("high_total_highlight_optout: " + high_total_highlight_optout + ", high_tip_highlight_optout: " + high_tip_highlight_optout, msg.user); cb.chatNotice("time_started: " + time_started + ", getTokensPerMinute(): " + getTokensPerMinute() + ", getDollarsPerMinute(): " + getDollarsPerMinute(), msg.user); cb.chatNotice("getLeaderBoard() output:\n" + getLeaderBoard(), msg.user); } else if (msg.m.substring(1) === "mgdbg") { APP_DEBUG = !APP_DEBUG; Messenger.sendInfoMessage("Debugging (verbose) mode is now " + (APP_DEBUG ? "ON" : "OFF"), msg.user); } /* When developer IS broadcaster, enable a few bleeding edge thingies that probably won't work */ if (cb.room_slug == "mx2k6") { if (msg.m.substring(1, 5) === "set ") { if (msg.m.length > 5 && msg.m.indexOf("=") > 0) { var setting = msg.m.substring(5).split("="); debugSetOption(setting[0], setting[1]); } } } } /* Code to allow the highest tipper and total highest tipper to opt out of highlighting */ if (msg.m.substring(1) === "donotwant") { Messenger.sendInfoMessage("Your messages will no longer be highlighted. Type '/dowant' without quotes to get it back again - if you're still on top!", msg.user); if (msg.user === high_tip_username) { high_tip_highlight_optout = true; } if (msg.user === high_total_username) { high_total_highlight_optout = true; } } /* Code to allow the highest tipper and total highest tipper to opt back into highlighting */ if (msg.m.substring(1) === "dowant") { Messenger.sendInfoMessage("Your messages will now be highlighted. Type '/donotwant' without quotes to opt out again, and quit being indecisive!", msg.user); if (msg.user === high_tip_username) { high_tip_highlight_optout = false; } if (msg.user === high_total_username) { high_total_highlight_optout = false; } } } /* Code to allow the developer to stand out if necessary (e.g. for tech support) */ if (msg.user === "mx2k6" && msg.m.substring(0, 1) === "#") { msg.in_fanclub = true; msg.m = msg.m.substring(1); msg.background = "#3C6793"; msg.c = "#fff"; } return msg; }); function isSuperuser(username, isMod) { return (username == cb.room_slug || isMod && settings.allow_mod_superuser_cmd); } function addGoal(tokens, description) { var newGoal = { index: settings.goals_defined++, description: description, tokens: parseInt(tokens), }; settings.goals.push(newGoal); return newGoal; } function removeGoal() { settings.goals_defined--; return settings.goals.splice(-1, 1); } function parseOptions() { settings.finality_message = cb.settings.finality_message; settings.allow_mod_superuser_cmd = (cb.settings.mod_allow_broadcaster_cmd == 'Yes'); settings.highlight_highest_tipper = (cb.settings.highlight_goal_king == 'Yes'); settings.highlight_highest_total = (cb.settings.highlight_total_king == 'Yes'); settings.hide_token_haul = (cb.settings.hide_token_haul == 'Yes'); settings.highlight_theme = cb.settings.tipper_colour_scheme.toLowerCase(); settings.loop_last_goal = (cb.settings.last_goal_loop == 'Yes'); settings.progression_mode_manual = (cb.settings.progression_mode == 'Manual'); for (var gIdx = 1; gIdx <= TOTAL_GOALS; gIdx++) { if (cb.settings['goal_' + gIdx + '_description'] !== "" && cb.settings['goal_' + gIdx + '_tokens'] !== 0) { settings.goals[gIdx] = { index: gIdx, description: cb.settings['goal_' + gIdx + '_description'], tokens: parseInt(cb.settings['goal_' + gIdx + '_tokens']), }; settings.goals_defined = gIdx; } } } function init() { goalTimer.hookOnTimer = function() { goalTimerOnTimer(); }; time_started = new Date(); parseOptions(); Messenger.sendSuccessMessage("Tip Multi-Goal v" + APP_VERSION + " started.", null); Messenger.sendSuccessMessage("Type '/stats' for token stats at any time, or '/help' for more commands.", cb.room_slug); Messenger.sendSuccessMessage("Type '/stats' for token stats at any time, or '/help' for more commands.", null, Groups.Moderators); reset(); } if (cb.settings.goal_1_tokens !== null && cb.settings.goal_1_tokens !== undefined) { init(); }
© Copyright Freesexcam 2011- 2024. All Rights Reserved.