Advertisement
ooshbin

Modified Concentration

Aug 14th, 2022
800
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JavaScript 23.24 KB | Source Code | 0 0
  1. /*
  2.  * Version 0.1.14
  3.  * Made By Robin Kuiper
  4.  * Skype: RobinKuiper.eu
  5.  * Discord: Atheos#1095
  6.  * My Discord Server: https://discord.gg/AcC9VME
  7.  * Roll20: https://app.roll20.net/users/1226016/robin
  8.  * Roll20 Wiki: https://wiki.roll20.net/Script:Concentration
  9.  * Roll20 Thread: https://app.roll20.net/forum/post/6364317/script-concentration/?pageforid=6364317#post-6364317
  10.  * Github: https://github.com/RobinKuiper/Roll20APIScripts
  11.  * Reddit: https://www.reddit.com/user/robinkuiper/
  12.  * Patreon: https://patreon.com/robinkuiper
  13.  * Paypal.me: https://www.paypal.me/robinkuiper
  14. */
  15.  
  16. var Concentration = Concentration || (function() {
  17.   'use strict';
  18.  
  19.   let checked = [];
  20.  
  21.   // Styling for the chat responses.
  22.   const styles = {
  23.       reset: 'padding: 0; margin: 0;',
  24.       menu:  'background-color: #fff; border: 1px solid #000; padding: 5px; border-radius: 5px;',
  25.       button: 'background-color: #000; border: 1px solid #292929; border-radius: 3px; padding: 5px; color: #fff; text-align: center;',
  26.       textButton: 'background-color: transparent; border: none; padding: 0; color: #000; text-decoration: underline',
  27.       list: 'list-style: none;',
  28.       float: {
  29.           right: 'float: right;',
  30.           left: 'float: left;'
  31.       },
  32.       overflow: 'overflow: hidden;',
  33.       fullWidth: 'width: 100%;'
  34.   },
  35.   script_name = 'Concentration',
  36.   state_name = 'CONCENTRATION',
  37.   markers = ['blue', 'brown', 'green', 'pink', 'purple', 'red', 'yellow', '-', 'all-for-one', 'angel-outfit', 'archery-target', 'arrowed', 'aura', 'back-pain', 'black-flag', 'bleeding-eye', 'bolt-shield', 'broken-heart', 'broken-shield', 'broken-skull', 'chained-heart', 'chemical-bolt', 'cobweb', 'dead', 'death-zone', 'drink-me', 'edge-crack', 'fishing-net', 'fist', 'fluffy-wing', 'flying-flag', 'frozen-orb', 'grab', 'grenade', 'half-haze', 'half-heart', 'interdiction', 'lightning-helix', 'ninja-mask', 'overdrive', 'padlock', 'pummeled', 'radioactive', 'rolling-tomb', 'screaming', 'sentry-gun', 'skull', 'sleepy', 'snail', 'spanner',   'stopwatch','strong', 'three-leaves', 'tread', 'trophy', 'white-tower'],
  38.  
  39.   handleInput = (msg) => {
  40.       if(state[state_name].config.auto_add_concentration_marker && msg && msg.rolltemplate && msg.rolltemplate === 'spell' && (msg.content.includes("{{concentration=1}}"))){
  41.           handleConcentrationSpellCast(msg);
  42.       }
  43.  
  44.       if (msg.type != 'api') return;
  45.  
  46.       // Split the message into command and argument(s)
  47.       let args = msg.content.split(' ');
  48.       let command = args.shift().substring(1);
  49.       let extracommand = args.shift();
  50.       let message;
  51.  
  52.       if (command == state[state_name].config.command) {
  53.           if(playerIsGM(msg.playerid)){
  54.               switch(extracommand){
  55.                   case 'reset':
  56.                       state[state_name] = {};
  57.                       setDefaults(true);
  58.                       sendConfigMenu(false, '<span style="color: red">The API Library needs to be restarted for this to take effect.</span>');
  59.                   break;
  60.  
  61.                   case 'config':
  62.                       if(args.length > 0){
  63.                           let setting = args.shift().split('|');
  64.                           let key = setting.shift();
  65.                           let value = (setting[0] === 'true') ? true : (setting[0] === 'false') ? false : setting[0];
  66.  
  67.                           state[state_name].config[key] = value;
  68.  
  69.                           if(key === 'bar'){
  70.                               //registerEventHandlers();
  71.                               message = '<span style="color: red">The API Library needs to be restarted for this to take effect.</span>';
  72.                           }
  73.                       }
  74.  
  75.                       sendConfigMenu(false, message);
  76.                   break;
  77.  
  78.                   case 'advantage-menu':
  79.                       sendAdvantageMenu();
  80.                   break;
  81.  
  82.                   case 'toggle-advantage': {
  83.                           let id = args[0];
  84.  
  85.                           if(state[state_name].advantages[id]){
  86.                               state[state_name].advantages[id] = !state[state_name].advantages[id];
  87.                           }else{
  88.                               state[state_name].advantages[id] = true;
  89.                           }
  90.  
  91.                           sendAdvantageMenu();
  92.                       }
  93.                   break;
  94.  
  95.                   case 'roll': {
  96.                           let represents = args[0],
  97.                               DC = parseInt(args[1], 10),
  98.                               con_save_mod = parseInt(args[2], 10),
  99.                               name = args[3],
  100.                               target = args[4];
  101.  
  102.                           roll(represents, DC, con_save_mod, name, target, false);
  103.                       }
  104.                   break;
  105.  
  106.                   case 'advantage': {
  107.                       let represents_a = args[0],
  108.                       DC_a = parseInt(args[1], 10),
  109.                       con_save_mod_a = parseInt(args[2], 10),
  110.                       name_a = args[3],
  111.                       target_a = args[4];
  112.  
  113.                       roll(represents_a, DC_a, con_save_mod_a, name_a, target_a, true);
  114.                     }
  115.                   break;
  116.  
  117.                   default:
  118.                       if(msg.selected && msg.selected.length){
  119.                           msg.selected.forEach(s => {
  120.                               let token = getObj(s._type, s._id);
  121.                               addConcentration(token, msg.playerid, extracommand);
  122.                           });
  123.                           return;
  124.                       }
  125.  
  126.                       sendConfigMenu();
  127.                   break;
  128.               }
  129.           }else{
  130.               if(msg.selected && msg.selected.length){
  131.                   msg.selected.forEach(s => {
  132.                       let token = getObj(s._type, s._id);
  133.                       addConcentration(token, msg.playerid, extracommand);
  134.                   });
  135.               }
  136.           }
  137.       }
  138.   },
  139.  
  140.   addConcentration = (token, playerid, spell) => {
  141.       const marker = state[state_name].config.statusmarker;
  142.       let character = getObj('character', token.get('represents'));
  143.       if((token.get('controlledby').split(',').includes(playerid) || token.get('controlledby').split(',').includes('all')) ||
  144.           (character && (character.get('controlledby').split(',').includes(playerid) || character.get('controlledby').split(',').includes('all'))) ||
  145.           playerIsGM(playerid)){
  146.               if(!token.get('status_'+marker)){
  147.                   let target = state[state_name].config.send_reminder_to;
  148.                   if(target === 'character'){
  149.                       target = character.get('name');
  150.                   }else if(target === 'everyone'){
  151.                       target = '';
  152.                   }
  153.  
  154.                   let message;
  155.                   if(spell){
  156.                       message = '<b>'+token.get('name')+'</b> is now concentrating on <b>'+spell+'</b>.';
  157.                   }else{
  158.                       message = '<b>'+token.get('name')+'</b> is now concentrating.';
  159.                   }
  160.  
  161.                   makeAndSendMenu(message, '', target);
  162.               }
  163.               token.set('status_'+marker, !token.get('status_'+marker));
  164.       }
  165.   },
  166.  
  167.   handleConcentrationSpellCast = (msg) => {
  168.       const marker = state[state_name].config.statusmarker;
  169.  
  170.       let character_name = msg.content.match(/charname=([^\n{}]*[^"\n{}])/);            
  171.       character_name = RegExp.$1;
  172.       let spell_name = msg.content.match(/name=([^\n{}]*[^"\n{}])/);  
  173.       spell_name = RegExp.$1;
  174.       let player = getObj('player', msg.playerid),
  175.           characterid = findObjs({ name: character_name, _type: 'character' }).shift().get('id'),                
  176.           represented_tokens = findObjs({ represents: characterid, _type: 'graphic' }),
  177.           message,
  178.           target = state[state_name].config.send_reminder_to;
  179.  
  180.       if(!character_name || !spell_name || !player || !characterid) return;
  181.  
  182.       let search_attributes = {
  183.           represents: characterid,
  184.           _type: 'graphic',
  185.           _pageid: player.get('lastpage')
  186.       };
  187.       search_attributes['status_'+marker] = true;
  188.       let is_concentrating = (findObjs(search_attributes).length > 0);
  189.  
  190.       if(is_concentrating){
  191.           message = '<b>'+character_name+'</b> is concentrating already.';
  192.       }else{
  193.           represented_tokens.forEach(token => {
  194.               let attributes = {};
  195.               attributes['status_'+marker] = true;
  196.               token.set(attributes);
  197.               message = '<b>'+character_name+'</b> is now concentrating on <b>'+spell_name+'</b>.';
  198.           });
  199.       }
  200.  
  201.       if(target === 'character'){
  202.           target = character_name;
  203.       }else if(target === 'everyone'){
  204.           target = '';
  205.       }
  206.  
  207.       makeAndSendMenu(message, '', target);
  208.   },
  209.  
  210.   handleStatusMarkerChange = (obj /*, prev */) => {
  211.       const marker = state[state_name].config.statusmarker;
  212.      
  213.       if(!obj.get('status_'+marker)){
  214.           removeMarker(obj.get('represents'));
  215.       }
  216.   },
  217.  
  218.   handleGraphicChange = (obj, prev) => {
  219.       if(checked.includes(obj.get('represents'))){ return false; }
  220.  
  221.       let bar = 'bar'+state[state_name].config.bar+'_value',
  222.           target = state[state_name].config.send_reminder_to,
  223.           marker = state[state_name].config.statusmarker;
  224.  
  225.       if(prev && obj.get('status_'+marker) && obj.get(bar) < prev[bar]){
  226.           let calc_DC = Math.floor((prev[bar] - obj.get(bar))/2),
  227.               DC = (calc_DC > 10) ? calc_DC : 10,
  228.               con_save_mod = parseInt(getAttrByName(obj.get('represents'), state[state_name].config.bonus_attribute, 'current')) || 0,
  229.               chat_text;
  230.  
  231.           if(target === 'character'){
  232.               chat_text = "Make a Concentration Check - <b>DC " + DC + "</b>.";
  233.               target = obj.get('name');
  234.           }else if(target === 'everyone'){
  235.               chat_text = '<b>'+obj.get('name')+'</b> must make a Concentration Check - <b>DC ' + DC + '</b>.';
  236.               target = '';
  237.           }else{
  238.               chat_text = '<b>'+obj.get('name')+'</b> must make a Concentration Check - <b>DC ' + DC + '</b>.';
  239.               target = 'gm';
  240.           }
  241.  
  242.           if(state[state_name].config.show_roll_button){
  243.               chat_text += '<hr>' + makeButton('Advantage', '!' + state[state_name].config.command + ' advantage ' + obj.get('represents') + ' ' + DC + ' ' + con_save_mod + ' ' + obj.get('name') + ' ' + target, styles.button + styles.float.right);
  244.               chat_text += '&nbsp;' + makeButton('Roll', '!' + state[state_name].config.command + ' roll ' + obj.get('represents') + ' ' + DC + ' ' + con_save_mod + ' ' + obj.get('name') + ' ' + target, styles.button + styles.float.left);
  245.           }
  246.  
  247.           if(state[state_name].config.auto_roll_save){
  248.               //&{template:default} {{name='+obj.get('name')+' - Concentration Save}} {{Modifier='+con_save_mod+'}} {{Roll=[[1d20cf<'+(DC-con_save_mod-1)+'cs>'+(DC-con_save_mod-1)+'+'+con_save_mod+']]}} {{DC='+DC+'}}
  249.               roll(obj.get('represents'), DC, con_save_mod, obj.get('name'), target, state[state_name].advantages[obj.get('represents')]);
  250.           }else{
  251.               makeAndSendMenu(chat_text, '', target);
  252.           }
  253.  
  254.           let length = checked.push(obj.get('represents'));
  255.           setTimeout(() => {
  256.               checked.splice(length-1, 1);
  257.           }, 1000);
  258.       }
  259.   },
  260.  
  261.   roll = (represents, DC, con_save_mod, name, target, advantage) => {
  262.       sendChat(script_name, '[[1d20cf<'+(DC-con_save_mod-1)+'cs>'+(DC-con_save_mod-1)+'+'+con_save_mod+']]', results => {
  263.           let title = 'Concentration Save <br> <b style="font-size: 10pt; color: gray;">'+name+'</b>',
  264.               advantageRollResult;
  265.  
  266.           let rollresult = results[0].inlinerolls[0].results.rolls[0].results[0].v;
  267.           let result = rollresult;
  268.  
  269.           if(advantage){
  270.               advantageRollResult = randomInteger(20);
  271.               result = (rollresult <= advantageRollResult) ? advantageRollResult : rollresult;
  272.           }
  273.  
  274.           let total = result + con_save_mod;
  275.  
  276.           let success = total >= DC;
  277.  
  278.           let result_text = (success) ? 'Success' : 'Failed',
  279.               result_color = (success) ? 'green' : 'red';
  280.  
  281.           let rollResultString = (advantage) ? rollresult + ' / ' + advantageRollResult : rollresult;
  282.  
  283.           let contents = ' \
  284.          <table style="width: 100%; text-align: left;"> \
  285.              <tr> \
  286.                  <th>DC</th> \
  287.                  <td>'+DC+'</td> \
  288.              </tr> \
  289.              <tr> \
  290.                  <th>Modifier</th> \
  291.                  <td>'+con_save_mod+'</td> \
  292.              </tr> \
  293.              <tr> \
  294.                  <th>Roll Result</th> \
  295.                  <td>'+rollResultString+'</td> \
  296.              </tr> \
  297.          </table> \
  298.          <div style="text-align: center"> \
  299.              <b style="font-size: 16pt;"> \
  300.                  <span style="border: 1px solid '+result_color+'; padding-bottom: 2px; padding-top: 4px;">[['+result+'+'+con_save_mod+']]</span><br><br> \
  301.                  '+result_text+' \
  302.              </b> \
  303.          </div>';
  304.           makeAndSendMenu(contents, title, target);
  305.  
  306.           if(target !== '' && target !== 'gm'){
  307.               makeAndSendMenu(contents, title, 'gm');
  308.           }
  309.  
  310.           if(!success){
  311.               removeMarker(represents);
  312.           }
  313.       });
  314.   },
  315.  
  316.   removeMarker = (represents, type='graphic') => {
  317.       findObjs({ type, represents }).forEach(o => {
  318.           o.set('status_'+state[state_name].config.statusmarker, false);
  319.       });
  320.   },
  321.  
  322.   ucFirst = (string) => {
  323.       return string.charAt(0).toUpperCase() + string.slice(1);
  324.   },
  325.  
  326.   sendConfigMenu = (first, message) => {
  327.       let markerDropdown = '?{Marker';
  328.       markers.forEach((marker) => {
  329.           markerDropdown += '|'+ucFirst(marker).replace('-', ' ')+','+marker;
  330.       });
  331.       markerDropdown += '}';
  332.  
  333.       let markerButton = makeButton(state[state_name].config.statusmarker, '!' + state[state_name].config.command + ' config statusmarker|'+markerDropdown, styles.button + styles.float.right),
  334.           commandButton = makeButton('!'+state[state_name].config.command, '!' + state[state_name].config.command + ' config command|?{Command (without !)}', styles.button + styles.float.right),
  335.           barButton = makeButton('bar ' + state[state_name].config.bar, '!' + state[state_name].config.command + ' config bar|?{Bar|Bar 1 (green),1|Bar 2 (blue),2|Bar 3 (red),3}', styles.button + styles.float.right),
  336.           sendToButton = makeButton(state[state_name].config.send_reminder_to, '!' + state[state_name].config.command + ' config send_reminder_to|?{Send To|Everyone,everyone|Character,character|GM,gm}', styles.button + styles.float.right),
  337.           addConMarkerButton = makeButton(state[state_name].config.auto_add_concentration_marker, '!' + state[state_name].config.command + ' config auto_add_concentration_marker|'+!state[state_name].config.auto_add_concentration_marker, styles.button + styles.float.right),
  338.           autoRollButton = makeButton(state[state_name].config.auto_roll_save, '!' + state[state_name].config.command + ' config auto_roll_save|'+!state[state_name].config.auto_roll_save, styles.button + styles.float.right),
  339.           //advantageButton = makeButton(state[state_name].config.advantage, '!' + state[state_name].config.command + ' config advantage|'+!state[state_name].config.advantage, styles.button + styles.float.right),
  340.           bonusAttrButton = makeButton(state[state_name].config.bonus_attribute, '!' + state[state_name].config.command + ' config bonus_attribute|?{Attribute|'+state[state_name].config.bonus_attribute+'}', styles.button + styles.float.right),
  341.           showRollButtonButton = makeButton(state[state_name].config.show_roll_button, '!' + state[state_name].config.command + ' config show_roll_button|'+!state[state_name].config.show_roll_button, styles.button + styles.float.right),
  342.  
  343.           listItems = [
  344.               '<span style="'+styles.float.left+'">Command:</span> ' + commandButton,
  345.               '<span style="'+styles.float.left+'">Statusmarker:</span> ' + markerButton,
  346.               '<span style="'+styles.float.left+'">HP Bar:</span> ' + barButton,
  347.               '<span style="'+styles.float.left+'">Send Reminder To:</span> ' + sendToButton,
  348.               '<span style="'+styles.float.left+'">Auto Add Con. Marker: <p style="font-size: 8pt;">Works only for 5e OGL Sheet.</p></span> ' + addConMarkerButton,
  349.               '<span style="'+styles.float.left+'">Auto Roll Save:</span> ' + autoRollButton
  350.           ],
  351.  
  352.           resetButton = makeButton('Reset', '!' + state[state_name].config.command + ' reset', styles.button + styles.fullWidth),
  353.  
  354.           title_text = (first) ? script_name + ' First Time Setup' : script_name + ' Config';
  355.  
  356.       /*if(state[state_name].config.auto_roll_save){
  357.           listItems.push('<span style="'+styles.float.left+'">Advantage:</span> ' + advantageButton);
  358.       }*/
  359.  
  360.       if(state[state_name].config.auto_roll_save){
  361.           listItems.push('<span style="'+styles.float.left+'">Bonus Attribute:</span> ' + bonusAttrButton);
  362.       }
  363.  
  364.       if(!state[state_name].config.auto_roll_save){
  365.           listItems.push('<span style="'+styles.float.left+'">Roll Button:</span> ' + showRollButtonButton);
  366.       }
  367.  
  368.       let advantageMenuButton = (state[state_name].config.auto_roll_save) ? makeButton('Advantage Menu', '!' + state[state_name].config.command + ' advantage-menu', styles.button + styles.fullWidth) : '';
  369.  
  370.       message = (message) ? '<p>'+message+'</p>' : '';
  371.       let contents = message+makeList(listItems, styles.reset + styles.list + styles.overflow, styles.overflow)+'<br>'+advantageMenuButton+'<hr><p style="font-size: 80%">You can always come back to this config by typing `!'+state[state_name].config.command+' config`.</p><hr>'+resetButton;
  372.       makeAndSendMenu(contents, title_text, 'gm');
  373.   },
  374.  
  375.   sendAdvantageMenu = () => {
  376.       let menu_text = "";
  377.       let characters = findObjs({ type: 'character' }).sort((a, b) => {
  378.           let nameA = a.get('name').toUpperCase();
  379.           let nameB = b.get('name').toUpperCase();
  380.  
  381.           if(nameA < nameB) return -1;
  382.           if(nameA > nameB) return 1;
  383.  
  384.           return 0;
  385.       });
  386.  
  387.       characters.forEach(character => {
  388.           let name = (state[state_name].advantages && state[state_name].advantages[character.get('id')]) ? '<b>'+character.get('name')+'</b>' : character.get('name');
  389.           menu_text += makeButton(name, '!' + state[state_name].config.command + ' toggle-advantage ' + character.get('id'), styles.textButton) + '<br>';
  390.       });
  391.  
  392.       makeAndSendMenu(menu_text, 'Advantage Menu', 'gm');
  393.   },
  394.  
  395.   makeAndSendMenu = (contents, title, whisper /*, callback */) => {
  396.       title = (title && title != '') ? makeTitle(title) : '';
  397.       whisper = (whisper && whisper !== '') ? `/w "${whisper}" ` : '';
  398.       sendChat(script_name, whisper + '<div style="'+styles.menu+styles.overflow+'">'+title+contents+'</div>', null, {noarchive:true});
  399.   },
  400.  
  401.   makeTitle = (title) => {
  402.       return '<h3 style="margin-bottom: 10px;">'+title+'</h3>';
  403.   },
  404.  
  405.   makeButton = (title, href, style) => {
  406.       return '<a style="'+style+'" href="'+href+'">'+title+'</a>';
  407.   },
  408.  
  409.   makeList = (items, listStyle, itemStyle) => {
  410.       let list = '<ul style="'+listStyle+'">';
  411.       items.forEach((item) => {
  412.           list += '<li style="'+itemStyle+'">'+item+'</li>';
  413.       });
  414.       list += '</ul>';
  415.       return list;
  416.   },
  417.  
  418. /*
  419.   pre_log = (message) => {
  420.       log('---------------------------------------------------------------------------------------------');
  421.       if(!message){ return; }
  422.       log(message);
  423.       log('---------------------------------------------------------------------------------------------');
  424.   },
  425.   */
  426.  
  427.   checkInstall = () => {
  428.       if(!_.has(state, state_name)){
  429.           state[state_name] = state[state_name] || {};
  430.       }
  431.       setDefaults();
  432.  
  433.       log(script_name + ' Ready! Command: !'+state[state_name].config.command);
  434.       if(state[state_name].config.debug){ makeAndSendMenu(script_name + ' Ready! Debug On.', '', 'gm'); }
  435.   },
  436.  
  437.   registerEventHandlers = () => {
  438.       on('chat:message', handleInput);
  439.       on('change:graphic:bar'+state[state_name].config.bar+'_value', handleGraphicChange);
  440.       on('change:graphic:statusmarkers', handleStatusMarkerChange);
  441.       setTimeout(() => {
  442.         if (typeof(TokenMod) === 'object') TokenMod.ObserveTokenChange(handleGraphicChange);
  443.       }, 500);
  444.   },
  445.  
  446.   setDefaults = (reset) => {
  447.       const defaults = {
  448.           config: {
  449.               command: 'concentration',
  450.               statusmarker: 'stopwatch',
  451.               bar: 1,
  452.               send_reminder_to: 'everyone', // character,gm,
  453.               auto_add_concentration_marker: true,
  454.               auto_roll_save: true,
  455.               advantage: false,
  456.               bonus_attribute: 'constitution_save_bonus',
  457.               show_roll_button: true
  458.           },
  459.           advantages: {}
  460.       };
  461.  
  462.       if(!state[state_name].config){
  463.           state[state_name].config = defaults.config;
  464.       }else{
  465.           if(!state[state_name].config.hasOwnProperty('command')){
  466.               state[state_name].config.command = defaults.config.command;
  467.           }
  468.           if(!state[state_name].config.hasOwnProperty('statusmarker')){
  469.               state[state_name].config.statusmarker = defaults.config.statusmarker;
  470.           }
  471.           if(!state[state_name].config.hasOwnProperty('bar')){
  472.               state[state_name].config.bar = defaults.config.bar;
  473.           }
  474.           if(!state[state_name].config.hasOwnProperty('send_reminder_to')){
  475.               state[state_name].config.send_reminder_to = defaults.config.send_reminder_to;
  476.           }
  477.           if(!state[state_name].config.hasOwnProperty('auto_add_concentration_marker')){
  478.               state[state_name].config.auto_add_concentration_marker = defaults.config.auto_add_concentration_marker;
  479.           }
  480.           if(!state[state_name].config.hasOwnProperty('auto_roll_save')){
  481.               state[state_name].config.auto_roll_save = defaults.config.auto_roll_save;
  482.           }
  483.           if(!state[state_name].config.hasOwnProperty('advantage')){
  484.               state[state_name].config.advantage = defaults.config.advantage;
  485.           }
  486.           if(!state[state_name].config.hasOwnProperty('bonus_attribute')){
  487.               state[state_name].config.bonus_attribute = defaults.config.bonus_attribute;
  488.           }
  489.           if(!state[state_name].config.hasOwnProperty('show_roll_button')){
  490.               state[state_name].config.show_roll_button = defaults.config.show_roll_button;
  491.           }
  492.       }
  493.       if(!state[state_name].advantages){
  494.           state[state_name].advantages = defaults.advantages;
  495.       }
  496.  
  497.       if(!state[state_name].config.hasOwnProperty('firsttime') && !reset){
  498.           sendConfigMenu(true);
  499.           state[state_name].config.firsttime = false;
  500.       }
  501.   };
  502.  
  503.   return {
  504.       CheckInstall: checkInstall,
  505.       RegisterEventHandlers: registerEventHandlers
  506.   };
  507. })();
  508.  
  509. on('ready',function() {
  510.   'use strict';
  511.  
  512.   Concentration.CheckInstall();
  513.   Concentration.RegisterEventHandlers();
  514. });
  515.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement