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

[Script] [Error] need some help fixing

1562508085
Michael I.
Pro
Sheet Author
I am having 2 issues 1. First is the error below I am just not seeing the error so hope someone else will see. API Output Console Your scripts are currently disabled due to an error that was detected. Please make appropriate changes to your scripts and click the "Save Script" button and we'll attempt to start running them again.&nbsp; More info... For reference, the error message generated was:&nbsp; TypeError: Cannot read property 'set' of undefined TypeError: Cannot read property 'set' of undefined at checkWeary (apiscript.js:5138:32) at Array.forEach (native) at apiscript.js:4984:16 at eval (eval at &lt;anonymous&gt; (/home/node/d20-api-server/api.js:151:1), &lt;anonymous&gt;:65:16) at Object.publish (eval at &lt;anonymous&gt; (/home/node/d20-api-server/api.js:151:1), &lt;anonymous&gt;:70:8) at checkForReady (/home/node/d20-api-server/api.js:1438:12) at /home/node/d20-api-server/api.js:1518:9 at c (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:14:64) at /home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:560 at hc (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:39:147) /* update for tor-state-checker.js for Roll20. # Weary Checks to see if a character's endurance drops below her fatigue, and automatically sets the `weary` attribute to `weary` or `normal`, depending. This is very useful particularly if you're using the TOR roll tables, as you can then read the weary attribute of the selected token in a macro and roll on the appropriate success die table automatically: /r 1t[feat] + @{travel}t[@{weary}] It requires that the characters have `endurance`, `travel_fatigue`, 'weapon_encubrance_x' (x for 1-4) and 'gear_encumbrance_x (x for 1-8) and `weary` attributes. Make also sure that all NPCs have the radio button in the character sheet set to adversary and all player characters are set to Player Character accordingly (also via the radio button on top). If you want to manually set a character weary, you can do that via the gear list. Just add a gear that says "temporarily weary" with a very high encumbrance value that will in any case exceed the current limit. # Wounded / Treated Wound Sets a half-heart marker on the tokens of wounded/treated wound characters, mostly to serve as a reminder. It requires that the characters have 'wounded' and "wound_treated' attributes. # Miserable Sets a marker on the tokens of miserable characters. Also automatically detects if a character is turning miserable if hope is less or equal total_shadow. However it does not reset miserable. This is on purpose not to override any temporary miserable state. Needs 'total_shadow', 'temporary_shadow' and 'permanent_shadow' as well as 'miserable' and 'hope' attributes. # More Information Works great with the The One Ring character sheet for Roll20. For more of my The One Ring shenanigans: <a href="https://ringen.squarespace.com/loremasters-journal/" rel="nofollow">https://ringen.squarespace.com/loremasters-journal/</a> */ on('ready', function() { var characters = findObjs({ _type: 'character' }); characters.forEach(checkWeary, this); }); on('change:attribute', function(obj, prev) { var characterid = obj.get('_characterid'); var character = getObj("character", characterid); checkWeary(character); }); var checkWeary = function (character) { var characterid = character.get('_id'); var charactername = character.get('name'); var tokens = findObjs({ _type: 'graphic', represents: characterid }); // that's the value from the radio button mentioned in the comments above var isplayer = getAttrByName(characterid, 'pc', 'current'); // WEARY // characters only if (isplayer === '1') { // do some calculations on fatigue // weapon encumbrance var weapon_encumbrance_1 = getAttrByName(characterid, 'weapon_encumbrance_1', 'current'); var weapon_encumbrance_2 = getAttrByName(characterid, 'weapon_encumbrance_2', 'current'); var weapon_encumbrance_3 = getAttrByName(characterid, 'weapon_encumbrance_3', 'current'); var weapon_encumbrance_4 = getAttrByName(characterid, 'weapon_encumbrance_4', 'current'); var weapon_encumbrance_5 = getAttrByName(characterid, 'weapon_encumbrance_5', 'current'); var weapon_encumbrance_6 = getAttrByName(characterid, 'weapon_encumbrance_6', 'current'); var weapon_encumbrance = parseInt(weapon_encumbrance_1, 10) + parseInt(weapon_encumbrance_2, 10) + parseInt(weapon_encumbrance_3, 10) + parseInt(weapon_encumbrance_4, 10) + parseInt(weapon_encumbrance_5, 10) + parseInt(weapon_encumbrance_6, 10); // gear encumbrance var gear_encumbrance_1 = getAttrByName(characterid, 'gear_encumbrance_1', 'current'); var gear_encumbrance_2 = getAttrByName(characterid, 'gear_encumbrance_2', 'current'); var gear_encumbrance_3 = getAttrByName(characterid, 'gear_encumbrance_3', 'current'); var gear_encumbrance_4 = getAttrByName(characterid, 'gear_encumbrance_4', 'current'); var gear_encumbrance_5 = getAttrByName(characterid, 'gear_encumbrance_5', 'current'); var gear_encumbrance_6 = getAttrByName(characterid, 'gear_encumbrance_6', 'current'); var gear_encumbrance_7 = getAttrByName(characterid, 'gear_encumbrance_7', 'current'); var gear_encumbrance_8 = getAttrByName(characterid, 'gear_encumbrance_8', 'current'); var gear_encumbrance_9 = getAttrByName(characterid, 'gear_encumbrance_9', 'current'); var gear_encumbrance_10 = getAttrByName(characterid, 'gear_encumbrance_10', 'current'); var gear_encumbrance = parseInt(gear_encumbrance_1, 10) + parseInt(gear_encumbrance_2, 10) + parseInt(gear_encumbrance_3, 10) + parseInt(gear_encumbrance_4, 10) + parseInt(gear_encumbrance_5, 10) + parseInt(gear_encumbrance_6, 10) + parseInt(gear_encumbrance_7, 10) + parseInt(gear_encumbrance_8, 10) + parseInt(gear_encumbrance_9, 10) + parseInt(gear_encumbrance_10, 10); // travel fatigue var travel_fatigue = getAttrByName(characterid, 'travel_fatigue', 'current'); // sum it all up var total_fatigue = parseInt(travel_fatigue, 10) + weapon_encumbrance + gear_encumbrance; // do some calculation on miserable var permanent_shadow = getAttrByName(characterid, 'permanent_shadow', 'current'); var temporary_shadow = getAttrByName(characterid, 'temporary_shadow', 'current'); var total_shadow = parseInt(permanent_shadow, 10) + parseInt(temporary_shadow, 10); // setting the other variables, make sure they are created in the sheet var endurance = getAttrByName(characterid, 'endurance', 'current'); var weary = getAttrByName(characterid, 'weary', 'current'); var wounded = getAttrByName(characterid, 'wounded', 'current'); var wound_treated = getAttrByName(characterid, 'wound_treated', 'current'); var miserable = getAttrByName(characterid, 'miserable', 'current'); var hope = getAttrByName(characterid, 'hope', 'current'); // this initiates the attribute 'weary' not only the value of it var weary_attribute = findObjs({ _characterid: characterid, _type: 'attribute', name: 'weary' })[0]; // compare endurance to total_fatigue, lesser or equal triggers the "weary" state if (endurance &lt;= total_fatigue) { // optional: send a message to everyone // but send the message only on state changes if (weary === 'normal') { sendChat('character|'+characterid, '/me is weary!'); } // this sets weary to the new value weary_attribute.set('current', 'weary'); // this now tints the token yellowish tokens.forEach(function(token) { // #ff9900 token.set('tint_color', '#ff9900'); }, this); } else if (endurance &gt; total_fatigue) { // optional: send a message to everyone // but send the message only on state changes if (weary === 'weary') { sendChat('character|'+characterid, '/me is well again!'); } // this sets weary to the new value weary_attribute.set('current', 'normal'); tokens.forEach(function(token) { // transparent token.set('tint_color', 'transparent'); }, this); } else { return; } // WOUNDED if ( (wounded &amp;&amp; parseInt(wounded, 10) !== 0) || (wound_treated &amp;&amp; parseInt(wound_treated, 10) !== 0) ) { tokens.forEach(function(token) { // #98000 token.set('status_half-heart', ''); }, this); } else { tokens.forEach(function(token) { // transparent token.set('status_half-heart', false); }, this); } // MISERABLE // this initiates the attribute 'miserable' not only the value of it var miserable_attribute = findObjs({ _characterid: characterid, _type: 'attribute', name: 'miserable' })[0]; if ( // hope is below or equal shadow, but not if shadow is 0 (parseInt(hope, 10) &lt;= parseInt(total_shadow, 10) &amp;&amp; parseInt(total_shadow, 10) != 0) || // in case it has been set manually by the player, e.g. as result of a hazard (miserable === '1') ) { // optional: send a message to everyone // but send the message only on state changes if (miserable === '0') { sendChat('character|'+characterid, '/me is miserable!'); miserable_attribute.set('current', '1'); } tokens.forEach(function(token) { // #98000 token.set('status_bleeding-eye', ''); }, this); } else if ( (miserable === '0') || (parseInt(hope, 10) &gt; parseInt(total_shadow, 10)) ) { miserable_attribute.set('current', '0'); tokens.forEach(function(token) { // transparent token.set('status_bleeding-eye', false); }, this); } else { return; } } };&nbsp; 2nd Issue is that this should set status markers on the token but there not showing on the token, I see them highlighted if I go in manual to set them but they are not showing up on token themselves. But lets solve this in order #1 being the first priority Thanks in advance.
1562510224
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
Well, it's telling you that you're trying to use .set on an undefined variable. The error is being triggered somewhere in here: weary_attribute.set('current', 'weary'); // this now tints the token yellowish tokens.forEach(function(token) { // #ff9900 token.set('tint_color', '#ff9900'); }, this); } else if (endurance &gt; total_fatigue) { // optional: send a message to everyone // but send the message only on state changes if (weary === 'weary') { sendChat('character|'+characterid, '/me is well again!'); } // this sets weary to the new value weary_attribute.set('current', 'normal'); tokens.forEach(function(token) { // transparent token.set('tint_color', 'transparent'); }, this); } else { return; } // WOUNDED if ( (wounded &amp;&amp; parseInt(wounded, 10) !== 0) || (wound_treated &amp;&amp; parseInt(wound_treated, 10) !== 0) ) { tokens.forEach(function(token) { // #98000 token.set('status_half-heart', ''); }, this); } else { tokens.forEach(function(token) { // transparent token.set('status_half-heart', false); }, this); } // MISERABLE // this initiates the attribute 'miserable' not only the value of it var miserable_attribute = findObjs({ _characterid: characterid, _type: 'attribute', name: 'miserable' })[0]; if ( // hope is below or equal shadow, but not if shadow is 0 (parseInt(hope, 10) &lt;= parseInt(total_shadow, 10) &amp;&amp; parseInt(total_shadow, 10) != 0) || // in case it has been set manually by the player, e.g. as result of a hazard (miserable === '1') ) { // optional: send a message to everyone // but send the message only on state changes if (miserable === '0') { sendChat('character|'+characterid, '/me is miserable!'); miserable_attribute.set('current', '1'); } tokens.forEach(function(token) { // #98000 token.set('status_bleeding-eye', ''); }, this); } else if ( (miserable === '0') || (parseInt(hope, 10) &gt; parseInt(total_shadow, 10)) ) { miserable_attribute.set('current', '0'); tokens.forEach(function(token) { // transparent token.set('status_bleeding-eye', false); }, this); } The easy way to find where is to disable all your other scripts so that instead of getting aline number 5138 as the location, which doesn't exist within this code, you'll get the line number of your actual script. If you can't do this for some reason, like say script dependencies, then I'd do some logging of each of the variables you're trying to use .set on. My guess is it's weary_attribute or missrable_attribut since if there's no token found, tokens should just be an empty array that gives .foreach nothing to iterate on. As for question 2: I believe the problem is how your setting the status icon: token.set('status_half-heart', ''); You're setting the value to an empty string. It's been awhile since I have dealt with status icons, but I'm reasonably sure you need to set them to something besides an empty string. Although I also recall that something about this changed in the last year&nbsp;
1562510664
Victor B.
Pro
Sheet Author
API Scripter
You're probably right Scott.&nbsp;&nbsp; Here's how to set a status without a number showing over the icon token.set('status_'+newCondition.icon, true); Here's how to set a status with a number showing over the icon token.set('status_'+newCondition.icon,newCondition.duration); Here's how to remove the icon from the token token.set('status_'+newCondition.icon, false);
1562511620

Edited 1562511649
GM Michael
API Scripter
Alternatively, if you can't turn off your other scripts, you can always run with Airbag .&nbsp; It'll give the precise line number.
1562513953

Edited 1562516028
Michael I.
Pro
Sheet Author
Thanks Scott C. &amp; Victor B. Ok was able to disable all script so now points to 203:32 and 49:16 new error below with all other scripts off. 49: lines 49 and 50&nbsp; &nbsp; &nbsp; &nbsp; characters.forEach(checkWeary, this); }); lines 203 miserable_attribute.set('current', '0'); API Output Console Your scripts are currently disabled due to an error that was detected. Please make appropriate changes to your scripts and click the "Save Script" button and we'll attempt to start running them again.&nbsp; More info... For reference, the error message generated was:&nbsp; TypeError: Cannot read property 'set' of undefined TypeError: Cannot read property 'set' of undefined at checkWeary (apiscript.js:203:32) at Array.forEach (native) at apiscript.js:49:16 at eval (eval at &lt;anonymous&gt; (/home/node/d20-api-server/api.js:151:1), &lt;anonymous&gt;:65:16) at Object.publish (eval at &lt;anonymous&gt; (/home/node/d20-api-server/api.js:151:1), &lt;anonymous&gt;:70:8) at checkForReady (/home/node/d20-api-server/api.js:1438:12) at /home/node/d20-api-server/api.js:1518:9 at c (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:14:64) at /home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:560 at hc (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:39:147) I think I understand what's happened even though the character sheet has total_shadow below is from the sheet &lt; tr &gt; &lt; td &gt;&lt; span class = " label " data-i18n = " total-shadow " &gt;Total Shadow&lt;/ span &gt;&lt;/ td &gt; &lt; td colspan = " 2 " &gt;&lt; input type = " number " name = " attr_total_shadow " class = " sheet-center " value = " @{permanent_shadow}+@{temporary_shadow} " disabled = " true " &gt;&lt;/ td &gt; &lt;/ tr &gt; I don't see it listed under attributes. so I am guessing this is a hidden Attribute. so ill need to add it. nope still throwing error Thanks Michael G. (that is a nice API to keep in the bag of tricks)
1562515463
Victor B.
Pro
Sheet Author
API Scripter
I'd suggest putting in tons of log() statements.&nbsp; Comment out all of the code, then start at the top and log your objects to be sure.&nbsp; Your problem seems to be in one of the forEach loops against your tokens array.&nbsp; So start with that.&nbsp;&nbsp;
1562516317
Michael I.
Pro
Sheet Author
Thanks Victor B. I will try that Now
1562516842

Edited 1562516886
The Aaron
Roll20 Production Team
API Scripter
If it's not in Attributes, it's an autocalc field. These cause problems for the API because they don't have a representation, just a formula that is calculated on use. Before sheet workers, it was the only way to get something composite like a to hit with a proficient weapon. With the advent of sheet workers, I think it's fair to say that autocalc fields should be avoided. You can get the value of an autocalc field with getattrbyname() from the API, but you can't set them because they aren't attributes, and even if they were, they're a formula, not a value.&nbsp;
1562517403
Michael I.
Pro
Sheet Author
Thanks Aaron, they community updated the Character sheets a while back, but looks like we may need to update them again and use sheet workers instead of autocalc fields.&nbsp;
1562521949
Scott C.
Forum Champion
Sheet Author
API Scripter
Compendium Curator
yep, you're problem based on the line adjusted error is that miserable_attribute is not being found by the API. I'd recommend logging the values of your found attributes to make sure you're getting what you expect and putting in some gates to prevent the script from attempting to use an undefined attribute.
1563420714
Michael I.
Pro
Sheet Author
Ok fixed the errors but still could use help with the following parts of the api // WOUNDED if ( (wounded &amp;&amp; parseInt(wounded, 10) !== 0) || (wound_treated &amp;&amp; parseInt(wound_treated, 10) !== 0) ) { tokens.forEach(function(token) { // #98000 token.set('status_half-heart', ''); }, this); } else { tokens.forEach(function(token) { // transparent token.set('status_half-heart', false); }, this); } //wounded (is represented by a check box on the character sheet) and wound treated is also a Checkbox on the Character sheet I know I can set under wounded status icon by changing&nbsp; token.set('status_bleeding-eye', ''); &nbsp;just my FYI shouldn't this set it as true, but it doesn't it selects the icon but doesn't display it. how ever if I do&nbsp; token.set('status_bleeding-eye', ""); &nbsp;or if I do&nbsp; changing it to&nbsp; token.set('status_bleeding-eye', '0'); &nbsp;or&nbsp; token.set('status_bleeding-eye', true); &nbsp;all display the icon with 0. sorry got off track I need to alter this currently as written it will place the Icon on the token if the Broken check box is on and take it off if its not (this is the desired effect) however if the Wound Treated check box&nbsp; is checked it also places the Icon on the token and takes it off this is not the desired effect. also like to add if wounded send chat /me is wounded