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

Mod that worked fine previously suddenly no longer working.

1726728629

Edited 1726729705
Blud
Pro
Your scripts are currently disabled due to an error that was detected. Please make appropriate changes to your script's code and click the "Save Script" button. We will then attempt to start running the scripts again.&nbsp; More info... &nbsp;If this script was installed from the Mod Library, you might find help in the Community API Forum. For reference, the error message generated was:&nbsp; TypeError: Cannot read properties of undefined (reading 'get') TypeError: Cannot read properties of undefined (reading 'get') at apiscript.js:26:48 at eval (eval at &lt;anonymous&gt; (/home/node/d20-api-server/api.js:169:1), &lt;anonymous&gt;:65:16) at Object.publish (eval at &lt;anonymous&gt; (/home/node/d20-api-server/api.js:169:1), &lt;anonymous&gt;:70:8) at /home/node/d20-api-server/api.js:1763:12 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) at Kd (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:546) at Id.Mb (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:93:489) at Ld.Mb (/home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:94:425) at /home/node/d20-api-server/node_modules/firebase/lib/firebase-node.js:111:400 The error. The script is from this video: <a href="https://www.youtube.com/watch?v=S_D0QrIE1Zo&amp;ab_channel=NickOlivo" rel="nofollow">https://www.youtube.com/watch?v=S_D0QrIE1Zo&amp;ab_channel=NickOlivo</a> I used this multiple times a few months ago, now I came back to my game and it no longer works.
1726728904
keithcurtis
Forum Champion
Marketplace Creator
API Scripter
Hi Blud! Does the selected token represent a character? It looks like the script expects that. Also, have you moved your game to Jumpgate, loaded the DnD2024 sheet, or switched from classic to experimental on your mod page?
I have not moved to jumpgate, loaded the dnd2024 sheet, nor switched off classic. and the Token selected does indeed represent a character.
on("chat:message",function(msg){ &nbsp; &nbsp; if(msg.type=="api" &amp;&amp; msg.content.indexOf("!spiritualWeapon")==0) &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; var selected = msg.selected; &nbsp; &nbsp; &nbsp; &nbsp; if (selected===undefined) &nbsp; &nbsp; &nbsp; &nbsp; { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat("API","Please select a character."); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; var tok = getObj("graphic",selected[0]._id); &nbsp; &nbsp; &nbsp; &nbsp; var character = getObj("character",tok.get("represents")); &nbsp; &nbsp; &nbsp; &nbsp; var player = getObj("player",character.get("controlledby")); &nbsp; &nbsp; &nbsp; &nbsp; createObj("graphic",{ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; left:tok.get("left")+70, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; top:tok.get("top"), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; height:70, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; width:70, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pageid:tok.get("pageid"), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; layer:"objects", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; imgsrc:"<a href="https://s3.amazonaws.com/files.d20.io/images/373246253/CQRL9dANE2P9x0hq5Y82rg/original.webp?17039019515" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/373246253/CQRL9dANE2P9x0hq5Y82rg/original.webp?17039019515</a>", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name:tok.get("name") + "'s Spiritual Weapon", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; controlledby:player.get("id"), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; aura1_radius:0, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; aura1_color:"#ffff00", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; showplayers_aura1:true &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; sendChat(tok.get("name"),"Spiritual Weapon"); &nbsp; &nbsp; &nbsp; &nbsp; spawnFx(tok.get("left")+70,tok.get("top"),"burst-holy",tok.get("pageid")); &nbsp; &nbsp; } The script itself ^
1726754664
timmaugh
Pro
API Scripter
It could be that your controlledby property has more than one entry, or is set to "all players". Either way, you're not going to get a player in that case. To be sure you're going to get a player, you should split the controlledby property on commas, then filter out "all": let player = getObj("player", character.get("controlledby").split(/\s*,\s*/).filter(c =&gt; c.toLowerCase() !=== 'all')[0]); Of course, you don't actually need to go this far, since the only reason you're getting the player in the first place is to get the id... which is already in the controlledby property. So you could instead just do: let playerID = character.get("controlledby").split(/\s*,\s*/).filter(c =&gt; c.toLowerCase() !=== 'all')[0]; ...and then, later in the createObj function, just use this playerID variable directly: controlledby: playerID, That will make it so you don't have to get the player object in the first place, however, you would still want to test whether the filtering of the controlledby string even returned anything: let playerID = character.get("controlledby").split(/\s*,\s*/).filter(c =&gt; c.toLowerCase() !=== 'all')[0]; if (!playerID || !playerID.length) { // ...send message to chat return; } Once you go this far, though, I have to wonder whether there's even worth in filtering the controlledby property at all...? If the original character is set to be controlled by "all," shouldn't the spiritual weapon you are spawning be controlled by all, as well? If that's the case, you can skip the playerID assignment altogether and just refer to the controlledby property directly in the createObj function: controlledby: character.get("controlledby"), Give it a whirl and let us know.
1726792507
Nick O.
Forum Champion
Hi Blud!&nbsp; Timmaugh's answer is spot on, this typically happens when the character sheet can be controlled by more than one player. This video shows one approach to address that -&nbsp; <a href="https://www.youtube.com/watch?v=OvVT9ZKtjcI" rel="nofollow">https://www.youtube.com/watch?v=OvVT9ZKtjcI</a> , but honestly, I think Timmaugh's is probably better.&nbsp; Happy gaming!
if someone could show me how the block of code should look like, that'd be great, I am a suuuuper rookie at this lol
1726802173
timmaugh
Pro
API Scripter
Sure, Blud, try this: on("chat:message", function (msg) { &nbsp; &nbsp; if (!(msg.type == "api" &amp;&amp; msg.content.indexOf("!spiritualWeapon") == 0)) { return; } &nbsp; &nbsp; if (!(msg.selected &amp;&amp; msg.selected.length)) { &nbsp; &nbsp; &nbsp; &nbsp; sendChat("API", "Please select a character."); &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; } &nbsp; &nbsp; let selected = msg.selected; &nbsp; &nbsp; let tok = getObj("graphic", selected[0]._id); &nbsp; &nbsp; let character = getObj("character", tok.get("represents")); &nbsp; &nbsp; if (!character) { &nbsp; &nbsp; &nbsp; &nbsp; sendChat("API", "Please select a character."); &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; } &nbsp; &nbsp; createObj("graphic", { &nbsp; &nbsp; &nbsp; &nbsp; left: tok.get("left") + 70, &nbsp; &nbsp; &nbsp; &nbsp; top: tok.get("top"), &nbsp; &nbsp; &nbsp; &nbsp; height: 70, &nbsp; &nbsp; &nbsp; &nbsp; width: 70, &nbsp; &nbsp; &nbsp; &nbsp; pageid: tok.get("pageid"), &nbsp; &nbsp; &nbsp; &nbsp; layer: "objects", &nbsp; &nbsp; &nbsp; &nbsp; imgsrc: "<a href="https://s3.amazonaws.com/files.d20.io/images/373246253/CQRL9dANE2P9x0hq5Y82rg/original.webp?17039019515" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/373246253/CQRL9dANE2P9x0hq5Y82rg/original.webp?17039019515</a>", &nbsp; &nbsp; &nbsp; &nbsp; name: tok.get("name") + "'s Spiritual Weapon", &nbsp; &nbsp; &nbsp; &nbsp; controlledby: character.get("controlledby"), &nbsp; &nbsp; &nbsp; &nbsp; aura1_radius: 0, &nbsp; &nbsp; &nbsp; &nbsp; aura1_color: "#ffff00", &nbsp; &nbsp; &nbsp; &nbsp; showplayers_aura1: true &nbsp; &nbsp; }); &nbsp; &nbsp; sendChat(tok.get("name"), "Spiritual Weapon"); &nbsp; &nbsp; spawnFx(tok.get("left") + 70, tok.get("top"), "burst-holy", tok.get("pageid")); }); That uses the approach that I mentioned right at the end of my previous post -- that you might as well just duplicate the entire controlledby property for the weapon, since anyone who has control of the character should be able to control the weapon. If you wanted to go the other route (limit it to a single player), post back and we can give you the alternate version.
1726871185

Edited 1726871961
Blud
Pro
Okay, now whenever I do it, whether I have a token selected or not, it just says please select a character, the console is not spitting out any errors however
1726927244
timmaugh
Pro
API Scripter
OK, this is working for me, except I had to change the size of the image for the imgsrc property to be "thumb" rather than "original". But, in any case, here is a version with more specific complaints about what you're missing. on("chat:message", function (msg) { &nbsp; &nbsp; if (!(msg.type == "api" &amp;&amp; msg.content.indexOf("!spiritualWeapon") == 0)) { return; } &nbsp; &nbsp; if (!(msg.selected &amp;&amp; msg.selected.length)) { &nbsp; &nbsp; &nbsp; &nbsp; sendChat("API", "Please select a token."); &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; } &nbsp; &nbsp; let selected = msg.selected; &nbsp; &nbsp; let tok = getObj("graphic", selected[0]._id); &nbsp; &nbsp; let character = getObj("character", tok.get("represents")); &nbsp; &nbsp; if (!character) { &nbsp; &nbsp; &nbsp; &nbsp; sendChat("API", "The chosen token must represent a character."); &nbsp; &nbsp; &nbsp; &nbsp; return; &nbsp; &nbsp; } &nbsp; &nbsp; createObj("graphic", { &nbsp; &nbsp; &nbsp; &nbsp; left: tok.get("left") + 70, &nbsp; &nbsp; &nbsp; &nbsp; top: tok.get("top"), &nbsp; &nbsp; &nbsp; &nbsp; height: 70, &nbsp; &nbsp; &nbsp; &nbsp; width: 70, &nbsp; &nbsp; &nbsp; &nbsp; pageid: tok.get("pageid"), &nbsp; &nbsp; &nbsp; &nbsp; layer: "objects", &nbsp; &nbsp; &nbsp; &nbsp; imgsrc: "<a href="https://s3.amazonaws.com/files.d20.io/images/373246253/CQRL9dANE2P9x0hq5Y82rg/thumb.webp?17039019515" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/373246253/CQRL9dANE2P9x0hq5Y82rg/thumb.webp?17039019515</a>", &nbsp; &nbsp; &nbsp; &nbsp; name: tok.get("name") + "'s Spiritual Weapon", &nbsp; &nbsp; &nbsp; &nbsp; controlledby: character.get("controlledby"), &nbsp; &nbsp; &nbsp; &nbsp; aura1_radius: 0, &nbsp; &nbsp; &nbsp; &nbsp; aura1_color: "#ffff00", &nbsp; &nbsp; &nbsp; &nbsp; showplayers_aura1: true &nbsp; &nbsp; }); &nbsp; &nbsp; sendChat(tok.get("name"), "Spiritual Weapon"); &nbsp; &nbsp; spawnFx(tok.get("left") + 70, tok.get("top"), "burst-holy", tok.get("pageid")); }); That should prompt you to select a token if you don't have one selected. If you select a token that doesn't represent a character, it will tell you the token has to represent a character. I think that might be what you were running into (selecting a token that doesn't represent a character) because, like I said, this works in my game.
How does one insure your token represents a character? just that they can be edited and controlled right? &nbsp;
1726978450
timmaugh
Pro
API Scripter
No... control rights govern what Players can interact with and edit the character or token. Your screenshot was of a character. The "represents" property is on the token. Open a token's property window and you'll see this: Use that Represents Character to choose the character that the token actually represents. If it says "None/Generic Token" there, then that token does not actually represent the character. It can still be used as the default token for a character even though it doesn't have the character's name in this field (it actually stores the character's ID, but you'll see the name). That is, the character can have designated for it a default token which doesn't actually point back to the character in the represents field. You might find you have a few characters in this condition -- if you didn't know about the need to configure the token to represent the character it's easy to leave multiple characters so configured. It is easy enough to fix: once you've chosen the represented character in the drop down (and configured anything else about the token (like bar linkages, etc.), use the "Update Default Token" button to update the token info the sheet will use the next time you want to drag that character out onto the map. (The "Update Default Token" button is disabled in my screenshot, above, but becomes enabled when you select a character in the drop down).
thank you so much!