From b91ef05a966857774623bdf42738cb8c3f953185 Mon Sep 17 00:00:00 2001 From: Meow <30401521+me0wg4ming@users.noreply.github.com> Date: Mon, 2 Mar 2026 13:05:22 +0100 Subject: [PATCH] SuperWoW dependency fully removed Read the Readme for more informations please. --- README.md | 15 +++++++++ libs/libcast.lua | 75 ++++++++++++++++++++++--------------------- libs/libdebuff.lua | 29 +++++------------ libs/librange.lua | 4 +-- modules/actionbar.lua | 46 ++++++++++++-------------- modules/nampower.lua | 8 ++--- pfUI-tbc.toc | 2 +- pfUI.toc | 2 +- 8 files changed, 87 insertions(+), 94 deletions(-) diff --git a/README.md b/README.md index fa77d343..c334480c 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,21 @@ This version includes significant performance improvements, DLL-enhanced feature --- +## 🎯 What's New in Version 8.0.0 + +* **Nampower 3.0.0+ now required** — minimum version bumped from 2.41.0 +* **SuperWoW dependency fully removed** — all SuperWoW-specific code paths eliminated: + * `UNIT_CASTEVENT` replaced with `SPELL_GO_SELF` hook for Druid Prowl detection + * `UnitCastingInfo`/`UnitChannelInfo` SuperWoW fallbacks removed from libcast + * `SpellInfo()` (SuperWoW) replaced with `GetSpellRecField()` (Nampower) throughout + * `SPELL_HEAL_BY_SELF` CVar (`NP_EnableSpellHealEvents`) now auto-enabled by libdebuff +* **`GetUnitGUID()` migration** — replaced all `local _, guid = UnitExists(unit)` with `GetUnitGUID(unit)` across 11 files (Nampower 3.0.0 API) +* **Player castbar icon fix** — icons for custom Turtle WoW spells (e.g. Swift Travel Form) now correctly resolved via `GetSpellRecField`/`GetSpellIconTexture` instead of falling back to the previous spell's icon +* **Castbar timer rounding** — 1-decimal mode now rounds correctly to match the Blizzard spellbook display (e.g. 2798ms → 2.8s instead of 2.7s) +* **Nampower warning popup** — updated to be more prominent (`!!!WARNING!!!` in red, non-dismissable via Escape, uses pfUI URL copy frame for download link) + +--- + ## 🎯 What's New in Version 7.8.0 ### 🔗 libdebuff External Hook System (libs/libdebuff.lua) diff --git a/libs/libcast.lua b/libs/libcast.lua index cb9a49b8..0b87df2a 100644 --- a/libs/libcast.lua +++ b/libs/libcast.lua @@ -53,9 +53,6 @@ local scanner = libtipscan:GetScanner("libcast") local libcast = CreateFrame("Frame", "pfEnemyCast") local player = UnitName("player") --- Store original SuperWoW UnitChannelInfo if it exists -local SuperWoW_UnitChannelInfo = _G.UnitChannelInfo - UnitChannelInfo = function(unit) -- convert to name if unitstring was given local unitName = pfValidUnits[unit] and UnitName(unit) or unit @@ -100,11 +97,7 @@ UnitChannelInfo = function(unit) return cast, nameSubtext, text, texture, startTime, endTime, isTradeSkill end - -- For non-player units: use SuperWoW if available, otherwise use libcast.db - if SuperWoW_UnitChannelInfo then - return SuperWoW_UnitChannelInfo(unit) - end - + -- For non-player units: use libdebuff GUID-based tracking or libcast.db -- Try GUID-based lookup first (from libdebuff's SPELL_START tracking) local db = nil if guid and pfUI.libdebuff_casts and pfUI.libdebuff_casts[guid] then @@ -152,9 +145,6 @@ UnitChannelInfo = function(unit) return cast, nameSubtext, text, texture, startTime, endTime, isTradeSkill end --- Store original SuperWoW UnitCastingInfo if it exists -local SuperWoW_UnitCastingInfo = _G.UnitCastingInfo - UnitCastingInfo = function(unit) -- convert to name if unitstring was given local unitName = pfValidUnits[unit] and UnitName(unit) or unit @@ -172,7 +162,6 @@ UnitCastingInfo = function(unit) end -- For player: ALWAYS use libcast.db because it handles pushback correctly - -- SuperWoW's UnitCastingInfo doesn't track SPELLCAST_DELAYED events local isPlayer = unit == "player" or unitName == player if isPlayer then @@ -200,11 +189,7 @@ UnitCastingInfo = function(unit) return cast, nameSubtext, text, texture, startTime, endTime, isTradeSkill end - -- For non-player units: use SuperWoW if available, otherwise use libcast.db - if SuperWoW_UnitCastingInfo then - return SuperWoW_UnitCastingInfo(unit) - end - + -- For non-player units: use libdebuff GUID-based tracking or libcast.db -- Try GUID-based lookup first (from libdebuff's SPELL_START tracking) local db = nil if guid and pfUI.libdebuff_casts and pfUI.libdebuff_casts[guid] then @@ -321,30 +306,34 @@ libcast:RegisterEvent("SPELLCAST_CHANNEL_STOP") libcast:RegisterEvent("SPELLCAST_CHANNEL_UPDATE") local mob, spell, icon, _ +local lastSpellId = nil -- spellId cached from SPELL_START_SELF (Nampower) libcast:SetScript("OnEvent", function() -- Fill database with player casts if event == "SPELLCAST_START" then - icon = L["spells"][arg1] and L["spells"][arg1].icon and string.format("%s%s", "Interface\\Icons\\", L["spells"][arg1].icon) or lastcasttex - - -- Check if SuperWoW already set the cast data (with correct haste-adjusted casttime) - -- If so, only update icon if needed, don't overwrite casttime - local superWowAlreadySet = this.db[player].cast == arg1 and this.db[player].casttime and this.db[player].casttime > 0 - - if superWowAlreadySet then - -- SuperWoW already set correct casttime, only update icon if better - if icon and not this.db[player].icon then - this.db[player].icon = icon + -- Get icon from Nampower using spellId cached from SPELL_START_SELF + icon = nil + if lastSpellId and GetSpellRecField and GetSpellIconTexture then + local iconId = GetSpellRecField(lastSpellId, "spellIconID") + if iconId then + icon = GetSpellIconTexture(iconId) + if icon and not string.find(icon, "\\") then + icon = "Interface\\Icons\\" .. icon + end end - else - -- No SuperWoW data, use SPELLCAST_START data - this.db[player].cast = arg1 - this.db[player].rank = lastrank - this.db[player].start = GetTime() - this.db[player].casttime = arg2 - this.db[player].icon = icon - this.db[player].channel = nil end + -- fallback to L["spells"] / lastcasttex if Nampower didn't provide icon + if not icon then + icon = L["spells"][arg1] and L["spells"][arg1].icon and string.format("%s%s", "Interface\\Icons\\", L["spells"][arg1].icon) or lastcasttex + end + lastSpellId = nil + + this.db[player].cast = arg1 + this.db[player].rank = lastrank + this.db[player].start = GetTime() + this.db[player].casttime = arg2 + this.db[player].icon = icon + this.db[player].channel = nil if not L["spells"][arg1] or not L["spells"][arg1].icon or not L["spells"][arg1].t then L["spells"][arg1] = L["spells"][arg1] or { } @@ -353,6 +342,7 @@ libcast:SetScript("OnEvent", function() end lastcasttex, lastrank = nil, nil elseif event == "SPELLCAST_STOP" or event == "SPELLCAST_FAILED" or event == "SPELLCAST_INTERRUPTED" then + lastSpellId = nil if this.db[player] and not this.db[player].channel then -- remove cast action to the database this.db[player].cast = nil @@ -530,7 +520,12 @@ libcast.customcast[strlower(multishot)] = function(begin, duration) end local function CastCustom(id, bookType, rawSpellName, rank, texture, castingTime) - if not id or not rawSpellName or not castingTime then return end -- ignore if the spell is not found or if it is instant-cast + if not id or not rawSpellName then return end -- ignore if the spell is not found + if not castingTime or castingTime == 0 then + -- instant-cast: clear lastcasttex so next cast doesn't inherit this icon + lastcasttex, lastrank = nil, nil + return + end lastrank = rank lastcasttex = texture @@ -571,5 +566,11 @@ hooksecurefunc("UseAction", function(slot, target, button) CastCustom(cachedSpellId, cachedBookType, cachedRawSpellName, cachedRank, cachedTexture, cachedCastingTime) end) +-- Cache spellId from SPELL_START_SELF so SPELLCAST_START can use it for icon lookup +pfUI.libdebuff_spell_start_self_hooks = pfUI.libdebuff_spell_start_self_hooks or {} +pfUI.libdebuff_spell_start_self_hooks["libcast_icon"] = function(spellId) + lastSpellId = spellId +end + -- add libcast to pfUI API -pfUI.api.libcast = libcast +pfUI.api.libcast = libcast \ No newline at end of file diff --git a/libs/libdebuff.lua b/libs/libdebuff.lua index 676a75f6..887167a8 100644 --- a/libs/libdebuff.lua +++ b/libs/libdebuff.lua @@ -384,11 +384,6 @@ function libdebuff:GetSpellIcon(spellId) end end - if not texture and SpellInfo then - local _, _, spellTexture = SpellInfo(spellId) - texture = spellTexture - end - if not texture then texture = "Interface\\Icons\\INV_Misc_QuestionMark" end @@ -459,7 +454,7 @@ local function GetDebuffSlotMap(guid) local spellId = auras[auraSlot] if spellId and spellId > 0 then displaySlot = displaySlot + 1 - local spellName = GetSpellRecField and GetSpellRecField(spellId, "name") or SpellInfo(spellId) + local spellName = GetSpellRecField and GetSpellRecField(spellId, "name") local texture = libdebuff:GetSpellIcon(spellId) -- Get stacks from auraApplications (0-indexed, so +1 for display) @@ -1215,9 +1210,7 @@ if hasNampower then local rec = GetSpellRec(spellId) spellName = rec and rec.name or nil end - if not spellName and SpellInfo then - spellName = SpellInfo(spellId) - end + local icon = libdebuff:GetSpellIcon(spellId) @@ -1282,12 +1275,8 @@ if hasNampower then if numMissed > 0 or numHit == 0 then return end - local spellName, spellRankString - if SpellInfo then - spellName, spellRankString = SpellInfo(spellId) - elseif GetSpellRecField then - spellName = GetSpellRecField(spellId, "name") - end + local spellName = GetSpellRecField and GetSpellRecField(spellId, "name") + local spellRankString if not spellName then return end local castRank = 0 @@ -1377,9 +1366,7 @@ if hasNampower then local rec = GetSpellRec(spellId) spellName = rec and rec.name or nil end - if not spellName and SpellInfo then - spellName = SpellInfo(spellId) - end + -- Store pending cast info for libpredict (heal prediction target tracking) -- This allows libpredict to resolve the correct target for Nampower queued casts, @@ -1424,7 +1411,7 @@ if hasNampower then if not spellId then return end if not targetGuid or targetGuid == "" or targetGuid == "0x0000000000000000" then return end - local spellName = SpellInfo and SpellInfo(spellId) or (GetSpellRecField and GetSpellRecField(spellId, "name")) + local spellName = GetSpellRecField and GetSpellRecField(spellId, "name") if not spellName then return end -- Deduplicate: Ignore if we processed this exact cast recently (within 100ms) @@ -1680,7 +1667,7 @@ if hasNampower then -- Invalidate slot map cache for this GUID slotMapCache[guid] = nil - local spellName = SpellInfo and SpellInfo(spellId) + local spellName = GetSpellRecField and GetSpellRecField(spellId, "name") if not spellName then return end if debugStats.enabled then @@ -1816,7 +1803,7 @@ if hasNampower then -- Invalidate slot map cache for this GUID slotMapCache[guid] = nil - local spellName = SpellInfo and SpellInfo(spellId) or "?" + local spellName = (GetSpellRecField and GetSpellRecField(spellId, "name")) or "?" if debugStats.enabled then debugStats.debuff_removed = debugStats.debuff_removed + 1 diff --git a/libs/librange.lua b/libs/librange.lua index 988fe2f0..e7a8f372 100644 --- a/libs/librange.lua +++ b/libs/librange.lua @@ -1,8 +1,6 @@ -- load pfUI environment setfenv(1, pfUI:GetEnvironment()) -local superwow_active = HasSuperWoW() - --[[ librange ]]-- -- A pfUI library that detects and caches distance to units. -- @@ -197,7 +195,7 @@ librange:SetScript("OnUpdate", function() end -- try to read distance via superwow second - if superwow_active then + if HasSuperWoW() and UnitPosition then local x1, y1, z1 = UnitPosition("player") local x2, y2, z2 = UnitPosition(unit) -- only continue if we got position values diff --git a/modules/actionbar.lua b/modules/actionbar.lua index 02384ed7..222b32a1 100644 --- a/modules/actionbar.lua +++ b/modules/actionbar.lua @@ -984,7 +984,6 @@ pfUI:RegisterModule("actionbar", "vanilla", function () local pageswitch = CreateFrame("Frame", "pfActionBarPageSwitch", UIParent) pageswitch:RegisterEvent("PLAYER_AURAS_CHANGED") pageswitch:RegisterEvent("PLAYER_ENTERING_WORLD") - pageswitch:RegisterEvent("UNIT_CASTEVENT") pageswitch:RegisterEvent("PLAYER_LOGOUT") pageswitch:SetScript("OnEvent", function() -- Handle shutdown to prevent crash 132 @@ -994,34 +993,15 @@ pfUI:RegisterModule("actionbar", "vanilla", function () this:SetScript("OnUpdate", nil) return end - + if class ~= "DRUID" then return end - + -- On login/reload: full scan if event == "PLAYER_ENTERING_WORLD" then prowling = FullScan() return end - - -- UNIT_CASTEVENT: detect Prowl cast instantly - -- Prowl Spell IDs: 5215 (Rank 1), 6783 (Rank 2), 9913 (Rank 3) - if event == "UNIT_CASTEVENT" then - local guid, target, cEvent, spellId = arg1, arg2, arg3, arg4 - local playerGuid = GetUnitGUID("player") - if guid == playerGuid and cEvent == "CAST" then - if spellId == 5215 or spellId == 6783 or spellId == 9913 then - -- Prowl cast detected - inCatForm = true - prowlActive = true - prowling = true - elseif spellId == 768 then - -- Cat Form cast (Spell ID 768) - inCatForm = true - end - end - return - end - + -- PLAYER_AURAS_CHANGED: smart scanning if event == "PLAYER_AURAS_CHANGED" then if prowlActive then @@ -1047,9 +1027,25 @@ pfUI:RegisterModule("actionbar", "vanilla", function () -- Not in cat form, do a full scan (might have just shifted) prowling = FullScan() end - -- If inCatForm but not prowlActive, no scan needed (wait for UNIT_CASTEVENT) + -- If inCatForm but not prowlActive, no scan needed (wait for SPELL_GO_SELF hook) end end) + + -- Prowl/CatForm detection via Nampower SPELL_GO_SELF hook (replaces UNIT_CASTEVENT) + -- Prowl Spell IDs: 5215 (Rank 1), 6783 (Rank 2), 9913 (Rank 3) + -- Cat Form Spell ID: 768 + local PROWL_IDS = { [5215] = true, [6783] = true, [9913] = true } + pfUI.libdebuff_spell_go_hooks = pfUI.libdebuff_spell_go_hooks or {} + pfUI.libdebuff_spell_go_hooks["actionbar_prowl"] = function(spellId) + if class ~= "DRUID" then return end + if PROWL_IDS[spellId] then + inCatForm = true + prowlActive = true + prowling = true + elseif spellId == 768 then + inCatForm = true + end + end pageswitch:SetScript("OnUpdate", function() -- switch actionbar page depending on meta key that is pressed if C.bars.pagemastershift == "1" and IsShiftKeyDown() then @@ -1756,4 +1752,4 @@ pfUI:RegisterModule("actionbar", "vanilla", function () return reagent_counts[reagent_slots[slot]] end end -end) +end) \ No newline at end of file diff --git a/modules/nampower.lua b/modules/nampower.lua index d6374e83..08a42988 100644 --- a/modules/nampower.lua +++ b/modules/nampower.lua @@ -67,14 +67,11 @@ pfUI:RegisterModule("nampower", "vanilla", function () local spellId = arg2 if eventCode == NORMAL_QUEUED or eventCode == NON_GCD_QUEUED or eventCode == ON_SWING_QUEUED then - -- Get spell texture from GetSpellRec (Nampower) or SpellInfo (SuperWoW fallback) + -- Get spell texture from GetSpellRec (Nampower) local texture if GetSpellRec then local rec = GetSpellRec(spellId) texture = rec and rec.spellIconID and GetSpellIconTexture(rec.spellIconID) or nil - elseif SpellInfo then - local _, _, tex = SpellInfo(spellId) - texture = tex end if texture then @@ -112,8 +109,7 @@ pfUI:RegisterModule("nampower", "vanilla", function () local iconID = rec.spellIconID texture = iconID and GetSpellIconTexture(iconID) or nil end - elseif SpellInfo then - name, rank, texture = SpellInfo(spellId) + end if not name then name, rank = SafeGetSpellNameAndRank(spellId) diff --git a/pfUI-tbc.toc b/pfUI-tbc.toc index c4693fb7..561e293f 100644 --- a/pfUI-tbc.toc +++ b/pfUI-tbc.toc @@ -3,7 +3,7 @@ ## Author: Shagu - modfied by me0wg4ming ## Notes: A complete user interface replacement. ## Notes-ruRU: Полная замена пользовательского интерфейса. -## Version: 7.8.0 +## Version: 8.0.0 ## SavedVariables: pfUI_profiles, pfUI_addon_profiles, pfUI_cache, pfUI_throttle ## SavedVariablesPerCharacter: pfUI_config, pfUI_init, pfUI_playerDB diff --git a/pfUI.toc b/pfUI.toc index 9bc25284..b98cd8a5 100644 --- a/pfUI.toc +++ b/pfUI.toc @@ -3,7 +3,7 @@ ## Author: Shagu - modfied by me0wg4ming ## Notes: A complete user interface replacement. ## Notes-ruRU: Полная замена пользовательского интерфейса. -## Version: 7.8.0 +## Version: 8.0.0 ## SavedVariables: pfUI_profiles, pfUI_addon_profiles, pfUI_cache, pfUI_throttle ## SavedVariablesPerCharacter: pfUI_config, pfUI_init, pfUI_playerDB