Go to Page... |
Thread Tools | Display Modes |
08-01-14, 11:49 AM | #1 |
Need help for troubleshooting my addon
Hey there, i would appreciate some help in troubleshooting my addon. It's the first addon i have ever written and now i am unable to find my mistake.
Basicly this error message pops up everytime i log into the game. Nevertheless it won't show up again if i /reload ui. So it only occurs at my first login. My theory: some of the data i call is not available dircetly after login (?) The error message: Code:
Message: Interface\AddOns\Shot Indicator\Shot Indicator.lua:68: attempt to perform arithmetic on upvalue 'mainSpellCost' (a nil value) Time: 08/01/14 19:45:40 Count: 1 Stack: Interface\AddOns\Shot Indicator\Shot Indicator.lua:68: in function `?' Interface\AddOns\Shot Indicator\Shot Indicator.lua:36: in function <Interface\AddOns\Shot Indicator\Shot Indicator.lua:36> Locals: self = <unnamed> { 0 = <userdata> ADDON_LOADED = <function> defined @Interface\AddOns\Shot Indicator\Shot Indicator.lua:39 PLAYER_ENTERING_WORLD = <function> defined @Interface\AddOns\Shot Indicator\Shot Indicator.lua:58 PLAYER_SPECIALIZATION_CHANGED = <function> defined @Interface\AddOns\Shot Indicator\Shot Indicator.lua:65 texture = <unnamed> { } } (*temporary) = <function> defined =[C]:-1 (*temporary) = <unnamed> { 0 = <userdata> ADDON_LOADED = <function> defined @Interface\AddOns\Shot Indicator\Shot Indicator.lua:39 PLAYER_ENTERING_WORLD = <function> defined @Interface\AddOns\Shot Indicator\Shot Indicator.lua:58 PLAYER_SPECIALIZATION_CHANGED = <function> defined @Interface\AddOns\Shot Indicator\Shot Indicator.lua:65 texture = <unnamed> { } } (*temporary) = "LEFT" (*temporary) = PlayerFrameManaBar { 0 = <userdata> currValue = 0 cvarLabel = "STATUS_TEXT_PLAYER" prefix = "Mana" textLockable = 1 disconnected = true unit = "player" cvar = "playerStatusText" capNumericDisplay = true TextString = PlayerFrameManaBarText { } powerType = 0 frequentUpdates = true lockShow = 0 } (*temporary) = <function> defined =[C]:-1 (*temporary) = 119 (*temporary) = 119 (*temporary) = nil (*temporary) = nil (*temporary) = "attempt to perform arithmetic on upvalue 'mainSpellCost' (a nil value)" f = <unnamed> { 0 = <userdata> ADDON_LOADED = <function> defined @Interface\AddOns\Shot Indicator\Shot Indicator.lua:39 PLAYER_ENTERING_WORLD = <function> defined @Interface\AddOns\Shot Indicator\Shot Indicator.lua:58 PLAYER_SPECIALIZATION_CHANGED = <function> defined @Interface\AddOns\Shot Indicator\Shot Indicator.lua:65 texture = <unnamed> { } } w = 119 mainSpellCost = nil Code:
--get locales local playerClass = select(2, UnitClass("player")) local w = PlayerFrameManaBar:GetWidth() local h = PlayerFrameManaBar:GetHeight() local mainSpells = {[253] = 34026, [254] = 53209, [255] = 53301} --kill command, chimera shot, explosive shot local mainSpellCost = 0 --update spellcost of main spells function updateSpellCost() local currentSpecId = select(1, GetSpecializationInfo(GetSpecialization())) local currentSpellCost = select(4, GetSpellInfo(mainSpells[currentSpecId])) if (currentSpellCost ~= 0) then mainSpellCost = currentSpellCost end return mainSpellCost end --update max power function updateMaxPower() local currentMaxPower = UnitPowerMax("player") if (currentMaxPower ~= 0) then maxPower = currentMaxPower end return maxPower end --create frame local f = CreateFrame("Frame") f:SetSize(2,h) f:SetPoint("LEFT", PlayerFrameManaBar, 0, 0) f:RegisterEvent("PLAYER_ENTERING_WORLD") f:RegisterEvent("ADDON_LOADED") f:RegisterEvent("PLAYER_SPECIALIZATION_CHANGED") --f:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED") f:SetScript("OnEvent", function(self, event, ...) self[event](self, ...) end) --should addon be loaded? function f:ADDON_LOADED(AddOnName) if (AddOnName == "Shot Indicator") and (playerClass ~= "HUNTER") then DisableAddOn("Shot Indicator") else print("Shot Indicator succesfully loaded!") end f:UnregisterEvent("ADDON_LOADED") end --texture stuff f.texture = f:CreateTexture(nil, "OVERLAY") f.texture:ClearAllPoints() f.texture:SetAllPoints(f) f.texture:SetTexture("Interface\\CastingBar\\UI-CastingBar-Spark") f.texture:SetTexture(0, 130, 245, 1) f.texture:SetBlendMode("ADD") f.texture:Hide() --show the indicator function f:PLAYER_ENTERING_WORLD() updateMaxPower() updateSpellCost() f:SetPoint("LEFT", PlayerFrameManaBar, math.floor((w-w*(1-mainSpellCost/maxPower))), 0) f.texture:Show() end function f:PLAYER_SPECIALIZATION_CHANGED() updateMaxPower() updateSpellCost() f:SetPoint("LEFT", PlayerFrameManaBar, math.floor((w-w*(1-mainSpellCost/maxPower))), 0) f.texture:Show() end --[[ function f:ACTIVE_TALENT_GROUP_CHANGED() updateMaxPower() updateSpellCost() f:SetPoint("LEFT", PlayerFrameManaBar, math.floor((w-w*(1-mainSpellCost/maxPower))), 0) f.texture:Show() end ]] |
|
08-01-14, 12:41 PM | #2 |
I'm no expert at reading error codes, but it seems to not like your maths. Sub line 58 (your entering world call), it seems to believe you have done something untoward with your mainSpellCost maths. That's what I got from the error code, anyway? Did you have multiple error codes? Seems odd that it would only call out line 68 and not 61 and 75.
(Like I said, not an expert on reading error codes, so someone correct me if I'm wrong. Also, this is just from reading the error. I'm not entirely certain what your addon is supposed to do. Track spell costs and focus?)
__________________
"For in the plot we find more than just a man, we find the idea of that man, the spirit of that man, and that is what we must never forget." Evey (V) |
|
08-01-14, 01:15 PM | #3 | ||
Well, it's not erroring for line 75 because that block is commented out.
Lua error messages are quite nice 90% of the time, and tell you exactly what's wrong. The stack trace you provided also lists the values of your variables at the time of the error.
Since, when you declared this upvalue, you specifically gave it a value of 0, then your issue lies where you reassign a different value to the variable. Lua Code:
Since the error is occuring in the function for the PLAYER_SPECIALIZATION_CHANGED event and not in PLAYER_ENTERING_WORLD, perhaps this event is firing before PEW. It does fire for party and raid members also. Also, talent info may not be available at PLAYER_ENTERING_WORLD. If you read here, you will find:
Try changing your code to this: Lua Code:
Oh! Also, make your two functions, updateSpellCost and updateMaxPower, local so that you're not polluting the global namespace. |
|||
08-01-14, 02:07 PM | #4 | ||
It looks like it's all coming from GetSpellInfo() in updateSpellCost(). The first time you use GetSpellInfo() in a play session and the spell you're querying hasn't been seen by the game client in that session before, it will return nil. Every query for the same spell afterward (even after a UI reload) will provide the necessary information. The reason the error doesn't persist through a UI reload is because WoW only restarts the Lua interpreter and reloads all the addon data. It doesn't go through and clear its internal data caches.
Also...
To make sure your addon only loads on hunters, you need to have your addon check before running ANY other code and stop itself if needed. To do this, you put this line at the top of your addon. Code:
if select(2,UnitClass("player"))~="HUNTER" then return; end
__________________
WoWInterface AddOns
Last edited by SDPhantom : 08-01-14 at 02:45 PM. |
|||
08-01-14, 02:31 PM | #5 | |
Spell data is all stored in the client, so it doesn't need to request the information from the server. |
||
08-01-14, 06:08 PM | #6 | |
It seems PLAYER_SPECIALIZATION_CHANGED is the culprit in this as it kept firing before PLAYER_LOGIN even though specialization data wasn't available. GetSpecialization() returns the correct value while GetSpecializationInfo() returns nil. For some reason, nil is now allowed to propagate through table indexing as a key and caused the whole chain reaction.
The following code has some other fixes and optimizations. lua Code:
Note setting a texture, then using texture:SetTexture() to set a color will overwrite the texture with a solid box of the specified color. If you wish to use a texture and change the color of it, you need to use texture:SetVertexColor(). Also, color values are percentage ranges between 0 and 1. EDIT: Removed the texture hide and show calls. These shouldn't be needed since the texture is being created, hidden, then immediately and permanently shown.
__________________
WoWInterface AddOns
Last edited by SDPhantom : 08-02-14 at 11:38 AM. |
||
08-01-14, 07:14 PM | #7 | |
However, this is still weird: Code:
function f:ADDON_LOADED(AddOnName) if (AddOnName == "Shot Indicator") and (playerClass ~= "HUNTER") then DisableAddOn("Shot Indicator") else print("Shot Indicator succesfully loaded!") end f:UnregisterEvent("ADDON_LOADED") end 2) Currently you're saying "if this event is for this addon and the player isn't a hunter, disable this addon, otherwise -- no matter which addon this event is for -- spam the chat frame with a message saying the addon was loaded". Unless you specifically want to detect and respond to other addons' loading events, check the addon first, and only proceed with anything else if it's yours: Code:
function f:ADDON_LOADED(AddOnName) if (AddOnName ~= "Shot Indicator") then return end if (playerClass ~= "HUNTER") then DisableAddOn("Shot Indicator") else print("Shot Indicator succesfully loaded!") end f:UnregisterEvent("ADDON_LOADED") end Code:
local ADDON_NAME, privateTable = ... local _, playerClass = UnitClass("player") if playerClass ~= "HUNTER" then return DisableAddOn(ADDON_NAME) end -- if you get to this point, go ahead and create your frame, register events, etc. Finally, once you get to the point where you're ready to publish your addon for others to use, please do not print "addon loaded" messages to the user's chat frame every time the addon loads. The user knows your addon is loaded -- they installed it, and made sure it was enabled, so of course it's loaded. They don't need to be reminded of this every time they log into the game. While you may not think it's a big deal, imagine what happens if you're using 100 addons, and they all print an "addon loaded" message on login -- that's a lot of spam.
__________________
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. |
||
08-02-14, 07:45 AM | #8 | |||||
How do i get the percentage ranges for the color values? I got my information from here: http://www.colorschemer.com/online.html
My changes:
First test results: SDPhantom's Code works just fine after trying it out. But i will still fiddle around with my own one and trying to get it to work for learning effects. My fine working code: Code:
--get locales local ShotIndicator, privateTable = ... local playerClass = select(2, UnitClass("player")) local w, h = PlayerFrameManaBar:GetSize() local mainSpellCost = 0 local maxPower = 0 local mainSpells = { [253] = 34026, --kill command [254] = 53209, --chimera shot [255] = 53301 --explosive shot } --should addon be loaded? if (playerClass ~= "HUNTER") then return DisableAddOn(ShotIndicator) end --update spellcost of main spells local function updateSpellCost() --local currentSpecId = select(1, GetSpecializationInfo(GetSpecialization())) local currentSpellCost = select(4, GetSpellInfo(mainSpells[GetSpecializationInfo(GetSpecialization())])) if (currentSpellCost ~= 0 and currentSpellCost ~= nil) then mainSpellCost = currentSpellCost end return mainSpellCost end --update max power local function updateMaxPower() local currentMaxPower = UnitPowerMax("player") if (currentMaxPower ~= 0 and currentMaxPower ~= nil) then maxPower = currentMaxPower end return maxPower end --create frame local f = CreateFrame("Frame") f:SetSize(2,h) f:SetPoint("LEFT", PlayerFrameManaBar, 0, 0) f:RegisterEvent("PLAYER_LOGIN") f:RegisterEvent("ACTIVE_TALENT_GROUP_CHANGED") --texture stuff f.texture = f:CreateTexture(nil, "OVERLAY") --f.texture:ClearAllPoints() f.texture:SetAllPoints(f) --f.texture:SetTexture("Interface\\CastingBar\\UI-CastingBar-Spark") f.texture:SetTexture(0,0.51,0.96,1) --was told r,g,b values are not cool enough(0, 130, 245, 1) f.texture:SetBlendMode("ADD") f.texture:Hide() f:SetScript("OnEvent", function(self, event, ...) self[event](self, ...) end) --show the indicator function f:PLAYER_LOGIN() updateMaxPower() updateSpellCost() f:SetPoint("LEFT", PlayerFrameManaBar, w*mainSpellCost/maxPower, 0) f.texture:Show() end function f:ACTIVE_TALENT_GROUP_CHANGED() updateMaxPower() updateSpellCost() f:SetPoint("LEFT", PlayerFrameManaBar, w*mainSpellCost/maxPower, 0) f.texture:Show() end Stuff i dont get:
SDPhantom can i actually use your code? It's shorter, more efficient and overall looks much smoother then mine one does. |
||||||
08-02-14, 09:00 AM | #9 |
The decimal value is just out of 255. You could just as easily use 245/255, but then you're doing some math you don't need to.
As for the private table, Blizzard passes through two arguments to every Lua file: the name of the addon the file belongs to, and a table that is locally accessible to every file in that addon. (This is so that if you need something declared in one file to be accessible in another, you don't need to make it global.) |
|
08-02-14, 09:21 AM | #10 |
Ah i see now. This is basically needed if you want to make a separate config file.
|
|
08-02-14, 11:29 AM | #11 | ||
Among the changes I made:
For future reference, if you have a choice between saving memory and saving CPU cycles, saving CPU cycles is the best way to go. The less time the CPU spends processing your code, the more time it has to render the game. This isn't an excuse to get sloppy with memory usage. Good code is finding ways to be efficient with both. PS: I made a small change to the code I posted above and removed a couple calls that were unnecessary.
__________________
WoWInterface AddOns
Last edited by SDPhantom : 08-02-14 at 11:39 AM. |
|||
WoWInterface » AddOns, Compilations, Macros » AddOn Help/Support » Need help for troubleshooting my addon |
«
Previous Thread
|
Next Thread
»
|
Display Modes |
Linear Mode |
Switch to Hybrid Mode |
Switch to Threaded Mode |
|
|