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

Getting a variable from a list based on a stat amount

Would it be possible to make a list of a stat in the roll20 html that corresponds to a dice amount, and that it gets picked up in the attack roll?  I.e: Skill stat, character has 5 skill, so they'd roll 1d6 to see if they crit.  At the end of the htmlcode, a short list like:  1 skill = null 3 skill = 1d4 5 skill = 1d6 7 skill = 1d4 + 1d6 etc and thus the attack roll would check character skill amount and then pick the dice amount from that?  If not possible, that's fine, but just wondering if there is a way to make this work. 
1671156688

Edited 1671156726
GiGs
Pro
Sheet Author
API Scripter
Yes, this is easy. You just need an array like const dice = ['0', '0', '1d4', '1d6', '1d4+1d6' ] I've started this with 0 twice, because arrays start at 0, not 1 (going, 0, 1, 2, 3, etc) so this is the easiest way to cope - add in 0 value that is never used. I've set the 1 value to '0' instead of null, because I assume you'll use these values in dice rolls, and having a 0 means it won't break. This would need to be put in a sheet worker. The code for that would depend on more details of how its going to be used. My guess is you'd have a hidden attribute which changes whenever the stat value changes, putting that dice value. Then your attack roll button would have a reference to the hidden value, like "/roll @{hidden-value}" More details of your html would be needed to answer more clearly, but maybe this is enough for you.
Oh thankyou!  Yeah, so if i understand correctly i can make the roll something like /@{crit_bonus} + {crit_base} after i've mad an array.  Yeah, the value of 1 would be 0!  The idea is that the players have a stat called skill, that they can freely edit when they level up, and then there'd be a table that shows how much crit you have based on skill. So it's not a really hidden value?  Crit is also a value they can fill in manually, but i'd rather save time during sessions and make it an automatic button It's just the following code for now regarding to skill and crit.  <h6>Skill</h6> <input type="number" placeholder= "2" name="attr_skill" title="@{skill}"> <h6>Crit</h6> <input type="text" placeholder= "2" name="attr_crit" title="@{crit}"> <button type="roll" name="roll_Crit" value="/roll @{crit}" > Crit </button> So ideally i'd make it something like this?   /@{crit_bonus} + {crit_base} With a normal action button that can get the values from the array? <script type="text/worker"> on("clicked:crit", function(){ getAttrs(["crit","crit_bonus1"], function(values) { //weapons can have crit bonusses, and characters can swap between3/4 weapons startRoll("&{template:custom} {{title=@{equipment1}}} {{Crit Total =[[@{crit_bonus1}+@{crit}]]}}",(results) => { finishRoll(results.rollId); }); }); }); And then add a crit array somewhere to do the following? const dice = ['0', '0', '1d4', '1d6', '2d4', '1d4 +1d6', '2d6' ] //etc const iterator = attr.skill(); Would it be possible to make it so that every odd number of skill would grab the next dice from this? So 1/3/5/7 etc.  Sorry for all the questions, but am unable to find this on the wiki myself.
1671334447

Edited 1671334505
GiGs
Pro
Sheet Author
API Scripter
No need to apologise for asking lots of questions. When I answer, I try to find out what the person really wants, and so I usually ask a lot of questions too. This post for example :) Are skill and crit universal stats - that is, for a single character, those are are always the same? They dont vary with attacks (like one attack has one crit score, and another attack has another crit score) but remain constant accoss all attacks? Liliana said: And then add a crit array somewhere to do the following? const dice = ['0', '0', '1d4', '1d6', '2d4', '1d4 +1d6', '2d6' ] //etc const iterator = attr.skill(); Would it be possible to make it so that every odd number of skill would grab the next dice from this? So 1/3/5/7 etc. Yes, this is easy. You can do it two ways. The first does the method I suggested: const skill = +attr.skill || 0; const iterator = Math.ceil(skill /2); Math.ceil rounds up, so you 1-2 = 1, 3-4 = 2, 5-6 = 3, etc. Since the even numbers don't matter, you get what you want. Alternatively if there are no even numbers, you can round down, using Math.floor. const dice = ['0', '1d4', '1d6', '2d4', '1d4 +1d6', '2d6' ] //etc const skill = +attr.skill || 0; const iterator = Math.floor(skill /2); With this version 0-1 = 0, 2-3 = 2, 4-5 = 3, etc. Because this version is rounding down 1 /2 = 0, so you don't need to add an extra '0' at the start. However if even numbers or possible (but just arent different scores) this method will be wrong - the first methiod is better. Notice also in both of these examples I process the skill value with "+attr.skill || 0;" Roll20's backend always stores value as text, so even though you have set type="number" on skill, some processing is often safe. In your case, values should always be numbers. But it's a safe habit to adopt :) In your code you seem to be using Custom Roll Parsing. That's a more advanced level of coding than I was expecting from your initial question, but might not be necessary. But I'm not sure what exactly is going on here. Can you describe an attack roll as if we were playing face-to-face and I was at your table? What do I need to know to make an attack roll? I'm assuming it's something like you add a universal crit score to the weapon's crit bonus, then look on that table that gets 1d6, 1d6+1d4, etc., and roll that. If so, CRP is a bit more than you need.
Ty so much for helping me through this! I'm slowly learning roll20's system and thus learning a little jscript for crp haha, so that might be why it's throwing you off :p If we were playing at a table, you'd roll a d20, add the weapons hit, then add your skill +any misc bonusses. Then the opponent rolls avoid, which is d20+ speed +luck/2 +Amy misc bonusses. If you hit, you can roll crit which is a static amount of dice based on your skill, which increases every odd amount of skill, +any misc bonusses from weapons or feats. This means that crit scores based on skill are the same, but some weapons might add a d6 or a +1, same for feats. If your crit is higher then their dodge, you crit! Basically means double damage Rounding up does really seem to be the play yes! The way I'm trying to get it is that players can add their crit bonusses to their weapons, so that they don't need to keep checking the table etc to speed up combat (it's a combat heavy system and players can level up during combat, so it's easier if the array is doing some of the book keeping) So ideally it would check skill, grab the number from the array, add the crit bonus listed, then roll that.
1671376210

Edited 1671376263
Friend of mine and me made it work.  on("clicked:dmgmag4", function(){ getAttrs(["health", "channel_cost4","dmg_equipment4","magic"], function(values) { let hp=values.health; let channel=values.channel_cost4; startRoll("&{template:custom} {{title=@{equipment4}}} {{Magic Damage =[[@{dmg_equipment4}+@{magic}]]}}",(results) => { finishRoll(results.rollId); }); setAttrs({ health: hp-channel }); }); getAttrs(["skill","crit_bonus"], function(values){ const dice = ["0", "1d4", "1d6", "2d4", "1d4 + 1d6", "2d6", "2d4 +1d6", "3d6", "2d4 +2d6", "4d6", "2d4 + 3d6"]; const skill = values.skill; const x = Math.floor(skill /2); const rollCrit="&{template:custom} {{title=@{character_name}}} {{subtitle=@{equipment4}}} {{Crit =[[" +dice[x]+ "+@{crit_bonus4}]]}}"; startRoll(rollCrit,(results) => { finishRoll(results.rollId); }); }); }); </script> This does output two text boxes, but that's not as much of a headache to fix!  Thanks for getting us jumpstarted! Edit: Only the lower half is relevant for the array. 
1671381881

Edited 1671383127
GiGs
Pro
Sheet Author
API Scripter
I hadnt had time to think about this yet, but I think the CRP solutrion might be overkill. It requires you to press a button to update info. I see a problem with your current approach - you should combine those two getAttrs into a single one, and move the setAttrs down to after one finishRoll. Both changes for efficiency - reducing lag. Every getAttrs, setAttrs, and startRoll requires a separate access of roll20's servers - this can slow down your sheet, as it is delayed by however many other people are in Roll20's queue. It's made worse if you have other activating sheet workers, and other players with their own sheet. This does add up to very real lag if you aren't careful. I'm not sure what the first starRoll is doing in your worker. Does the attacker pay a cost for their attack? Also, having both startRolls - are you rolling attack and critical together? If so, you can do that with a single roll (and might not need CRP). Also the second getAttrs includes 'crit_bonus' but doesnt use it in the following code. Is it meant to do something? The first getAttrs has "dmg_equipment4","magic" But they aren't used in the sheet worker so can be removed. They are used in roll (@{magic} etc) but the roll part has its own method of getting the values and you don't need to declare them in getAttrs. Which leads me to another question: Why do you have two startRolls in your worker? I follow the second part, but I'm not sure about the first. Are you rolling attack and critical together, but having a separate startRoll for each? My solution just looked at the second part of your code. I was thinking that for just the critical roll you'd populate a hidden attribute with the dice value. let's say its called critValue. Then you can have a roll button with value="&{template:custom} {{title=@{character_name}}} {{subtitle=@{equipment4}}} {{Crit =[[@{critValue}+@{crit_bonus4}]]}}" It would be updated automatically without the user doing anything. Whenever they changed whatever stat the stat depends on. The sheet worker for that based on your post would look like this: on ( 'change:skill sheet:opened' , function () {   const dice = [ "0" , "1d4" , "1d6" , "2d4" , "1d4 + 1d6" , "2d6" , "2d4 +1d6" , "3d6" , "2d4 +2d6" , "4d6" , "2d4 + 3d6" ];   const skill = values . skill ;   const x = Math . floor ( skill / 2 );   setAttrs ({     critValue : x   }) }); The dice value would be calculated when the skill value changed and avoids the potential lag problem because it is done ahead of time, and it just seems like it's part of roll automatically (because getting values from a sheet doesn't have to tough roll20's servers - everything on the sheet is already there). It just does one call the servers - the roll itself. But your first part adds a complication - I don't fully understand what's going on there, hence the questions above.
1671382991

Edited 1671383166
GiGs
Pro
Sheet Author
API Scripter
By the way, here's one way of rewriting your existing worker (I havent checked the syntax): on ( "clicked:dmgmag4" , async function (){   getAttrs ([ "health" , "channel_cost4" , "skill" ], async function ( values ) {     let hp = values . health ;     let channel = values . channel_cost4 ;     const dice = [ "0" , "1d4" , "1d6" , "2d4" , "1d4 + 1d6" , "2d6" , "2d4 +1d6" , "3d6" , "2d4 +2d6" , "4d6" , "2d4 + 3d6" ];     const skill = values . skill ;     const x = Math . floor ( skill / 2 );     const rollCrit = "&{template:custom} {{title=@{character_name}}} {{subtitle=@{equipment4}}} {{Crit =[[" + dice [ x ]+ "+@{crit_bonus4}]]}}" ;     const rollResults = await startRoll ( "&{template:custom} {{title=@{character_name}}} {{subtitle=@{equipment4}}} {{Magic Damage =[[@{dmg_equipment4}+@{magic}]]}} {{Crit =[[" + dice [ x ]+ "+@{crit_bonus4}]]}}" );     setAttrs ({       health : hp - channel     }, { silent : false },       finishRoll ( rollResults . rollId )     );    });   }); Making the function async at the top lets you do the await thing with startRoll later - which means the code waits for that to finish before proceding. setAttrs has a feature where you can chain it with another function, and when you do this, the other function doesnt run till after the setAttrs function finishes, This probably isn't important here, but since you are already messing with fairly advanced code, you might as well add this tool to your toolbox. The {silent:false} part can be replaced with {silent:true} (and should be, if appropriate). true means the sheet worker won't trigger any other sheet workers if it changes any attributes, whereas false will. If your health attribute has sheet workers depending on its value, you should use silent:false, but if you don't, silent:true is better (to reduce sheet activity). Again, I'm still wondering if the CRP is needed at all (if you want a roll that also changes an attribute on the sheet at the same time, you do need CRP, though). If you want to use an approach like this, maybe this will steer you in a more efficient direction.
Ah yeah, the reasons I'm using crp/sheet workers and action buttons is that it's slightly faster at getting a result in chat then a roll button did for me.  It's not really lagging for me, but we only have a few player characters, so that might be why!  I will definitely look at the more nicely written version you sent tho, see if i can get it to work on my sheet. Whenever people use magic damage in this system, they pay with health, as to keep it fair and balanced.