Edit: corrected a typo in the script in the last post. Here's how you make it universal. First in your script section, make a list of all the skills in your game with matching stat bonuses in this format: const skills = { "navigation": "int", "anotherskill": "an_attribute", "yet another skill": "an_attribute", }; This is an object called skills . You dont need to put them on separate lines, it just looks neater. Dont put int_total, just put int. I assume all the stat bonuses are named the same (stat_total). Then add this worker immediately after it: Object.keys(skills).forEach(skill => { on("change:" +skill + "_levels change:" +skills[skill] + "_total sheet:opened", function() { getAttrs([skill + "_levels", skills[skill] + "_total"], function(v) { const level = parseInt(v[skill + "_levels"],10)||0, stat = parseInt(v[skills[skill] + "_total"],10)||0; let result = level < 0 ? Math.floor(stat/2) : stat + level; setAttrs({ [skill]: result }); }); }); }); In case you;re interested in how it works: The first line Object.keys(skills).forEach(skill sets up a loop, going through the skills object one row at a time. Each row has a pair of values - the key , and the value . Navigation is a key , and int is that key's value . The script can then access these values: skill gives the current key, and skills[skill] gives that key's value, the stat. So you carefully substitute each reference to a skill with skill , and each reference to the stat with skills[skill] . Notice this line (with parseInt removed for clarity):: const level = v[skill + "_levels"]; Normally when you are getting an attributes value you would use const level = v.navigation_levels; but when you are building the attribute name with a string in the previous example, that format wont work and you have to use the [ ] format. You also need to do that on the setAttrs row [skill]: instead of navigation: So there you have it. I hope is useful for you. To recap, add this to your sheet worker and fill in the skills object, and you're good to go. const skills = { "navigation": "int", "anotherskill": "its_attribute", "yet another skill": "its attribute", }; Object.keys(skills).forEach(skill => { on("change:" +skill + "_levels change:" +skills[skill] + "_total sheet:opened", function() { getAttrs([skill + "_levels", skills[skill] + "_total"], function(v) { const level = parseInt(v[skill + "_levels"],10)||0, stat = parseInt(v[skills[skill] + "_total"],10)||0; let result = level < 0 ? Math.floor(stat/2) : stat + level; setAttrs({ [skill]: result }); }); }); });