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

Need help with my Daylight Spell API script

I am attempting to create a Daylight spell that can be summoned by the spell caster. The API script calls a token image (modified from a tutorial by Nick Olivo). I added the lights language (from Roll20 "API Support For Dynamic Lighting" page) and attempted to meld the two. It appeared to work after my initial creation of the script (yesterday), but when I tried it today, the token image is summoned correctly, but the light settings are not turned in the token image settings.&nbsp; Instead, the API script changed the spell caster token light settings. I am not a programmer so I am at a loss on what to do at this point. I could turn the image lights settings on using Token-mod&nbsp; (which I set up and it worked), but that is a 2 -step process.&nbsp; I would like to simplify the process and use the API script for the whole thing if I can. Ideas and suggestions would be appreciated. The script I am using is shown below: on("ready",function() { &nbsp;&nbsp;&nbsp; on("chat:message",function(msg){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(msg.type=="api" &amp;&amp;msg.content.indexOf("!daylight")==0) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var selected = msg.selected; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (selected===undefined) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sendChat("API", "Please select a character."); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var tok = getObj("graphic",selected[0]._id); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var character = getObj("character",tok.get("represents")); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var player = getObj("player",character.get("controlledby")); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; createObj("graphic",{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; left:tok.get("left")+70, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; top:tok.get("top"), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; height:70, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; width:70, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pageid:tok.get("pageid"), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; layer:"objects", &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; imgsrc:"<a href="https://s3.amazonaws.com/files.d20.io/images/335812172/hA3aNp5bSqNng1aMEFxHvQ/thumb.png?168061740855" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/335812172/hA3aNp5bSqNng1aMEFxHvQ/thumb.png?168061740855</a>", &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; name:tok.get("name") + "'s Daylight", &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; controlledby:player.get("id"), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }); &nbsp;&nbsp;&nbsp;&nbsp; on("change:graphic", function(obj) { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; obj.set({ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; has_bright_light_vision: true, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; emits_bright_light: true, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bright_light_distance: 60, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; emits_low_light: true, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; low_light_distance: 120 &nbsp; }); });&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sendChat(tok.get("name"),"light's up the area with a daylight spell!"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; spawnFx(tok.get("left")+70,tok.get("top"),"nova-smoke",tok.get("pageid")); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;&nbsp;&nbsp; }); });
1680789529
David M.
Pro
API Scripter
I'd try setting the light setting properties when you define your object to create and then remove that on("change...") code block. Your script as written will also be vulnerable to crashing if, for example, the token does not represent a character or if controlledby is set to multiple players. So you'll want to check to make sure none of your variables are coming back "undefined", etc. Generally it's also a good idea to use let instead of var for variable definitions as well, to keep the scope of the variables limited to just the places they are used. With a simple script it's not a big deal, but hoisting with var might cause issues down the road if you try to re-use a variable name somewhere else, for example.&nbsp; Also, you might want to check out&nbsp; this thread &nbsp;where GiGs and The Aaron discuss namespaces, encapsulation, and coding structure best practices for your scripts moving forward.&nbsp; I'm sure folks with a lot more coding experience than I have could offer some better tips or better explanations of the reasons behind these conventions. This is just what I've picked up from poking around the forums and people helping me out the last couple years :) Finally, on the off chance that you are just looking for the functionality as opposed to this being a learning exercise, you might want to take a look at the&nbsp; Spawn&nbsp; script which can accomplish what you are doing with more generalization and options as opposed to having this very specific script. Otherwise, good luck with the coding! It's a very gratifying feeling when it all comes together!
1680789732
timmaugh
Forum Champion
API Scripter
Hey, Steve... I think your primary issue is that you have an event listener within an event listener (your graphic change listener is in your chat listener). Also, you don't need to use an event listener for a change to a graphic... in your case, you're creating the graphic that you want to have those properties, right? So you should* be able to just include your lighting parameters in the createObj property: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; createObj("graphic", { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; left: tok.get("left") + 70, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; top: tok.get("top"), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; height: 70, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; width: 70, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pageid: tok.get("pageid"), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; layer: "objects", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; imgsrc: "<a href="https://s3.amazonaws.com/files.d20.io/images/335812172/hA3aNp5bSqNng1aMEFxHvQ/thumb.png?168061740855" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/335812172/hA3aNp5bSqNng1aMEFxHvQ/thumb.png?168061740855</a>", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name: tok.get("name") + "'s Daylight", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; controlledby: player.get("id"), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; has_bright_light_vision: true, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; emits_bright_light: true, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bright_light_distance: 60, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; emits_low_light: true, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; low_light_distance: 120 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); * - I say "should" because this is valid javascript, but might run into a quirk of Roll20 scripting limitations around lighting. An alternative form would be to assign the results of the original createObj() function to a variable, and then use the obj.set() function out of the original graphic change function: &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let obj = createObj("graphic", { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; left: tok.get("left") + 70, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; top: tok.get("top"), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; height: 70, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; width: 70, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; pageid: tok.get("pageid"), &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; layer: "objects", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; imgsrc: "<a href="https://s3.amazonaws.com/files.d20.io/images/335812172/hA3aNp5bSqNng1aMEFxHvQ/thumb.png?168061740855" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/335812172/hA3aNp5bSqNng1aMEFxHvQ/thumb.png?168061740855</a>", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; name: tok.get("name") + "'s Daylight", &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; controlledby: player.get("id") &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; obj.set({ &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; has_bright_light_vision: true, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; emits_bright_light: true, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; bright_light_distance: 60, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; emits_low_light: true, &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; low_light_distance: 120 &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }); Either way, you no longer need the on('graphic:change') listener function at all.
1680794639
The Aaron
Roll20 Production Team
API Scripter
Here's how I might adjust your script: on("ready",() =&gt;{ on("chat:message",(msg) =&gt; { if(msg.type=="api" &amp;&amp; msg.content.indexOf("!daylight")==0) { let who = (getObj('player',msg.playerid)||{get:()=&gt;'API'}).get('_displayname'); let tok = getObj("graphic",(msg.selected||[{_id:null}])[0]._id); if(tok) { createObj("graphic",{ left : tok.get("left")+70, top : tok.get("top"), height : 70, width : 70, pageid : tok.get("pageid"), layer : "objects", imgsrc : "<a href="https://s3.amazonaws.com/files.d20.io/images/335812172/hA3aNp5bSqNng1aMEFxHvQ/thumb.png?168061740855" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/335812172/hA3aNp5bSqNng1aMEFxHvQ/thumb.png?168061740855</a>", name : tok.get("name") + "'s Daylight", controlledby : msg.playerid, emits_bright_light : true, bright_light_distance : 60, emits_low_light : true, low_light_distance : 120 }); sendChat(tok.get("name"),"light's up the area with a daylight spell!"); spawnFx(tok.get("left")+70,tok.get("top"),"nova-smoke",tok.get("pageid")); } else { sendChat('', `/w "${who}" Please select a token to summon Daylight for.`); } } }); });
Thank you all for you ideas. I will definitely check out David M.'s suggested links as I continue to try to improve my scripting skills. I tried using the Aaron's script as well as Tim's first suggested change. The token lights came on with the settings shown by the scripts, with the exception of the low_light_distance, which was set to zero with both scripts.&nbsp; I haven't has much time to troubleshoot the "why not" but hopefully I will be able to figure it out.&nbsp; In the meantime, I just set the bright light distance to 120 and deleted the two lines referencing the low-light settings. That seems to work okay, and I figured, "what the heck, its daylight", so bright light all the way! Thanks guys!
1680812904
The Aaron
Roll20 Production Team
API Scripter
Ah, I dug into it.&nbsp; Apparently, there's a bug where setting the low_light_distance at creation doesn't work.&nbsp; I've opened a ticket with the devs and provided reproduction steps.&nbsp; We had worked together to fix this for setting the low_light_distance on already created tokens, but hadn't looked at the creation side before. This version works: on("ready",() =&gt;{ on("chat:message",(msg) =&gt; { if(msg.type=="api" &amp;&amp; msg.content.indexOf("!daylight")==0) { let who = (getObj('player',msg.playerid)||{get:()=&gt;'API'}).get('_displayname'); let tok = getObj("graphic",(msg.selected||[{_id:null}])[0]._id); if(tok) { let dl = createObj("graphic",{ left : tok.get("left")+70, top : tok.get("top"), height : 70, width : 70, pageid : tok.get("pageid"), layer : "objects", imgsrc : "<a href="https://s3.amazonaws.com/files.d20.io/images/335812172/hA3aNp5bSqNng1aMEFxHvQ/thumb.png?168061740855" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/335812172/hA3aNp5bSqNng1aMEFxHvQ/thumb.png?168061740855</a>", name : tok.get("name") + "'s Daylight", controlledby : msg.playerid, emits_bright_light : true, bright_light_distance : 60, emits_low_light : true }); dl.set('low_light_distance',120); sendChat(tok.get("name"),"light's up the area with a daylight spell!"); spawnFx(tok.get("left")+70,tok.get("top"),"nova-smoke",tok.get("pageid")); } else { sendChat('', `/w "${who}" Please select a token to summon Daylight for.`); } } }); });
1680814292
timmaugh
Forum Champion
API Scripter
There it is. That's the kind of bug I didn't know about but half expected. There are a few other similar exceptions to setting properties at creation which are noted in the wiki, if I remember.
Wow - thank you both.&nbsp; You are fabulous Mr. "The Aaron"!! The script works very well....I appreciate you looking into this and making a script that works.
1680825943
The Aaron
Roll20 Production Team
API Scripter
No problem! =D