Advertisement
ooshbin

findResource script

Jan 30th, 2021
202
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // eslint-disable-next-line no-unused-vars
  2. const findResource = (() => {
  3.    
  4.     const r20_5e = {
  5.         repSec: [
  6.             {
  7.                 sec: 'repeating_resource',
  8.                 nameAttrs: ['resource_left_name', 'resource_right_name'], // index of Name Attributes should match index of linked Value Attributes in next Array
  9.                 valAttrs: ['resource_left', 'resource_right'],
  10.             }
  11.         ],
  12.         other:
  13.             {
  14.                 nameAttrs: ['class_resource_name', 'other_resource_name'], // index of Name Attributes should match index of linked Value Attributes in next Array
  15.                 valAttrs: ['class_resource', 'other_resource']
  16.             }
  17.     };
  18.  
  19.     const currentSheet = r20_5e;
  20.     let scriptName = 'findResourceBot';
  21.     let lastWho, selectedToken;
  22.     let silentMode, publicMode;
  23.  
  24.     const modRes = (char, attrName, attrMod, limit, silent) => {
  25.         silentMode = (silent) ? true : silentMode;
  26.         let targetAttr = findRes(char, attrName);
  27.         if (!targetAttr) return sendChat(scriptName, `/w ${lastWho} No resource named ${attrName} found on ${char.id}`);
  28.         let curVal = targetAttr.get('current');
  29.         let mod = (attrMod.match(/^\s*([+-])\s*/)) ? attrMod.match(/^\s*([+-])\s*/)[1] : null;
  30.         let newVal;
  31.         if (mod) {
  32.             curVal = parseFloat(curVal, 10);
  33.             let modVal = (attrMod.match(/\d+/)) ? parseFloat(attrMod.match(/\d+/)[0]) : null;
  34.             if (isNaN(curVal) || isNaN(modVal)) return sendChat(scriptName, `/w ${lastWho} Error: must use integers with math, check input:"${attrMod} or resource ${attrName}`);
  35.             if (mod.match(/\+/)) newVal = (curVal + modVal);
  36.             if (mod.match(/-/)) newVal = curVal - modVal;
  37.         } else newVal = attrMod;
  38.         if (limit.length) {
  39.             newVal = (isNaN(newVal)) ? parseFloat(newVal, 10) : newVal;
  40.             if (isNaN(newVal)) sendChat(`/w ${lastWho} Error: can only apply limit to numeric values.`);
  41.             else {
  42.                 let minmax = limit.map(lim => {
  43.                     if (typeof(lim) === 'string' && lim.match(/max/i)) lim = targetAttr.get('max');
  44.                     lim = (!isNaN(parseFloat(lim, 10))) ? parseFloat(lim, 10) : null;
  45.                     return lim;
  46.                 });
  47.                 if (minmax[0] || minmax[0] === 0) newVal = Math.max(minmax[0], newVal);
  48.                 if (minmax[1] || minmax[1] === 0) newVal = Math.min(minmax[1], newVal);
  49.             }
  50.         }
  51.         getObj('attribute', targetAttr.id).set('current', newVal);
  52.         silentChat(scriptName, `/w ${lastWho} ${attrName} set to ${newVal}.`);
  53.         if (publicMode) pubChat(`${char.get('name')}'s ${attrName} was set to ${newVal}.`);
  54.     }
  55.  
  56.     const findRes = (char, attrName) => {
  57.         let regexRes = new RegExp(`\\d+:\\s*${attrName}\\s*$`,'i');
  58.         let otherResNames = [];     // first try non-repeating attributes
  59.         currentSheet.other.nameAttrs.forEach((attr,i) => {
  60.             let v = findObjs({type: 'attribute', characterid: char.id, name: attr}, {caseInsensitive: true});
  61.             if (v.length > 0) {
  62.                 otherResNames.push(`${i}:${v[0].get('current')}`);
  63.             }
  64.         })
  65.         let target = otherResNames.find(a => a.match(regexRes));
  66.         if (target) {
  67.             let attrIndex = target.match(/(^\d+)/)[1];
  68.             let targetName = currentSheet.other.valAttrs[attrIndex];
  69.             let targetAttr = findObjs({type: 'attribute', characterid: char.id, name: targetName});
  70.             if (targetAttr.length) return targetAttr[0];
  71.             else log(`Couldn't find attribute "${targetName}"`);
  72.         }
  73.         let targetRep = getRepResNames(char.id, attrName); // then try rep rows
  74.         if (targetRep) {
  75.             let targetAttr = findObjs({type: 'attribute', characterid: char.id, name: targetRep});
  76.             if (targetAttr.length) return targetAttr[0];
  77.             else log(`Couldn't find repeating attribute "${targetRep}"`);
  78.         }
  79.         return null;
  80.     }
  81.  
  82.     const getRepResNames = (charId, attrName) => {
  83.         let regexRes = new RegExp(`${attrName}`,'i');
  84.         let targetAttr;
  85.         for (let i=0; i<currentSheet.repSec.length; i++) {
  86.             let secName = `${currentSheet.repSec[i].sec}_$0_${currentSheet.repSec[i].nameAttrs[0]}`;
  87.             let idArray = getRepIds(charId, secName);
  88.             let repAttrs = getRepAttrs(charId, secName, idArray, currentSheet.repSec[i].nameAttrs, true);
  89.             repAttrs.forEach(row => {
  90.                 currentSheet.repSec[i].nameAttrs.forEach((a, valIndex) => {
  91.                     if (row[a] && row[a].current) {
  92.                         //log(`Searching ${row[a].current}...`);
  93.                         if (row[a].current.match(regexRes)) {
  94.                             let rowId = row.rowId;
  95.                             let valAttr = currentSheet.repSec[i].valAttrs[valIndex];
  96.                             targetAttr = `${currentSheet.repSec[i].sec}_${rowId}_${valAttr}`;
  97.                         }
  98.                     }
  99.                 });
  100.             });
  101.         }
  102.         return targetAttr;
  103.     }
  104.  
  105.    const getRepIds = (charId, sectionName, ignoreBlanks = false) => {  
  106.        if (getObj('character', charId)) {
  107.            let repSecParts = sectionName.trim().split(/_\$\d*_/);
  108.            let regex = new RegExp(`${repSecParts[0]}_(-.*)_${repSecParts[1]}$`);
  109.            if (repSecParts.length !== 2 || repSecParts[0].search(/repeating/i) === -1) {
  110.                log(`Bad repeating section name: ${sectionName}, aborting...`);
  111.                return;
  112.            }
  113.            //log(`repeating section: ${repSecParts[0]} --- ${repSecParts[1]}`);
  114.            let idArray = [];
  115.            findObjs({type: 'attribute', characterid: charId}).filter(attr => {
  116.                if (attr.get('name').match(regex) && attr.id) {
  117.                    if (!ignoreBlanks || attr.get('current').trim() !== '') idArray.push(attr.get('name').match(regex)[1]);
  118.                    else log(`Row found, but name field blank - skipping ${charId} -- ${attr.get('name').current}`);
  119.                }
  120.            })
  121.            let reporder = findObjs({type: 'attribute', characterid: charId, name: `_reporder_${repSecParts[0]}`})[0];
  122.            if (reporder) {
  123.                reporder = reporder.get('current').trim().split(',');
  124.                idArray = [...new Set(reporder.filter((id) => idArray.includes(id)).concat(idArray))];
  125.            }
  126.             idArray.filter((attr) => attr.current != '')
  127.             //log(idArray);
  128.            return idArray;
  129.        }        
  130.    }
  131.  
  132.    const getRepAttrs = (charId, sectionName, rowIds, attrNamesArray, createMissing = false) => {
  133.        if (getObj('character', charId) && sectionName.search(/repeating.*_\$/i) !== -1) {
  134.            let sectionPrefix = sectionName.match(/(repeating.*_)\$/i)[1];
  135.            attrNamesArray = (Array.isArray(attrNamesArray)) ? attrNamesArray : [attrNamesArray];
  136.            attrNamesArray = attrNamesArray.filter((a) => (a) && a != '0')
  137.            rowIds = (Array.isArray(rowIds)) ? rowIds : [rowIds];
  138.            let attrArray = [], index = 0;
  139.            rowIds.forEach(row => {
  140.                let rowObj = {prefix: sectionPrefix, rowId: row};
  141.                    attrNamesArray.forEach(attrName => {
  142.                        if (findObjs({type:'attribute', characterid: charId, name: `${sectionPrefix}${row}_${attrName}`}).length < 1) {
  143.                            log(`Can't find attribute: ${sectionPrefix}$${index}_${attrName}`)
  144.                            if (createMissing) {
  145.                                let x = createObj('attribute', {characterid: charId, name: `${sectionPrefix}${row}_${attrName}`, current: '', max: ''});
  146.                                rowObj[attrName] = {id: x.id, current: '', max: ''}
  147.                            }
  148.                        } else {
  149.                            let currentAttr = findObjs({type:'attribute', characterid: charId, name: `${sectionPrefix}${row}_${attrName}`})[0];
  150.                            rowObj[attrName] = {id: currentAttr.get('_id'), current: currentAttr.get('current'), max: currentAttr.get('max')}
  151.                        }
  152.                    })
  153.                attrArray.push(rowObj);
  154.                index ++;
  155.             })
  156.         //log(attrArray);
  157.        return attrArray;
  158.        } else {log(`invalid charId (${charId}) or repeating section name (${sectionName}), aborting...`)}
  159.    }
  160.    
  161.     const getChar = (charRef) => {
  162.         if (charRef.match(/^(sel|selected)$/)) {
  163.             if (!selectedToken) {
  164.                 sendChat(scriptName, `/w ${lastWho} No token selected!`);
  165.                 return null;
  166.             }
  167.             let t = getObj('graphic', selectedToken._id)
  168.             let r = (t) ? t.get('represents') : null;
  169.             if (!r) {
  170.                 sendChat(scriptName, `/w ${lastWho} No linked character found for token: ${t.id}`)
  171.                 return null;
  172.             }
  173.             let char = (getObj('character', r)) ? getObj('character', r) : false;
  174.             return char;
  175.         }
  176.         let char = getObj('character', charRef);
  177.         if (char) return char;
  178.         let chars = findObjs({type:'character', name: charRef}, {caseInsensitive: true});
  179.         if (chars.length > 0) return chars[0];
  180.         return false;
  181.     }
  182.    
  183.    const handleInput = (msg) => { // !findres --char|sel --name|arrows --mod|-1 --limit|0,max
  184.        if (msg.type === "api" && msg.content.match(/^!findres/i)) {
  185.             lastWho = `"${msg.who.replace(/\s*\(gm\)\s*/i, '')}"`;
  186.             selectedToken = (msg.selected) ? msg.selected[0] : null;
  187.             let cmds = (msg.content.match(/^[^-]*(-.*)/i)) ? msg.content.match(/^[^-]*(-.*)/i)[1].split(/\s*--\s*/) : [];
  188.             if (cmds.length) cmds.shift();
  189.             let char, attrName, attrMod, limit=[], silent = false;
  190.             silentMode = (state.findResource.silentMode) ? true : false;
  191.             publicMode = (state.findResource.publicMode) ? true : false;
  192.             cmds.forEach(c => {
  193.                 let parts = c.split(/\s*\|\s*/);
  194.                 let cmd = parts[0];
  195.                 let args = (parts.length > 1) ? parts[1] : null;           
  196.                 switch(cmd) {
  197.                     case 'char':
  198.                         if (!args) return sendChat(scriptName, `/w ${lastWho} no argument supplied: ${c}`);
  199.                         char = getChar(args);
  200.                         if (char === false) return sendChat(scriptName, `/w ${lastWho} bad character ID or name.`);
  201.                         break;
  202.                     case 'name':
  203.                         if (!args) return sendChat(scriptName, `/w ${lastWho} no argument supplied: ${c}`);
  204.                         attrName = args;
  205.                         break;
  206.                     case 'mod':
  207.                         if (!args) return sendChat(scriptName, `/w ${lastWho} no argument supplied: ${c}`);
  208.                         attrMod = args;
  209.                         break;
  210.                     case 'limit':
  211.                         if (!args) return sendChat(scriptName, `/w ${lastWho} no argument supplied: ${c}`);
  212.                         limit = args.split(/\s*,\s*/);
  213.                         break;
  214.                     case 'pub':
  215.                         if (!args) publicMode = true;
  216.                         else {
  217.                             if (args.match(/(on|true)/i)) state.findResource.publicMode = true;
  218.                             else if (args.match(/(off|false)/i)) state.findResource.publicMode = false;
  219.                             else return;
  220.                             publicMode = state.findResource.publicMode;
  221.                             sendChat(scriptName, `/w ${lastWho} Public reporting is ${(state.findResource.publicMode) ? 'enabled' : 'disabled'}.`)
  222.                         }
  223.                         break;
  224.                     case 'silent':
  225.                         if (!args) silent = true;
  226.                         else {
  227.                             if (args.match(/(on|true)/i)) state.findResource.silentMode = true;
  228.                             else if (args.match(/(off|false)/i)) state.findResource.silentMode = false;
  229.                             else return;
  230.                             silentMode = state.findResource.silentMode;
  231.                             sendChat(scriptName, `/w ${lastWho} Silent mode is ${(state.findResource.silentMode) ? 'enabled' : 'disabled'}.`)
  232.                         }
  233.                         break;
  234.                     case 'sel':
  235.                         char = getChar('sel');
  236.                         if (char === false) return sendChat(scriptName, `/w ${lastWho} bad character ID or name.`);
  237.                         break;
  238.                     default:
  239.                         sendChat(scriptName, `/w ${lastWho} unrecognised command: ${c}`);
  240.                         break;
  241.                 }
  242.             });
  243.             if (char) {
  244.                 if (attrName && attrMod) {
  245.                     modRes(char, attrName, attrMod, limit, silent);
  246.                 } else if (attrName) {
  247.                     let target = findRes(char, attrName);
  248.                     if (target) {
  249.                         let curVal = (target.get('current') || target.get('current') == 0) ? target.get('current') : '<no value>';
  250.                         let maxVal = (target.get('max')) ? `/${target.get('max')}` : '';
  251.                         pubChat(`${char.get('name')}'s current ${attrName}: ${curVal}${maxVal}`);
  252.                     }
  253.                 } else sendChat(scriptName, `/w ${lastWho} Not enough arguments supplied to modify resource.`);
  254.             }
  255.        }
  256.     };
  257.  
  258.     const style = {
  259.         std: "color:darkblue; display:block; border:2px solid darkblue; background:white; padding:4px; font-size:14px; text-align:center; "
  260.     }
  261.    
  262.     const silentChat = (from, msg) => {
  263.         if (!silentMode) sendChat(from, msg);
  264.         return;
  265.     }
  266.    
  267.     const pubChat = (msg) => {
  268.         let w = (publicMode)  ? '' : `/w ${lastWho} `;
  269.         sendChat(scriptName, `${w}[${msg}](#" style="${style.std})`);
  270.     }
  271.  
  272.    const registerEventHandlers = () => {
  273.        on('chat:message', handleInput);
  274.    };
  275.  
  276.    on('ready', () => {
  277.         if (!state.findResource) state.findResource = {silentMode: false, publicMode: false};
  278.        registerEventHandlers();
  279.    });
  280.  
  281. })();
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement