19 Commits
Author SHA1 Message Date
Bluewhale1337 ee11884976 Merge pull request #21 from Bluewhale1337/dev
Dev
2026-09-24 22:34:31 +02:00
Bluewhale1337 eb7cbc52f2 refactor: mark all unit buttons dirty instead of calling HealBot_Action_Refresh 2026-09-24 22:31:24 +02:00
Bluewhale1337 1edb4b22bb fix: correct BuffWatchSelf UI element lookup and document the fix in README 2026-09-24 21:38:19 +02:00
Bluewhale1337 5e33429dee feat: add support for group-wide healing spell tracking and communication 2026-09-16 11:10:55 +02:00
Bluewhale1337 55bc6f1ea0 Fix: optimize execution performance and memory usage via caching and table reuse 2026-09-16 10:24:33 +02:00
Bluewhale1337 7f4d4be827 Fix: add pooling to rest of the tables out there 2026-09-13 20:39:46 +02:00
Bluewhale1337 029235a733 Merge branch 'dev' of https://github.com/Bluewhale1337/HealBotBlue into dev 2026-09-13 20:10:11 +02:00
Bluewhale1337 7beff1c4ca Fix: expand table pooling across modules to reduce garbage collection 2026-09-13 20:09:46 +02:00
Bluewhale1337 4e8d5d8426 Merge pull request #20 from Bluewhale1337/dev
Dev
2026-09-13 12:58:54 +02:00
Bluewhale1337 b40135a386 Merge branch 'main' into dev
Signed-off-by: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com>
2026-09-13 12:58:40 +02:00
Bluewhale1337 27ba0a386e chore: bump version to 1.7.2 and update changelog 2026-09-12 13:32:13 +02:00
Bluewhale1337 4caaa85634 Merge branch 'main' of https://github.com/Bluewhale1337/HealBotBlue 2026-09-12 12:26:16 +02:00
Bluewhale1337 8894700b0a fix: return nil instead of index when excluding forms from unshifting 2026-09-12 12:26:13 +02:00
Bluewhale1337 50a64c5549 fix: return nil instead of index when excluding forms from unshifting 2026-09-12 12:25:49 +02:00
Bluewhale1337 2958bc8e94 Update README.md
removed accidently added dev branch changelog from main
2026-09-11 08:16:52 +02:00
Bluewhale1337 4486682568 Update README.md
More fixes of broken formating

Signed-off-by: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com>
2026-09-09 20:51:09 +02:00
Bluewhale1337 27231aaf99 Update README.md
Signed-off-by: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com>
2026-09-09 20:50:36 +02:00
Bluewhale1337 bcd497104f docs: reorder change log entries in README to follow reverse chronological versioning 2026-09-09 19:02:28 +02:00
Bluewhale1337 ee4f706338 Merge pull request #19 from Bluewhale1337/main
Migrating hotfixes from main to dev
2026-09-09 18:54:15 +02:00
9 changed files with 146 additions and 49 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
## Interface: 11200 ## Interface: 11200
## Title: HealBotBlue ## Title: HealBotBlue
## Version: 1.7.1 ## Version: 1.7.3
## Author: Bluewhale ## Author: Bluewhale
## Notes: Raidframe replacement for healing, decursing, resource tracking and buffing with optional support for SuperWow, ClassicAPI, UnitXP_SP3 and Nampower. ## Notes: Raidframe replacement for healing, decursing, resource tracking and buffing with optional support for SuperWow, ClassicAPI, UnitXP_SP3 and Nampower.
## SavedVariablesPerCharacter: HealBot_Config ## SavedVariablesPerCharacter: HealBot_Config
+4 -2
View File
@@ -136,9 +136,10 @@ end
-- HealBot_SplitString: Internal utility: HealBot_SplitString -- HealBot_SplitString: Internal utility: HealBot_SplitString
function HealBot_SplitString(str, delimiter) function HealBot_SplitString(str, delimiter)
local result = {} local result = HealBot_GetTable()
if not delimiter or delimiter == "" then if not delimiter or delimiter == "" then
return {str} table.insert(result, str)
return result
end end
local start_pos = 1 local start_pos = 1
while true do while true do
@@ -160,6 +161,7 @@ function HealBot_RunMacroText(body)
ChatFrameEditBox:SetText(commands[i]) ChatFrameEditBox:SetText(commands[i])
ChatEdit_SendText(ChatFrameEditBox) ChatEdit_SendText(ChatFrameEditBox)
end end
HealBot_ReleaseTable(commands)
end end
-- HealBot_RunMacro: Internal utility: HealBot_RunMacro -- HealBot_RunMacro: Internal utility: HealBot_RunMacro
+8 -2
View File
@@ -41,6 +41,7 @@ function HealBot_CheckShamanWeaponBuff(spellName)
if not firstWord then return false end if not firstWord then return false end
HealBot_ScanTooltip:SetOwner(UIParent, "ANCHOR_NONE") HealBot_ScanTooltip:SetOwner(UIParent, "ANCHOR_NONE")
if not HealBot_ScanTooltip_Lines then HealBot_ScanTooltip_Lines = {} end
local slots = HealBot_GetTable() local slots = HealBot_GetTable()
if hasMainHandEnchant then table.insert(slots, 16) end if hasMainHandEnchant then table.insert(slots, 16) end
if hasOffHandEnchant then table.insert(slots, 17) end if hasOffHandEnchant then table.insert(slots, 17) end
@@ -49,7 +50,11 @@ function HealBot_CheckShamanWeaponBuff(spellName)
HealBot_ScanTooltip:ClearLines() HealBot_ScanTooltip:ClearLines()
HealBot_ScanTooltip:SetInventoryItem("player", slot) HealBot_ScanTooltip:SetInventoryItem("player", slot)
for i = 1, HealBot_ScanTooltip:NumLines() do 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 if textObj then
local text = textObj:GetText() local text = textObj:GetText()
if text and string.find(text, firstWord) then if text and string.find(text, firstWord) then
@@ -184,7 +189,7 @@ function HealBot_OnEvent_UnitAura(this, unit)
local iconCount = 0 local iconCount = 0
local i = 1; local i = 1;
HealBot_UnitDebuff[unit] = nil; HealBot_UnitDebuff[unit] = nil;
local trackedTextures = {} local trackedTextures = HealBot_GetTable()
while true do while true do
local debuff, tmp, debuff_type = UnitDebuff(unit, i, 1) local debuff, tmp, debuff_type = UnitDebuff(unit, i, 1)
@@ -301,5 +306,6 @@ function HealBot_OnEvent_UnitAura(this, unit)
-- Defer UI updates -- Defer UI updates
HealBot_View_DirtyUnits[unit] = true HealBot_View_DirtyUnits[unit] = true
HealBot_ReleaseTable(trackedTextures)
end end
end end
+6 -6
View File
@@ -69,11 +69,11 @@ function HealBot_OnUpdate(this, arg1)
local pending = HealBot_TargetRestorePending; local pending = HealBot_TargetRestorePending;
HealBot_TargetRestorePending = nil; HealBot_TargetRestorePending = nil;
HealBot_TargetRestoreTimer = 0; HealBot_TargetRestoreTimer = 0;
if pending.type == "enemy" then if pending == "enemy" then
TargetLastEnemy(); TargetLastEnemy();
elseif pending.type == "friend" then elseif pending == "friend" then
TargetLastTarget(); TargetLastTarget();
elseif pending.type == "clear" then elseif pending == "clear" then
ClearTarget(); ClearTarget();
end end
end end
@@ -112,11 +112,11 @@ function HealBot_OnUpdate(this, arg1)
-- Restore target logic -- Restore target logic
if pendingCast.targetEnemy then if pendingCast.targetEnemy then
HealBot_TargetRestorePending = { type = "enemy" } HealBot_TargetRestorePending = "enemy"
elseif pendingCast.oldTarget and pendingCast.oldTarget ~= UnitName(pendingCast.target) then elseif pendingCast.oldTarget and pendingCast.oldTarget ~= UnitName(pendingCast.target) then
HealBot_TargetRestorePending = { type = "friend" } HealBot_TargetRestorePending = "friend"
elseif not pendingCast.oldTarget then elseif not pendingCast.oldTarget then
HealBot_TargetRestorePending = { type = "clear" } HealBot_TargetRestorePending = "clear"
end end
HealBot_TargetRestoreTimer = 0 HealBot_TargetRestoreTimer = 0
end end
+103 -25
View File
@@ -3,6 +3,7 @@
HealBot_CastingSpell = nil; HealBot_CastingSpell = nil;
HealBot_CastingTarget = nil; HealBot_CastingTarget = nil;
HealBot_CastingGroupMembers = nil;
HealBot_TargetRestorePending = nil; HealBot_TargetRestorePending = nil;
HealBot_TargetRestoreTimer = 0; HealBot_TargetRestoreTimer = 0;
@@ -158,13 +159,52 @@ function HealBot_Process_HealValue(spell, target)
end end
local uname = UnitName(target) local uname = UnitName(target)
if uname then if uname then
HealBot_SendAddonMessage(HEALBOT_ADDON_ID, ">> " .. uname .. " <<=>> " .. HealBot_HealValue .. " << "); if not HealBot_CastingGroupMembers then HealBot_CastingGroupMembers = {} end
HealBot_SendAddonMessage("HealComm", "Heal/" .. uname .. "/" .. HealBot_HealValue .. "/1500/"); for i=1, table.getn(HealBot_CastingGroupMembers) do HealBot_CastingGroupMembers[i] = nil end
if not HealBot_HealsIn[uname] then table.setn(HealBot_CastingGroupMembers, 0)
HealBot_HealsIn[uname] = 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 end
HealBot_HealsIn[uname] = HealBot_HealsIn[uname] + HealBot_HealValue;
HealBot_RecalcHeals(HealBot_FindUnitID(uname));
end end
end end
end end
@@ -217,14 +257,24 @@ function HealBot_StopCasting()
if HealBot_HealValue > 0 then if HealBot_HealValue > 0 then
local uname = UnitName(HealBot_CastingTarget) local uname = UnitName(HealBot_CastingTarget)
if uname then if uname then
HealBot_SendAddonMessage(HEALBOT_ADDON_ID, ">> " .. uname .. " <<=>> " .. 0 - HealBot_HealValue .. " << "); if HealBot_CastingGroupMembers and table.getn(HealBot_CastingGroupMembers) > 1 then
HealBot_SendAddonMessage("HealComm", "Healstop"); HealBot_SendAddonMessage("HealComm", "GrpHealstop");
if HealBot_HealsIn[uname] then for _, memberName in ipairs(HealBot_CastingGroupMembers) do
HealBot_HealsIn[uname] = HealBot_HealsIn[uname] - HealBot_HealValue; HealBot_SendAddonMessage(HEALBOT_ADDON_ID, ">> " .. memberName .. " <<=>> " .. 0 - HealBot_HealValue .. " << ")
if HealBot_HealsIn[uname] < 0 then if HealBot_HealsIn[memberName] then
HealBot_HealsIn[uname] = 0; HealBot_HealsIn[memberName] = HealBot_HealsIn[memberName] - HealBot_HealValue;
end if HealBot_HealsIn[memberName] < 0 then HealBot_HealsIn[memberName] = 0; end
HealBot_RecalcHeals(HealBot_FindUnitID(uname)); 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
end end
HealBot_HealValue = 0; HealBot_HealValue = 0;
@@ -237,7 +287,7 @@ function HealBot_StopCasting()
local ag = HealBot_Config.babortcolg[HealBot_Config.Current_Skin] or 0.1; 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 ab = HealBot_Config.babortcolb[HealBot_Config.Current_Skin] or 0.5;
local aa = HealBot_Config.babortcola[HealBot_Config.Current_Skin] or 1; 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); bar:SetStatusBarColor(ar, ag, ab, 0);
local sr = HealBot_Config.btextdisbledcolr[HealBot_Config.Current_Skin]; local sr = HealBot_Config.btextdisbledcolr[HealBot_Config.Current_Skin];
local sg = HealBot_Config.btextdisbledcolg[HealBot_Config.Current_Skin]; local sg = HealBot_Config.btextdisbledcolg[HealBot_Config.Current_Skin];
@@ -303,7 +353,7 @@ function HealBot_CheckCasting(unit)
local sg = HealBot_Config.btextenabledcolg[HealBot_Config.Current_Skin]; local sg = HealBot_Config.btextenabledcolg[HealBot_Config.Current_Skin];
local sb = HealBot_Config.btextenabledcolb[HealBot_Config.Current_Skin]; local sb = HealBot_Config.btextenabledcolb[HealBot_Config.Current_Skin];
local sa = HealBot_Config.btextenabledcola[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); bar.txt:SetTextColor(sr, sg, sb, sa);
end end
end end
@@ -328,7 +378,15 @@ function HealBot_CastSpellOnFriend(spell, target)
if formCancelled then if formCancelled then
-- ALWAYS put the cast into the Pending queue so the OnUpdate loop can wait for the server -- 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". -- 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; return;
end end
@@ -339,11 +397,11 @@ function HealBot_CastSpellOnFriend(spell, target)
HealBot_StartCasting(spell, target, "direct"); HealBot_StartCasting(spell, target, "direct");
if targetEnemy then if targetEnemy then
HealBot_TargetRestorePending = { type = "enemy" }; HealBot_TargetRestorePending = "enemy";
elseif oldTarget and oldTarget ~= UnitName(target) then elseif oldTarget and oldTarget ~= UnitName(target) then
HealBot_TargetRestorePending = { type = "friend" }; HealBot_TargetRestorePending = "friend";
elseif not oldTarget then elseif not oldTarget then
HealBot_TargetRestorePending = { type = "clear" }; HealBot_TargetRestorePending = "clear";
end end
HealBot_TargetRestoreTimer = 0; HealBot_TargetRestoreTimer = 0;
end end
@@ -472,7 +530,7 @@ function HealBot_FindHealSpells()
end end
end); end);
local items = {}; local items = HealBot_GetTable();
for bag = 0, NUM_BAG_FRAMES do for bag = 0, NUM_BAG_FRAMES do
for slot = 1, GetContainerNumSlots(bag) do for slot = 1, GetContainerNumSlots(bag) do
local item = HealBot_GetItemName(bag, slot); local item = HealBot_GetItemName(bag, slot);
@@ -498,6 +556,7 @@ function HealBot_FindHealSpells()
HealBot_Heals["raidpet" .. i] = HealBot_Heals.party; HealBot_Heals["raidpet" .. i] = HealBot_Heals.party;
end end
HealBot_ReleaseTable(items);
if HealBot_CalcEquipBonus then if HealBot_CalcEquipBonus then
HealBot_AddDebug("...Done Equip Bonus:" .. RealHealing); HealBot_AddDebug("...Done Equip Bonus:" .. RealHealing);
end end
@@ -568,7 +627,15 @@ end
-- HealBot_RecalcHeals: Flags unit for visual refresh. -- HealBot_RecalcHeals: Flags unit for visual refresh.
function HealBot_RecalcHeals(unit) function HealBot_RecalcHeals(unit)
HealBot_Action_Refresh(unit); if unit then
HealBot_View_DirtyUnits[unit] = true;
else
if HealBot_Action_UnitButtons then
for u, _ in pairs(HealBot_Action_UnitButtons) do
HealBot_View_DirtyUnits[u] = true;
end
end
end
end end
-- HealBot_RecalcParty: Triggers group layout rebuild. -- HealBot_RecalcParty: Triggers group layout rebuild.
@@ -673,8 +740,15 @@ function HealBot_InitGetSpellData(spell, id, class)
_cast = 0; _cast = 0;
line = nil; 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 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 if lText and lText:IsVisible() and lText:GetText() then
local txt = lText:GetText(); local txt = lText:GetText();
local t1, t2, match; local t1, t2, match;
@@ -698,7 +772,11 @@ function HealBot_InitGetSpellData(spell, id, class)
end end
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 if rText and rText:IsVisible() and rText:GetText() then
local txt = rText:GetText(); local txt = rText:GetText();
local t1, t2, match; local t1, t2, match;
@@ -873,7 +951,7 @@ function HealBot_GetShapeshiftForm()
local icon_lower = string.lower(icon) local icon_lower = string.lower(icon)
-- Exclude non-standard/custom forms like Tree of Life from unshifting -- Exclude non-standard/custom forms like Tree of Life from unshifting
if not string.find(icon_lower, "humanoidform") and not string.find(icon_lower, "treeoflife") and not string.find(icon_lower, "healingway") and not string.find(icon_lower, "stoneclawtotem") then if not string.find(icon_lower, "humanoidform") and not string.find(icon_lower, "treeoflife") and not string.find(icon_lower, "healingway") and not string.find(icon_lower, "stoneclawtotem") then
return i; return nil;
end end
else else
return i; return i;
+5 -2
View File
@@ -44,7 +44,7 @@ function HealBot_Integrations_Toggle()
if not spellName then return end if not spellName then return end
if not HealBot_Nampower_Auras[target] then if not HealBot_Nampower_Auras[target] then
HealBot_Nampower_Auras[target] = {} HealBot_Nampower_Auras[target] = HealBot_GetTable()
end end
local expirationTime = GetTime() + (duration / 1000) local expirationTime = GetTime() + (duration / 1000)
@@ -61,7 +61,8 @@ function HealBot_Integrations_Toggle()
HealBot_Integrations_Nampower_Active = false; HealBot_Integrations_Nampower_Active = false;
HealBot_AddDebug("nampower Integration: DISABLED"); HealBot_AddDebug("nampower Integration: DISABLED");
if HealBot_Nampower_Auras then 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 HealBot_Nampower_Auras[k] = nil
end end
end end
@@ -76,6 +77,7 @@ function HealBot_Integrations_PruneNampower()
for targetName, auras in pairs(HealBot_Nampower_Auras) do for targetName, auras in pairs(HealBot_Nampower_Auras) do
-- Check if target is still in the raid/party -- Check if target is still in the raid/party
if not HealBot_Model:GetUnitIDByName(targetName) then if not HealBot_Model:GetUnitIDByName(targetName) then
HealBot_ReleaseTable(auras)
HealBot_Nampower_Auras[targetName] = nil HealBot_Nampower_Auras[targetName] = nil
else else
-- Prune expired auras -- Prune expired auras
@@ -88,6 +90,7 @@ function HealBot_Integrations_PruneNampower()
end end
end end
if not hasAuras then if not hasAuras then
HealBot_ReleaseTable(auras)
HealBot_Nampower_Auras[targetName] = nil HealBot_Nampower_Auras[targetName] = nil
end end
end end
+4 -3
View File
@@ -245,11 +245,12 @@ function HealBot_Model:PreserveStateByGUID()
for targetUnit, stateData in pairs(stateSwaps) do for targetUnit, stateData in pairs(stateSwaps) do
-- Deep copy to prevent memory aliasing -- Deep copy to prevent memory aliasing
if not self.units[targetUnit] then if not self.units[targetUnit] then
self.units[targetUnit] = { icons = {} } self.units[targetUnit] = HealBot_GetTable()
self.units[targetUnit].icons = HealBot_GetTable()
end end
local targetIcons = self.units[targetUnit].icons 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(targetIcons) do targetIcons[k] = nil end
for k in pairs(self.units[targetUnit]) do self.units[targetUnit][k] = nil end for k in pairs(self.units[targetUnit]) do self.units[targetUnit][k] = nil end
@@ -262,7 +263,7 @@ function HealBot_Model:PreserveStateByGUID()
self.units[targetUnit].icons = targetIcons self.units[targetUnit].icons = targetIcons
if HealBot_UnitIcons and iconSwaps[targetUnit] then 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 for j=1, 10 do
HealBot_UnitIcons[targetUnit][j] = iconSwaps[targetUnit][j] HealBot_UnitIcons[targetUnit][j] = iconSwaps[targetUnit][j]
end end
+6 -3
View File
@@ -857,8 +857,10 @@ function HealBot_Action_PartyChanged()
if i == last then break end if i == last then break end
end end
else else
local petUnits = { "pet", "partypet1", "partypet2", "partypet3", "partypet4" }; if not HealBot_PetUnits then
for _, unit in ipairs(petUnits) do 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 if not HealBot_Action_UnitButtons[unit] and HealBot_MayHeal(unit) then
i = i + 1; i = i + 1;
HealBot_Action_SetHealButton(i, unit); HealBot_Action_SetHealButton(i, unit);
@@ -1153,7 +1155,7 @@ end
function HealBot_Action_AppendNewUnits() function HealBot_Action_AppendNewUnits()
if not HealBot_Grid_LastI then return end if not HealBot_Grid_LastI then return end
local unitsToCheck = {} local unitsToCheck = HealBot_GetTable()
-- Gather units based on config, similar to PartyChanged -- Gather units based on config, similar to PartyChanged
if HealBot_Config.GroupHeals == 1 then if HealBot_Config.GroupHeals == 1 then
@@ -1220,4 +1222,5 @@ function HealBot_Action_AppendNewUnits()
HealBot_Action_AppendUnit(unit) HealBot_Action_AppendUnit(unit)
end end
end end
HealBot_ReleaseTable(unitsToCheck)
end end
+9 -5
View File
@@ -49,11 +49,11 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\
### Change Log ### Change Log
**v1.7.1** **v1.7.3**
* **Bug Fix - Shapeshift Auto-Unshift** - Fixed an issue where the shapeshift spell queue would incorrectly pull druids out of Tree of Life form . * **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().
* **Cleanup** - Removed deprecated `UPDATE_SHAPESHIFT_FORM` event listeners and `HealBot_UpdateShapeshiftForm` function to save CPU cycles. * **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** **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 - 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. * **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.
* **Bug Fix - Incoming Heals Comms** - Fixed a regex string parsing bug that caused incoming heals from other HealBot instances to drop if a unit's name contained non-alphabetic characters (e.g. dashes or spaces in pet names). * **Bug Fix - Incoming Heals Comms** - Fixed a regex string parsing bug that caused incoming heals from other HealBot instances to drop if a unit's name contained non-alphabetic characters (e.g. dashes or spaces in pet names).
@@ -61,6 +61,10 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\
* **UI Update - Raid Marks** - Anchored raid target icons to top of unit frames instead of center. * **UI Update - Raid Marks** - Anchored raid target icons to top of unit frames instead of center.
* **Bug Fix** - Fixed an issue where the debuff warning sound and UI message would spam repeatedly on every aura update. The warning now only plays once per unique dispellable debuff type applied to a unit. Increased warning trigger range to 40 yards. * **Bug Fix** - Fixed an issue where the debuff warning sound and UI message would spam repeatedly on every aura update. The warning now only plays once per unique dispellable debuff type applied to a unit. Increased warning trigger range to 40 yards.
**v1.7.1**
* **Bug Fix - Shapeshift Auto-Unshift** - Fixed an issue where the shapeshift spell queue would incorrectly pull druids out of Tree of Life form .
* **Cleanup** - Removed deprecated `UPDATE_SHAPESHIFT_FORM` event listeners and `HealBot_UpdateShapeshiftForm` function to save CPU cycles.
**v1.7.0** **v1.7.0**
* **Feature - Raid Marks** - Added tracking and display of raid marks on unit frames. * **Feature - Raid Marks** - Added tracking and display of raid marks on unit frames.
* **External Addon Integrations** - Added a new 'Extras' tab in Options to optionally enable integrations with `UnitXP_SP3` (for ultra-precise 3D range and Line of Sight checks), `nampower` (for accurate real-time heal/buff tracking), `SuperWoW` (for robust GUID-based state tracking), and `ClassicAPI` (for native +Healing bonuses and fast 3D distance checks). * **External Addon Integrations** - Added a new 'Extras' tab in Options to optionally enable integrations with `UnitXP_SP3` (for ultra-precise 3D range and Line of Sight checks), `nampower` (for accurate real-time heal/buff tracking), `SuperWoW` (for robust GUID-based state tracking), and `ClassicAPI` (for native +Healing bonuses and fast 3D distance checks).