diff --git a/modules/actionbar.lua b/modules/actionbar.lua index 7d7cf538..0af1436b 100644 --- a/modules/actionbar.lua +++ b/modules/actionbar.lua @@ -949,11 +949,11 @@ pfUI:RegisterModule("actionbar", "vanilla", function () -- setup page switch frame local prowling = nil local pageswitch = CreateFrame("Frame", "pfActionBarPageSwitch", UIParent) - pageswitch:RegisterEvent("PLAYER_AURAS_CHANGED") pageswitch:RegisterEvent("PLAYER_ENTERING_WORLD") + pageswitch:RegisterEvent("UPDATE_SHAPESHIFT_FORM") + pageswitch:RegisterEvent("PLAYER_AURAS_CHANGED") pageswitch:RegisterEvent("PLAYER_LOGOUT") pageswitch:SetScript("OnEvent", function() - -- Handle shutdown to prevent crash 132 if event == "PLAYER_LOGOUT" then this:UnregisterAllEvents() this:SetScript("OnEvent", nil) @@ -963,34 +963,38 @@ pfUI:RegisterModule("actionbar", "vanilla", function () if class ~= "DRUID" then return end - -- On login/reload: full scan if event == "PLAYER_ENTERING_WORLD" then prowling = FullScan() return end - -- PLAYER_AURAS_CHANGED: smart scanning - if event == "PLAYER_AURAS_CHANGED" then - if prowlActive then - if IsStealthed() then - prowling = true - else - -- Prowl ended; recheck cat form (we might have shifted out entirely) - prowlActive = nil - prowling = nil - inCatForm = HasCatForm() - end - elseif not inCatForm then - -- Not in cat form, do a full scan (might have just shifted) - prowling = FullScan() + if event == "UPDATE_SHAPESHIFT_FORM" then + -- Authoritative form-change signal — recompute and short-circuit. + inCatForm = HasCatForm() + if not inCatForm then + prowlActive = nil + prowling = nil + end + return + end + + -- PLAYER_AURAS_CHANGED: form changes already went through + -- UPDATE_SHAPESHIFT_FORM above; this handler only watches prowl on/off. + if inCatForm then + if IsStealthed() then + prowlActive = true + prowling = true + else + prowlActive = nil + prowling = nil end - -- 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 + -- Eager prowl detection via Nampower SPELL_GO_SELF — zero-latency vs. + -- PLAYER_AURAS_CHANGED, which can land a frame or two behind the cast. + -- Form changes are no longer hooked here; UPDATE_SHAPESHIFT_FORM covers + -- those without needing a per-spellID watchlist. 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) @@ -999,8 +1003,6 @@ pfUI:RegisterModule("actionbar", "vanilla", function () inCatForm = true prowlActive = true prowling = true - elseif spellId == 768 then - inCatForm = true end end pageswitch:SetScript("OnUpdate", function() diff --git a/modules/autoshift.lua b/modules/autoshift.lua index 77e57929..f14ddc3c 100644 --- a/modules/autoshift.lua +++ b/modules/autoshift.lua @@ -24,31 +24,25 @@ pfUI:RegisterModule("autoshift", "vanilla", function () "根据您的骑行技能提高速度。", "根据骑术技能提高速度。", "又慢又稳......", } + -- Form ID -> icon-path fragment of that form's buff. GetShapeshiftFormID + -- tells us the active form directly; we still need to locate the buff in + -- the player's array to find the bid for CancelPlayerBuff. + -- + -- Replaces the old texture-list scan plus moonkin_scan frame: the agility + -- buff that shares moonkin's icon no longer causes false positives because + -- form ID 31 is only reported when the player is genuinely in Moonkin Form, + -- regardless of what other buffs happen to be active. pfUI.autoshift.shapeshifts = { - "ability_racial_bearform", "ability_druid_catform", "ability_druid_travelform", - "ability_druid_aquaticform", "spell_shadow_shadowform", "spell_nature_spiritwolf", + [1] = "ability_druid_catform", -- Cat Form + [3] = "ability_druid_travelform", -- Travel Form + [4] = "ability_druid_aquaticform", -- Aquatic Form + [5] = "ability_racial_bearform", -- Bear Form + [8] = "ability_racial_bearform", -- Dire Bear (shares texture with Bear) + [16] = "spell_nature_spiritwolf", -- Shaman Ghost Wolf + [28] = "spell_shadow_shadowform", -- Priest Shadowform + [31] = "spell_nature_forceofnature", -- Druid Moonkin } - -- an agility buff exists which has the same icon as the moonkin form - -- therefore only add the moonkin icon to the removable buffs if - -- moonkin is skilled and player is druid. Frame is required as talentpoints - -- are only accessible after certain events. - local moonkin_scan = CreateFrame("Frame") - moonkin_scan:RegisterEvent("PLAYER_ENTERING_WORLD") - moonkin_scan:RegisterEvent("UNIT_NAME_UPDATE") - moonkin_scan:SetScript("OnEvent", function() - local _, class = UnitClass("player") - if class == "DRUID" then - local _,_,_,_,moonkin = GetTalentInfo(1,16) - if moonkin == 1 then - table.insert(pfUI.autoshift.shapeshifts, "spell_nature_forceofnature") - moonkin_scan:UnregisterAllEvents() - end - else - moonkin_scan:UnregisterAllEvents() - end - end) - pfUI.autoshift.errors = { SPELL_FAILED_NOT_MOUNTED, ERR_ATTACK_MOUNTED, ERR_TAXIPLAYERALREADYMOUNTED, SPELL_FAILED_NOT_SHAPESHIFT, SPELL_FAILED_NO_ITEMS_WHILE_SHAPESHIFTED, SPELL_NOT_SHAPESHIFTED, SPELL_NOT_SHAPESHIFTED_NOSPACE, ERR_CANT_INTERACT_SHAPESHIFTED, ERR_NOT_WHILE_SHAPESHIFTED, @@ -71,19 +65,17 @@ pfUI:RegisterModule("autoshift", "vanilla", function () return end - -- delay shapeshift cancel - local CancelLater = nil - -- scan through buffs and cancel shapeshift/mount for id, errorstring in pairs(pfUI.autoshift.errors) do if arg1 == errorstring then - -- dont's cancel form when clicking on npcs while in combat + -- don't cancel form when clicking on npcs while in combat if arg1 == ERR_CANT_INTERACT_SHAPESHIFTED and UnitAffectingCombat("player") then return end - for i=0,31,1 do - -- detect mounts based on tooltip text + -- Phase 1: mounts take priority (mount/shapeshift can't coexist in + -- vanilla, but the original error list also covers mount-only states). + for i = 0, 31 do pfUI.autoshift.scanner:SetPlayerBuff(i) for _, str in pairs(pfUI.autoshift.mounts) do if pfUI.autoshift.scanner:Find(str) then @@ -91,27 +83,19 @@ pfUI:RegisterModule("autoshift", "vanilla", function () return end end - - -- detect shapeshift based on texture - local buff = GetPlayerBuffTexture(i) - if buff then - for id, bufftype in pairs(pfUI.autoshift.shapeshifts) do - if string.find(string.lower(buff), bufftype, 1) then - if string.find(string.lower(buff), "spell_shadow_shadowform", 1) then - -- only cancel shadow form if no other buff was hindering casting - CancelLater = i - else - CancelPlayerBuff(i) - return - end - end - end - end end - -- if nothing else was found, cancel shadowform - if CancelLater then - CancelPlayerBuff(CancelLater) + -- Phase 2: cancel the active shapeshift if any. GetShapeshiftFormID + -- gives us the form directly; we iterate to find its buff bid. + local formTexture = pfUI.autoshift.shapeshifts[GetShapeshiftFormID()] + if formTexture then + for i = 0, 31 do + local buff = GetPlayerBuffTexture(i) + if buff and string.find(string.lower(buff), formTexture, 1) then + CancelPlayerBuff(i) + return + end + end end end end