mirror of
https://github.com/brues-code/pfUI.git
synced 2026-10-13 17:00:49 +00:00
predict + libdebuff + swingtimer: drop hardcoded spell data
Replace per-locale name tables and per-rank ID lists with single
canonical-rank lookups through C_Spell. Spell.dbc bits hoisted to
named constants at module top.
libpredict:
- Four 7-locale tables (PRAYER_OF_HEALING / REJUVENATION / RENEW /
REGROWTH) collapsed to one C_Spell.GetSpellName(rank1id) call each.
- 25-entry SPELL_IDS (all ranks of Rejuv + Renew) for SPELL_GO_SELF
HoT detection replaced by name comparison against REJUVENATION /
RENEW. No per-rank ID maintenance.
libdebuff:
- GetSpellRecField(id, "name") → C_Spell.GetSpellName(id) at all call
sites; the presence-guard pattern is gone (ClassicAPI is a hard
dep, per memory).
- GetSpellRecField(id, "rank") → C_Spell.GetSpellSubtext(id).
swingtimer:
- Hoist FLAG_AUTOATTACK / ATTR_KEEP_SWINGS / ATTR_ON_NEXT_SWING to
module-top constants via tonumber("0xNN", 16) so the SPELL_GO_SELF
hot path stops re-parsing them on every call. Lua 5.0 has no hex
number literals; strtoul-backed tonumber handles the "0x" prefix.
This commit is contained in:
+13
-13
@@ -427,7 +427,7 @@ local function GetDebuffSlotMap(guid)
|
|||||||
local spellId = auras[auraSlot]
|
local spellId = auras[auraSlot]
|
||||||
if spellId and spellId > 0 then
|
if spellId and spellId > 0 then
|
||||||
displaySlot = displaySlot + 1
|
displaySlot = displaySlot + 1
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
local texture = libdebuff:GetSpellIcon(spellId)
|
local texture = libdebuff:GetSpellIcon(spellId)
|
||||||
local stacks = (auraApps and auraApps[auraSlot] or 0) + 1
|
local stacks = (auraApps and auraApps[auraSlot] or 0) + 1
|
||||||
local dtype = nil
|
local dtype = nil
|
||||||
@@ -1024,7 +1024,7 @@ if hasNampower then
|
|||||||
local targetGuid = arg4
|
local targetGuid = arg4
|
||||||
local numHit = arg6 or 0
|
local numHit = arg6 or 0
|
||||||
local numMissed = arg7 or 0
|
local numMissed = arg7 or 0
|
||||||
|
|
||||||
-- Fire registered SPELL_GO_SELF hooks BEFORE miss guard
|
-- Fire registered SPELL_GO_SELF hooks BEFORE miss guard
|
||||||
-- (Swingtimer needs to see ALL casts, even misses, for swing reset)
|
-- (Swingtimer needs to see ALL casts, even misses, for swing reset)
|
||||||
if event == "SPELL_GO_SELF" and pfUI.libdebuff_spell_go_hooks then
|
if event == "SPELL_GO_SELF" and pfUI.libdebuff_spell_go_hooks then
|
||||||
@@ -1035,15 +1035,15 @@ if hasNampower then
|
|||||||
|
|
||||||
if numMissed > 0 or numHit == 0 then return end
|
if numMissed > 0 or numHit == 0 then return end
|
||||||
|
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
local spellRankString = GetSpellRecField and GetSpellRecField(spellId, "rank")
|
|
||||||
if not spellName then return end
|
if not spellName then return end
|
||||||
|
local spellRankString = C_Spell.GetSpellSubtext(spellId)
|
||||||
|
|
||||||
local castRank = 0
|
local castRank = 0
|
||||||
if spellRankString and spellRankString ~= "" then
|
if spellRankString and spellRankString ~= "" then
|
||||||
castRank = tonumber((string.gsub(spellRankString, "Rank ", ""))) or 0
|
castRank = tonumber((string.gsub(spellRankString, "Rank ", ""))) or 0
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Store in pendingCasts for DEBUFF_ADDED correlation.
|
-- Store in pendingCasts for DEBUFF_ADDED correlation.
|
||||||
-- If this cast is a downrank of an already active debuff, fire the downrank blocked hook
|
-- If this cast is a downrank of an already active debuff, fire the downrank blocked hook
|
||||||
-- so external addons (e.g. SuperCleveRoidMacros) don't need to re-implement this check.
|
-- so external addons (e.g. SuperCleveRoidMacros) don't need to re-implement this check.
|
||||||
@@ -1209,7 +1209,7 @@ if hasNampower then
|
|||||||
if not spellId then return end
|
if not spellId then return end
|
||||||
if not targetGuid or targetGuid == "" or targetGuid == "0x0000000000000000" then return end
|
if not targetGuid or targetGuid == "" or targetGuid == "0x0000000000000000" then return end
|
||||||
|
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
if not spellName then return end
|
if not spellName then return end
|
||||||
|
|
||||||
-- Deduplicate: Ignore if we processed this exact cast recently (within 100ms)
|
-- Deduplicate: Ignore if we processed this exact cast recently (within 100ms)
|
||||||
@@ -1469,7 +1469,7 @@ if hasNampower then
|
|||||||
|
|
||||||
-- Invalidate slot map cache for this GUID
|
-- Invalidate slot map cache for this GUID
|
||||||
|
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
if not spellName then return end
|
if not spellName then return end
|
||||||
|
|
||||||
if debugStats.enabled then
|
if debugStats.enabled then
|
||||||
@@ -1599,9 +1599,9 @@ if hasNampower then
|
|||||||
local auraSlot = auraSlot_0based and (auraSlot_0based + 1) or nil
|
local auraSlot = auraSlot_0based and (auraSlot_0based + 1) or nil
|
||||||
|
|
||||||
-- Invalidate slot map cache for this GUID
|
-- Invalidate slot map cache for this GUID
|
||||||
|
|
||||||
local spellName = (GetSpellRecField and GetSpellRecField(spellId, "name")) or "?"
|
local spellName = C_Spell.GetSpellName(spellId) or "?"
|
||||||
|
|
||||||
if debugStats.enabled then
|
if debugStats.enabled then
|
||||||
debugStats.debuff_removed = debugStats.debuff_removed + 1
|
debugStats.debuff_removed = debugStats.debuff_removed + 1
|
||||||
if IsCurrentTarget(guid) then
|
if IsCurrentTarget(guid) then
|
||||||
@@ -1609,13 +1609,13 @@ if hasNampower then
|
|||||||
GetDebugTimestamp(), displaySlot, auraSlot or -1, auraSlot_0based or -1, spellName))
|
GetDebugTimestamp(), displaySlot, auraSlot or -1, auraSlot_0based or -1, spellName))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- If unit is dead, cleanup all
|
-- If unit is dead, cleanup all
|
||||||
if UnitIsDead and UnitIsDead(guid) then
|
if UnitIsDead and UnitIsDead(guid) then
|
||||||
CleanupUnit(guid)
|
CleanupUnit(guid)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get auraSlot from event parameter (Nampower 2.29+)
|
-- Get auraSlot from event parameter (Nampower 2.29+)
|
||||||
-- Fallback to displayToAura mapping if not available
|
-- Fallback to displayToAura mapping if not available
|
||||||
local foundAuraSlot = auraSlot
|
local foundAuraSlot = auraSlot
|
||||||
|
|||||||
+21
-81
@@ -44,78 +44,13 @@ local healGuidToName = {} -- [casterGuid] = casterName, for SPELL_FAILED_OTHER c
|
|||||||
local ress_timers = {} -- [target][sender] = expiry_timestamp (60s rez window)
|
local ress_timers = {} -- [target][sender] = expiry_timestamp (60s rez window)
|
||||||
local RESS_TIMEOUT = 60 -- Vanilla: rez offer expires after 60s
|
local RESS_TIMEOUT = 60 -- Vanilla: rez offer expires after 60s
|
||||||
|
|
||||||
local PRAYER_OF_HEALING
|
-- Localized spell names resolved once from canonical rank-1 spellIDs.
|
||||||
do -- Prayer of Healing
|
-- Every rank shares the same name, so per-rank comparisons elsewhere can
|
||||||
local locales = {
|
-- be done against these constants without per-locale or per-rank tables.
|
||||||
["deDE"] = "Gebet der Heilung",
|
local PRAYER_OF_HEALING = C_Spell.GetSpellName(596) -- Prayer of Healing (Rank 1)
|
||||||
["enUS"] = "Prayer of Healing",
|
local REJUVENATION = C_Spell.GetSpellName(774) -- Rejuvenation (Rank 1)
|
||||||
["esES"] = "Rezo de curación",
|
local RENEW = C_Spell.GetSpellName(139) -- Renew (Rank 1)
|
||||||
["frFR"] = "Prière de soins",
|
local REGROWTH = C_Spell.GetSpellName(8936) -- Regrowth (Rank 1)
|
||||||
["koKR"] = "치유의 기원",
|
|
||||||
["ruRU"] = "Молитва исцеления",
|
|
||||||
["zhCN"] = "治疗祷言",
|
|
||||||
}
|
|
||||||
|
|
||||||
PRAYER_OF_HEALING = locales[GetLocale()] or locales["enUS"]
|
|
||||||
end
|
|
||||||
|
|
||||||
local REJUVENATION
|
|
||||||
do -- Rejuvenation
|
|
||||||
local locales = {
|
|
||||||
["deDE"] = "Verjüngung",
|
|
||||||
["enUS"] = "Rejuvenation",
|
|
||||||
["esES"] = "Rejuvenecimiento",
|
|
||||||
["frFR"] = "Récupération",
|
|
||||||
["koKR"] = "회복",
|
|
||||||
["ruRU"] = "Омоложение",
|
|
||||||
["zhCN"] = "回春术",
|
|
||||||
}
|
|
||||||
|
|
||||||
REJUVENATION = locales[GetLocale()] or locales["enUS"]
|
|
||||||
end
|
|
||||||
|
|
||||||
local RENEW
|
|
||||||
do -- Renew
|
|
||||||
local locales = {
|
|
||||||
["deDE"] = "Erneuerung",
|
|
||||||
["enUS"] = "Renew",
|
|
||||||
["esES"] = "Renovar",
|
|
||||||
["frFR"] = "Rénovation",
|
|
||||||
["koKR"] = "소생",
|
|
||||||
["ruRU"] = "Обновление",
|
|
||||||
["zhCN"] = "恢复",
|
|
||||||
}
|
|
||||||
|
|
||||||
RENEW = locales[GetLocale()] or locales["enUS"]
|
|
||||||
end
|
|
||||||
|
|
||||||
local REGROWTH
|
|
||||||
do -- Regrowth
|
|
||||||
local locales = {
|
|
||||||
["deDE"] = "Nachwachsen",
|
|
||||||
["enUS"] = "Regrowth",
|
|
||||||
["esES"] = "Recrecimiento",
|
|
||||||
["frFR"] = "Rétablissement",
|
|
||||||
["koKR"] = "재생",
|
|
||||||
["ruRU"] = "Восстановление",
|
|
||||||
["zhCN"] = "愈合",
|
|
||||||
}
|
|
||||||
|
|
||||||
REGROWTH = locales[GetLocale()] or locales["enUS"]
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
-- Spell IDs for SPELL_GO_SELF callback (Nampower) - Instant HoT detection
|
|
||||||
local SPELL_IDS = {
|
|
||||||
-- Rejuvenation (all ranks)
|
|
||||||
[774] = "Reju", [1058] = "Reju", [1430] = "Reju", [2090] = "Reju", [2091] = "Reju",
|
|
||||||
[3627] = "Reju", [8910] = "Reju", [9839] = "Reju", [9840] = "Reju", [9841] = "Reju",
|
|
||||||
[25299] = "Reju", [26981] = "Reju", [26982] = "Reju",
|
|
||||||
-- Renew (all ranks)
|
|
||||||
[139] = "Renew", [6074] = "Renew", [6075] = "Renew", [6076] = "Renew", [6077] = "Renew",
|
|
||||||
[6078] = "Renew", [10927] = "Renew", [10928] = "Renew", [10929] = "Renew", [25315] = "Renew",
|
|
||||||
[25221] = "Renew", [25222] = "Renew",
|
|
||||||
}
|
|
||||||
|
|
||||||
local libpredict = CreateFrame("Frame")
|
local libpredict = CreateFrame("Frame")
|
||||||
libpredict:RegisterEvent("UNIT_HEALTH")
|
libpredict:RegisterEvent("UNIT_HEALTH")
|
||||||
@@ -173,7 +108,7 @@ end
|
|||||||
|
|
||||||
local function isRezSpell(spellId)
|
local function isRezSpell(spellId)
|
||||||
if not L["resurrections"] then return false end
|
if not L["resurrections"] then return false end
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
return spellName and L["resurrections"][spellName]
|
return spellName and L["resurrections"][spellName]
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -192,7 +127,7 @@ end)
|
|||||||
-- SPELL_START_SELF: own cast started (heals + rez)
|
-- SPELL_START_SELF: own cast started (heals + rez)
|
||||||
pfUI.libdebuff_spell_start_self_hooks = pfUI.libdebuff_spell_start_self_hooks or {}
|
pfUI.libdebuff_spell_start_self_hooks = pfUI.libdebuff_spell_start_self_hooks or {}
|
||||||
pfUI.libdebuff_spell_start_self_hooks["libpredict"] = function(spellId, casterGuid, targetGuid, castTime)
|
pfUI.libdebuff_spell_start_self_hooks["libpredict"] = function(spellId, casterGuid, targetGuid, castTime)
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
if not spellName then return end
|
if not spellName then return end
|
||||||
|
|
||||||
local pendingTarget = nil
|
local pendingTarget = nil
|
||||||
@@ -319,7 +254,7 @@ end
|
|||||||
-- SPELL_GO_SELF: own cast landed (HealStop + Regrowth timer)
|
-- SPELL_GO_SELF: own cast landed (HealStop + Regrowth timer)
|
||||||
pfUI.libdebuff_spell_go_hooks["libpredict_sender"] = function(spellId)
|
pfUI.libdebuff_spell_go_hooks["libpredict_sender"] = function(spellId)
|
||||||
libpredict:HealStop(player)
|
libpredict:HealStop(player)
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
if spellName == REGROWTH then
|
if spellName == REGROWTH then
|
||||||
local now = pfUI.uf.now or GetTime()
|
local now = pfUI.uf.now or GetTime()
|
||||||
if libpredict.sender.regrowth_timer then
|
if libpredict.sender.regrowth_timer then
|
||||||
@@ -337,7 +272,7 @@ end
|
|||||||
-- Signature: fn(spellId, casterGuid, targetGuid, castTime)
|
-- Signature: fn(spellId, casterGuid, targetGuid, castTime)
|
||||||
pfUI.libdebuff_spell_start_other_hooks = pfUI.libdebuff_spell_start_other_hooks or {}
|
pfUI.libdebuff_spell_start_other_hooks = pfUI.libdebuff_spell_start_other_hooks or {}
|
||||||
pfUI.libdebuff_spell_start_other_hooks["libpredict"] = function(spellId, casterGuid, targetGuid, castTime)
|
pfUI.libdebuff_spell_start_other_hooks["libpredict"] = function(spellId, casterGuid, targetGuid, castTime)
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
if not spellName then return end
|
if not spellName then return end
|
||||||
|
|
||||||
local casterName = resolveNameFromGuid(casterGuid)
|
local casterName = resolveNameFromGuid(casterGuid)
|
||||||
@@ -404,8 +339,13 @@ end
|
|||||||
-- Signature: fn(spellId, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
|
-- Signature: fn(spellId, arg1, arg2, arg3, arg4, arg5, arg6, arg7)
|
||||||
pfUI.libdebuff_spell_go_hooks = pfUI.libdebuff_spell_go_hooks or {}
|
pfUI.libdebuff_spell_go_hooks = pfUI.libdebuff_spell_go_hooks or {}
|
||||||
pfUI.libdebuff_spell_go_hooks["libpredict"] = function(spellId, a1, a2, a3, a4, a5, a6, a7)
|
pfUI.libdebuff_spell_go_hooks["libpredict"] = function(spellId, a1, a2, a3, a4, a5, a6, a7)
|
||||||
-- Instant HoTs
|
-- Instant HoTs — classify by name (rank-independent) instead of a
|
||||||
local hotType = SPELL_IDS[spellId]
|
-- hardcoded per-rank ID table.
|
||||||
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
|
local hotType
|
||||||
|
if spellName == REJUVENATION then hotType = "Reju"
|
||||||
|
elseif spellName == RENEW then hotType = "Renew"
|
||||||
|
end
|
||||||
if hotType then
|
if hotType then
|
||||||
local targetGuid = a4
|
local targetGuid = a4
|
||||||
local targetName = resolveNameFromGuid(targetGuid)
|
local targetName = resolveNameFromGuid(targetGuid)
|
||||||
@@ -1236,7 +1176,7 @@ libpredict.sender:SetScript("OnEvent", function()
|
|||||||
local amount = arg4
|
local amount = arg4
|
||||||
local isCrit = arg5 == 1
|
local isCrit = arg5 == 1
|
||||||
local isPeriodic = arg6 == 1
|
local isPeriodic = arg6 == 1
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
if spellName and spell_queue[1] == spellName then
|
if spellName and spell_queue[1] == spellName then
|
||||||
UpdateCache(spell_queue[2], amount, isCrit)
|
UpdateCache(spell_queue[2], amount, isCrit)
|
||||||
end
|
end
|
||||||
@@ -1256,9 +1196,9 @@ libpredict.sender:SetScript("OnEvent", function()
|
|||||||
local casterName = resolveNameFromGuid(casterGuid)
|
local casterName = resolveNameFromGuid(casterGuid)
|
||||||
if not casterName or casterName == player then return end -- own heals handled by SPELL_HEAL_BY_SELF
|
if not casterName or casterName == player then return end -- own heals handled by SPELL_HEAL_BY_SELF
|
||||||
|
|
||||||
local spellName = GetSpellRecField and GetSpellRecField(spellId, "name")
|
local spellName = C_Spell.GetSpellName(spellId)
|
||||||
if not spellName then return end
|
if not spellName then return end
|
||||||
local rankStr = GetSpellRecField and GetSpellRecField(spellId, "rank") or ""
|
local rankStr = C_Spell.GetSpellSubtext(spellId)
|
||||||
local spellKey = spellName .. (rankStr or "")
|
local spellKey = spellName .. (rankStr or "")
|
||||||
|
|
||||||
foreignCache[casterName] = foreignCache[casterName] or {}
|
foreignCache[casterName] = foreignCache[casterName] or {}
|
||||||
|
|||||||
+12
-10
@@ -10,6 +10,11 @@ pfUI:RegisterModule("swingtimer", function ()
|
|||||||
local ON_SWING_QUEUED = 0
|
local ON_SWING_QUEUED = 0
|
||||||
local ON_SWING_QUEUE_POPPED = 1
|
local ON_SWING_QUEUE_POPPED = 1
|
||||||
|
|
||||||
|
-- Spell.dbc bits used to mirror server-side swing-reset rules.
|
||||||
|
local FLAG_AUTOATTACK = tonumber("0x08", 16) -- SPELL_INTERRUPT_FLAG_AUTOATTACK
|
||||||
|
local ATTR_KEEP_SWINGS = tonumber("0x20000", 16) -- SPELL_ATTR_EX2_NOT_RESET_AUTO_ACTIONS
|
||||||
|
local ATTR_ON_NEXT_SWING = tonumber("0x04", 16) -- SPELL_ATTR_ON_NEXT_SWING
|
||||||
|
|
||||||
-- Consolidate state into a table to avoid Lua 5.0 upvalue limit (32 max)
|
-- Consolidate state into a table to avoid Lua 5.0 upvalue limit (32 max)
|
||||||
local S = {
|
local S = {
|
||||||
mhTimer = 0, mhTimerMax = 1,
|
mhTimer = 0, mhTimerMax = 1,
|
||||||
@@ -39,9 +44,8 @@ pfUI:RegisterModule("swingtimer", function ()
|
|||||||
local WAND_SHOOT_SPELLID = 5019
|
local WAND_SHOOT_SPELLID = 5019
|
||||||
local THROW_SPELLID = 2764 -- one-shot ranged, not auto-repeat
|
local THROW_SPELLID = 2764 -- one-shot ranged, not auto-repeat
|
||||||
|
|
||||||
-- SPELL_ATTR_ON_NEXT_SWING (bit 2, value 4): spell replaces next auto-attack swing.
|
-- ATTR_ON_NEXT_SWING: spell replaces next auto-attack swing.
|
||||||
-- Covers Raptor Strike, Maul, Mongoose Bite, Holy Strike, etc. automatically.
|
-- Covers Raptor Strike, Maul, Mongoose Bite, Holy Strike, etc. automatically.
|
||||||
local ATTR_ON_NEXT_SWING = 4
|
|
||||||
local function IsOnSwingSpell(spellId)
|
local function IsOnSwingSpell(spellId)
|
||||||
if S.onSwingCache[spellId] ~= nil then return S.onSwingCache[spellId] end
|
if S.onSwingCache[spellId] ~= nil then return S.onSwingCache[spellId] end
|
||||||
local attr = GetSpellRecField(spellId, "attributes") or 0
|
local attr = GetSpellRecField(spellId, "attributes") or 0
|
||||||
@@ -702,12 +706,12 @@ pfUI:RegisterModule("swingtimer", function ()
|
|||||||
-- Freeze the swing timer for cast-time spells that DON'T reset auto-
|
-- Freeze the swing timer for cast-time spells that DON'T reset auto-
|
||||||
-- attack on completion (Slam, Hammer of Wrath on Turtle, etc.) — those
|
-- attack on completion (Slam, Hammer of Wrath on Turtle, etc.) — those
|
||||||
-- let the swing resume from where it paused. Detect dynamically via the
|
-- let the swing resume from where it paused. Detect dynamically via the
|
||||||
-- absent AUTOATTACK interrupt flag (0x08); spells with 0x08 reset on
|
-- absent AUTOATTACK interrupt flag (8); spells with that bit reset on
|
||||||
-- SPELL_GO_SELF so freezing isn't necessary. Subsumes the old hardcoded
|
-- SPELL_GO_SELF so freezing isn't necessary. Subsumes the old hardcoded
|
||||||
-- swingDelaySpells list (no list maintenance for new Slam-style spells).
|
-- swingDelaySpells list (no list maintenance for new Slam-style spells).
|
||||||
if S.mhActive then
|
if S.mhActive then
|
||||||
local iflags = GetSpellRecField(arg1, "interruptFlags") or 0
|
local iflags = GetSpellRecField(arg1, "interruptFlags") or 0
|
||||||
if bit.band(iflags, 0x08) == 0 then
|
if bit.band(iflags, FLAG_AUTOATTACK) == 0 then
|
||||||
S.mhFrozenAt = GetTime()
|
S.mhFrozenAt = GetTime()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -747,13 +751,11 @@ pfUI:RegisterModule("swingtimer", function ()
|
|||||||
-- Mirror the server rule for "does this spell reset the auto-attack
|
-- Mirror the server rule for "does this spell reset the auto-attack
|
||||||
-- swing" (Spell::IsMeleeAttackResetSpell in Turtle's core):
|
-- swing" (Spell::IsMeleeAttackResetSpell in Turtle's core):
|
||||||
-- InterruptFlags has SPELL_INTERRUPT_FLAG_AUTOATTACK (0x08)
|
-- InterruptFlags has SPELL_INTERRUPT_FLAG_AUTOATTACK (0x08)
|
||||||
-- AND AttributesEx2 doesn't have NOT_RESET_AUTO_ACTIONS (0x20000).
|
-- AND AttributesEx2 lacks NOT_RESET_AUTO_ACTIONS (0x20000).
|
||||||
-- If neither path resets and we're holding a frozen-swing-during-cast
|
-- If neither path resets and we're holding a frozen-swing-during-cast
|
||||||
-- (mhFrozenAt set by SPELL_START_SELF for non-0x08 spells), this is a
|
-- (mhFrozenAt set by SPELL_START_SELF for non-AUTOATTACK spells), this
|
||||||
-- Slam-style cast — push the timer forward by the cast duration so
|
-- is a Slam-style cast — push the timer forward by the cast duration
|
||||||
-- the bar resumes from where it paused.
|
-- so the bar resumes from where it paused.
|
||||||
local FLAG_AUTOATTACK = 0x08 -- SPELL_INTERRUPT_FLAG_AUTOATTACK
|
|
||||||
local ATTR_KEEP_SWINGS = 0x20000 -- SPELL_ATTR_EX2_NOT_RESET_AUTO_ACTIONS
|
|
||||||
local iflags = GetSpellRecField(spellId, "interruptFlags") or 0
|
local iflags = GetSpellRecField(spellId, "interruptFlags") or 0
|
||||||
if bit.band(iflags, FLAG_AUTOATTACK) ~= 0
|
if bit.band(iflags, FLAG_AUTOATTACK) ~= 0
|
||||||
and bit.band(GetSpellRecField(spellId, "attributesEx2") or 0, ATTR_KEEP_SWINGS) == 0 then
|
and bit.band(GetSpellRecField(spellId, "attributesEx2") or 0, ATTR_KEEP_SWINGS) == 0 then
|
||||||
|
|||||||
Reference in New Issue
Block a user