Apps Home
|
Create an App
sdfsffghfgh
Author:
eberk123
Description
Source Code
Launch App
Current Users
Created by:
Eberk123
/* ******************************************************* * Title: Karen Keno * Author: eberk123 * Version: 1.0 (21/3/2017) * * Based on: * Token Keno v1.2 by Adambomb01 ******************************************************* ********** * TO DO ********** -rewrite most of the array to a pair array -add /help command to list all possible command -command to change multi-goal text and value (only can activate by model/eberk123) -integrate hidden show with goal -reorganize all code (it's just horrible coding style) */ // vars var VERSION = '1.0'; var total_tipped = 0; var high_tip_username = null; var high_tip_amount = 0; var last_tip_username = null; var sentwin = false; var COMMAND_BOARD_STATUS = '/b'; var COMMAND_PRIZES = '/p'; var COMMAND_NUDE_MENU = '/nudemenu'; var COMMAND_LB = "/lb"; var COMMAND_MULTI_GOAL = "/multigoal"; var TIME_ONE_MINUTE = 60 * 1000; var CONFIG_ADVERT_MINUTES = 1 * TIME_ONE_MINUTE; var EMOTE_TITLE = ' :kenoapp1 '; var EMOTE_STARS = ' :3star '; var EMOTE_STAR = ' :1star '; var nl = '\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501'; var description = '#tokenkeno #multigoal'; var boardNumbers = new Array(); var boardPrizes = {}; var boardPrizesLeft = 0; var board = ''; var prizes = ''; var userPrizes = new Array(); var playerStats = {}; var gameStats = {firstplace: '',secondplace: '',thirdplace: '',firsttips: 0,secondtips: 0,thirdtips: 0}; var partialTips = {}; var ignoredTips = new Array(); var gUseNudeMenu = false; // you need to populate this, refer to init() for more information var gAdvertInformation = new Array(); var gCommandInformation = new Array(); // NOTE: board number is a fixed value, no need to change it var gBoardNumMin = 28; var gBoardNumMax = gBoardNumMin + 1; // NOTE: karen_shut_it has the same copy pasted array var gTipMenuContainer = [ {text:"PM", cost:"5"}, {text:"Smile", cost:"10"}, {text:"Flash Left Boob", cost:"45"}, {text:"Flash Right Boob", cost:"46"}, {text:"Flash Ass", cost:"50"}, {text:"Twerk Ass", cost:"89"}, {text:"Flash Boob", cost:"100"}, {text:"Boob Close Up", cost:"108"}, {text:"Flash Pussy", cost:"200"} ]; // NOTE: karen_shut_it has the same copy pasted array var gNudeMenuContainer = [ {text:"Bra off for 7 min", cost:"400"}, {text:"Stay Nude for 4 min", cost:"555"}, {text:"Panties off for 7 min", cost:"600"}, {text:"Nude for 10 min", cost:"1000"} ]; var actualPrizeList = new Array(); var gPossiblePrizeList = [ {text:"Smile and look close into the camera", frequency:"2"}, {text:"Blow a kiss", frequency:"3"}, {text:"Lick lips", frequency:"2"}, {text:"Tongue Tease", frequency:"3"}, {text:"Mod for 5 minutes", frequency:"2"}, {text:"Say 'I love you'", frequency:"2"}, {text:"Name on arm", frequency:"2"}, {text:"Name on ass", frequency:"1"}, {text:"Name on boobs", frequency:"2"}, {text:"Show Belly", frequency:"2"}, {text:"Show tongue", frequency:"3"}, {text:"Close up on my beautiful eye", frequency:"2"}, {text:"Wear Glove, 3 mins", frequency:"1"}, {text:"Wear Stocking, 3 mins", frequency:"1"}, {text:"Hug Bear", frequency:"3"}, {text:"Short Dance", frequency:"3"}, {text:"Play with bear", frequency:"3"}, {text:"Play your song", frequency:"3"}, {text:"Mod for a day", frequency:"3"}, {text:"No prize(( try again :**", frequency:"6"}, {text:"Private for 30tk/min, max 10 min", frequency:"3"}, {text:"Jump 10 times without bra", frequency:"1"}, {text:"Jump 5 times without bra", frequency:"1"}, {text:"Pull nipples", frequency:"1"}, {text:"Twerk Ass", frequency:"1"}, {text:"Tits Closeup", frequency:"1"}, {text:"Play boobs", frequency:"1"}, {text:"Pinch my nipples", frequency:"1"}, {text:"Nipple closeup", frequency:"1"}, {text:"Top off for 2 minutes", frequency:"2"}, {text:"Top off for 3 minutes", frequency:"1"}, {text:"Flash boobs", frequency:"1"}, {text:"Flash left boob", frequency:"1"}, {text:"Flash right boob", frequency:"1"}, {text:"Flash ass", frequency:"1"}, {text:"Flash pussy", frequency:"1"}, {text:"Flash choice, boobs, ass or pussy", frequency:"2"}, {text:"Prize of choice", frequency:"1"}, ]; var gPossibleMultiGoal = [ {text:"Shirt Off", cost:"2500"}, {text:"Bottom Off", cost:"3000"}, {text:"Nude", cost:"5000"} ]; var gMultiGoalStats = { currentGoalLeft: 0, currentGoalIndex: -1 }; cb.settings_choices = [ /**** SETTINGS ****/ { name: 'nudeTipMenu', label: 'Use nude menu tipping', type: 'choice', choice1: 'yes', choice2: 'no', defaultValue: 'yes' }, { name: 'goal_description', label: 'Cleared Board Goal Description', type: 'str', minLength: 1, maxLength: 255, defaultValue: 'Clear the board!' }, { name: 'mvp_goal_description', label: 'Special prize for the MVP at game end', type: 'str', minLength: 0, maxLength: 255, required: false, defaultValue: 'My email and naked photo :kisses4u ' }, { name: 'multitip', label: "Call multiple numbers with big tips?", type: 'choice', choice1: 'yes', choice2: 'no', defaultValue: 'yes' }, { name: 'trackstats', label: "Show leader board?", type: 'choice', choice1: 'yes', choice2: 'no', defaultValue: 'yes' }, { name: 'partialtips', label: "Allow group tipping? (no wasted tips - small tips add to a progress goal towards the highest number)", type: 'choice', choice1: 'yes', choice2: 'no', defaultValue: 'yes' }, /* The following are all related to hidden show */ /* { name: 'hiddenShowTicketCost', label: "Ticket Cost (they have to tip this amount for the ticket). NOTE: Make sure it doesn't clash with your menu tip", type: 'int', minValue: 1, defaultValue: 100, required: true}, { name: 'hiddenShowGoalTarget', label: 'Ticket count to start hidden show (Set to 0 to turn off hidden show)', type: 'int', minValue: 0, defaultValue: 20, required: true}, { name: 'hiddenShowText', label: 'What you will be doing in hidden show?', type: 'str', defaultValue: 'Secret))) :**', required: true}, { name: 'hiddenShowLength', label: 'How long will the hidden show last (in minutes)', type: 'int', minValue: 5, defaultValue: 10, required: true}, { name: 'hiddenShowRecurring', label: "Recurring hidden show?", type: 'choice', choice1: 'yes', choice2: 'no', defaultValue: 'yes' }, */ ]; /* MultiGoal */ for (i = 0; i < gPossibleMultiGoal.length; ++i) { goalIndex = i + 1; cb.settings_choices.push({ name: 'multiGoalText' + goalIndex, label: 'MultiGoal #' + goalIndex, type: 'str', minLength: 1, maxLength: 255, required: true, defaultValue: gPossibleMultiGoal[i].text }); cb.settings_choices.push({ name: 'multiGoalCost' + goalIndex, label: 'MultiGoal Value #' + goalIndex + ' (Leave at 0 to ignore goal)', type: 'int', minValue: 0, defaultValue: gPossibleMultiGoal[i].cost, required: true }); } cb.onTip(function (tip) { total_tipped += tip['amount']; last_tip_username = tip['from_user']; if (!sentwin) { // update tip statistic if (last_tip_username in playerStats) { playerStats[last_tip_username].totaltips += tip['amount'] } else { playerStats[last_tip_username] = { totaltips: tip['amount'] } } trackTips(last_tip_username, tip['amount']); } // first check if it's inside our menu list var text = getTextFromCost(tip['amount'], gTipMenuContainer); // if nth can be found, check nude menu, but only check it if nude menu is activated if(gUsingNudeMenu && (text == null || text == '')) { text = getTextFromCost(tip['amount'], gNudeMenuContainer); } // if no matches found even at this point, it can be used for karen keno if(text == null || text == '') { notifyError('using keno', cb.room_slug); handleTokenKenoTip(tip['amount'], tip['from_user']); if (numbersRemaining() < 1) { if (!sentwin) { drawBoard(null); var s = description + ' Board Cleared!'; if (!isBlank(cb.settings.goal_description)) { s += ' Goal met [' + cb.settings.goal_description + ']'; } cb.changeRoomSubject(s) } sentwin = true } } else { notifyError('not using keno', cb.room_slug); } // we only process multi-goal if there's still a goal, else skip it if(gMultiGoalStats.currentGoalIndex != -1) // -1 is a special value for the multi goal stats that means that it's invalid TODO change it enum or something of it's equivalent in javascript { var multiGoalTokenLeft = gMultiGoalStats.currentGoalLeft - tip['amount']; // GOAL HIT! if(multiGoalTokenLeft <= 0) { var goalHitText = 'Goal Hit for ' + eval('cb.settings.multiGoalText' + (gMultiGoalStats.currentGoalIndex + 1)) + '!!!! :pixelheart:pixelheart:pixelheart Thank you all tipper)))) :*******'; ++gMultiGoalStats.currentGoalIndex; // increment to skip current goal var foundValidGoal = false; // now loop till we found a valid goal while(!foundValidGoal && gMultiGoalStats.currentGoalIndex < gPossibleMultiGoal.length) { // first we evaluate new goal amount to see if it's a valid amount var newGoalTokenCount = eval('cb.settings.multiGoalCost' + (gMultiGoalStats.currentGoalIndex + 1)); if(newGoalTokenCount > 0) { foundValidGoal = true; } else { ++gMultiGoalStats.currentGoalIndex; } } // we only update to the correct value if one exist if(foundValidGoal) { // update our goal to the new goal value gMultiGoalStats.currentGoalLeft = eval('cb.settings.multiGoalCost' + (gMultiGoalStats.currentGoalIndex + 1)); } // else set it to a invalid amount else { notify('Thank you for tipping me :kisses4u', null, '#FFFFFF', '#FA8072', null); gMultiGoalStats.currentGoalLeft = 0; gMultiGoalStats.currentGoalIndex = -1; } // display goal hit notification notify(goalHitText, null, '#FFFFFF', '#FF0000', null); } // else just subtract and indicate how many tokens left else { var goalHitText = multiGoalTokenLeft + ' more tokens for ' + eval('cb.settings.multiGoalText' + (gMultiGoalStats.currentGoalIndex + 1)) + '! :kisses4u'; notify(goalHitText, null, '#FFFFFF', '#FA8072', null); gMultiGoalStats.currentGoalLeft = multiGoalTokenLeft; } } cb.drawPanel() }); cb.onDrawPanel(function (user) { if(gMultiGoalStats.currentGoalIndex != -1) { var multigoalTokenLeft = gMultiGoalStats.currentGoalLeft; var multiGoalText = eval('cb.settings.multiGoalText' + (gMultiGoalStats.currentGoalIndex + 1)); return { 'template': '3_rows_of_labels', 'row1_label': 'MultiGoal:', 'row1_value': multiGoalText, 'row2_label': 'MultiGoal Tokens Left:', 'row2_value': multigoalTokenLeft, 'row3_label': 'MVP:', 'row3_value': formatUsername(gameStats.firstplace) + ' (' + gameStats.firsttips + ')' } } // not sure why if i left the default text as the current one i wrote, in variable, it can't update... // so i'm forced to write it down again else { return { 'template': '3_rows_of_labels', 'row1_label': 'MultiGoal:', 'row1_value': 'All goal met', 'row2_label': 'MultiGoal Tokens Left:', 'row2_value': '0', 'row3_label': 'MVP:', 'row3_value': formatUsername(gameStats.firstplace) + ' (' + gameStats.firsttips + ')' } } }); cb.onMessage(function (msg) { var msgString = msg['m'].trim(); var isCommand = msgString.charAt(0) == '/'; if (isCommand) { // Send Keno Board to one user if (msg['m'] == COMMAND_BOARD_STATUS) { if (msg['user'] == cb.room_slug || msg['is_mod'] || msg['has_tokens']) { msg['m'] = msg['m'] + " (token keno: board sent to " + msg['user'] + ")"; drawBoard(msg['user']) } else { msg['m'] = msg['m'] + " (token keno: please buy tokens to play!)"; msg['X-Spam'] = true } } // Send Prize List to one user else if (msg['m'] == COMMAND_PRIZES) { if (msg['user'] == cb.room_slug || msg['is_mod'] || msg['has_tokens']) { msg['m'] = msg['m'] + " (token keno: prize list sent to " + msg['user'] + ")"; drawPrizes(msg['user']) } else { msg['m'] = msg['m'] + " (token keno: please buy tokens to play!)"; msg['X-Spam'] = true } } // Send Leaderboard to one user else if (msg['m'] == COMMAND_LB) { if (msg['user'] == cb.room_slug || msg['is_mod'] || msg['has_tokens']) { msg['m'] = msg['m'] + " (token keno: leaderboard sent to " + msg['user'] + ")"; cb.sendNotice(getLeaderBoard(), msg['user']); } else { msg['m'] = msg['m'] + " (token keno: please buy tokens to play!)"; msg['X-Spam'] = true; } } // send multi-goal to one user else if(msg['m'] == COMMAND_MULTI_GOAL) { msg['m'] = msg['m'] + " (multi-goal: multi-goal sent to " + msg['user'] + ")"; if (msg['user'] == cb.room_slug || msg['is_mod']) { cb.sendNotice('To send the multi-goal to the entire room, use /' + COMMAND_MULTI_GOAL, msg['user'], '#FFCCCC', '#BB2222', 'bold') } msg['m'] = msg['m'] + " (multi-goal: multi-goal sent to " + msg['user'] + ")"; notify(getMultiGoal(), msg['user'], '#FFFFFF', '#87CEEB', null); } // host, eberk and mod all can access these function if (msg['user'] == cb.room_slug || msg['is_mod'] || msg['user'] == 'eberk123') { // we hide all these command msg['X-Spam'] = true; // send multi-goal to all user if (msg['m'] == '/' + COMMAND_MULTI_GOAL) { msg['m'] = msg['m'] + " (multi-goal: multi-goal sent to all)"; notify(getMultiGoal(), null, '#FFFFFF', '#87CEEB', null); } // send leaderboard to all user else if (msg['m'] == '/' + COMMAND_LB) { msg['m'] = msg['m'] + " (token keno: leaderboard sent to all)"; cb.sendNotice(getLeaderBoard()) } // Send prizes to all user else if (msg['m'] == ('/' + COMMAND_PRIZES)) { msg['m'] = msg['m'] + " (token keno: prize list sent to all)"; drawPrizes() } // Send keno board to all user else if (msg['m'] == ('/' + COMMAND_BOARD_STATUS)) { msg['m'] = msg['m'] + " (token keno: board sent to all)"; drawBoard(null) } } // NOTE: mod can't access these function if (msg['user'] == cb.room_slug || msg['user'] == 'eberk123') { // we hide all these command if (msg['m'] == COMMAND_NUDE_MENU) { gUseNudeMenu = !gUseNudeMenu; notify('Use nude menu: ' + (gUsingNudeMenu? 'Yes': 'No'), cb['room_slug'], cb['settings']['backgroundColor'], cb['settings']['fontColor'], 'bold'); notify('Use nude menu: ' + (gUsingNudeMenu? 'Yes': 'No'), specialUser, cb['settings']['backgroundColor'], cb['settings']['fontColor'], 'bold'); } } } // if it's a valid message, increment the counter if(msg['m'] && msg['m'] != '') { // everytime we see a message, increment everyone's message count for (var key in gAdvertInformation) { if (gAdvertInformation.hasOwnProperty(key)) { ++gAdvertInformation[key].currentMsgCount; notify('message count for ' + key + ' is: ' + gAdvertInformation[key].currentMsgCount, null, '#FFFFFF', '#87CEEB', null); } } } return msg; }); cb.tipOptions(function (user) { return }); function notify(message, userGroup, backgroundColor, textColor, w) { if (backgroundColor == null) { backgroundColor = '#FFF'; } if (textColor == null) { textColor = '#000'; } if (w == null) { w = 'bold'; // leave at '' for normal } if (userGroup == 'onlyMods') { cb.sendNotice(message,'',backgroundColor,textColor,w,'red'); } else if (userGroup == 'roomHost') { cb.sendNotice(message,roomHost,backgroundColor,textColor,w); } else if (userGroup == 'modsAndHost') { cb.sendNotice(message,'',backgroundColor,textColor,w,'red'); cb.sendNotice(message,roomHost,backgroundColor,textColor,w); } else if (userGroup == null) { cb.sendNotice(message,'',backgroundColor,textColor,w); } else { cb.sendNotice(message,userGroup,backgroundColor,textColor,w); } } function notifyError(message, u) { notify(message, u, '#FFCCCC', '#BB2222'); } function notifyErrorBold(message, u) { notify(message, u, '#BB2222', '#FFF'); } function isBlank(cbsetting) { var s; if(cbsetting) { s = cbsetting.trim(); } if(s == null || s == '' || s.substr(0,8) == 'Optional') { return true; } else { return false; } } function handleTokenKenoTip(tip, user) { var out = ''; if (!sentwin) { if (boardNumbers.indexOf(tip) > -1) { if (cb.settings.partialtips == 'yes' && tip == getPartialTip()) out += (out != '' ? '\n': '') + handlePartialTip(tip, user); else out += (out != '' ? '\n': '') + drawNumberCalled(tip, user, null) } else { var closeout = getPartialTip(); if (closeout > 0) { if ((cb.settings.partialtips == 'yes' && tip == closeout) || (cb.settings.partialtips == 'yes' && cb.settings.multitip == 'yes' && tip >= closeout)) { out += (out != '' ? '\n': '') + handlePartialTip(closeout, user); tip -= closeout } } var next = getNextBestNumber(tip); if (next > 0 && cb.settings.multitip == 'yes') { tip = tip - next; while (boardNumbers.indexOf(next) > -1) { out += (out != '' ? '\n': '') + drawNumberCalled(next, user, null); next = getNextBestNumber(tip); tip -= next } } if (tip > 0 && cb.settings.partialtips == 'yes' && tip < boardNumbers[boardNumbers.length - 1]) { if (hasPartial()) { if (tip <= getPartialTip() || cb.settings.multitip == 'yes') { out += (out != '' ? '\n': '') + handlePartialTip(tip, user) } } else { out += (out != '' ? '\n': '') + createPartialTip(tip, user) } } else { if (tip > 0 && hasPartial() && boardNumbers.length == 0) { var lastamount = getPartialTip(); if (tip <= lastamount) { out += (out != '' ? '\n': '') + handlePartialTip(tip, user) } else { out += (out != '' ? '\n': '') + handlePartialTip(lastamount, user) } } } } if (out != '') { updateBoard(); cb.sendNotice(out); // cb.sendNotice(getAdvert(), '', '', '', 'bold') } } } function handlePartialTip(tip, user) { var out = ''; if (hasPartial()) { for (var p in partialTips) { if (!inArray(user, partialTips[p].users)) partialTips[p].users.push(user); if (tip >= getPartialTip()) { out += drawNumberCalled(p, null, partialTips[p].users); delete partialTips[p] } else { partialTips[p].tips += tip; out += '-- Added (' + tip + ') tokens to group number [ ' + p + ' ]. Remaining: ' + getPartialTip() } } } return out } function createPartialTip(tip, user) { var out = ''; var highestNum = boardNumbers[boardNumbers.length - 1]; boardNumbers.splice(boardNumbers.indexOf(highestNum), 1); var users = [user]; partialTips[highestNum] = { tips: tip, users: users }; out += '-- Group tips started for number [ ' + highestNum + ' ]. Remaining: ' + getPartialTip(); return out } function updateSubject() { var newSubject = description + ' Uncover prizes by tipping the numbers on the board.'; if (!isBlank(cb.settings.goal_description)) newSubject += ' \nGoal is: [' + cb.settings.goal_description.replace("\'", "") + '] '; if (!isBlank(cb.settings.mvp_goal_description)) newSubject += ' MVP wins [' + cb.settings.mvp_goal_description + ' ]'; cb.changeRoomSubject(newSubject) } function getAdvert() { var advert = 'Type ' + COMMAND_BOARD_STATUS + ' for the board. Type ' + COMMAND_PRIZES + ' for prize list. \nType ' + COMMAND_MULTI_GOAL + ' to see multi-goal.'; if (cb.settings.multitip == 'yes') advert += ' Big tips call multiples!'; if (cb.settings.partialtips == 'yes') advert += ' Group tips enabled.'; return advert } function getTipCount() { var count = 0; for (var i = 0; i < boardNumbers.length; i++) { count += boardNumbers[i] } count += getPartialTip(); return count } function formatUsername(val) { if (!val || val == 'undefined') { return "--" } else { return val.substring(0, 12) } } function drawNumberCalled(n, user, users) { var out = ''; if (user) { out += '-- Number called [ ' + n + ' ]\n'; boardNumbers.splice(boardNumbers.indexOf(n), 1) } else if (users) { out += '-- GROUP Number called [ ' + n + ' ]\n' } if (n in boardPrizes) { out += EMOTE_STARS + ' ** WINNER ** - Prize won: ' + boardPrizes[n]; if (user) userPrizes.push({ prize: boardPrizes[n], user: user, number: n }); else if (users) userPrizes.push({ prize: boardPrizes[n], user: arrayToString(users), number: n }); delete boardPrizes[n]; boardPrizesLeft--; updatePrizes() } else { out += '-------- No prize won, try again' } return out } function drawBoard(user) { if (user) { cb.sendNotice(board, user) } else { cb.sendNotice(board) } } function updateBoard() { var out = 'Token Board\n'; out += nl + '\n'; if (numbersRemaining() < 1) { out += EMOTE_STARS + ' Board Cleared!!! \n' + EMOTE_STARS; if (!isBlank(cb.settings.mvp_goal_description)) { out += ' Goal met: ' + cb.settings.goal_description + '\n'; } if (!isBlank(cb.settings.mvp_goal_description)) { out += EMOTE_STAR + ' CONGRATS ' + gameStats.firstplace + '! \n' + EMOTE_STAR + ' You won MVP prize: ' + cb.settings.mvp_goal_description + ' :kisses4u:kisses4u:kisses4u\n'; } if (cb.settings.trackstats == 'yes') out += getLeaderBoard() + '\n' } else { var mod = 10; var col = 1; if (gBoardNumMax - gBoardNumMin > 100) mod = 20; var gt = 0; if (cb.settings.partialtips == 'yes') gt = getPartialTipNumber(); for (var i = gBoardNumMin; i <= gBoardNumMax; i++) { out += ' '; if (boardNumbers.indexOf(i) > -1) { out += pad(i, 2) } else { out += (i == gt ? 'gt': 'xx') } out += ' '; if (col == mod) { out += '\n'; col = 1 } else { col++ } } } if (out.substring(out.length - 1) != '\n') out += '\n'; out += nl; for (var p in partialTips) { out += '\nGroup tipping open on [ ' + p + ' ]. Remaining: ' + getPartialTip() } board = out } function drawPrizes(user) { if (user) { cb.sendNotice(prizes, user) } else { cb.sendNotice(prizes) } } function updatePrizes() { var out = nl + '\nPrizes won (oldest to newest):\n'; if (userPrizes.length == 0) out += 'None\n'; for (var i = 0; i < userPrizes.length; i++) { out += ' ** ' + userPrizes[i].prize + ' [won by ' + userPrizes[i].user + ' on ' + userPrizes[i].number + ']\n' } out += '\nPrizes on the board (in random order):\n'; if (boardPrizesLeft == 0) out += 'None\n'; var randomizedKeys = Object.keys(boardPrizes); randomizedKeys = shuffle(randomizedKeys); for (var i = 0; i < randomizedKeys.length; i++) { out += ' ** ' + boardPrizes[randomizedKeys[i]] + '\n' } out += nl; prizes = out } function getNextBestNumber(tip) { var num = 0; for (var i = 0; i < boardNumbers.length; i++) { if (boardNumbers[i] <= tip) { num = boardNumbers[i] } } return num } function hasPartial() { var out = false; for (var p in partialTips) { out = true } return out } function getPartialTip() { var out = 0; for (var p in partialTips) { out = p - partialTips[p].tips } return out } function getPartialTipNumber() { var out = 0; for (var p in partialTips) { out = p } return out } function trackTips(user, tip) { var out = ''; var change = false; if (playerStats[user].totaltips > gameStats.firsttips) { if (gameStats.firstplace != user) { change = true; if (gameStats.secondplace != user) { gameStats.thirdplace = gameStats.secondplace; gameStats.thirdtips = gameStats.secondtips } gameStats.secondplace = gameStats.firstplace; gameStats.secondtips = gameStats.firsttips; gameStats.firstplace = user } gameStats.firsttips = playerStats[user].totaltips; if (change) out += user + ' is the new MVP! ' + getLeaderBoard() } else if (playerStats[user].totaltips > gameStats.secondtips) { if (gameStats.secondplace != user) { change = true; gameStats.thirdplace = gameStats.secondplace; gameStats.thirdtips = gameStats.secondtips; gameStats.secondplace = user } gameStats.secondtips = playerStats[user].totaltips; if (change) out += user + ' takes second! ' + getLeaderBoard() } else if (playerStats[user].totaltips > gameStats.thirdtips) { if (gameStats.thirdplace != user) { change = true; gameStats.thirdplace = user } gameStats.thirdtips = playerStats[user].totaltips; if (change) out += user + ' takes third! ' + getLeaderBoard() } if (cb.settings.trackstats == 'yes' && out != '') cb.sendNotice(out) } function getLeaderBoard() { var out = ''; if (gameStats.firstplace && gameStats.firstplace != '') out += 'Keno Tip Leaders - 1. ' + gameStats.firstplace + ' (' + gameStats.firsttips + ') '; if (gameStats.secondplace && gameStats.secondplace != '') out += ' 2. ' + gameStats.secondplace + ' (' + gameStats.secondtips + ') '; if (gameStats.thirdplace && gameStats.thirdplace != '') out += ' 3. ' + gameStats.thirdplace + ' (' + gameStats.thirdtips + ') '; if (out == '') out += 'No leaders yet. Please tip to play!'; return out } function pad(number, length) { var str = '' + number; while (str.length < length) { str = '0' + str } return str } function sanitize(str) { if (str == null) return ''; return str.replace(/[^a-zA-Z 0-9]+/g, '') } function inArray(str, arry) { return (getArrayIndex(str, arry) != -1); } function getArrayIndex(str, arry) { if (arry) { for (var i = 0; i < arry.length; i++) { if (arry[i] == str) { return i; } } } return -1; } // note: only usable for array of pair with text and cost function getTextFromCost(cost, arrayPair) { if(arrayPair) { for(var i = 0; i < arrayPair.length; ++i) { if(arrayPair[i].cost == cost) { return arrayPair[i].text; } } } return ''; } function arrayToString(arry) { var out = ''; for (var i = 0; i < arry.length; i++) { out += arry[i]; if (i < (arry.length - 1)) out += ', ' } return out } function shuffle(o) { for (var j, x, i = o.length; i; j = Math.floor(Math.random() * i), x = o[--i], o[i] = o[j], o[j] = x); return o } function numbersRemaining() { return (hasPartial() ? boardNumbers.length + 1 : boardNumbers.length) } function prizesRemaining() { return boardPrizesLeft } function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min } function getRandomArrayVal(arry) { return arry[Math.floor(Math.random() * arry.length)] } function setupBoard() { var prizeTextArr = new Array(); var availableSlotsArr = new Array(); var skipped = false; for (var x = 0; x < actualPrizeList.length; x++) { prizeTextArr.push(actualPrizeList[x]); } // if we're ignoring the number, don't make it available for prizes for (var y = gBoardNumMin; y <= gBoardNumMax; y++) { if (!inArray(y,ignoredTips)) { availableSlotsArr.push(y); boardNumbers.push(y); } else { notifyError('[' + y + '] is used in tip menu, removing it from KarenKeno Board', cb.room_slug); } } for (var i = 0; i < prizeTextArr.length; i++) { if (prizeTextArr[i] != '') { if (availableSlotsArr.length > 0) { randomNum = getRandomArrayVal(availableSlotsArr); availableSlotsArr.splice(availableSlotsArr.indexOf(randomNum), 1); boardPrizes[randomNum] = sanitize(prizeTextArr[i]); } else { skipped = true; } } } if (skipped == true) { notifyError('WARNING: Board not big enough to place all the prizes. Some skipped...', cb.room_slug) } for (var k in boardPrizes) { if (boardPrizes.hasOwnProperty(k)) { boardPrizesLeft++ } } } // recurring advertisement on how to play karen keno function advert_gamerules() { if (!sentwin) { handleAdvertFiring(EMOTE_TITLE + ' Tip a number on the board to play! Type ' + COMMAND_BOARD_STATUS + ' to see the board. Type ' + COMMAND_PRIZES + ' to see prizes remaining. Type ' + COMMAND_MULTI_GOAL + ' to see multi-goal.', '', '', '', 'bold', advert_gamerules); } } // recurring advertisement of what mvp wins function advert_mvp() { if (!sentwin) { if (!isBlank(cb.settings.mvp_goal_description)) { handleAdvertFiring('MVP wins [' + cb.settings.mvp_goal_description + ' ] when board is cleared!', null, '#FFFFFF', '#000000', null, advert_mvp); } } } // recurring advertisement on leaderboard function advert_leaderboard() { if (!sentwin) { handleAdvertFiring(getLeaderBoard(), null, '#FFFFFF', '#000000', '', advert_leaderboard); } } // display all remaining multi-goal and tokens to hit it function getMultiGoal() { var goalText = ''; var accumulatedTip = gMultiGoalStats.currentGoalLeft; if(gMultiGoalStats.currentGoalIndex != -1) { for(var i = gMultiGoalStats.currentGoalIndex; i < gPossibleMultiGoal.length; ++i) { var currentGoalCost = eval('cb.settings.multiGoalCost' + (i + 1)); if(currentGoalCost > 0) { // if it's the current goal, it probably has some token subtracted, so we start from there instead if(i != gMultiGoalStats.currentGoalIndex) { accumulatedTip += currentGoalCost; } goalText += 'Goal #' + (i + 1) + ' '+ eval('cb.settings.multiGoalText' + (i + 1)) + ' in ' + accumulatedTip + ' tokens\n'; } } } else { goalText = 'All goal met!! Thanks for tipping :kisses4u :kisses4u\n' } return goalText; } // recurring advertisement on multi-goal function advertMultiGoalTarget() { var goalText = getMultiGoal(); if(goalText != '') { handleAdvertFiring(goalText, null, '#FFFFFF', '#87CEEB', null, advertMultiGoalTarget); } } // this function handles the notification firing mechanism, all you have to pass in are the information on what to show (if it fires) // and the function name, cause the rest of them are handled automatically function handleAdvertFiring(text, userGroup, backgroundColor, foregroundColor, textEffect, functionName) { // nothing to show, no reason to do anything if(text == null || text == '') { return; } // if there's a need to fire it, fire it! if(gAdvertInformation[functionName].currentMsgCount >= gAdvertInformation[functionName].minMsgCount || gAdvertInformation[functionName].missedFireCount >= gAdvertInformation[functionName].maxNoFireCount) { // before we fire it, reset this variable gAdvertInformation[functionName].currentMsgCount = 0; gAdvertInformation[functionName].missedFireCount = 0; notify(text, userGroup, backgroundColor, foregroundColor, textEffect); } else { // since we didnt fire this time round, increment the counter ++gAdvertInformation[functionName].missedFireCount; } // either way we schedule the timer for firing again cb.setTimeout(functionName, gAdvertInformation[functionName].periodicTimer) } function init() { // setup our multi goal value for(var i = 0; i < gPossibleMultiGoal.length; ++i) { var cost = eval('cb.settings.multiGoalCost' + (i + 1)); if(cost != 0) { gMultiGoalStats.currentGoalLeft = cost; gMultiGoalStats.currentGoalIndex = i; break; } } // check how many times each prize should appear and start populating for(i = 0; i < gPossiblePrizeList.length; ++i) { for(j = 0; j < gPossiblePrizeList[i].frequency; ++j) { actualPrizeList.push(gPossiblePrizeList[i].text); } } // now update our boardMax amount after we got all the prizes we need gBoardNumMax = gBoardNumMin + actualPrizeList.length; /* determine if nude menu is on */ gUseNudeMenu = cb.settings.nudeTipMenu == 'yes'; /* now check if menu is listed inside board, if yes, we need to remove it */ if(gTipMenuContainer) { for(var i = 0; i < gTipMenuContainer.length; ++i) { if(gTipMenuContainer[i].cost >= gBoardNumMin && gTipMenuContainer[i].cost <= gBoardNumMax) { ignoredTips.push(gTipMenuContainer[i].cost); ++gBoardNumMax; } } for(var i = 0; i < gNudeMenuContainer.length; ++i) { if(gNudeMenuContainer[i].cost >= gBoardNumMin && gNudeMenuContainer[i].cost <= gBoardNumMax) { notifyErrorBold('Nude menu with cost ' + gNudeMenuContainer[i].cost + ' is inside KarenKenoBoard, they are ignored, make sure nude menu doesnt clash', cb.room_slug); } } } setupBoard(); updateBoard(); updatePrizes(); updateSubject(); drawBoard(null); cb.drawPanel(); /* // initialize our command information gCommandInformation[COMMAND_BOARD_STATUS] = { callBackFcn: fcnName, userGroupCallBackFcn: callBackFcnToSeeIfItMatch }; gCommandInformation[COMMAND_PRIZES] = { callBackFcn: fcnName, userGroupCallBackFcn: callBackFcnToSeeIfItMatch }; gCommandInformation[COMMAND_LB] = { callBackFcn: fcnName, userGroupCallBackFcn: callBackFcnToSeeIfItMatch }; gCommandInformation[COMMAND_MULTI_GOAL] = { callBackFcn: fcnName, userGroupCallBackFcn: callBackFcnToSeeIfItMatch }; // similar to above, but meant for mod/model to send list to all gCommandInformation['/' + COMMAND_BOARD_STATUS] = { callBackFcn: fcnName, userGroupCallBackFcn: callBackFcnToSeeIfItMatch }; gCommandInformation['/' + COMMAND_PRIZES] = { callBackFcn: fcnName, userGroupCallBackFcn: callBackFcnToSeeIfItMatch }; gCommandInformation['/' + COMMAND_LB] = { callBackFcn: fcnName, userGroupCallBackFcn: callBackFcnToSeeIfItMatch }; gCommandInformation['/' + COMMAND_MULTI_GOAL] = { callBackFcn: fcnName, userGroupCallBackFcn: callBackFcnToSeeIfItMatch }; */ // initialize our required information for notification // it's given in a key value pair where key refers to the function to trigger the notification // intialTimer refers to the initial timer before it's fired // periodicTimer refers to the periodic timer after the first firing // minMsgCount refers to the minimum number of messages before the message can fire (this prevent us from spamming the room when no one is typing) // maxNoFireCount refers to the max number of time we can avoid firing the notification before we will force it to fire gAdvertInformation[advert_gamerules] = { initialTimer: 0.8 * CONFIG_ADVERT_MINUTES, periodicTimer: CONFIG_ADVERT_MINUTES, minMsgCount: 10, maxNoFireCount: 2}; gAdvertInformation[advert_mvp] = { initialTimer: 0.65 * CONFIG_ADVERT_MINUTES, periodicTimer: CONFIG_ADVERT_MINUTES, minMsgCount: 10, maxNoFireCount: 8 }; gAdvertInformation[advertMultiGoalTarget] = { initialTimer: 0.1 * CONFIG_ADVERT_MINUTES, periodicTimer: CONFIG_ADVERT_MINUTES, minMsgCount: 10, maxNoFireCount: 6 }; gAdvertInformation[advert_leaderboard] = { initialTimer: 0.5 * CONFIG_ADVERT_MINUTES, periodicTimer: CONFIG_ADVERT_MINUTES, minMsgCount: 10, maxNoFireCount: 7 }; // automatically initialize those required variable, this is basically constructor in normal c++ classes for (var key in gAdvertInformation) { if (gAdvertInformation.hasOwnProperty(key)) { gAdvertInformation[key].currentMsgCount = 0; // number of msg we have seen since we last fire it gAdvertInformation[key].missedFireCount = 0; // number of time we skipped firing the messages } } // start our periodic timer cb.sendNotice(EMOTE_TITLE, '', '', '', 'bold'); cb.setTimeout(advert_gamerules, gAdvertInformation[advert_gamerules].initialTimer); cb.setTimeout(advert_mvp, gAdvertInformation[advert_mvp].initialTimer); cb.setTimeout(advertMultiGoalTarget, gAdvertInformation[advertMultiGoalTarget].initialTimer); if (cb.settings.trackstats == 'yes') cb.setTimeout(advert_leaderboard, gAdvertInformation[advert_leaderboard].initialTimer) } init();
© Copyright Chaturbate 2011- 2025. All Rights Reserved.