Lua Errors with Example Implementation
Snoogens101 opened this issue ยท 6 comments
Am I doing something wrong?
Playing on Official Classic, WotLK Pre-Patch
local SwingTimerLib = LibStub("LibClassicSwingTimerAPI", true)
if not SwingTimerLib then return end
local f = CreateFrame("Frame", nil)
local SwingTimerInfo = function(hand)
return SwingTimerLib:SwingTimerInfo(hand)
end
local SwingTimerEventHandler = function(event, ...)
return f[event](f, event, ...)
end
SwingTimerLib.RegisterCallback(f, "SWING_TIMER_START", SwingTimerEventHandler)
SwingTimerLib.RegisterCallback(f, "SWING_TIMER_UPDATE", SwingTimerEventHandler)
SwingTimerLib.RegisterCallback(f, "SWING_TIMER_CLIPPED", SwingTimerEventHandler)
SwingTimerLib.RegisterCallback(f, "SWING_TIMER_PAUSED", SwingTimerEventHandler)
SwingTimerLib.RegisterCallback(f, "SWING_TIMER_STOP", SwingTimerEventHandler)
SwingTimerLib.RegisterCallback(f, "SWING_TIMER_DELTA", SwingTimerEventHandler)
If I fix the Lua errors below with guards, I only get nil, nil, nil as a return to SwingTimerInfo("mainhand").
However if I mount, funnily enough, I get a proper value for all three returns - but it also results in a Lua error for the line return f[event](f, event, ...)
(attempt to call field '?' (a nil value)).
Lua Errors before manual guards added:
attempt to perform arithmetic on field 'offSpeed' (a nil value)
function lib:PLAYER_ENTER_COMBAT()
local now = GetTime()
self.isAttacking = true
if now > (self.offExpirationTime - (self.offSpeed / 2)) then -- THIS LINE (self.offSpeed)
if self.offTimer then
self.offTimer:Cancel()
end
self:SwingStart("offhand", now, true)
end
end
attempt to compare number with nil
function lib:UNIT_ATTACK_SPEED()
if isClassic and self.class == "PALADIN" then return end -- Ignore UNIT_ATTACK_SPEED on Classic for Paladin. Seal of the Crusader snapshot. No other dynamic speed change.
local now = GetTime()
if
self.skipNextAttackSpeedUpdate
and tonumber(self.skipNextAttackSpeedUpdate)
and (now - self.skipNextAttackSpeedUpdate) < 0.04
and tonumber(self.skipNextAttackSpeedUpdateCount)
then
self.skipNextAttackSpeedUpdateCount = self.skipNextAttackSpeedUpdateCount - 1
return
end
if self.mainTimer then
self.mainTimer:Cancel()
end
if self.offTimer then
self.offTimer:Cancel()
end
local mainSpeedNew, offSpeedNew = UnitAttackSpeed("player")
offSpeedNew = offSpeedNew or 0
if mainSpeedNew > 0 and self.mainSpeed > 0 and mainSpeedNew ~= self.mainSpeed then -- THIS LINE (self.mainSpeed)
local multiplier = mainSpeedNew / self.mainSpeed
local timeLeft = (self.lastMainSwing + self.mainSpeed - now) * multiplier
self.mainSpeed = mainSpeedNew
self.mainExpirationTime = now + timeLeft
self:Fire("SWING_TIMER_UPDATE", self.mainSpeed, self.mainExpirationTime, "mainhand")
if self.mainSpeed > 0 and self.mainExpirationTime - GetTime() > 0 then
self.mainTimer = C_Timer.NewTimer(self.mainExpirationTime - GetTime(), function()
self:SwingEnd("mainhand")
end)
end
end
if offSpeedNew > 0 and self.offSpeed > 0 and offSpeedNew ~= self.offSpeed then -- THIS LINE (self.offSpeed)
local multiplier = offSpeedNew / self.offSpeed
local timeLeft = (self.lastOffSwing + self.offSpeed - now) * multiplier
self.offSpeed = offSpeedNew
self.offExpirationTime = now + timeLeft
if self.calculaDeltaTimer ~= nil then
self.calculaDeltaTimer:Cancel()
end
self:Fire("SWING_TIMER_UPDATE", self.offSpeed, self.offExpirationTime, "offhand")
if self.offSpeed > 0 and self.offExpirationTime - GetTime() > 0 then
self.offTimer = C_Timer.NewTimer(self.offExpirationTime - GetTime(), function()
self:SwingEnd("offhand")
end)
end
end
end
I think @hypernormalisation had a similar issue during it's addon implementation. On the next release we are adding a new event to the lib SWING_TIMER_INFO_INITIALIZED. This event give the possibility for addon implementation to know when the lib is initialized and all method/EVENT can be used.
@Ralgathor , I see the new event is now added, but I get the exact same issues with the latest version. Is there any special thing that needs to be done for it to work properly? It passively fails, I'm not even calling any function, I just have the lib initialized.
Well after a lot of messing around I got it to work. First problem was initialising. You only seem to do it on PLAYER_ENTER_WORLD, but so I had to add that it also inits on load.
Then the next problem is this function, no idea what it does but whatever it tries to process is always nil. I had to make it just return true to get it work.
local SwingTimerEventHandler = function(event, ...)
return f[event](f, event, ...)
end
@Snoogens101 What your exact use of the lib? If you can provide some code example maybe It can hehp to better understand your issue.
It's OK, I've managed to get it to work, I'm not sure what the purpose is of the function above but it doesn't work with it - works well without, as the function will always return nil.
Then I recommend you add some nil checks for your self.nTimer:Cancel(), was missing in one part for all of them so had to add that to avoid Lua errors when zoning. Works great tho with some tweaks!
It's OK, I've managed to get it to work, I'm not sure what the purpose is of the function above but it doesn't work with it - works well without, as the function will always return nil. Then I recommend you add some nil checks for your self.nTimer:Cancel(), was missing in one part for all of them so had to add that to avoid Lua errors when zoning. Works great tho with some tweaks!
local SwingTimerEventHandler = function(event, ...)
return f[event](f, event, ...)
end
That an exampe of an event handler you need to adapt it to your addon implementation. f is a frame you need to declare the event handled on the frame to avoid the nil like:
function f:SWING_TIMER_START()
// Whatever your addon need to do with this event
end