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 .
×
Why do rogues wear leather armor? Because it’s made of hide. 🥷

[Help] Detect if a token is in range of an active light source

Hello all. As the title says, I'm looking for a solution to automatically determine if a token is in range of an active light source. The background is that there is a Gloomstalker Ranger playing in my group who can only be seen under certain conditions - in our case, mostly when he is in bright light. Currently, I'm using a token-flip macro that makes him visible and invisible to the other players at the touch of a button. It would be nice if this could be automated. I dare to do the programming, but, if the implementation is at all possible, I would appreciate a hint on the right direction. Thanks in advance!
1643744942
timmaugh
Roll20 Production Team
API Scripter
You might be able to use the It's A Trap! script to tie a trap into each light-source... and then use the token-flip macro as the "consequence" of springing the trap. If the token moves within range of the trap, your macro fires. I'm not much more fluent in the IaT script than that, however.
1643748380
The Aaron
Roll20 Production Team
API Scripter
That sounds like a fun project!  There are many things you might consider doing for the sake of efficiency, but I'd probably start by being able to toggle a token of interest (you can look at Here or Here for examples), then watch for that token changing location using an on('change:graphic',...) call.  When they move, find all the tokens that have light sources on their page, then check the distance between them and the light emitting token, and check if it's within the bright light emit distance, if it is, prompt for a flip.   That will get you about 90% of the solution.  The last 10% is determining if they are actually in the light due to DL blocking the light.  That part's quite a bit harder, so you might tackle it after you get the above part working.
1643751998
timmaugh
Roll20 Production Team
API Scripter
ah... missed that you were looking to do the coding, yourself. Forget everything I just said.
1643805821

Edited 1643805880
David M.
Pro
API Scripter
Line of sight testing is a pain, but possible. If you enjoy wading through a morass of poorly written spaghetti code, you can check out my Radar script which does this. It's in one-click, you would want to "import" it to see the code. Look for the  isLoSBlocked function and the code leading up to where it is called to see how I gathered the path segments and performed the checks. Note that this particular script tests five points on each token (center and corners) relative to an origin point. All five points must be blocked by DL lines to be considered out of LoS. You could modify that logic as you'd like.  
Thank you all very much. Thanks to your hints and the code, I now have a clue where to start on Sunday.  I think it will be a combination of The Aaron's tip and David's LoS solution. Detect which light sources have a line of sight to the player token and then measure the distance to decide if the token is in the light or not. At least in the first attempt. The D&D adventure is set in the Dungeon of the Mad Mage, which has quite a few light sources in parts, but I'll just be surprised which problem I run into first. :) Thanks again, for your kind advice!
1643811704
The Aaron
Roll20 Production Team
API Scripter
That sounds like a great start, save that I would reverse you checks and do distance first. (Note, squared distance is much more efficient.). LoC calculations will be much more expensive, so saving those for just the light sources they are in the radius of is better. 
1643815758

Edited 1643815792
The Aaron
Roll20 Production Team
API Scripter
You could make use of this function:&nbsp; <a href="https://app.roll20.net/forum/permalink/10661153/" rel="nofollow">https://app.roll20.net/forum/permalink/10661153/</a> With a filter/predicate function that checks if the object is a token that emits light and has a bright light radius greater than the distance.&nbsp;
1643817261
The Aaron
Roll20 Production Team
API Scripter
This should get you the first part: class Util { static Roll20Type(o) { const validTypes = [ 'ability', 'attribute', 'campaign', 'card', 'character', 'deck', 'graphic', 'hand', 'handout', 'jukeboxtrack', 'macro', 'message', 'page', 'path', 'player', 'rollabletable', 'tableitem', 'text', 'token' ]; if('function' === typeof o.get){ let t = o.get('type'); if(validTypes.includes(t)){ return t; } } } static Roll20MapObjectType(o) { const validTypes = ['path','text','graphic']; let t = Util.Roll20Type(o); if(validTypes.includes(t)){ return t; } } } const findNearObjs = (location, predicate=()=&gt;true, filterProps={}) =&gt; { let x=0; let y=0; let pageid = Campaign().get('playerpageid'); let pred = predicate; if(Util.Roll20MapObjectType(location)){ pred = (o,d)=&gt;location.id !== o.id &amp;&amp; predicate(o,d); x = location.get('left'); y = location.get('top'); pageid= location.get('pageid'); } else { x = location.x || x; y = location.y || y; pageid = location.pageid || pageid; } const distSq = (obj) =&gt; Math.pow((obj.get('left')-x),2)+Math.pow((obj.get('top')-y),2); const compareDistSq = (a,b) =&gt; a.distSq-b.distSq; return findObjs({ pageid, ...filterProps }) .map(o=&gt;({distSq:distSq(o),object:o})) .filter((o)=&gt;pred(o.object,o.distSq)) .sort(compareDistSq); }; const brightLightFilter = (o,distSq)=&gt; (o.get('emits_bright_light') &amp;&amp; Math.pow(o.get('bright_light_distance'),2)&gt;distSq); // for some token: let candidates = findNearObjs(token,brightLightFilter,{type:'graphic'});
Wow what a great idea ! All that could be of great use and i foresee a lot of developments possible. Something like the paladins various auras.. I know that there was a good try from another roll20 former user, but it would be great if an in-range ally of a paladin could see its bonus toggled on the sheet or removed if out of range. Really wish I wasn't that old and busy to start learning how to code haha
As a DM with a Gloomstalker *and* a Shadow Monk in the party, this would be an incredible tool to have!
Hello again. Thanks for your support and also for the code, The Aaron. Since it's my first contact with the Roll20 API, away from using ready-made projects, I had to get to grips with the object model a bit first. So it's also a learning project for me, which is why I'm trying to do as much as possible myself, which in turn will probably lead to messy solutions to already long-solved problems. My current state is that a token is set as "main token", whose name is stored in a state variable, so that then always the appropriate token ID can be used when changing pages. When entering a page or updating the main token, the system looks which tokens on the current page emit light and how big their distance to the "main token" is. Everything still divided into single code-snippets and not polished. @TheAaron. Thanks for your code fragments. I'll take a closer look at them tonight and take the opportunity to get a little more familiar with the javascript synatx. To be honest, coming from C#, I was hoping to get into JS faster. But I see it as a good opportunity to learn something new. :)
1644161270

Edited 1644161313
The Aaron
Roll20 Production Team
API Scripter
No problem. I'll drop some links here later to some helpful learning javascript forum threads.&nbsp; Real quick though, token ids are unique to a given graphic instance, so the same graphic on a different page, or even other copies on the same page, will have a different id. You'll probably want to store the character id, and deal with tokens that have that as their represents value.&nbsp;
1644165798
The Aaron
Roll20 Production Team
API Scripter
I recommend&nbsp; Javascript: the Good Parts &nbsp; by Douglas Crockford &nbsp;for some early knowledge.&nbsp; Here's some links to Roll20 specific stuff: <a href="https://app.roll20.net/forum/post/6605115/namespaces-novice-seeks-help-exploring-the-revealing-module-pattern" rel="nofollow">https://app.roll20.net/forum/post/6605115/namespaces-novice-seeks-help-exploring-the-revealing-module-pattern</a> <a href="https://app.roll20.net/forum/post/6584105/creating-an-object-that-holds-specific-character-dot-id-and-character-name/?pagenum=1" rel="nofollow">https://app.roll20.net/forum/post/6584105/creating-an-object-that-holds-specific-character-dot-id-and-character-name/?pagenum=1</a> <a href="https://app.roll20.net/forum/post/6237754/slug%7D" rel="nofollow">https://app.roll20.net/forum/post/6237754/slug%7D</a>
I haven't thought about the way of taking the character ID as a base and then looking for their associated tokens. Probably this is the better solution, because this way the script still works when the token is renamed. And the probability that a character is represented by two tokens should not be so big. So far I have solved it like this: function getTokenId(Token-Name, (Page-ID)){ return Token-ID; }
Following. Please let me know if you get this working. I am looking for a similar solution. In Pathfinder, I have a character who is dazzled when in bright light. If there is code that will determine if he is under bright light, then I can easily modify it to add the dazzled condition when he is.&nbsp;