PDA

View Full Version : When can I trigger a addUnderlay after a token is added?



celestian
May 27th, 2020, 02:44
I've run into this ... tail chasing/chicken-egg problem.

The idea is to apply an underlay to a token in various situations.

When token added to image.
When the image is opened.
When effects change.

The problem seems to be that I cannot get it to properly add when the token is added. Either using Token.onAdd() or ImageControl.onTokenAdded().

Token.onAdd() triggers but it doesn't have a CT yet so getCTFromToken() wont work (I need this for effects).

ImageControl.onTokenAdded() has the same problem. Even when dragging from the CT onto the map it cannot find a valid from nodeCT using

local nodeCT = CombatManager.getCTFromToken(tokenCT); (tokenCT is valid).

The kludge I used to get around the image sending all this bogus "addToken()" without having the attached data... well I use Interface.onWindowOpened = onWindowOpened; and check for class imagecontrol. Yup it's ugly but there are no other options right now. Using that I am able to get a imagecontrol thats opened and size isn't 0/0 and the tokens are actually there and have matching nodeCTs.

However, I still need to have something that triggers when the token is added so that if they add a new N/PC that has an aura to the map it'll update the underlay. Right now, there isn't a way to do that.

What I need is some event I can attach to that triggers AFTER the token is placed and AFTER the image is setup and AFTER the nodeCT is connected.

Any such thing?

celestian
May 27th, 2020, 15:45
This is an example of what I've got working so far. The outstanding issues as I mentioned above are still there.


https://i.imgur.com/f67hC1k.gif

jackkerouac
May 27th, 2020, 17:07
Unfortunately, I cannot help, but I have to say - that's pretty cool so far.

Moon Wizard
May 29th, 2020, 21:07
The token add events are all triggered immediately on campaign load after loading all data and initializing all scripts. As far as I'm aware, this is exactly how the TokenManager script actually uses this information to generate all the widgets for tokens on the map at campaign load.

Regards,
JPG

celestian
May 29th, 2020, 21:32
The token add events are all triggered immediately on campaign load after loading all data and initializing all scripts. As far as I'm aware, this is exactly how the TokenManager script actually uses this information to generate all the widgets for tokens on the map at campaign load.

Regards,
JPG

The issue seems to be with the 2 events I mentioned above that when you try to getCTFromToken(tokenCT) it's nil. My only guess is the onAdd()/onTokenAdd() event is triggered before the token is linked back to the CT node but I'm only speculating since that code is outside of my view.

gamerhawaii
May 30th, 2020, 03:36
So I am sure you already tried this as your stuff is light years ahead of the trivial stuff I do, but I will throw it out there just in case. I had a similar problem of trying to catch when tokens were being added. I ended up looking for two things to see the token adds. One was the Token.onAdd as you say. The other was to add this to my onInit():



CombatManager.addCombatantFieldChangeHandler("tokenrefid", "onUpdate", onUpdateToken);


and then the onUpdateToken was:



function onUpdateToken(nodeField)
local combatTrackerNode = nodeField.getParent();
local token = CombatManager.getTokenFromCT(combatTrackerNode);
if (token) then
** do same stuff as Token.onAdd would do **
end
end


Between the Token.onAdd and this, I don't seem to ever miss tokens being added. Hopefully at least spawns an idea.

---
Sorry, forgot that I had to add a third thing to catch the token adds when an image/map was opened. I had to add a script to the imagewindow so I had to make a record_image.xml addition:


<root>
<windowclass name="imagewindow" merge="join">
<script file="campaign/scripts/scriptNameHere.lua" />
</windowclass>
</root>


and then the script was:


function onInit()
super.onInit();
addInitialTokens();
end

function addInitialTokens()
local tokens = image.getTokens();
for _,token in pairs(tokens) do
** do same stuff as Token.onAdd **
end
end



Anyway, sorry for interrupting when the grown ups are talking, but maybe with a natural 20 it can spark an idea that helps. :)

celestian
May 30th, 2020, 20:19
[QUOTE=gamerhawaii;514643]So I am sure you already tried this as your stuff is light years ahead of the trivial stuff I do, but I will throw it out there just in case. I had a similar problem of trying to catch when tokens were being added. I ended up looking for two things to see the token adds. One was the Token.onAdd as you say.

I did some testing trying your method. I ended up finding at least this event working.

CombatManager.addCombatantFieldChangeHandler("tokenrefnode", "onUpdate", onUpdateToken);

However, after that triggers the getCTFromToken returns nil when nodeCT from the above event is valid.

This was the function I used to test.



function onUpdateToken(nodeCT)
-- trim off .tokenrefnode
nodeCT = nodeCT.getParent();
Debug.console("manager_token_adnd.lua","onUpdateToken","nodeCT",nodeCT);
local tokenCT = CombatManager.getTokenFromCT(nodeCT);
Debug.console("manager_token_adnd.lua","onUpdateToken","tokenCT",tokenCT);
applyAura(nodeCT,tokenCT);
end


After that I decided to try and add a handler to image_record.lua where it would look for changes in image.tokens (onChildUpdate) but that never fired. Tried it down to just "image" and neither did that. I'm not entirely sure I can.



local node = getDatabaseNode().getParent();
DB.addHandler(DB.getPath(node, "scale"), "onUpdate", TokenManagerADND.applyAuras);
DB.addHandler(DB.getPath(node, "image"), "onChildUpdate", TokenManagerADND.onUpdateToken);


The "scale" handler does work, so not sure why the other wouldn't :( I was hoping to see when a image.tokens.*.id was updated and then trigger the update based on that (because I should be able to find things at that point?).

So, right now, I still can't find events where the needed data exists when triggered.

gamerhawaii
May 30th, 2020, 22:31
Hmm, I wonder if you are getting some other conflict with the 2E ruleset, though more likely I am still not understanding what you are doing. Attaching an extension that does not seem to miss adding tokens for me. I tested it with the 5E ruleset.

So as an example I had one map with two tokens already on it. Then I add a third token by dragging from the Combat Tracker.

From the debug below you can see what happened:
1) Before anything was ever opened (basically on FG initialization), I already get two calls from Token.onAdd for the two tokens. Both get a combat tracker node.
2) When I open the map, I get two more calls from the additional code I added to imagewindow. Both tokens get called and both get a combat tracker node.
3) When I drag a new monster from the Combat Tracker to the map, I get two events. One from Token.onAdd. It does NOT have a combat tracker node. However, immediately after that call is another for the same token via addCombatantFieldChangeHandler and it does get a combat tracker node.

36282

celestian
May 31st, 2020, 00:29
Hmm, I wonder if you are getting some other conflict with the 2E ruleset, though more likely I am still not understanding what you are doing. Attaching an extension that does not seem to miss adding tokens for me. I tested it with the 5E ruleset.

So as an example I had one map with two tokens already on it. Then I add a third token by dragging from the Combat Tracker.

From the debug below you can see what happened:
1) Before anything was ever opened (basically on FG initialization), I already get two calls from Token.onAdd for the two tokens. Both get a combat tracker node.
2) When I open the map, I get two more calls from the additional code I added to imagewindow. Both tokens get called and both get a combat tracker node.
3) When I drag a new monster from the Combat Tracker to the map, I get two events. One from Token.onAdd. It does NOT have a combat tracker node. However, immediately after that call is another for the same token via addCombatantFieldChangeHandler and it does get a combat tracker node.

36282

So, you are not incorrect. Your code works but using the same change handler() in my manager_token_adnd.lua doesn't work.



function onInit()
OOBManager.registerOOBMsgHandler(OOB_MSGTYPE_APPLY UNDERLAY, handleApplyUnderlay);
-- override this
CombatManager.handleFactionDropOnImage = handleFactionDropOnImage;

-- capture hover/click/target updates and tweak the CT/tokens.
Token.onHover = onHoverADND
Token.onClickDown = onClickDownADND;
Token.onTargetUpdate = onTargetUpdateADND
Token.onAdd = onAddADND
--Token.onContainerChanged = onContainerChangedADND;

--CombatManager.addCombatantFieldChangeHandler("tokenrefnode", "onUpdate", onUpdateToken);
CombatManager.addCombatantFieldChangeHandler("tokenrefid", "onUpdate", onUpdateToken);


---
OptionsManager.registerOption2("COMBAT_SHOW_RIP", false, "option_header_combat", "option_label_RIP", "option_entry_cycler",
{ labels = "option_val_on", values = "on", baselabel = "option_val_off", baseval = "off", default = "off" });
OptionsManager.registerOption2("COMBAT_SHOW_RIP_DM", false, "option_header_combat", "option_label_RIP_DM", "option_entry_cycler",
{ labels = "option_val_on", values = "on", baselabel = "option_val_off", baseval = "off", default = "off" });

CombatManager.addCombatantFieldChangeHandler("wounds", "onUpdate", updateHealth);
CombatManager.addCombatantFieldChangeHandler("tokenrefid", "onUpdate", updateHealth);

DB.addHandler("options.COMBAT_SHOW_RIP", "onUpdate", TokenManager.onOptionChanged);
DB.addHandler("options.COMBAT_SHOW_RIP_DM", "onUpdate", TokenManager.onOptionChanged);

-- for when options are toggled in settings.
DB.addHandler("options.COMBAT_SHOW_RIP", "onUpdate", updateCTEntries);
DB.addHandler("options.COMBAT_SHOW_RIP_DM", "onUpdate", updateCTEntries);

DB.addHandler("combattracker.list.*.effects", "onChildUpdate", updateAuras);

Interface.onDesktopInit = onDesktopInit
end


Where you see I added CombatManager.addCombatantFieldChangeHandler("tokenrefid", "onUpdate", onUpdateToken); there is also one for tokenrefnode. The tokenrefid never triggers but when using tokenrefnode it will (but doesn't contain the nodeCT).

I am unsure why it does not trigger when watching tokenrefid but does in your extension.

I've got a game coming up here in a few but will dig into this more when it's over.

Edit: As I submitted this and re-read it and looked over the code I see why... I am so blind...this is in the middle of the code I pasted for the onInit().

CombatManager.addCombatantFieldChangeHandler("tokenrefid", "onUpdate", updateHealth);

To be clear, once I ... tweaked that a little (trigger updateHealth() from the updateToken() function and removed the one called for updateHealth I was able to get the nodeCT and tokenCT... which resolves (I think) all my issues now.

Thanks for the assistance gamerhawaii, it has been invaluable.

jackkerouac
May 31st, 2020, 01:08
Are you going to fold all this into an extension? That would be awesome.