While I use the 5e sheet, I don't think that it is a good example of coding best practices. Its code is incredibly complex and difficult to understand. As for harder to develop, I think that relying on functions that are called as needed is easier to understand than having several change listeners that react to each other as I find it easier to see interactions when function calls are used than looking for several event listeners that I wrote 6 months ago that are now going to be triggered by new code that I just wrote. Sorrow, for your example code above, at a minimum I'd probably write it like this: let getArr = ['strength','strength_curr','constitution','constitution_curr','agility','agility_curr','peraware','peraware_curr','willpower','willpower_curr','intelligence','intelligence_curr','social','social_curr','agility_mod','defense-talent-mod'];
on("change:strength change:strength_curr change:constitution change:constitution_curr change:agility change:agility_curr " +
"change:peraware change:peraware_curr change:willpower change:willpower_curr change:intelligence change:intelligence_curr " +
"change:social change:social_curr", baseChange);
on("change:defense-talent-mod", defenseChanged);
const defenseChanged = function() {
getAttrs(["agility_mod", "defense-talent-mod"], function(values) {
const setObj = {};
setObj.defense_rating = defenseAffected(values);
setAttrs(setObj,{silent:true});
});
};
const baseChange = function(eventInfo) {
const attrib = eventInfo.sourceAttribute;
getAttrs(getArr, function(values) {
const attribVal = values[attrib];
const setObj = {};
if (attribVal < 0){
setObj[attrib] = 0;
}else if (attribVal > 40){
setObj[attrib] = 40;
}
values[attrib] = setObj[attrib];
//I'm assuming you actually wanted this if to be separate from the above if/else chain
if (attrib.endsWith("_curr")) {
let modName = `${attrib.slice(0, (attrib.length-5))}_mod`
setObj[modName] = calculateMod(attribVal);
values[modName] = setObj[modName];
if(modName === 'agility_mod'){
setObj.defense_rating = defenseAffected(values);
}
}
setAttrs(setObj,{silent:true});
});
};
const defenseAffected = function(values){
let agm = parseInt(values.agility_mod)||0;
let dtm = parseInt(values.defense-talent-mod)||0;
return (10+agm+dtm);
}; For this, I'm assuming that the mods are readOnly, or otherwise not changeable by the user directly. EDIT: Also, if this was my sheet I'd standardize the underscores vs. dashes in attribute names to all use underscores.