Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CMFunctions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,7 @@ function CombatMetronome:AutomaticSVCleanup()
CombatMetronome.debug:Print("No SV cleanup necessary. Last SV cleanup has taken place less than a year ago on "..CombatMetronome.SV.lastSVCleanup.lastCleanup.day.."-"..CombatMetronome.SV.lastSVCleanup.lastCleanup.month.."-"..CombatMetronome.SV.lastSVCleanup.lastCleanup.year)
elseif CombatMetronome.SV.automaticSVCleanup.lastCleanup.year == 0 then
CombatMetronome.debug:Print("No SV cleanup has taken place yet. Starting automatic cleanup.")
self:CleanupSVEnstries()
self:CleanupSVEntries()
elseif year > CombatMetronome.SV.automaticSVCleanup.lastCleanup.year and month >= CombatMetronome.SV.lastSVCleanup.lastCleanup.month then
CombatMetronome.SV.lastSVCleanup = {["year"] = year, ["month"] = month, ["day"] = day}
CombatMetronome.debug:Print("Last SV cleanup was about a year ago. Starting automatic cleanup.")
Expand Down
2 changes: 1 addition & 1 deletion CMProgressbar.lua
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ function CombatMetronome:Update()
cdTimer = time - start
end

local duration = math.max(ability.heavy and 0 or (self.gcd or 1000), ability.delay) + (self.currentEvent.adjust or 0)
local duration = math.max(ability.heavy and self.SV.Progressbar.stopHATracking and 0 or (self.gcd or 1000), ability.delay) + (self.currentEvent.adjust or 0)
-- local timeRemaining = ((start + duration + latency) - time) / 1000 or ((start + channelTime + latency) - time) < 0 and 0
local timeRemaining = (duration - cdTimer) / 1000
local castProgress = 1 - (cdTimer/duration)
Expand Down
2 changes: 1 addition & 1 deletion CMResources.lua
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ function CombatMetronome:UpdateLabels()
else
self.Resources.hpLabel:SetHidden(true)
end
if not CombatMetronome.SV.Resources.unlockExecuteReminder then
if not CombatMetronome.SV.Resources.unlockExecuteReminder and CombatMetronome.Resources.executeThreshold then
if not IsUnitDead("reticleover") and showResources and CombatMetronome.SV.Resources.showExecuteReminder and hp~=1 and 100 * (hp / maxHp) <= CombatMetronome.Resources.executeThreshold and CombatMetronome.Resources.executeThreshold ~= 0 then
self.Resources.executeLabel:SetHidden(false)
else
Expand Down
2 changes: 1 addition & 1 deletion CMSettings.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1448,7 +1448,7 @@ function CombatMetronome:BuildMenu()
},
{
type = "slider",
name = "Modify skill adjust",
name = "Modify skill adjust (in ms)",
min = -MAX_ADJUST,
max = MAX_ADJUST,
step = 1,
Expand Down
5 changes: 5 additions & 0 deletions Changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
2025-07-02 v1.7.3
! Finally applied correct version, so it is now correctly shown in the settings menu
! Additional failsaves for not tracking all gcd
! Fixing minor spelling errors that caused bugs

2025-06-05 v1.7.2
! Bugfix for flame skull stacks
! Bugfix for channeled/cast abilities < 1 sec not releasing channel color correctly
Expand Down
6 changes: 3 additions & 3 deletions CombatMetronome.addon
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
## Title: |ce11212C|rombat |ce11212M|retronome
## Description: The All-in-one Combat Timing bar. Track your heavy swings, ability cooldowns and cast/channels all in one bar to help you perfect your rotation timing and take advantage of abilty queuing with live latency information.
## Author: Darianopolis, |c2a52beb|rarny
## Version: 1.7.2
## AddOnVersion: 010702
## Version: 1.7.3
## AddOnVersion: 010703
## APIVersion: 101046
## SavedVariables: CombatMetronomeSavedVars
## DependsOn: LibAddonMenu-2.0>=40 libAddonKeybinds>=5 DariansUtilities>=10801 LibChatMessage>=113 LibNotification>=15
## DependsOn: LibAddonMenu-2.0>=40 libAddonKeybinds>=5 DariansUtilities>=10802 LibChatMessage>=113 LibNotification>=15
## OptionalDependsOn: LibSetDetection>=4

; This Add-on is not created by, affiliated with or sponsored by ZeniMax
Expand Down
120 changes: 64 additions & 56 deletions CombatMetronome.lua
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ CombatMetronome = {
version = {
["patch"] = 1,
["major"] = 7,
["minor"] = 0,
["minor"] = 3,
},
API = GetAPIVersion(),
beta = beta,
Expand Down Expand Up @@ -317,19 +317,19 @@ function CombatMetronome:RegisterCM()

self.cmRegistered = true

if CombatMetronome.SV.Progressbar.trackCollectibles or (CombatMetronome.SV.Progressbar.showMountNick and CombatMetronome.SV.Progressbar.trackMounting) then
if CombatMetronome.SV.Progressbar.trackGCD and (CombatMetronome.SV.Progressbar.trackCollectibles or (CombatMetronome.SV.Progressbar.showMountNick and CombatMetronome.SV.Progressbar.trackMounting)) then
CombatMetronome:RegisterCollectiblesTracker()
end

if CombatMetronome.SV.Progressbar.trackItems then
if CombatMetronome.SV.Progressbar.trackGCD and CombatMetronome.SV.Progressbar.trackItems then
CombatMetronome:RegisterItemsTracker()
end

if CombatMetronome:CheckForCombatEventsRegister() then
if CombatMetronome.SV.Progressbar.trackGCD and CombatMetronome:CheckForCombatEventsRegister() then
CombatMetronome:RegisterCombatEvents()
end

if CombatMetronome.SV.Progressbar.trackSynergies then
if CombatMetronome.SV.Progressbar.trackGCD and CombatMetronome.SV.Progressbar.trackSynergies then
CombatMetronome:RegisterSynergyChanged()
end
-- if CombatMetronome.SV.debug.enabled then CombatMetronome.debug:Print("cm is registered") end
Expand All @@ -340,22 +340,24 @@ function CombatMetronome:RegisterCollectiblesTracker()
self.name.."CollectibleUsed",
EVENT_COLLECTIBLE_UPDATED,
function(_, id)
local name,_,icon,_,_,_,_,type,_ = GetCollectibleInfo(id)
if type == COLLECTIBLE_CATEGORY_TYPE_ASSISTANT or type == COLLECTIBLE_CATEGORY_TYPE_COMPANION then
CombatMetronome:SetIconsAndNamesNil()
self.Progressbar.collectibleInUse = {}
self.Progressbar.collectibleInUse.name = Util.Text.CropZOSString(name, "collectible")
self.Progressbar.collectibleInUse.icon = icon
zo_callLater(function() self.Progressbar.collectibleInUse = nil end, 1000)
end
if type == COLLECTIBLE_CATEGORY_TYPE_MOUNT then
-- if id == GetActiveCollectibleByType(COLLECTIBLE_CATEGORY_TYPE_MOUNT,GAMEPLAY_ACTOR_CATEGORY_PLAYER) then
self.Progressbar.activeMount.name = Util.Text.CropZOSString(GetCollectibleNickname(id), "collectible")
self.Progressbar.activeMount.icon = icon
if CombatMetronome.menu.icons[2] then
CombatMetronome.menu.icons[2]:SetTexture(icon)
end
-- end
if CombatMetronome.SV.Progressbar.trackGCD then
local name,_,icon,_,_,_,_,type,_ = GetCollectibleInfo(id)
if type == COLLECTIBLE_CATEGORY_TYPE_ASSISTANT or type == COLLECTIBLE_CATEGORY_TYPE_COMPANION then
CombatMetronome:SetIconsAndNamesNil()
self.Progressbar.collectibleInUse = {}
self.Progressbar.collectibleInUse.name = Util.Text.CropZOSString(name, "collectible")
self.Progressbar.collectibleInUse.icon = icon
zo_callLater(function() self.Progressbar.collectibleInUse = nil end, 1000)
end
if type == COLLECTIBLE_CATEGORY_TYPE_MOUNT then
-- if id == GetActiveCollectibleByType(COLLECTIBLE_CATEGORY_TYPE_MOUNT,GAMEPLAY_ACTOR_CATEGORY_PLAYER) then
self.Progressbar.activeMount.name = Util.Text.CropZOSString(GetCollectibleNickname(id), "collectible")
self.Progressbar.activeMount.icon = icon
if CombatMetronome.menu.icons[2] then
CombatMetronome.menu.icons[2]:SetTexture(icon)
end
-- end
end
end
end
)
Expand All @@ -368,39 +370,43 @@ function CombatMetronome:RegisterItemsTracker()
self.name.."InventoryItemUsed",
EVENT_INVENTORY_ITEM_USED,
function()
local bagSize = GetBagSize(1)
CombatMetronome:SetIconsAndNamesNil()
self.itemCache = {}
self.itemCache.name = {}
self.itemCache.icon = {}
for i = 1, bagSize do
self.itemCache.name[i] = Util.Text.CropZOSString(GetItemName(1, i), "item")
self.itemCache.icon[i] = GetItemInfo(1, i)
if CombatMetronome.SV.Progressbar.trackGCD then
local bagSize = GetBagSize(1)
CombatMetronome:SetIconsAndNamesNil()
self.itemCache = {}
self.itemCache.name = {}
self.itemCache.icon = {}
for i = 1, bagSize do
self.itemCache.name[i] = Util.Text.CropZOSString(GetItemName(1, i), "item")
self.itemCache.icon[i] = GetItemInfo(1, i)
end
-- zo_callLater(function()
-- self.itemCache = nil
-- end,
-- 400)
end
-- zo_callLater(function()
-- self.itemCache = nil
-- end,
-- 400)
end
)

EVENT_MANAGER:RegisterForEvent(
self.name.."InventoryItemInfo",
EVENT_INVENTORY_SINGLE_SLOT_UPDATE,
function(_, bagId, slotId, _, _, _, stackCountChange, _, _, _, _)
if not self.Progressbar.synergy.wasUsed and stackCountChange == -1 and self.itemCache then
CombatMetronome:SetIconsAndNamesNil()
self.Progressbar.itemUsed = {
["name"] = self.itemCache.name[slotId],
["icon"] = self.itemCache.icon[slotId]
}
zo_callLater(function()
if self.Progressbar.itemUsed then
self.Progressbar.itemUsed = nil
self.itemCache = nil
end
end,
950)
if CombatMetronome.SV.Progressbar.trackGCD then
if not self.Progressbar.synergy.wasUsed and stackCountChange == -1 and self.itemCache then
CombatMetronome:SetIconsAndNamesNil()
self.Progressbar.itemUsed = {
["name"] = self.itemCache.name[slotId],
["icon"] = self.itemCache.icon[slotId]
}
zo_callLater(function()
if self.Progressbar.itemUsed then
self.Progressbar.itemUsed = nil
self.itemCache = nil
end
end,
950)
end
end
end
)
Expand All @@ -417,7 +423,7 @@ function CombatMetronome:RegisterCombatEvents()
-- ------------------------------
function (_, res, err, aName, aGraphic, aSlotType, sName, sType, tName,
tType, hVal, pType, dType, _, sUId, tUId, aId, _ )
if Util.Text.CropZOSString(sName, "name") == self.currentCharacterName then
if Util.Text.CropZOSString(sName, "name") == self.currentCharacterName and CombatMetronome.SV.Progressbar.trackGCD then
if IsMounted() and aId == 36432 and self.Progressbar.activeMount.action ~= "Dismounting" then
CombatMetronome:SetIconsAndNamesNil()
self.Progressbar.activeMount.action = "Dismounting"
Expand Down Expand Up @@ -463,14 +469,16 @@ function CombatMetronome:RegisterSynergyChanged()
self.name.."SynergyChanged",
EVENT_SYNERGY_ABILITY_CHANGED,
function()
local hasSynergy, name, icon, _, _ = GetCurrentSynergyInfo()
if hasSynergy then
-- if CombatMetronome.SV.debug.enabled then self.debug:Print("Found synergy: "..Util.Text.CropZOSString(name, "synergy")) end
self.Progressbar.synergy.name = Util.Text.CropZOSString(name, "synergy")
self.Progressbar.synergy.icon = icon
-- else
-- self.Progressbar.synergy = nil
-- if CombatMetronome.SV.debug.enabled then self.debug:Print("Synergy deleted") end
if CombatMetronome.SV.Progressbar.trackGCD then
local hasSynergy, name, icon, _, _ = GetCurrentSynergyInfo()
if hasSynergy then
-- if CombatMetronome.SV.debug.enabled then self.debug:Print("Found synergy: "..Util.Text.CropZOSString(name, "synergy")) end
self.Progressbar.synergy.name = Util.Text.CropZOSString(name, "synergy")
self.Progressbar.synergy.icon = icon
-- else
-- self.Progressbar.synergy = nil
-- if CombatMetronome.SV.debug.enabled then self.debug:Print("Synergy deleted") end
end
end
end
)
Expand Down Expand Up @@ -721,7 +729,7 @@ end
function CombatMetronome:DevTools()

local ADDON_DEPENDENCY_VERSIONS = {
["libAddonKeybinds"] = -1, ["LibAddonMenu-2.0"] = -1, ["LibChatMessage"] = -1, ["LibSetDetection"] = -1, ["LibNotification"] = -1, ["LibGroupBroadcast"] = -1,
["libAddonKeybinds"] = -1, ["LibAddonMenu-2.0"] = -1, ["LibChatMessage"] = -1, ["LibSetDetection"] = -1, ["LibNotification"] = -1, ["LibGroupBroadcast"] = -1, ["LibAddonMenuOrderListBox"] = -1,
}

local function GetDependencyVersions()
Expand Down
4 changes: 4 additions & 0 deletions DariansUtilities/Changelog.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
2025-07-02 v1.8.2
+ Reenabling slot updated as ability trigger in an attempt to fix ability triggers
- Also reverting those changes right back.

2025-06-06 v1.8.1
! Bugfixes for stack tracking of GF and FS

Expand Down
4 changes: 2 additions & 2 deletions DariansUtilities/DariansUtilities.addon
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
## Title: DariansUtilities
## Description: Darian's Mod Library
## Author: Darianopolis, |c2a52beb|rarny
## Version: 1.8.1
## AddOnVersion: 10801
## Version: 1.8.2
## AddOnVersion: 10802
## APIVersion: 101046
## IsLibrary: true

Expand Down
53 changes: 47 additions & 6 deletions DariansUtilities/abilities/Ability.lua
Original file line number Diff line number Diff line change
Expand Up @@ -283,10 +283,10 @@ function Ability.Tracker:GCDCheck()
local cdInfo = {[1] = { ["sR"] = 0, ["sD"] = 0 }, [2] = { ["sR"] = 0, ["sD"] = 0 }}
for i = 3, 7 do
sR, sD, global, _ = GetSlotCooldownInfo(i)
if j == 3 then break end
if global then
cdInfo[j] = { ["sR"] = sR, ["sD"] = sD }
j = j+1
if j == 2 then break end
end
end

Expand Down Expand Up @@ -518,6 +518,8 @@ function Ability.Tracker:AbilityUsed(trigger)
return
end

-- local time = GetFrameTimeMilliseconds()

local gcdProgress, sR, sD
if self.queuedEvent and self.queuedEvent.ability.heavy then
sR, sD, _, _ = GetSlotCooldownInfo(2)
Expand All @@ -528,6 +530,8 @@ function Ability.Tracker:AbilityUsed(trigger)

if gcdProgress > 0.92 or (self.queuedEvent and self.queuedEvent.ability.heavy) then

-- if (self.queuedEvent and self.queuedEvent.ability.heavy) or self.abilityTrigger == time then

-- killing old self.currentEvent since new event is coming
if self.currentEvent then self:CancelCurrentEvent("Old event over, new event coming") end

Expand Down Expand Up @@ -558,6 +562,12 @@ function Ability.Tracker:AbilityUsed(trigger)
end

self.lastAbilityFinished = event.start + math.max(event.ability.delay, self.adjustedGCD)

if trigger == "Slot updated" or trigger == "CD updated" then
self.abilityTriggerCounters.normal = self.abilityTriggerCounters.normal + 1
end
-- else
-- self.abilityTrigger = time
end
end

Expand Down Expand Up @@ -598,6 +608,37 @@ function Ability.Tracker:CallbackAbilityCancelled(event)
-- end
end

function Ability.Tracker:HandleSlotUpdated(e, slot)
if (slot < 3) then return
elseif self.queuedEvent and self.queuedEvent.slot ~= slot then return
end

-- local remaining, duration, global, t = GetSlotCooldownInfo(slot)
local gcdProgress, sR, sD = self:GCDCheck()
local time = GetFrameTimeMilliseconds()

if (sD > 0 and sR > 0) then
self.gcd = sD

local oldStart = self.eventStart or 0
self.eventStart = time + sR - sD

-- if (oldStart ~= self.eventStart) then
-- _=self.log and d(""..time.." : Event start "..tostring(duration - remaining).."ms ago")
-- end

if self.queuedEvent and self.eventStart > oldStart then
-- _=self.log and d(""..time.." : Moved queued "..self.queuedEvent.ability.name.." to current")
-- log(" Dispatching ", self.queuedEvent.ability.name)
-- log(" oldStart = ", oldStart)
-- log(" newStart = ", self.eventStart)
-- log(" current = ", GetFrameTimeMilliseconds())
self:AbilityUsed("Slot updated")
-- self.abilityTriggerCounters.normal = self.abilityTriggerCounters.normal + 1
end
end
end

function Ability.Tracker:HandleCooldownsUpdated()
self.cdTriggerTime = GetFrameTimeMilliseconds()

Expand All @@ -619,8 +660,8 @@ function Ability.Tracker:HandleCooldownsUpdated()
self.eventStart = self.cdTriggerTime + sR - sD
if self.eventStart + (CombatMetronome.SV.debug.triggers and CombatMetronome.SV.debug.triggerTimer or 170) >= self.cdTriggerTime then
-- CombatMetronome.debug:Print("Firing "..self.queuedEvent.ability.name)
self:AbilityUsed("normal")
self.abilityTriggerCounters.normal = self.abilityTriggerCounters.normal + 1
self:AbilityUsed("CD updated")
-- self.abilityTriggerCounters.normal = self.abilityTriggerCounters.normal + 1
end
end
end
Expand Down Expand Up @@ -812,13 +853,13 @@ function Ability.Tracker:HandleCombatEvent(_, res, err, aName, _, aSlotTy
return
end
-- local lightId = GetSlotBoundId(1)
if aSlotType == ACTION_SLOT_TYPE_LIGHT_ATTACK --[[and res == 2240 and time ~= self.lastLightAttack ]]then
if res == ACTION_RESULT_EFFECT_GAINED and time ~= self.lastLightAttack then
if aSlotType == ACTION_SLOT_TYPE_LIGHT_ATTACK or aSlotType == ACTION_SLOT_TYPE_WEAPON_ATTACK--[[and res == 2240 and time ~= self.lastLightAttack ]]then
if (res == ACTION_RESULT_EFFECT_GAINED or res == ACTION_RESULT_CRITICAL_DAMAGE or res == ACTION_RESULT_DAMAGE) and time ~= self.lastLightAttack then
Ability.Tracker:CallbackLightAttackUsed(time)
self.lastLightAttack = time
end
--CombatMetronome.debug:Print(res.." - "..hVal.." - "..overflow)
end
self.lastLightAttack = time
else
return
end
Expand Down