Apps Home
|
Create an App
Goal Runner
Author:
annika_brooks
Description
Source Code
Launch App
Current Users
Created by:
Annika_Brooks
/* Name: Goal Runner Author: Annika Brooks Credits ============================================ Mx2k6's multigoal simplified and with 50 goals. */ var current_version = 1.0; // vars var actual_total_tipped = 0; var total_tipped = 0; var current_total_tipped = 0; 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 spit_verbose_output = false; cb.settings_choices = [ // {name: 'goal_1_tokens', label: 'Goal 1 Token Amount', type: 'int', minValue: 1, defaultValue: 1}, // {name: 'goal_1_description', label: 'Goal 1 Description', type: 'str', minLength: 1, maxLength: 255}, // {name: 'goal_2_tokens', label: 'Goal 2 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_2_description', label: 'Goal 2 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_3_tokens', label: 'Goal 3 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_3_description', label: 'Goal 3 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_4_tokens', label: 'Goal 4 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_4_description', label: 'Goal 4 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_5_tokens', label: 'Goal 5 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_5_description', label: 'Goal 5 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_6_tokens', label: 'Goal 6 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_6_description', label: 'Goal 6 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_7_tokens', label: 'Goal 7 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_7_description', label: 'Goal 7 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_8_tokens', label: 'Goal 8 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_8_description', label: 'Goal 8 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_9_tokens', label: 'Goal 9 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_9_description', label: 'Goal 9 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_10_tokens', label: 'Goal 10 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_10_description', label: 'Goal 10 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // // {name: 'goal_11_tokens', label: 'Goal 11 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_11_description', label: 'Goal 11 Description', type: 'str', minLength: 1, maxLength: 255, required: false}, // {name: 'goal_12_tokens', label: 'Goal 12 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_12_description', label: 'Goal 12 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_13_tokens', label: 'Goal 13 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_13_description', label: 'Goal 13 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_14_tokens', label: 'Goal 14 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_14_description', label: 'Goal 14 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_15_tokens', label: 'Goal 15 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_15_description', label: 'Goal 15 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_16_tokens', label: 'Goal 16 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_16_description', label: 'Goal 16 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_17_tokens', label: 'Goal 17 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_17_description', label: 'Goal 17 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_18_tokens', label: 'Goal 18 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_18_description', label: 'Goal 18 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_19_tokens', label: 'Goal 19 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_19_description', label: 'Goal 19 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // // // {name: 'goal_20_tokens', label: 'Goal 20 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_20_description', label: 'Goal 20 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_21_tokens', label: 'Goal 21 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_21_description', label: 'Goal 21 Description', type: 'str', minLength: 1, maxLength: 255, required: false}, // {name: 'goal_22_tokens', label: 'Goal 22 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_22_description', label: 'Goal 22 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_23_tokens', label: 'Goal 23 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_23_description', label: 'Goal 23 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_24_tokens', label: 'Goal 24 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_24_description', label: 'Goal 24 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_25_tokens', label: 'Goal 25 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_25_description', label: 'Goal 25 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_26_tokens', label: 'Goal 26 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_26_description', label: 'Goal 26 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_27_tokens', label: 'Goal 27 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_27_description', label: 'Goal 27 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_28_tokens', label: 'Goal 28 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_28_description', label: 'Goal 28 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_29_tokens', label: 'Goal 29 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_29_description', label: 'Goal 29 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // // {name: 'goal_30_tokens', label: 'Goal 30 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_30_description', label: 'Goal 30 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_31_tokens', label: 'Goal 31 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_31_description', label: 'Goal 31 Description', type: 'str', minLength: 1, maxLength: 255, required: false}, // {name: 'goal_32_tokens', label: 'Goal 32 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_32_description', label: 'Goal 32 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_33_tokens', label: 'Goal 33 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_33_description', label: 'Goal 33 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_34_tokens', label: 'Goal 34 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_34_description', label: 'Goal 34 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_35_tokens', label: 'Goal 35 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_35_description', label: 'Goal 35 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_36_tokens', label: 'Goal 36 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_36_description', label: 'Goal 36 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_37_tokens', label: 'Goal 37 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_37_description', label: 'Goal 37 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_38_tokens', label: 'Goal 38 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_38_description', label: 'Goal 38 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_39_tokens', label: 'Goal 39 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_39_description', label: 'Goal 39 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // // {name: 'goal_40_tokens', label: 'Goal 40 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_40_description', label: 'Goal 40 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_41_tokens', label: 'Goal 41 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_41_description', label: 'Goal 41 Description', type: 'str', minLength: 1, maxLength: 255, required: false}, // {name: 'goal_42_tokens', label: 'Goal 42 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_42_description', label: 'Goal 42 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_43_tokens', label: 'Goal 43 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_43_description', label: 'Goal 43 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_44_tokens', label: 'Goal 44 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_44_description', label: 'Goal 44 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_45_tokens', label: 'Goal 45 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_45_description', label: 'Goal 45 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_46_tokens', label: 'Goal 46 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_46_description', label: 'Goal 46 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_47_tokens', label: 'Goal 47 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_47_description', label: 'Goal 47 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_48_tokens', label: 'Goal 48 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_48_description', label: 'Goal 48 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // {name: 'goal_49_tokens', label: 'Goal 49 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_49_description', label: 'Goal 49 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, // // {name: 'goal_50_tokens', label: 'Goal 50 Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}, // {name: 'goal_50_description', label: 'Goal 50 Description', type: 'str', minLength: 0, maxLength: 255, required: false}, {name: 'purchase_email_tokens', label: 'Purchase Email Amount', type: 'int', minValue: 1, defaultValue: 111, required: true}, {name: 'purchase_email_text', label: 'Email Address', type: 'str', minLength: 0, maxLength: 255, required: true}, {name: 'purchase_snapchat_tokens', label: 'Purchase Snapchat Amount', type: 'int', minValue: 1, defaultValue: 444, required: true}, {name: 'purchase_snapchat_text', label: 'Snapchat Username', type: 'str', minLength: 0, maxLength: 255, required: true}, {name: 'last_goal_loop', label: 'Loop Last Goal', type: 'hidden', 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: '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'} ]; var number_of_goals = 100; for(i = 1; i <= number_of_goals; i++) { var required = (i == 1); cb.settings_choices.push({name: 'goal_' + i + '_tokens', label: 'Goal '+ i + ' Token Amount', type: 'int', minValue: 1, defaultValue: 1, required: false}); cb.settings_choices.push({name: 'goal_' + i + '_description', label: 'Goal ' + i + ' Description', type: 'str', minLength: 0, maxLength: 255, required: false}); } function verboseMessage(message, user) { cb.log("Verbose debug message: " + message); if (spit_verbose_output) { cb.chatNotice("[Verbose] " + message, user); } } 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) { verboseMessage("Timer started at " + new Date().toString(), cb.room_slug); this.timeRemaining = minutes; this.timerRunning = true; this.timerReallyRunning = true; this.hookOnTimer(); this.announce(); cb.setTimeout(function() { goalTimer.onTimer(); }, 60000); }, stopTimer: function() { verboseMessage("Timer stopped at " + new Date().toString(), cb.room_slug); this.timerRunning = false; this.hookOnTimer(); }, onTimer: function() { this.timerReallyRunning = false; if (this.timerRunning) { verboseMessage("Timer interval reached at " + new Date().toString(), cb.room_slug); this.timeRemaining--; this.hookOnTimer(); this.announce(); if (this.timeRemaining === 0) { verboseMessage("Timer expired at " + new Date().toString(), cb.room_slug); 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 && cb.settings.show_timer_in_subject !== "Yes" ) { cb.chatNotice(this.spamMessage.replace("%time", this.timeRemaining), '', '#FFFFFF', '#FF0000', 'bold'); } else if ( this.timeRemaining === 0 ) { cb.chatNotice(this.timesUpMessage, '', '#FFFFFF', '#FF0000', 'bold'); } } }; function getCurrentGoalDescription() { return cb.settings['goal_' + current_goal + '_description']; } function getPreviousGoalAmount() { return cb.settings['goal_' + ( current_goal - 1 ) + '_tokens']; } function getCurrentGoalAmount() { return cb.settings['goal_' + current_goal + '_tokens']; } function getSumTotalGoal() { var total_goal = 0; var i = 1; for (i = 1; i <= 6; i++) { if (cb.settings['goal_' + i + '_description'] !== "" && cb.settings['goal_' + i + '_tokens'] !== 0 ) { total_goal += cb.settings['goal_' + i + '_tokens']; } } return total_goal; } function getAllGoals() { var all_goals = ""; for (i = 1; i <= 6; i++) { if (cb.settings['goal_' + i + '_description'] !== "" && cb.settings['goal_' + i + '_tokens'] !== 0 ) { all_goals += cb.settings['goal_' + i + '_description'] + ' (' + cb.settings['goal_' + i + '_tokens'] + ' tokens)\n'; } } all_goals += "- All Goals: " + getSumTotalGoal(); return all_goals; } 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 tokens_per_min = ((Math.round(actual_total_tipped * 10) / 10) / (Math.round(timespan / 1000 / 60 * 10) / 10)); return (Math.round(tokens_per_min * 10) / 10); } function getDollarsPerMinute() { return (0.05 * Math.floor(getTokensPerMinute())).toFixed(2); } function skipGoal() { current_goal++; checkFinality(); update_goals(); } function getNextGoalAnnouncement() { return tips_remaining() + " tokens to next goal: " + cb.settings['goal_' + ( current_goal + 1 ) + '_description']; } function checkFinality() { if (getCurrentGoalAmount() <= 0 || getCurrentGoalDescription() === "" || current_goal === 7) { if (cb.settings.last_goal_loop === 'Yes') { current_goal--; final_goal_met = false; } else { final_goal_met = true; } } else { final_goal_met = false; } } function tips_remaining() { var r = getCurrentGoalAmount() - current_total_tipped; return (r < 0) ? 0 : r; } function format_username(val) { return (val === null) ? "--" : val.substring(0, 12); } function update_goals() { var new_subject = ""; if (subject_is_final && final_goal_met) { return; } if (final_goal_met) { cb.log("Final goal met - notifying broadcaster and setting finality"); cb.chatNotice("Your final goal has been met! You can type '/reset' to start again from zero.", cb.room_slug, '#FFFFFF', '#FF0000', 'bold'); new_subject = cb.settings.finality_message; subject_is_final = true; } else { new_subject = getCurrentGoalDescription() + " [" + tips_remaining() + " tokens remaining]"; if (cb.settings.show_timer_in_subject === "Yes" && goalTimer.timerRunning) { new_subject += " (" + goalTimer.getExtraText() + ")"; } subject_is_final = false; } cb.log("Changing subject to: " + new_subject); cb.changeRoomSubject(new_subject); } function recordTip(username, tokens, record_actual) { var tipper_found = false; total_tipped += tokens; current_total_tipped += tokens; if ( record_actual ) actual_total_tipped += tokens; if(tokens == cb.settings.purchase_email_tokens) { cb.sendNotice("==EMAIL== Thank you for your puchase! Email: " + cb.settings.purchase_email_text, username, '#9dff9d', '#000000', 'bolder'); cb.sendNotice(username + " has purchased Annika's Email Address! Ooh la la! Want it too? Tip " + cb.settings.purchase_email_tokens + " tokens!", '', '#9dff9d', '#000000', 'bolder'); } if(tokens == cb.settings.purchase_snapchat_tokens) { cb.sendNotice("==SNAPCHAT== Thank you for your puchase! Username: " + cb.settings.purchase_snapchat_text, username, '#9dff9d', '#000000', 'bolder'); cb.sendNotice(username + " has purchased Annika's Snapchat! Ooh la la! Want it too? Tip " + cb.settings.purchase_snapchat_tokens + " tokens!", '', '#9dff9d', '#000000', 'bolder'); } while (current_total_tipped >= getCurrentGoalAmount()) { cb.log("Total tipped has exceeded current goal - incrementing step"); current_total_tipped = current_total_tipped - getCurrentGoalAmount(); if ( goalTimer.timerRunning ) goalTimer.stopTimer(); cb.sendNotice("*****************", '', '#FFFFFF', '#ff1a75', 'bolder'); cb.sendNotice("GOAL REACHED!", '', '#FFFFFF', '#ff1a75', 'bolder'); cb.sendNotice("" + getCurrentGoalDescription() + "", '', '#FFFFFF', '#ff1a75', 'bolder'); cb.sendNotice("*****************", '', '#FFFFFF', '#ff1a75', 'bolder'); current_goal++; checkFinality(); if(getCurrentGoalAmount() < 100) { current_total_tipped = 0; } } while (current_total_tipped < 0) { cb.log("Total subtracted has gone below zero [" + current_total_tipped + "] - decrementing step"); current_total_tipped = current_total_tipped + getPreviousGoalAmount(); current_goal--; cb.chatNotice("* Goal unmet: " + getCurrentGoalDescription(), cb.room_slug); checkFinality(); } last_tip_amount = tokens; last_tip_username = username; if (tokens > high_tip_amount) { high_tip_amount = tokens; high_tip_username = username; high_tip_highlight_optout = false; } 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) { tipper_found = true; all_tippers[idx].tokens += tokens; break; } } if (!tipper_found) { all_tippers.push({ name: username, tokens: tokens }); } all_tippers.sort(function (a, b) { return b.tokens - a.tokens; }); high_total_username = all_tippers[0].name; high_total_amount = all_tippers[0].tokens; high_total_highlight_optout = false; checkFinality(); update_goals(); cb.drawPanel(); } function goalTimerOnTimer() { cb.drawPanel(); if (cb.settings.show_timer_in_subject === "Yes") { update_goals(); } } function reset() { cb.log("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 = []; cb.drawPanel(); update_goals(); } cb.onTip(function (tip) { recordTip(tip.from_user, tip.amount, true); }); cb.onDrawPanel(function (user) { var panel = {}; if (final_goal_met) { panel = { 'template': '3_rows_of_labels', 'row1_label': 'Total Tips:', 'row1_value': total_tipped, 'row2_label': 'Highest Tip:', 'row2_value': format_username(high_tip_username) + ' (' + high_tip_amount + ')', 'row3_label': 'Latest Tip Received:', 'row3_value': format_username(last_tip_username) + ' (' + last_tip_amount + ')' }; } else { panel = { 'template': '3_rows_of_labels', 'row1_label': 'Tip Received / Goal (Total):', 'row1_value': current_total_tipped + ' / ' + getCurrentGoalAmount(), 'row2_label': 'King of Tips:', 'row2_value': format_username(high_tip_username) + ' (' + high_tip_amount + ')', 'row3_label': 'Latest Tip Received:', 'row3_value': format_username(last_tip_username) + ' (' + last_tip_amount + ')' }; if (goalTimer.timerRunning) { panel.row3_label = 'Time Remaining:'; panel.row3_value = goalTimer.getExtraText(); } } return panel; }); cb.onMessage(function (msg) { var i = 0; var key = null; /* Tip king highlighting */ if (cb.settings.highlight_goal_king === "Yes" && msg.user === high_tip_username && !high_tip_highlight_optout) { msg.background = '#9F9'; } if (cb.settings.highlight_total_king === "Yes" && msg.user === high_total_username && !high_total_highlight_optout ) { msg.background = '#CCF'; } var bc_only_text = " (broadcaster only)"; if (cb.settings.mod_allow_broadcaster_cmd === "Yes") { bc_only_text = ""; } /* 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) { /* Broadcaster or mod commands */ if (msg.m.substring(1) === "stats") { cb.log("Stats command received from " + msg.user); cb.chatNotice("=== Total Stats ===", msg.user, '#FFFFFF', '#000000', 'bold'); cb.chatNotice("Sum total goal: " + getSumTotalGoal(), msg.user); cb.chatNotice("Total tipped so far: " + total_tipped, msg.user); cb.chatNotice("Total goal remaining: " + (getSumTotalGoal() - total_tipped), msg.user); cb.chatNotice("Tokens/min: " + getTokensPerMinute(), msg.user); cb.chatNotice("Disclaimer: per minute figures EXCLUDE private shows, group shows, and other non-tip token gains", msg.user); if (msg.user === cb.room_slug) { cb.chatNotice("=== Broadcaster Only Stats (mods cannot see this section) ===", msg.user, '#FFFFFF', '#000000', 'bold'); cb.chatNotice("Total actual tipped (disregarding resets): " + actual_total_tipped, msg.user); cb.chatNotice("Dollars/min (assuming $0.05/token): $" + getDollarsPerMinute(), msg.user); } cb.chatNotice("=== Tip Stats ===", msg.user, '#FFFFFF', '#000000', 'bold'); cb.chatNotice("Highest total tips: " + high_total_amount + " from " + high_total_username, msg.user); cb.chatNotice("Awesomest tip: " + high_tip_amount + " from " + high_tip_username, msg.user); cb.chatNotice("Stingiest tip: " + low_tip_amount + " from " + low_tip_username, msg.user); cb.chatNotice("Most recent tip: " + last_tip_amount + " from " + last_tip_username, msg.user); cb.chatNotice("=== Leaderboard (Top 10) ===", msg.user, '#FFFFFF', '#000000', 'bold'); cb.chatNotice(getLeaderBoard(), msg.user); } else if (msg.m.substring(1) === "goals") { cb.log("Goals command received from " + msg.user); cb.chatNotice("=== All Goals ===", msg.user, '#FFFFFF', '#000000', 'bold'); cb.chatNotice(getAllGoals(), msg.user); } else if (msg.m.substring(1) === "help") { cb.log("Help command received from " + msg.user); cb.chatNotice("=== Help ===", msg.user, '#FFFFFF', '#000000', 'bold'); cb.chatNotice("/stats - displays token statistics, including the sum total goal, amount so far, and misc information", msg.user); cb.chatNotice("/goals - displays all goals in in order", msg.user); cb.chatNotice("/upnext - announces the next goal to the room" + bc_only_text, msg.user); cb.chatNotice("/skip - skips the current goal, and moves onto the next one" + bc_only_text, msg.user); cb.chatNotice("/reset - resets goal status back to zero" + bc_only_text, msg.user); cb.chatNotice("/timer x - sets goal timer to x minutes" + bc_only_text, msg.user); cb.chatNotice("/timer stop - stops the running goal timer" + bc_only_text, msg.user); cb.chatNotice("/addtokens x - Adds an x token tip to the goal, incrementing if necessary (broadcaster only)", msg.user); cb.chatNotice("/removetokens x - Removes an x token tip from the goal, decrementing if necessary (broadcaster only)", msg.user); cb.chatNotice("=== For more help ===", msg.user, '#FFFFFF', '#000000', 'bold'); cb.chatNotice("View the CB app page: http://chaturbate.com/apps/app_details/tip-multi-goal/", msg.user); cb.chatNotice("Email the developer: c9max69" + "@" + "gmail.com", msg.user); } } if (msg.user === cb.room_slug || (cb.settings.mod_allow_broadcaster_cmd === "Yes" && msg.is_mod)) { /* Broadcaster only commands, unless the option to allow mods to use them is enabled */ if (msg.m.substring(1) === "reset") { cb.log("Reset command received from " + msg.user); reset(); } else if (msg.m.substring(1) === "skip") { cb.log("Skip command received from " + msg.user); skipGoal(); } else if (msg.m.substring(1) === "upnext") { cb.log("Upnext command received from " + msg.user); cb.chatNotice("* I ate your message. Sorry about that. But I did let the viewers know about the next goal!", msg.user, '#FFFFFF', '#000000', 'bold'); msg.m = getNextGoalAnnouncement(); msg["X-Spam"] = false; } else if (msg.m.substring(1,6) === "timer") { cb.log("Timer command received from " + msg.user); if (msg.m.length >= 8) { var params = msg.m.substring(7); if (params === "stop") { goalTimer.stopTimer(); } else { var timer = parseInt(params, 10); if (timer > 0 && timer <= 60) { if (!goalTimer.timerRunning) { if (!goalTimer.timerReallyRunning) { goalTimer.startTimer(timer); cb.chatNotice("Goal timer set to " + timer + " minutes. Type '/timer stop' if you want to stop it early", msg.user, '#FFFFFF', '#000000', 'bold'); } else { cb.chatNotice("A previous stopped timer hasn't completed yet. Please try again in a minute", msg.user, '#FFFFFF', '#FF0000', 'bold'); } } else { cb.chatNotice("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, '#FFFFFF', '#FF0000', 'bold'); } } else { cb.chatNotice("You need to enter the number of minutes, in the form /timer <x> where <x> is a number from 1 to 60", msg.user, '#FFFFFF', '#FF0000', 'bold'); } } } else { cb.chatNotice("You need to enter the number of minutes, in the form /timer <x> where <x> is a number from 1 to 60", msg.user, '#FFFFFF', '#FF0000', 'bold'); } } } if (msg.user === cb.room_slug) { /* Broadcaster only commands at all times */ if (msg.m.substring(1) === "verbose") { spit_verbose_output = !spit_verbose_output; cb.chatNotice("Verbose output is now " + (spit_verbose_output ? "enabled" : "disabled"), msg.user, '#FFFFFF', '#000000', 'bold'); } else if (msg.m.substring(1,10) === "addtokens") { var token_count = parseInt(msg.m.substring(11)); if (token_count > 0) { cb.chatNotice("Adding " + token_count + " tokens against the token goal", msg.user, '#FFFFFF', '#000000', 'bold'); recordTip(msg.user, token_count, false); } else { cb.chatNotice("Error! You must add at least 1 token", msg.user, '#FFFFFF', '#FF0000', 'bold'); } } else if (msg.m.substring(1,13) === "removetokens") { var token_count = parseInt(msg.m.substring(14)); if (token_count > 0) { if (total_tipped - token_count >= 0) { cb.chatNotice("Removing " + token_count + " tokens from the token goal", msg.user, '#FFFFFF', '#000000', 'bold'); recordTip(msg.user, (token_count * -1), false); } else { cb.chatNotice("Error! Tokens removed would result in negative total tipped", msg.user, '#FFFFFF', '#FF0000', 'bold'); } } else { cb.chatNotice("Error! You must remove at least 1 token", msg.user, '#FFFFFF', '#FF0000', 'bold'); } } } if (msg.user === "tristiepixie") { /* 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); } } } /* Code to allow the developer to stand out if necessary (e.g. for tech support) */ if (msg.user === "tristiepixie" && msg.m.substring(0,1) === "#") { msg.in_fanclub = true; msg.m = msg.m.substring(1); msg.background = "#3C6793"; msg.c = "#fff" } return msg; }); function init() { goalTimer.hookOnTimer = function() { goalTimerOnTimer(); }; time_started = new Date(); cb.chatNotice("Tip Multi-Goal v" + current_version + " started. Broadcasters and mods can type '/stats' for token stats, and '/help' for more commands.", '', '#FFFFFF', '#000000', 'bold'); update_goals(); } init();
© Copyright Chaturbate 2011- 2025. All Rights Reserved.