We use Cookies to help personalize and improve Roll20. For more information on our use of non-essential Cookies, visit our Privacy Policy here.
Accept
Advertisement Create a free account

API doesn't register every chat message

So I have a token macro that I use for monsters with multiattack. I also have an api script that listens for an attack and performs a function. What I am noticing is that the API doesn't always trigger for each of the monster's individual attacks. I'm wondering if other people have run into this situation and have found a way to get the API to trigger on commands sent in quick succession from a macro. 
1491861364
Brian
Sheet Author
API Scripter
I've seen identical chat logs within a short time frame get squashed, but I've never seen the API fail to trigger for an event.
Here is some more information on what was going on when I encountered this situation. The macro for the multiattack One output : Second Output: In the first attempt for using the macro, only one of the attacks were picked up by my API Hitpoint Tracker script whereas in the second use of the macro all three attacks were registered.
1491965660
Scott C.
Forum Champion
Sheet Author
API Scripter
Kyle, can you link your code for the hitpoint tracker? Might be something in there to figure out what is going on.
Here is the link to the Github repository&nbsp; <a href="https://github.com/oukag/roll20-api-script" rel="nofollow">https://github.com/oukag/roll20-api-script</a> . The function that is not being triggered is inside Hitpoint Tracker version 2.4 - damageEventHandler. Thank you so much for taking a look at this.
1492006238

Edited 1492006293
Scott C.
Forum Champion
Sheet Author
API Scripter
Haven't dug too deep into it yet, but one thing I noticed is that you have a lot of on('chat:message',...): obj.registerEventHandlers = function() { on("change:token:bar1_value", updateHealthStatus); on("change:attribute:current", clearDeathSavingThrows); on("chat:message", handleModHealth); on("chat:message", handleToggleConcentration); on("chat:message", handleToggleRage); on("chat:message", deathSaveEventHandler); on("chat:message", hitDiceEventHandler); on("chat:message", secondWindEventHandler); on("chat:message", healingPotionEventHandler); on("chat:message", damageEventHandler); on("chat:message", songOfRestEventHandler); }; You might find that you'll have a performance improvement if you change to having a handleInput function to handle all chat messages. This is because all the on('chat:message') lines will be run for each chat message in sequence. This can delay the execution of the function you actually want. Having multiple on's would also cause a lot of duplicate handling and message manipulation.
Good to know, thanks for the tip.
1492007198

Edited 1492007213
The Aaron
Forum Champion
API Scripter
So, probably the issue is that you are modifying msg in some of your handlers. &nbsp;It's not obvious, but the msg object is shared between all handler objects, if you change it, it will be changed for the handlers that are called later. &nbsp;If you want to change the object for convenience, use _.clone() to make a copy.
1492007565

Edited 1492007595
Scott C.
Forum Champion
Sheet Author
API Scripter
I think that that might actually be what is causing your issue. Just using a basic script to log chat input, I can't get it to miss logging any chat messages. I am just a tyro though, so could be something I'm missing. EDIT: And Aaron has pointed out what I probably missed.
1492008191
The Aaron
Forum Champion
API Scripter
Well, I didn't try it out, but that's usually the problem when you get multiple chat handlers that don't seem to be working well together. &nbsp; It took me about a year to figure out that the msg object is shared. =D &nbsp;The design of isGM module was influenced by that, in fact. &nbsp;Powercards would strip the (GM) part off an api command message, so it was never there for isGM to do detection with, which is why isGM only did detection on non-api chat messages. =D &nbsp;
Thank you both so much for your help! Scott, I think that your suggestion was the issue. I condensed the handlers into a single handler function and now the API is triggered every time. Aaron. That is a great tip and thank you for pointing it out.&nbsp;
1492009010
The Aaron
Forum Champion
API Scripter
Rad. You're welcome. =D
1492009284
Scott C.
Forum Champion
Sheet Author
API Scripter
Glad my suggestion worked, but I think it was actually due to Aaron's explanation rather than mine. So, right solution, wrong reason.
1492009914
The Aaron
Forum Champion
API Scripter
It's a team effort. =D
1492019042
The Aaron said: So, probably the issue is that you are modifying msg in some of your handlers. &nbsp;It's not obvious, but the msg object is shared between all handler objects, if you change it, it will be changed for the handlers that are called later. &nbsp;If you want to change the object for convenience, use _.clone() to make a copy. But doesn't clone just make a shallow copy and still reference the original object? Currently trying to understand the differences between shallow and deep copies.
1492020042
Scott C.
Forum Champion
Sheet Author
API Scripter
Nope, that's what just doing equivalency does: var i = original i++ is the same as doing original++. whereas: var i = _.clone(original); i++ has no effect on original and original++ has no effect on i.
1492021128
I'm confused then... cause others are saying clone is shallow and if there are other references in that clone, they reference the original.
1492028280

Edited 1492028581
Jakob
Pro
Sheet Author
API Scripter
Sky said: I'm confused then... cause others are saying clone is shallow and if there are other references in that clone, they reference the original. It is a shallow clone. This means that properties are copied exactly, and if the properties are themselves references, only the reference will be copied. Example: let obj = { foo: { v: 1 }, bar: 1 }; let obj2 = _.clone(obj); obj2.bar = 2; obj2.foo.v = 2; log(obj.bar); // Will log 1 log(obj.foo.v); // Will log 2 This may actually be relevant, since the msg object has a bunch of object nested within, for example msg.inlinerolls or msg.selected.
1492028643
Scott C.
Forum Champion
Sheet Author
API Scripter
Thanks for that nice explanation Jakob. That does help explain it.
1492029305
Brian
Sheet Author
API Scripter
Sky said: I'm confused then... cause others are saying clone is shallow and if there are other references in that clone, they reference the original. Hope this helps: const original = { foo: { bar: 1 }, }; const shallowCopy = myShallowCopyFn(original); const deepCopy = myDeepCopyFn(original); // the following all evaluate to true shallowCopy !== original deepCopy !== original shallowCopy.foo === original.foo deepCopy.foo !== original.foo shallowCopy.foo.bar === original.foo.bar deepCopy.foo.bar === original.foo.bar So, if you have a shallow copy of msg: msg.who = msg.who.substring(...) // bad idea msgCopy.who = msgCopy.who.substring(...) // okay msg.inlinerolls.rolls = msg.inlinerolls.rolls.slice(0, 1) // bad idea msgCopy.inlinerolls.rolls = msg.inlinerolls.rolls.slice(0, 1) // also a bad idea
1492032356
Definitely something to keep in mind with my next project. Thanks all.