/** * This script rolls a d100 and computes and outputs the success results based * on Dark Heresy Second Edition RPG criteria. * * The following commands is used: * !roll40k [tokenName], [attributeValue], [ModifierValue] * * This script was written by Jack D on Roll20 Forums at https://app.roll20.net/forum/post/4607859/help-dark-heresy-2nd-edition-api * **/ //Rolls a d100 and calculates the success or fail results to the chat window. var Roll40k = Roll40k || (function(){ //Addition of tracking for used Psy Rating to use in flavor text and for Psy Damage roll if needed. Created by Oosh. on('ready', () => { const rxRoll = /^!roll40k\s/i; const rxLabel = /(\d+)\[mymod\]/i; on('chat:message', (msg) => { if (rxRoll.test(msg.content) && msg.inlinerolls) { let sender = msg.who.replace(/\(gm\)/i, ''); // Grab and verify data proceeding [mymod] is added. reqRoll = msg.inlinerolls.find(r => rxLabel.test(r.expression)); if (!reqRoll) return /*sendChat('modifierBot', `/w "${sender}" Something went horribly wrong in reqRoll. Please reinstall universe.`)*/; // Grab the query value and set to a variable. psyU = reqRoll.expression.match(rxLabel)[1]; if (!psyU) return /*sendChat('modifierBot', `/w "${sender}" Something went horribly wrong in psyU. Please reinstall universe.`)*/; // Grab the @{character_name} reference from the roll expression let charName = msg.content.match(/^!roll40k\s+([^,]+)/i)[1]; let char = (findObjs({type: 'character', name: charName})||[])[0] if (!char) return sendChat('modifierBot', `/w "${sender}" Something went horribly wrong. Please reinstall universe.`); let charId = char.id; // Update the attribute if it exists, or create it if it doesn't let attr = (findObjs({type: 'attribute', characterid: charId, name: 'psyuse'})||[])[0]; if (!attr) createObj('attribute', {characterid: charId, name:'psyuse', current: psyU}); else attr.set({current: psyU}); } }); var rollResultForRoll40k = function (token, attribute, modifier) { var roll = randomInteger(100); var modTarget = parseInt(attribute) + parseInt(modifier); var output2 = token + ' has a modified target of ' + modTarget + ' and rolled a ' + roll + '. '; var output3, degOfSuc; //Form output message based on result if (roll === 1) { degOfSuc = Math.floor((modTarget - roll) / 10) + 1; output3 = '' + token + ' rolled a 1 and critically succeeds with ' + degOfSuc + ' degree(s)!'; } else if (roll === 100) { degOfSuc = Math.floor((roll - modTarget) / 10) + 1; output3 = '' + token + ' rolled a 100 and critically fails with ' + degOfSuc + ' degree(s)!'; } else if (roll <= modTarget) { degOfSuc = Math.floor((modTarget - roll) / 10) + 1; output3 = '' + token + ' succeeds by ' + degOfSuc + ' degree(s).'; } else { degOfSuc = Math.floor((roll - modTarget) / 10) + 1; output3 = '' + token + ' fails by ' + degOfSuc + ' degree(s).'; } //Return output: modified to have psy and non-psy output. if (!reqRoll) { log("weapon output"); return output2 + '

' + output3; }else { log("psy output"); var output1 = 'Psy Rating: ' + psyU + ''; return output1 + '

' + output2 + '

' + output3; } }, processInlinerolls = function(msg) { if (_.has(msg, 'inlinerolls')) { return _.chain(msg.inlinerolls) .reduce(function(previous, current, index) { previous['$[[' + index + ']]'] = current.results.total || 0; return previous; },{}) .reduce(function(previous, current, index) { return previous.replace(index, current); }, msg.content) .value(); } else { return msg.content; } }; /** Interpret the chat commands. **/ on('chat:message', function (msg) { 'use strict'; var cmdName = '!roll40k '; if (msg.type === 'api' && msg.content.indexOf(cmdName) !== -1) { let content = processInlinerolls(msg); var paramArray = content.slice(cmdName.length).split(','); if (paramArray.length !== 3) { sendChat(msg.who, '/w ' + msg.who + ' You must specify three comma-separated ' + 'parameters for the !roll40k command.'); } else { log("Success!"); var result = rollResultForRoll40k(paramArray[0].trim(), paramArray[1].trim(), paramArray[2].trim()); sendChat(msg.who, result); } } }); }); }())