Reply
Thread Tools Display Modes
Unread 08-24-14, 03:47 AM   #1
Wimpface
A Molten Giant
 
Wimpface's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 643
Struggling with changing variable value

I'm trying to make my oUF layout load different castbar settings depending on class and spec, and was planning on using a boolean for this but the variable I'm checking never seems to update it's value.

I get no errors, but I've added a debug print to see what isCaster returns and it always returns nil. I've tried this from multiple places in the code (inside the cbCheck function, inside the cbCheckFrame SetScript and inside the Shared function where I create the castbars) and the return is always nil.

This is where I try to change the value.
https://gist.github.com/ShredL/f00b576ae70456a971a8

Lua Code:
  1. -- Doesn't seem to change the value of my isCaster variable
  2. local spec = GetSpecialization()
  3. local _, playerClass = UnitClass("PLAYER")
  4. local isCaster
  5. local function cbCheck()
  6.     if playerClass == 'DRUID' or 'MONK' or 'PALADIN' or 'SHAMAN' then
  7.         if playerClass == 'DRUID' then
  8.             if spec == 1 or 4 then
  9.                 isCaster = true
  10.             else
  11.                 isCaster = false
  12.             end
  13.         elseif playerClass == 'MONK' then
  14.             if spec == 2 then
  15.                 isCaster = true
  16.             else
  17.                 isCaster = false
  18.             end
  19.         elseif playerClass == 'PALADIN' then
  20.             if spec == 1 then
  21.                 isCaster = true
  22.             else
  23.                 isCaster = false
  24.             end
  25.         elseif playerClass == 'SHAMAN' then
  26.             if spec == 2 then
  27.                 isCaster = false
  28.             else
  29.                 isCaster = true
  30.             end
  31.         end
  32.     elseif playerClass == 'DEATHKNIGHT' or 'HUNTER' or 'ROGUE' or 'WARRIOR' then
  33.         isCaster = false
  34.     else
  35.         isCaster = true
  36.     end
  37. end
  38. local cbCheckFrame = CreateFrame("Frame")
  39. cbCheckFrame:RegisterEvent('PLAYER_SPECIALIZATION_CHANGED')
  40. cbCheckFrame:RegisterEvent('PLAYER_ENTERING_WORLD')
  41. cbCheckFrame:RegisterEvent('PLAYER_LOGIN')
  42. cbCheckFrame:SetScript("OnEvent", function()
  43.     cbCheck()
  44. end)

This is what is in my Shared function
https://gist.github.com/ShredL/8ee3b4978b3de4498c4c

Lua Code:
  1. -- Castbar
  2.     if(unit=='player' or unit=='target') then
  3.         local Castbar = CreateFrame('StatusBar', nil, self)
  4.         local Spark = Castbar:CreateTexture(nil, 'OVERLAY')
  5.  
  6.         if(unit=='player') then
  7.             if isCaster == false then
  8.                 Castbar:SetAllPoints(Health)
  9.                 Castbar:SetStatusBarTexture(statusBar)
  10.                 Castbar:SetStatusBarColor(0, 0, 0, 0)
  11.                 Castbar:SetFrameStrata('HIGH')
  12.  
  13.                 Spark:SetSize(2, 7)
  14.                 Spark:SetTexture(1, 1, 1)
  15.             elseif isCaster == true then
  16.                 Castbar:SetAllPoints(Health)
  17.                 Castbar:SetStatusBarTexture(statusBar)
  18.                 Castbar:SetStatusBarColor(0, 0, 0, 0)
  19.                 Castbar:SetFrameStrata('HIGH')
  20.  
  21.                 Spark:SetSize(2, 7)
  22.                 Spark:SetTexture(1, 1, 1)
  23.             end
  24.         else
  25.             Castbar:SetAllPoints(Health)
  26.             Castbar:SetStatusBarTexture(statusBar)
  27.             Castbar:SetStatusBarColor(0, 0, 0, 0)
  28.             Castbar:SetFrameStrata('HIGH')
  29.  
  30.             Spark:SetSize(2, 20)
  31.             Spark:SetTexture(1, 1, 1)
  32.         end
  33.  
  34.         self.Castbar = Castbar
  35.         Castbar.Spark = Spark
  36.  
  37.     end

And here is the entire code if needed
https://gist.github.com/ShredL/59b138b727ca3a818299

It is probably something super simple that I'm overlooking, but I cannot seem to figure out how to change the value of isCaster. Any help is appreciated as always.
__________________
All I see is strobe lights blinding me in my hindsight.

Last edited by Wimpface : 08-24-14 at 04:15 AM.
Wimpface is offline   Reply With Quote
Unread 08-24-14, 07:24 AM   #2
Malakahh
A Fallenroot Satyr
AddOn Author - Click to view addons
Join Date: Jun 2009
Posts: 25
Some of your if statements are a bit odd to say the least, as they will always be true. The ones I'm talking about are lines 6, 8, and 32 of the first block of code you posted. Try changing it to

Lua Code:
  1. -- Doesn't seem to change the value of my isCaster variable
  2. local spec = GetSpecialization()
  3. local _, playerClass = UnitClass("PLAYER")
  4. local isCaster
  5. local function cbCheck()
  6.     if playerClass == 'DRUID' or playerClass == 'MONK' or playerClass == 'PALADIN' or playerClass == 'SHAMAN' then
  7.         if playerClass == 'DRUID' then
  8.             if spec == 1 or spec == 4 then
  9.                 isCaster = true
  10.             else
  11.                 isCaster = false
  12.             end
  13.         elseif playerClass == 'MONK' then
  14.             if spec == 2 then
  15.                 isCaster = true
  16.             else
  17.                 isCaster = false
  18.             end
  19.         elseif playerClass == 'PALADIN' then
  20.             if spec == 1 then
  21.                 isCaster = true
  22.             else
  23.                 isCaster = false
  24.             end
  25.         elseif playerClass == 'SHAMAN' then
  26.             if spec == 2 then
  27.                 isCaster = false
  28.             else
  29.                 isCaster = true
  30.             end
  31.         end
  32.     elseif playerClass == 'DEATHKNIGHT' or playerClass == 'HUNTER' or playerClass == 'ROGUE' or playerClass == 'WARRIOR' then
  33.         isCaster = false
  34.     else
  35.         isCaster = true
  36.     end
  37. end
  38. local cbCheckFrame = CreateFrame("Frame")
  39. cbCheckFrame:RegisterEvent('PLAYER_SPECIALIZATION_CHANGED')
  40. cbCheckFrame:RegisterEvent('PLAYER_ENTERING_WORLD')
  41. cbCheckFrame:RegisterEvent('PLAYER_LOGIN')
  42. cbCheckFrame:SetScript("OnEvent", function()
  43.     cbCheck()
  44. end)
Malakahh is offline   Reply With Quote
Unread 08-24-14, 02:11 PM   #3
Wimpface
A Molten Giant
 
Wimpface's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 643
Ofcourse, silly me. Fixing the if statements fixed it... sorta. The castbar now gets disabled when reloading UI (EDIT: or rather, it always did and I just didn't know). I'm assuming this has to do with the event calls. Is there another event I should be checking?
Lua Code:
  1. local function cbCheck()
  2.     if playerClass == 'DRUID' or playerClass == 'MONK' or playerClass == 'PALADIN' or playerClass == 'SHAMAN' then
  3.         if playerClass == 'DRUID' then
  4.             if spec == 1 or spec == 4 then
  5.                 isCaster = true
  6.             else
  7.                 isCaster = false
  8.             end
  9.         elseif playerClass == 'MONK' then
  10.             if spec == 2 then
  11.                 isCaster = true
  12.             else
  13.                 isCaster = false
  14.             end
  15.         elseif playerClass == 'PALADIN' then
  16.             if spec == 1 then
  17.                 isCaster = true
  18.             else
  19.                 isCaster = false
  20.             end
  21.         elseif playerClass == 'SHAMAN' then
  22.             if spec == 2 then
  23.                 isCaster = false
  24.             else
  25.                 isCaster = true
  26.             end
  27.         end
  28.     elseif playerClass == 'DEATHKNIGHT' or playerClass == 'HUNTER' or playerClass == 'ROGUE' or playerClass == 'WARRIOR' then
  29.         isCaster = false
  30.     elseif playerClass == 'MAGE' or playerClass == 'PRIEST' or playerClass == 'WARLOCK' then
  31.         isCaster = true
  32.     end
  33. end

I've been trying it out on Monk, Mage, Warlock, and Shaman (caster) so far. Reloading kills it every time.

EDIT: Perhaps it should be noted it's only the player castbar that disappears when reloading. Using a Mage teleport spell did not make it disappear, taking a portal did.
__________________
All I see is strobe lights blinding me in my hindsight.

Last edited by Wimpface : 08-24-14 at 03:09 PM.
Wimpface is offline   Reply With Quote
Unread 08-24-14, 11:29 PM   #4
Phanx
A Pyroguard Emberseer
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 4,435
Your current method:

Code:
local spec = GetSpecialization()
local _, playerClass = UnitClass("PLAYER")
local isCaster
local function cbCheck()
    -- stuff here
end

local cbCheckFrame = CreateFrame("Frame")
cbCheckFrame:RegisterEvent('PLAYER_SPECIALIZATION_CHANGED')
cbCheckFrame:RegisterEvent('PLAYER_ENTERING_WORLD')
cbCheckFrame:RegisterEvent('PLAYER_LOGIN')
cbCheckFrame:SetScript("OnEvent", function()
    cbCheck()
end)
... may as well not listen for events at all, since you only check the player's spec once in the main chunk. Your cbCheck function will run the same logic every time it's run, even if the player's spec changes during play or isn't available yet in the main chunk (eg. on a fresh login GetSpecialization() is probably always nil).

You need to check the spec [b]inside[/i] the function. Also, defining a function outside of the OnEvent handler offers no benefit, and has the non-insignifcant downside of adding an extra function call, which is pretty much the slowest thing you can do in Lua. Just move all that code directly into the OnEvent handler or, if you really want to have a variable pointing to your function, set the cbCheck function as the OnEvent handler directly.

Code:
local isCaster
local _, playerClass = UnitClass("player")

local cbCheckFrame = CreateFrame("Frame")
cbCheckFrame:RegisterEvent('PLAYER_SPECIALIZATION_CHANGED')
cbCheckFrame:RegisterEvent('PLAYER_ENTERING_WORLD')
cbCheckFrame:RegisterEvent('PLAYER_LOGIN')
cbCheckFrame:SetScript("OnEvent", function()
    local spec = GetSpecialization()
    -- stuff here
end)
(On a side note, the proper capitalization for unit tokens is lowercase, so it should be "player", not "PLAYER". The API will auto-correct values you pass into it, but you should be in the habit of using the correct capitalization, not only because it's, well, correct, but also because if you're ever performing comparisons on values returned by the API, you'll have to write your comparison correctly, or waste time calling string.upper on the returned value.)
__________________
Author/maintainer of Grid, PhanxChat, ShieldsUp, and many more.
Troubleshoot an addon Turn any code into an addon More addon resources
Need help with your code? Post all of your actual code! Attach or paste your files.
Please dont PM me about addon bugs or code questions. Post a comment or forum thread instead!
Phanx is offline   Reply With Quote
Unread 08-25-14, 01:55 AM   #5
Wimpface
A Molten Giant
 
Wimpface's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 643
Thanks Phanx, you're the best as always.

I moved the code and the spec variable into the OnEvent handler. I had no idea function calls were slow, I should probably re-do some of my other addons...

Forgive my ignorance, but is the reason I don't need to check for events at all because I need to reload anyway for my castbar to change, even if the variable value changes when PLAYER_SPECIALIZATION_CHANGED fires? I'm fairly sure it won't be dynamic in it's current incarnation. If I'm correct, that means I can just make a function and call it whenever the code loads because I'll need a reload anyway. Would this be more efficient or not, given what I've learned about function calls being slow?
EDIT: Ofcourse it won't be dynamic. Zz

Also, would I not run into troubles with GetSpecialization() not being available until PLAYER_ENTERING_WORLD? How would I go about finding this out?
I read in an old thread from 2011 in which you replied to that GetPrimaryTalentTree() isn't available until after PLAYER_ALIVE fires. Perhaps I should just check for that event? Assuming GetSpecialization() follows the same rules it's predecessor did.

This is the state my code is in right now, I'm going to try out some of the stuff in this post and see where it gets me. The castbar still disappears on reload with this code.
Lua Code:
  1. local isCaster
  2. local cbCheckFrame = CreateFrame("Frame")
  3. cbCheckFrame:RegisterEvent('PLAYER_SPECIALIZATION_CHANGED')
  4. cbCheckFrame:RegisterEvent('PLAYER_ENTERING_WORLD')
  5. cbCheckFrame:RegisterEvent('PLAYER_LOGIN')
  6. cbCheckFrame:SetScript("OnEvent", function()
  7.     local spec = GetSpecialization()
  8.  
  9.     if playerClass == 'DRUID' or playerClass == 'MONK' or playerClass == 'PALADIN' or playerClass == 'SHAMAN' then
  10.         if playerClass == 'DRUID' then
  11.             if spec == 1 or spec == 4 then
  12.                 isCaster = true
  13.             else
  14.                 isCaster = false
  15.             end
  16.         elseif playerClass == 'MONK' then
  17.             if spec == 2 then
  18.                 isCaster = true
  19.             else
  20.                 isCaster = false
  21.             end
  22.         elseif playerClass == 'PALADIN' then
  23.             if spec == 1 then
  24.                 isCaster = true
  25.             else
  26.                 isCaster = false
  27.             end
  28.         elseif playerClass == 'SHAMAN' then
  29.             if spec == 2 then
  30.                 isCaster = false
  31.             else
  32.                 isCaster = true
  33.             end
  34.         end
  35.     elseif playerClass == 'DEATHKNIGHT' or playerClass == 'HUNTER' or playerClass == 'ROGUE' or playerClass == 'WARRIOR' then
  36.         isCaster = false
  37.     elseif playerClass == 'MAGE' or playerClass == 'PRIEST' or playerClass == 'WARLOCK' then
  38.         isCaster = true
  39.     end
  40.  
  41.     print(isCaster)
  42. end)

Finally, I've been doing "PLAYER" for years and saw you mention something similar in a thread yesterday. Can't believe it's something I've never thought about twice, even though I've looked up UnitClass, UnitName, UnitRace and so forth about a million times. Bad habits die hard I suppose.

EDIT#2: I took events out of it altogether, and just did a function that I call once when the code fires. It now works correctly, but maybe it isn't the best way of doing it? Is this different than running a SetScript on a frame? If not, I have no idea what handler to use as OnEvent seems wasteful. Maybe OnLoad?
Lua Code:
  1. local isCaster
  2. local cbCheck = function()
  3.     local spec = GetSpecialization()
  4.  
  5.     if playerClass == 'DRUID' or playerClass == 'MONK' or playerClass == 'PALADIN' or playerClass == 'SHAMAN' then
  6.         if playerClass == 'DRUID' then
  7.             if spec == 1 or spec == 4 then
  8.                 isCaster = true
  9.             else
  10.                 isCaster = false
  11.             end
  12.         elseif playerClass == 'MONK' then
  13.             if spec == 2 then
  14.                 isCaster = true
  15.             else
  16.                 isCaster = false
  17.             end
  18.         elseif playerClass == 'PALADIN' then
  19.             if spec == 1 then
  20.                 isCaster = true
  21.             else
  22.                 isCaster = false
  23.             end
  24.         elseif playerClass == 'SHAMAN' then
  25.             if spec == 2 then
  26.                 isCaster = false
  27.             else
  28.                 isCaster = true
  29.             end
  30.         end
  31.     elseif playerClass == 'DEATHKNIGHT' or playerClass == 'HUNTER' or playerClass == 'ROGUE' or playerClass == 'WARRIOR' then
  32.         isCaster = false
  33.     elseif playerClass == 'MAGE' or playerClass == 'PRIEST' or playerClass == 'WARLOCK' then
  34.         isCaster = true
  35.     end
  36.  
  37.     print(isCaster)
  38. end
  39.  
  40. cbCheck()
__________________
All I see is strobe lights blinding me in my hindsight.

Last edited by Wimpface : 08-25-14 at 02:11 AM.
Wimpface is offline   Reply With Quote
Unread 08-25-14, 02:46 AM   #6
p3lim
A Pyroguard Emberseer
 
p3lim's Avatar
AddOn Author - Click to view addons
Join Date: Feb 2007
Posts: 1,297
You could also simplify the isCaster check a bit
Lua Code:
  1. local cbCheck = function()
  2.     local _, playerClass = UnitClass('player')
  3.     local spec = GetSpecialization()
  4.  
  5.     local isCaster = false
  6.     if(playerClass == 'DRUID' and (spec == 1 or spec == 4)) then
  7.         isCaster = true
  8.     elseif(playerClass == 'MONK' and spec == 2) then
  9.         isCaster = true
  10.     elseif(playerClass == 'PALADIN' and spec == 1) then
  11.         isCaster = true
  12.     elseif(playerClass == 'SHAMAN' and spec == 2) then
  13.         isCaster = true
  14.     elseif(playerClass == 'MAGE' or playerClass == 'PRIEST' or playerClass == 'WARLOCK') then
  15.         isCaster = true
  16.     end
  17. end

Also, you need the events to delay the check, on init the spec is not available yet, and will return nil.

Last edited by p3lim : 08-25-14 at 02:49 AM.
p3lim is offline   Reply With Quote
Unread 08-25-14, 02:50 AM   #7
Phanx
A Pyroguard Emberseer
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 4,435
Originally Posted by Wimpface View Post
I had no idea function calls were slow, I should probably re-do some of my other addons...
Well, function calls are still effectively instant in terms of human perception, it's just that they're significantly slower than everything else you can do in Lua, such as looking up values in tables. This is why I always suggest doing things like "r, g, b = t[1], t[2], t[3]" instead of "r, g, b = unpack(t)" or "for i = 1, #t do local v = t[i]" instead of "for i, v in ipairs(t)" -- wherever you can achieve the same result without calling a function, you're probably better off doing so.

Originally Posted by Wimpface View Post
... is the reason I don't need to check for events at all because I need to reload anyway for my castbar to change, even if the variable value changes when PLAYER_SPECIALIZATION_CHANGED fires?
Information about spells, talents, etc. is available immediately when you reload the UI because you're only reloading the UI; you're not actually disconnecting and reconnecting from the server. Your character and all information about it remain loaded in the client.

Functions like UnitGUID don't return useful values right away on a fresh login, and most likely GetSpecialization doesn't either. You can easily test this by logging out to the character screen and logging back in, with the following code in the main chunk:

Code:
print("Current spec is:", GetSpecialization())
On an actual login I suspect it will report "nil", though it will report the correct value on a UI reload.

Originally Posted by Wimpface View Post
This is the state my code is in right now, ... The castbar still disappears on reload with this code.
There's nothing in the code you posted that does anything with any castbar, so I can't really help you with that.

Originally Posted by Wimpface View Post
I took events out of it altogether, and just did a function that I call once when the code fires. It now works correctly, but maybe it isn't the best way of doing it? Is this different than running a SetScript on a frame? If not, I have no idea what handler to use as OnEvent seems wasteful. Maybe OnLoad?
It won't work on a fresh login; see above.

OnLoad doesn't fire for frames created in Lua, and doesn't need to, as it's the same as just writing the code directly after the CreateFrame call.

If you're not using oUF:Factory already, I'd recommend you switch to it, as it will delay creating your frames until PLAYER_LOGIN, at which time information about things like your spec should be available, even on a fresh login.
__________________
Author/maintainer of Grid, PhanxChat, ShieldsUp, and many more.
Troubleshoot an addon Turn any code into an addon More addon resources
Need help with your code? Post all of your actual code! Attach or paste your files.
Please dont PM me about addon bugs or code questions. Post a comment or forum thread instead!
Phanx is offline   Reply With Quote
Unread 08-25-14, 04:06 AM   #8
Wimpface
A Molten Giant
 
Wimpface's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 643
Originally Posted by p3lim View Post
You could also simplify the isCaster check a bit
Lua Code:
  1. local cbCheck = function()
  2.     local _, playerClass = UnitClass('player')
  3.     local spec = GetSpecialization()
  4.  
  5.     local isCaster = false
  6.     if(playerClass == 'DRUID' and (spec == 1 or spec == 4)) then
  7.         isCaster = true
  8.     elseif(playerClass == 'MONK' and spec == 2) then
  9.         isCaster = true
  10.     elseif(playerClass == 'PALADIN' and spec == 1) then
  11.         isCaster = true
  12.     elseif(playerClass == 'SHAMAN' and spec == 2) then
  13.         isCaster = true
  14.     elseif(playerClass == 'MAGE' or playerClass == 'PRIEST' or playerClass == 'WARLOCK') then
  15.         isCaster = true
  16.     end
  17. end

Also, you need the events to delay the check, on init the spec is not available yet, and will return nil.
Thanks, looks a lot tidier. Changing to this makes it not work on login, as is apparently expected according to you and Phanx' replies. Keeping it the way I have it works on both login and reload...

Originally Posted by Phanx View Post
Well, function calls are still effectively instant in terms of human perception, it's just that they're significantly slower than everything else you can do in Lua, such as looking up values in tables. This is why I always suggest doing things like "r, g, b = t[1], t[2], t[3]" instead of "r, g, b = unpack(t)" or "for i = 1, #t do local v = t[i]" instead of "for i, v in ipairs(t)" -- wherever you can achieve the same result without calling a function, you're probably better off doing so.
That makes sense. I've done this for your first example before, so this is vaguely familiar.

Originally Posted by Phanx View Post
Information about spells, talents, etc. is available immediately when you reload the UI because you're only reloading the UI; you're not actually disconnecting and reconnecting from the server. Your character and all information about it remain loaded in the client.

Functions like UnitGUID don't return useful values right away on a fresh login, and most likely GetSpecialization doesn't either. You can easily test this by logging out to the character screen and logging back in, with the following code in the main chunk:

Code:
print("Current spec is:", GetSpecialization())
On an actual login I suspect it will report "nil", though it will report the correct value on a UI reload.
This makes my results seem even weirder, as I took all event handling out of the cbCheck() function and it now works properly, both on login and on reload. Unless I'm grossly misunderstanding, it shouldn't work on login as GetSpecialization() doesn't return anything?


Originally Posted by Phanx View Post
There's nothing in the code you posted that does anything with any castbar, so I can't really help you with that.
Sorry, it was included in the OP and I hadn't changed anything important (apart from appearance, like size etc) so I didn't think to include it again. It now works!

Originally Posted by Phanx View Post
It won't work on a fresh login; see above.

OnLoad doesn't fire for frames created in Lua, and doesn't need to, as it's the same as just writing the code directly after the CreateFrame call.

If you're not using oUF:Factory already, I'd recommend you switch to it, as it will delay creating your frames until PLAYER_LOGIN, at which time information about things like your spec should be available, even on a fresh login.
I am using oUF:Factory, is this why it's working correctly despite not waiting for events to trigger the function? I don't know why, but it does work on a fresh login for both my melee Monk and my casters with the way I have it now, but changing to p3lim's check makes it behave the way you describe it, as in it doesn't work anymore.

The only difference is at line 192, the cbCheck() function
This works on a fresh login: https://gist.github.com/ShredL/d785e8761d9736d252d5
This doesn't (p3lim's check): https://gist.github.com/ShredL/f9657dd9c9538a89e9ef

Why does one work and not the other? From what I can see, the only difference is cleaning up the if statements. Printing the first (working) version of isCaster returns the correct value on fresh login and reload while printing the other one returns nil on both login and reload.

I appreciate all the help!

EDIT: This reply was messy, I was changing things around as I was testing new things etc and it got really messy. Summary is that it is working correctly when it apparently shouldn't have (first gist) and it isn't working correctly like it apparently shouldn't when using p3lim's suggestion (second gist).
__________________
All I see is strobe lights blinding me in my hindsight.

Last edited by Wimpface : 08-25-14 at 04:09 AM.
Wimpface is offline   Reply With Quote
Unread 08-25-14, 09:02 AM   #9
Vrul
A Cobalt Mageweaver
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 203
Originally Posted by Wimpface View Post
I am using oUF:Factory, is this why it's working correctly despite not waiting for events to trigger the function? I don't know why, but it does work on a fresh login for both my melee Monk and my casters with the way I have it now, but changing to p3lim's check makes it behave the way you describe it, as in it doesn't work anymore.
Since GetSpecialization() returns nil on a fresh login I have a hard time believing the code posted works on a fresh login for any caster other than a mage, priest, or warlock.

Originally Posted by Wimpface View Post
The only difference is at line 192, the cbCheck() function
This works on a fresh login: https://gist.github.com/ShredL/d785e8761d9736d252d5
This doesn't (p3lim's check): https://gist.github.com/ShredL/f9657dd9c9538a89e9ef

Why does one work and not the other? From what I can see, the only difference is cleaning up the if statements. Printing the first (working) version of isCaster returns the correct value on fresh login and reload while printing the other one returns nil on both login and reload.
The reason p3lim's version isn't working for you is that the isCaster variable is being redefined as local in the cbCheck function instead of reused. So basically you have two isCaster variables at two different scopes.

You can trim it down more with:
Code:
local isCaster
local cbCheck = function()
	if playerClass == 'DRUID' then
		isCaster = (GetSpecialization() or 0) % 3 == 1
	elseif playerClass == 'MONK' or playerClass == 'SHAMAN' then
		isCaster = GetSpecialization() == 2
	elseif playerClass == 'PALADIN' then
		isCaster = GetSpecialization() == 1
	else
		isCaster = playerClass == 'MAGE' or playerClass == 'PRIEST' or playerClass == 'WARLOCK'
	end
end
Vrul is offline   Reply With Quote
Unread 08-26-14, 12:19 AM   #10
Wimpface
A Molten Giant
 
Wimpface's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 643
Originally Posted by Vrul View Post
Since GetSpecialization() returns nil on a fresh login I have a hard time believing the code posted works on a fresh login for any caster other than a mage, priest, or warlock.
I just tested, and it does seem to work on everything...
I even made a little video to show that it works on a fresh login on my caster Shaman, my caster Mage and my melee Monk.
Excuse shoddy framerate but text should be very readable atleast:


Is it because of what Phanx said earlier about oUF:Factory delaying the creation of frames until PLAYER_LOGIN?

Don't get me wrong, I'm really happy it works, I'm just curious why it does because it apparently shouldn't, and I simply don't have the knowledge to understand the logic behind it.

Originally Posted by Vrul View Post
The reason p3lim's version isn't working for you is that the isCaster variable is being redefined as local in the cbCheck function instead of reused. So basically you have two isCaster variables at two different scopes.

You can trim it down more with:
Code:
local isCaster
local cbCheck = function()
	if playerClass == 'DRUID' then
		isCaster = (GetSpecialization() or 0) % 3 == 1
	elseif playerClass == 'MONK' or playerClass == 'SHAMAN' then
		isCaster = GetSpecialization() == 2
	elseif playerClass == 'PALADIN' then
		isCaster = GetSpecialization() == 1
	else
		isCaster = playerClass == 'MAGE' or playerClass == 'PRIEST' or playerClass == 'WARLOCK'
	end
end
Ofcourse, I should've spotted that. I'll clean it up a bit more after I wake up properly.
__________________
All I see is strobe lights blinding me in my hindsight.
Wimpface is offline   Reply With Quote
Unread 08-26-14, 08:01 AM   #11
Vrul
A Cobalt Mageweaver
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 203
Originally Posted by Wimpface View Post
I even made a little video to show that it works on a fresh login on my caster Shaman, my caster Mage and my melee Monk.
I didn't pay enough attention to notice the shaman line has it's true/false assignments reversed compared to the others.

Try your code on a druid, monk, or paladin caster; or a melee shaman, and see if it works. The only reason it works now is because when GetSpecialization() returns nil the default fall through value is what you wanted anyway (for the classes you tested).

Also, the code I posted should be changed to:
Code:
local isCaster
local cbCheck = function()
	if playerClass == 'DRUID' then
		isCaster = (GetSpecialization() or 0) % 3 == 1
	elseif playerClass == 'MONK' then
		isCaster = GetSpecialization() == 2
	elseif playerClass == 'PALADIN' then
		isCaster = GetSpecialization() == 1
	elseif playerClass == 'SHAMAN' then
		isCaster = GetSpecialization() ~= 2
	else
		isCaster = playerClass == 'MAGE' or playerClass == 'PRIEST' or playerClass == 'WARLOCK'
	end
end
You will also have an issue with a druid, monk, paladin, or shaman who changes spec from caster to non-caster (or vice versa). They will need to /reload for the castbar to update as the code stands now.
Vrul is offline   Reply With Quote
Unread 08-26-14, 10:12 AM   #12
Wimpface
A Molten Giant
 
Wimpface's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 643
Originally Posted by Vrul View Post
I didn't pay enough attention to notice the shaman line has it's true/false assignments reversed compared to the others.

Try your code on a druid, monk, or paladin caster; or a melee shaman, and see if it works. The only reason it works now is because when GetSpecialization() returns nil the default fall through value is what you wanted anyway (for the classes you tested).
Tried it out on a caster Druid and you are correct, it returns false rather than nil though. Looking at it now it just dawned on me that the reason it works for a Shaman is as you say, it falls back on true for Shamans and false for Druids because spec returns nil.

I'm going to try waiting for PLAYER_LOGIN to fire and see if that helps me.

Originally Posted by Vrul View Post
Also, the code I posted should be changed to:
Code:
local isCaster
local cbCheck = function()
	if playerClass == 'DRUID' then
		isCaster = (GetSpecialization() or 0) % 3 == 1
	elseif playerClass == 'MONK' then
		isCaster = GetSpecialization() == 2
	elseif playerClass == 'PALADIN' then
		isCaster = GetSpecialization() == 1
	elseif playerClass == 'SHAMAN' then
		isCaster = GetSpecialization() ~= 2
	else
		isCaster = playerClass == 'MAGE' or playerClass == 'PRIEST' or playerClass == 'WARLOCK'
	end
end
Thanks a bunch for this!

Originally Posted by Vrul View Post
You will also have an issue with a druid, monk, paladin, or shaman who changes spec from caster to non-caster (or vice versa). They will need to /reload for the castbar to update as the code stands now.
This I know, I was trying to get around that by listening for the PLAYER_SPECIALIZATION_CHANGED event but it wouldn't have worked that way anyway I'm fairly sure. I simply don't know how to make it change without a reload, so it's a limitation I'll live with. I'm not planning to make this layout available to the public anyway.

EDIT: Back to where it doesn't work on reload but seems to work on a fresh login now. Code here: https://gist.github.com/ShredL/1ebcc6b803a0aaab86ea

isCaster check on line 192, castbar creation at line 277. It prints isCaster correctly now, just doesn't spawn a castbar after reloading and I don't know why.
__________________
All I see is strobe lights blinding me in my hindsight.

Last edited by Wimpface : 08-26-14 at 10:19 AM.
Wimpface is offline   Reply With Quote
Unread 08-26-14, 07:39 PM   #13
Vrul
A Cobalt Mageweaver
 
Vrul's Avatar
AddOn Author - Click to view addons
Join Date: Nov 2007
Posts: 203
Try replacing:
Code:
local isCaster
local cbCheckFrame = CreateFrame("Frame")
cbCheckFrame:RegisterEvent("PLAYER_LOGIN")
cbCheckFrame:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED")
cbCheckFrame:SetScript("OnEvent", function()
	if playerClass == 'DRUID' then
		isCaster = (GetSpecialization() or 0) % 3 == 1
	elseif playerClass == 'MONK' then
		isCaster = GetSpecialization() == 2
	elseif playerClass == 'PALADIN' then
		isCaster = GetSpecialization() == 1
	elseif playerClass == 'SHAMAN' then
		isCaster = GetSpecialization() ~= 2
	else
		isCaster = playerClass == 'MAGE' or playerClass == 'PRIEST' or playerClass == 'WARLOCK'
	end
 
	print(isCaster)
end)
with:
Code:
local detectTalentChange = CreateFrame('Frame')
detectTalentChange:SetScript('OnEvent', function(self)
	if not self.unitFrame then return end

	local isCaster
	if playerClass == 'DRUID' then
		isCaster = (GetSpecialization() or 0) % 3 == 1
	elseif playerClass == 'MONK' then
		isCaster = GetSpecialization() == 2
	elseif playerClass == 'PALADIN' then
		isCaster = GetSpecialization() == 1
	elseif playerClass == 'SHAMAN' then
		isCaster = GetSpecialization() ~= 2
	else
		isCaster = playerClass == 'MAGE' or playerClass == 'PRIEST' or playerClass == 'WARLOCK'
		self:UnregisterAllEvents()
		self:SetScript('OnEvent', nil)
	end

	if isCaster ~= self.isCaster then
		self.isCaster = isCaster
		local Castbar = self.unitFrame.Castbar
		Castbar:ClearAllPoints()
		if isCaster then
			Castbar:SetPoint('TOP', self.unitFrame, 'BOTTOM', 0, -68)
			Castbar:SetStatusBarColor(1, 1, 1)
			Castbar:SetSize(barWidth, 4)
			Castbar:SetBackdrop(backdrop)
			Castbar:SetBackdropColor(0, 0, 0)
			if Castbar.Spark then
				Castbar.Spark:Hide()
			end
		else
			Castbar:SetAllPoints(self.unitFrame.Health)
			Castbar:SetStatusBarColor(1, 1, 1, 0.5)
			Castbar:SetBackdrop(nil)
			if not Castbar.Spark then
				local Spark = Castbar:CreateTexture(nil, 'OVERLAY')
				Spark:SetSize(2, 7)
				Spark:SetTexture(1, 1, 1)
				Castbar.Spark = Spark
			end
			Castbar.Spark:Show()
		end
	end
end)
detectTalentChange:RegisterEvent('ACTIVE_TALENT_GROUP_CHANGED')
detectTalentChange:RegisterEvent('PLAYER_LOGIN')
And change the Castbar portion of your Shared function to:
Code:
if(unit=='player' or unit=='target') then
	local Castbar = CreateFrame('StatusBar', nil, self)
	Castbar:SetStatusBarTexture(statusBar)
	Castbar:SetFrameStrata('HIGH')
	self.Castbar = Castbar

	if(unit=='player') then
		detectTalentChange.unitFrame = self
	else
		Castbar:SetPoint('BOTTOM', UIParent, 'CENTER', 0, 200)
		Castbar:SetStatusBarColor(1, 0, 0)
		Castbar:SetBackdrop(backdrop)
		Castbar:SetBackdropColor(0, 0, 0)
		Castbar:SetSize(350, 24)
 
		local Time = Castbar:CreateFontString(nil, 'OVERLAY', 'GameFontNormalSmall')
		Time:SetFont(nameFont, nameFontSize, 'OUTLINE')
		Time:SetTextColor(1, 1, 1)
		Time:SetPoint('RIGHT', Castbar)
		Castbar.Time = Time
 
		local Text = Castbar:CreateFontString(nil, 'OVERLAY', 'GameFontNormalSmall')
		Text:SetFont(nameFont, nameFontSize, 'OUTLINE')
		Text:SetTextColor(1, 1, 1)
		Text:SetPoint('LEFT', Castbar, 'LEFT', 4, 0)
		Castbar.Text = Text
 
		local Icon = Castbar:CreateTexture(nil, 'OVERLAY')
		Icon:SetSize(24, 24)
		Icon:SetPoint('RIGHT', Castbar, 'LEFT', -6, 0)
		Castbar.Icon = Icon
 
		local Shield = Castbar:CreateTexture(nil, 'OVERLAY')
		Shield:SetSize(64, 64)
		Shield:SetPoint('CENTER', Icon, 'CENTER', 12, 0)
		Shield:SetTexture([[Interface\CastingBar\UI-CastingBar-Arena-Shield]])
		Castbar.Shield = Shield
	end
end
The code is untested but is headed in the right direction. It uses the correct event to detect spec changes and can actually change your Castbar when they occur. One issue I'm not sure on is what oUF does with Castbar.Spark behind the scenes and if just hiding/showing it will be sufficient. This code assumes that your unit frames are created before the PLAYER_LOGIN event occurs, if this is not the case then it will need to be adjusted accordingly.
Vrul is offline   Reply With Quote
Unread 08-27-14, 03:38 AM   #14
Wimpface
A Molten Giant
 
Wimpface's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 643
It actually works perfectly, there doesn't seem to be a problem with the Spark either. I would've never figured this out, thanks for all the help!

Looking at it I could probably use this for other things such as role-specific raidframes... Hmm...
__________________
All I see is strobe lights blinding me in my hindsight.
Wimpface is offline   Reply With Quote
Reply

Go BackWoWInterface » Featured Projects » oUF (Otravi Unit Frames) » Struggling with changing variable value

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