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

Scriptworker help for coding noob

1708426791

Edited 1708427078
I've got an easy one for you. I'm almost entirely new to coding (my first experience being relatively complex command blocks in minecraft, then upgrading to making relatively simple datapacks) and I wanted to create a custom character sheet for my friend who adapted the V20 system to be significantly simplified, as to make it easier for him to make better balanced enemies. As I've played in no fewer than a dozen systems, and remember how at least half of them work (which is unusual, apparently?) I thought I'd try my hand at making his thing better, enter C risis o f C onquest: K ryssom. Yes, I know I have a childish sense of humour, and no I'm not changing it. Thanks to Chat GPT, I had a decent launchpoint to get started. I'm garbage at coding, but give me an example of correct format and a list of common terms within scripts, and I can adapt it, like how one can adapt dough into bread. I struggle with the ingredients, but once I've got them... well, now we're cooking! Due to how the system works, you roll 1d10! to hit (I've got the modifiers covered), then you have 1 die of damage, with your attack modifiers increasing the die size (5 dice in V20 would be +5 to hit, and then would be 1d5 damage), but since we're using exploding criticals, I thought it would be much more interesting if we had an extra die for each crit, ergo rolling 31 (10 10 6) or 29 (10 10 4) would give you 3d5 damage. The native way to do this in macros is: floor($[[1.computed]]/10) This will get the die roll result and divide by 10, simple enough. The way to do this with an API is: !setattr --name Secret Hub --silent --Roll Result|[[1d10!/10]] A bit more complicated for a workaround. Each time the macro in question is used, it will instead get the Roll Result attribute from the Secret Hub character sheet, process the macro, and then with this on its own line afterward, it will change the value of Roll Result. Both of these have their fatal flaws, of course. For the first one, computed values HATE being in nested brackets for some reason beyond me. And for the second, APIs aren't omni-user friendly. Only a paid subscription can use them, and so most of Roll20's userbase wouldn't get the seamless experience of It Just Works . I've done a few iterations with Chat GPT for the sheetworker script at the end of the HTML, and this is the best I've gotten: <script type="text/worker">     function rollDice() {         var totalRoll = 0;         while (true) {             var rollResult = Math.floor(Math.random() * 10) + 1;             totalRoll += rollResult;             if (rollResult !== 10) {                 break;             }         }         var resultElement = document.querySelector('input[name="attr_roll_check"]');         resultElement.value = totalRoll;         return(totalRoll);     } </script> Of course, I have no idea what I'm doing. Me working on a script is like a computer processing data. I can tell you what the words mean, but I can't tell you how they're supposed to make you feel. This is another work-around where the scriptworker detects a button on the sheet being pressed, then iterates 1d10! entirely within itself, and then saves the value in the destination before the button does its calculations. If this is processed after the triggering command just like with the API example, then it at least can store the value for the next roll in the hidden attribute. Am I being a smart idiot again? Is there an easier way to do this? Will I just have to accept using the macro example? Find out next time on Dragonball Z!
I have noticed a few typos in that, but fixing them didn't help. Here's another on I got: <script type="text/worker"> on("clicked:rollButton", function() { getAttrs(["attr_roll-check"], function(values) { var output = values["attr_roll-check"]; setAttrs({ "attr_roll-result": output }); }); }); </script>
1708452291

Edited 1708454238
GiGs
Pro
Sheet Author
API Scripter
You mentioned chatGPT, so I feel obligated to post this: <a href="https://cybersphere.me/using-chatgpt-in-character-design/" rel="nofollow">https://cybersphere.me/using-chatgpt-in-character-design/</a> You'll get stuff that works in non-Roll20 sites but will almost never get anything that works in Roll20, and what you do get will likely be so wrong for Roll20 that it will lead you in directions that simply cannot be done on Roll20. (Both posts have examples of code that will never work on Roll20, for example.) I'm not following your roll mechanic description so I can't tell if you need a roll button (standard macro) or an action button (with Custom Roll Parsing). I'm leaning towards the latter (which is more complex), but both are very unique to Roll20 and chatGPT will not help at all. If you want good help, here is what I'd like you to do: Forget Roll20. Describe the roll mechanic as if you were describing it to a new player at your game table, a player that does not know anything about the game being played or any of the games its based on. For example, how many dice are rolled? Is it always 1 d10? Do you need a full 10 points to do 1d5 damage, and do you get an extra 1d5 for each 10? Don'yt leave anything out. Don't say, "I've got the modifiers covered" - we need to know how they are calculated and what they do. After that, we can talk about how to make it fit your roll20 sheet. We'll need to know attribute names if they are used, and the HTML structure of any buttons you are usung.
1708453622
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Seconding everything GiGs said. ChatGPT, while useful for generic web dev, is useless for anything R20 related; it just doesn't have a large enough code base to learn from.
Thank you both, you are fine gentlemen indeed. So here's how i would describe the combat system to a new player: you have you base ability bonus from your stats, say strength. you can get extras based on certain things, e.g: silver weapons gain +1 to hit against werewolves, and these are all tallied in the bonuses section, and then there's the attack modifier itself, which comes from a skill. skills are sorted into 4 categories: offensive, defensive, productive, and tactical. a great example of this is intimidation. in other games intimidation is a charisma skill, but a butt-ugly bodybuilder giving you the stink eye sounds pretty intimidating to me... it also sounds like it could serve as a tactical advantage. martial as a skill is used for feats of strength, like shoving a boulder aside, or holding up part of a bridge so others can cross. it adds on to your melee attack, like how athletics gets added to your melee defence (block). unlike V20, these modifiers go onto specific attacks, e.g: batting someone with a laser rifle is a strength attack, firing it as normal is a dex (ranged) attack, summoning a tentacle to use it for you, or using telepathy to pull the trigger is a con (magic) attack, using a drone instead is an int (tech/hack) attack, faking a stab with an affixed bayonet before slicing the enemy throat is a wis (poise) attack, and figuring out where an enemy weakpoint is, to assist an ally's aim is a cha (intrigue) attack. when you make an attack roll, you roll 1d10 plus the modifiers mentioned before, and then if it beats their defensive ability (like block), then you can do damage. the default damage is 1 die, but if you roll a critical hit, you reroll and add it to the total, ergo rolling 10 twice and then 6 earns you a 26 to hit. for each critical, you get to roll an extra damage die, so in this case you'd roll 3 dice. the size of the dice you roll for damage is equal to your bonuses. if you have an odd number of bonuses, such as +5, and you have to use physical dice, simply roll the die that's 1 more and if it lands on that highest number, then reroll. playing on roll20 however is much more straightforward. all you need to roll 1d5 is to type it. there we go. i tried to be as detailed as possible without talking down to you (bad habit). here's a snippet of my code so far, within context: &lt;html lang="en"&gt; &lt;div class="sheet-3colrow"&gt;&lt;h2&gt;Abilities&lt;/h2&gt;&lt;/div&gt; &lt;div class="grid-container"&gt; &lt;div class="1"&gt;&lt;button onclick="rollDice" type="roll" class="sheet-blank-button" value="[[(@{roll-check}+@{net-str})]]"&gt;&lt;h4&gt;Strength&lt;/h4&gt;&lt;/button&gt;&lt;/div&gt; &lt;div class="1"&gt;&lt;input type="number" name="attr_base-str" value="1"/&gt;&lt;/div&gt; &lt;div class="7"&gt;Physique&lt;/div&gt; &lt;div class="7"&gt;&lt;input type="number" name="attr_bonus-str" value="0"/&gt;&lt;/div&gt; &lt;/div&gt; &lt;div class="sheet-3colrow"&gt;&lt;h2&gt;Combat Stats&lt;/h2&gt;&lt;/div&gt; &lt;div class="grid-container"&gt; &lt;div class="1"&gt;&lt;button onclick="rollButton" class="sheet-blank-button" value="[[@{roll-check}+@{net-str}+@{a-str}]]" type="roll"&gt;&lt;h4&gt;Melee&lt;/h4&gt;&lt;/button &gt;&lt;/div&gt; &lt;div class="1"&gt;&lt;input type="number" name="attr_net-str" value="(@{base-str}+@{bonus-str})" disabled="true"/&gt;&lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;div&gt;&lt;input type="hidden" name ="attr_roll_check" value="0"/&gt;&lt;/div&gt; &lt;div&gt;&lt;input type="hidden" name ="attr_roll_result" value="0"/&gt;&lt;/div&gt; &lt;script type="text/worker"&gt; on("clicked:rollButton", function() { getAttrs(["attr_roll-check"], function(values) { var output = values["attr_roll-check"]; setAttrs({ "attr_roll-result": output }); }); }); &lt;/script&gt; .sheet-3colrow { display:flex; background:#9a7647; gap:20px; text-align:center; border-top-style: solid; border-top-width: 5px; border-top-color: white; } .charsheet button[type=roll].sheet-blank-button::before { content: ''; display:flex; gap:20px; padding-left: 2px; padding-right: 2px; justify-content:center; width: 80px; text-align: center; } .grid-container { display: grid; text-align:center; grid-template-columns: repeat(6, 1fr); border-bottom-style: solid; border-bottom-width: 20px; border-bottom-color: white; grid-template-areas: "1 2 3 4 5 6" "7 8 9 10 11 12"; } .1 {grid-area:1;} .2 {grid-area:2;} .3 {grid-area:3;} .4 {grid-area:4;} .5 {grid-area:5;} .6 {grid-area:6;} .7 {grid-area:1;} .8 {grid-area:2;} .9 {grid-area:3;} .10 {grid-area:4;} .11 {grid-area:5;} .12 {grid-area:6;} I would have minified the code blocks, but I thought you might prefer exact, specific detail. They are always printed in this format, after all. This picture shows what it looks like, in case it helps. everything works except for the actual rolling of the d10. if literally any numerical value or number-resolving command (such as ' [[1d10!]] ') is placed in the "roll-check" attribute, it will read the valid value and continue the sum instead of referencing the javascript. now that i think about it, i might be trying to reinvent the wheel. after all dnd 5e has a simple box to confirm what extra to roll in case of a crit. thank you in advance for your time, and your help.
1708463163

Edited 1708467515
GiGs
Pro
Sheet Author
API Scripter
I'll post more later, but can make a quick note: this section looks like it was built by chatGPT and will not work on Roll20: &lt;button onclick="rollButton" class="sheet-blank-button" value="[[@{roll-check}+@{net-str}+@{a-str}]]" type="roll"&gt;&lt;h4&gt;Melee&lt;/h4&gt;&lt;/button &gt; This is a good example of why chatGPT doesnt work for HTML - it's not just sheet workers it fails for. onclick does not work here. You'd need to decide if that was a roll button or an action button. If a roll button, it would look like this: &lt;button type="roll" class="sheet-blank-button" name="roll_str_roll" value="[[@{roll-check}+@{net-str}+@{a-str}]]"&gt;&lt;h4&gt;Melee&lt;/h4&gt;&lt;/button &gt; In this case, the value will be treated as a roll or calculation and sent to chat: I don't see a roll there. You might want to use the default rolltemplate too, to make this look nicer, like &lt;button type="roll" class="sheet-blank-button" name="roll_str_roll" value="&amp;{template:default} {{[[@{roll-check}+@{net-str}+@{a-str}]]}}" type="roll"&gt;&lt;h4&gt;Melee&lt;/h4&gt;&lt;/button &gt; (You could add more to prettify that) Also your attributes in inputs appear to be defined properly, but as a general recommendation, avoid any characters but letters, numbers, and underscores in attribute names (and start with a letter). If you use the attributes in sheet workers (and you probably will), this makes the code easier.
1708464058

Edited 1708465014
GiGs
Pro
Sheet Author
API Scripter
I'm guessing @{roll_check} is your roll, in which case you probably want to replace that with a standard roll20 dice expression. For instance, change the button value to this: value="&amp;{template:default} [[ [[floor([[1d10!!+@{net-str}+@{a-str}]]/10)]]d5]] {{name=TYPE OF ROLL}} {{attack=$[[0]]}} {{damage ($[[1]] dice)=$[[2]]}}" This uses an undocumented feature of roll20 called Reusing Rolls . You'd want to change TYPE OF ROLL to match your desired roll name. It'll be displayed above the roll. You can test this by the way, by putting this in an Ability for the character (Attributes &amp; Abilities tab): &amp;{template:default} [[ [[floor([[1d10!!+@{net-str}+@{a-str}]]/10)]]d5]] {{name=TYPE OF ROLL}} {{attack=$[[0]]}} {{damage ($[[1]] dice)=$[[2]]}} If you want the user to be prompted to enter a bonus, change the value to add a query like this: value="&amp;{template:default} [[ [[floor([[1d10!!++@{net-str}+@{a-str}+?{Bonus|0}]]/10)]]d5]] {{name=TYPE OF ROLL}} {{attack=$[[0]]}} {{damage ($[[1]] dice)=$[[2]]}}"
&lt;levity&gt; &nbsp;&nbsp;&nbsp; //*frantically searches for the like button* &gt;/levity&gt; i was thinking of using a rolltemplate, as i've gotten fair at them in my time, but the source issue is rolling a die, then referencing it within the same command. like with my original example, roll20 hates nesting "$[[1.computed]]", and there appears to be no way forward in modifying the dice otherwise. as for the code that looks like it was built by chat gpt, really the only part it contributed was the onclick portion. i built basically everything else from code fragments i found in various discussions... most of which happened to involve your good self, actually. now where is that Adonalsium-damned like button?!
1708468318

Edited 1708468342
GiGs
Pro
Sheet Author
API Scripter
Hehe, I'm flattered. If you want to see more of my code samples, and want to answer character sheet question, I'll have to point you to my blog: <a href="https://cybersphere.me/roll20-sheet-author-master-list/" rel="nofollow">https://cybersphere.me/roll20-sheet-author-master-list/</a> (and ask away if you have any questions - that'll show me where the text there isn't clear enough). Also, $[[1.computed]] is part of the Reusing Rolls system. I need to practice with that syntax more: if I remember correctly, you should be able to perform arithmetic with that. But I'm not very experienced with that syntax and generally find I can use the earlier syntax for everything I need (as in this example). PS: I've looked for a like button too - it would be handy!
in my (well-advised) research last night, i happened across rolltables. i've always avoided any kind of mathy logic stuff with "table" in its name, like loottables in minecraft (though normal mathy logic stuff, like table charts i'm fine with??), so i never considered rolltables. is there a way to use rolltables as a kind of crit-detection? e.g: 10 entries on the table, you click the button, it tells you the roll, and iterates crits through a feedback loop, and something else tallies it up?
1708535920
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
roll tables by themselves are very limited. They can just return the text of a given roll on the table (and only the first result if you do multiple rolls on the table in a given roll). The best way to handle something like tables in a roll from a sheet is to use custom roll parsing and have the js CRP function handle the table output.
1708536938
GiGs
Pro
Sheet Author
API Scripter
As Scott says, Rollable Tables in Roll20 are very limited. They don't work with modifiers at all. Theyare best avoided for actual rolls. They have their uses, but despite the name, their main uses do not involve dice rolls.
1708555020
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
And someone else just asked a similar question, you can see how that would work in our answers over there .
1708689370

Edited 1708712392
so, i've had another peek at reusing rolls, and i was right. indexed rolls can't be used in other rolls, broadly speaking. my question is why? if it's a matter of recursive logic, surely a simple "ERROR: Recursive logic not supported." would suffice. Edit: Thank you Scott C. ( <a href="https://wiki.roll20.net/Reusing_Rolls" rel="nofollow">https://wiki.roll20.net/Reusing_Rolls</a> ) &amp;{template:default} [[ [[1d20]] + [[1d6]] + [[6]] ]] {{name=My Attack}} {{$[[0]] + $[[1]] + $[[2]]==$[[3]]}} Edit: I FREAKIN' LOVE YOU GUYS! i figured it out!! if i can't nest an indexed roll, then i should NEST THE ROLL TO BE INDEXED!! &amp;{template:default} {{name=Melee Attack}} [[[[floor([[[[1d10!+@{attack_bonus}+@{prof_bonus}]]-@{attack_bonus}-@{prof_bonus}]]/10)+1]]d[[@{attack_bonus}]]]] {{$[[0]] to hit. $[[4]] damage.}}
Sorry to cast resurrection on this, but at least it's not true resurrection. i have a new issue that's just out of my reach to figure out. i have each section of the character sheet capable of being hidden with a checkbox, and i found something from 5 years ago that mostly GiGs helped with in regards to a very similar issue, the biggest difference is that what i'm making isn't quite complicated enough to warrant entire other tabs. i want to relocate the checkboxes to the top of the sheet and put them in a row. so far it's simple enough: set up a grid at hte top of the sheet, clone the checkboxes, change the original from checkbox to hidden, then... link... them? somehow?? i tried to follow the linked forum post as best as i could, but i'm still having a major issue (that being; when the box is checked, it doesn't hide the contents). &lt;div&gt; &lt;div class="sheet-body"&gt; &lt;div class="grid-container"&gt; &lt;div class="1"&gt; &lt;input type="checkbox" name="attr_stats" class="sheet-toggle-hide" value="1"/&gt;&lt;span&gt;Hide Stats&lt;/span&gt; &lt;/div&gt; &lt;div class="2"&gt; &lt;input type="checkbox" name="attr_abilities" class="sheet-toggle-hide" value="1"/&gt;&lt;span&gt;Hide Abilities&lt;/span&gt; &lt;/div&gt; &lt;div class="3"&gt; &lt;input type="checkbox" name="attr_combat" class="sheet-toggle-hide" value="1"/&gt;&lt;span&gt;Hide Combat&lt;/span&gt; &lt;/div&gt; &lt;div class="4"&gt; &lt;input type="checkbox" name="attr_skills" class="sheet-toggle-hide" value="1"/&gt;&lt;span&gt;Hide Skills&lt;/span&gt; &lt;/div&gt; &lt;div class="5"&gt; &lt;input type="checkbox" name="attr_help" class="sheet-toggle-show" value="1"/&gt;&lt;span&gt;Show Help&lt;/span&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;div&gt; &lt;input type="hidden" name="attr_stats" class="sheet-body" /&gt; &lt;div class="grid-container"&gt; //insert generic stuff tm here. &lt;/div&gt; &lt;/div&gt; .grid-container { display: grid; text-align:center; grid-template-columns: repeat(6, 1fr); border-bottom-style: solid; border-bottom-width: 10px; border-bottom-color: white; grid-template-areas: "1 2 3 4 5 6" "7 8 9 10 11 12"; } input.sheet-toggle-hidden:not([value='1']) ~ div .sheet-stats, input.sheet-toggle-hidden:not([value='1']) ~ div .sheet-attributes, input.sheet-toggle-hidden:not([value='1']) ~ div .sheet-combat, input.sheet-toggle-hidden:not([value='1']) ~ div .sheet-skills, input.sheet-toggle-shown:([value='1']) ~ div .sheet-help{ display: none; } .charsheet input.sheet-toggle-show:not(:checked) ~ div.sheet-body, //this works for normal check boxes located with the stuff to be hidden .charsheet input.sheet-toggle-hide:checked ~ div.sheet-body { display: none; } textarea.inputarea { width: calc(100% - 5px); height: 108px; } help me, zero-one codernobi, you're my only hope.
1708988251

Edited 1708988382
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
I'd probably leave the originals as checkboxes, just set them to display none via some css. Then you can use the same css that was working before. Also, as long as the name is the same, they are linked (doesn't quite work if they are radios).
i am such an idiot. my mistake was that the section to be hidden was labelled "sheet-body" instead of "sheet-toggle-hide". thank you for your help, it honestly did lead me to see what i was doing wrong.