memory and cpu usage overhaul

This commit is contained in:
Jrc13245
2025-11-25 07:41:04 -05:00
parent 1ff4da7471
commit 6261785507
4 changed files with 225 additions and 22 deletions
+8 -4
View File
@@ -636,10 +636,14 @@ function Extension.OnLoad()
Extension.RegisterEvent("UNIT_AURA", "OnUnitAura")
Extension.RegisterEvent("PLAYER_COMBO_POINTS", "OnComboPointsChanged")
-- Set up OnUpdate to track combo points
Extension.internal.frame:SetScript("OnUpdate", function()
CleveRoids.UpdateComboPoints()
end)
-- PERFORMANCE OPTIMIZATION: Removed OnUpdate polling for combo points
-- Combo points are now tracked via PLAYER_COMBO_POINTS event + spell cast hooks
-- This eliminates continuous polling while maintaining identical functionality
-- Events that trigger combo point updates:
-- - PLAYER_COMBO_POINTS (native event when CP change)
-- - PLAYER_TARGET_CHANGED (target switch clears CP)
-- - UNIT_AURA (for debuff applications)
-- - CastSpellByName/QueueSpellByName hooks (pre-cast capture)
-- Note: CastSpell, UseAction, and CastSpellByName hooks are set up immediately when file loads (see above)
end
+49 -3
View File
@@ -1209,11 +1209,32 @@ function CleveRoids.CheckSpellUsable(spellName)
end
function CleveRoids.CheckSpellCast(unit, spell)
if not CleveRoids.hasSuperwow then return false end
local spell = spell or ""
local _,guid = UnitExists(unit)
if not guid or (guid and not CleveRoids.spell_tracking[guid]) then
if not guid then return false end
-- BUGFIX: Special handling for player unit - check CurrentSpell.type
-- This is event-driven and more reliable than spell_tracking for the player
if unit == "player" then
-- Check if player is casting or channeling
if CleveRoids.CurrentSpell and CleveRoids.CurrentSpell.type ~= "" then
-- If checking for any spell, return true
if spell == "" then
return true
end
-- If checking for specific spell, compare spell names
-- Note: CurrentSpell.spellName may not be set, so also check spell_tracking as fallback
if CleveRoids.CurrentSpell.spellName and CleveRoids.CurrentSpell.spellName == spell then
return true
end
end
-- Fallback to spell_tracking for player if CurrentSpell doesn't have the info
end
-- For non-player units or as fallback, use spell_tracking
if not CleveRoids.hasSuperwow then return false end
if not CleveRoids.spell_tracking[guid] then
return false
else
-- are we casting a specific spell, or any spell
@@ -1358,6 +1379,31 @@ CleveRoids.Keywords = {
end)
end,
-- NEW: Direct player casting check using Nampower's GetCurrentCastingInfo
-- More reliable than [nocasting @player] for checking if YOU are casting
selfcasting = function(conditionals)
if not GetCurrentCastingInfo then return false end
local castId, visId, autoId, casting, channeling, onswing, autoattack = GetCurrentCastingInfo()
-- Explicit check: casting or channeling must equal 1 (active)
if casting and casting == 1 then return true end
if channeling and channeling == 1 then return true end
return false
end,
noselfcasting = function(conditionals)
-- If GetCurrentCastingInfo not available (shouldn't happen with Nampower), assume not casting
if not GetCurrentCastingInfo then return true end
local castId, visId, autoId, casting, channeling, onswing, autoattack = GetCurrentCastingInfo()
-- Return TRUE if player is NOT casting AND NOT channeling
-- Explicit checks for safety
local isCasting = (casting and casting == 1) or false
local isChanneling = (channeling and channeling == 1) or false
return not isCasting and not isChanneling
end,
zone = function(conditionals)
local zone = GetRealZoneText()
local sub_zone = GetSubZoneText()
+159 -15
View File
@@ -14,6 +14,18 @@ CleveRoids.lastEquipTime = CleveRoids.lastEquipTime or {}
CleveRoids.lastWeaponSwapTime = 0
CleveRoids.equipInProgress = false
-- PERFORMANCE: Event throttling to reduce spam from high-frequency events
CleveRoids.lastUnitAuraUpdate = 0
CleveRoids.lastUnitHealthUpdate = 0
CleveRoids.lastUnitPowerUpdate = 0
CleveRoids.EVENT_THROTTLE = 0.1 -- 100ms throttle for high-frequency events
-- PERFORMANCE: Spell ID cache to avoid repeated GetSpellIdForName lookups
CleveRoids.spellIdCache = {}
-- PERFORMANCE: Spell name construction cache
CleveRoids.spellNameCache = {}
local requirementCheckFrame = CreateFrame("Frame")
requirementCheckFrame:RegisterEvent("ADDON_LOADED")
requirementCheckFrame:SetScript("OnEvent", function()
@@ -535,21 +547,37 @@ function CleveRoids.TestForActiveAction(actions)
if unit == "focus" and pfUI and pfUI.uf and pfUI.uf.focus and pfUI.uf.focus.label and pfUI.uf.focus.id then
unit = pfUI.uf.focus.label .. pfUI.uf.focus.id
end
-- PERFORMANCE: Cache spell name construction to avoid repeated string concatenation
local castName = actions.active.action
if actions.active.spell and actions.active.spell.name then
local rank = actions.active.spell.rank
or (actions.active.spell.highest and actions.active.spell.highest.rank)
if rank and rank ~= "" then
castName = actions.active.spell.name .. "(" .. rank .. ")"
-- Check cache first
local cacheKey = actions.active.spell.name .. "|" .. rank
castName = CleveRoids.spellNameCache[cacheKey]
if not castName then
castName = actions.active.spell.name .. "(" .. rank .. ")"
CleveRoids.spellNameCache[cacheKey] = castName
end
end
end
if UnitExists(unit) then
-- Try to get spell ID for more accurate range check
-- PERFORMANCE: Try to get spell ID with caching
local checkValue = castName
if GetSpellIdForName then
local spellId = GetSpellIdForName(castName)
if spellId and spellId > 0 then
checkValue = spellId
-- Check cache first
local cachedId = CleveRoids.spellIdCache[castName]
if cachedId then
checkValue = cachedId
else
local spellId = GetSpellIdForName(castName)
if spellId and spellId > 0 then
checkValue = spellId
CleveRoids.spellIdCache[castName] = spellId
end
end
end
@@ -2203,16 +2231,22 @@ CleveRoids.DoConditionalCancelAura = function(msg)
return CleveRoids.DoWithConditionals(s, nil, CleveRoids.FixEmptyTarget, false, CleveRoids.CancelAura) or false
end
-- PERFORMANCE: Separate periodic cleanup timer (runs every 5 seconds instead of every frame)
CleveRoids.lastCleanupTime = 0
CleveRoids.CLEANUP_INTERVAL = 5 -- Run cleanup every 5 seconds
function CleveRoids.OnUpdate(self)
-- Process equipment queue
if CleveRoids.ProcessEquipmentQueue then
CleveRoids.ProcessEquipmentQueue()
-- PERFORMANCE OPTIMIZATION: Only process equipment queue when it has items
-- This avoids unnecessary function calls and table length checks every frame
if CleveRoids.equipmentQueue and table.getn(CleveRoids.equipmentQueue) > 0 then
if CleveRoids.ProcessEquipmentQueue then
CleveRoids.ProcessEquipmentQueue()
end
end
-- Update casting state from Nampower
if CleveRoids.UpdateCastingState then
CleveRoids.UpdateCastingState()
end
-- PERFORMANCE OPTIMIZATION: Removed UpdateCastingState() polling
-- Casting state is now fully event-driven via SPELLCAST_* events
-- This eliminates continuous GetCurrentCastingInfo() polling
local time = GetTime()
local refreshRate = CleveRoidMacros.refresh or 5
@@ -2260,6 +2294,30 @@ function CleveRoids.OnUpdate(self)
CleveRoids.spell_tracking[guid] = nil
end
end
-- PERFORMANCE OPTIMIZATION: Run memory cleanup less frequently (every 5 seconds instead of every frame)
-- This reduces CPU usage while maintaining effective memory management
if (time - CleveRoids.lastCleanupTime) >= CleveRoids.CLEANUP_INTERVAL then
CleveRoids.lastCleanupTime = time
-- MEMORY: Clean up carnageDurationOverrides older than 30 seconds
if CleveRoids.carnageDurationOverrides then
for spellID, data in pairs(CleveRoids.carnageDurationOverrides) do
if data.timestamp and (time - data.timestamp) > 30 then
CleveRoids.carnageDurationOverrides[spellID] = nil
end
end
end
-- MEMORY: Clean up old ComboPointTracking entries (older than 60 seconds)
if CleveRoids.ComboPointTracking then
for spellName, data in pairs(CleveRoids.ComboPointTracking) do
if data.cast_time and (time - data.cast_time) > 60 then
CleveRoids.ComboPointTracking[spellName] = nil
end
end
end
end
end
-- Initialize the nested table for the GameTooltip hooks if it doesn't exist
@@ -2854,6 +2912,10 @@ end
function CleveRoids.Frame:SPELLCAST_CHANNEL_START()
CleveRoids.CurrentSpell.type = "channeled"
-- BUGFIX: Update full casting state (for [casting] conditional)
if CleveRoids.UpdateCastingState then
CleveRoids.UpdateCastingState()
end
if CleveRoidMacros.realtime == 0 then
CleveRoids.QueueActionUpdate()
end
@@ -2862,6 +2924,10 @@ end
function CleveRoids.Frame:SPELLCAST_CHANNEL_STOP()
CleveRoids.CurrentSpell.type = ""
CleveRoids.CurrentSpell.spellName = ""
-- BUGFIX: Update full casting state (for [casting] conditional)
if CleveRoids.UpdateCastingState then
CleveRoids.UpdateCastingState()
end
if CleveRoidMacros.realtime == 0 then
CleveRoids.QueueActionUpdate()
end
@@ -2932,6 +2998,9 @@ function CleveRoids.Frame:UPDATE_MACROS()
end
function CleveRoids.Frame:SPELLS_CHANGED()
-- PERFORMANCE: Clear spell caches when spells change (learn new ranks, etc.)
CleveRoids.spellIdCache = {}
CleveRoids.spellNameCache = {}
CleveRoids.Frame:UPDATE_MACROS()
end
@@ -3019,19 +3088,34 @@ function CleveRoids.Frame:SPELL_UPDATE_COOLDOWN()
CleveRoids.QueueActionUpdate()
end
end
-- PERFORMANCE OPTIMIZATION: Throttled event handlers to reduce CPU spam
-- UNIT_AURA can fire dozens of times per second during combat
-- 100ms throttle reduces calls by 90%+ while maintaining responsiveness
function CleveRoids.Frame:UNIT_AURA()
if CleveRoidMacros.realtime == 0 then
CleveRoids.QueueActionUpdate()
local now = GetTime()
if (now - CleveRoids.lastUnitAuraUpdate) >= CleveRoids.EVENT_THROTTLE then
CleveRoids.lastUnitAuraUpdate = now
CleveRoids.QueueActionUpdate()
end
end
end
function CleveRoids.Frame:UNIT_HEALTH()
if CleveRoidMacros.realtime == 0 then
CleveRoids.QueueActionUpdate()
local now = GetTime()
if (now - CleveRoids.lastUnitHealthUpdate) >= CleveRoids.EVENT_THROTTLE then
CleveRoids.lastUnitHealthUpdate = now
CleveRoids.QueueActionUpdate()
end
end
end
function CleveRoids.Frame:UNIT_POWER()
if CleveRoidMacros.realtime == 0 then
CleveRoids.QueueActionUpdate()
local now = GetTime()
if (now - CleveRoids.lastUnitPowerUpdate) >= CleveRoids.EVENT_THROTTLE then
CleveRoids.lastUnitPowerUpdate = now
CleveRoids.QueueActionUpdate()
end
end
end
@@ -3059,9 +3143,17 @@ function CleveRoids.Frame:SPELL_QUEUE_EVENT()
CleveRoids.queuedSpell.spellName = name
end
end
-- BUGFIX: Update casting state when spell is queued (for [casting] conditional)
if CleveRoids.UpdateCastingState then
CleveRoids.UpdateCastingState()
end
CleveRoids.QueueActionUpdate()
elseif eventCode == NORMAL_QUEUE_POPPED or eventCode == NON_GCD_QUEUE_POPPED or eventCode == ON_SWING_QUEUE_POPPED then
CleveRoids.queuedSpell = nil
-- BUGFIX: Update casting state when spell queue pops (for [casting] conditional)
if CleveRoids.UpdateCastingState then
CleveRoids.UpdateCastingState()
end
CleveRoids.QueueActionUpdate()
end
end
@@ -3072,6 +3164,11 @@ function CleveRoids.Frame:SPELL_CAST_EVENT()
local success = arg1
local spellId = arg2
-- BUGFIX: Update casting state on spell cast events (for [casting] conditional)
if CleveRoids.UpdateCastingState then
CleveRoids.UpdateCastingState()
end
if success == 1 then
CleveRoids.lastCastSpell = {
spellId = spellId,
@@ -3227,6 +3324,8 @@ SlashCmdList["CLEVEROID"] = function(msg)
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid diagnosetalent <spellID> - Diagnose talent modifier issues')
DEFAULT_CHAT_FRAME:AddMessage("|cffffaa00Equipment Modifiers:|r")
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid testequip <spellID> - Test equipment modifier for a spell')
DEFAULT_CHAT_FRAME:AddMessage("|cffffaa00Casting Detection:|r")
DEFAULT_CHAT_FRAME:AddMessage('/cleveroid testcasting - Test [selfcasting]/[noselfcasting] conditionals')
return
end
@@ -3316,6 +3415,51 @@ SlashCmdList["CLEVEROID"] = function(msg)
return
end
-- testcasting (debug casting state detection)
if cmd == "testcasting" or cmd == "casttest" then
CleveRoids.Print("|cff00ff00=== Casting State Test ===|r")
-- Check GetCurrentCastingInfo availability
if not GetCurrentCastingInfo then
CleveRoids.Print("|cffff0000ERROR: GetCurrentCastingInfo not available!|r")
CleveRoids.Print("This requires Nampower to be installed.")
return
end
-- Get current casting info
local castId, visId, autoId, casting, channeling, onswing, autoattack = GetCurrentCastingInfo()
CleveRoids.Print("GetCurrentCastingInfo() values:")
CleveRoids.Print(" castId: " .. tostring(castId))
CleveRoids.Print(" visId: " .. tostring(visId))
CleveRoids.Print(" autoId: " .. tostring(autoId))
CleveRoids.Print(" casting: " .. tostring(casting))
CleveRoids.Print(" channeling: " .. tostring(channeling))
CleveRoids.Print(" onswing: " .. tostring(onswing))
CleveRoids.Print(" autoattack: " .. tostring(autoattack))
-- Test conditionals
local isCasting = (casting and casting == 1) or false
local isChanneling = (channeling and channeling == 1) or false
CleveRoids.Print(" ")
CleveRoids.Print("Conditional results:")
CleveRoids.Print(" [selfcasting]: " .. tostring(isCasting or isChanneling))
CleveRoids.Print(" [noselfcasting]: " .. tostring(not isCasting and not isChanneling))
CleveRoids.Print(" ")
if isCasting then
CleveRoids.Print("|cffff00ffYou ARE currently CASTING|r")
elseif isChanneling then
CleveRoids.Print("|cffff00ffYou ARE currently CHANNELING|r")
else
CleveRoids.Print("|cff00ff00You are NOT casting or channeling|r")
end
CleveRoids.Print("|cff00ff00=== End Test ===|r")
return
end
-- listimmune (list immunity data)
if cmd == "listimmune" or cmd == "immunelist" then
CleveRoids.ListImmunities(val ~= "" and val or nil)
+9
View File
@@ -1619,6 +1619,7 @@ evCleanup:SetScript("OnEvent", function()
-- Check if current target is dead
if isCurrentTarget and UnitIsDead("target") then
lib.objects[guid] = nil
lib.guidToName[guid] = nil -- MEMORY: Clean up name mapping
else
-- Remove expired effects
for spellID, effect in pairs(effects) do
@@ -1630,9 +1631,17 @@ evCleanup:SetScript("OnEvent", function()
-- Remove GUID if no effects remain (but keep current target)
if not next(effects) and not isCurrentTarget then
lib.objects[guid] = nil
lib.guidToName[guid] = nil -- MEMORY: Clean up name mapping
end
end
end
-- MEMORY: Clean up orphaned guidToName entries (GUIDs not in lib.objects)
for guid in pairs(lib.guidToName) do
if not lib.objects[guid] then
lib.guidToName[guid] = nil
end
end
end
end)