Apps Home
|
Create an App
sf23423sdf23eehgjhj
Author:
eberk123
Description
Source Code
Launch App
Current Users
Created by:
Eberk123
/* ******************************************************* * Title: Karen Keno * Author: eberk123 * Version: 1.9 (21/3/2017) * ******************************************************* */ // vars var gHighTipUsername = null; var gHighTipAmount = 0; var last_tip_username = null; var TIME_ONE_SEC = 1000; var TIME_ONE_MINUTE = 60 * TIME_ONE_SEC; var CONFIG_ADVERT_MINUTES = 1 * TIME_ONE_MINUTE; var EMOTE_STAR = ' :star_olivia_dellvine '; var EMOTE_STARS = EMOTE_STAR + EMOTE_STAR + EMOTE_STAR; var gGoalCommand = '/setgoaltarget'; var gGoalCommand = '/setgoaltarget'; var gSpecialUser = 'piglovesalmon'; // KarenJackpot specific stuff that are constant var gRarePrizeIncrementRate = 1.1; // rate at which rare prize chance increases var gInitialRarePrizeChance = 1; // initial chance in % at which rare prize occurs var gGoalTarget = 9; // how much token for goal var gMaxRarePrizeBeforeLowChance = 5; // max rare chance before we don't increase the probability of it occurring var gMaxCommonPrizeCount = 5; // max common prize per roll // KarenJackpot specific stuff that changes over time var gJackpot = new Array(); var gJackpotPrize = new Array(); var gCurrentRarePrizeChance = 0; var gCurrentGoalTarget = 0; var gCurrentGoalCount = 0; var gTotalTip = 0; var gWinner = ''; // requires resetting too var playerStats = {}; var gameStats = {firstplace: '',secondplace: '',thirdplace: '',firsttips: 0,secondtips: 0,thirdtips: 0}; var gCurrentCommandArg = new Array(); // i'm abusing global variable here, this is used to store current command argument (only valid during command parsing) // you need to populate this, refer to init() for more information var gAdvertInformation = new Array(); var gCommandInformation = new Array(); var gCommonPrizeList = new Array(); var gRarePrizeList = new Array(); var gPossibleCommonPrizeList = [ {text:"Smile", frequency:"35"}, {text:"Smile and look close into the camera", frequency:"35"}, {text:"Blow a kiss", frequency:"35"}, {text:"Lick lips", frequency:"35"}, {text:"Tongue Tease", frequency:"35"}, {text:"Say 'I love you'", frequency:"35"}, {text:"Show Belly", frequency:"35"}, {text:"Show tongue", frequency:"35"}, {text:"Close up on my eye", frequency:"35"}, {text:"Short Dance", frequency:"15"}, {text:"Play your song", frequency:"5"}, {text:"Name on arm", frequency:"2"}, {text:"Name on ass", frequency:"2"}, {text:"Name on boobs", frequency:"2"}, {text:"Flash ass", frequency:"15"}, {text:"Flash Right Boob", frequency:"15"}, {text:"Flash Left Boob", frequency:"15"}, {text:"Mod for a day", frequency:"5"} ]; var gPossibleRarePrizeList = [ {text:"Flash boobs", frequency:"15"}, {text:"Private for 30tk/min, max 10 min", frequency:"5"}, {text:"Pull nipples", frequency:"8"}, {text:"Tits Closeup", frequency:"8"}, {text:"Play boobs", frequency:"5"}, {text:"Pinch my nipples", frequency:"5"}, {text:"Flash pussy", frequency:"5"}, {text:"Flash choice, boobs, ass or pussy", frequency:"5"}, {text:"Jump 10 times without bra", frequency:"2"}, {text:"Top off for 2 minutes", frequency:"2"}, {text:"Prize of choice", frequency:"2"}, ]; var gPossibleJackpot = [ {text:"Naked 10 min", target:"1000"}, {text:"Top off for rest of show", target:"1000"}, {text:"Email and naked photo for jackpot winner", target:"1000"}, {text:"Bottom off for rest of show", target:"2000"}, {text:"Karen choose a prize", target:"2000"} ]; /* SETTINGS */ cb.settings_choices = new Array(); /* cb.settings_choices = [ { name: 'goalTarget', label: 'Goal Token Cost', type: 'int', defaultValue: gGoalTarget } ]; */ /* KarenJackpot */ for (i = 0; i < gPossibleJackpot.length; ++i) { goalIndex = i + 1; cb.settings_choices.push({ name: 'jackpotText' + goalIndex, label: 'Jackpot #' + goalIndex, type: 'str', minLength: 1, maxLength: 255, required: true, defaultValue: gPossibleJackpot[i].text }); cb.settings_choices.push({ name: 'jackpotTarget' + goalIndex, label: 'Jackpot #' + goalIndex + ' (Leave at 0 to turn off prize)', type: 'int', defaultValue: gPossibleJackpot[i].target, required: true }); } /* ON TIP */ cb.onTip(function (tip) { last_tip_username = tip['from_user']; if(tip['amount'] > gHighTipAmount) { gHighTipAmount = tip['amount']; gHighTipUsername = tip['from_user']; } IncrementAdvertMessagesCount(); if (last_tip_username in playerStats) { playerStats[last_tip_username].totaltips += tip['amount'] } else { playerStats[last_tip_username] = { totaltips: tip['amount'] } } // update tip statistic trackTips(last_tip_username, tip['amount']); handleKarenJackpot(tip['amount'], tip['from_user']); cb.drawPanel(); }); /* DRAW PANEL */ cb.onDrawPanel(function (user) { return { 'template': '3_rows_of_labels', 'row1_label': 'Token to next goal:', 'row1_value': (gGoalTarget - gCurrentGoalTarget), 'row2_label': 'Chance for Rare Prize:', 'row2_value': Math.ceil(gCurrentRarePrizeChance) + '%', 'row3_label': 'Jackpot Prize:', 'row3_value': gJackpot.length == 0? 'None': gJackpot[0].text } }); function IncrementAdvertMessagesCount() { // everytime we see a message, increment everyone's message count for (var key in gAdvertInformation) { if (gAdvertInformation.hasOwnProperty(key)) { ++gAdvertInformation[key].currentMsgCount; } } } function handleKarenJackpot(tipAmount, user) { gCurrentGoalTarget += tipAmount; gTotalTip += tipAmount; for(var i = 0; i < gJackpot.length;) { if(gTotalTip >= gJackpot[i].target) { gJackpotPrize.push(gJackpot[i].text); // add jackpot to jackpot prize list gJackpot.splice(i, 1); // remove it from array } // only increment 'i' if we not removing anything else { ++i; } } var rarePrizeWonCount = 0; var goalMetCount = 0; // as long as we have left over, continue looping while(gCurrentGoalTarget >= gGoalTarget) { ++goalMetCount; // track how many times we met the goal var currentPrize = ''; var isJackpotWon = false; var rolledChance = Math.random() * 100; //var debugText = 'rolled: ' + rolledChance + '% require ' + gCurrentRarePrizeChance + '%'; //notify(debugText); // first roll and see if we hit the rare chance if(rolledChance < gCurrentRarePrizeChance) { ++rarePrizeWonCount; if(gJackpotPrize.length != 0) { isJackpotWon = true; } // now pick something from rare prize pool currentPrize = getPrizeFromPrizeList(gRarePrizeList, gPossibleRarePrizeList); // track previous rare prize winner gWinner += currentPrize + ' - won by ' + user + '\x0A'; // display the prize that we won notify(EMOTE_STARS + user + EMOTE_STARS + ' WINNER ' + ' - Rare Prize won: ' + currentPrize); gCurrentRarePrizeChance = gInitialRarePrizeChance; // we want to reset it each time we get a rare prize } // since we didn't get a rare prize, we increment the chance for it instead // NOTE: if we already won a rare prize this time round, we dont bother incrementing the chance of success else if(rarePrizeWonCount < gMaxRarePrizeBeforeLowChance) { gCurrentRarePrizeChance *= gRarePrizeIncrementRate; } // if jackpot is won if(isJackpotWon) { // always take the first jackpot prize then remove it notify(EMOTE_STARS + 'JACKPOT!!!!' + EMOTE_STARS + gJackpotPrize[0]); gJackpotPrize.shift(); } gCurrentGoalTarget -= gGoalTarget; ++gCurrentGoalCount; } for(var i = 0; i < goalMetCount && i < gMaxCommonPrizeCount; ++i) { // pick something from common prize pool and display it notify(EMOTE_STAR + user + EMOTE_STAR + ' WINNER ' + ' - Prize won: ' + getPrizeFromPrizeList(gCommonPrizeList, gPossibleCommonPrizeList)); } } function getPrizeFromPrizeList(prizeList, possiblePrizeList) { // if empty, we repopulate the list first if(prizeList.length == 0) { for(var i = 0; i < possiblePrizeList.length; ++i) { for(var j = 0; j < possiblePrizeList[i].frequency; ++j) { prizeList.push(possiblePrizeList[i].text); } } } // fetch from the prize list (guaranteed to have something so don't bother checking) var randIndex = Math.floor(Math.random() * (prizeList.length - 1)); var currentPrize = prizeList[randIndex]; // remove it from the prize list prizeList.splice(randIndex, 1); return currentPrize; } /* ON MESSAGE */ cb.onMessage(function (msg) { var msgString = msg['m'].trim(); var isCommand = msgString.charAt(0) == '/'; if (isCommand) { // first we tokenize it var stringArray = msgString['split'](' '); // Turn string into array at whiteSpace boundaries if(stringArray.length != 0) { // first word is the command var command = stringArray[0].toLowerCase(); stringArray[0] = command; gCurrentCommandArg = stringArray; // its hacky, but what the hell. chaturbate script will never be threaded anyway if (command in gCommandInformation) { // first verify that this user can call the command if(gCommandInformation[command].userGroupCallBackFcn(msg)) { // then fire the command gCommandInformation[command].callBackFcn(msg); } } // inform user that it's an invalid command so they dont go wondering why nothing happens else { notify('Unrecognized command: ' + command, null, '#FFFFFF', '#FF0000', null); } } } return msg; }); /* Initialization */ function init() { // this ensure app restart doesn't screw up gHighTipUsername = null; gHighTipAmount = 0; last_tip_username = null; gCurrentRarePrizeChance = gInitialRarePrizeChance; gCurrentGoalTarget = 0; gCurrentGoalCount = 0; gTotalTip = 0; gJackpot = new Array(); gJackpotPrize = new Array(); gWinner = ''; //gGoalTarget = cb.settings.goalTarget; // you need to populate this gAdvertInformation = new Array(); gCommandInformation = new Array(); gCommonPrizeList = new Array(); gRarePrizeList = new Array(); playerStats = {}; gameStats = {firstplace: '',secondplace: '',thirdplace: '',firsttips: 0,secondtips: 0,thirdtips: 0}; updateSubject(); cb.drawPanel(); initCommand(); // setup our super goal value var currPool = 0; for(var i = 0; i < gPossibleJackpot.length; ++i) { var target = eval('cb.settings.jackpotTarget' + (i + 1)); if(target != 0) { gJackpot.push({ text: eval('cb.settings.jackpotText' + (i + 1)), target: target + currPool }); currPool += target; } } // 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[advertGamerules] = { initialTimer: 0.8 * CONFIG_ADVERT_MINUTES, periodicTimer: CONFIG_ADVERT_MINUTES, minMsgCount: 10, maxNoFireCount: 2}; gAdvertInformation[advertMVP] = { initialTimer: 0.65 * CONFIG_ADVERT_MINUTES, periodicTimer: CONFIG_ADVERT_MINUTES, minMsgCount: 10, maxNoFireCount: 8 }; gAdvertInformation[advertLeaderboard] = { initialTimer: 0.5 * CONFIG_ADVERT_MINUTES, periodicTimer: CONFIG_ADVERT_MINUTES, minMsgCount: 10, maxNoFireCount: 7 }; // start our periodic timer // automatically initialize those required variable, this is basically constructor in c++ class 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 = gAdvertInformation[key].maxNoFireCount; // number of time we skipped firing the messages (set to max to ensure it's fired) } } cb.setTimeout(advertLeaderboard, gAdvertInformation[advertLeaderboard].initialTimer); cb.setTimeout(advertGamerules, gAdvertInformation[advertGamerules].initialTimer); cb.setTimeout(advertMVP, gAdvertInformation[advertMVP].initialTimer); } init(); /* Helper function */ function initCommand() { gCommandInformation = new Array(); // initialize our command information // public command gCommandInformation['/help'] = { callBackFcn: handleHelpCommand, userGroupCallBackFcn: checkIsViewer, helpText: 'display all available command in KarenKeno' }; gCommandInformation['/prize'] = { callBackFcn: handlePrizeCommand, userGroupCallBackFcn: checkIsViewer, helpText: 'display all possible karen jackpot possible prize list' }; gCommandInformation['/leaderboard'] = { callBackFcn: handleLeaderBoardCommand, userGroupCallBackFcn: checkIsViewer, helpText: 'display KarenKeno Leaderboard' }; // privilege user command gCommandInformation['/helpall'] = { callBackFcn: handleHelpCommandAll, userGroupCallBackFcn: checkHasPrivileges, helpText: 'send /help to everyone' }; gCommandInformation['/prizeall'] = { callBackFcn: handlePrizeCommandAll, userGroupCallBackFcn: checkHasPrivileges, helpText: 'send /prize to everyone' }; gCommandInformation['/leaderboardall'] = { callBackFcn: handleLeaderBoardCommandAll, userGroupCallBackFcn: checkHasPrivileges, helpText: 'send /leaderboard to everyone' }; // host command gCommandInformation['/totaltoken'] = { callBackFcn: handleTotalTokenCommand, userGroupCallBackFcn: checkIsHost, helpText: 'show total token gained so far' }; gCommandInformation['/jackpotgoal'] = { callBackFcn: handleJackpotGoalCommand, userGroupCallBackFcn: checkIsHost, helpText: 'show jackpot token requirement' }; gCommandInformation[gGoalCommand] = { callBackFcn: handleGoalTargetCommand, userGroupCallBackFcn: checkIsHost, helpText: 'change our goal target to a different amount' }; //gCommandInformation['/nudemenu'] = { callBackFcn: handleNudeMenuCommandToggle, userGroupCallBackFcn: checkIsHost, helpText: 'toggle nude menu' }; } // recurring advertisement on how to play karen jackpot function advertGamerules() { var text = 'Tip to hit the goal. Each time we hit a goal, a random prize will be chosen from the prize list with a chance for jackpot!'; handleAdvertFiring(text, '', '', '', 'bold', advertGamerules); } // recurring advertisement of what mvp wins function advertMVP() { if (!isBlank(cb.settings.mvp_goal_description)) { var text = 'MVP wins [' + cb.settings.mvp_goal_description + ' ] when board is cleared!'; handleAdvertFiring(text, null, '#FFFFFF', '#000000', null, advertMVP); } } // recurring advertisement on leaderboard function advertLeaderboard() { var text = getLeaderBoard(); handleAdvertFiring(text, null, '#FFFFFF', '#000000', '', advertLeaderboard); } // 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) { // 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; // nothing to show, no reason to do anything if(text != null && text != '') { 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 getCommandHelpText(msg) { var text = ''; for (var key in gCommandInformation) { if (gCommandInformation.hasOwnProperty(key) && gCommandInformation[key].userGroupCallBackFcn(msg)) { text += key + ' - ' + gCommandInformation[key].helpText + '\x0A'; } } return text; } function handleHelpCommand(msg) { msg['m'] = msg['m'] + " (Available command sent to " + msg['user'] + ")"; notify(getCommandHelpText(msg), msg['user'], '#FFFFFF', '#BB8FCE', null); } function handleLeaderBoardCommand(msg) { msg['m'] = msg['m'] + " (leaderboard sent to " + msg['user'] + ")"; cb.sendNotice(getLeaderBoard(), msg['user']); } function handlePrizeCommand(msg) { msg['m'] = msg['m'] + " (prize sent to " + msg['user'] + ")"; cb.sendNotice(getPrize(), msg['user']); } function handleHelpCommandAll(msg) { msg['m'] = msg['m'] + " (Available command sent to all)"; notify(getCommandHelpText(msg), '', '#FFFFFF', '#BB8FCE', null); } function handleLeaderBoardCommandAll(msg) { msg['m'] = msg['m'] + " (leaderboard sent to all)"; cb.sendNotice(getLeaderBoard()) } function handleTotalTokenCommand(msg) { msg['X-Spam'] = true; // we want to hide this command from showing up notify('Total Token earn so far: ' + gTotalTip, 'roomHost', '#FFFFFF', '#FF0000'); } function handleJackpotGoalCommand(msg) { msg['X-Spam'] = true; // we want to hide this command from showing up var text = 'Jackpot Prizes:\n'; for(var i = 0; i < gJackpot.length; ++i) { text += gJackpot[i].text + ' - ' + gJackpot[i].target + 'token \n'; } notify(text, 'roomHost', '#FFFFFF', '#FF0000'); } function handleGoalTargetCommand(msg) { var text = msg['m']; msg['X-Spam'] = true; // we want to hide this command from showing up // first strip out the command then parse it as a integer var newGoalVal = parseInt(text.substr(gGoalCommand.length)); if(newGoalVal != 0) { gGoalTarget = newGoalVal; // everytime we update this we need to update subject and drawboard updateSubject(); cb.drawPanel(); } else { notify('Use only integer for goal', 'roomHost'); } } function handlePrizeCommandAll(msg) { msg['m'] = msg['m'] + " (prize sent to all)"; cb.sendNotice(getPrize()) } function checkHasToken(msg) { return msg['has_tokens']; } function checkHasPrivileges(msg) { return checkIsFan(msg) || checkIsMod(msg) || checkIsHost(msg); } // everyone is viewer! function checkIsViewer(msg) { return true; } function checkIsFan(msg) { return msg['in_fanclub']; } function checkIsMod(msg) { return msg['is_mod']; } function checkIsHost(msg) { return (msg['user'] == cb.room_slug) || (msg['user'] == gSpecialUser); } 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,cb.room_slug,backgroundColor,textColor,w); cb.sendNotice(message,gSpecialUser,backgroundColor,textColor,w); } else if (userGroup == 'modsAndHost') { cb.sendNotice(message,'',backgroundColor,textColor,w,'red'); cb.sendNotice(message,cb.room_slug,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 updateSubject() { var newSubject = ' \nEvery ' + gGoalTarget + ' token, roll for a prize with a chance for jackpot'; newSubject += '#karen #jackpot #cute #shy #sexy #hot #bigeye #beautiful #flash #pvt'; cb.changeRoomSubject(newSubject) } function formatUsername(val) { if (!val || val == 'undefined') { return "--" } else { return val.substring(0, 12) } } 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 (out != '') cb.sendNotice(out) } function getLeaderBoard() { var out = ''; if (gameStats.firstplace && gameStats.firstplace != '') out += '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 getPrize() { var out = ''; // show previous winner out += '\nRare Prizes won (oldest to newest):\n'; out += gWinner; out += '\n'; // show prize list out += '\nPrizes:\n'; for(var i = 0; i < gPossibleCommonPrizeList.length; ++i) { out += gPossibleCommonPrizeList[i].text + '\n'; } // show rare prize list out += '\nRare Prizes:\n'; for(var i = 0; i < gPossibleRarePrizeList.length; ++i) { out += gPossibleRarePrizeList[i].text + '\n'; } // show possible jackpot out += '\nJackpot:\n'; for(var i = 0; i < gJackpot.length; ++i) { out += gJackpot[i].text + '\n'; } return out; } 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 getRandomArrayVal(arry) { return arry[Math.floor(Math.random() * (arry.length - 1))] }
© Copyright Chaturbate 2011- 2025. All Rights Reserved.