mirror of
https://github.com/brues-code/SuperCleveRoidMacros.git
synced 2026-09-16 03:38:00 +00:00
aedb2684b5
Problem: Macro conditional evaluations create tracking entries, but pfUI's AddEffect can fire during these evaluations (before actual cast), causing it to use incorrect combo point data. Flow before fix: 1. Macro evaluates [combo:>0] → TrackComboPointCast(0 CP, confirmed=false) 2. Macro evaluates again → TrackComboPointCast(1 CP, confirmed=false) 3. pfUI AddEffect fires → uses tracking (wrong timing!) ✗ 4. SPELLCAST_START fires (actual cast) Flow after fix: 1. Macro evaluates [combo:>0] → TrackComboPointCast(0 CP, confirmed=false) 2. Macro evaluates again → TrackComboPointCast(1 CP, confirmed=false) 3. SPELLCAST_START fires → sets confirmed=true ✓ 4. pfUI AddEffect fires → only uses tracking if confirmed=true ✓ Changes: - Added 'confirmed' field to tracking (default: false) - SPELLCAST_START sets confirmed=true when spell actually casts - pfUI AddEffect hook only uses tracking if confirmed=true - Clear confirmed flag after use to prevent reuse - Clear on failed/interrupted casts Debug shows: "Ignoring X tracking (not confirmed - evaluation only)" when preventing use of evaluation-only data.
336 lines
12 KiB
Lua
336 lines
12 KiB
Lua
local _G = _G or getfenv(0)
|
|
local CleveRoids = _G.CleveRoids or {}
|
|
|
|
local Extension = CleveRoids.RegisterExtension("Compatibility_pfUI")
|
|
Extension.RegisterEvent("ADDON_LOADED", "ADDON_LOADED")
|
|
Extension.RegisterEvent("PLAYER_LOGIN", "PLAYER_LOGIN")
|
|
Extension.Debug = false
|
|
|
|
-- Track pfUI state
|
|
Extension.pfUILoaded = false
|
|
Extension.macrotweakLoaded = false
|
|
Extension.slashCommandsOverridden = false
|
|
|
|
function Extension.RunMacro(name)
|
|
CleveRoids.ExecuteMacroByName(name)
|
|
end
|
|
|
|
function Extension.DLOG(msg)
|
|
if Extension.Debug then
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffcccc33[R]: |cffffff55" .. ( msg ))
|
|
end
|
|
end
|
|
|
|
function Extension.FocusNameHook()
|
|
local hook = Extension.internal.memberHooks[CleveRoids]["GetFocusName"]
|
|
local target = hook.original()
|
|
|
|
if pfUI and pfUI.uf and pfUI.uf.focus and pfUI.uf.focus.unitname then
|
|
target = pfUI.uf.focus.unitname
|
|
end
|
|
|
|
--Extension.DLOG(target)
|
|
|
|
return target
|
|
end
|
|
|
|
-- Check if pfUI's macrotweak module is loaded
|
|
function Extension.IsPfUIMacrotweakLoaded()
|
|
if not pfUI then return false end
|
|
|
|
-- pfUI loads modules and stores them in pfUI.modules
|
|
if pfUI.modules and pfUI.modules.macrotweak then
|
|
return true
|
|
end
|
|
|
|
-- Also check if the slash commands exist with pfUI's pattern
|
|
if SlashCmdList.PFUSE or SlashCmdList.PFEQUIP then
|
|
return true
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
-- Override pfUI's /use and /equip with CleveRoids versions
|
|
function Extension.OverridePfUISlashCommands()
|
|
if Extension.slashCommandsOverridden then return end
|
|
|
|
-- Save pfUI's original handlers as fallbacks
|
|
if SlashCmdList.PFUSE then
|
|
CleveRoids.Hooks.PFUI_USE = SlashCmdList.PFUSE
|
|
end
|
|
if SlashCmdList.PFEQUIP then
|
|
CleveRoids.Hooks.PFUI_EQUIP = SlashCmdList.PFEQUIP
|
|
end
|
|
|
|
-- Override with CleveRoids' conditional-aware handlers
|
|
SlashCmdList.USE = CleveRoids.DoUse
|
|
SlashCmdList.EQUIP = CleveRoids.DoUse
|
|
SlashCmdList.PFUSE = CleveRoids.DoUse
|
|
SlashCmdList.PFEQUIP = CleveRoids.DoUse
|
|
SlashCmdList.SMEQUIP = CleveRoids.DoUse
|
|
|
|
Extension.slashCommandsOverridden = true
|
|
|
|
Extension.DLOG("Overrode /use and /equip commands for conditional support")
|
|
end
|
|
|
|
-- Check and handle SendChatMessage hook compatibility
|
|
function Extension.HandleSendChatMessageHook()
|
|
-- Check if SendChatMessage has already been hooked by something else
|
|
local currentHook = _G.SendChatMessage
|
|
local originalSendChat = CleveRoids.Hooks.SendChatMessage
|
|
|
|
if not originalSendChat then return end
|
|
|
|
-- If pfUI already hooked SendChatMessage, we need to chain properly
|
|
if currentHook and currentHook ~= originalSendChat then
|
|
-- pfUI's hook is in place, let it handle #showtooltip filtering
|
|
-- Our hook is redundant, so we can skip it
|
|
Extension.DLOG("pfUI's SendChatMessage hook detected, using pfUI's filtering")
|
|
end
|
|
end
|
|
|
|
-- Hook pfUI's libdebuff to use our combo-aware durations
|
|
function Extension.HookPfUILibdebuff()
|
|
if not pfUI or not pfUI.api or not pfUI.api.libdebuff then
|
|
return false
|
|
end
|
|
|
|
local pflib = pfUI.api.libdebuff
|
|
|
|
-- Hook GetDuration if it exists
|
|
if pflib.GetDuration and not Extension.pfLibDebuffHooked then
|
|
local originalGetDuration = pflib.GetDuration
|
|
|
|
pflib.GetDuration = function(self, spellID, casterGUID, comboPoints)
|
|
-- Check if this is a combo scaling spell first
|
|
if CleveRoids.IsComboScalingSpellID and CleveRoids.IsComboScalingSpellID(spellID) then
|
|
-- If combo points provided, check learned combo durations
|
|
if comboPoints and CleveRoids_ComboDurations and CleveRoids_ComboDurations[spellID] then
|
|
local comboDur = CleveRoids_ComboDurations[spellID][comboPoints]
|
|
if comboDur and comboDur > 0 then
|
|
if CleveRoids.debug then
|
|
DEFAULT_CHAT_FRAME:AddMessage(
|
|
string.format("|cff00ff00[pfUI Hook]|r Returning %ds for spell %d at %d CP",
|
|
comboDur, spellID, comboPoints)
|
|
)
|
|
end
|
|
return comboDur
|
|
end
|
|
end
|
|
|
|
-- Fallback: check for highest learned combo duration
|
|
if CleveRoids_ComboDurations and CleveRoids_ComboDurations[spellID] then
|
|
for cp = 5, 1, -1 do
|
|
if CleveRoids_ComboDurations[spellID][cp] then
|
|
if CleveRoids.debug then
|
|
DEFAULT_CHAT_FRAME:AddMessage(
|
|
string.format("|cff00ff00[pfUI Hook]|r Returning %ds for spell %d (fallback %d CP)",
|
|
CleveRoids_ComboDurations[spellID][cp], spellID, cp)
|
|
)
|
|
end
|
|
return CleveRoids_ComboDurations[spellID][cp]
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Not a combo spell or no learned duration, use original
|
|
return originalGetDuration(self, spellID, casterGUID, comboPoints)
|
|
end
|
|
|
|
Extension.pfLibDebuffHooked = true
|
|
Extension.DLOG("Hooked pfUI.api.libdebuff.GetDuration for combo duration support")
|
|
end
|
|
|
|
-- Hook AddEffect if it exists to inject combo-aware durations
|
|
if pflib.AddEffect and not Extension.pfLibAddEffectHooked then
|
|
local originalAddEffect = pflib.AddEffect
|
|
|
|
pflib.AddEffect = function(self, unit, unitlevel, effect, duration, caster)
|
|
-- effect is a spell name, not ID
|
|
-- Check if this is a combo scaling spell by name
|
|
if CleveRoids.IsComboScalingSpell and CleveRoids.IsComboScalingSpell(effect) then
|
|
-- Use name-based tracking which is populated BEFORE pfUI's AddEffect
|
|
if CleveRoids.ComboPointTracking and CleveRoids.ComboPointTracking[effect] then
|
|
local tracking = CleveRoids.ComboPointTracking[effect]
|
|
-- Only use tracking if it's confirmed (actual cast, not just evaluation)
|
|
if tracking.duration and tracking.confirmed and (GetTime() - tracking.cast_time) < 0.5 then
|
|
duration = tracking.duration
|
|
-- Clear confirmed flag after use to prevent reuse
|
|
tracking.confirmed = false
|
|
if CleveRoids.debug then
|
|
DEFAULT_CHAT_FRAME:AddMessage(
|
|
string.format("|cff00ff00[pfUI AddEffect Hook]|r Overriding %s duration to %ds (from confirmed tracking)",
|
|
effect, duration)
|
|
)
|
|
end
|
|
elseif CleveRoids.debug and tracking.duration and not tracking.confirmed then
|
|
DEFAULT_CHAT_FRAME:AddMessage(
|
|
string.format("|cffaaaa00[pfUI AddEffect Hook]|r Ignoring %s tracking (not confirmed - evaluation only)",
|
|
effect)
|
|
)
|
|
end
|
|
end
|
|
end
|
|
|
|
return originalAddEffect(self, unit, unitlevel, effect, duration, caster)
|
|
end
|
|
|
|
Extension.pfLibAddEffectHooked = true
|
|
Extension.DLOG("Hooked pfUI.api.libdebuff.AddEffect for combo duration support")
|
|
end
|
|
|
|
return Extension.pfLibDebuffHooked or Extension.pfLibAddEffectHooked
|
|
end
|
|
|
|
-- Synchronize combo durations to pfUI's libdebuff objects
|
|
function Extension.SyncComboDurationToPfUI(guid, spellID, duration)
|
|
if not pfUI or not pfUI.api or not pfUI.api.libdebuff then
|
|
return
|
|
end
|
|
|
|
-- Get unit name from GUID
|
|
local unitName = nil
|
|
local unitLevel = 0
|
|
|
|
-- Check if this is the current target
|
|
local _, targetGUID = UnitExists("target")
|
|
if targetGUID == guid then
|
|
unitName = UnitName("target")
|
|
unitLevel = UnitLevel("target") or 0
|
|
end
|
|
|
|
-- If we couldn't find the unit, use GUID to name mapping from libdebuff
|
|
if not unitName and CleveRoids.libdebuff and CleveRoids.libdebuff.guidToName then
|
|
unitName = CleveRoids.libdebuff.guidToName[guid]
|
|
-- Default to level 0 if we don't have the unit targeted
|
|
unitLevel = 0
|
|
end
|
|
|
|
if not unitName then
|
|
if CleveRoids.debug then
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000[pfUI Sync]|r Could not find unit name for GUID")
|
|
end
|
|
return
|
|
end
|
|
|
|
-- Get spell name from spell ID
|
|
local spellName = SpellInfo(spellID)
|
|
if not spellName then
|
|
if CleveRoids.debug then
|
|
DEFAULT_CHAT_FRAME:AddMessage("|cffff0000[pfUI Sync]|r Could not find spell name for ID " .. spellID)
|
|
end
|
|
return
|
|
end
|
|
|
|
-- Remove rank from spell name to match pfUI's format
|
|
local effectName = string.gsub(spellName, "%s*%(Rank %d+%)", "")
|
|
|
|
-- Update pfUI's stored debuff duration
|
|
local pflib = pfUI.api.libdebuff
|
|
if pflib.objects and pflib.objects[unitName] then
|
|
-- Try both the specific level and level 0 (fallback)
|
|
for _, level in ipairs({unitLevel, 0}) do
|
|
if pflib.objects[unitName][level] and pflib.objects[unitName][level][effectName] then
|
|
local old_duration = pflib.objects[unitName][level][effectName].duration
|
|
pflib.objects[unitName][level][effectName].duration = duration
|
|
|
|
if CleveRoids.debug then
|
|
DEFAULT_CHAT_FRAME:AddMessage(
|
|
string.format("|cff00ffaa[pfUI Sync]|r Updated %s on %s (L%d): %ds -> %ds",
|
|
effectName, unitName, level, old_duration or 0, duration)
|
|
)
|
|
end
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
if CleveRoids.debug then
|
|
DEFAULT_CHAT_FRAME:AddMessage(
|
|
string.format("|cffaaaa00[pfUI Sync]|r Effect not found in pfUI storage: %s on %s",
|
|
effectName, unitName)
|
|
)
|
|
end
|
|
end
|
|
|
|
-- Main compatibility check and setup
|
|
function Extension.SetupCompatibility()
|
|
Extension.pfUILoaded = (pfUI ~= nil)
|
|
Extension.macrotweakLoaded = Extension.IsPfUIMacrotweakLoaded()
|
|
|
|
if Extension.pfUILoaded then
|
|
Extension.DLOG("pfUI detected")
|
|
|
|
-- Hook libdebuff for combo duration support
|
|
Extension.HookPfUILibdebuff()
|
|
|
|
if Extension.macrotweakLoaded then
|
|
Extension.DLOG("pfUI macrotweak module detected")
|
|
|
|
-- Override slash commands to ensure CleveRoids' conditional support works
|
|
Extension.OverridePfUISlashCommands()
|
|
|
|
-- Handle SendChatMessage hook
|
|
Extension.HandleSendChatMessageHook()
|
|
end
|
|
end
|
|
end
|
|
|
|
function Extension.OnLoad()
|
|
Extension.DLOG("Extension pfUI Loaded.")
|
|
Extension.HookMethod(CleveRoids, "GetFocusName", "FocusNameHook", true)
|
|
|
|
-- Export extension for external access
|
|
CleveRoids.Compatibility_pfUI = Extension
|
|
|
|
-- Initial compatibility check
|
|
Extension.SetupCompatibility()
|
|
end
|
|
|
|
function Extension.ADDON_LOADED()
|
|
-- Check if pfUI just loaded
|
|
if arg1 == "pfUI" then
|
|
Extension.pfUILoaded = true
|
|
-- pfUI modules load after ADDON_LOADED, so schedule a check
|
|
if CleveRoids.ScheduleTimer then
|
|
CleveRoids.ScheduleTimer(function()
|
|
Extension.SetupCompatibility()
|
|
end, 0.5)
|
|
end
|
|
end
|
|
end
|
|
|
|
function Extension.PLAYER_LOGIN()
|
|
-- Final check after everything is loaded
|
|
Extension.SetupCompatibility()
|
|
end
|
|
|
|
-- Utility: Schedule a delayed function call (if not already defined)
|
|
if not CleveRoids.ScheduleTimer then
|
|
local timerFrame = CreateFrame("Frame")
|
|
local timers = {}
|
|
|
|
timerFrame:SetScript("OnUpdate", function()
|
|
local time = GetTime()
|
|
for i = table.getn(timers), 1, -1 do
|
|
local timer = timers[i]
|
|
if time >= timer.time then
|
|
timer.func()
|
|
table.remove(timers, i)
|
|
end
|
|
end
|
|
end)
|
|
|
|
CleveRoids.ScheduleTimer = function(func, delay)
|
|
table.insert(timers, {
|
|
func = func,
|
|
time = GetTime() + delay
|
|
})
|
|
end
|
|
end
|
|
|
|
_G["CleveRoids"] = CleveRoids
|