on([ "sheet:opened", "change:force_base", "change:force_lettre", "change:force_divers", "change:niveau" ].join(" "), function () { getAttrs(["FORCE_BASE", "FORCE_LETTRE", "FORCE_DIVERS", "DEXTERITE_BASE", "DEXTERITE_LETTRE", "DEXTERITE_DIVERS", "CONSTITUTION_BASE", "CONSTITUTION_LETTRE", "CONSTITUTION_DIVERS", "INTELLIGENCE_BASE", "INTELLIGENCE_LETTRE", "INTELLIGENCE_DIVERS", "SAGESSE_BASE", "SAGESSE_LETTRE", "SAGESSE_DIVERS", "CHARISME_BASE", "CHARISME_LETTRE", "CHARISME_DIVERS", "NIVEAU"], function(v) { var force = Math.round(parseInt(v["FORCE_BASE"],10) + (parseInt(v["FORCE_LETTRE"],10)+ parseInt(v["FORCE_DIVERS"],10)) * parseInt(v["NIVEAU"],10) / 100); var dexterite = Math.round(parseInt(v["DEXTERITE_BASE"],10) + (parseInt(v["DEXTERITE_LETTRE"],10)+ parseInt(v["DEXTERITE_DIVERS"],10)) * parseInt(v["NIVEAU"],10) / 100); var constitution = Math.round(parseInt(v["CONSTITUTION_BASE"],10) + (parseInt(v["CONSTITUTION_LETTRE"],10)+ parseInt(v["CONSTITUTION_DIVERS"],10)) * parseInt(v["NIVEAU"],10) / 100); var intelligence = Math.round(parseInt(v["INTELLIGENCE_BASE"],10) + (parseInt(v["INTELLIGENCE_LETTRE"],10)+ parseInt(v["INTELLIGENCE_DIVERS"],10)) * parseInt(v["NIVEAU"],10) / 100); var sagesse = Math.round(parseInt(v["SAGESSE_BASE"],10) + (parseInt(v["SAGESSE_LETTRE"],10)+ parseInt(v["SAGESSE_DIVERS"],10)) * parseInt(v["NIVEAU"],10) / 100); var charisme = Math.round(parseInt(v["CHARISME_BASE"],10) + (parseInt(v["CHARISME_LETTRE"],10)+ parseInt(v["CHARISME_DIVERS"],10)) * parseInt(v["NIVEAU"],10) / 100); setAttrs({ ["FORCE"] : force, ["FOR"] : Math.floor(force/2 - 5), ["DEXTERITE"] : dexterite, ["DEX"] : Math.floor(dexterite/2 - 5), ["CONSTITUTION"] : constitution, ["CON"] : Math.floor(constitution/2 - 5), ["INTELLIGENCE"] : intelligence, ["INT"] : Math.floor(intelligence/2 - 5), ["SAGESSE"] : sagesse, ["SAG"] : Math.floor(sagesse/2 - 5), ["CHARISME"] : charisme, ["CHA"] : Math.floor(charisme/2 - 5) }) }); }); on([ "sheet:opened", "change:atkcac_carac1_selector" ].join(" "), function () { getAttrs(["FORCE_BASE", "FOR", "DEXTERITE_BASE", "DEX", "CONSTITUTION_BASE", "CON", "INTELLIGENCE_BASE", "INT", "SAGESSE_BASE", "SAG", "CHARISME_BASE", "CHA", "atkcac_carac1_selector"], function(v) { var caracval = 0; switch(parseInt(v["atkcac_carac1_selector"],10)) { case 0: caracval=0 break; case 1: caracval=parseInt(v["FORCE_BASE"],10) + parseInt(v["FOR"],10); break; case 2: caracval=parseInt(v["DEXTERITE_BASE"],10) + parseInt(v["DEX"],10); break; case 3: caracval=parseInt(v["CONSTITUTION_BASE"],10) + parseInt(v["CON"],10); break; case 4: caracval=parseInt(v["INTELLIGENCE_BASE"],10) + parseInt(v["INT"],10); break; case 5: caracval=parseInt(v["SAGESSE_BASE"],10) + parseInt(v["SAG"],10); break; case 6: caracval=parseInt(v["CHARISME_BASE"],10) + parseInt(v["CHA"],10); break; } setAttrs({ ["ATKCAC_CARAC1"] : caracval }) }); }); ^ Above is my current code that I did before reading your answer. It seems like I did something similar to you, but I instead used a hardcoded switch-case rather than parsing logic. As for other attributes I have DEXTERITE/DEX, CONSTITUTION/CON, INTELLIGENCE/INT, SAGESSE/SAG, CHARISME/CHA which are equivalent to FORCE/FOR. (With the usual CODE, LETTRE, TOT for everyone. Note : I have now renamed FORCE_TOT to simply FORCE, before I needed two names because I had two different autocalc names displaying the same number.) Aside from BARPHY[...], I also have BARMAG, DEFPHY,DEFMAG, that have similar fields (_CARAC1/2/3, ...). But I think you've given me enough info to figure out everything else by myself for now. (But if I made any major mistake in my code, please do tell me).