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

Recalculating Modifiers (iterating over an array of strings, doing getAttrs and deciding to update)

1516045530

Edited 1516047835
I have a lot of characteristics (ie STR, SIZ, INT) that have "attr_str_modchange", and "attr_siz_modchange" attributes associated with them.  These "_modchange" attributes get changed when the associated "_current" attribute changes.  The "_modchange" serves only to detect a change that might affect skills (which have modifiers based on the characteristics). I registered an "on change" function for each characteristic's  "_modchange".  When that fires it iterates over the array of skill names (ie "throw", "art1") and gets the associated "_modstring" from each of them, which will look something like "STR/SIZ/DEX/POW" or "DEX,INT///".  The change handler then parses the "_modstring" by splitting it on "/" and "," and does a getAttr on a list of modifier attributes associated with each skill.  It then recalculates the modifier for the skill by adding up the modifier attributes and setAttr to  the "_mods" attribute associated with each skill. Believe it or not, this all actually works.  Sort of.  It only ever seems to work for the last skill in the array of skill names.  I'm going to share some bits here, but I may need to share the full sheet with someone.  I've been banging my head against this for several hours now and I think it may be down to asynchronicity or something.  /*If Characteristic _modchange changes, recalc mods for affected skills*/ allCharacteristics.forEach(function (charName) {    on("change:" + charName + "_modchange", function() {       var logprefix = "*** Characteristic " + charName + "_modchange change: ";       console.log(logprefix + "recalc affected skills");       console.log(logprefix + "allSkills: " + allSkills.toString());       for (var sk = 0; sk < allSkills.length; sk++) {          var skillName = allSkills[sk];          console.log(logprefix + "does " + skillName + " at index " + sk + " need to have it's mod recalculated?");          getAttrs([skillName + "_modstring"], function(modstrings) {             console.log(logprefix + "In gettAttrs for _modstring for skill: " + skillName);             console.log(logprefix + "skillName: " + skillName + ", modstrings length: " + modstrings.length);             if (typeof modstrings === "undefined")             {                console.log(logprefix + "Skill " + skillName + " modstrings is undefined after getAttrs");             }             else {                console.log(logprefix + "skillName: " + skillName + ", modstrings: " + modstrings);                var modString = modstrings[skillName + "_modstring"];                /*It seems like it either comes through here twice, once with modString === undefined                  and then another time with modString with a real value, or it's somehow doing both                  sides of the if statement.  Very odd.*/                if (typeof modString === "undefined"){                   console.log(logprefix + "Skill " + skillName + "_modstring is undefined");                   //setAttrs({[allSkills[sk] + "_mods"]: 0});                }                else{                   console.log(logprefix + "Skill " + skillName + " has modString " + modString);                   if (modString.toLowerCase().includes(charName)) {                      var charMods = [];                      var modStringSplit = modString.toLowerCase().split("/");                      var modPrimary = modStringSplit[0].split(",");                      var modSecondary = modStringSplit[1].split(",");                      var modNegSecondary = modStringSplit[2].split(",");                      var modNegPrimary = modStringSplit[3].split(",");                      for (var mp = 0; mp < modPrimary.length; mp++) {                         charMods.push(modPrimary[mp] + "_modprimary");                      }                      for (var ms = 0; ms < modSecondary.length; ms++) {                         charMods.push(modSecondary[ms] + "_modsecondary");                      }                      for (var mns = 0; mns < modNegSecondary.length; mns++) {                         charMods.push(modNegSecondary[mns] + "_modsecondary");                      }                      for (var mnp = 0; mnp < modNegPrimary.length; mnp++) {                         charMods.push(modNegPrimary[mnp] + "_modnegprimary");                      }                      console.log(logprefix + "charMods to get for " + skillName + ": " + charMods.toString());                      getAttrs(charMods, function(charModValues) {                         var modTotal = 0;                         for (var key in charModValues) {                            if (charModValues.hasOwnProperty(key)) {                               console.log(logprefix + "for allSkills[sk] " + skillName + ", charModValues property " + key + ", value " + charModValues[key]);                               modTotal += charModValues[key];                            }                         }                         console.log(logprefix + " " + skillName + " new Mods = " + modTotal);                         setAttrs({[skillName + "_mods"]: modTotal});                      });                                         }                   else {                      console.log(logprefix + "modString " + modString.toLowerCase() + " does not contain " + charName );                   }                }             }          });       }    }); });
1516047862

Edited 1516048310
Jakob
Sheet Author
API Scripter
You have some issues with variable scope (and, as you had correctly guessed, asynchronicity). I don't know if this will be enough, but you can do these things 1) Replace all instances of "var" with "let". 2) Replace for (var sk = 0; sk < allSkills.length; sk++) { By allSkills.forEach(function (skill) { and add the appropriate closing bracket ");" at the end of what used to be the for loop, and replace all instances of "allSkills[sk]" with "skill". Sorry, don't have time for more in-depth explanations.
I pasted the wrong code above, and fixed that.  This is it "working" as best as I can get it, which is that it resets the mod for "art1" but not for "throw".   *** Characteristic dex_modchange change: does throw at index 0 need to have it's mod recalculated? (unknown) *** Characteristic dex_modchange change: does art1 at index 1 need to have it's mod recalculated? /js/d20/sheetsandboxworker.js?20170926:67 This looks like it is at least trying both, but it never really does more with "throw" and it should be at least getting the "throw_modstring" the way it gets "art1". *** Characteristic dex_modchange change: Skill art1 has modString DEX,POW/INT// But it never does, and it looks like it does "art1" twice. *** Characteristic dex_modchange change: recalc affected skills (unknown) *** Characteristic dex_modchange change: allSkills: throw,art1 (unknown) *** Characteristic dex_modchange change: does throw at index 0 need to have it's mod recalculated? (unknown) *** Characteristic dex_modchange change: does art1 at index 1 need to have it's mod recalculated? /js/d20/sheetsandboxworker.js?20170926:67 Triggering for change:dex_modchange_max /js/d20/sheetsandboxworker.js?20170926:67 Triggering for change:xptotal /js/d20/sheetsandboxworker.js?20170926:67 Triggering for change:xptotal_max VM21:179 *** Characteristic dex_modchange change: In gettAttrs for _modstring for skill: art1 (unknown) *** Characteristic dex_modchange change: In gettAttrs for _modstring for skill: art1 VM21:180 *** Characteristic dex_modchange change: skillName: art1, modstrings length: undefined (unknown) *** Characteristic dex_modchange change: skillName: art1, modstrings length: undefined VM21:186 *** Characteristic dex_modchange change: skillName: art1, modstrings: [object Object] (unknown) *** Characteristic dex_modchange change: skillName: art1, modstrings: [object Object] VM21:192 *** Characteristic dex_modchange change: Skill art1_modstring is undefined (unknown) *** Characteristic dex_modchange change: Skill art1_modstring is undefined VM21:179 *** Characteristic dex_modchange change: In gettAttrs for _modstring for skill: art1 VM21:180 *** Characteristic dex_modchange change: skillName: art1, modstrings length: undefined VM21:186 *** Characteristic dex_modchange change: skillName: art1, modstrings: [object Object] (unknown) *** Characteristic dex_modchange change: In gettAttrs for _modstring for skill: art1 VM21:196 *** Characteristic dex_modchange change: Skill art1 has modString DEX,POW/INT// (unknown) *** Characteristic dex_modchange change: skillName: art1, modstrings length: undefined (unknown) *** Characteristic dex_modchange change: skillName: art1, modstrings: [object Object] VM21:218 *** Characteristic dex_modchange change: charMods to get for art1: dex_modprimary,pow_modprimary,int_modsecondary,_modsecondary,_modnegprimary (unknown) *** Characteristic dex_modchange change: Skill art1 has modString DEX,POW/INT// (unknown) *** Characteristic dex_modchange change: charMods to get for art1: dex_modprimary,pow_modprimary,int_modsecondary,_modsecondary,_modnegprimary VM21:223 *** Characteristic dex_modchange change: for allSkills[sk] art1, charModValues property dex_modprimary, value 90 (unknown) *** Characteristic dex_modchange change: for allSkills[sk] art1, charModValues property dex_modprimary, value 90 VM21:223 *** Characteristic dex_modchange change: for allSkills[sk] art1, charModValues property pow_modprimary, value 4 (unknown) *** Characteristic dex_modchange change: for allSkills[sk] art1, charModValues property pow_modprimary, value 4 VM21:223 *** Characteristic dex_modchange change: for allSkills[sk] art1, charModValues property int_modsecondary, value -5 VM21:227 *** Characteristic dex_modchange change: art1 new Mods = 89 (unknown) *** Characteristic dex_modchange change: for allSkills[sk] art1, charModValues property int_modsecondary, value -5 (unknown) *** Characteristic dex_modchange change: art1 new Mods = 89
Jakob, thanks for the reply.  I know it's pretty in-depth.  I'll try to implement your suggestions.
Thank you! THANK YOU!  I needed to use .forEach.  That was it.
1516049870
Jakob
Sheet Author
API Scripter
Justin C. said: Thank you! THANK YOU!  I needed to use .forEach.  That was it. Cool. The problem was that with the asynchronous calls within the for loop, sk would have been increased by the time the argument of getAttr() would actually be executed. Using the forEach() method, this problem can be avoided.