Thread Tools Display Modes
04/19/24, 02:39 PM   #1
Vilkasmanga
AddOn Author - Click to view addons
Join Date: Dec 2023
Posts: 8
Question on EVENT_JUSTICE_* firing

Hi, I've taken a few runs at this without success, would like some insight, if possible.

I'm trying to display a countdown of the remaining time for an active bounty. The display code works, my problem is that the event registers don't seem to be firing. (That is, the system-counter in the lower right corner updates but my Addon doesn't. However, if I manually call the update routine, everything aligns / works / displays values as expected.)

Perhaps I am calling the event handlers incorrectly?

Code:
EVENT_MANAGER:RegisterForEvent(FarmersToolkit.name,  EVENT_JUSTICE_BOUNTY_PAYOFF_AMOUNT_UPDATED , FarmersToolkit.UpdateActivities)
EVENT_MANAGER:RegisterForEvent(FarmersToolkit.name,  EVENT_JUSTICE_INFAMY_UPDATED , FarmersToolkit.UpdateActivities)
EVENT_MANAGER:RegisterForEvent(FarmersToolkit.name,  EVENT_JUSTICE_NO_LONGER_KOS , FarmersToolkit.UpdateActivities)
where FarmersToolkit.UpdateActivities just calls routines that update the screen contents as expected. Calling this manually via "/script" works so... the events aren't firing? (I suspect PAYOFF_AMOUNT_UPDATE is really all I need but threw the others in for giggles.)

Suggestions, insights welcome - thanks in advance.

-V

PS. Other events (like inventory updates) that call the UpdateActivities routine do correctly update the bounty counter section, I was just hoping to have the update occur without an unrelated triggering event?
  Reply With Quote
04/19/24, 04:03 PM   #2
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 5,015
Wrong forum, moved to the correct one.

Read here about how to see which events fire (by enabling an overall event listener):
https://www.esoui.com/forums/showthr...ighlight=track

Hope that helps to see for you if any of these events fire as the bottom-right bounty counter updates.
Else look into ZOs code how they update teh bounty counter.
To find it use mertorchbug or zgoo, move mouse above the control and ype /tbm or /tbugm or /tbug mouse or /tgoo mouse to inspect the control's name and then search the beginning of it, or parts of it, in ZOs esoui source code.
  Reply With Quote
04/19/24, 07:19 PM   #3
Vilkasmanga
AddOn Author - Click to view addons
Join Date: Dec 2023
Posts: 8
Thanks, will do; apologies for the misfire on forums!

-V
  Reply With Quote
04/19/24, 11:18 PM   #4
Vilkasmanga
AddOn Author - Click to view addons
Join Date: Dec 2023
Posts: 8
Confirmed: EVENT_JUSTICE* doesn't fire as bounties rot, nothing else seems to either but will continue to look.

Baertram - Thanks for the mertorchbug suggestion, very helpful (though I still have much to learn to use it more effectively).

-V
  Reply With Quote
04/21/24, 04:25 AM   #5
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 5,015
By searching in esoui sources for event_justice I found the bounty display control.

At this function it seems to update your currently active bounty currency (gold to pay):
https://github.com/esoui/esoui/blob/...isplay.lua#L49

ZO_BountyDisplay is the "class" here and via ZO_BountyDisplay:New you create the object of that class, which can be accessed ingame (and inspected via tbug too).
So searching for ZO_BountyDisplay:New ->
You will get here
https://github.com/esoui/esoui/blob/...oard.lua#L1192
STATS_BOUNTY_DISPLAY is your global object then

So you can hook that function like this I guess to react on any update, check the current currency value or use other ApI to check current bounty values and react on that with your addon:

Lua Code:
  1. SecurePostHook("STATS_BOUNTY_DISPLAY", function()
  2. if IsJusticeEnabled() then
  3. --local self = STATS_BOUNTY_DISPLAY --> Justt o explain what the self in the original function ZO_BountyDisplay:OnBountyUpdated relates to!
  4.  
  5.  
  6. local currentBounty = GetFullBountyPayoffAmount()
  7. if currentBounty >= x then
  8. -- do your bounty value related stuff 1
  9. else
  10. -- do your bounty value related stuff 2
  11. end
  12. end
  13. end)


There might be better ways to achieve your goal, but I hope it expalins enough how to search esoui sources and get to the point where the UI controls update and show things "the ZOs way" (vanilla code).
Maybe you can find an even better point to hook into then.
  Reply With Quote
04/21/24, 01:35 PM   #6
Vilkasmanga
AddOn Author - Click to view addons
Join Date: Dec 2023
Posts: 8
Baertram - As always, thank you for your help - I appreciate the time & effort you spend helping me up the learning curve

I had looked in and around the code you referenced but didn't see or find the nuggets you did, I will go look at them more closely. I have been focused on ESO more than ZO* code and I suspect you've nudged me into a whole new realm of discovery. Thanks (I think? :-) )

In the meantime, I coded at least a temporary solution, though it might be too unpleasant for the real world. Since I can successfully detect the initial bounty assignment (and subsequent increases), I use that trigger to launch a routine to update the onscreen timers, followed by a 15 second followup call to do it again:

Code:
EVENT_MANAGER:RegisterForUpdate(identifier, 15000, FarmersToolkit.BountyCheck)
This (I think) effectively runs a timed loop for updates. Once the bounty is zero, I UnRegisterforUpdate and go back to status quo.

The plus side is, the screen automatically updates every 15 seconds with a revised "time remaining" value for the bounty. (I'm not sure if that frequency of updates will stay that high once I find bounty-event driven updates).

On the down wide, I'm calling a routine every 15 seconds for the duration of a bounty which may be impolitely taxing the servers and doesn't feel like it is in the EVENT-driven style.

Still, unless I hear concerns or find issues, this may work while I go research your posting and find a more elegant solution.

Thanks again for your help and patience.

-V
  Reply With Quote
04/21/24, 03:17 PM   #7
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 5,015
Those RegisterForUpdate timers might be okay to update a counter showing on screen but they should not be used to run timers in general, where other ways are better. e.g. events fire or CALLBACK_MANAGER is available to register a callback function to run, or you can hok into Zos code to run your code befre/after it.

For example if you only want to react on real changes try my example code and just add your on screen information into that.
Instead of the
Code:
if currentBounty  >= x then
else
end
add a

Lua Code:
  1. d("Current bounty: " ..tostring(currentBounty))

and you should see the actual bounty in gold in a chat debug message.
Hope that works, have not tested it so far.
  Reply With Quote
04/24/24, 05:11 PM   #8
Vilkasmanga
AddOn Author - Click to view addons
Join Date: Dec 2023
Posts: 8
Originally Posted by Baertram View Post
Those RegisterForUpdate timers might be okay to update a counter showing on screen but they should not be used to run timers in general, where other ways are better. e.g. events fire or CALLBACK_MANAGER is available to register a callback function to run, or you can hok into Zos code to run your code befre/after it.

For example if you only want to react on real changes try my example code and just add your on screen information into that.
Instead of the
Code:
if currentBounty  >= x then
else
end
add a

Lua Code:
  1. d("Current bounty: " ..tostring(currentBounty))

and you should see the actual bounty in gold in a chat debug message.
Hope that works, have not tested it so far.
Baertram - Thanks, I'm adding this to my "to read / to understand / to use" list.

I'm not yet seeing the triggers that will update as often as I want but the callbacks may have unseen surprises (ok, unseen, as yet, to me...) After reading through (some) of your helpful hints, my sense now is the bounty is continuously decreasing - which would explain the (current?) absence of triggers when something changes.

For now, I've folded in the timer-approach and it actually works reasonably well (in that updates do occur fairly often, no longer requires any other activity / intervention, the timer is useful [when needed], and polite [goes away when not needed]). The feedback that it provides a "quasi-realtime" bounty countdown seems to be generally positive. However, your point that "they should not be used to run timers in general" is well taken. One (future) option would be to make the 15 seconds a configurable value, but I'd likely hold the minimum close to 15 just to avoid any onerous server loads.

For an interim solution, this seems like a decent balance. I have to remind myself: if it is truly a burden, it is limited to the duration of a bounty.

Thanks again for your help, I'll keep poring over your suggestions and learn more for the next update.

-V
  Reply With Quote
04/25/24, 03:15 AM   #9
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 5,015
Yes, having a timer run every 15s as in your case is fine.
Just make sure the timer unregisters properly once your bounty is gone, and does not register with a new name (reuse the same name so it "overwrites" old exisitng ones!) once next bounty comes up.
  Reply With Quote
04/25/24, 03:14 PM   #10
Vilkasmanga
AddOn Author - Click to view addons
Join Date: Dec 2023
Posts: 8
Originally Posted by Baertram View Post
Yes, having a timer run every 15s as in your case is fine.
Just make sure the timer unregisters properly once your bounty is gone, and does not register with a new name (reuse the same name so it "overwrites" old exisitng ones!) once next bounty comes up.
Great, thanks. I think I coded this correctly (thanks to your and others' help, ofc)

Code:
function FarmersToolkit.BountyCheck()

        local CurBounty=GetFullBountyPayoffAmount();
        local identifier="FarmersToolkit-BountyCheck";

        -- In case this is the first time we've been called this session...
        if ( type(FarmersToolkit.BountyValue) == "nil" ) then
                FarmersToolkit.BountyValue=0;
        end

        if ( CurBounty  == 0 ) then  -- We have no bounty, whew!
                if ( FarmersToolkit.BountyValue > 0 ) then -- We may have a outstanding timer event tho
                        EVENT_MANAGER:UnregisterForUpdate(identifier)
                end

                FarmersToolkit.BountyValue = 0; -- Zero out internal counter / tracker
                FarmersToolkit.UpdateActivities(); -- Update the screen
                dft_debug("BountyCheck indicates you are safe as of " .. os.time() .. "!"); -- Debug
                dft("Bounty appears cleared, cancelling timers - happy hunting."); -- Announce
        else
                if ( ( FarmersToolkit.BountyValue == 0 ) and ( CurBounty > 0 ) ) then -- This is the onset of a bounty
                        dft("Bounty detected (" .. CurBounty .. "), updates posted to screen until cleared.");
                end
                FarmersToolkit.UpdateActivities();
                FarmersToolkit.BountyValue=CurBounty;
                dft_debug("BountyCheck = " .. CurBounty .. ", timer set for 15 seconds as of " .. os.time());
                EVENT_MANAGER:UnregisterForUpdate(identifier)  -- Just in case
                EVENT_MANAGER:RegisterForUpdate(identifier, 15000, FarmersToolkit.BountyCheck)
        end

end -- FarmersToolkit.BountyCheck
  Reply With Quote
04/26/24, 03:53 AM   #11
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 5,015
Yes looks good
Added a few comments, hope it's understandable.
Maybe that helps you too:

Lua Code:
  1. function FarmersToolkit.BountyCheck()
  2.  
  3.         local CurBounty=GetFullBountyPayoffAmount(); --lua does not need the ; at line ends (allthough they raise no error)
  4.         local identifier="FarmersToolkit-BountyCheck";
  5.  
  6.         -- local reference variable to speed up things a bit. Can help if you access the same variables more than once.
  7.         -- Else it would each time completely search your table FarmersToolkit for the variable BountyValue again!
  8.         -- If you put a local reference it directly points there and can read and write that table's variable too
  9.         local FTbountyValue = FarmersToolkit.BountyValue
  10.  
  11.  
  12.         -- In case this is the first time we've been called this session...
  13.         FTbountyValue = FTbountyValue or 0 --checks if it's ot nil and uses itssself then, or else defaults it to 0
  14.  
  15.         if ( CurBounty == 0 ) then  -- We have no bounty, whew!
  16.                 if ( FTbountyValue > 0 ) then -- We may have a outstanding timer event tho
  17.                         EVENT_MANAGER:UnregisterForUpdate(identifier)
  18.                 end
  19.  
  20.                 FTbountyValue = 0; -- Zero out internal counter / tracker
  21.                 FarmersToolkit.UpdateActivities(); -- Update the screen
  22.                 dft_debug("BountyCheck indicates you are safe as of " .. os.time() .. "!"); -- Debug
  23.                 dft("Bounty appears cleared, cancelling timers - happy hunting."); -- Announce
  24.         else
  25.                 if ( ( FTbountyValue == 0 ) and ( CurBounty > 0 ) ) then -- This is the onset of a bounty
  26.                         dft("Bounty detected (" .. CurBounty .. "), updates posted to screen until cleared.");
  27.                 end
  28.                 FarmersToolkit.UpdateActivities();
  29.                 FTbountyValue=CurBounty;
  30.                 dft_debug("BountyCheck = " .. CurBounty .. ", timer set for 15 seconds as of " .. os.time());
  31.                 EVENT_MANAGER:UnregisterForUpdate(identifier)  -- Just in case
  32.                 EVENT_MANAGER:RegisterForUpdate(identifier, 15000, FarmersToolkit.BountyCheck)
  33.         end
  34.  
  35. end -- FarmersToolkit.BountyCheck
  Reply With Quote
04/26/24, 09:51 AM   #12
Vilkasmanga
AddOn Author - Click to view addons
Join Date: Dec 2023
Posts: 8
Baertram - Awesome feedback and help, thank you!

Suggestions like "FTbountyValue = FTbountyValue or 0 " are extremely helpful because I know efficiencies like that should exist but I don't always know how - this will definitely be a trick I use going forward.

Thanks also for the tip on localizing FTbountyValue for speed up. Again, a nice touch that isn't something I would have easily stumbled across / appreciated on my own. I need to see if I use FarmersToolkit.BountyValue anywhere outside of this routine but, worst case, I can always drop a single line at the bottom of this routine that sets FarmersToolkit.BountyValue = FTbountyValue - one call versus 4-5 is still a win!

Even though they aren't needed and aren't harmful, I'll probably keep doing semi-colons out of habit from so many other languages that do need them. At this point, I think my fingers are trained to end lines with semi-colon and my eye twitches until I match open and closing parentheses, even if it is just in chat

-V
  Reply With Quote
04/26/24, 10:12 AM   #13
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 5,015
Another example for that will be e.g. SavedVariables where you use ZO_SavedVars wrapper to load the global SavedVariable table, which you have defined in your manifest txt file after ## SavedVariables: <tableNameHere>, into a local reference "settings".

Code:
local settings = ZO_SavedVars:New*
settings is a local reference then to the global table _G, where there was defined another subtable called <tableNameHere>

_G["<tableNameHere>"] = same as <tableNameHere>

If e.g. <tableNameHere> would be MyAddonsSavedVariables then you can access (after EVENT_ADD_ON_LOADED) that table MyAddonsSavedVariables directly or via _G["MyAddonsSavedVariables"], and your local settings would point to the actual real savedvariables patch like
MyAddonsSavedVariables["Default"]["NA Megaserver"]["@accountName"]
which all got handled by the wrapper ZO_SavedVars creating these subtables if not already exisiting and then returning that reference
  Reply With Quote

ESOUI » Developer Discussions » General Authoring Discussion » Question on EVENT_JUSTICE_* firing

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off