Quantcast [AceAddon-3.0] Module doesn't fire OnEnable/OnDisable function - WoWInterface
Thread Tools Display Modes
12-27-17, 04:08 AM   #1
Layback_
An Onyxian Warder
Join Date: Feb 2016
Posts: 356
[AceAddon-3.0] Module doesn't fire OnEnable/OnDisable function

Hi again all,

I personally thought that I'm pretty familiar with AceAddon-3.0, but seems I'm not

Okay, so I'm currently trying to make an AceAddon-3.0 based addon with three different modules that gets enabled & disabled based on player's current specialization and here's what I have done so far.

init.lua
Lua Code:
  1. local name, ns = ...;
  2.  
  3. -- Upvalue
  4. local _G = _G;
  5.  
  6. -- Addon
  7. local E = LibStub("AceAddon-3.0"):NewAddon(name, "AceEvent-3.0");
  8. local L = LibStub("AceLocale-3.0"):GetLocale(name, false);
  9. local D = {};
  10.  
  11. ns[1] = E; -- Engine
  12. ns[2] = L; -- Locale
  13. ns[3] = D; -- Defaults
  14.  
  15. _G[name] = ns;
  16.  
  17. -- Variable
  18. local specNameByID = { -- Needed for non English client
  19.     [259] = "Assassination",
  20.     [260] = "Outlaw",
  21.     [261] = "Subtlety",
  22. }
  23.  
  24. -- Function
  25. function E:OnInitialize()
  26.     self.db = LibStub("AceDB-3.0"):New(name .. "DB", D, true);
  27.  
  28.     self:ACTIVE_TALENT_GROUP_CHANGED(nil, nil, nil, true);
  29. end
  30.  
  31. function E:OnEnable()
  32.     print(E:GetName() .. " OnEnable");
  33. end
  34.  
  35. function E:OnDisable()
  36.     print(E:GetName() .. " OnDisable");
  37. end
  38.  
  39. function E:ACTIVE_TALENT_GROUP_CHANGED(event, arg1, arg2, isOnInitialize)
  40.     local db = self.db.global;
  41.  
  42.     local newSpecID = GetSpecializationInfo(GetSpecialization());
  43.  
  44.     if isOnInitialize or (db.currentSpecID and db.currentSpecID ~= newSpecID) then
  45.         db.currentSpecID = newSpecID;
  46.  
  47.         for id, name in pairs(specNameByID) do
  48.             local module = self:GetModule(name);
  49.  
  50.             (id == db.currentSpecID and module.Enable or module.Disable)(module);
  51.         end
  52.     end
  53. end
  54.  
  55. E:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED");

Outlaw.lua
Lua Code:
  1. local E, L, D = unpack(select(2, ...));
  2.  
  3. -- Module
  4. local M = E:NewModule("Outlaw");
  5.  
  6. -- Variable
  7. local RtBIDs = {
  8.     199603, -- Jolly Roger
  9.     193358, -- Grand Melee
  10.     193357, -- Shark Infested Waters
  11.     193359, -- True Bearing
  12.     199600, -- Buried Treasure
  13.     193356, -- Broadsides
  14. }
  15.  
  16. local CotDID = 202665; -- Curse of the Dradeblades
  17.  
  18. local SaDID = 5171; -- Slice and Dice
  19.  
  20. local selectedSaD;
  21.  
  22. local InitializeObjects, ManageObjectStates;
  23.  
  24. -- Function
  25. function M:OnInitialize()
  26.     InitializeObjects();
  27. end
  28.  
  29. function M:OnEnable()
  30.     print(M:GetName(), "OnEnable");
  31.  
  32.     local holder = self.holder;
  33.     holder:Show();
  34.     holder:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED");
  35.     holder:RegisterUnitEvent("UNIT_AURA", "player");
  36.     holder:SetScript("OnEvent", function(self, event, ...)
  37.         M[event](M, ...);
  38.     end);
  39.  
  40.     ManageObjectStates();
  41. end
  42.  
  43. function M:OnDisable()
  44.     print(M:GetName(), "OnDisable");
  45.  
  46.     local holder = self.holder;
  47.     holder:UnregisterAllEvents();
  48.     holder:Hide();
  49. end

The current problem is that after calling Enable/Disable functions within ACTIVE_TALENT_GROUP_CHANGED method on addon initialization, the module's OnEnable/OnDisable functions don't get called on login, reload and etc, but only gets affected when the player actually changes his/her spec.
(talent changes are not considered on purpose)

According to the description in AceAddon-3.0.lua file, OnEnable functions get called during the PLAYER_LOGIN event (normally I'd say right after OnInitialize function gets called) and the state of modules are changed while initialization (L#50 of init.lua), thus I can't really think why it is not working

Am I doing something wrong?

Last edited by Layback_ : 12-27-17 at 05:14 AM.
  Reply With Quote
12-27-17, 08:25 AM   #2
briskman3000
A Theradrim Guardian
AddOn Author - Click to view addons
Join Date: Mar 2009
Posts: 66
So ignoring the Ace part (since I know nothing about ace). You are watching for ACTIVE_TALENT_GROUP_CHANGED to fire your code correct? If so, that event only fires when you change specs.

Before I changed my code for ConvertRatings to a not-dumb lookup method for Mastery Coefficient lookup (I used to have them stored in a table and looked up the player's spec and pulled it from a table, instead of just querying the active spec coefficient), I just had the spec lookup function plopped towards the top of my code with no calls so it just ran on all the events that cause non-event specific code to be run, and then I also had it plopped in an event check for ACTIVE_TALENT_GROUP_CHANGED, so that it would run on talent changes without forcing a reload or similar.

I would assume in ace that you could run an initial check based on the specid pulled on first login if you plop the check after the plopped specid pull, and then run triggered checks on ACTIVE_TALENT_GROUP_CHANGED.
  Reply With Quote
12-27-17, 05:56 PM   #3
Layback_
An Onyxian Warder
Join Date: Feb 2016
Posts: 356
Hi briskman3000,

even if the function is called E:ACTIVE_TALENT_GROUP_CHANGED, since I'm manually calling it at L#28, this function would still run with an extra parameter named isOnInitialize.

Lua Code:
  1. self:ACTIVE_TALENT_GROUP_CHANGED(nil, nil, nil, true);

That being said, for the first time when the AceAddon-3.0 initializes its addon, E:ACTIVE_TALENT_GROUP_CHANGED would still run once with isOnInitialize flag being true even if the event is not fired. Otherwise, this function will only be called on ACTIVE_TALENT_GROUP_CHANGED event without isOnInitialize being set as you said

Last edited by Layback_ : 12-27-17 at 06:00 PM.
  Reply With Quote
12-27-17, 07:20 PM   #4
Layback_
An Onyxian Warder
Join Date: Feb 2016
Posts: 356
Guess I should correct some errors!

First of all, OnEnable function for the initial spec is being successfully called on addon's OnInitialize function. However, OnDisable function for the other two are still not working.

In addition to that, on specialization switch, the old spec's OnDisable function and the new spec's OnEnable function get called even if I disable the third spec's module as well.
(pretty sure this is an intended behavior, tho...)

Last edited by Layback_ : 12-28-17 at 01:29 AM.
  Reply With Quote
12-28-17, 01:32 AM   #5
Layback_
An Onyxian Warder
Join Date: Feb 2016
Posts: 356
EDIT: I've done further experiment and figured that even if I set an addon's default module state to false, it doesn't call OnDisable function on initialization phase.

Does that mean I'll have to manually call OnDisable function if needed?

Last edited by Layback_ : 12-28-17 at 01:39 AM.
  Reply With Quote
12-31-17, 04:23 PM   #6
myrroddin
A Molten Giant
 
myrroddin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 882
I see you are comparing TukUI/ElvUI code with Ace3 and the game's built-in Lua. No wonder you are confused!
  • Calling the event handler in OnInit does nothing because you haven't registered the event yet. That is done in OnEnable (correct). If you need it right away, then register the event in OnEnable and then call it in OnEnable. Of course that requires the module to be enabled.
  • Outlaw.lua's lines 36-38 are useless because AceEvent already handles that. Either pick AceEvent or handle event script handles yourself; don't mix them.
  • There might be a reason why you have holder hooking events, but wouldn't it be easier to just register directly on M?

For your last question, if you set the default state to disabled, then yes, OnEnable, OnDisable do not run, and I don't think OnInit even fires (but I'm not 100% certain of that).

If you want to see a working code base for how to handle Ace3 modules and events, check out SmartRes2 and SmartRes2_Chat. Both work, although I haven't continued them in quite some time. You will notice I do not follow the Tuk/Elv methodology because that is just too complicated and hard to bug fix. You can find both addons here on Wowinterface and also on Twitch/Curse.
  Reply With Quote
12-31-17, 07:08 PM   #7
Layback_
An Onyxian Warder
Join Date: Feb 2016
Posts: 356
Hi myrroddin,

Originally Posted by myrroddin View Post
I see you are comparing TukUI/ElvUI code with Ace3 and the game's built-in Lua. No wonder you are confused!
No, I quit having a look at TukUI/ElvUI codes since many addon authors (including you) advised me that those are not a good example for beginners to work with

The current structure of the code is just the way I'm used to at this stage, haha!

Originally Posted by myrroddin View Post
Calling the event handler in OnInit does nothing because you haven't registered the event yet. That is done in OnEnable (correct). If you need it right away, then register the event in OnEnable and then call it in OnEnable. Of course that requires the module to be enabled.
I am not sure if I am understanding correctly, but you mean that the events are registered on OnEnable phase of the AceAddon?

Hm... I guess in my case it's more likely calling a function (event handler in this case) E:ACTIVE_TALENT_GROUP_CHANGED, manually, and that's why I'm passing another paramter called isOnInitialize on its call. Thus, I don't need an event to be registered at this point, but just need that event handler to be called manually

Originally Posted by myrroddin View Post
Outlaw.lua's lines 36-38 are useless because AceEvent already handles that. Either pick AceEvent or handle event script handles yourself; don't mix them.
I've been told that AceEvent can still control those unit specific events, but can't specify which unit it should listen to (e.g. UNIT_AURA). Of course, I could still use AceEvent and put an if statement to check if the unit that is being passed is what I want, but eeh.....

I don't know how the registered events with :RegisterUnitEvent works internally (guess it's done by C, maybe?), but I honestly didn't want it to call function over and over again on my side just for single line of if statement to check if the unit is player or not when there is an update with aura especially while I'm in huge raid.

In addition to that my first intention of handling events separately for AceAddon and its module (module's core frame in this case) was to give them an independent job.

Addon will only use ACTIVE_TALENT_GROUP_CHANGED event for toggling its modules depending on player's current specialization while Outlaw module will use it to show/hide its child objects depending on its talent change (not spec).

Again, you are right that mixing AceEvent and separate event handler would be a bad idea and maybe I should consider combining them into one, but I would like to keep them as they are, at least for now.

I really appreciate your advice!

Originally Posted by myrroddin View Post
There might be a reason why you have holder hooking events, but wouldn't it be easier to just register directly on M?
Same reason as above

Originally Posted by myrroddin View Post
For your last question, if you set the default state to disabled, then yes, OnEnable, OnDisable do not run, and I don't think OnInit even fires (but I'm not 100% certain of that).
Maybe I should do some further experiment regarding this!

Originally Posted by myrroddin View Post
If you want to see a working code base for how to handle Ace3 modules and events, check out SmartRes2 and SmartRes2_Chat. Both work, although I haven't continued them in quite some time. You will notice I do not follow the Tuk/Elv methodology because that is just too complicated and hard to bug fix. You can find both addons here on Wowinterface and also on Twitch/Curse.
Of course I had a look at SmartRes2 and SmartRes2_Chat.

You've already told me to do so when I got confused with AceDB

But guess it is a great idea to revisit those codes for refresh
  Reply With Quote
12-31-17, 08:59 PM   #8
myrroddin
A Molten Giant
 
myrroddin's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 882
Lua Code:
  1. function myaddon:OnEnable()
  2.     self:RegisterEvent("SOME_EVENT")
  3.  
  4.     -- now call it if you need it right away
  5.     self:SOME_EVENT()
  6. end
  7.  
  8. function myaddon:OnDisable()
  9.     self:UnregisterEvent("SOME_EVENT")
  10.     -- or
  11.     self:UnregisterAllEvents()
  12.  
  13. function myaddon:SOME_EVENT()
  14.     -- handle it
  15. end
  Reply With Quote
02-11-18, 05:03 PM   #9
doofus
A Cyclonian
Join Date: Feb 2018
Posts: 47
Have not read this thread thoroughly but I landed here looking for bugs around the event ACTIVE_TALENT_GROUP_CHANGED. If you do, as I do, "gPlayerPowerType, gPlayerPowerTypeString = UnitPowerType("player"); " right on the event callback, you will get, the OLD specialisation's power type.

For example if you are Resto druid your power type is 0 (mana), you then switch to Balance, and at least in the event callback your power type still reads 0 (mana) when in fact it should be 8 (Lunar Power). You then switch to Guardian and you read 8 (Lunar Power) when it should be 1 (Rage).

However right after the unit (you) casts a spell 200749 "Activating Specialization". Maybe we need to trap that spell to make sure the talent switch has been completed.

Another thing, I receive the ACTIVE_TALENT_GROUP_CHANGED twice on a talent switch.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » [AceAddon-3.0] Module doesn't fire OnEnable/OnDisable function

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