libtotem fix

This commit is contained in:
Meow
2026-03-10 18:28:15 +01:00
parent 5c8ed4a938
commit c503635622
+151 -59
View File
@@ -26,59 +26,119 @@ AIR_TOTEM_SLOT = AIR_TOTEM_SLOT or 4
local _, class = UnitClass("player")
local libtotem
local queue = { ["slot"] = nil, ["name"] = nil, ["start"] = nil, ["duration"] = nil, ["icon"] = nil }
local active = { [1] = {}, [2] = {}, [3] = {}, [4] = {} }
-- SpellID -> { slot, duration } mapping
-- rank-specific durations are handled via spellId directly
local spellids = {
-- FIRE (slot 1)
[1535] = { slot = FIRE_TOTEM_SLOT, duration = 5 }, -- Fire Nova Totem R1
[8498] = { slot = FIRE_TOTEM_SLOT, duration = 5 }, -- Fire Nova Totem R2
[8499] = { slot = FIRE_TOTEM_SLOT, duration = 5 }, -- Fire Nova Totem R3
[11314] = { slot = FIRE_TOTEM_SLOT, duration = 5 }, -- Fire Nova Totem R4
[11315] = { slot = FIRE_TOTEM_SLOT, duration = 5 }, -- Fire Nova Totem R5
[8227] = { slot = FIRE_TOTEM_SLOT, duration = 120 }, -- Flametongue Totem R1
[8249] = { slot = FIRE_TOTEM_SLOT, duration = 120 }, -- Flametongue Totem R2
[10526] = { slot = FIRE_TOTEM_SLOT, duration = 120 }, -- Flametongue Totem R3
[16387] = { slot = FIRE_TOTEM_SLOT, duration = 120 }, -- Flametongue Totem R4
[8184] = { slot = FIRE_TOTEM_SLOT, duration = 120 }, -- Frost Resistance Totem R1
[10478] = { slot = FIRE_TOTEM_SLOT, duration = 120 }, -- Frost Resistance Totem R2
[10479] = { slot = FIRE_TOTEM_SLOT, duration = 120 }, -- Frost Resistance Totem R3
[8190] = { slot = FIRE_TOTEM_SLOT, duration = 20 }, -- Magma Totem R1
[10585] = { slot = FIRE_TOTEM_SLOT, duration = 20 }, -- Magma Totem R2
[10586] = { slot = FIRE_TOTEM_SLOT, duration = 20 }, -- Magma Totem R3
[10587] = { slot = FIRE_TOTEM_SLOT, duration = 20 }, -- Magma Totem R4
[3599] = { slot = FIRE_TOTEM_SLOT, duration = 30 }, -- Searing Totem R1
[6363] = { slot = FIRE_TOTEM_SLOT, duration = 35 }, -- Searing Totem R2
[6364] = { slot = FIRE_TOTEM_SLOT, duration = 40 }, -- Searing Totem R3
[6365] = { slot = FIRE_TOTEM_SLOT, duration = 45 }, -- Searing Totem R4
[10437] = { slot = FIRE_TOTEM_SLOT, duration = 50 }, -- Searing Totem R5
[10438] = { slot = FIRE_TOTEM_SLOT, duration = 55 }, -- Searing Totem R6
-- EARTH (slot 2)
[2484] = { slot = EARTH_TOTEM_SLOT, duration = 45 }, -- Earthbind Totem
[5730] = { slot = EARTH_TOTEM_SLOT, duration = 15 }, -- Stoneclaw Totem R1
[6390] = { slot = EARTH_TOTEM_SLOT, duration = 15 }, -- Stoneclaw Totem R2
[6391] = { slot = EARTH_TOTEM_SLOT, duration = 15 }, -- Stoneclaw Totem R3
[6392] = { slot = EARTH_TOTEM_SLOT, duration = 15 }, -- Stoneclaw Totem R4
[10427] = { slot = EARTH_TOTEM_SLOT, duration = 15 }, -- Stoneclaw Totem R5
[10428] = { slot = EARTH_TOTEM_SLOT, duration = 15 }, -- Stoneclaw Totem R6
[8071] = { slot = EARTH_TOTEM_SLOT, duration = 120 }, -- Stoneskin Totem R1
[8154] = { slot = EARTH_TOTEM_SLOT, duration = 120 }, -- Stoneskin Totem R2
[8155] = { slot = EARTH_TOTEM_SLOT, duration = 120 }, -- Stoneskin Totem R3
[10406] = { slot = EARTH_TOTEM_SLOT, duration = 120 }, -- Stoneskin Totem R4
[10407] = { slot = EARTH_TOTEM_SLOT, duration = 120 }, -- Stoneskin Totem R5
[10408] = { slot = EARTH_TOTEM_SLOT, duration = 120 }, -- Stoneskin Totem R6
[8075] = { slot = EARTH_TOTEM_SLOT, duration = 120 }, -- Strength of Earth Totem R1
[8160] = { slot = EARTH_TOTEM_SLOT, duration = 120 }, -- Strength of Earth Totem R2
[8161] = { slot = EARTH_TOTEM_SLOT, duration = 120 }, -- Strength of Earth Totem R3
[10442] = { slot = EARTH_TOTEM_SLOT, duration = 120 }, -- Strength of Earth Totem R4
[25361] = { slot = EARTH_TOTEM_SLOT, duration = 120 }, -- Strength of Earth Totem R5
[8143] = { slot = EARTH_TOTEM_SLOT, duration = 120 }, -- Tremor Totem
-- WATER (slot 3)
[8170] = { slot = WATER_TOTEM_SLOT, duration = 120 }, -- Disease Cleansing Totem
[8185] = { slot = WATER_TOTEM_SLOT, duration = 120 }, -- Fire Resistance Totem R1
[10537] = { slot = WATER_TOTEM_SLOT, duration = 120 }, -- Fire Resistance Totem R2
[10538] = { slot = WATER_TOTEM_SLOT, duration = 120 }, -- Fire Resistance Totem R3
[5394] = { slot = WATER_TOTEM_SLOT, duration = 60 }, -- Healing Stream Totem R1
[6375] = { slot = WATER_TOTEM_SLOT, duration = 60 }, -- Healing Stream Totem R2
[6377] = { slot = WATER_TOTEM_SLOT, duration = 60 }, -- Healing Stream Totem R3
[10462] = { slot = WATER_TOTEM_SLOT, duration = 60 }, -- Healing Stream Totem R4
[10463] = { slot = WATER_TOTEM_SLOT, duration = 60 }, -- Healing Stream Totem R5
[5675] = { slot = WATER_TOTEM_SLOT, duration = 60 }, -- Mana Spring Totem R1
[10495] = { slot = WATER_TOTEM_SLOT, duration = 60 }, -- Mana Spring Totem R2
[10496] = { slot = WATER_TOTEM_SLOT, duration = 60 }, -- Mana Spring Totem R3
[10497] = { slot = WATER_TOTEM_SLOT, duration = 60 }, -- Mana Spring Totem R4
[16190] = { slot = WATER_TOTEM_SLOT, duration = 12 }, -- Mana Tide Totem
[8166] = { slot = WATER_TOTEM_SLOT, duration = 120 }, -- Poison Cleansing Totem
-- AIR (slot 4)
[8835] = { slot = AIR_TOTEM_SLOT, duration = 120 }, -- Grace of Air Totem R1
[10627] = { slot = AIR_TOTEM_SLOT, duration = 120 }, -- Grace of Air Totem R2
[8177] = { slot = AIR_TOTEM_SLOT, duration = 45 }, -- Grounding Totem
[10595] = { slot = AIR_TOTEM_SLOT, duration = 120 }, -- Nature Resistance Totem R1
[10600] = { slot = AIR_TOTEM_SLOT, duration = 120 }, -- Nature Resistance Totem R2
[10601] = { slot = AIR_TOTEM_SLOT, duration = 120 }, -- Nature Resistance Totem R3
[25359] = { slot = AIR_TOTEM_SLOT, duration = 120 }, -- Tranquil Air Totem
[8512] = { slot = AIR_TOTEM_SLOT, duration = 120 }, -- Windfury Totem R1
[10613] = { slot = AIR_TOTEM_SLOT, duration = 120 }, -- Windfury Totem R2
[10614] = { slot = AIR_TOTEM_SLOT, duration = 120 }, -- Windfury Totem R3
[15107] = { slot = AIR_TOTEM_SLOT, duration = 120 }, -- Windwall Totem R1
[15421] = { slot = AIR_TOTEM_SLOT, duration = 120 }, -- Windwall Totem R2
[15422] = { slot = AIR_TOTEM_SLOT, duration = 120 }, -- Windwall Totem R3
}
-- icon-based fallback table (used by CastSpell/UseAction hooks that don't have spellId)
local totems = {
[FIRE_TOTEM_SLOT] = {
--Fire Nova Totem (Fire)
["Spell_Fire_SealOfFire"] = {[-1] = 5},
--Flametongue Totem (Fire)
["Spell_Nature_GuardianWard"] = {[-1] = 120},
--Frost Resistance Totem (Fire)
["Spell_FrostResistanceTotem_01"] = {[-1] = 120},
--Magma Totem (Fire)
["Spell_Fire_SelfDestruct"] = {[-1] = 20},
--Searing Totem (Fire)
["Spell_Fire_SearingTotem"] = {[-1] = 55,[1] = 30,[2] = 35,[3] = 40,[4] = 45,[5] = 50,[6] = 55},
},
[EARTH_TOTEM_SLOT] = {
--Earthbind Totem (Earth)
["Spell_Nature_StrengthOfEarthTotem02"] = {[-1] = 45},
--Stoneclaw Totem (Earth)
["Spell_Nature_StoneClawTotem"] = {[-1] = 15},
--Stoneskin Totem (Earth)
["Spell_Nature_StoneSkinTotem"] = {[-1] = 120},
--Strength of Earth Totem (Earth)
["Spell_Nature_EarthBindTotem"] = {[-1] = 120},
--Tremor Totem (Earth)
["Spell_Nature_TremorTotem"] = {[-1] = 120},
},
[WATER_TOTEM_SLOT] = {
-- Disease Cleansing Totem (Water)
["Spell_Nature_DiseaseCleansingTotem"] = {[-1] = 120},
--Fire Resistance Totem (Water)
["Spell_FireResistanceTotem_01"] = {[-1] = 120},
--Healing Stream Totem (Water)
["INV_Spear_04"] = {[-1] = 60},
--Mana Spring Totem (Water)
["Spell_Nature_ManaRegenTotem"] = {[-1] = 60},
--Mana Tide Totem (Water)
["Spell_Frost_SummonWaterElemental"] = {[-1] = 12},
--Poison Cleansing Totem (Water)
["Spell_Nature_PoisonCleansingTotem"] = {[-1] = 120},
},
[AIR_TOTEM_SLOT] = {
--Grace of Air Totem (Air)
["Spell_Nature_InvisibilityTotem"] = {[-1] = 120},
--Grounding Totem (Air)
["Spell_Nature_GroundingTotem"] = {[-1] = 45},
--Nature Resistance Totem (Air)
["Spell_Nature_NatureResistanceTotem"] = {[-1] = 120},
--Tranquil Air Totem (Air)
["Spell_Nature_Brilliance"] = {[-1] = 120},
--Windfury Totem (Air)
["Spell_Nature_Windfury"] = {[-1] = 120},
--Windwall Totem (Air)
["Spell_Nature_EarthBind"] = {[-1] = 120},
},
}
@@ -89,30 +149,16 @@ GetTotemInfo = function(id)
libtotem:Clean(id)
return nil
end
return 1, active[id].name, active[id].start, active[id].duration, active[id].icon
end
if class ~= "SHAMAN" then return end
libtotem = CreateFrame("Frame")
libtotem:RegisterEvent("SPELLCAST_STOP")
libtotem:RegisterEvent("PLAYER_DEAD")
libtotem:SetScript("OnEvent", function()
if event == "PLAYER_DEAD" then
for i = 1,4 do
libtotem:Clean(i)
end
elseif event == "SPELLCAST_STOP" then
if queue.slot and queue.name then
active[queue.slot].name = queue.name
active[queue.slot].duration = queue.duration
active[queue.slot].icon = queue.icon
active[queue.slot].start = GetTime()
end
queue.slot = nil
queue.name = nil
for i = 1, 4 do libtotem:Clean(i) end
end
end)
@@ -125,47 +171,93 @@ libtotem.Clean = function(self, slot)
active[slot].icon = nil
end
libtotem.CheckAddQueue = function(self, name, rank, icon)
-- Direct SpellID commit (Nampower SPELL_GO_SELF, most accurate)
libtotem.CommitBySpellId = function(spellId, icon)
local data = spellids[spellId]
if not data then return false end
local slot = data.slot
active[slot].name = active[slot].pending_name or active[slot].name
active[slot].duration = data.duration
active[slot].icon = icon or active[slot].pending_icon
active[slot].start = GetTime()
active[slot].pending_name = nil
active[slot].pending_icon = nil
return true
end
-- Fallback: icon-based lookup (for CastSpell/UseAction without spellId)
libtotem.CheckAddQueue = function(self, name, rank, icon, spellId)
-- if we have a spellId, just store the name/icon as pending for SPELL_GO
if spellId and spellids[spellId] then
local slot = spellids[spellId].slot
active[slot].pending_name = name
active[slot].pending_icon = icon
return true
end
-- icon-based fallback
for slot = 1, 4 do
for texture, data in pairs(totems[slot]) do
if string.find(icon, texture, 1) then
if rank then -- try to obtain plain rank number
_, _, rank = string.find(rank,"%s(%d+)")
if rank then
_, _, rank = string.find(rank, "%s(%d+)")
end
queue.slot = slot
queue.name = name
queue.icon = icon
local duration
if rank and tonumber(rank) and data[tonumber(rank)] then
queue.duration = data[tonumber(rank)]
duration = data[tonumber(rank)]
else
queue.duration = data[-1]
duration = data[-1]
end
active[slot].pending_name = name
active[slot].pending_icon = icon
active[slot].pending_duration = duration
return true
end
end
end
return nil
end
-- assign library to global space
pfUI.api.libtotem = libtotem
-- Check for totem spell casts
hooksecurefunc("CastSpell", function(id, bookType)
local name, rank, icon = libspell.GetSpellInfo(id, bookType)
if not name then return end
if libtotem:CheckAddQueue(name, rank, icon) then return end
end)
-- SPELL_GO_SELF from libdebuff: commit directly by SpellID, no queue needed
pfUI.libdebuff_spell_go_hooks = pfUI.libdebuff_spell_go_hooks or {}
pfUI.libdebuff_spell_go_hooks["libtotem"] = function(spellId)
if not spellId then return end
local data = spellids[spellId]
if not data then return end
local slot = data.slot
-- use pending name/icon if available (set by CastSpellByName hook), else GetSpellInfo
local name = active[slot].pending_name
local icon = active[slot].pending_icon
if not name and GetSpellInfo then
name = GetSpellInfo(spellId)
end
active[slot].name = name
active[slot].duration = data.duration
active[slot].icon = icon
active[slot].start = GetTime()
active[slot].pending_name = nil
active[slot].pending_icon = nil
active[slot].pending_duration = nil
end
-- Hook CastSpellByName to store pending name/icon per slot
hooksecurefunc("CastSpellByName", function(effect, target)
local name, rank, icon = libspell.GetSpellInfo(effect)
local name, rank, icon, _, _, _, spellId = libspell.GetSpellInfo(effect)
if not name then return end
if libtotem:CheckAddQueue(name, rank, icon) then return end
libtotem:CheckAddQueue(name, rank, icon, spellId)
end)
-- Hook CastSpell to store pending name/icon per slot
hooksecurefunc("CastSpell", function(id, bookType)
local name, rank, icon, _, _, _, spellId = libspell.GetSpellInfo(id, bookType)
if not name then return end
libtotem:CheckAddQueue(name, rank, icon, spellId)
end)
-- Hook UseAction (no spellId available, icon-based fallback)
local scanner = libtipscan:GetScanner("prediction")
hooksecurefunc("UseAction", function(slot, target, selfcast)
if GetActionText(slot) or not IsCurrentAction(slot) then return end
@@ -173,5 +265,5 @@ hooksecurefunc("UseAction", function(slot, target, selfcast)
local name, rank = scanner:Line(1)
local icon = GetActionTexture(slot)
if not name then return end
if libtotem:CheckAddQueue(name, rank, icon) then return end
end)
libtotem:CheckAddQueue(name, rank, icon, nil)
end)