From 7fdf76eff8d44975076010d3c6ec2bab5bb58c12 Mon Sep 17 00:00:00 2001 From: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com> Date: Thu, 5 Nov 2026 17:37:46 +0100 Subject: [PATCH] fix: HoT timer tracking premature deletion of auta_Cast_ON even fixed guid cache fixed .show() call on overlay visible --- HealBot_Controller_Aura.lua | 22 ++++----- HealBot_Controller_Events.lua | 3 ++ HealBot_Integrations.lua | 89 +++++++++++++++++++++++++---------- HealBot_Model.lua | 43 +++++++++++++++++ HealBot_View_Layout.lua | 79 ++++++++++++++++++++++++++----- 5 files changed, 185 insertions(+), 51 deletions(-) diff --git a/HealBot_Controller_Aura.lua b/HealBot_Controller_Aura.lua index 3283920..e9cffe6 100644 --- a/HealBot_Controller_Aura.lua +++ b/HealBot_Controller_Aura.lua @@ -339,19 +339,15 @@ function HealBot_OnEvent_UnitAura(this, unit) local guid = HealBot_GetUnitGUID and HealBot_GetUnitGUID(unit) if guid then if not HealBot_Nampower_NameCache then HealBot_Nampower_NameCache = HealBot_GetTable() end - HealBot_Nampower_NameCache[guid] = UnitName(unit) - - if HealBot_Nampower_Auras[guid] then - for spellName, _ in pairs(HealBot_Nampower_Auras[guid]) do - local auraInfo = HealBot_TrackedAura_Spells and HealBot_TrackedAura_Spells[spellName] - if auraInfo then - local tex = auraInfo.texture - local isActive = auraInfo.isDebuff and activeDebuffs[tex] or activeBuffs[tex] - if not isActive then - HealBot_Nampower_Auras[guid][spellName] = nil - end - end - end + local uName = UnitName(unit) + if uName then + HealBot_Nampower_NameCache[guid] = uName + HealBot_Nampower_NameCache[string.lower(guid)] = uName + end + if HealBot_Model and HealBot_Model.guidUnits then + HealBot_Model.guidUnits[guid] = unit + HealBot_Model.guidUnits[string.lower(guid)] = unit + HealBot_Model.unitGUIDs[unit] = guid end end end diff --git a/HealBot_Controller_Events.lua b/HealBot_Controller_Events.lua index 4f7300f..c132ebb 100644 --- a/HealBot_Controller_Events.lua +++ b/HealBot_Controller_Events.lua @@ -333,6 +333,9 @@ local HealBot_EventHandlers = { ["PLAYER_ENTERING_WORLD"] = function(this) HealBot_Model:RefreshUnit("player") HealBot_Model:RefreshUnit("pet") + if HealBot_Model and HealBot_Model.PopulateAllGUIDs then + HealBot_Model:PopulateAllGUIDs() + end HealBot_OnEvent_PlayerEnteringWorld(this) end, ["VARIABLES_LOADED"] = function(this) diff --git a/HealBot_Integrations.lua b/HealBot_Integrations.lua index a8ad1a0..da673ec 100644 --- a/HealBot_Integrations.lua +++ b/HealBot_Integrations.lua @@ -62,31 +62,62 @@ function HealBot_Integrations_Toggle() HealBot_Nampower_Auras[target][spellName] = expirationTime if not HealBot_Nampower_NameCache then HealBot_Nampower_NameCache = HealBot_GetTable() end - if event == "AURA_CAST_ON_SELF" then - HealBot_Nampower_NameCache[target] = UnitName("player") - HealBot_OnEvent_UnitAura(nil, "player") + local unitID = nil + local tName = nil + + if event == "AURA_CAST_ON_SELF" or (HealBot_PlayerGUID and (target == HealBot_PlayerGUID or string.lower(target) == string.lower(HealBot_PlayerGUID))) then + unitID = "player" + tName = UnitName("player") + if not HealBot_PlayerGUID then + HealBot_PlayerGUID = target + end else - local tName = nil + unitID = HealBot_Model and (HealBot_Model:GetUnitByGUID(target) or HealBot_Model:GetUnitByGUID(string.lower(target))) + if not unitID and HealBot_PlayerGUID and (target == HealBot_PlayerGUID or string.lower(target) == string.lower(HealBot_PlayerGUID)) then + unitID = "player" + end + if UnitExists("target") then local curTargetGuid = HealBot_GetUnitGUID and HealBot_GetUnitGUID("target") if curTargetGuid and (curTargetGuid == target or string.lower(curTargetGuid) == string.lower(target)) then tName = UnitName("target") + if not unitID and UnitIsUnit("target", "player") then unitID = "player" end end end - local unitID = HealBot_Model and HealBot_Model:GetUnitByGUID(target) - if not unitID and HealBot_PlayerGUID and (target == HealBot_PlayerGUID or string.lower(target) == string.lower(HealBot_PlayerGUID)) then - unitID = "player" + if not tName and UnitExists("mouseover") then + local curMOGuid = HealBot_GetUnitGUID and HealBot_GetUnitGUID("mouseover") + if curMOGuid and (curMOGuid == target or string.lower(curMOGuid) == string.lower(target)) then + tName = UnitName("mouseover") + if not unitID and UnitIsUnit("mouseover", "player") then unitID = "player" end + end end if not tName and unitID then tName = UnitName(unitID) or (HealBot_Model and HealBot_Model.units[unitID] and HealBot_Model.units[unitID].name) end - if tName then - HealBot_Nampower_NameCache[target] = tName + end + + if tName then + HealBot_Nampower_NameCache[target] = tName + HealBot_Nampower_NameCache[string.lower(target)] = tName + end + if unitID and HealBot_Model then + if HealBot_Model.guidUnits then + HealBot_Model.guidUnits[target] = unitID + HealBot_Model.guidUnits[string.lower(target)] = unitID end - if unitID then - HealBot_OnEvent_UnitAura(nil, unitID) + if HealBot_Model.unitGUIDs then + HealBot_Model.unitGUIDs[unitID] = target end end + + if unitID and HealBot_View_DirtyUnits then + HealBot_View_DirtyUnits[unitID] = true + end + if HealBot_UpdateActiveHoTTimers then + HealBot_UpdateActiveHoTTimers() + elseif HealBot_Action_UpdatePlayerHoTs then + HealBot_Action_UpdatePlayerHoTs() + end end end) end @@ -157,23 +188,29 @@ function HealBot_Integrations_PruneNampower() local currentTime = GetTime() for targetName, auras in pairs(HealBot_Nampower_Auras) do - -- Check if target is still in the raid/party, or is the player - local isPlayer = (HealBot_PlayerGUID and string.lower(targetName) == string.lower(HealBot_PlayerGUID)) - or (UnitName("player") and string.lower(targetName) == string.lower(UnitName("player"))) - if not isPlayer and not HealBot_Model:GetUnitByGUID(targetName) and not HealBot_Model:GetUnitIDByName(targetName) then + local lowerName = string.lower(targetName) + local isPlayer = (HealBot_PlayerGUID and lowerName == string.lower(HealBot_PlayerGUID)) + or (UnitName("player") and lowerName == string.lower(UnitName("player"))) + or (HealBot_GetUnitGUID and (targetName == HealBot_GetUnitGUID("player") or lowerName == string.lower(HealBot_GetUnitGUID("player") or ""))) + + -- Prune expired auras + local hasAuras = false + for spellName, expiration in pairs(auras) do + if currentTime > expiration then + auras[spellName] = nil + else + hasAuras = true + end + end + + if not hasAuras then HealBot_ReleaseTable(auras) HealBot_Nampower_Auras[targetName] = nil - else - -- Prune expired auras - local hasAuras = false - for spellName, expiration in pairs(auras) do - if currentTime > expiration then - auras[spellName] = nil - else - hasAuras = true - end - end - if not hasAuras then + elseif not isPlayer and not (HealBot_Model and (HealBot_Model:GetUnitByGUID(targetName) or HealBot_Model:GetUnitByGUID(lowerName))) and not (HealBot_Model and HealBot_Model:GetUnitIDByName(targetName)) then + -- Target left group or disconnected and is not player + if GetNumPartyMembers() == 0 and GetNumRaidMembers() == 0 then + -- Solo: keep non-player auras until expired + else HealBot_ReleaseTable(auras) HealBot_Nampower_Auras[targetName] = nil end diff --git a/HealBot_Model.lua b/HealBot_Model.lua index 4b025f8..bb15b2b 100644 --- a/HealBot_Model.lua +++ b/HealBot_Model.lua @@ -206,27 +206,49 @@ end -- HealBot_Model:PopulateAllGUIDs: Refreshes unit-to-GUID and GUID-to-unit mappings for all current roster units. function HealBot_Model:PopulateAllGUIDs() if not (HealBot_Integrations_SuperWoW_Active or HealBot_Integrations_ClassicAPI_Active or HealBot_Integrations_Nampower_Active) or not HealBot_GetUnitGUID then return end + if not HealBot_Nampower_NameCache then HealBot_Nampower_NameCache = HealBot_GetTable() end local playerGuid = HealBot_GetUnitGUID("player") if playerGuid and playerGuid ~= "0" and playerGuid ~= "0x0000000000000000" then + local lowerPGuid = string.lower(playerGuid) self.unitGUIDs["player"] = playerGuid self.guidUnits[playerGuid] = "player" + self.guidUnits[lowerPGuid] = "player" HealBot_PlayerGUID = playerGuid + local pName = UnitName("player") + if pName then + HealBot_Nampower_NameCache[playerGuid] = pName + HealBot_Nampower_NameCache[lowerPGuid] = pName + end end for _, unit in ipairs(self.partyMembers) do local guid = HealBot_GetUnitGUID(unit) if guid and guid ~= "0" and guid ~= "0x0000000000000000" then + local lowerGuid = string.lower(guid) self.unitGUIDs[unit] = guid self.guidUnits[guid] = unit + self.guidUnits[lowerGuid] = unit + local uName = UnitName(unit) + if uName then + HealBot_Nampower_NameCache[guid] = uName + HealBot_Nampower_NameCache[lowerGuid] = uName + end end end for _, unit in ipairs(self.raidMembers) do local guid = HealBot_GetUnitGUID(unit) if guid and guid ~= "0" and guid ~= "0x0000000000000000" then + local lowerGuid = string.lower(guid) self.unitGUIDs[unit] = guid self.guidUnits[guid] = unit + self.guidUnits[lowerGuid] = unit + local uName = UnitName(unit) + if uName then + HealBot_Nampower_NameCache[guid] = uName + HealBot_Nampower_NameCache[lowerGuid] = uName + end end end end @@ -238,14 +260,19 @@ function HealBot_Model:GetUnitByGUID(guid) if unit and UnitExists(unit) then return unit end local lowerGuid = string.lower(guid) + unit = self.guidUnits[lowerGuid] + if unit and UnitExists(unit) then return unit end + if HealBot_PlayerGUID and string.lower(HealBot_PlayerGUID) == lowerGuid then self.guidUnits[guid] = "player" + self.guidUnits[lowerGuid] = "player" return "player" end if HealBot_GetUnitGUID then local pGuid = HealBot_GetUnitGUID("player") if pGuid and string.lower(pGuid) == lowerGuid then self.guidUnits[guid] = "player" + self.guidUnits[lowerGuid] = "player" HealBot_PlayerGUID = pGuid return "player" end @@ -255,6 +282,8 @@ function HealBot_Model:GetUnitByGUID(guid) local uGuid = HealBot_GetUnitGUID(u) if uGuid and string.lower(uGuid) == lowerGuid then self.guidUnits[guid] = u + self.guidUnits[lowerGuid] = u + self.unitGUIDs[u] = guid return u end end @@ -265,10 +294,24 @@ function HealBot_Model:GetUnitByGUID(guid) local uGuid = HealBot_GetUnitGUID(u) if uGuid and string.lower(uGuid) == lowerGuid then self.guidUnits[guid] = u + self.guidUnits[lowerGuid] = u + self.unitGUIDs[u] = guid return u end end end + if UnitExists("target") then + local tGuid = HealBot_GetUnitGUID("target") + if tGuid and string.lower(tGuid) == lowerGuid then + return "target" + end + end + if UnitExists("mouseover") then + local moGuid = HealBot_GetUnitGUID("mouseover") + if moGuid and string.lower(moGuid) == lowerGuid then + return "mouseover" + end + end end return nil end diff --git a/HealBot_View_Layout.lua b/HealBot_View_Layout.lua index 29e0bc1..6b57464 100644 --- a/HealBot_View_Layout.lua +++ b/HealBot_View_Layout.lua @@ -335,13 +335,18 @@ function HealBot_Action_EnableButton(button) iconText:SetTextColor(1, 1, 1, 1) bar["iconText"..i] = iconText end - local timeLeft = unitMap and (unitMap[newTexture] or (newTexture and unitMap[string.lower(newTexture)])) + local cleanTex = newTexture and string.lower(string.gsub(newTexture, "/", "\\")) + local shortTex = cleanTex and string.match(cleanTex, "([^\\]+)$") + local timeLeft = unitMap and (unitMap[newTexture] or (cleanTex and unitMap[cleanTex]) or (shortTex and unitMap[shortTex])) if timeLeft then + if bar.overlayFrame then bar.overlayFrame:Show() end iconText:SetText(timeLeft) iconText:Show() else - iconText:SetText("") - iconText:Hide() + if iconText and iconText:IsVisible() then + iconText:SetText("") + iconText:Hide() + end end elseif iconText and iconText:IsVisible() then iconText:SetText("") @@ -1493,7 +1498,9 @@ function HealBot_RenderHoTOverlays() local iconText = bar["iconText"..i] if icon and icon:IsVisible() then local tex = icon:GetTexture() - local timeLeft = unitMap and (unitMap[tex] or (tex and unitMap[string.lower(tex)])) + local cleanTex = tex and string.lower(string.gsub(tex, "/", "\\")) + local shortTex = cleanTex and string.match(cleanTex, "([^\\]+)$") + local timeLeft = unitMap and (unitMap[tex] or (cleanTex and unitMap[cleanTex]) or (shortTex and unitMap[shortTex])) if timeLeft then if not iconText then local overlayFrame = bar.overlayFrame @@ -1509,6 +1516,7 @@ function HealBot_RenderHoTOverlays() iconText:SetTextColor(1, 1, 1, 1) bar["iconText"..i] = iconText end + if bar.overlayFrame then bar.overlayFrame:Show() end iconText:SetText(timeLeft) iconText:Show() else @@ -1603,13 +1611,23 @@ function HealBot_UpdateActiveHoTTimers() if HealBot_Integrations_Nampower_Active and HealBot_Nampower_Auras then for targetKey, auras in pairs(HealBot_Nampower_Auras) do - local unitID = HealBot_Model and HealBot_Model:GetUnitByGUID(targetKey) - if not unitID and HealBot_PlayerGUID and (targetKey == HealBot_PlayerGUID or string.lower(targetKey) == string.lower(HealBot_PlayerGUID)) then - unitID = "player" + local lowerKey = string.lower(targetKey) + local unitID = HealBot_Model and (HealBot_Model:GetUnitByGUID(targetKey) or HealBot_Model:GetUnitByGUID(lowerKey)) + + if not unitID then + local isPlayer = (HealBot_PlayerGUID and (targetKey == HealBot_PlayerGUID or lowerKey == string.lower(HealBot_PlayerGUID))) + or (UnitName("player") and (targetKey == UnitName("player") or lowerKey == string.lower(UnitName("player")))) + or (HealBot_GetUnitGUID and (targetKey == HealBot_GetUnitGUID("player") or lowerKey == string.lower(HealBot_GetUnitGUID("player") or ""))) + if isPlayer then + unitID = "player" + end end - if not unitID and UnitName("player") and (targetKey == UnitName("player") or string.lower(targetKey) == string.lower(UnitName("player"))) then - unitID = "player" + + if not unitID and HealBot_Model and HealBot_Model.GetUnitIDByName then + unitID = HealBot_Model:GetUnitIDByName(targetKey) end + + -- Multi-tier player name resolution local displayName = nil if unitID and unitID ~= "target" then if HealBot_Model and HealBot_Model.units[unitID] and HealBot_Model.units[unitID].name then @@ -1620,16 +1638,32 @@ function HealBot_UpdateActiveHoTTimers() end end if not displayName and HealBot_Nampower_NameCache then - displayName = HealBot_Nampower_NameCache[targetKey] + displayName = HealBot_Nampower_NameCache[targetKey] or HealBot_Nampower_NameCache[lowerKey] + end + if not displayName and UnitExists("target") and HealBot_GetUnitGUID and (targetKey == HealBot_GetUnitGUID("target") or lowerKey == string.lower(HealBot_GetUnitGUID("target") or "")) then + displayName = UnitName("target") + end + if not displayName and UnitExists("mouseover") and HealBot_GetUnitGUID and (targetKey == HealBot_GetUnitGUID("mouseover") or lowerKey == string.lower(HealBot_GetUnitGUID("mouseover") or "")) then + displayName = UnitName("mouseover") + end + if not displayName then + local uName = UnitName(targetKey) + if uName and uName ~= targetKey and uName ~= "Unknown" then + displayName = uName + end end if displayName and HealBot_Nampower_NameCache then HealBot_Nampower_NameCache[targetKey] = displayName + HealBot_Nampower_NameCache[lowerKey] = displayName end -- Exclude pets if not (unitID and string.find(unitID, "pet")) then for spellName, expiration in pairs(auras) do local auraInfo = HealBot_TrackedAura_Spells and HealBot_TrackedAura_Spells[spellName] + if not auraInfo and HealBot_TrackedAuras and HealBot_TrackedAuras[spellName] then + auraInfo = HealBot_TrackedAuras[spellName] + end if auraInfo and auraInfo.showTimer and expiration > currentTime then local timeLeft = math.floor(expiration - currentTime) local tex = auraInfo.texture or "Interface\\Icons\\INV_Misc_QuestionMark" @@ -1640,7 +1674,7 @@ function HealBot_UpdateActiveHoTTimers() end local hot = HealBot_PlayerHoTs_ListCache[numHoTs] hot.unit = unitID - hot.name = displayName or targetKey + hot.name = displayName or "Unknown" hot.spell = spellName hot.texture = tex hot.expires = expiration @@ -1650,8 +1684,29 @@ function HealBot_UpdateActiveHoTTimers() if not HealBot_ActiveHoTUnitMap[unitID] then HealBot_ActiveHoTUnitMap[unitID] = {} end + local cleanTex = string.lower(string.gsub(tex, "/", "\\")) + local shortTex = string.match(cleanTex, "([^\\]+)$") HealBot_ActiveHoTUnitMap[unitID][tex] = timeLeft - HealBot_ActiveHoTUnitMap[unitID][string.lower(tex)] = timeLeft + HealBot_ActiveHoTUnitMap[unitID][cleanTex] = timeLeft + if shortTex then + HealBot_ActiveHoTUnitMap[unitID][shortTex] = timeLeft + end + + -- If player in raid, map under raid token button as well + if unitID == "player" and HealBot_Action_UnitButtons then + for btnUnit in pairs(HealBot_Action_UnitButtons) do + if btnUnit ~= "player" and UnitIsUnit(btnUnit, "player") then + if not HealBot_ActiveHoTUnitMap[btnUnit] then + HealBot_ActiveHoTUnitMap[btnUnit] = {} + end + HealBot_ActiveHoTUnitMap[btnUnit][tex] = timeLeft + HealBot_ActiveHoTUnitMap[btnUnit][cleanTex] = timeLeft + if shortTex then + HealBot_ActiveHoTUnitMap[btnUnit][shortTex] = timeLeft + end + end + end + end end end end