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

Probably Easy - How do I pass multiple dice rolls to the script?

Forgive me, I'm easily stumped on scripting stuff.  I've been working on a script that handles only one dice roll and passes that to split arguments.  I'm now trying to add a damage roll to the same script and I'm not sure how you differentiate it.  Currently my script has:   let hits = 0;             let dice = [];             let cf = 0;                          // walk the inline roll structure grabbing the dice and comparing vs target, focus and expertise             (msg.inlinerolls || []).forEach(r => {                 ((r.results || {}).rolls || []).forEach(r2 => {                     (r2.results || []).forEach(r3 => {                         hits += ((r3.v || 0) <= target ? 1 : 0);                         hits += ((r3.v || 0) <= focus ? 1 : 0);                         cf += ((r3.v||0)>= (expertise === 0 ? 19: 20) ? 1 : 0);                         dice.push(r3.v || 0);                     });                 }); And that's the only use of "dice."  So let's say my chat input is: !infattack ?{Dice|2}d20 @{selected|weapon_damage_rep}d6 How do I grab the second roll and do separate things with it? Sorry, I know I should be able to find an easy answer but so far I have beefed it...
1559032511
GiGs
Pro
Sheet Author
API Scripter
That function will loop through all inline rolls, which if you have multiple rolls that work the same can be useful, or if you have a single inline roll, will work fine. If you have several rolls which do different things, or contribute to different totals you need to change the function to only iterate over a specific roll. The first line, specifically (msg.inlinerolls || []).forEach(r => { loops over every roll (the r here refers to a specific roll). A clunky way to solve your issue, if your rolls are always in the same order, would be to put an if() statement inside the workings of this section. In the first roll, r = 0, in the second roll, r = 1, and so on.             (msg.inlinerolls || []).forEach(r => {                 ((r.results || {}).rolls || []).forEach(r2 => {                     (r2.results || []).forEach(r3 => { if(r === 0) { // do the first roll here                             hits += ((r3.v || 0) <= target ? 1 : 0);                                     hits += ((r3.v || 0) <= focus ? 1 : 0);                             cf += ((r3.v||0)>= (expertise === 0 ? 19: 20) ? 1 : 0);                             dice.push(r3.v || 0); } else if(r === 1){ // whatever you want to do with the second roll here }                     });                 }); You might prefer to break them up into separate functions, one for each die roll. It'll be neater :) I'll have to come back late and suggest an approach for that when  i get time, if no one else gets to it first.
1559036394

Edited 1559036445
GiGs
Pro
Sheet Author
API Scripter
In your script, add this function before the on(chat) part: const getDice = (msg, which) => { let found = []; if(msg.inlinerolls && msg.inlinerolls.length > which) { ((msg.inlinerolls[which].results || {}).rolls || []).forEach(r => { (r.results || []).forEach(r2 => { found.push(r2.v); }); }); } return found; }; This function will return an array of dice results in the roll, so if you rolled 3d6 and got 3, 6, 1 it would be an array like this [3, 6, 1]. So then you can replace the code you posted above with let hits = 0; let cf = 0; const attackdice = getrolls(msg,0); attackdice.forEach(die => { hits += ((die || 0) <= target ? 1 : 0); hits += ((die || 0) <= focus ? 1 : 0); cf += ((die||0)>= (expertise === 0 ? 19: 20) ? 1 : 0); }); const damagedice = getrolls(msg,1); // this gets the contents of the second roll. If there isnt a secod roll, it'll be an empty array. damagedice.forEach(die => { // whatever rou want to do with damage dice }); Note that I removed the dice variable: you don't need it any more. Just replace all reference in your code from dice to attackdice. They are the same thing.
Perfect, thank you thank you.  I'm so close to having this done.   I'm noticing that as I add more complicated arguments to this script, I begin to muck things up by including attributes that may contain spaces.  I'm trying to make this a repeating macro button, so I don't know if I can call for the attributes for each weapon inside the script.  I think I have to leave those attribute calls inside the button value so the sheet appends different repeating ids to each weapon attribute, right? So if I have a button where one of the calls is @{weapon_name_rep}, and the weapon I'm calling is "Fusion Cannons," it will split the argument at "Fusion" and move on to the next thing, botching the whole script.  The "weapon qualities" section is worse, with stuff like "Spread 2, Vicious 1" in the attribute field.  Is there a technique to make the script ignore a variable amount of spaces - or to work around this in general?   Here's the macro call as of now, btw.  Note how I can grab a few attributes from the character and target ids inside the chat, but the weapon stuff I have left to the macro. !infattack [[?{Dice|2}d20]] Ballistics @{selected|character_id} @{selected|Coordination} @{selected|Ballistics_Expertise} @{selected|Ballistics_Focus} ?{Difficulty|1} @{target|Aiming for...|character_id} @{weapon_name_rep} [[(?{Modifier to Damage Dice|0}+@{weapon_damage_rep}+@{weapon_attribute_rep})d6]] @{weapon_damagebonus_rep} @{weapon_range_rep} @{weapon_qualities_rep}
1559099357
GiGs
Pro
Sheet Author
API Scripter
This is because the space is being used as a separator in your script, and that's fine in a lot of cases, but breaks when your parameters might contain spaces.  The trick here is to use a different separator in your code, that wont appear in attributes. I believe your code uses .split(/\s+/). If you change that to .split(\s+--) your separator is now  -- thats at least one space followed by two dashes. You'd have to rewrite your macros like (just add two ashes after every space) !infattack --[[?{Dice|2}d20]] --Ballistics @{selected|character_id} --@{selected|Coordination} --@{selected|Ballistics_Expertise} --@{selected|Ballistics_Focus} --?{Difficulty|1} --@{target|Aiming for...|character_id} --@{weapon_name_rep} --[[(?{Modifier to Damage Dice|0}+@{weapon_damage_rep}+@{weapon_attribute_rep})d6]] --@{weapon_damagebonus_rep} --@{weapon_range_rep} --@{weapon_qualities_rep}
Thanks for the tip, Gigs.  Not quite working yet.  .split(\s+--) yielded a syntax error, which I believe was because of the lack of backslash?  But after adding that there is no output.  No error either.  I tried logging "attackdice" and "hits," which are in argument 1, but got no return for that.  Any ideas?
1559101113

Edited 1559101178
GiGs
Pro
Sheet Author
API Scripter
sorry, i missed off the endings / / .split(/\s+--/)
Oops, I had already done that.  Turns out it was the lack of -- before the character id.  Now it works!  Finally done - see the results below.  I've used some of the forum Stylus tricks to hack at the default template.  Still some to be desired stylistically but now this is all in a quick/ easy ability button. I'd want to make this script publicly available because I think it's a big help, but it uses such a heavily customized version of the Infinity sheet that I don't know who could make use of it.   Wilhelm: Melee Attack D1 -- Hammer (Melee Range) SKILL Target 14 | Focus 3 ENEMY Grunt | Vigour 7| Dodge 5 DICE 10 9 RESULTS Hit 2 | CF 0 MOMENTUM 1 HIT Torso | Armour 2 DAMAGE 3 + 1 - 2 = 2 EFFECT 2 Non-Hackable, Unsubtle 2, Stun, Parry 1, Antimaterial 1
Wait... of course, the CSS didn't actually copy, hehe.  I'll post a screenshot in a bit.
Oof, I feel bad making multiple threads.  I have vastly different questions, but I don't want to take up too much forum space...  I'll keep going on this one for now.  Trying to add an extra bit of functionality and flair.  A new field on the sheet now contains the FX attribute, so that each weapon can have its own paired FX.  I want to have the unique weapon fx go off between attacker and target when that weapon goes through the script.  From what I understand, one must use the " spawnFxBetweenPoints(point1, point2, type, pageid)" function to do this once you go through the API?  If so, how can I substitute the target and character token ids for point1, point2?  Something where you get the left and top properties of the target and character tokens, right?  This is another situation where I can grasp the general idea, but I don't quite know how to write it. I am now feeding the script @{selected|token_id} and @{target|token_id} as arguments, by the way.
1559214288
GiGs
Pro
Sheet Author
API Scripter
This should definitely be a separate thread, it's calling on completely different techniques than used so far. there's nothing wrong with a single user creating dozens of threads, as long as they are each asking for help on a particular topic. You get more people reading new threads that are named for their problem, and will attract people who know how to answer that specific problem.