diff --git a/WeakAuras/GenericTrigger.lua b/WeakAuras/GenericTrigger.lua index 3898ffc..a60cd46 100644 --- a/WeakAuras/GenericTrigger.lua +++ b/WeakAuras/GenericTrigger.lua @@ -1774,7 +1774,7 @@ function GenericTrigger.Add(data, region) end elseif Private.InternalEventByIDList[trueEvent] then tinsert(trigger_events, trueEvent..":"..i) - elseif trueEvent:match("^UNIT_") or Private.UnitEventList[trueEvent] then + elseif trueEvent:match("^UNIT_") then isUnitEvent = true if string.lower(strsub(i, #i - 3)) == "pets" then @@ -1940,6 +1940,8 @@ do local selfGUID; local mainSpeed, offSpeed = UnitAttackSpeed("player") local casting = false + local skipNextAttack, skipNextAttackCount + local isAttacking function WeakAuras.GetSwingTimerInfo(hand) if(hand == "main") then @@ -1971,6 +1973,10 @@ do return 0, math.huge; end + local function swingTriggerUpdate() + Private.ScanEvents("SWING_TIMER_UPDATE") + end + local function swingEnd(hand) if(hand == "main") then lastSwingMain, swingDurationMain, mainSwingOffset = nil, nil, nil; @@ -1979,65 +1985,84 @@ do elseif(hand == "ranged") then lastSwingRange, swingDurationRange = nil, nil; end - Private.ScanEvents("SWING_TIMER_END"); + swingTriggerUpdate() + end + + local function swingStart(hand) + mainSpeed, offSpeed = UnitAttackSpeed("player") + offSpeed = offSpeed or 0 + local currentTime = GetTime() + if hand == "main" then + lastSwingMain = currentTime + swingDurationMain = mainSpeed + mainSwingOffset = 0 + if mainTimer then + timer:CancelTimer(mainTimer) + end + if mainSpeed and mainSpeed > 0 then + mainTimer = timer:ScheduleTimer(swingEnd, mainSpeed, hand) + else + swingEnd(hand) + end + elseif hand == "off" then + lastSwingOff = currentTime + swingDurationOff = offSpeed + if offTimer then + timer:CancelTimer(offTimer) + end + if offSpeed and offSpeed > 0 then + offTimer = timer:ScheduleTimer(swingEnd, offSpeed, hand) + else + swingEnd(hand) + end + elseif hand == "ranged" then + local rangeSpeed = UnitRangedDamage("player") + lastSwingRange = currentTime + swingDurationRange = rangeSpeed + if rangeTimer then + timer:CancelTimer(rangeTimer) + end + if rangeSpeed and rangeSpeed > 0 then + rangeTimer = timer:ScheduleTimer(swingEnd, rangeSpeed, hand) + else + swingEnd(hand) + end + end end local function swingTimerCLEUCheck(ts, event, sourceGUID, _, _, destGUID, _, _, ...) Private.StartProfileSystem("generictrigger swing"); if(sourceGUID == selfGUID) then - if(event == "SWING_DAMAGE" or event == "SWING_MISSED") then - local isOffHand = select(event == "SWING_DAMAGE" and 10 or 2, ...); - - local event; - local currentTime = GetTime(); - mainSpeed, offSpeed = UnitAttackSpeed("player"); - offSpeed = offSpeed or 0; - if not(lastSwingMain) then - lastSwingMain = currentTime; - swingDurationMain = mainSpeed; - mainSwingOffset = 0; - event = "SWING_TIMER_START"; - timer:CancelTimer(mainTimer); - mainTimer = timer:ScheduleTimer(swingEnd, mainSpeed, "main"); - elseif(OffhandHasWeapon() and not lastSwingOff) then - lastSwingOff = currentTime; - swingDurationOff = offSpeed; - event = "SWING_TIMER_START"; - timer:CancelTimer(offTimer); - offTimer = timer:ScheduleTimer(swingEnd, offSpeed, "off"); - else - -- A swing occurred while both weapons are supposed to be on cooldown - -- Simply refresh the timer of the weapon swing which would have ended sooner - local mainRem, offRem = (lastSwingMain or math.huge) + mainSpeed - currentTime, (lastSwingOff or math.huge) + offSpeed - currentTime; - if(mainRem < offRem or not OffhandHasWeapon()) then - timer:CancelTimer(mainTimer, true); - lastSwingMain = currentTime; - swingDurationMain = mainSpeed; - event = "SWING_TIMER_CHANGE"; - mainTimer = timer:ScheduleTimer(swingEnd, mainSpeed, "main"); - else - timer:CancelTimer(mainTimer, true); - lastSwingOff = currentTime; - swingDurationOff = offSpeed; - event = "SWING_TIMER_CHANGE"; - offTimer = timer:ScheduleTimer(swingEnd, offSpeed, "off"); + if event == "SPELL_EXTRA_ATTACKS" then + skipNextAttack = ts + skipNextAttackCount = select(4, ...) + elseif(event == "SWING_DAMAGE" or event == "SWING_MISSED") then + if tonumber(skipNextAttack) and (ts - skipNextAttack) < 0.04 and tonumber(skipNextAttackCount) then + if skipNextAttackCount > 0 then + skipNextAttackCount = skipNextAttackCount - 1 + return end end - Private.ScanEvents(event); + local isOffHand = select(event == "SWING_DAMAGE" and 10 or 2, ...); + if not isOffHand then + swingStart("main") + elseif(isOffHand) then + swingStart("off") + end + swingTriggerUpdate() end - elseif (destGUID == selfGUID and (select(1, ...) == "PARRY" or select(4, ...) == "PARRY")) then + elseif (destGUID == selfGUID and (... == "PARRY" or select(4, ...) == "PARRY")) then if (lastSwingMain) then - local timeLeft = lastSwingMain + swingDurationMain - GetTime(); - if (timeLeft > 0.6 * swingDurationMain) then + local timeLeft = lastSwingMain + swingDurationMain - GetTime() - (mainSwingOffset or 0); + if (timeLeft > 0.2 * swingDurationMain) then + local offset = 0.4 * swingDurationMain + if (timeLeft - offset < 0.2 * swingDurationMain) then + offset = timeLeft - 0.2 * swingDurationMain + end timer:CancelTimer(mainTimer); - mainTimer = timer:ScheduleTimer(swingEnd, timeLeft - 0.4 * swingDurationMain, "main"); - mainSwingOffset = 0.4 * swingDurationMain - Private.ScanEvents("SWING_TIMER_CHANGE"); - elseif (timeLeft > 0.2 * swingDurationMain) then - timer:CancelTimer(mainTimer); - mainTimer = timer:ScheduleTimer(swingEnd, timeLeft - 0.2 * swingDurationMain, "main"); - mainSwingOffset = 0.2 * swingDurationMain - Private.ScanEvents("SWING_TIMER_CHANGE"); + mainTimer = timer:ScheduleTimer(swingEnd, timeLeft - offset, "main"); + mainSwingOffset = (mainSwingOffset or 0) + offset + swingTriggerUpdate() end end end @@ -2045,8 +2070,9 @@ do end local function swingTimerCheck(event, unit, spell) - if unit ~= "player" then return end + if event ~= "PLAYER_EQUIPMENT_CHANGED" and unit and unit ~= "player" then return end Private.StartProfileSystem("generictrigger swing"); + local now = GetTime() if event == "UNIT_ATTACK_SPEED" then local mainSpeedNew, offSpeedNew = UnitAttackSpeed("player") offSpeedNew = offSpeedNew or 0 @@ -2054,64 +2080,60 @@ do if mainSpeedNew ~= mainSpeed then timer:CancelTimer(mainTimer) local multiplier = mainSpeedNew / mainSpeed - local timeLeft = (lastSwingMain + swingDurationMain - GetTime()) * multiplier + local timeLeft = (lastSwingMain + swingDurationMain - now) * multiplier swingDurationMain = mainSpeedNew + mainSwingOffset = (lastSwingMain + swingDurationMain) - (now + timeLeft) mainTimer = timer:ScheduleTimer(swingEnd, timeLeft, "main") - Private.ScanEvents("SWING_TIMER_CHANGE") end end if lastSwingOff then if offSpeedNew ~= offSpeed then timer:CancelTimer(offTimer) local multiplier = offSpeedNew / mainSpeed - local timeLeft = (lastSwingOff + swingDurationOff - GetTime()) * multiplier + local timeLeft = (lastSwingOff + swingDurationOff - now) * multiplier swingDurationOff = offSpeedNew offTimer = timer:ScheduleTimer(swingEnd, timeLeft, "off") - Private.ScanEvents("SWING_TIMER_CHANGE") end end mainSpeed, offSpeed = mainSpeedNew, offSpeedNew + swingTriggerUpdate() elseif casting and (event == "UNIT_SPELLCAST_INTERRUPTED" or event == "UNIT_SPELLCAST_FAILED") then casting = false + elseif event == "PLAYER_EQUIPMENT_CHANGED" and isAttacking then + swingStart("main") + swingStart("off") + swingStart("ranged") + swingTriggerUpdate() elseif event == "UNIT_SPELLCAST_SUCCEEDED" then if Private.reset_swing_spells[spell] or casting then if casting then casting = false end - local event; - mainSpeed, offSpeed = UnitAttackSpeed("player"); - lastSwingMain = GetTime(); - swingDurationMain = mainSpeed; - mainSwingOffset = 0; - if (lastSwingMain) then - timer:CancelTimer(mainTimer); - event = "SWING_TIMER_CHANGE"; - else - event = "SWING_TIMER_START"; - end - mainTimer = timer:ScheduleTimer(swingEnd, mainSpeed, "main"); - Private.ScanEvents(event); - elseif Private.reset_ranged_swing_spells[spell] then - local event; - local currentTime = GetTime(); - local speed = UnitRangedDamage("player"); - if(lastSwingRange) then - timer:CancelTimer(rangeTimer, true) - event = "SWING_TIMER_CHANGE"; - else - event = "SWING_TIMER_START"; - end - lastSwingRange = currentTime; - swingDurationRange = speed; - rangeTimer = timer:ScheduleTimer(swingEnd, speed, "ranged"); - Private.ScanEvents(event); + -- check next frame + swingTimerFrame:SetScript("OnUpdate", function(self) + if isAttacking then + swingStart("main") + swingTriggerUpdate() + end + self:SetScript("OnUpdate", nil) + end) + end + if Private.reset_ranged_swing_spells[spell] then + swingStart("ranged") + swingTriggerUpdate() end elseif event == "UNIT_SPELLCAST_START" then - -- pause swing timer - casting = true - lastSwingMain, swingDurationMain, mainSwingOffset = nil, nil, nil - lastSwingOff, swingDurationOff = nil, nil - Private.ScanEvents("SWING_TIMER_END") + if not Private.noreset_swing_spells[spell] then + -- pause swing timer + casting = true + lastSwingMain, swingDurationMain, mainSwingOffset = nil, nil, nil + lastSwingOff, swingDurationOff = nil, nil + swingTriggerUpdate() + end + elseif event == "PLAYER_REGEN_DISABLED" then + isAttacking = true + elseif event == "PLAYER_REGEN_ENABLED" then + isAttacking = nil end Private.StopProfileSystem("generictrigger swing"); end @@ -2120,7 +2142,9 @@ do if not(swingTimerFrame) then swingTimerFrame = CreateFrame("Frame"); swingTimerFrame:RegisterEvent("COMBAT_LOG_EVENT_UNFILTERED"); - swingTimerFrame:RegisterEvent("PLAYER_ENTER_COMBAT"); + swingTimerFrame:RegisterEvent("PLAYER_REGEN_DISABLED"); + swingTimerFrame:RegisterEvent("PLAYER_REGEN_ENABLED"); + swingTimerFrame:RegisterEvent("PLAYER_EQUIPMENT_CHANGED"); swingTimerFrame:RegisterEvent("UNIT_ATTACK_SPEED"); swingTimerFrame:RegisterEvent("UNIT_SPELLCAST_SUCCEEDED"); swingTimerFrame:RegisterEvent("UNIT_SPELLCAST_START") diff --git a/WeakAuras/Prototypes.lua b/WeakAuras/Prototypes.lua index 77a62d4..496d1fc 100644 --- a/WeakAuras/Prototypes.lua +++ b/WeakAuras/Prototypes.lua @@ -4434,9 +4434,6 @@ Private.event_prototypes = { type = "unit", events = {}, internal_events = { - "SWING_TIMER_START", - "SWING_TIMER_CHANGE", - "SWING_TIMER_END", "SWING_TIMER_UPDATE" }, force_events = "SWING_TIMER_UPDATE", @@ -4532,6 +4529,10 @@ Private.event_prototypes = { { hidden = true, test = "(inverse and duration == 0) or (not inverse and duration > 0)" + }, + { + hidden = true, + test = "remainingCheck" } }, automaticrequired = true, diff --git a/WeakAuras/Types.lua b/WeakAuras/Types.lua index c25746d..e453624 100644 --- a/WeakAuras/Types.lua +++ b/WeakAuras/Types.lua @@ -3208,7 +3208,10 @@ Private.reset_swing_spells = { [GetSpellInfo(20549)] = true, -- War Stomp [GetSpellInfo(56815)] = true, -- Rune Strike [GetSpellInfo(5384)] = true, -- Feign Death + [GetSpellInfo(2764)] = true, -- Throw + [GetSpellInfo(5019)] = true, -- Shoot } + Private.reset_ranged_swing_spells = { [GetSpellInfo(2764)] = true, -- Throw [GetSpellInfo(5019)] = true, -- Shoot Wands @@ -3216,6 +3219,39 @@ Private.reset_ranged_swing_spells = { [GetSpellInfo(5384)] = true, -- Feign Death } +Private.noreset_swing_spells = { + [GetSpellInfo(23063)] = true, -- Dense Dynamite + [GetSpellInfo(4054)] = true, -- Rough Dynamite + [GetSpellInfo(4064)] = true, -- Rough Copper Bomb + [GetSpellInfo(4061)] = true, -- Coarse Dynamite + [GetSpellInfo(8331)] = true, -- Ez-Thro Dynamite + [GetSpellInfo(4065)] = true, -- Large Copper Bomb + [GetSpellInfo(4066)] = true, -- Small Bronze Bomb + [GetSpellInfo(4062)] = true, -- Heavy Dynamite + [GetSpellInfo(4067)] = true, -- Big Bronze Bomb + [GetSpellInfo(4068)] = true, -- Iron Grenade + [GetSpellInfo(23000)] = true, -- Ez-Thro Dynamite II + [GetSpellInfo(12421)] = true, -- Mithril Frag Bomb + [GetSpellInfo(4069)] = true, -- Big Iron Bomb + [GetSpellInfo(12562)] = true, -- The Big One + [GetSpellInfo(12543)] = true, -- Hi-Explosive Bomb + [GetSpellInfo(19769)] = true, -- Thorium Grenade + [GetSpellInfo(19784)] = true, -- Dark Iron Bomb + [GetSpellInfo(30216)] = true, -- Fel Iron Bomb + [GetSpellInfo(19821)] = true, -- Arcane Bomb + [GetSpellInfo(39965)] = true, -- Frost Grenade + [GetSpellInfo(30461)] = true, -- The Bigger One + [GetSpellInfo(30217)] = true, -- Adamantite Grenade + [GetSpellInfo(35476)] = true, -- Drums of Battle + [GetSpellInfo(35475)] = true, -- Drums of War + [GetSpellInfo(35477)] = true, -- Drums of Speed + [GetSpellInfo(35478)] = true, -- Drums of Restoration + [GetSpellInfo(34120)] = true, -- Steady Shot (rank 1) + [GetSpellInfo(19434)] = true, -- Aimed Shot (rank 1) + [GetSpellInfo(1464)] = true, -- Slam (rank 1) + --35474 Drums of Panic DO reset the swing timer, do not add +} + WeakAuras.StopMotion = WeakAuras.StopMotion or {} WeakAuras.StopMotion.texture_types = WeakAuras.StopMotion.texture_types or {} WeakAuras.StopMotion.texture_data = WeakAuras.StopMotion.texture_data or {}