From f1048bd7bba7c5396825f703dc5d160fb0b77ec0 Mon Sep 17 00:00:00 2001 From: Meow <30401521+me0wg4ming@users.noreply.github.com> Date: Fri, 20 Feb 2026 20:25:16 +0100 Subject: [PATCH] Revert "possible fix for libpredict to not show resses that are canceled." This reverts commit 947b11f9187364ca0c0fae4e601febf78a8c3110. --- libs/libdebuff.lua | 14 ---- libs/libpredict.lua | 190 ++++++++++++++++++++++++-------------------- 2 files changed, 103 insertions(+), 101 deletions(-) diff --git a/libs/libdebuff.lua b/libs/libdebuff.lua index a92899df..fd0ffe03 100644 --- a/libs/libdebuff.lua +++ b/libs/libdebuff.lua @@ -1289,13 +1289,6 @@ if hasNampower then carnageCheckFrame:Show() end end - - -- Forward to registered callbacks (e.g. libpredict) - if pfUI.libdebuff_spell_go_callbacks then - for _, cb in pairs(pfUI.libdebuff_spell_go_callbacks) do - cb(spellId, spellName, castRank, casterGuid, targetGuid, event == "SPELL_GO_SELF") - end - end elseif event == "SPELL_FAILED_OTHER" then local casterGuid = arg1 @@ -1303,13 +1296,6 @@ if hasNampower then if casterGuid and pfUI.libdebuff_casts[casterGuid] then pfUI.libdebuff_casts[casterGuid] = nil end - - -- Forward to registered callbacks (e.g. libpredict) - if pfUI.libdebuff_spell_failed_other_callbacks then - for _, cb in pairs(pfUI.libdebuff_spell_failed_other_callbacks) do - cb(casterGuid) - end - end elseif event == "SPELL_CAST_EVENT" then -- Capture combo points BEFORE they're consumed diff --git a/libs/libpredict.lua b/libs/libpredict.lua index e992bd3a..e747261e 100644 --- a/libs/libpredict.lua +++ b/libs/libpredict.lua @@ -35,8 +35,6 @@ local hasNampower = GetNampowerVersion ~= nil local senttarget local heals, ress, events, hots = {}, {}, {}, {} -local ressGuidToName = {} -- [casterGuid] = casterName, for SPELL_FAILED_OTHER cleanup -local healGuidToName = {} -- [casterGuid] = casterName, for SPELL_FAILED_OTHER cleanup local PRAYER_OF_HEALING do -- Prayer of Healing @@ -116,8 +114,14 @@ local SPELL_IDS = { local libpredict = CreateFrame("Frame") libpredict:RegisterEvent("UNIT_HEALTH") libpredict:RegisterEvent("CHAT_MSG_ADDON") +libpredict:RegisterEvent("PLAYER_TARGET_CHANGED") libpredict:RegisterEvent("PLAYER_LOGOUT") +-- SuperWoW: Registriere UNIT_CASTEVENT für akkurate Instant-HoT Detection +if superwow_active then + libpredict:RegisterEvent("UNIT_CASTEVENT") +end + libpredict:SetScript("OnEvent", function() -- Handle shutdown to prevent crash 132 if event == "PLAYER_LOGOUT" then @@ -131,63 +135,105 @@ libpredict:SetScript("OnEvent", function() elseif event == "UNIT_HEALTH" then local name = UnitName(arg1) if name and ress[name] and not UnitIsDeadOrGhost(arg1) then - ress[name] = nil + ress[name] = nil -- Reuse 'name' variable instead of calling UnitName again end - end -end) - --- Register with libdebuff for event forwarding (avoids double event registration) -if hasNampower then - -- SPELL_GO: HoT detection (SELF) + Rez tracking (OTHER) - pfUI.libdebuff_spell_go_callbacks = pfUI.libdebuff_spell_go_callbacks or {} - pfUI.libdebuff_spell_go_callbacks["libpredict"] = function(spellId, spellName, rank, casterGuid, targetGuid, isSelf) - -- Own instant HoTs (Rejuvenation, Renew) - if isSelf then - local hotType = SPELL_IDS[spellId] - if not hotType then return end - local targetUnit = UnitExists(targetGuid) - local targetName = targetUnit and UnitName(targetUnit) - if not targetName then return end - local duration - if hotType == "Reju" then - duration = rejuvDuration or 12 - elseif hotType == "Renew" then - duration = renewDuration or 15 - end - local playerName = UnitName("player") - libpredict:Hot(playerName, targetName, hotType, duration, nil, "SPELL_GO_SELF", rank) - local rankStr = rank and tostring(rank) or "0" - if libpredict.sender and libpredict.sender.SendHealCommMsg then - libpredict.sender:SendHealCommMsg(hotType .. "/" .. targetName .. "/" .. duration .. "/" .. rankStr .. "/") - elseif GetNumRaidMembers() > 0 then - SendAddonMessage("HealComm", hotType .. "/" .. targetName .. "/" .. duration .. "/" .. rankStr .. "/", "RAID") - elseif GetNumPartyMembers() > 0 then - SendAddonMessage("HealComm", hotType .. "/" .. targetName .. "/" .. duration .. "/" .. rankStr .. "/", "PARTY") - end - else - -- Other players' rez casts - if L["resurrections"][spellName] and casterGuid and targetGuid then - local casterUnit = UnitExists(casterGuid) - local targetUnit = UnitExists(targetGuid) - local casterName = casterUnit and UnitName(casterUnit) - local targetName = targetUnit and UnitName(targetUnit) - if casterName and targetName then - libpredict:Ress(casterName, targetName, casterGuid) + elseif event == "UNIT_CASTEVENT" and superwow_active then + -- arg1 = casterGUID, arg2 = targetGUID, arg3 = event type, arg4 = spellId, arg5 = castTime + local casterGUID, targetGUID, castEvent, spellId = arg1, arg2, arg3, arg4 + + -- Nur eigene Casts (player) + local _, playerGUID = UnitExists("player") + if casterGUID ~= playerGUID then return end + + -- Nur "CAST" events (erfolgreiche Instant-Casts) + if castEvent ~= "CAST" then return end + + -- Prüfe ob es ein Instant-HoT ist + local hotType = SPELL_IDS[spellId] + if not hotType then return end + + -- Finde Target Name + local targetName + for i = 1, 40 do + local unit = "raid" .. i + if UnitExists(unit) then + local _, guid = UnitExists(unit) + if guid == targetGUID then + targetName = UnitName(unit) + break end end end + if not targetName then + for i = 1, 4 do + local unit = "party" .. i + if UnitExists(unit) then + local _, guid = UnitExists(unit) + if guid == targetGUID then + targetName = UnitName(unit) + break + end + end + end + end + if not targetName then + local _, guid = UnitExists("player") + if guid == targetGUID then + targetName = UnitName("player") + end + end + if not targetName then + local _, guid = UnitExists("target") + if guid == targetGUID then + targetName = UnitName("target") + end + end + + if not targetName then return end + + -- Duration bestimmen + local duration + if hotType == "Reju" then + duration = rejuvDuration or 12 + elseif hotType == "Renew" then + duration = renewDuration or 15 + end + + -- Extract rank from spellId (if SpellInfo available) + local rank = nil + if SpellInfo then + local _, rankString = SpellInfo(spellId) + if rankString and rankString ~= "" then + rank = tonumber((string.gsub(rankString, "Rank ", ""))) or nil + end + end + + if libpredict.debug then + DEFAULT_CHAT_FRAME:AddMessage(string.format("|cff00ffff[UNIT_CASTEVENT]|r spell=%s target=%s dur=%s rank=%s", + hotType, targetName, tostring(duration), tostring(rank or "?"))) + end + + -- Sende HoT mit Rank + local playerName = UnitName("player") + libpredict:Hot(playerName, targetName, hotType, duration, nil, "UNIT_CASTEVENT", rank) + + -- Sende HealComm Nachricht mit Rank (backwards compatible: rank optional) + -- Use "0" for unknown rank instead of empty string to avoid parsing issues + local rankStr = rank and tostring(rank) or "0" + if libpredict.sender and libpredict.sender.SendHealCommMsg then + libpredict.sender:SendHealCommMsg(hotType .. "/" .. targetName .. "/" .. duration .. "/" .. rankStr .. "/") + else + -- Fallback: direkt senden (smart channel selection) + local msg = hotType .. "/" .. targetName .. "/" .. duration .. "/" .. rankStr .. "/" + if GetNumRaidMembers() > 0 then + SendAddonMessage("HealComm", msg, "RAID") + elseif GetNumPartyMembers() > 0 then + SendAddonMessage("HealComm", msg, "PARTY") + end + -- Note: BATTLEGROUND channel not used (no reliable way to detect BG in Vanilla) + end end - - -- SPELL_FAILED_OTHER: Rez/Heal cancel for other players - pfUI.libdebuff_spell_failed_other_callbacks = pfUI.libdebuff_spell_failed_other_callbacks or {} - pfUI.libdebuff_spell_failed_other_callbacks["libpredict"] = function(casterGuid) - if not casterGuid then return end - local ressName = ressGuidToName[casterGuid] - if ressName then libpredict:RessStop(ressName) end - local healName = healGuidToName[casterGuid] - if healName then libpredict:HealStop(healName) end - end -end +end) libpredict:SetScript("OnUpdate", function() -- throttle cleanup - no need to check every frame @@ -313,27 +359,7 @@ function libpredict:ParseChatMessage(sender, msg, comm) libpredict:Heal(sender, target, heal, time) end elseif msgtype == "Ress" then - -- Try to find sender's GUID for SPELL_FAILED_OTHER tracking - local senderGuid - for i = 1, GetNumRaidMembers() do - local unit = "raid" .. i - if UnitName(unit) == sender then - local _, guid = UnitExists(unit) - senderGuid = guid - break - end - end - if not senderGuid then - for i = 1, GetNumPartyMembers() do - local unit = "party" .. i - if UnitName(unit) == sender then - local _, guid = UnitExists(unit) - senderGuid = guid - break - end - end - end - libpredict:Ress(sender, target, senderGuid) + libpredict:Ress(sender, target) elseif msgtype == "Hot" then -- Duplikat-Check: gleicher sender+target+spell innerhalb DUPLICATE_WINDOW ignorieren local now = pfUI.uf.now or GetTime() @@ -381,7 +407,7 @@ function libpredict:AddEvent(time, target) table.insert(events[time], target) end -function libpredict:Heal(sender, target, amount, duration, senderGuid) +function libpredict:Heal(sender, target, amount, duration) if not sender or not target or not amount or not duration then return end @@ -390,7 +416,6 @@ function libpredict:Heal(sender, target, amount, duration, senderGuid) local timeout = duration/1000 + now heals[target] = heals[target] or {} heals[target][sender] = { amount, timeout } - if senderGuid then healGuidToName[senderGuid] = sender end libpredict:AddEvent(timeout, target) end @@ -464,10 +489,6 @@ function libpredict:HealStop(sender) end end end - -- cleanup reverse lookup - for guid, name in pairs(healGuidToName) do - if name == sender then healGuidToName[guid] = nil end - end end function libpredict:HealDelay(sender, delay) @@ -482,10 +503,9 @@ function libpredict:HealDelay(sender, delay) end end -function libpredict:Ress(sender, target, senderGuid) +function libpredict:Ress(sender, target) ress[target] = ress[target] or {} ress[target][sender] = true - if senderGuid then ressGuidToName[senderGuid] = sender end end function libpredict:RessStop(sender) @@ -496,10 +516,6 @@ function libpredict:RessStop(sender) end end end - -- cleanup reverse lookup - for guid, name in pairs(ressGuidToName) do - if name == sender then ressGuidToName[guid] = nil end - end end function libpredict:UnitGetIncomingHeals(unit)