From 7beff1c4caabb4a12e5b31e04ac48f5b72166051 Mon Sep 17 00:00:00 2001 From: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com> Date: Sun, 13 Sep 2026 20:09:46 +0200 Subject: [PATCH 1/6] Fix: expand table pooling across modules to reduce garbage collection --- HealBotBlue.toc | 2 +- HealBot_Action.lua | 6 ++++-- HealBot_Controller_Aura.lua | 3 ++- HealBot_Controller_Spells.lua | 3 ++- HealBot_Integrations.lua | 7 +++++-- HealBot_Model.lua | 3 ++- HealBot_View_Layout.lua | 3 ++- README.md | 3 +++ 8 files changed, 21 insertions(+), 9 deletions(-) diff --git a/HealBotBlue.toc b/HealBotBlue.toc index 96d1a22..30b9bda 100644 --- a/HealBotBlue.toc +++ b/HealBotBlue.toc @@ -1,6 +1,6 @@ ## Interface: 11200 ## Title: HealBotBlue -## Version: 1.7.2 +## Version: 1.7.3 ## Author: Bluewhale ## Notes: Raidframe replacement for healing, decursing, resource tracking and buffing with optional support for SuperWow, ClassicAPI, UnitXP_SP3 and Nampower. ## SavedVariablesPerCharacter: HealBot_Config diff --git a/HealBot_Action.lua b/HealBot_Action.lua index 69ef209..207d7ad 100644 --- a/HealBot_Action.lua +++ b/HealBot_Action.lua @@ -136,9 +136,10 @@ end -- HealBot_SplitString: Internal utility: HealBot_SplitString function HealBot_SplitString(str, delimiter) - local result = {} + local result = HealBot_GetTable() if not delimiter or delimiter == "" then - return {str} + table.insert(result, str) + return result end local start_pos = 1 while true do @@ -160,6 +161,7 @@ function HealBot_RunMacroText(body) ChatFrameEditBox:SetText(commands[i]) ChatEdit_SendText(ChatFrameEditBox) end + HealBot_ReleaseTable(commands) end -- HealBot_RunMacro: Internal utility: HealBot_RunMacro diff --git a/HealBot_Controller_Aura.lua b/HealBot_Controller_Aura.lua index 3757ab8..d3decfe 100644 --- a/HealBot_Controller_Aura.lua +++ b/HealBot_Controller_Aura.lua @@ -184,7 +184,7 @@ function HealBot_OnEvent_UnitAura(this, unit) local iconCount = 0 local i = 1; HealBot_UnitDebuff[unit] = nil; - local trackedTextures = {} + local trackedTextures = HealBot_GetTable() while true do local debuff, tmp, debuff_type = UnitDebuff(unit, i, 1) @@ -301,5 +301,6 @@ function HealBot_OnEvent_UnitAura(this, unit) -- Defer UI updates HealBot_View_DirtyUnits[unit] = true + HealBot_ReleaseTable(trackedTextures) end end diff --git a/HealBot_Controller_Spells.lua b/HealBot_Controller_Spells.lua index b248a76..eb11850 100644 --- a/HealBot_Controller_Spells.lua +++ b/HealBot_Controller_Spells.lua @@ -472,7 +472,7 @@ function HealBot_FindHealSpells() end end); - local items = {}; + local items = HealBot_GetTable(); for bag = 0, NUM_BAG_FRAMES do for slot = 1, GetContainerNumSlots(bag) do local item = HealBot_GetItemName(bag, slot); @@ -498,6 +498,7 @@ function HealBot_FindHealSpells() HealBot_Heals["raidpet" .. i] = HealBot_Heals.party; end + HealBot_ReleaseTable(items); if HealBot_CalcEquipBonus then HealBot_AddDebug("...Done Equip Bonus:" .. RealHealing); end diff --git a/HealBot_Integrations.lua b/HealBot_Integrations.lua index 4dd03b3..42ac6c2 100644 --- a/HealBot_Integrations.lua +++ b/HealBot_Integrations.lua @@ -44,7 +44,7 @@ function HealBot_Integrations_Toggle() if not spellName then return end if not HealBot_Nampower_Auras[target] then - HealBot_Nampower_Auras[target] = {} + HealBot_Nampower_Auras[target] = HealBot_GetTable() end local expirationTime = GetTime() + (duration / 1000) @@ -61,7 +61,8 @@ function HealBot_Integrations_Toggle() HealBot_Integrations_Nampower_Active = false; HealBot_AddDebug("nampower Integration: DISABLED"); if HealBot_Nampower_Auras then - for k in pairs(HealBot_Nampower_Auras) do + for k, v in pairs(HealBot_Nampower_Auras) do + HealBot_ReleaseTable(v) HealBot_Nampower_Auras[k] = nil end end @@ -76,6 +77,7 @@ function HealBot_Integrations_PruneNampower() for targetName, auras in pairs(HealBot_Nampower_Auras) do -- Check if target is still in the raid/party if not HealBot_Model:GetUnitIDByName(targetName) then + HealBot_ReleaseTable(auras) HealBot_Nampower_Auras[targetName] = nil else -- Prune expired auras @@ -88,6 +90,7 @@ function HealBot_Integrations_PruneNampower() end end if not hasAuras then + HealBot_ReleaseTable(auras) HealBot_Nampower_Auras[targetName] = nil end end diff --git a/HealBot_Model.lua b/HealBot_Model.lua index 2114e4f..e3fdfa8 100644 --- a/HealBot_Model.lua +++ b/HealBot_Model.lua @@ -245,7 +245,8 @@ function HealBot_Model:PreserveStateByGUID() for targetUnit, stateData in pairs(stateSwaps) do -- Deep copy to prevent memory aliasing if not self.units[targetUnit] then - self.units[targetUnit] = { icons = {} } + self.units[targetUnit] = HealBot_GetTable() + self.units[targetUnit].icons = HealBot_GetTable() end local targetIcons = self.units[targetUnit].icons diff --git a/HealBot_View_Layout.lua b/HealBot_View_Layout.lua index efd88ac..c02bbde 100644 --- a/HealBot_View_Layout.lua +++ b/HealBot_View_Layout.lua @@ -1153,7 +1153,7 @@ end function HealBot_Action_AppendNewUnits() if not HealBot_Grid_LastI then return end - local unitsToCheck = {} + local unitsToCheck = HealBot_GetTable() -- Gather units based on config, similar to PartyChanged if HealBot_Config.GroupHeals == 1 then @@ -1220,4 +1220,5 @@ function HealBot_Action_AppendNewUnits() HealBot_Action_AppendUnit(unit) end end + HealBot_ReleaseTable(unitsToCheck) end diff --git a/README.md b/README.md index f6f3853..30f3c00 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,9 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\ ### Change Log +**v1.7.3** +* **Performance Fix - Table Pooling Part 2** - Fixed remaining un-pooled table allocations in layout updates, macro parsing, nampower integration, and aura tracking by utilizing HealBot_GetTable(). + **v1.7.2** * **Performance Fix - Table Pooling** - Fixed massive Vanilla Lua 5.0 garbage collection memory leaks caused by unbounded table allocations in high-frequency update loops (e.g., `OnUpdate` and `PreserveStateByGUID`). Moved tables to file-local scope and implemented inline clearing. * **Performance Fix - OOC Cleanup** - Added an out-of-combat garbage collection hook (`PLAYER_REGEN_ENABLED`) to purge disconnected senders from the `HealBot_IncomingHealers` global table, preventing memory bloat during prolonged play sessions. From 7f4d4be827c340c5a40647a2b98e58494f97aaf1 Mon Sep 17 00:00:00 2001 From: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com> Date: Sun, 13 Sep 2026 20:39:46 +0200 Subject: [PATCH 2/6] Fix: add pooling to rest of the tables out there From 55bc6f1ea01ddd025f8552a1c407fa6c7297c3a5 Mon Sep 17 00:00:00 2001 From: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com> Date: Wed, 16 Sep 2026 10:24:33 +0200 Subject: [PATCH 3/6] Fix: optimize execution performance and memory usage via caching and table reuse --- HealBot_Controller_Aura.lua | 7 ++++++- HealBot_Controller_Events.lua | 12 ++++++------ HealBot_Controller_Spells.lua | 35 +++++++++++++++++++++++++++-------- HealBot_Model.lua | 4 ++-- HealBot_View_Layout.lua | 6 ++++-- 5 files changed, 45 insertions(+), 19 deletions(-) diff --git a/HealBot_Controller_Aura.lua b/HealBot_Controller_Aura.lua index d3decfe..597adee 100644 --- a/HealBot_Controller_Aura.lua +++ b/HealBot_Controller_Aura.lua @@ -41,6 +41,7 @@ function HealBot_CheckShamanWeaponBuff(spellName) if not firstWord then return false end HealBot_ScanTooltip:SetOwner(UIParent, "ANCHOR_NONE") + if not HealBot_ScanTooltip_Lines then HealBot_ScanTooltip_Lines = {} end local slots = HealBot_GetTable() if hasMainHandEnchant then table.insert(slots, 16) end if hasOffHandEnchant then table.insert(slots, 17) end @@ -49,7 +50,11 @@ function HealBot_CheckShamanWeaponBuff(spellName) HealBot_ScanTooltip:ClearLines() HealBot_ScanTooltip:SetInventoryItem("player", slot) for i = 1, HealBot_ScanTooltip:NumLines() do - local textObj = getglobal("HealBot_ScanTooltipTextLeft" .. i) + local textObj = HealBot_ScanTooltip_Lines[i] + if not textObj then + textObj = getglobal("HealBot_ScanTooltipTextLeft" .. i) + HealBot_ScanTooltip_Lines[i] = textObj + end if textObj then local text = textObj:GetText() if text and string.find(text, firstWord) then diff --git a/HealBot_Controller_Events.lua b/HealBot_Controller_Events.lua index 7a6aab3..ab5521e 100644 --- a/HealBot_Controller_Events.lua +++ b/HealBot_Controller_Events.lua @@ -69,11 +69,11 @@ function HealBot_OnUpdate(this, arg1) local pending = HealBot_TargetRestorePending; HealBot_TargetRestorePending = nil; HealBot_TargetRestoreTimer = 0; - if pending.type == "enemy" then + if pending == "enemy" then TargetLastEnemy(); - elseif pending.type == "friend" then + elseif pending == "friend" then TargetLastTarget(); - elseif pending.type == "clear" then + elseif pending == "clear" then ClearTarget(); end end @@ -112,11 +112,11 @@ function HealBot_OnUpdate(this, arg1) -- Restore target logic if pendingCast.targetEnemy then - HealBot_TargetRestorePending = { type = "enemy" } + HealBot_TargetRestorePending = "enemy" elseif pendingCast.oldTarget and pendingCast.oldTarget ~= UnitName(pendingCast.target) then - HealBot_TargetRestorePending = { type = "friend" } + HealBot_TargetRestorePending = "friend" elseif not pendingCast.oldTarget then - HealBot_TargetRestorePending = { type = "clear" } + HealBot_TargetRestorePending = "clear" end HealBot_TargetRestoreTimer = 0 end diff --git a/HealBot_Controller_Spells.lua b/HealBot_Controller_Spells.lua index eb11850..4030930 100644 --- a/HealBot_Controller_Spells.lua +++ b/HealBot_Controller_Spells.lua @@ -237,7 +237,7 @@ function HealBot_StopCasting() local ag = HealBot_Config.babortcolg[HealBot_Config.Current_Skin] or 0.1; local ab = HealBot_Config.babortcolb[HealBot_Config.Current_Skin] or 0.5; local aa = HealBot_Config.babortcola[HealBot_Config.Current_Skin] or 1; - bar.txt = getglobal(bar:GetName() .. "_text"); + if not bar.txt then bar.txt = getglobal(bar:GetName() .. "_text") end bar:SetStatusBarColor(ar, ag, ab, 0); local sr = HealBot_Config.btextdisbledcolr[HealBot_Config.Current_Skin]; local sg = HealBot_Config.btextdisbledcolg[HealBot_Config.Current_Skin]; @@ -303,7 +303,7 @@ function HealBot_CheckCasting(unit) local sg = HealBot_Config.btextenabledcolg[HealBot_Config.Current_Skin]; local sb = HealBot_Config.btextenabledcolb[HealBot_Config.Current_Skin]; local sa = HealBot_Config.btextenabledcola[HealBot_Config.Current_Skin]; - bar.txt = getglobal(bar:GetName() .. "_text"); + if not bar.txt then bar.txt = getglobal(bar:GetName() .. "_text") end bar.txt:SetTextColor(sr, sg, sb, sa); end end @@ -328,7 +328,15 @@ function HealBot_CastSpellOnFriend(spell, target) if formCancelled then -- ALWAYS put the cast into the Pending queue so the OnUpdate loop can wait for the server -- to process the unshift before attempting the cast, otherwise we get "You are in shapeshift form". - HealBot_PendingShapeshiftCast = { spell = spell, target = target, targetEnemy = targetEnemy, oldTarget = oldTarget, fireTime = GetTime() + 0.05, expires = GetTime() + 2.0 } + if not HealBot_PendingShapeshiftCast then HealBot_PendingShapeshiftCast = {} end + HealBot_PendingShapeshiftCast.spell = spell + HealBot_PendingShapeshiftCast.target = target + HealBot_PendingShapeshiftCast.targetEnemy = targetEnemy + HealBot_PendingShapeshiftCast.oldTarget = oldTarget + HealBot_PendingShapeshiftCast.fireTime = GetTime() + 0.05 + HealBot_PendingShapeshiftCast.expires = GetTime() + 2.0 + HealBot_PendingShapeshiftCast.started = nil + HealBot_PendingShapeshiftCast.nextSpam = nil return; end @@ -339,11 +347,11 @@ function HealBot_CastSpellOnFriend(spell, target) HealBot_StartCasting(spell, target, "direct"); if targetEnemy then - HealBot_TargetRestorePending = { type = "enemy" }; + HealBot_TargetRestorePending = "enemy"; elseif oldTarget and oldTarget ~= UnitName(target) then - HealBot_TargetRestorePending = { type = "friend" }; + HealBot_TargetRestorePending = "friend"; elseif not oldTarget then - HealBot_TargetRestorePending = { type = "clear" }; + HealBot_TargetRestorePending = "clear"; end HealBot_TargetRestoreTimer = 0; end @@ -674,8 +682,15 @@ function HealBot_InitGetSpellData(spell, id, class) _cast = 0; line = nil; + if not HealBot_ScanTooltip_Lines_Left then HealBot_ScanTooltip_Lines_Left = {} end + if not HealBot_ScanTooltip_Lines_Right then HealBot_ScanTooltip_Lines_Right = {} end + for lineNum = 2, 6 do - local lText = getglobal("HealBot_ScanTooltipTextLeft"..lineNum); + local lText = HealBot_ScanTooltip_Lines_Left[lineNum]; + if not lText then + lText = getglobal("HealBot_ScanTooltipTextLeft"..lineNum); + HealBot_ScanTooltip_Lines_Left[lineNum] = lText; + end if lText and lText:IsVisible() and lText:GetText() then local txt = lText:GetText(); local t1, t2, match; @@ -699,7 +714,11 @@ function HealBot_InitGetSpellData(spell, id, class) end end - local rText = getglobal("HealBot_ScanTooltipTextRight"..lineNum); + local rText = HealBot_ScanTooltip_Lines_Right[lineNum]; + if not rText then + rText = getglobal("HealBot_ScanTooltipTextRight"..lineNum); + HealBot_ScanTooltip_Lines_Right[lineNum] = rText; + end if rText and rText:IsVisible() and rText:GetText() then local txt = rText:GetText(); local t1, t2, match; diff --git a/HealBot_Model.lua b/HealBot_Model.lua index e3fdfa8..5d3511b 100644 --- a/HealBot_Model.lua +++ b/HealBot_Model.lua @@ -250,7 +250,7 @@ function HealBot_Model:PreserveStateByGUID() end local targetIcons = self.units[targetUnit].icons - if not targetIcons then targetIcons = {} end + if not targetIcons then targetIcons = HealBot_GetTable() end for k in pairs(targetIcons) do targetIcons[k] = nil end for k in pairs(self.units[targetUnit]) do self.units[targetUnit][k] = nil end @@ -263,7 +263,7 @@ function HealBot_Model:PreserveStateByGUID() self.units[targetUnit].icons = targetIcons if HealBot_UnitIcons and iconSwaps[targetUnit] then - if not HealBot_UnitIcons[targetUnit] then HealBot_UnitIcons[targetUnit] = {} end + if not HealBot_UnitIcons[targetUnit] then HealBot_UnitIcons[targetUnit] = HealBot_GetTable() end for j=1, 10 do HealBot_UnitIcons[targetUnit][j] = iconSwaps[targetUnit][j] end diff --git a/HealBot_View_Layout.lua b/HealBot_View_Layout.lua index c02bbde..25179d3 100644 --- a/HealBot_View_Layout.lua +++ b/HealBot_View_Layout.lua @@ -857,8 +857,10 @@ function HealBot_Action_PartyChanged() if i == last then break end end else - local petUnits = { "pet", "partypet1", "partypet2", "partypet3", "partypet4" }; - for _, unit in ipairs(petUnits) do + if not HealBot_PetUnits then + HealBot_PetUnits = { "pet", "partypet1", "partypet2", "partypet3", "partypet4" }; + end + for _, unit in ipairs(HealBot_PetUnits) do if not HealBot_Action_UnitButtons[unit] and HealBot_MayHeal(unit) then i = i + 1; HealBot_Action_SetHealButton(i, unit); From 5e33429deec0e8c21342cd0d6d2e213e3d9c3412 Mon Sep 17 00:00:00 2001 From: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com> Date: Wed, 16 Sep 2026 11:10:55 +0200 Subject: [PATCH 4/6] feat: add support for group-wide healing spell tracking and communication --- HealBot_Controller_Spells.lua | 78 ++++++++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 14 deletions(-) diff --git a/HealBot_Controller_Spells.lua b/HealBot_Controller_Spells.lua index 4030930..8ee88cb 100644 --- a/HealBot_Controller_Spells.lua +++ b/HealBot_Controller_Spells.lua @@ -3,6 +3,7 @@ HealBot_CastingSpell = nil; HealBot_CastingTarget = nil; +HealBot_CastingGroupMembers = nil; HealBot_TargetRestorePending = nil; HealBot_TargetRestoreTimer = 0; @@ -158,13 +159,52 @@ function HealBot_Process_HealValue(spell, target) end local uname = UnitName(target) if uname then - HealBot_SendAddonMessage(HEALBOT_ADDON_ID, ">> " .. uname .. " <<=>> " .. HealBot_HealValue .. " << "); - HealBot_SendAddonMessage("HealComm", "Heal/" .. uname .. "/" .. HealBot_HealValue .. "/1500/"); - if not HealBot_HealsIn[uname] then - HealBot_HealsIn[uname] = 0; + if not HealBot_CastingGroupMembers then HealBot_CastingGroupMembers = {} end + for i=1, table.getn(HealBot_CastingGroupMembers) do HealBot_CastingGroupMembers[i] = nil end + table.setn(HealBot_CastingGroupMembers, 0) + if HEALBOT_PRAYER_OF_HEALING and string.find(spell, HEALBOT_PRAYER_OF_HEALING) then + if GetNumRaidMembers() > 0 then + local targetGroup = 0 + for i = 1, GetNumRaidMembers() do + local name, _, subgroup = GetRaidRosterInfo(i) + if name == uname then targetGroup = subgroup; break; end + end + if targetGroup > 0 then + for i = 1, GetNumRaidMembers() do + local name, _, subgroup = GetRaidRosterInfo(i) + if subgroup == targetGroup and name then table.insert(HealBot_CastingGroupMembers, name); end + end + end + else + table.insert(HealBot_CastingGroupMembers, UnitName("player")) + for i = 1, GetNumPartyMembers() do + if UnitName("party"..i) then table.insert(HealBot_CastingGroupMembers, UnitName("party"..i)); end + end + end + end + if table.getn(HealBot_CastingGroupMembers) == 0 then + table.insert(HealBot_CastingGroupMembers, uname) + end + + if table.getn(HealBot_CastingGroupMembers) > 1 then + local commsStr = "GrpHeal/" .. HealBot_HealValue .. "/1500/" + for _, memberName in ipairs(HealBot_CastingGroupMembers) do + commsStr = commsStr .. memberName .. "/" + end + HealBot_SendAddonMessage("HealComm", commsStr) + for _, memberName in ipairs(HealBot_CastingGroupMembers) do + HealBot_SendAddonMessage(HEALBOT_ADDON_ID, ">> " .. memberName .. " <<=>> " .. HealBot_HealValue .. " << ") + if not HealBot_HealsIn[memberName] then HealBot_HealsIn[memberName] = 0 end + HealBot_HealsIn[memberName] = HealBot_HealsIn[memberName] + HealBot_HealValue + HealBot_RecalcHeals(HealBot_FindUnitID(memberName)) + end + else + HealBot_SendAddonMessage("HealComm", "Heal/" .. uname .. "/" .. HealBot_HealValue .. "/1500/") + HealBot_SendAddonMessage(HEALBOT_ADDON_ID, ">> " .. uname .. " <<=>> " .. HealBot_HealValue .. " << ") + if not HealBot_HealsIn[uname] then HealBot_HealsIn[uname] = 0 end + HealBot_HealsIn[uname] = HealBot_HealsIn[uname] + HealBot_HealValue + HealBot_RecalcHeals(HealBot_FindUnitID(uname)) end - HealBot_HealsIn[uname] = HealBot_HealsIn[uname] + HealBot_HealValue; - HealBot_RecalcHeals(HealBot_FindUnitID(uname)); end end end @@ -217,14 +257,24 @@ function HealBot_StopCasting() if HealBot_HealValue > 0 then local uname = UnitName(HealBot_CastingTarget) if uname then - HealBot_SendAddonMessage(HEALBOT_ADDON_ID, ">> " .. uname .. " <<=>> " .. 0 - HealBot_HealValue .. " << "); - HealBot_SendAddonMessage("HealComm", "Healstop"); - if HealBot_HealsIn[uname] then - HealBot_HealsIn[uname] = HealBot_HealsIn[uname] - HealBot_HealValue; - if HealBot_HealsIn[uname] < 0 then - HealBot_HealsIn[uname] = 0; - end - HealBot_RecalcHeals(HealBot_FindUnitID(uname)); + if HealBot_CastingGroupMembers and table.getn(HealBot_CastingGroupMembers) > 1 then + HealBot_SendAddonMessage("HealComm", "GrpHealstop"); + for _, memberName in ipairs(HealBot_CastingGroupMembers) do + HealBot_SendAddonMessage(HEALBOT_ADDON_ID, ">> " .. memberName .. " <<=>> " .. 0 - HealBot_HealValue .. " << ") + if HealBot_HealsIn[memberName] then + HealBot_HealsIn[memberName] = HealBot_HealsIn[memberName] - HealBot_HealValue; + if HealBot_HealsIn[memberName] < 0 then HealBot_HealsIn[memberName] = 0; end + HealBot_RecalcHeals(HealBot_FindUnitID(memberName)); + end + end + else + HealBot_SendAddonMessage("HealComm", "Healstop"); + HealBot_SendAddonMessage(HEALBOT_ADDON_ID, ">> " .. uname .. " <<=>> " .. 0 - HealBot_HealValue .. " << "); + if HealBot_HealsIn[uname] then + HealBot_HealsIn[uname] = HealBot_HealsIn[uname] - HealBot_HealValue; + if HealBot_HealsIn[uname] < 0 then HealBot_HealsIn[uname] = 0; end + HealBot_RecalcHeals(HealBot_FindUnitID(uname)); + end end end HealBot_HealValue = 0; From 1edb4b22bb23213cebf73eb5f3de05ccd2c6ff81 Mon Sep 17 00:00:00 2001 From: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com> Date: Thu, 24 Sep 2026 21:38:19 +0200 Subject: [PATCH 5/6] fix: correct BuffWatchSelf UI element lookup and document the fix in README --- HealBot_Controller_Spells.lua | 6 +++++- README.md | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/HealBot_Controller_Spells.lua b/HealBot_Controller_Spells.lua index 8ee88cb..e84201d 100644 --- a/HealBot_Controller_Spells.lua +++ b/HealBot_Controller_Spells.lua @@ -627,7 +627,11 @@ end -- HealBot_RecalcHeals: Flags unit for visual refresh. function HealBot_RecalcHeals(unit) - HealBot_Action_Refresh(unit); + if unit then + HealBot_View_DirtyUnits[unit] = true; + else + HealBot_Action_Refresh(); + end end -- HealBot_RecalcParty: Triggers group layout rebuild. diff --git a/README.md b/README.md index 30f3c00..a0a402c 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,7 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\ **v1.7.3** * **Performance Fix - Table Pooling Part 2** - Fixed remaining un-pooled table allocations in layout updates, macro parsing, nampower integration, and aura tracking by utilizing HealBot_GetTable(). +* **Performance Fix - HealComm Networking** - Fixed issue where incoming `HealComm` messages triggered synchronous UI redraws, causing massive lag in 40-man raids during combat. `HealBot_RecalcHeals` is now decoupled and deferred through the `HealBot_OnUpdate` dirty queue, allowing multiple network events to collapse into a single frame redraw. **v1.7.2** * **Performance Fix - Table Pooling** - Fixed massive Vanilla Lua 5.0 garbage collection memory leaks caused by unbounded table allocations in high-frequency update loops (e.g., `OnUpdate` and `PreserveStateByGUID`). Moved tables to file-local scope and implemented inline clearing. From eb7cbc52f2c05b779b6b6853e51009e555fe6011 Mon Sep 17 00:00:00 2001 From: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com> Date: Thu, 24 Sep 2026 22:31:24 +0200 Subject: [PATCH 6/6] refactor: mark all unit buttons dirty instead of calling HealBot_Action_Refresh --- HealBot_Controller_Spells.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/HealBot_Controller_Spells.lua b/HealBot_Controller_Spells.lua index e84201d..b9bea6c 100644 --- a/HealBot_Controller_Spells.lua +++ b/HealBot_Controller_Spells.lua @@ -630,7 +630,11 @@ function HealBot_RecalcHeals(unit) if unit then HealBot_View_DirtyUnits[unit] = true; else - HealBot_Action_Refresh(); + if HealBot_Action_UnitButtons then + for u, _ in pairs(HealBot_Action_UnitButtons) do + HealBot_View_DirtyUnits[u] = true; + end + end end end