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

Making 1 attribute give a negative (custom character sheet)

Hello! I need help with making an attribute of 0 -2 stats only go from 0 to like 9, and only 0 gives a -2. 1 gives 1, 2:2 ETC.
Chad, How will this be used?  In a macro?  In a sheetworker?  If you're looking to use in a sheetworker, I imagine something like this would work for you: const stat_mod = attribute === 0 ? -2 : attribute; What this does is, if the "attribute" value is 0 then stat_mod is -2, else stat_mod is equal to the value of attribute.  Then you can use stat_mod as you require in your code.
yes sorry I should have included that, I am working on a sheetworker for a home brewed game, so it should look like the following? const stats = ['Agility','Body','Intelligence','Willpower'];     stats.forEach(function (stat) {         on("change:" + stat + " sheet:opened", function () {             getAttrs([stat], function (values) {                 const stat_mod = attribute === 0 ? -2 : attribute;                 setAttrs({                     [stat + 'Mod']: mod                 });             });         });     });
1689905970

Edited 1689906148
GiGs
Pro
Sheet Author
API Scripter
That looks like the right idea. Though you might want to check for <=0 than === 0, because if players can enter a value, they might incorrectly enter a negative value. The problem is you have attribute as a variable, but never set it anywhere. So maybe: const stats = ['Agility','Body','Intelligence','Willpower'];     stats.forEach(function (stat) {         on("change:" + stat.toLowerCase() + " sheet:opened", function () {             getAttrs([stat], function (values) { const attribute = +values[stat] || 0;                 const stat_mod = attribute <= 0 ? -2 : attribute;                 setAttrs({                     [stat + 'Mod']: mod                 });             });         });     }); Also, attributes on the event line (the one that starts with on ) must be in lower case. If not, they might appear to work for a while, but at some point in the future, the attribute will not be recognised and the sheet worker will stop working, it's a bug, IMO (not that attributes need to be in lower-vase, but that they intermittently work when they aren't lower-case), but it is documentated.
okay and do I need to make a sheet worker for each stat? I was under the assumption that its 1 and done. but I have little knowledge of HTML lol
1689939586
GiGs
Pro
Sheet Author
API Scripter
You can make a single sheet worker and include all stats within it, but its for more common (and easier) to write a sheet worker for each stat. The code you listed above creates a separateb sheet worker for each stat and that's fine.
sweet! thank you for your help!
Those are some good points, GiGs.  I'd assumed Chad was enforcing strict values for stats.  Chad, the single sheet worker is advice GiGs provide me in the past, too.  I think it's sound advice and can provide optimization, depending on how complex your sheet is perhaps.  I created an event builder that allows me to easily add and review what events I'm using (helps with dev and troubleshooting)...something like this...note, I've not tested it but looks right ;)... const stats = [     'agility',     'body',     'intelligence',     'willpower', ]; const events = `change:${stats.join(" change:")} sheet:opened`; on(events, function (eventInfo) { const get_stats = eventInfo.triggerName === 'sheet:opened' ? stats : [`${eventInfo.sourceAttribute}`]; getAttrs(get_stats, function (values) { const set_attrs = {}; const stat_mods = get_stats.map(v => { const attribute = +values[v] || 0; return attribute <= 0 ? -2 : attribute; }); for (let i = 0, n = get_stats.length; i < n; i++) { set_attrs[get_stats[i] + 'Mod'] = stat_mods[i]; } setAttrs(set_attrs,{slient:true}); }); }); If you wanted to use something like this with buttons or removed repeating rows, you'd just replace 'change' in const events with 'clicked' or 'remove', respectively.  If you're looking to include those button or removed events in the same sheetworker, you can do that too but I'd recommend making separate event builders for each, and then string them together.  Like this... let events = ''; // Input names const input_events = [ 'body', 'intellect', ]; events = `change:${input_events.join(" change:")}`; // Button names const button_events = [ 'attack', 'spell', ]; events += ` clicked:${button_events.join(" clicked:")}`; // Repeating sections const remove_events = [ 'repeating_spell', 'repeating_weapon', ]; events += ` remove:${remove_events.join(" remove:")}`; GiGs, I've seen you use the '+' in front of a variable in the past...assuming a numerical value... const attribute = +values[stat] || 0; ...   but I'm not familiar with it.  Looks like it's a good replacement for parseInt().  What are your thoughts?  Are there caveats with it or does it really just replace parseInt()?
1689990819

Edited 1689991393
GiGs
Pro
Sheet Author
API Scripter
I think Scott's more of a proponent of using a single sheet worker than I am. It is the more efficient approach, but makes maintaining the code harder - a more modular, "many small sheet workers" approach - is better there I think (as long as your sheet doesn't have too much spaghetti code!). But the heavier your sheet is, the more likely that the single sheet worker approach will be better. I use the + here mainly because its less typing. :) But + coerces a value into a number, just like the Number() function. It doesn't replace parseInt because it gives a floating point number, It operates more like parseFloat than parseInt ( like, not the same as - there are minor technical differences that shouldn't be relevant for most sheet workers). There are times you want an integer not a floating point number. I use a function to simplify the typing there: const int = (score, fallback) => parseInt(score) || fallback; Put this at the start of your script block, and whenever you'd be tempted to type parseInt(something) || 0 , you can instead type int(something) . It also means you can do multiple operations on the same line, like int(first) + int(second) , instead of something clunky like (parseInt(first) || 0) + (parseInt(second) || 0) . Whether I use int() or + really depends on mood. Most of the time an integer is fine, so if I want to safeguard against rounding errors, I'lkl use int(). I use + a lot on the forums because it's less typing, and I don't have to explain int (). i don't want to type parseInt() out every time.