From 1172e3377ba8d6f959efa4e952343d832ef826c9 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 16 Nov 2025 16:49:30 +0000 Subject: [PATCH] Add learned combo duration system - saves actual durations per CP Major enhancement: System now learns actual combo finisher durations and saves them per combo point level (1-5 CP). **New SavedVariable:** - CleveRoids_ComboDurations[spellID][comboPoints] = duration - Persists between sessions - Uses learned durations before calculated formulas **ComboPointTracker.lua:** - Added GetLearnedComboDuration(spellID, cp) - fetch learned duration - Updated CalculateComboScaledDurationByID to check learned first - Falls back to formula if not learned yet **Utility.lua (libdebuff):** - UNIT_CASTEVENT handler stores combo points in learnCastTimers - RAW_COMBATLOG fade handler learns combo durations when spells expire - Stores learned duration keyed by [spellID][comboPoints] - Debug message shows "Learned combo spell X at Y CP = Zs" **Core.lua:** - New command: /cleveroid combolearn - Show all learned combo durations - Lists each spell with all learned CP levels (1-5) - Shows which durations have been learned vs not yet **Benefits:** - Debuff conditionals like [debuff:Rip<4] now use ACTUAL max duration - Accounts for talents that modify finisher durations - Learns different durations per rank - More accurate than formulas for edge cases **Example:** After casting Rip with 5 CP and letting it expire, system learns: CleveRoids_ComboDurations[1079][5] = 28 Future casts use 28s instead of calculated 12+4*4 --- ComboPointTracker.lua | 21 ++++++++++++++++++++- Core.lua | 21 +++++++++++++++++++++ SuperCleveRoidMacros.toc | 2 +- Utility.lua | 31 +++++++++++++++++++++++++------ 4 files changed, 67 insertions(+), 8 deletions(-) diff --git a/ComboPointTracker.lua b/ComboPointTracker.lua index e2514bb..2fa97f7 100644 --- a/ComboPointTracker.lua +++ b/ComboPointTracker.lua @@ -12,6 +12,10 @@ CleveRoids.ComboPointTracking = CleveRoids.ComboPointTracking or {} CleveRoids.spell_tracking = CleveRoids.spell_tracking or {} CleveRoids.lastComboPoints = CleveRoids.lastComboPoints or 0 -- Track last known CP count +-- Initialize SavedVariable for learned combo durations +-- Structure: CleveRoids_ComboDurations[spellID][comboPoints] = duration +CleveRoids_ComboDurations = CleveRoids_ComboDurations or {} + -- Define spells that scale with combo points by SPELL ID and their duration formulas -- Duration = base + (combo_points - 1) * increment CleveRoids.ComboScalingSpellsByID = { @@ -143,7 +147,15 @@ function CleveRoids.GetComboScalingDataByID(spellID) return CleveRoids.ComboScalingSpellsByID[spellID] end --- NEW: Calculate duration by spell ID and combo points +-- NEW: Get learned duration for specific combo point count +function CleveRoids.GetLearnedComboDuration(spellID, comboPoints) + if CleveRoids_ComboDurations[spellID] and CleveRoids_ComboDurations[spellID][comboPoints] then + return CleveRoids_ComboDurations[spellID][comboPoints] + end + return nil +end + +-- NEW: Calculate duration by spell ID and combo points (uses learned durations first) function CleveRoids.CalculateComboScaledDurationByID(spellID, comboPoints) local data = CleveRoids.GetComboScalingDataByID(spellID) if not data then return nil end @@ -152,6 +164,13 @@ function CleveRoids.CalculateComboScaledDurationByID(spellID, comboPoints) if comboPoints < 1 then comboPoints = 1 end -- Minimum 1 combo point if comboPoints > 5 then comboPoints = 5 end -- Maximum 5 combo points + -- Check for learned duration first + local learned = CleveRoids.GetLearnedComboDuration(spellID, comboPoints) + if learned then + return learned + end + + -- Fall back to formula return data.base + (comboPoints - 1) * data.increment end diff --git a/Core.lua b/Core.lua index b264da0..2321aba 100644 --- a/Core.lua +++ b/Core.lua @@ -3136,6 +3136,7 @@ SlashCmdList["CLEVEROID"] = function(msg) DEFAULT_CHAT_FRAME:AddMessage("|cffffaa00Combo Point Tracking:|r") DEFAULT_CHAT_FRAME:AddMessage('/cleveroid combotrack - Show combo point tracking info') DEFAULT_CHAT_FRAME:AddMessage('/cleveroid comboclear - Clear combo tracking data') + DEFAULT_CHAT_FRAME:AddMessage('/cleveroid combolearn - Show learned combo durations (per CP)') return end @@ -3299,6 +3300,25 @@ SlashCmdList["CLEVEROID"] = function(msg) return end + -- combolearn (show learned combo durations) + if cmd == "combolearn" or cmd == "combodurations" then + CleveRoids.Print("=== Learned Combo Durations ===") + if not CleveRoids_ComboDurations or not next(CleveRoids_ComboDurations) then + CleveRoids.Print("No learned combo durations yet. Cast finishers and let them expire!") + else + for spellID, cpData in pairs(CleveRoids_ComboDurations) do + local spellName = SpellInfo(spellID) or ("Spell " .. spellID) + CleveRoids.Print(spellName .. " (ID:" .. spellID .. "):") + for cp = 1, 5 do + if cpData[cp] then + CleveRoids.Print(" " .. cp .. " CP = " .. cpData[cp] .. "s") + end + end + end + end + return + end + -- Unknown command fallback CleveRoids.Print("Usage:") DEFAULT_CHAT_FRAME:AddMessage("/cleveroid - Show current settings") @@ -3317,6 +3337,7 @@ SlashCmdList["CLEVEROID"] = function(msg) DEFAULT_CHAT_FRAME:AddMessage("|cffffaa00Combo Point Tracking:|r") DEFAULT_CHAT_FRAME:AddMessage('/cleveroid combotrack - Show combo point tracking info') DEFAULT_CHAT_FRAME:AddMessage('/cleveroid comboclear - Clear combo tracking data') + DEFAULT_CHAT_FRAME:AddMessage('/cleveroid combolearn - Show learned combo durations (per CP)') end SLASH_CLEAREQUIPQUEUE1 = "/clearequipqueue" diff --git a/SuperCleveRoidMacros.toc b/SuperCleveRoidMacros.toc index af8b81a..cbe22e3 100644 --- a/SuperCleveRoidMacros.toc +++ b/SuperCleveRoidMacros.toc @@ -4,7 +4,7 @@ ## Notes: /cleveroid for settings ## Version: 1.3 ## OptionalDeps: ClassicFocus, FocusFrame, pfUI, SuperMacro, Bongos_ActionBar -## SavedVariables: CleveRoidMacros, CleveRoids_LearnedDurations, CleveRoids_AuraTextures, CleveRoids_ImmunityData +## SavedVariables: CleveRoidMacros, CleveRoids_LearnedDurations, CleveRoids_AuraTextures, CleveRoids_ImmunityData, CleveRoids_ComboDurations Localization.lua Init.lua Utility.lua diff --git a/Utility.lua b/Utility.lua index 795b83a..a92a0d2 100644 --- a/Utility.lua +++ b/Utility.lua @@ -838,8 +838,14 @@ ev:SetScript("OnEvent", function() -- Check if this is a combo point scaling spell first local duration = nil + local comboPoints = nil if CleveRoids.TrackComboPointCastByID then duration = CleveRoids.TrackComboPointCastByID(spellID, targetGUID) + -- Get combo points used from tracking + if CleveRoids.ComboPointTracking and CleveRoids.ComboPointTracking.byID and + CleveRoids.ComboPointTracking.byID[spellID] then + comboPoints = CleveRoids.ComboPointTracking.byID[spellID].combo_points + end end -- If not a combo scaling spell, use normal duration lookup @@ -860,6 +866,16 @@ ev:SetScript("OnEvent", function() end lib:AddEffect(targetGUID, targetName, spellID, duration, 0, "player") + -- ALWAYS set up learning for combo spells (even if we have calculated duration) + if comboPoints then + lib.learnCastTimers[targetGUID] = lib.learnCastTimers[targetGUID] or {} + lib.learnCastTimers[targetGUID][spellID] = { + start = GetTime(), + caster = casterGUID, + comboPoints = comboPoints -- Store CP count for learning + } + end + else lib.learnCastTimers[targetGUID] = lib.learnCastTimers[targetGUID] or {} lib.learnCastTimers[targetGUID][spellID] = { @@ -915,18 +931,21 @@ evLearn:SetScript("OnEvent", function() local actualDuration = timestamp - castTime -- Check if this is a combo point spell - if so, learn it with combo point context - local isComboSpell = false - if CleveRoids.IsComboScalingSpellID and CleveRoids.IsComboScalingSpellID(spellID) then - isComboSpell = true + local comboPoints = lib.learnCastTimers[targetGUID][spellID].comboPoints + if comboPoints and CleveRoids.IsComboScalingSpellID and CleveRoids.IsComboScalingSpellID(spellID) then + -- Learn combo spell duration + CleveRoids_ComboDurations = CleveRoids_ComboDurations or {} + CleveRoids_ComboDurations[spellID] = CleveRoids_ComboDurations[spellID] or {} + CleveRoids_ComboDurations[spellID][comboPoints] = floor(actualDuration + 0.5) + if CleveRoids.debug then - local comboData = CleveRoids.ComboPointTracking.byID and CleveRoids.ComboPointTracking.byID[spellID] - local cpUsed = comboData and comboData.combo_points or "?" DEFAULT_CHAT_FRAME:AddMessage( "|cff4b7dccCleveRoids:|r Learned combo spell " .. spellName .. - " (ID:" .. spellID .. ") with " .. cpUsed .. " CP = " .. floor(actualDuration + 0.5) .. "s" + " (ID:" .. spellID .. ") at " .. comboPoints .. " CP = " .. floor(actualDuration + 0.5) .. "s" ) end else + -- Learn normal spell duration CleveRoids_LearnedDurations[spellID] = CleveRoids_LearnedDurations[spellID] or {} CleveRoids_LearnedDurations[spellID][casterGUID] = floor(actualDuration + 0.5)