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

Can't get value of an autocalculated field in API

Hi all I am trying to write a script that searches a repeating section (skills) of a character sheet for a specific skill, then return the level of that skill (which is an auto-calculated field on the character sheet due to the sheer number of parameters involved). I can use sendChat to calculate the actual value of the field (in the getSkillLevel function) and that works fine, and the value is passed to the FindSkill function fine, but instead of having FindSkill return that value, it returns a -1 as if it never executed the WHILE loop. I put a log statement to check the value of the var slevel before the break statement, and the log shows the correct value. A log statement to check slevel before the return statement always shows its value to be -1. I'm not terribly experienced in Javascript, so I might be missing something simple. Anybody have any thoughts? Here are my functions: function getSkillLevel(charName, n) {      return new Promise(resolve => {           sendChat('API', '[[@{'+charName+'|repeating_skills_$'+n+'_level}]]', ops => {                let total = ops[0].inlinerolls[0].results.total;                resolve(total);            });      }); } function findSkill(charId,charName,searchName) {      var n = 0;      var sName = 'sname';      var slevel = -1      while (sName != '' && n < 100) {           sName = getAttrByName(charId,'repeating_skills_$'+n+'_name');                if (sName === searchName) {                     getSkillLevel(charName, n).then((result) => {                          slevel = result;                      });                      break;                }                n++;      }      return slevel; };
1523142218
The Aaron
Pro
API Scripter
It's because sendChat() is asynchronous and Promises provide a means of dealing with that asynchronicity, but don't change the behavior.  The while loop runs through all 100 possible values and generates the promises that are waiting to be fulfilled by sendChat() completing, then returns slevel at it's unmodified value. See if passing the repeating attribute to getAttrByName() will resolve, that will prevent the need for the call to sendChat(). If that doesn't work, you'll have to look into redesigning your script to work with Promises or with Async/Await.
1523142284
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Not sure if this is just a copy paste error, but your while is incorrect: while (sName != '' && n < 100) { There isn't a check for what sName shouldn't be equal to.
Thanks for the replies. unfortunately getAttrByName() returns the formula in the cell, not the calculated value. I found that sending the formula to chat actually calculated it for me. sname != '' is actually a pair of single quotes, supposed to equal a null. It does work in practice. Never played with Async/Await.  Guess I have more research to do. *sigh*
1523143322
The Aaron
Pro
API Scripter
Yeah.. Promises are infectious. You might find it easier to collect all the attributes first and send them to sendChat as several inline rolls, then you just have to deal with one asynchronous call.  You could also collect all the promises in an array and use Promise.all() (or whatever it's called) to wait on all of them to finish.
Grabbing a value on a character sheet (auto-calculated or not) just shouldn't be this difficult! It seems like it should be a very elementary thing to do.
As I understand things, the true "value" of autocalc attribute is the formula itself. If you can edit the sheet itself, I would recommend computing the value with a sheetworker. Then you can call the attribute and get a value. Otherwise, I think you will need to replicate the calculation in your script to get the value.
Unfortunately, using a sheetworker would not be feasible considering the number of fields that contribute to the autocalc attribute, and the fact that some of those fields are also autocalc fields.
How many fields are we talking about? Sheetworkers can handle a lot. I believe there are times where autocalc is preferable, but I know on my own custom sheet anytime I am referencing an attribute elsewhere, I have made it either a directly-edited value or it is calculated by sheetworker. It has made referencing attributes much easier for me.
1523199787
The Aaron
Pro
API Scripter
If you control the character sheet, sheet workers do seem like a better alternative.  If you're worried about cascading changes, you can setup your update function using something like  _.debounce() to get trailing edge activation.