From c8a5e4f0ebf926230929319c664a69f63357759b Mon Sep 17 00:00:00 2001
From: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com>
Date: Sat, 18 Jul 2026 13:35:59 +0200
Subject: [PATCH 01/12] perf: eliminate string allocation GC spikes in
healthbar refreshing and remove full UI rebuilds on target change
---
HealBot_Controller_Events.lua | 5 ++++-
HealBot_Controller_Spells.lua | 2 +-
HealBot_View_Layout.lua | 17 +++++++++++------
3 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/HealBot_Controller_Events.lua b/HealBot_Controller_Events.lua
index 122b32f..825d1ae 100644
--- a/HealBot_Controller_Events.lua
+++ b/HealBot_Controller_Events.lua
@@ -378,7 +378,10 @@ function HealBot_OnEvent_PlayerRegenEnabled(this)
end
function HealBot_OnEvent_PlayerTargetChanged(this)
- HealBot_RecalcParty();
+ if HealBot_Action_UnitButtons and HealBot_Action_UnitButtons["target"] then
+ HealBot_Action_RefreshButtons("target");
+ HealBot_OnEvent_UnitAura(nil, "target");
+ end
end
function HealBot_OnEvent_PartyMembersChanged(this)
diff --git a/HealBot_Controller_Spells.lua b/HealBot_Controller_Spells.lua
index 97f9dd9..2895dd3 100644
--- a/HealBot_Controller_Spells.lua
+++ b/HealBot_Controller_Spells.lua
@@ -246,7 +246,7 @@ function HealBot_CheckCasting(unit)
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
if HealBot_IsCasting == false and HealBot_AbortButton == 0 then
bar:SetStatusBarColor(ar, ag, ab, 0);
diff --git a/HealBot_View_Layout.lua b/HealBot_View_Layout.lua
index 40ef3c9..8756244 100644
--- a/HealBot_View_Layout.lua
+++ b/HealBot_View_Layout.lua
@@ -87,13 +87,17 @@ function HealBot_HealthColor(unit, hlth, maxhlth)
end
function HealBot_Action_HealthBar(button)
- local name = button:GetName();
- return getglobal(name .. "Bar");
+ if not button.bar then
+ button.bar = getglobal(button:GetName() .. "Bar")
+ end
+ return button.bar;
end
function HealBot_Action_HealthBar2(button)
- local name = button:GetName();
- return getglobal(name .. "Bar2");
+ if not button.bar2 then
+ button.bar2 = getglobal(button:GetName() .. "Bar2")
+ end
+ return button.bar2;
end
function HealBot_Action_EnableButton(button)
@@ -108,7 +112,8 @@ function HealBot_Action_EnableButton(button)
local bar = HealBot_Action_HealthBar(button);
local bar2 = HealBot_Action_HealthBar2(button);
- local bar3 = getglobal(button:GetName() .. "Bar3");
+ if not button.bar3 then button.bar3 = getglobal(button:GetName() .. "Bar3") end
+ local bar3 = button.bar3;
local btexture = HealBot_Config.btexture[HealBot_Config.Current_Skin];
local bheight = HealBot_Config.bheight[HealBot_Config.Current_Skin];
local sr = HealBot_Config.btextenabledcolr[HealBot_Config.Current_Skin];
@@ -175,7 +180,7 @@ function HealBot_Action_EnableButton(button)
else
bar2:SetValue(0);
end
- bar.txt = getglobal(bar:GetName() .. "_text");
+ if not bar.txt then bar.txt = getglobal(bar:GetName() .. "_text") end
if (not HealBot_IsCasting and (HealBot_CanHeal(unit) or HealBot_MissingBuffs[unit])) then
button:Enable();
if HealBot_UnitDebuff[unit] then
From 8854cd3caa5effa062390a0d97e10b3e1c253138 Mon Sep 17 00:00:00 2001
From: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com>
Date: Sat, 18 Jul 2026 23:26:14 +0200
Subject: [PATCH 02/12] docs: add release notes for v1.4.2 to README.md
---
README.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/README.md b/README.md
index 0e8b1be..063f1fd 100644
--- a/README.md
+++ b/README.md
@@ -47,8 +47,10 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\
* **Macro, Item, and Script Bindings:** Support for binding named macros, inventory items, and inline scripts (e.g. `/target`) directly to mouse clicks in the Spells tab. All of these now natively support implicit `@mouseover` targeting on the unit frame you click, without losing your current target.
* **Modifier-Aware Tooltips & Resource Costs:** The tooltip dynamically updates to show exactly what action is bound when holding down Shift, Ctrl, or Alt over a frame. Spells also show their required mana cost, turning red if you do not have enough mana to cast them.
* **Memory Recycling Pool:** Added a local table recycling pool in the data layer to greatly reduce Lua garbage collection (GC) spikes, improving overall client frame rates during intense combat.
+
**v1.4.2**
* **Memory Optimization:** Fixed a significant memory leak where tracking tables were being repeatedly allocated every tick during aura scanning, and replaced `table.foreach` with pairs loops to avoid GC spikes during combat.
+
**v1.4.1**
* **Talent-based Healing Calculations:** Implemented dynamic spell healing calculations for Druid, Priest, and Paladin classes based on talents.
* **Modifier Key Polling:** Replaced MODIFIER_STATE_CHANGED event with polling in HealBot_OnUpdate to track modifier keys reliably.
From 826bf64eda86cf83e27f68f3f0759d7ce70a2a5d Mon Sep 17 00:00:00 2001
From: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com>
Date: Sat, 18 Jul 2026 23:34:20 +0200
Subject: [PATCH 03/12] fix: resolve Self Only buff tracking failing on raid
frames by replacing direct unit string comparisons with UnitIsUnit
---
HealBot_Controller_Aura.lua | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/HealBot_Controller_Aura.lua b/HealBot_Controller_Aura.lua
index 9ae5d5e..5ece90c 100644
--- a/HealBot_Controller_Aura.lua
+++ b/HealBot_Controller_Aura.lua
@@ -91,7 +91,7 @@ function HealBot_CheckBuffs(unit)
local val = HealBot_Config.BuffDropDowns[myClass][j]
if val and val > 0 then
local isSelfOnly = (HealBot_Config.BuffWatchSelf and HealBot_Config.BuffWatchSelf[j] == 1)
- if not (isSelfOnly and unit ~= "player") then
+ if not (isSelfOnly and not UnitIsUnit(unit, "player")) then
local spellName = HealBot_Buff_Spells[myClass][val]
local hasIt = hasBuff[spellName]
@@ -100,7 +100,7 @@ function HealBot_CheckBuffs(unit)
end
if not hasIt then
- if myClass == "SHAMAN" and unit == "player" and string.find(spellName, " Weapon") then
+ if myClass == "SHAMAN" and UnitIsUnit(unit, "player") and string.find(spellName, " Weapon") then
hasIt = HealBot_CheckShamanWeaponBuff(spellName)
end
end
From 3845ada15f5fc05342b70b83c9bc6fd5cfbbac1a Mon Sep 17 00:00:00 2001
From: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com>
Date: Sat, 18 Jul 2026 23:37:51 +0200
Subject: [PATCH 04/12] fix: remove artificial mana check to allow 0-mana cost
buffs and fix tooltips disappearing instead of turning red
---
HealBot_Controller_Spells.lua | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/HealBot_Controller_Spells.lua b/HealBot_Controller_Spells.lua
index 2895dd3..38784c1 100644
--- a/HealBot_Controller_Spells.lua
+++ b/HealBot_Controller_Spells.lua
@@ -462,7 +462,8 @@ end
function HealBot_CanCastSpell(spell, unit)
local this = HealBot_Spells[spell];
- if this.Mana > UnitMana("player") then return false end;
+ -- Removed manual mana check so WoW can properly handle 0-cost buffs (Clearcasting/Inner Focus)
+ -- and so tooltips can render in red instead of disappearing.
if this.BagSlot then
local bag, slot = HealBot_UnpackBagSlot(this.BagSlot);
local start, duration, enable = GetContainerItemCooldown(bag, slot);
From 9f08b356e1cca7412a3867894a7b96e7641cf437 Mon Sep 17 00:00:00 2001
From: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com>
Date: Sat, 18 Jul 2026 23:39:07 +0200
Subject: [PATCH 05/12] docs: append v1.5.1 changelog detailing memory, mana,
and buff tracking fixes
---
README.md | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/README.md b/README.md
index 063f1fd..7179741 100644
--- a/README.md
+++ b/README.md
@@ -43,6 +43,11 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\
### Change Log
+**v1.5.1**
+* **Memory Optimization:** Fixed severe Lua garbage collection spikes during UI reloads by preventing full party layout rebuilds on `PLAYER_TARGET_CHANGED`, and cached dynamic string concatenations directly to unit frames to eliminate memory leakage on high frequency UI refreshes.
+* **Mana Validation Fix:** Removed artificial spell mana gating, fixing an issue where low-mana spells disappeared from tooltips and couldn't be cast. WoW's native mana validation now correctly processes 0-cost buffs (e.g. Clearcasting, Inner Focus) while turning low-mana tooltip spells red.
+* **Self-Buff Tracking:** Fixed a bug where "Self Only" buff tracking incorrectly excluded the player when represented by party or raid frames instead of the standard "player" unit ID.
+
**v1.5**
* **Macro, Item, and Script Bindings:** Support for binding named macros, inventory items, and inline scripts (e.g. `/target`) directly to mouse clicks in the Spells tab. All of these now natively support implicit `@mouseover` targeting on the unit frame you click, without losing your current target.
* **Modifier-Aware Tooltips & Resource Costs:** The tooltip dynamically updates to show exactly what action is bound when holding down Shift, Ctrl, or Alt over a frame. Spells also show their required mana cost, turning red if you do not have enough mana to cast them.
From e6ad9e7506c1094af5eee26045189016634b0c1d Mon Sep 17 00:00:00 2001
From: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com>
Date: Sat, 18 Jul 2026 23:43:35 +0200
Subject: [PATCH 06/12] perf: eliminate remaining GC spikes by preventing
layout rebuilds on combat toggle and zeroing hot-loop table allocations
---
HealBot_Controller_Aura.lua | 6 +++++-
HealBot_Controller_Events.lua | 8 ++++----
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/HealBot_Controller_Aura.lua b/HealBot_Controller_Aura.lua
index 5ece90c..64eed93 100644
--- a/HealBot_Controller_Aura.lua
+++ b/HealBot_Controller_Aura.lua
@@ -2,6 +2,7 @@
-- Handles tracking buffs/debuffs (auras) on group/raid units
HealBot_MissingBuffs = {}
+local StaticHasBuff = {}
function HealBot_UnitAffected(unit, effect)
if not effect then return nil; end
@@ -68,7 +69,10 @@ function HealBot_CheckBuffs(unit)
}
-- Gather buffs on unit
- local hasBuff = {}
+ local hasBuff = StaticHasBuff
+ for k in pairs(hasBuff) do
+ hasBuff[k] = nil
+ end
local i = 1
while true do
local buffTexture = UnitBuff(unit, i)
diff --git a/HealBot_Controller_Events.lua b/HealBot_Controller_Events.lua
index 825d1ae..d7d4276 100644
--- a/HealBot_Controller_Events.lua
+++ b/HealBot_Controller_Events.lua
@@ -85,8 +85,8 @@ function HealBot_OnUpdate(this, arg1)
if not HealBot_IsFighting then
HealsIn_Timer = HealsIn_Timer + 1;
if HealsIn_Timer >= 10 then
- HealBot_HealsIn = {};
- HealBot_Healers = {};
+ for k in pairs(HealBot_HealsIn) do HealBot_HealsIn[k] = nil end
+ for k in pairs(HealBot_Healers) do HealBot_Healers[k] = nil end
HealsIn_Timer = 0;
end
@@ -338,7 +338,7 @@ function HealBot_OnEvent_ZoneChanged(this)
end
function HealBot_OnEvent_PlayerRegenDisabled(this)
- HealBot_RecalcParty();
+ -- Removed HealBot_RecalcParty();
if (UnitIsDeadOrGhost("player")) or (UnitOnTaxi("player")) then
if HealBot_Config.AutoClose==1 and HealBot_Config.ActionVisible~=0 then
HealBot_Action.ProgrammaticHide = true;
@@ -374,7 +374,7 @@ end
function HealBot_OnEvent_PlayerRegenEnabled(this)
HealBot_IsFighting = false;
- HealBot_Delay_RecalcParty = 1;
+ -- Removed HealBot_Delay_RecalcParty = 1;
end
function HealBot_OnEvent_PlayerTargetChanged(this)
From 441a45150f6461d8fd7f33de9b731399e7a29f82 Mon Sep 17 00:00:00 2001
From: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com>
Date: Mon, 20 Jul 2026 18:13:47 +0200
Subject: [PATCH 07/12] feat: add Spell_Holy_AshesToAshes icon and implement
debuff tracking loop in UnitAura handler
---
HealBot_Controller_Aura.lua | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/HealBot_Controller_Aura.lua b/HealBot_Controller_Aura.lua
index 64eed93..95fc671 100644
--- a/HealBot_Controller_Aura.lua
+++ b/HealBot_Controller_Aura.lua
@@ -127,6 +127,7 @@ local HealBot_TrackedHoTs = {
["Interface\\Icons\\Spell_Holy_SealOfProtection"] = true,
["Interface\\Icons\\Spell_Holy_Excorcism"] = true,
["Interface\\Icons\\btnholyscriptures"] = true,
+ ["Interface\\Icons\\Spell_Holy_AshesToAshes"] = true,
}
function HealBot_OnEvent_UnitAura(this, unit)
@@ -172,6 +173,17 @@ function HealBot_OnEvent_UnitAura(this, unit)
end
b = b + 1
end
+
+ local d = 1
+ while true do
+ local debuff = UnitDebuff(unit, d)
+ if not debuff then break end
+ if HealBot_TrackedHoTs[debuff] and iconCount < 5 then
+ iconCount = iconCount + 1
+ HealBot_UnitIcons[unit][iconCount] = debuff
+ end
+ d = d + 1
+ end
if HealBot_UnitDebuff[unit] then
if DebuffType and HealBot_Range_Check(unit, 27) == 1 then
From 85ad55c1cb2fe889ad3bddbd7e87b67c0c69471c Mon Sep 17 00:00:00 2001
From: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com>
Date: Mon, 20 Jul 2026 23:22:15 +0200
Subject: [PATCH 08/12] perf: optimize CPU and memory usage via boolean state
tracking, event filtering, and per-character SavedVariables.
---
HealBotBlue.toc | 2 +-
HealBot_Controller_Aura.lua | 2 +-
HealBot_Controller_Events.lua | 44 ++++++++++++-----------------------
HealBot_Data.lua | 2 +-
HealBot_Options_CDC.lua | 6 ++---
README.md | 4 ++++
6 files changed, 25 insertions(+), 35 deletions(-)
diff --git a/HealBotBlue.toc b/HealBotBlue.toc
index 6309ac0..1713e79 100644
--- a/HealBotBlue.toc
+++ b/HealBotBlue.toc
@@ -3,7 +3,7 @@
## Version: 1.5
## Author: Bluewhale
## Notes: Adds panel with skinable bars for healing and decursive
-## SavedVariables: HealBot_Config
+## SavedVariablesPerCharacter: HealBot_Config
..\..\FrameXML\Fonts.xml
..\..\FrameXML\OptionsFrameTemplates.xml
..\..\FrameXML\UIPanelTemplates.xml
diff --git a/HealBot_Controller_Aura.lua b/HealBot_Controller_Aura.lua
index 95fc671..9dee3c1 100644
--- a/HealBot_Controller_Aura.lua
+++ b/HealBot_Controller_Aura.lua
@@ -149,7 +149,7 @@ function HealBot_OnEvent_UnitAura(this, unit)
iconCount = iconCount + 1
HealBot_UnitIcons[unit][iconCount] = debuff
end
- if HealBot_CDCInc[UnitClass(unit)] == 1 and HealBot_DebuffWatch[debuff_type] == "YES" then
+ if HealBot_CDCInc[UnitClass(unit)] == 1 and HealBot_DebuffWatch[debuff_type] then
HealBot_UnitDebuff[unit] = debuff_type
DebuffType = debuff_type;
if HealBot_DebuffPriority[debuff_type] then
diff --git a/HealBot_Controller_Events.lua b/HealBot_Controller_Events.lua
index d7d4276..228fb0e 100644
--- a/HealBot_Controller_Events.lua
+++ b/HealBot_Controller_Events.lua
@@ -43,17 +43,20 @@ end
function HealBot_OnUpdate(this, arg1)
if HealBot_Action_TooltipUnit and HealBot_Tooltip:IsVisible() then
- local currentModState = ""
- if IsShiftKeyDown() then currentModState = currentModState .. "S" end
- if IsControlKeyDown() then currentModState = currentModState .. "C" end
- if IsAltKeyDown() then currentModState = currentModState .. "A" end
+ local s = IsShiftKeyDown() and true or false
+ local c = IsControlKeyDown() and true or false
+ local a = IsAltKeyDown() and true or false
- if HealBot_LastModState ~= currentModState then
- HealBot_LastModState = currentModState
+ if HealBot_LastModS ~= s or HealBot_LastModC ~= c or HealBot_LastModA ~= a then
+ HealBot_LastModS = s
+ HealBot_LastModC = c
+ HealBot_LastModA = a
HealBot_Action_RefreshTooltip(HealBot_Action_TooltipUnit)
end
else
- HealBot_LastModState = ""
+ HealBot_LastModS = false
+ HealBot_LastModC = false
+ HealBot_LastModA = false
end
if HealBot_TargetRestorePending then
@@ -131,6 +134,7 @@ local HealBot_EventHandlers = {
HealBot_OnEvent_UnitHealth(this, arg1)
end,
["UNIT_MANA"] = function(this, arg1)
+ if arg1 ~= "player" and HealBot_Config.ShowManaBars == 0 then return end
if HealBot_Model:UpdateUnitPower(arg1) then
HealBot_Model:NotifyObservers("UNIT_POWER_CHANGED", arg1)
end
@@ -138,6 +142,7 @@ local HealBot_EventHandlers = {
HealBot_Action_RefreshButtons(arg1);
end,
["UNIT_RAGE"] = function(this, arg1)
+ if arg1 ~= "player" and HealBot_Config.ShowManaBars == 0 then return end
if HealBot_Model:UpdateUnitPower(arg1) then
HealBot_Model:NotifyObservers("UNIT_POWER_CHANGED", arg1)
end
@@ -145,6 +150,7 @@ local HealBot_EventHandlers = {
HealBot_Action_RefreshButtons(arg1);
end,
["UNIT_ENERGY"] = function(this, arg1)
+ if arg1 ~= "player" and HealBot_Config.ShowManaBars == 0 then return end
if HealBot_Model:UpdateUnitPower(arg1) then
HealBot_Model:NotifyObservers("UNIT_POWER_CHANGED", arg1)
end
@@ -152,6 +158,7 @@ local HealBot_EventHandlers = {
HealBot_Action_RefreshButtons(arg1);
end,
["UNIT_DISPLAYPOWER"] = function(this, arg1)
+ if arg1 ~= "player" and HealBot_Config.ShowManaBars == 0 then return end
if HealBot_Model:UpdateUnitPower(arg1) then
HealBot_Model:NotifyObservers("UNIT_POWER_CHANGED", arg1)
end
@@ -201,8 +208,6 @@ local HealBot_EventHandlers = {
["SPELLCAST_FAILED"] = function(this) HealBot_OnEvent_SpellcastStop(this, "SPELLCAST_FAILED") end,
["PLAYER_REGEN_DISABLED"] = function(this) HealBot_OnEvent_PlayerRegenDisabled(this) end,
["PLAYER_REGEN_ENABLED"] = function(this) HealBot_OnEvent_PlayerRegenEnabled(this) end,
- ["BAG_UPDATE_COOLDOWN"] = function(this, arg1) HealBot_OnEvent_BagUpdateCooldown(this, arg1) end,
- ["BAG_UPDATE"] = function(this, arg1) HealBot_OnEvent_BagUpdate(this, arg1) end,
["PARTY_MEMBER_DISABLE"] = function(this, arg1) HealBot_OnEvent_PartyMemberDisable(this, arg1) end,
["PARTY_MEMBER_ENABLE"] = function(this, arg1) HealBot_OnEvent_PartyMemberEnable(this, arg1) end,
["CHAT_MSG_SYSTEM"] = function(this, arg1) HealBot_OnEvent_SystemMsg(this, arg1) end,
@@ -212,11 +217,10 @@ local HealBot_EventHandlers = {
HealBot_OnEvent_PlayerEquipmentChanged(this)
end,
["UNIT_INVENTORY_CHANGED"] = function(this, arg1)
+ if arg1 ~= "player" then return end
HealBot_Model:NotifyObservers("EQUIPMENT_CHANGED", arg1)
HealBot_OnEvent_PlayerEquipmentChanged2(this, arg1)
end,
- ["PET_BAR_SHOWGRID"] = function(this) HealBot_OnEvent_PartyMembersChanged(this) end,
- ["PET_BAR_HIDEGRID"] = function(this) HealBot_OnEvent_PartyMembersChanged(this) end,
["UNIT_PET"] = function(this, arg1) HealBot_OnEvent_PartyMembersChanged(this) end,
["SPELLS_CHANGED"] = function(this, arg1) HealBot_OnEvent_SpellsChanged(this, arg1) end,
["UPDATE_SHAPESHIFT_FORM"] = function(this) HealBot_UpdateShapeshiftForm() end,
@@ -288,8 +292,6 @@ function HealBot_OnEvent_VariablesLoaded(this)
this:RegisterEvent("PARTY_MEMBERS_CHANGED");
this:RegisterEvent("PARTY_MEMBER_DISABLE");
this:RegisterEvent("PARTY_MEMBER_ENABLE");
- this:RegisterEvent("PET_BAR_SHOWGRID");
- this:RegisterEvent("PET_BAR_HIDEGRID");
this:RegisterEvent("UNIT_PET");
this:RegisterEvent("UNIT_HEALTH");
this:RegisterEvent("UNIT_MANA");
@@ -301,8 +303,6 @@ function HealBot_OnEvent_VariablesLoaded(this)
this:RegisterEvent("SPELLCAST_STOP");
this:RegisterEvent("SPELLCAST_INTERRUPTED");
this:RegisterEvent("SPELLCAST_FAILED");
- this:RegisterEvent("BAG_UPDATE");
- this:RegisterEvent("BAG_UPDATE_COOLDOWN");
this:RegisterEvent("UNIT_AURA");
this:RegisterEvent("UPDATE_INVENTORY_ALERTS");
this:RegisterEvent("UNIT_INVENTORY_CHANGED");
@@ -442,20 +442,6 @@ function HealBot_OnEvent_TalentsChanged(this, arg1)
HealBot_AddDebug("HB: TalentsChanged");
end
-function HealBot_OnEvent_BagUpdate(this, bag)
- if HealBot_EquipChangeTimer == 0 then
- HealBot_RecalcSpells();
- end
-end
-
-function HealBot_OnEvent_BagUpdateCooldown(this, bag)
- if not bag then
- bag = "undef"
- elseif HealBot_EquipChangeTimer == 0 then
- HealBot_RecalcSpells();
- end
-end
-
function HealBot_OnEvent_PlayerEnteringWorld(this)
HealBot_IsFighting = false;
-- Re-apply the refresh hook late in case another addon overrode it during load
diff --git a/HealBot_Data.lua b/HealBot_Data.lua
index 6915aa6..a6fe2bf 100644
--- a/HealBot_Data.lua
+++ b/HealBot_Data.lua
@@ -545,7 +545,7 @@ HealBot_Debuff_Types = {
HealBot_IsFighting = false;
HealBot_DebuffPriority = {"none"};
-HealBot_DebuffWatch = {[HEALBOT_DISEASE_en]="NO", [HEALBOT_MAGIC_en]="NO", [HEALBOT_POISON_en]="NO", [HEALBOT_CURSE_en]="NO"};
+HealBot_DebuffWatch = {[HEALBOT_DISEASE_en]=false, [HEALBOT_MAGIC_en]=false, [HEALBOT_POISON_en]=false, [HEALBOT_CURSE_en]=false};
HealBot_Heals = {};
diff --git a/HealBot_Options_CDC.lua b/HealBot_Options_CDC.lua
index 14e81c4..c52de4b 100644
--- a/HealBot_Options_CDC.lua
+++ b/HealBot_Options_CDC.lua
@@ -247,16 +247,16 @@ function HealBot_Options_Debuff_Reset()
local classEN=HealBot_UnitClass("player")
if classEN=="PRIEST" or classEN=="DRUID" or classEN=="PALADIN" or classEN=="SHAMAN" then
local spell = HealBot_Config.CDCLeftText[UnitClass("player")];
- HealBot_DebuffWatch = {[HEALBOT_DISEASE_en]="NO", [HEALBOT_MAGIC_en]="NO", [HEALBOT_POISON_en]="NO", [HEALBOT_CURSE_en]="NO" }
+ HealBot_DebuffWatch = {[HEALBOT_DISEASE_en]=false, [HEALBOT_MAGIC_en]=false, [HEALBOT_POISON_en]=false, [HEALBOT_CURSE_en]=false }
if spell ~= "None" then
table.foreach(HealBot_Debuff_Types[spell], function (index,debuff)
- HealBot_DebuffWatch[debuff]="YES";
+ HealBot_DebuffWatch[debuff]=true;
end)
end
spell = HealBot_Config.CDCRightText[UnitClass("player")];
if spell ~= "None" then
table.foreach(HealBot_Debuff_Types[spell], function (index,debuff)
- HealBot_DebuffWatch[debuff]="YES";
+ HealBot_DebuffWatch[debuff]=true;
end)
end
end
diff --git a/README.md b/README.md
index 7179741..68f0212 100644
--- a/README.md
+++ b/README.md
@@ -47,6 +47,10 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\
* **Memory Optimization:** Fixed severe Lua garbage collection spikes during UI reloads by preventing full party layout rebuilds on `PLAYER_TARGET_CHANGED`, and cached dynamic string concatenations directly to unit frames to eliminate memory leakage on high frequency UI refreshes.
* **Mana Validation Fix:** Removed artificial spell mana gating, fixing an issue where low-mana spells disappeared from tooltips and couldn't be cast. WoW's native mana validation now correctly processes 0-cost buffs (e.g. Clearcasting, Inner Focus) while turning low-mana tooltip spells red.
* **Self-Buff Tracking:** Fixed a bug where "Self Only" buff tracking incorrectly excluded the player when represented by party or raid frames instead of the standard "player" unit ID.
+* **Settings Persistence Fix:** Changed `SavedVariables` to `SavedVariablesPerCharacter` in TOC so configurations correctly load unique per character instead of account-wide.
+* **CPU Optimization:** Added early exit logic to resource tracking events (Mana, Rage, Energy) to stop background polling on party/raid members when "Show Mana Bars" is toggled off. Also removed excessive triggers (`BAG_UPDATE`, `PET_BAR_SHOWGRID`) and filtered `UNIT_INVENTORY_CHANGED` to only process the player, eliminating massive CPU spikes and unnecessary UI layout rebuilds during looting, item cooldowns, or when other players change gear.
+* **OnUpdate GC Spike Fix:** Rewrote the modifier polling logic inside `HealBot_OnUpdate` to use boolean state tracking instead of dynamic string concatenation, eliminating a major source of garbage collection bloat while hovering over unit frames.
+* **Aura Scanning Optimization:** Refactored Debuff tracking (`HealBot_DebuffWatch`) to use native boolean values (`true`/`false`) instead of string comparisons (`"YES"`/`"NO"`). This improves performance inside the continuous aura scanning loops.
**v1.5**
* **Macro, Item, and Script Bindings:** Support for binding named macros, inventory items, and inline scripts (e.g. `/target`) directly to mouse clicks in the Spells tab. All of these now natively support implicit `@mouseover` targeting on the unit frame you click, without losing your current target.
From dd9f9886b4f96c4f939767b0adb0da28c02cb8d6 Mon Sep 17 00:00:00 2001
From: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com>
Date: Tue, 21 Jul 2026 09:02:33 +0200
Subject: [PATCH 09/12] feat: implement automatic skin swapping based on group
size and add horizontal grid layout options
---
HealBotBlue.toc | 1 +
HealBot_Data.lua | 10 +++
HealBot_Options.lua | 2 +
HealBot_Options.xml | 9 +++
HealBot_Options_Auto.lua | 79 ++++++++++++++++++++
HealBot_Options_Auto.xml | 152 ++++++++++++++++++++++++++++++++++++++
HealBot_Options_Skins.lua | 18 +++++
HealBot_Options_Skins.xml | 36 ++++++++-
HealBot_View_Layout.lua | 93 +++++++++++++++++++----
9 files changed, 385 insertions(+), 15 deletions(-)
create mode 100644 HealBot_Options_Auto.lua
create mode 100644 HealBot_Options_Auto.xml
diff --git a/HealBotBlue.toc b/HealBotBlue.toc
index 1713e79..cb73825 100644
--- a/HealBotBlue.toc
+++ b/HealBotBlue.toc
@@ -27,3 +27,4 @@ HealBot_Options_CDC.xml
HealBot_Options_Skins.xml
HealBot_Options_Buffs.xml
HealBot_Options_Chat.xml
+HealBot_Options_Auto.xml
diff --git a/HealBot_Data.lua b/HealBot_Data.lua
index a6fe2bf..e0a5377 100644
--- a/HealBot_Data.lua
+++ b/HealBot_Data.lua
@@ -181,7 +181,17 @@ HealBot_ConfigDefaults = {
Current_Skin = "Modern Flat",
Skin_ID = 1,
Skins = {"Modern Flat", HEALBOT_SKINS_STD, "HealBot Party", "HealBot Raid", "Alteric Valley"},
+ AutoSwap_Enabled = 0,
+ AutoSwap_Profiles = {
+ [1] = "Modern Flat", -- Solo
+ [2] = "HealBot Party", -- Party (2-5)
+ [3] = "HealBot Raid", -- Raid 15 (6-15)
+ [4] = "HealBot Raid", -- Raid 25 (16-25)
+ [5] = "HealBot Raid", -- Raid 40 (26-40)
+ },
numcols = {[HEALBOT_SKINS_STD] = 1, ["HealBot Party"] = 1, ["HealBot Raid"] = 4, ["Alteric Valley"] = 2, ["Modern Flat"] = 1},
+ bmaxrows = {[HEALBOT_SKINS_STD] = 0, ["HealBot Party"] = 0, ["HealBot Raid"] = 0, ["Alteric Valley"] = 0, ["Modern Flat"] = 0},
+ GridOrientation = {[HEALBOT_SKINS_STD] = 1, ["HealBot Party"] = 1, ["HealBot Raid"] = 1, ["Alteric Valley"] = 1, ["Modern Flat"] = 1},
btexture = {[HEALBOT_SKINS_STD] = 8,["HealBot Party"] = 6, ["HealBot Raid"] = 7, ["Alteric Valley"] = 9, ["Modern Flat"] = 10},
bcspace = {[HEALBOT_SKINS_STD] = 4, ["HealBot Party"] = 4, ["HealBot Raid"] = 2, ["Alteric Valley"] = 2, ["Modern Flat"] = 4},
brspace = {[HEALBOT_SKINS_STD] = 1, ["HealBot Party"] = 2, ["HealBot Raid"] = 2, ["Alteric Valley"] = 1, ["Modern Flat"] = 2},
diff --git a/HealBot_Options.lua b/HealBot_Options.lua
index 0a30e9c..f3ebf3e 100644
--- a/HealBot_Options.lua
+++ b/HealBot_Options.lua
@@ -314,6 +314,8 @@ function HealBot_Options_SetSkins()
HealBot_Options_BarHeightS:SetValue(HealBot_Config.bheight[HealBot_Config.Current_Skin])
HealBot_Options_BarWidthS:SetValue(HealBot_Config.bwidth[HealBot_Config.Current_Skin])
HealBot_Options_BarNumColsS:SetValue(HealBot_Config.numcols[HealBot_Config.Current_Skin])
+ HealBot_Options_BarMaxRowsS:SetValue(HealBot_Config.bmaxrows[HealBot_Config.Current_Skin] or 0)
+ HealBot_Options_GridOrientation:SetChecked((HealBot_Config.GridOrientation[HealBot_Config.Current_Skin] == 2) and 1 or nil)
HealBot_Options_BarBRSpaceS:SetValue(HealBot_Config.brspace[HealBot_Config.Current_Skin])
HealBot_Options_BarBCSpaceS:SetValue(HealBot_Config.bcspace[HealBot_Config.Current_Skin])
HealBot_Options_FramePaddingS:SetValue((HealBot_Config.bpadding and HealBot_Config.bpadding[HealBot_Config.Current_Skin]) or 10)
diff --git a/HealBot_Options.xml b/HealBot_Options.xml
index 31db38a..c2c12a2 100644
--- a/HealBot_Options.xml
+++ b/HealBot_Options.xml
@@ -206,6 +206,15 @@
+
-
-
+
HealBot_Options_OnLoad(this);
diff --git a/HealBot_Options_General.xml b/HealBot_Options_General.xml
index 0193047..0742fed 100644
--- a/HealBot_Options_General.xml
+++ b/HealBot_Options_General.xml
@@ -265,8 +265,38 @@
-
-
+
+
diff --git a/HealBot_Options_Skins.xml b/HealBot_Options_Skins.xml
index f8cb68a..fb8abf9 100644
--- a/HealBot_Options_Skins.xml
+++ b/HealBot_Options_Skins.xml
@@ -266,9 +266,9 @@
-
+
-
+
@@ -277,62 +277,14 @@
HealBot_Options_FramePaddingS_OnValueChanged(this)
-
-
-
-
-
-
-
-
-
-
-
-
- HealBot_Options_val_OnLoad(this,"Solid Border",1,10)
- HealBot_Options_BorderThicknessS_OnValueChanged(this)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- HealBot_Options_val_OnLoad(this,"Max Rows",0,40)
- HealBot_Options_BarMaxRowsS_OnValueChanged(this)
-
-
-
-
-
-
-
-
-
-
-
-
- getglobal(this:GetName().."Text"):SetText("Horizontal Grid");
-
-
- HealBot_Options_GridOrientation_OnClick(this);
-
-
-
+
-
+
@@ -409,6 +361,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ HealBot_Options_val_OnLoad(this,"Solid Border",1,10)
+ HealBot_Options_BorderThicknessS_OnValueChanged(this)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ HealBot_Options_val_OnLoad(this,"Max Rows",0,40)
+ HealBot_Options_BarMaxRowsS_OnValueChanged(this)
+
+
+
+
+
+
+
+
+
+
+
+
+ getglobal(this:GetName().."Text"):SetText("Horizontal Grid");
+
+
+ HealBot_Options_GridOrientation_OnClick(this);
+
+
+
+