diff --git a/ComboPointTracker.lua b/ComboPointTracker.lua index 34b2e81..3ff33cd 100644 --- a/ComboPointTracker.lua +++ b/ComboPointTracker.lua @@ -9,42 +9,40 @@ local CleveRoids = _G.CleveRoids or {} -- Initialize combo point tracking table CleveRoids.ComboPointTracking = CleveRoids.ComboPointTracking or {} +CleveRoids.spell_tracking = CleveRoids.spell_tracking or {} --- Define spells that scale with combo points and their duration formulas +-- Define spells that scale with combo points by SPELL ID and their duration formulas -- Duration = base + (combo_points - 1) * increment +CleveRoids.ComboScalingSpellsByID = { + -- ROGUE: Rupture - 8 sec base, +2 sec per additional combo point + [1943] = { base = 8, increment = 2, name = "Rupture" }, -- Rank 1 + [8639] = { base = 8, increment = 2, name = "Rupture" }, -- Rank 2 + [8640] = { base = 8, increment = 2, name = "Rupture" }, -- Rank 3 + [11273] = { base = 8, increment = 2, name = "Rupture" }, -- Rank 4 + [11274] = { base = 8, increment = 2, name = "Rupture" }, -- Rank 5 + [11275] = { base = 8, increment = 2, name = "Rupture" }, -- Rank 6 + + -- ROGUE: Kidney Shot - Rank 1: 1 sec base, Rank 2: 2 sec base, +1 sec per CP + [408] = { base = 1, increment = 1, name = "Kidney Shot" }, -- Rank 1 + [8643] = { base = 2, increment = 1, name = "Kidney Shot" }, -- Rank 2 + + -- DRUID: Rip - 12 sec base, +4 sec per additional combo point (Source: Vanilla WoW Wiki) + -- Note: Some sources say 10+2, but testing shows 12+4 is accurate for 1.12 + [1079] = { base = 12, increment = 4, name = "Rip" }, -- Rank 1 + [9492] = { base = 12, increment = 4, name = "Rip" }, -- Rank 2 + [9493] = { base = 12, increment = 4, name = "Rip" }, -- Rank 3 + [9752] = { base = 12, increment = 4, name = "Rip" }, -- Rank 4 + [9894] = { base = 12, increment = 4, name = "Rip" }, -- Rank 5 + [9896] = { base = 12, increment = 4, name = "Rip" }, -- Rank 6 +} + +-- Legacy name-based table for backwards compatibility CleveRoids.ComboScalingSpells = { - -- Rupture (all ranks): 8 sec base, +2 sec per additional combo point - ["Rupture"] = { - base_duration = 8, - increment = 2, - all_ranks = true - }, - - -- Kidney Shot Rank 1: 1 sec base, +1 sec per additional combo point - ["Kidney Shot(Rank 1)"] = { - base_duration = 1, - increment = 1 - }, - - -- Kidney Shot Rank 2: 2 sec base, +1 sec per additional combo point - ["Kidney Shot(Rank 2)"] = { - base_duration = 2, - increment = 1 - }, - - -- Kidney Shot (generic for all ranks if rank not specified) - ["Kidney Shot"] = { - base_duration = 1, -- Default to rank 1 if rank unknown - increment = 1, - check_rank = true - }, - - -- Rip (all ranks): 10 sec base, +2 sec per additional combo point - ["Rip"] = { - base_duration = 10, - increment = 2, - all_ranks = true - } + ["Rupture"] = { base_duration = 8, increment = 2, all_ranks = true }, + ["Kidney Shot(Rank 1)"] = { base_duration = 1, increment = 1 }, + ["Kidney Shot(Rank 2)"] = { base_duration = 2, increment = 1 }, + ["Kidney Shot"] = { base_duration = 1, increment = 1, check_rank = true }, + ["Rip"] = { base_duration = 12, increment = 4, all_ranks = true } } -- Function to get current combo points @@ -118,23 +116,45 @@ end function CleveRoids.CalculateComboScaledDuration(spellName, comboPoints) local data = CleveRoids.GetComboScalingData(spellName) if not data then return nil end - + comboPoints = comboPoints or CleveRoids.GetComboPoints() if comboPoints < 1 then comboPoints = 1 end -- Minimum 1 combo point if comboPoints > 5 then comboPoints = 5 end -- Maximum 5 combo points - + return data.base_duration + (comboPoints - 1) * data.increment end --- Function to track combo points when casting +-- NEW: Check if spell ID is a combo scaling spell +function CleveRoids.IsComboScalingSpellID(spellID) + return CleveRoids.ComboScalingSpellsByID[spellID] ~= nil +end + +-- NEW: Get combo scaling data by spell ID +function CleveRoids.GetComboScalingDataByID(spellID) + return CleveRoids.ComboScalingSpellsByID[spellID] +end + +-- NEW: Calculate duration by spell ID and combo points +function CleveRoids.CalculateComboScaledDurationByID(spellID, comboPoints) + local data = CleveRoids.GetComboScalingDataByID(spellID) + if not data then return nil end + + comboPoints = comboPoints or CleveRoids.GetComboPoints() + if comboPoints < 1 then comboPoints = 1 end -- Minimum 1 combo point + if comboPoints > 5 then comboPoints = 5 end -- Maximum 5 combo points + + return data.base + (comboPoints - 1) * data.increment +end + +-- Function to track combo points when casting (by spell name) function CleveRoids.TrackComboPointCast(spellName) if not CleveRoids.IsComboScalingSpell(spellName) then return end - + local comboPoints = CleveRoids.GetComboPoints() local duration = CleveRoids.CalculateComboScaledDuration(spellName, comboPoints) - + -- Store the tracking data CleveRoids.ComboPointTracking[spellName] = { combo_points = comboPoints, @@ -142,23 +162,60 @@ function CleveRoids.TrackComboPointCast(spellName) cast_time = GetTime(), target = UnitName("target") or "Unknown" } - + -- Also store in spell_tracking for integration with existing system if not CleveRoids.spell_tracking[spellName] then CleveRoids.spell_tracking[spellName] = {} end - + CleveRoids.spell_tracking[spellName].last_combo_points = comboPoints CleveRoids.spell_tracking[spellName].last_duration = duration CleveRoids.spell_tracking[spellName].last_cast_time = GetTime() - - -- Debug output (remove in production) - if CleveRoids.Debug then - CleveRoids.Print(string.format("ComboTrack: %s cast with %d combo points, duration: %d seconds", - spellName, comboPoints, duration)) + + -- Debug output + if CleveRoids.debug then + DEFAULT_CHAT_FRAME:AddMessage( + string.format("|cff4b7dccCleveRoids:|r ComboTrack: %s cast with %d CP, duration: %d seconds", + spellName, comboPoints, duration) + ) end end +-- NEW: Track combo points by spell ID (for UNIT_CASTEVENT integration) +function CleveRoids.TrackComboPointCastByID(spellID, targetGUID) + if not CleveRoids.IsComboScalingSpellID(spellID) then + return nil + end + + local comboPoints = CleveRoids.GetComboPoints() + local duration = CleveRoids.CalculateComboScaledDurationByID(spellID, comboPoints) + + if not duration then return nil end + + -- Store tracking data by spell ID + if not CleveRoids.ComboPointTracking.byID then + CleveRoids.ComboPointTracking.byID = {} + end + + CleveRoids.ComboPointTracking.byID[spellID] = { + combo_points = comboPoints, + duration = duration, + cast_time = GetTime(), + target_guid = targetGUID + } + + -- Debug output + if CleveRoids.debug then + local data = CleveRoids.ComboScalingSpellsByID[spellID] + DEFAULT_CHAT_FRAME:AddMessage( + string.format("|cff4b7dccCleveRoids:|r ComboTrack: %s (ID:%d) cast with %d CP, duration: %d seconds", + data.name, spellID, comboPoints, duration) + ) + end + + return duration +end + -- Hook into the existing DoCast function local Extension = CleveRoids.RegisterExtension("ComboPointTracker") diff --git a/Core.lua b/Core.lua index 110d35a..01259ca 100644 --- a/Core.lua +++ b/Core.lua @@ -3268,6 +3268,28 @@ SlashCmdList["CLEVEROID"] = function(msg) return end + -- combotrack (show combo point tracking info) + if cmd == "combotrack" or cmd == "combo" then + if CleveRoids.ShowComboTracking then + CleveRoids.ShowComboTracking() + else + CleveRoids.Print("Combo point tracking not available") + end + return + end + + -- comboclear (clear combo tracking data) + if cmd == "comboclear" then + if CleveRoids.ComboPointTracking then + CleveRoids.ComboPointTracking = {} + CleveRoids.ComboPointTracking.byID = {} + CleveRoids.Print("Combo point tracking data cleared") + else + CleveRoids.Print("Combo point tracking not available") + end + return + end + -- Unknown command fallback CleveRoids.Print("Usage:") DEFAULT_CHAT_FRAME:AddMessage("/cleveroid - Show current settings") @@ -3283,6 +3305,9 @@ SlashCmdList["CLEVEROID"] = function(msg) DEFAULT_CHAT_FRAME:AddMessage('/cleveroid addimmune "" [buff] - Add immunity') DEFAULT_CHAT_FRAME:AddMessage('/cleveroid removeimmune "" - Remove immunity') DEFAULT_CHAT_FRAME:AddMessage('/cleveroid clearimmune [school] - Clear immunity data') + 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') end SLASH_CLEAREQUIPQUEUE1 = "/clearequipqueue" diff --git a/README.md b/README.md index 7540f2d..748a7ca 100644 --- a/README.md +++ b/README.md @@ -31,10 +31,13 @@ Check slash command and all conditional lists for new usages! * `/cleveroid refresh X` - Set refresh rate (1 to 10 updates per second. Default: 5) * `/cleveroid learn ` - Manually set spell duration in seconds * `/cleveroid forget ` - Forget learned spell duration(s) -* `/cleveroid listimmune [school]` - List all or specific school immunities -* `/cleveroid addimmune "" [buff]` - Add manual immunity +* `/cleveroid debug [0|1]` - Toggle learning debug messages +* `/cleveroid listimmune [school]` - List all or specific school immunities +* `/cleveroid addimmune "" [buff]` - Add manual immunity * `/cleveroid removeimmune "" ` - Remove immunity -* `/cleveroid clearimmune [school]` - Clear data +* `/cleveroid clearimmune [school]` - Clear immunity data +* `/cleveroid combotrack` - Show combo point tracking info (Rip, Rupture, Kidney Shot) +* `/cleveroid comboclear` - Clear combo tracking data --- @@ -171,6 +174,25 @@ The system includes pre-configured durations for 329+ debuffs across all classes - **Paladin:** Judgements, Hammer of Justice, etc. - **Shaman:** Flame Shock, Frost Shock, etc. +### Combo Point Scaling +The addon automatically tracks combo point finishers that scale duration with combo points: +- **Rogue Rupture** (all ranks): 8s base + 2s per combo point (8s @ 1 CP, 16s @ 5 CP) +- **Rogue Kidney Shot**: Rank 1: 1s + 1s per CP, Rank 2: 2s + 1s per CP +- **Druid Rip** (all ranks): 12s base + 4s per combo point (12s @ 1 CP, 28s @ 5 CP) + +The system automatically detects combo points at cast time and calculates the correct duration: +```lua +-- Will show accurate duration based on combo points used +/cast [nodebuff:Rip] Rip +/cast [debuff:Rip<4] Rip + +-- Rupture duration tracking with combo point awareness +/cast [nodebuff:Rupture] Rupture +/cast [debuff:Rupture<2] Rupture +``` + +Use `/cleveroid combotrack` to see recent combo finisher casts and their calculated durations. + ### Technical Details - Uses **UNIT_CASTEVENT** for precise cast detection (only tracks successful hits) - Uses **RAW_COMBATLOG** to detect when debuffs fade diff --git a/Utility.lua b/Utility.lua index 98042ea..795b83a 100644 --- a/Utility.lua +++ b/Utility.lua @@ -836,9 +836,18 @@ ev:SetScript("OnEvent", function() local _, playerGUID = UnitExists("player") if casterGUID == playerGUID and targetGUID then - local duration = lib:GetDuration(spellID, casterGUID) + -- Check if this is a combo point scaling spell first + local duration = nil + if CleveRoids.TrackComboPointCastByID then + duration = CleveRoids.TrackComboPointCastByID(spellID, targetGUID) + end - if duration > 0 then + -- If not a combo scaling spell, use normal duration lookup + if not duration then + duration = lib:GetDuration(spellID, casterGUID) + end + + if duration and duration > 0 then local targetName = lib.guidToName[targetGUID] if not targetName then local _, currentTargetGUID = UnitExists("target") @@ -905,14 +914,28 @@ evLearn:SetScript("OnEvent", function() local casterGUID = lib.learnCastTimers[targetGUID][spellID].caster local actualDuration = timestamp - castTime - CleveRoids_LearnedDurations[spellID] = CleveRoids_LearnedDurations[spellID] or {} - CleveRoids_LearnedDurations[spellID][casterGUID] = floor(actualDuration + 0.5) + -- 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 + 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" + ) + end + else + CleveRoids_LearnedDurations[spellID] = CleveRoids_LearnedDurations[spellID] or {} + CleveRoids_LearnedDurations[spellID][casterGUID] = floor(actualDuration + 0.5) - if CleveRoids.debug then - DEFAULT_CHAT_FRAME:AddMessage( - "|cff4b7dccCleveRoids:|r Learned " .. spellName .. - " (ID:" .. spellID .. ") = " .. floor(actualDuration + 0.5) .. "s" - ) + if CleveRoids.debug then + DEFAULT_CHAT_FRAME:AddMessage( + "|cff4b7dccCleveRoids:|r Learned " .. spellName .. + " (ID:" .. spellID .. ") = " .. floor(actualDuration + 0.5) .. "s" + ) + end end lib.learnCastTimers[targetGUID][spellID] = nil