diff --git a/README.md b/README.md index 41e5ace7..4f2bbb16 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # pfUI - Turtle WoW Edition -[![Version](https://img.shields.io/badge/version-6.2.1-blue.svg)](https://github.com/me0wg4ming/pfUI) +[![Version](https://img.shields.io/badge/version-6.2.2-blue.svg)](https://github.com/me0wg4ming/pfUI) [![Turtle WoW](https://img.shields.io/badge/Turtle%20WoW-1.18.0-brightgreen.svg)](https://turtlecraft.gg/) [![SuperWoW](https://img.shields.io/badge/SuperWoW-Enhanced-purple.svg)](https://github.com/balakethelock/SuperWoW) [![Nampower](https://img.shields.io/badge/Nampower-Optional-yellow.svg)](https://gitea.com/avitasia/nampower) @@ -14,6 +14,33 @@ This version includes significant performance improvements, DLL-enhanced feature --- +## What's New in Version 6.2.2 (January 10, 2026) + +### 🎯 Failed Spell Detection (libdebuff.lua) + +- ✅ **Resist/Miss/Dodge/Parry Detection** - Spells that fail to land no longer create or update timers + - Detects: Miss, Resist, Dodge, Parry, Evade, Deflect, Reflect, Block, Absorb, Immune + - Timer is either blocked before creation or reverted if fail event arrives late +- ✅ **Public API: `libdebuff:DidSpellFail(spell)`** - Other modules can check if a spell recently failed + - Returns true if spell failed within the last 1 second + - Used by turtle-wow.lua for refresh mechanics + +### 🐱 Druid/Warlock Refresh Fixes (turtle-wow.lua) + +- ✅ **Ferocious Bite Refresh Fix** - Rip/Rake timers only refresh when Ferocious Bite actually hits + - Previously: Timer refreshed even on dodge/parry/miss + - Now: Uses `DidSpellFail()` to verify hit before refreshing +- ✅ **Conflagrate Refresh Fix** - Immolate duration only reduced when Conflagrate actually hits +- ✅ **Caster Inheritance** - Refresh mechanics preserve existing caster info when not explicitly provided + +### ⚡ SuperWoW Compatibility (superwow.lua) + +- ✅ **Removed UNIT_CASTEVENT for DoT Timers** - SuperWoW's instant event fires before resist/miss detection + - DoT timers now use standard hook-based fallback (compatible with resist detection) + - HoT timers (Rejuvenation, Renew, etc.) still use SuperWoW for instant detection (buffs can't be resisted) + +--- + ## What's New in Version 6.2.1 (January 10, 2026) ### 🎯 Debuff Timer Protection System (libdebuff.lua) @@ -399,7 +426,7 @@ Same as original pfUI - free to use and modify. --- -**Version:** 6.2.1 +**Version:** 6.2.2 **Release Date:** January 10, 2026 **Compatibility:** Turtle WoW 1.18.0 **Status:** Stable diff --git a/libs/libdebuff.lua b/libs/libdebuff.lua index 460a009c..8cc22fa4 100644 --- a/libs/libdebuff.lua +++ b/libs/libdebuff.lua @@ -29,6 +29,19 @@ local lastspell -- Speichert die Ranks der zuletzt gecasteten Spells (bleibt länger als pending) local lastCastRanks = {} +-- Speichert Spells die gefailed sind (miss/dodge/parry/etc.) für 1 Sekunde +local lastFailedSpells = {} + +-- Prüft ob ein Spell kürzlich gefailed ist (öffentliche Funktion für andere Module) +function libdebuff:DidSpellFail(spell) + if not spell then return false end + local data = lastFailedSpells[spell] + if data and (GetTime() - data.time) < 1 then + return true + end + return false +end + -- Shared Debuffs: Diese werden von allen Spielern geteilt (nur einer kann drauf sein) -- Timer darf von anderen Spielern aktualisiert werden local sharedDebuffs = { @@ -166,6 +179,8 @@ function libdebuff:PersistPending(effect) end function libdebuff:RevertLastAction() + if lastspell and lastspell.effect then + end lastspell.start = lastspell.start_old lastspell.start_old = nil libdebuff:UpdateUnits() @@ -184,6 +199,13 @@ function libdebuff:AddEffect(unit, unitlevel, effect, duration, caster, rank) end if not unit or not effect then return end + + -- SCHUTZ: Wenn der Spell gerade gefailed ist (miss/dodge/parry/etc.), nicht anwenden + -- Nur für eigene Spells prüfen, nicht für andere Spieler + if caster == "player" and libdebuff:DidSpellFail(effect) then + return -- Spell hat nicht getroffen, keinen Timer setzen + end + unitlevel = unitlevel or 0 if not libdebuff.objects[unit] then libdebuff.objects[unit] = {} end if not libdebuff.objects[unit][unitlevel] then libdebuff.objects[unit][unitlevel] = {} end @@ -306,19 +328,24 @@ libdebuff:SetScript("OnEvent", function() end end - -- Update Pending Spells + -- Update Pending Spells und tracke failed spells elseif event == "CHAT_MSG_SPELL_FAILED_LOCALPLAYER" or event == "CHAT_MSG_SPELL_SELF_DAMAGE" then - -- Remove pending spell + -- Prüfe ob ein Spell gefailed ist und speichere ihn for _, msg in pairs(libdebuff.rp) do local effect = cmatch(arg1, msg) - if effect and libdebuff.pending[3] == effect then - -- instant removal of the pending spell - libdebuff:RemovePending() - return - elseif effect and lastspell and lastspell.start_old and lastspell.effect == effect then - -- late removal of debuffs (e.g hunter arrows as they hit late) - libdebuff:RevertLastAction() - return + if effect then + -- Speichere den failed spell für 1 Sekunde + lastFailedSpells[effect] = { time = GetTime() } + + -- Bestehende Logik: Remove pending spell + if libdebuff.pending[3] == effect then + libdebuff:RemovePending() + return + elseif lastspell and lastspell.start_old and lastspell.effect == effect then + -- late removal of debuffs (e.g hunter arrows as they hit late) + libdebuff:RevertLastAction() + return + end end end elseif event == "SPELLCAST_STOP" then diff --git a/modules/superwow.lua b/modules/superwow.lua index c6423dd8..24d67a90 100644 --- a/modules/superwow.lua +++ b/modules/superwow.lua @@ -300,30 +300,10 @@ pfUI:RegisterModule("superwow", "vanilla", function () end end - -- Enhance libdebuff with SuperWoW data - local superdebuff = CreateFrame("Frame") - superdebuff:RegisterEvent("UNIT_CASTEVENT") - superdebuff:SetScript("OnEvent", function() - -- variable assignments - local caster, target, event, spell, duration = arg1, arg2, arg3, arg4 - - -- skip other caster and empty target events - local _, guid = UnitExists("player") - if caster ~= guid then return end - if event ~= "CAST" then return end - if not target or target == "" then return end - - -- assign all required data - local unit = UnitName(target) - local unitlevel = UnitLevel(target) - if not SpellInfo then return end - local effect, rank = SpellInfo(spell) - local duration = libdebuff:GetDuration(effect, rank) - local caster = "player" - - -- add effect to current debuff data - libdebuff:AddEffect(unit, unitlevel, effect, duration, caster) - end) + -- NOTE: SuperWoW libdebuff enhancement removed. + -- UNIT_CASTEVENT fires before resist/miss/dodge events arrive, + -- which breaks the failed spell detection system in libdebuff. + -- DoT timers use the standard hook-based fallback instead. -- TrackUnit API for adding group members to minimap -- Tracks friendly units on the minimap for easier group coordination diff --git a/modules/turtle-wow.lua b/modules/turtle-wow.lua index 3687c71e..05515af0 100644 --- a/modules/turtle-wow.lua +++ b/modules/turtle-wow.lua @@ -33,8 +33,9 @@ pfUI:RegisterModule("turtle-wow", "vanilla", function () end -- refresh rip and rake duration on ferocious bite (Turtle WoW feature) + -- Only refresh if Ferocious Bite actually hit (not missed/dodged/parried/etc.) local match = string.find(arg1, "Ferocious Bite") - if match and arg2 then + if match and arg2 and not libdebuff:DidSpellFail("Ferocious Bite") then local name = UnitName("target") local level = UnitLevel("target") @@ -52,9 +53,9 @@ pfUI:RegisterModule("turtle-wow", "vanilla", function () end -- refresh Immolate duration after cast Conflagrate + -- Only refresh if Conflagrate actually hit local conflagrate = string.find(string.sub(arg1,6,17), "Conflagrate") - --arg2 is spell dmg when it hits, nil when it misses - if conflagrate and arg2 then + if conflagrate and arg2 and not libdebuff:DidSpellFail("Conflagrate") then local name = UnitName("target") local level = UnitLevel("target") if libdebuff.objects[name] and libdebuff.objects[name][level] and libdebuff.objects[name][level]["Immolate"] then diff --git a/pfUI-tbc.toc b/pfUI-tbc.toc index c61afb09..f03ca361 100644 --- a/pfUI-tbc.toc +++ b/pfUI-tbc.toc @@ -3,7 +3,7 @@ ## Author: Shagu ## Notes: A complete user interface replacement. ## Notes-ruRU: Полная замена пользовательского интерфейса. -## Version: 6.2.1 +## Version: 6.2.2 ## SavedVariables: pfUI_profiles, pfUI_addon_profiles, pfUI_cache ## SavedVariablesPerCharacter: pfUI_config, pfUI_init, pfUI_playerDB diff --git a/pfUI.toc b/pfUI.toc index 1daa848a..c1f23b76 100644 --- a/pfUI.toc +++ b/pfUI.toc @@ -3,7 +3,7 @@ ## Author: Shagu ## Notes: A complete user interface replacement. ## Notes-ruRU: Полная замена пользовательского интерфейса. -## Version: 6.2.1 +## Version: 6.2.2 ## SavedVariables: pfUI_profiles, pfUI_addon_profiles, pfUI_cache ## SavedVariablesPerCharacter: pfUI_config, pfUI_init, pfUI_playerDB