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

[Help] Custom HP/SP/Other bars?

Hello, I'm currently running a game based on Persona, another one of my player is also running his own game (In fact, he made most of the system himself, so props to him.) To deal with the rather large amount of macros the system use, I made a custom sheet for it, which we're using for both of our games, and since I'm already kinda deep in it, I've been wondering, is there a way to create a custom HP/SP or whatever bar via the API to set either under a token, or on the map itself, that can be edited to look how you see fit? I would like to have something similar to this   I just don't know if that's possible via the API, or even how to start doing that. Thanks.
1461331872
The Aaron
Pro
API Scripter
There are ways of approximating what you have there, but it would be unlikely to be satisfactory and would require a large amount of work for very little payoff.  What problem are you trying to solve with this?
It's not really trying to solve a problem as much as it is my habit of trying to replicate the aesthetics of the game we're basing the system from, really. I did do a "large amount of work for very little payoff" too without even using the API when I couldn't use it just so I could have some neat effects or pull a complete change in the gameplay style for the sake of a single boss before, including multiple pictures between each other for a slide show, etc etc. It's not particularly important to have it work to play the game, It's just that I wanted something neat for my players, which is basically the reason for all the stuff I described above anyway. I can do without, it's just that I'd prefer to be able to have such a HP/SP bar if that's possible.
1461334330
The Aaron
Pro
API Scripter
ok.  I can point you in the right direction if you want to give it a go. =D The basic idea is to create several graphic objects with the API and have them follow the token around and update as needed.  You can look at my Facing script, for the basic idea.  From your example image, I'm guessing you'd basically need 5 objects: The Background Image (no bards or numbers, just the space to house them. Use the API to keep it positioned at some offset from the token it represents. A Yellow Bar Positioned relative to the Background Image Scaled relative to one of the Bars A Green Bar Positioned relative to the Background Image Scaled relative to one of the Bars A Text Object (top) Positioned relative to the Background Image Value based on one of the Bars A Text Object (bottom) Positioned relative to the Background Image Value based on one of the Bars When the Token is changed: On a Move: Adjust the position of the Background Image Adjust all the bars and text relative to it. On a Bar Change Adjust the width of the bar that corresponds to it Adjust the value of the text object that corresponds to it You'll need to pay special attention to the sort order on the page for each of those objects.  The Background Image will need to be below the other 4, but you may want to have it above everything else, which means it will be on the Object Layer.  You'll also want to hook the modify events on your created graphics and text objects in order to prevent them from being accidentally moved/edited/deleted.
Thanks for your help, I'll see what I can do despite never really using the API save for some pre-made scripts. Hopefully I can get this to work.
Well, sorry to ask that, but if that's not a problem, i'd like an example if that's possible. Because as much as I'm trying, barely having any knowledge in coding really doesn't help with using the API. I know how should it work , but I have no idea how to code it to make it work that way. I don't even know how to make simple text appear or make the background image appear at all, even less making it appear near a specified token, or how to link it, linking the bars to anything, etc etc. I read the wiki for the API and tried to check other scripts for similar ideas on how to make this work, but it's really hard to wrap my head around it. Having some examples on how to make this work would be great, if that's not an issue.
1461344109

Edited 1461344950
The Aaron
Pro
API Scripter
Sure, i'll spew forth a few real quick. Maybe I can add some more to the API Wiki. Making Text on the current player page. // on() registers a function to call for an event. The 'ready' event occurs when the API has finished starting up. on('ready',function(){ "use strict"; // This creates a text object on the current player page with the text "Text Text!" in the top left corner. // This will happen each time the API starts up, so in a real script, you likely would want to look for some condition // before creating, such as whether the text already exists on that page. createObj('text',{ pageid: Campaign().get('playerpageid'), text: 'Text Text!', left: 70, top: 70, layer: 'objects' }); }); Making a label on the current page that moves to where an object is: on('ready',function(){ "use strict"; // As above, this will get created ever time the API starts up, not production ready! var text=createObj('text',{ pageid: Campaign().get('playerpageid'), text: 'Movement here!', left: 70, top: 70, layer: 'objects' }); // 'change:graphic' is another event that happens whenever an object of type 'graphic' gets changed // When a graphic is changed in any way, this will get called on('change:graphic',function(obj,prev){ // checking to see if the object changed is on the same page. // * (not checking if it moved, which might need to happen) // * (not checking if my text object still exists, which would need to happen) if(obj.get('pageid') === text.get('pageid')){ // moving the text object to the same place as the token text.set({ left: obj.get('left'), top: obj.get('top') }); } }); }); Both of these should work out of the box (I didn't text them though).  Neither of them has all the checking you'd really want to do, but they are simple and demonstrate 1) creating objects and 2) reacting to events of other objects. Play with those and see what questions you have and let me know.
For some reason, even if I do nothing by copypaste the first or second script, I get a  SyntaxError: Unexpected token ILLEGAL error, and I have no idea what's causing this.
1461344980
The Aaron
Pro
API Scripter
Oops, sorry!  That was my mistake.  I left the closing ' off of the ready event.  I've corrected the above examples, give them another try!
Oh, it works properly now. I'll have to play around some more to see how to make this work, next step is to make it a graphic (the background bar), and then figuring out how to make text represent a value on the token... And then how to make it so the value on the token also change the size of the bar. Oh boy, I have no idea where to start with this.
Well, even trying to make it a graphic seems out of my grasp somehow. I'm not exactly sure what's causing that, once again, though that one is obviously my fault. I tried to check for examples on other scripts, but I can't seem to get it to work anyway. It's probably something simple that I can't even notice, too.
1461352006
The Aaron
Pro
API Scripter
Need a comma after the URL string.  Try posting your code in JSLint or the Google closure compiler. I'll get you links when I'm back at my desk. 
Well, I found the compiler, and now there's no error. I actually managed to make it work, wow. Now I can properly make the picture appear as it should. I just have to make it rotate and stretch as it's needed, of course, but otherwise it follows as it should. That's progress. Though I'll have to find out how to make it appear when needed, as there's 12 characters that need the bar in my game but only three fight at a time rather than everyone at once, but in the other GM's game, there's always only 4 characters so that's probably simpler. So basically I need to figure out : *How to make the HP and SP bar that follows the background picture, and also make the text, with the bars shrinking the less HP and SP there is while the text show the numerical value *Find a way to create "clones" of the bar that follow the other tokens and take in the values of the other tokens since there's more than one character *Find a way to trigger the creating when It's necessary, so probably something like putting the token on the battle screen
1461354722
The Aaron
Pro
API Scripter
Maneater M. said: I just have to make it rotate and stretch as it's needed, of course, but otherwise it follows as it should. Rotation is an attribute on the graphic, that's going to make positioning sub graphics relative to the base complicated, but it's all math you can lookup on the internet.   Stretching, if you mean change of size is just managed via the width and height properties.  Your bars should be as easy as adjusting the width based on the ratio of bar current to bar maximum. Skewing (if that's what you mean by stretching) is not available in the API. Maneater M. said: That's progress. Though I'll have to find out how to make it appear when needed, as there's 12 characters that need the bar in my game but only three fight at a time rather than everyone at once, but in the other GM's game, there's always only 4 characters so that's probably simpler. That's a general programming question.  You need to think about what events cause it to be shown and hidden, and then trap for those events.  You could toggle it on based on a statusmarker on a token, which would be pretty easy to keep track of, or use an API command.  Either way, you'll likely need to learn about the state object which provides persistent storage between API restarts. Maneater M. said: So basically I need to figure out : *How to make the HP and SP bar that follows the background picture, and also make the text, with the bars shrinking the less HP and SP there is while the text show the numerical value *Find a way to create "clones" of the bar that follow the other tokens and take in the values of the other tokens since there's more than one character *Find a way to trigger the creating when It's necessary, so probably something like putting the token on the battle screen Probably you'll need to store an object in state which keeps the relationship between a token -> background object -> [Text objects, bar objects].  Changes to a token then would cascade through that relationship to update each of the dependant objects. Consider creating functions that abstract the operations you want to perform.  Write the code assuming each of them do the right thing, then make them do it. /* ... */ function addStatGraphicToToken(id){ // checks if id is in the state // creates base and related objects and adds their ids to the state }; function updateStatGraphicOnChange(id){ log('updateStatGraphicOnChange: '+id); // find the id in the state // loads the objects dependant on that id // makes changes to each }; on('change:graphic', function(obj,prev){ updateStatGraphicOnChange(obj.id); }); /* ... */ etc.  Ask questions, read the wiki, look at existing scripts.   =D
Well, I have to say that looking at existing scripts and the wiki doesn't help that much even if I keep checking it, because I tried but I'm going from zero on that, so most things are completely nebulous to me. For the "separate HP and SP bar per token", I've been trying to make the background be created upon a new token being put on the battle map for a start. It works, sure, and it then moves to the token due to the code set up below, and when you put another token, it creates another, but also drag the first background alongside the second token since it's not "separated". You say to create a state that keeps the relationship of the things used, but I don't have a single idea how to make this work, how to link the created background to the token that created it only, or how to even use that state thing in the first place.  I've been looking around for a fair amount of hours and I still really don't know how to handle the worst of it due to my lack of knowledge, which make the entire thing really complicated.
1461380875
The Aaron
Pro
API Scripter
I can certainly understand how you might be getting frustrated. It is a difficult problem to attempt to solve.  I'll try to get you some examples of using the state object tomorrow. The state object is a global simple object that all scripts have access to. You have to respect other scripts. Generally you create a property on the state object that will house your stored data: on('ready',function(){ 'use strict'; // create state namespace if(!_.has(state,'maneater')){ state.maneater={ tokens: {} }; } }); Then you can store details about tokens you are decorating in state.maneater.tokens. Use the token ID as the property and store the ids of each of the dependent objects there. On a change, look up the ID of the changed token to get the ids of the followers, etc. 
Alright, just woke up. Thanks for the example, time to see what I can do with this.
1461429757
The Aaron
Pro
API Scripter
Looks like I already wrote a pretty comprehensive guide to the state object here: &nbsp; <a href="https://wiki.roll20.net/API:Objects#state" rel="nofollow">https://wiki.roll20.net/API:Objects#state</a> Let me know if you find I've left anything out!
I still can't seem to figure out how to make it work, I'm such a pain. More precisely, I'm currently stuck on "making the background bar spawn upon token creation on a specific page that will automatically link the background bar to the token used and will only move when that token move" For now, the current code I have works when it comes to making the background bar spawn, and it automatically set itself to the proper position when the token is moved/created. (Direct link so the thread isn't filled with embedded pictures :&nbsp; <a href="http://puu.sh/ot4zn/a7da48300a.png" rel="nofollow">http://puu.sh/ot4zn/a7da48300a.png</a> ) However, if a second token is placed, the first background bar is going to move alongside the second bar that will be created. It's a small but important step to fix and I don't know how to use states to make it work.
1461449454

Edited 1461515934
The Aaron
Pro
API Scripter
I've not tested it, but something like this should work: on('ready',function(){ &nbsp; "use strict"; &nbsp; var leftOffset = 20, &nbsp; &nbsp; &nbsp; topOffset = 30, // creates a background object and adds relationship to the state &nbsp; addBackgroundBar = function(obj){ &nbsp; &nbsp; if(!_.has(state.maneater.tokens,obj.id)){ &nbsp; &nbsp; &nbsp; let bg=createObj('graphic',{ &nbsp; &nbsp; &nbsp; &nbsp; pageid: obj.get('pageid'), &nbsp; &nbsp; &nbsp; &nbsp; imgsrc: '<a href="https://s3.amazonaws.com/files.d20.io/images/18365129/ouWda8s3smxFGrIMd3GenA/thumb.png" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/18365129/ouWda8s3smxFGrIMd3GenA/thumb.png</a>', &nbsp; &nbsp; &nbsp; &nbsp; left: obj.get('left')+leftOffset, &nbsp; &nbsp; &nbsp; &nbsp; top: obj.get('top')+topOffset, &nbsp; &nbsp; &nbsp; &nbsp; width: 120, &nbsp; &nbsp; &nbsp; &nbsp; height: 30, &nbsp; &nbsp; &nbsp; &nbsp; rotation: -15, &nbsp; &nbsp; &nbsp; &nbsp; layer: 'objects' &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; state.maneater.tokens[obj.id]={ /* indexed by the token id for easy lookup */ &nbsp; &nbsp; &nbsp; &nbsp; tokenID: obj.id, /* token's id, useful to store here as well as the index */ &nbsp; &nbsp; &nbsp; &nbsp; bgID: bg.id /* id of the background image created for this token */ &nbsp; &nbsp; &nbsp; }; &nbsp; &nbsp; } &nbsp; }, /* updated the background image for this token */ &nbsp; updateBackgroundBar = function(obj){ // checks to see if there is a relationship in the state (eventually, you won't want to add these to everything...) &nbsp; &nbsp; if(_.has(state.maneater.tokens,obj.id)){ // gets the associated background image &nbsp; &nbsp; &nbsp; let bg=getObj('graphic',state.maneater.tokens[obj.id].bgID); // repositions it relative to the token &nbsp; &nbsp; &nbsp; bg.set({ &nbsp; &nbsp; &nbsp; &nbsp; left: obj.get('left')+leftOffset, &nbsp; &nbsp; &nbsp; &nbsp; top: obj.get('top')+topOffset &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; } &nbsp; }; // initializer for the state property maneater &nbsp; if(!_.has(state,'maneater')){ &nbsp; &nbsp; state.maneater={ &nbsp; &nbsp; &nbsp; tokens: {} &nbsp; &nbsp; }; &nbsp; } // catch the creation of graphics &nbsp; on('add:graphic', addBackgroundBar ); // catch the changing of graphics &nbsp; on('change:graphic', updateBackgroundBar ); }); Note that you don't want to register event handlers inside of event handlers (in the general case (there are some special reasons to do it but you'll know them when you get there)).
I added this code to the script, but this time, there's no error, however now the bar won't show up when I put a token down for some reason. I'm not sure why.
1461515654

Edited 1461515978
The Aaron
Pro
API Scripter
My imgsrc is not correct, just copy yours into there and it should work. &nbsp;Also, this code isn't reliant on what you've already written, it's stand alone. Edit: Oh, and I had ' create:graphic ', not ' add:graphic '. &nbsp;fixed that.
Oh jeez, now it's actually working how I wanted it to. Thanks. One of the major problem was fixed, getting closer to making this work. Now I have to make it so the HP and SP bars are set in the proper place when spawned (which shouldn't be too hard) and scale off the HP/SP value of the creator token.
1461517728
The Aaron
Pro
API Scripter
I suspect that keeping everything at the right depth will be the biggest next challenge. =D
Well, uh.... Turns out even just getting the HP and SP bar to spawn is a problem. It shouldn't have been too hard, just gotta make it work like the background bar and it's all fine, right? Guess I was wrong. on('ready',function(){ "use strict"; var leftOffset = 20, topOffset = 30, // creates a background object and adds relationship to the state addBackgroundBar = function(obj){ if(!_.has(state.maneater.tokens,obj.id)){ let bg=createObj('graphic',{ pageid: obj.get('pageid'), imgsrc: '<a href="https://s3.amazonaws.com/files.d20.io/images/18365129/ouWda8s3smxFGrIMd3GenA/thumb.png?1461339104" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/18365129/ouWda8s3smxFGrIMd3GenA/thumb.png?1461339104</a>', left: obj.get('left')+leftOffset, top: obj.get('top')+topOffset, width: 120, height: 30, rotation: -15, layer: 'objects' })}; addHPBar = function(obj){ if(!_.has(state.maneater.tokens,obj.id)){ let hp=createObj('graphic',{ pageid: obj.get('pageid'), imgsrc: '<a href="https://s3.amazonaws.com/files.d20.io/images/18365209/DnbjiCaANIFZ9lC-IIItRg/med.png?1461339385" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/18365209/DnbjiCaANIFZ9lC-IIItRg/med.png?1461339385</a>', left: obj.get('left')+leftOffset, top: obj.get('top')+topOffset, width: 120, height: 30, rotation: -15, layer: 'objects' })}; state.maneater.tokens[obj.id]={ /* indexed by the token id for easy lookup */ tokenID: obj.id, /* token's id, useful to store here as well as the index */ bgID: bg.id, /* id of the background image created for this token */ hpID: hp.id }; } }, /* updated the background image for this token */ updateBackgroundBar = function(obj){ // checks to see if there is a relationship in the state (eventually, you won't want to add these to everything...) if(_.has(state.maneater.tokens,obj.id)){ // gets the associated background image let bg=getObj('graphic',state.maneater.tokens[obj.id].bgID); // repositions it relative to the token bg.set({ left: obj.get('left')+leftOffset, top: obj.get('top')+topOffset }); } }; updateHPBar = function(obj){ if(_.has(state.maneater.tokens,obj.id)){ let hp=getObj('graphic',state.maneater.tokens[obj.id].hpID); hp.set({ left: obj.get('left')+leftOffset, top: obj.get('top')+topOffset }); } }; // initializer for the state property maneater if(!_.has(state,'maneater')){ state.maneater={ tokens: {} }; } // catch the creation of graphics on('add:graphic', addBackgroundBar ); on('add:graphic', addHPBar ); // catch the changing of graphics on('change:graphic', updateBackgroundBar ); on('change:graphic', updateHPBar ); }); I thought this would've worked, but sadly even just saving the code brings forth this. ReferenceError: updateHPBar is not defined at Object. (apiscript.js:1511:15) at eval (eval at (/home/node/d20-api-server/api.js:105:34), :65:16) at Object.publish (eval at (/home/node/d20-api-server/api.js:105:34), :70:8) at checkForReady (/home/node/d20-api-server/api.js:982:12) at /home/node/d20-api-server/api.js:1061: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) 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) So, uh, crap. It seems it doesn't recognize the updateHPBar as defined or something.
1461520479
The Aaron
Pro
API Scripter
It's because you have a semicolon instead of a comma after the preceding variable definition.&nbsp; I'd suggest putting all of the add and update in those two functions for simplicity and to avoid race conditions in their assignment to state.&nbsp;
1461521860

Edited 1461528591
on('ready',function(){ &nbsp; "use strict"; &nbsp; var leftOffset = 20, &nbsp; &nbsp; &nbsp; topOffset = 30, &nbsp; // creates a background object and adds relationship to the state &nbsp; addBar = function(obj){ &nbsp; &nbsp; if(!_.has(state.maneater.tokens,obj.id)){ &nbsp; &nbsp; &nbsp; let bg=createObj('graphic',{ &nbsp; &nbsp; &nbsp; &nbsp; pageid: obj.get('pageid'), &nbsp; &nbsp; &nbsp; &nbsp; imgsrc: '<a href="https://s3.amazonaws.com/files.d20.io/images/18365129/ouWda8s3smxFGrIMd3GenA/thumb.png?1461339104" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/18365129/ouWda8s3smxFGrIMd3GenA/thumb.png?1461339104</a>', &nbsp; &nbsp; &nbsp; &nbsp; left: obj.get('left')+leftOffset, &nbsp; &nbsp; &nbsp; &nbsp; top: obj.get('top')+topOffset, &nbsp; &nbsp; &nbsp; &nbsp; width: 120, &nbsp; &nbsp; &nbsp; &nbsp; height: 30, &nbsp; &nbsp; &nbsp; &nbsp; rotation: -15, &nbsp; &nbsp; &nbsp; &nbsp; layer: 'objects' &nbsp; &nbsp; &nbsp; }) &nbsp; &nbsp; &nbsp; let hp=createObj('graphic',{ &nbsp; &nbsp; &nbsp; &nbsp; pageid: obj.get('pageid'), &nbsp; &nbsp; &nbsp; &nbsp; imgsrc: '<a href="https://s3.amazonaws.com/files.d20.io/images/18365209/DnbjiCaANIFZ9lC-IIItRg/med.png?1461339385" rel="nofollow">https://s3.amazonaws.com/files.d20.io/images/18365209/DnbjiCaANIFZ9lC-IIItRg/med.png?1461339385</a>', &nbsp; &nbsp; &nbsp; &nbsp; left: obj.get('left')+leftOffset, &nbsp; &nbsp; &nbsp; &nbsp; top: obj.get('top')+topOffset, &nbsp; &nbsp; &nbsp; &nbsp; width: 120, &nbsp; &nbsp; &nbsp; &nbsp; height: 30, &nbsp; &nbsp; &nbsp; &nbsp; rotation: -15, &nbsp; &nbsp; &nbsp; &nbsp; layer: 'objects' &nbsp; &nbsp; &nbsp; }) &nbsp; &nbsp; }; &nbsp; &nbsp; &nbsp; state.maneater.tokens[obj.id]={ &nbsp;/* indexed by the token id for easy lookup */ &nbsp; &nbsp; &nbsp; &nbsp; tokenID: obj.id, &nbsp;/* token's id, useful to store here as well as the index */ &nbsp; &nbsp; &nbsp; &nbsp; bgID: bg.id, &nbsp;/* id of the background image created for this token */ &nbsp; &nbsp; &nbsp; &nbsp; hpID: hp.id &nbsp; &nbsp; &nbsp; }; &nbsp; }, /* &lt;=== that has to be a comma as the function is defined as a chain of variables */ &nbsp; /* updated the background image for this token */ &nbsp; updateBar = function(obj){ &nbsp; &nbsp; // checks to see if there is a relationship in the state (eventually, you won't want to add these to everything...) &nbsp; &nbsp; if(_.has(state.maneater.tokens,obj.id)){ &nbsp; &nbsp; &nbsp; // gets the associated background image &nbsp; &nbsp; &nbsp; let bg=getObj('graphic',state.maneater.tokens[obj.id].bgID); &nbsp; &nbsp; &nbsp; let hp=getObj('graphic',state.maneater.tokens[obj.id].hpID); &nbsp; &nbsp; &nbsp; // repositions it relative to the token &nbsp; &nbsp; &nbsp; bg.set({ &nbsp; &nbsp; &nbsp; &nbsp; left: obj.get('left')+leftOffset, &nbsp; &nbsp; &nbsp; &nbsp; top: obj.get('top')+topOffset &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; &nbsp; hp.set({ &nbsp; &nbsp; &nbsp; &nbsp; left: obj.get('left')+leftOffset, &nbsp; &nbsp; &nbsp; &nbsp; top: obj.get('top')+topOffset&nbsp; &nbsp; &nbsp; &nbsp; }); &nbsp; &nbsp; }; &nbsp; }; &nbsp;&nbsp; &nbsp; // initializer for the state property maneater &nbsp; if(!_.has(state,'maneater')){ &nbsp; &nbsp; state.maneater={ &nbsp; &nbsp; &nbsp; tokens: {} &nbsp; &nbsp; }; &nbsp; }; &nbsp; // catch the creation of graphics &nbsp; on('add:graphic', addBar ); &nbsp; // catch the changing of graphics &nbsp; on('change:graphic', updateBar ); }); Well I must be blind. I did set the add and updates into one function, but I'm probably too blind to notice what needs to be replaced, because I still see the updatebar error. I'm really not good at this.
1461528632
The Aaron
Pro
API Scripter
It's ok! &nbsp;I edited your code for simplicity and changed the ; to a , and left a comment where it was.
The bar now appear, but now once a token is set down, well... I get this and the script stop working. This is certainly confusing... Trial and error. ReferenceError: bg is not defined at addBar (apiscript.js:1490:15) at eval (eval at (/home/node/d20-api-server/api.js:105:34), :65:16) at Object.publish (eval at (/home/node/d20-api-server/api.js:105:34), :70:8) at TrackedObj.added (/home/node/d20-api-server/api.js:532:10) at updateLocalCache (/home/node/d20-api-server/api.js:899:18) at /home/node/d20-api-server/api.js:1035:11 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)
1461529511
The Aaron
Pro
API Scripter
let is block scoped, meaning bg is only defined inside the if block. &nbsp;That's fine because you only want to add to state if it isn't there already. &nbsp;I think you accidentally moved the state.maneater.tokens[obj.id]={ &nbsp;bit out of the if check when editing earlier.
1461529597
The Aaron
Pro
API Scripter
If you'd like even faster turnaround chat, join me in my Gitter: &nbsp; <a href="http://gitter.im/shdwjk/Roll20API" rel="nofollow">http://gitter.im/shdwjk/Roll20API</a> A bunch of API scripters hang out there and chat throughout the day.