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 .
Advertisement Create a free account

How do you render a "get()" query for an attribute safe?


Edited 1617882816
Hey, guys! So I have this issue. Roll20 character sheets don't actually store each attribute set in HTML until the attribute is actually changed from default value. This results in an error of " Cannot read property 'get' of undefined " when an API script uses obj.get() to get an attribute that hasn't yet been stored. I could make a sheet worker that actually sets each attribute in place at the default value (sort of circumventing the problem), but this seems like a bit of a kludge fix. Is there a way to have an obj.get() "fail gracefully" by, for example, somehow setting a fall-back value when you call for it ? (such as you can do with a sheetworker with "values.attribute || 0;" wherein the zero at the end after the "||" makes sure that a failed value resolution will result in a value of "0"). Thank you in advance for any help you can provide. Below is a snippet of code by way of example. This generated the error message above in the console when it ran, because the attribute "EqSlot" was not yet stored. It only existed as a default input value in the HTML of the page (e.g., name="attr_EqSlot" value="1"). But when I ran it after setting the attribute into the character sheet manually (under Attributes & Abilities), it worked fine. // Set ID var sID = obj.get("_characterid"); // Get ability to be adjusted var oSlot = findObjs({ type: 'attribute', characterid: sID, name: "EqSlot" }, {caseInsensitive: false})[0]; var sSlot = oSlot.get("current"); var nSlot = parseInt(sSlot);
The Aaron
Forum Champion
API Scripter
If an Attribute hasn't been set to a non-default value, there won't be an Attribute object to represent it yet.  To handle that, you can just create one in that case: // Set ID const sID = obj . get ( "_characterid" ); // Get ability to be adjusted let oSlot = ( findObjs ({ type : 'attribute' , characterid : sID , name : "EqSlot" }, { caseInsensitive : false })[ 0 ] || createObj ( 'attribute' ,{ characterid : sID , name : "EqSlot" })); let sSlot = oSlot . get ( "current" ); let nSlot = parseInt ( sSlot ) || 0 ; You can extract that to a method that you can call all over: const getOrCreateAttribute = ( name , cid ) => findObjs ({ type : 'attribute' , characterid : cid , name : name }, { caseInsensitive : false })[ 0 ] || createObj ( 'attribute' ,{ characterid : cid , name : name }); // Set ID const sID = obj . get ( "_characterid" ); // Get ability to be adjusted let oSlot = getOrCreateAttribute ( "EqSlot" , sID ); let sSlot = oSlot . get ( "current" ); let nSlot = parseInt ( sSlot ) || 0 ; If you're just interested in the value and don't care about creating an Attribute object if there isn't one, you can use the getAttrByName() function: let nSlot = parseInt ( getAttrByName ( sID , "EqSlot" ) || 0 ); That won't create the Attribute object if it doesn't exist, it will just return the default value in that case.