I can make a couple of observations. In your stat mod sheet worker, you have this var theAbility = eventInfo.sourceAttribute;
getAttrs([theAbility], function(values) { but since you using event, you dont need to use getAttrs at all. event.newValue tells you the value of the stat. That said, there is a bug with that - if you plan to use API scripts to change attributes, newValue doesnt work so its better to stick with getAttrs in that case. This line might be overkill (though it is clever): var theAbilityValue = Object.values(values); You already know the name of the attribute from sourceAttribute, so you can use var theAbilityValue = Number(values[theAbility]) || 10; You might as well convert it to a number immediately. The || is a logical OR: if the Number attempt fails, it returns whatever is after the || instead. So its like setting a default value. I set the default to 10, so it'll calculate an average bonus (+0) if the input value is invalid. The calculation of the stat bonus is fine, but you can optimise it, like so. // create a function you can create a bunch of variables without cluttering the sheet worker
function calcAbilityMod(theAbilityValue) {
// mods is the thresholds at which the ability mod changes.
const mods = [18, 16, 13, 9, 6, 4, 3];
// findIndex loops through the array in order, and stops at the FIRST index that matches the rule.
const bonus = 3 - mods.findIndex(element => theAbilityValue >= element);
// this is why mods is in descending order. We are looking for the first attribute where theAbilityValue is greater than or equal.
// that gives us the index, the first is 0, the second 1, etc.
// so by subtracting from 3 we get the correct bonus.
// this doesnt handle what happens if you have scores above 18 or below 3, so might need tweaking if those can happen
// thats why I set the default to 10, and not something like 0: 0 would break this function.
// finally we convert the number into a string.
const withplus = bonus >= 0 ? "+" + bonus : bonus; return withplus; } on("change:strength change:intelligence change:wisdom change:dexterity change:constitution change:charisma", function(eventInfo) { var theAbility = eventInfo.sourceAttribute; getAttrs([theAbility], function(values) { var theAbilityValue = Number(values[theAbility]) || 10; var theAbilityMod = calcAbilityMod(theAbilityValue); setAttrs({ [theAbility + "modifier"] : theAbilityMod }); }); });