Thread Tools Display Modes
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: 648
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.
  Reply With Quote
08-24-14, 07:24 AM   #2
Malakahh
An Aku'mai Servant
AddOn Author - Click to view addons
Join Date: Jun 2009
Posts: 30
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)
  Reply With Quote
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: 648
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.
  Reply With Quote
08-24-14, 11:29 PM   #4
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
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.)
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote
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: 648
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.
  Reply With Quote
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,710
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.
  Reply With Quote
08-25-14, 02:50 AM   #7
Phanx
Cat.
 
Phanx's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2006
Posts: 5,617
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.
__________________
Retired author of too many addons.
Message me if you're interested in taking over one of my addons.
Don’t message me about addon bugs or programming questions.
  Reply With Quote

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


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