Roll20 uses cookies to improve your experience on our site. Cookies enable you to enjoy certain features, social sharing functionality, and tailor message and display ads to your interests on our site and others. They also help us understand how our site is being used. By continuing to use our site, you consent to our use of cookies. Update your cookie preferences .
×
Create a free account

Adding the function of Process inLineRolls to an already built API with Results adjustments

So, the API was built and rejiggered a few times.  It is below.  The API is set up to allow for an action to be rolled based on a specific difficulty column.  The macro allows the player to choose the column and the action.  The API will roll 1d100 and pair the resulting number with the correct column and action.  Then, it gives the results based on that information.  If you roll on the CS0 table and score a 1, it will say Fumble.  If you roll on the CS9 table and score a 100, it will say Enhanced Success. I would like to be able to have a player input a value to be added to the d100 roll that can affect the results.  So, If you roll on the CS0 table and score a 49, it would result in a Fail.  However, if you did this with a +1, it would become a 50 and result in a Partial Success.  Is there a way to add a modifier option to this API and the macro for it? Fantasy API const CSF = (() => { const version = '0.1.0'; const successText = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; //not used let CS9 = [2, 05, 30, 55]; let CS8 = [2, 10, 35, 60]; let CS7 = [2, 15, 40, 65]; let CS6 = [2, 20, 45, 70]; let CS5 = [2, 25, 50, 75]; let CS4 = [2, 30, 55, 80]; let CS3 = [2, 35, 60, 85]; let CS2 = [2, 40, 65, 90]; let CS1 = [2, 45, 70, 95]; let CS0 = [2, 50, 75, 98]; let CS_1 = [5, 55, 80, 100]; let CS_2 = [5, 60, 85, 100]; let CS_3 = [5, 65, 90, 100]; let CS_4 = [10, 70, 95, 100]; let CS_5 = [10, 75, 98, 100]; let CS_6 = [10, 80, 98, 100]; let CS_7 = [15, 85, 98, 100]; let CS_8 = [15, 90, 98, 100]; let CS_9 = [20, 95, 98, 100]; let featRoll = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let might = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let mightClimbing = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let mightStrength = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let mightLeaping = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let mightStamina = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let mightSwimming = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let mightThrowing = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let prowess = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let prowessBrawling = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let prowessHafted = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let prowessHilted = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let prowessPolearm = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let prowessMartialarts = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let prowessShields = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let agility = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let agilityAcrobatics = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let agilityDance = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let agilityLegerdemain = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let agilityPilot = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let agilityRangedcombat = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let agilityShadow = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let insight = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let insightKnowledge = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let insightLanguage = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let insightMedicine = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let insightScience = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let insightStreetwise = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let insightSurvival = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let savvy = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let savvyDisguise = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let savvyGambling = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let savvyObservation = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let savvyRiding = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let savvyStealth = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let savvyTracking = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let discipline = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let disciplineAnimalhandling = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let disciplineArtisticexpression = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let disciplineCraft = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let disciplineFocus = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let disciplinePersuasion = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; let disciplineWillpower = ["Fumble", "Fail", "Partial Success", "Success", "Enhanced Success"]; const checkInstall = () => { log('-=> CSF v'+version); }; //sendChat output formatting styles const _h = { fumble: (...o) => `<span style="font-weight: bold;padding: .2em .2em; background-color:rgba(89,89,89,1);">${o.join('')}</span>`, fail: (...o) => `<span style="font-weight: bold;padding: .2em .2em; background-color:rgba(255,255,255,1);">${o.join('')}</span>`, partial: (...o) => `<span style="font-weight: bold;padding: .2em .2em; background-color:rgba(205,127,50,1);">${o.join('')}</span>`, success: (...o) => `<span style="font-weight: bold;padding: .2em .2em; background-color:rgba(161,157,148,1);">${o.join('')}</span>`, enhanced: (...o) => `<span style="font-weight: bold;padding: .2em .2em; background-color:rgba(113,121,126,1);">${o.join('')}</span>` }; const formattedResult = function (successLevel, text) { switch(successLevel){ case 0: return _h.fumble(text); break; case 1: return _h.fail(text); break; case 2: return _h.partial(text); break; case 3: return _h.success(text); break; case 4: return _h.enhanced(text); break; } } const getSuccessLevel = function (tableArr, roll) { if (roll>=tableArr[3]) {return 4} //"Enhanced Success" if (roll>=tableArr[2] && roll<tableArr[3]) {return 3} //"Success" if (roll>=tableArr[1] && roll<tableArr[2]) {return 2} //"Partial Success" if (roll>=tableArr[0] && roll<tableArr[1]) {return 1} //"Fail" if (roll<tableArr[0]) {return 0} //"Fumble" }; const processInlinerolls = (msg) => { if(msg.hasOwnProperty('inlinerolls')){ return msg.inlinerolls .reduce((m,v,k) => { let ti=v.results.rolls.reduce((m2,v2) => { if(v2.hasOwnProperty('table')){ m2.push(v2.results.reduce((m3,v3) => [...m3,(v3.tableItem||{}).name],[]).join(", ")); } return m2; },[]).join(', '); return [...m,{k:`$[[${k}]]`, v:(ti.length && ti) || v.results.total || 0}]; },[]) .reduce((m,o) => m.replace(o.k,o.v), msg.content); } else { return msg.content; } }; const handleInput = (msg) => { const scriptName = 'CSF'; let roll = 0; let tableName; let tableArr; let actionArr; let action = ""; let successLevel; let result; if(msg.type=="api" && msg.content.indexOf("!CSF") === 0 ) { try { who = getObj('player',msg.playerid).get('_displayname'); let args = msg.content.split(/\s+/); if (args[1]>=0) { tableName = 'CS' + parseInt(args[1]); } else { tableName = 'CS_' + -1*parseInt(args[1]); } //Get Success Level Array switch(tableName){ case "CS9": tableArr = CS9; break; case "CS8": tableArr = CS8; break; case "CS7": tableArr = CS7; break; case "CS6": tableArr = CS6; break; case "CS5": tableArr = CS5; break; case "CS4": tableArr = CS4; break; case "CS3": tableArr = CS3; break; case "CS2": tableArr = CS2; break; case "CS1": tableArr = CS1; break; case "CS0": tableArr = CS0; break; case "CS_1": tableArr = CS_1; break; case "CS_2": tableArr = CS_2; break; case "CS_3": tableArr = CS_3; break; case "CS_4": tableArr = CS_4; break; case "CS_5": tableArr = CS_5; break; case "CS_6": tableArr = CS_6; break; case "CS_7": tableArr = CS_7; break; case "CS_8": tableArr = CS_8; break; case "CS_9": tableArr = CS_9; break; } //Get Action Array action = args[2]; switch(args[2]){ case "FeatRoll": actionArr = featRoll; break; case "Might": actionArr = might; break; case "MightClimbing": actionArr = mightClimbing; break; case "MightFeatofStrength": actionArr = mightStrength; break; case "MightLeaping": actionArr = mightLeaping; break; case "MightStamina": actionArr = mightStamina; break; case "MightSwimming": actionArr = mightSwimming; break; case "MightThrowing": actionArr = mightThrowing; break; case "Prowess": actionArr = prowess; break; case "ProwessBrawling": actionArr = prowessBrawling; break; case "ProwessArmedCombatHafted": actionArr = prowessHafted; break; case "ProwessArmedCombatHilted": actionArr = prowessHilted; break; case "ProwessArmedCombatPolearm": actionArr = prowessPolearm; break; case "ProwessMartialArts": actionArr = prowessMartialarts; break; case "ProwessShields": actionArr = prowessShields; break; case "Agility": actionArr = agility; break; case "AgilityAcrobatics": actionArr = agilityAcrobatics; break; case "AgilityDance": actionArr = agilityDance; break; case "AgilityLegerdemain": actionArr = agilityLegerdemain; break; case "AgilityPilot": actionArr = agilityPilot; break; case "AgilityRangedCombat": actionArr = agilityRangedcombat; break; case "AgilityShadow": actionArr = agilityShadow; break; case "Insight": actionArr = insight; break; case "InsightKnowledge": actionArr = insightKnowledge; break; case "InsightLanguage": actionArr = insightLanguage; break; case "InsightMedicine": actionArr = insightMedicine; break; case "InsightScience": actionArr = insightScience; break; case "InsightStreetwise": actionArr = insightStreetwise; break; case "InsightSurvival": actionArr = insightSurvival; break; case "Savvy": actionArr = savvy; break; case "SavvyDisguise": actionArr = savvyDisguise; break; case "SavvyGambling": actionArr = savvyGambling; break; case "SavvyObservation": actionArr = savvyObservation; break; case "SavvyRiding": actionArr = savvyRiding; break; case "SavvyStealth": actionArr = savvyStealth; break; case "SavvyTracking": actionArr = savvyTracking; break; case "Discipline": actionArr = discipline; break; case "DisciplineAnimalHandling": actionArr = disciplineAnimalhandling; break; case "DisciplineArtisticExpression": actionArr = disciplineArtisticexpression; break; case "DisciplineCraft": actionArr = disciplineCraft; break; case "DisciplineFocus": actionArr = disciplineFocus; break; case "DisciplinePersuasion": actionArr = disciplinePersuasion; break; case "DisciplineWillpower": actionArr = disciplineWillpower; break; default: sendChat(scriptName,`/w "${who}" `+ 'Error: Action \"' + action + '\" not found.'); break } tableName = tableName.replace("_", "-"); roll = randomInteger(100); successLevel = getSuccessLevel(tableArr, roll); result = actionArr[successLevel]; //let output = '&{template:default} {{name=' + tableName + '}} {{Roll=[[' + roll + ']]}} {{SuccessLevel=' + _h.inlineResult(result) + '}}'; let output = '&{template:default} {{name=' + action + ' ' + tableName + '}} {{Roll=[[' + roll + ']]}} {{Result=' + formattedResult(successLevel, result) + '}}'; sendChat(scriptName, output); } catch(err) { sendChat(scriptName,`/w "${who}" `+ 'Error: ' + err.message); } }; }; const registerEventHandlers = () => { on('chat:message', handleInput); }; on('ready', () => { checkInstall(); registerEventHandlers(); }); })();
Here is an example of one of the current macros: !CSF ?{select CS|9|8|7|6|5|4|3|2|1|0|-1|-2|-3|-4|-5|-6|-7|-8|-9} ?{select Skill|Agility,Agility|Acrobatics,AgilityAcrobatics|Dance,AgilityDance|Legerdemain,AgilityLegerdemain|Pilot,AgilityPilot|Ranged Combat,AgilityRangedCombat|Shadow,AgilityShadow} @{selected|character_name}
1679076487

Edited 1679131367
timmaugh
Pro
API Scripter
Hey, Eggo... You've already got the processInlineRolls function in there, so you'd just want to run it prior to or as you are determining your args array. That function takes the entire msg object, but returns only the content (command line), so implementing it would look like: let args = processInlineRolls(msg).split(/\s+/); Then you could allow a third argument on your command line, and reference it as args[3]. A note: I'd really, really suggest implementing a more robust line parse so that your arguments could come in any order. That's discussed here and here . For now, I'll just continue on with the setup you currently have. With the modifier expected in the third argument, it could either be a number or an inline roll. However, by the time you examine the arg[3] item, it will have been rendered from an inline roll to the value. All that's left is to validate it's a number, default it to 0 if not supplied or not a number, and add it to your roll before looking up the result in the tables. You seem to know your way around js coding, so I won't give the specific syntax of those, but post back if you need more help.
The issue is that I didn't write it.  Much like a lot of people, I only feel comfortable changing certain variables that are easy to find and super obvious.  The benefits of MySpace.  That said, I keep breaking this everytime I try to change something that is not one of the two inputs or the colors of the outputs.  You and I have been down this road, in another post.  You literally had to hold my hand.  lol
1679083035

Edited 1679131404
timmaugh
Pro
API Scripter
Fair enough. So, the least invasive modification would be to leave the line parsing as is, then, and make the change to the args declaration statement as I showed in my previous post. Then, right before the line that currently reads roll = randomInteger(100); Add a line that says: let mod = parseInt(arg[3]) || 0; Then change the roll line to be: roll = randomInteger(100) + mod; That should do it.
1679110528

Edited 1679111066
timmaugh said: Fair enough. So, the least invasive modification would be to leave the line parsing as is, then, and make the change to the args declaration statement as I showed in my previous post. Then, right before the line that currently reads roll = randomInteger(100); Add a line that says: let mod = parseInt(arg[2]) || 0; Then change the roll line to be: roll = randomInteger(100) + mod; That should do it. I can follow this, but, as I am looking for the place to put in the info from the previous post, I see that I already have an args[2] in the original api.  So, I am not sure whether this would be [3] or still the same.  I can't even find the command line.  lol //Get Action Array action = args[2]; switch(args[2]){ case "FeatRoll":
1679131318
timmaugh
Pro
API Scripter
Yes, sorry. args[3]... I forgot your code hadn't dropped the script handle from the set of arguments, so it would occupy position 0, and bump everything out 1 position. I'll go correct my previous post.
1679147778

Edited 1679148161
timmaugh said: Yes, sorry. args[3]... I forgot your code hadn't dropped the script handle from the set of arguments, so it would occupy position 0, and bump everything out 1 position. I'll go correct my previous post. To confirm.  I modified this section per your first post: if(msg.type=="api" && msg.content.indexOf("!CSF") === 0 ) { try { who = getObj('player',msg.playerid).get('_displayname'); let args = processInlineRolls(msg).split(/\s+/); if (args[1]>=0) { tableName = 'CS' + parseInt(args[1]); } else { tableName = 'CS_' + -1*parseInt(args[1]); } And this section per your second post: let mod = parseInt(arg[3]) || 0; roll = randomInteger(100) + mod; successLevel = getSuccessLevel(tableArr, roll); result = actionArr[successLevel]; However, I am getting this error: Error: processInlineRolls is not defined
1679156531
timmaugh
Pro
API Scripter
Ah... because the way the processInlineRolls() function is defined, it has a lower case 'r'... it's actually processInlinerolls(). Change one or the other to make them match, then that error will go away.
timmaugh said: Ah... because the way the processInlineRolls() function is defined, it has a lower case 'r'... it's actually processInlinerolls(). Change one or the other to make them match, then that error will go away. I ran into another error, but managed to sort it out.  I had arg instead of args for the results area.  So, I managed to get that to working, with your guidance.  Thank you kindly, for all of your help and patience.  I know I will likely be back, with more questions and need for help, but I think this is a solid win, for the weekend.
1679174540
timmaugh
Pro
API Scripter
Excellent. Or should I say... Eggocellent.........? No? No, I shouldn't? Ok.