38 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
Bluewhale1337 56b55f34ad Merge branch 'dev' into main
Signed-off-by: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com>
2026-09-09 18:53:27 +02:00
Bluewhale1337 135a8f6bcd fix: prevent incorrect druid unshifting from Tree of Life form and remove deprecated shapeshift event listeners 2026-09-09 18:43:50 +02:00
Bluewhale1337 7f5b1afe23 refactor: remove deprecated shapeshift form update logic and refine form detection criteria 2026-09-09 18:32:13 +02:00
Bluewhale1337 00a1ddf789 fix: prevent accidental unshifting while in Tree of Life or Healing Way forms 2026-09-09 17:32:38 +02:00
Bluewhale1337 74e940f41c fix: prevent shapeshift cancellation while in Tree of Life or Healing Way forms 2026-09-09 17:32:18 +02:00
Bluewhale1337 98b34f24b8 Fix: Exception for shapeshift queue to allow heals in tree form 2026-09-09 17:30:38 +02:00
Bluewhale1337 604a26dbb3 refactor: replace table.foreach with recursive deep copy functions for config defaults 2026-09-08 20:32:36 +02:00
Bluewhale1337 03114d4802 Merge pull request #18 from Bluewhale1337/main
refactor: simplify CDC monitor and emergency filter logic by updating…
2026-09-08 18:51:12 +02:00
Bluewhale1337 a0b6e2f72d refactor: simplify CDC monitor and emergency filter logic by updating configuration indices and cleaning up unused data structures 2026-09-07 23:45:46 +02:00
Bluewhale1337 7d910eadd2 refactor: implement table pooling and out-of-combat cleanup to reduce memory allocation overhead and garbage collection pressure 2026-09-06 23:22:43 +02:00
Bluewhale1337 1ef79cfcd1 Fix: implement table pooling for tables previously omitted and add garbage collection hooks to eliminate memory leaks and bloat 2026-09-06 23:22:33 +02:00
Bluewhale1337 1f9d3af81e refactor: update incoming heal tracking to support multiple targets and add resurrection event handling 2026-09-06 22:38:33 +02:00
Bluewhale1337 e9cfd2fcc7 Merge branch 'dev' of https://github.com/Bluewhale1337/HealBotBlue into dev 2026-09-06 22:20:30 +02:00
Bluewhale1337 7c45d85030 feature: implemented HealComm without using whole heavy library to sync for cross-addon compatibility while keeping legacy healbot protocol to sync with older versions also fix unit name regex parsing bugs 2026-09-06 22:20:26 +02:00
Bluewhale1337 92a4cb070a Merge pull request #17 from Bluewhale1337/main
Move .toc changes to dev
2026-09-06 19:59:35 +02:00
Bluewhale1337 2af99cbc2b Update HealBotBlue.toc
Updated #Notes section of .toc file

Signed-off-by: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com>
2026-09-06 19:58:39 +02:00
Bluewhale1337 ebb42f936a Fix: adjust raid icon anchor position to top of unit frames - they no longer hide behind player name 2026-09-06 15:34:04 +02:00
Bluewhale1337 04519b9631 Merge branch 'dev' of https://github.com/Bluewhale1337/HealBotBlue into dev 2026-09-06 11:55:27 +02:00
Bluewhale1337 3ebcecb8e6 fix: throttle debuff warnings to once per debuff type and increase detection range to 40 yards 2026-09-06 11:55:20 +02:00
15 changed files with 375 additions and 154 deletions
+2 -2
View File
@@ -1,8 +1,8 @@
## Interface: 11200
## Title: HealBotBlue
## Version: 1.7.0
## Version: 1.7.3
## Author: Bluewhale
## Notes: Adds panel with skinable bars for healing and decursive
## Notes: Raidframe replacement for healing, decursing, resource tracking and buffing with optional support for SuperWow, ClassicAPI, UnitXP_SP3 and Nampower.
## SavedVariablesPerCharacter: HealBot_Config
..\..\FrameXML\Fonts.xml
..\..\FrameXML\OptionsFrameTemplates.xml
+4 -2
View File
@@ -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
+1 -1
View File
@@ -50,7 +50,7 @@
<Texture name="$parentRaidIcon" file="Interface\TargetingFrame\UI-RaidTargetingIcons" hidden="true">
<Size><AbsDimension x="14" y="14"/></Size>
<Anchors>
<Anchor point="CENTER">
<Anchor point="TOP">
<Offset><AbsDimension x="0" y="0"/></Offset>
</Anchor>
</Anchors>
+24 -12
View File
@@ -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
@@ -159,6 +164,7 @@ local HealBot_TrackedHoTs = {
}
local HealBot_DebuffTypeMap = nil
local HealBot_AuraWarningPlayed = {}
-- HealBot_OnEvent_UnitAura: Updates debuff lists and icon textures on aura change.
function HealBot_OnEvent_UnitAura(this, unit)
@@ -183,7 +189,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)
@@ -276,24 +282,30 @@ function HealBot_OnEvent_UnitAura(this, unit)
end
if HealBot_UnitDebuff[unit] then
if DebuffType and HealBot_Range_Check(unit, 27) == 1 then
if HealBot_Config.ShowDebuffWarning == 1 then
local color = HealBot_Config.CDCBarColour[DebuffType]
local r, g, b = 1, 0, 0
if color then
r, g, b = color.R, color.G, color.B
if DebuffType and HealBot_Range_Check(unit, 40) == 1 then
if HealBot_AuraWarningPlayed[unit] ~= DebuffType then
HealBot_AuraWarningPlayed[unit] = DebuffType
if HealBot_Config.ShowDebuffWarning == 1 then
local color = HealBot_Config.CDCBarColour[DebuffType]
local r, g, b = 1, 0, 0
if color then
r, g, b = color.R, color.G, color.B
end
UIErrorsFrame:AddMessage(UnitName(unit) .. " suffers from " .. DebuffType,
r, g, b,
1, UIERRORS_HOLD_TIME);
end
UIErrorsFrame:AddMessage(UnitName(unit) .. " suffers from " .. DebuffType,
r, g, b,
1, UIERRORS_HOLD_TIME);
if HealBot_Config.SoundDebuffWarning == 1 then HealBot_PlaySound(HealBot_Config.SoundDebuffPlay); end
end
if HealBot_Config.SoundDebuffWarning == 1 then HealBot_PlaySound(HealBot_Config.SoundDebuffPlay); end
end
else
HealBot_AuraWarningPlayed[unit] = nil
end
-- Check buffs synchronously because tooltip scanning fails in OnUpdate
HealBot_CheckBuffs(unit)
-- Defer UI updates
HealBot_View_DirtyUnits[unit] = true
HealBot_ReleaseTable(trackedTextures)
end
end
+102 -16
View File
@@ -71,33 +71,119 @@ function HealBot_SendAddonMessage(prefix, text)
end
end
-- HealBot_OnEvent_AddonMsg: Parses incoming heal data from other clients.
function HealBot_OnEvent_AddonMsg(this, addon_id, inc_msg, dist_target, sender_id)
if addon_id == HEALBOT_ADDON_ID then
local tmpTest, unitname, heal_val
tmpTest, tmpTest, unitname, heal_val = string.find(inc_msg, ">> (%a+) <<=>> (.%d+) <<" );
if heal_val then
if sender_id == UnitName("player") then return end
if not HealBot_HealsIn[unitname] then
HealBot_HealsIn[unitname] = 0;
if not HealBot_IncomingHealers then HealBot_IncomingHealers = {} end
-- Reusable global array for gfind string splitting
if not HealBot_Comms_Args then HealBot_Comms_Args = {} end
local function ClearIncomingHeal(sender)
local data = HealBot_IncomingHealers[sender]
if not data then return end
local oldAmount = data.amount
for i=1, 5 do
local oldTarget = data.targets[i]
if oldTarget then
if HealBot_HealsIn[oldTarget] then
HealBot_HealsIn[oldTarget] = HealBot_HealsIn[oldTarget] - oldAmount
if HealBot_HealsIn[oldTarget] < 0 then HealBot_HealsIn[oldTarget] = 0 end
HealBot_RecalcHeals(HealBot_FindUnitID(oldTarget))
end
HealBot_Healers[sender_id] = ">> " .. unitname .. " <<=>> " .. heal_val .. " <<";
HealBot_HealsIn[unitname] = HealBot_HealsIn[unitname] + tonumber(heal_val);
if tonumber(heal_val) > 0 then
HealBot_RecalcHeals(HealBot_FindUnitID(unitname))
elseif HealBot_HealsIn[unitname] < 0 then
HealBot_HealsIn[unitname] = 0;
data.targets[i] = nil
end
end
data.amount = 0
end
local function SetIncomingHeal(sender, amount, protocol, t1, t2, t3, t4, t5)
-- prioritize HealComm over HealBot protocol to avoid double-counting
if HealBot_IncomingHealers[sender] and HealBot_IncomingHealers[sender].protocol == "HealComm" and protocol == "HealBot" then
return
end
if not HealBot_IncomingHealers[sender] then
HealBot_IncomingHealers[sender] = { targets = {}, amount = 0, protocol = protocol }
end
ClearIncomingHeal(sender)
local data = HealBot_IncomingHealers[sender]
data.protocol = protocol
if amount > 0 and t1 then
data.amount = amount
data.targets[1] = t1
data.targets[2] = t2
data.targets[3] = t3
data.targets[4] = t4
data.targets[5] = t5
for i=1, 5 do
local target = data.targets[i]
if target then
if not HealBot_HealsIn[target] then HealBot_HealsIn[target] = 0 end
HealBot_HealsIn[target] = HealBot_HealsIn[target] + amount
HealBot_RecalcHeals(HealBot_FindUnitID(target))
end
end
end
end
-- HealBot_OnEvent_AddonMsg: Parses incoming heal data from other clients.
function HealBot_OnEvent_AddonMsg(this, addon_id, inc_msg, dist_target, sender_id)
if sender_id == UnitName("player") then return end
if addon_id == "HealComm" then
-- Clear reusable args array
for i=1, 10 do HealBot_Comms_Args[i] = nil end
local argCount = 0
for word in string.gfind(inc_msg, "[^/]+") do
argCount = argCount + 1
HealBot_Comms_Args[argCount] = word
end
local cmd = HealBot_Comms_Args[1]
if cmd == "Heal" and HealBot_Comms_Args[2] and HealBot_Comms_Args[3] then
SetIncomingHeal(sender_id, tonumber(HealBot_Comms_Args[3]) or 0, "HealComm", HealBot_Comms_Args[2])
elseif cmd == "Healstop" then
SetIncomingHeal(sender_id, 0, "HealComm")
elseif cmd == "GrpHeal" and HealBot_Comms_Args[2] then
SetIncomingHeal(sender_id, tonumber(HealBot_Comms_Args[2]) or 0, "HealComm", HealBot_Comms_Args[4], HealBot_Comms_Args[5], HealBot_Comms_Args[6], HealBot_Comms_Args[7], HealBot_Comms_Args[8])
elseif cmd == "GrpHealstop" then
SetIncomingHeal(sender_id, 0, "HealComm")
elseif cmd == "Resurrection" then
if HealBot_Comms_Args[2] == "stop" then
HealBot_AddDebug(sender_id .. " Stopped ressing");
for unit, resser in pairs(HealBot_Ressing) do
if resser == sender_id then
HealBot_Ressing[unit] = nil;
HealBot_RecalcHeals(HealBot_FindUnitID(unit));
end
end
elseif HealBot_Comms_Args[2] and HealBot_Comms_Args[3] == "start" then
HealBot_AddDebug(sender_id .. " is ressing " .. HealBot_Comms_Args[2]);
HealBot_Ressing[HealBot_Comms_Args[2]] = sender_id;
HealBot_RecalcHeals(HealBot_FindUnitID(HealBot_Comms_Args[2]));
end
end
elseif addon_id == HEALBOT_ADDON_ID then
local tmpTest, tmpTest, unitname, heal_val = string.find(inc_msg, ">> (.-) <<=>> (.-) <<" );
if heal_val and unitname then
local amount = tonumber(heal_val) or 0
if amount < 0 then amount = 0 end -- HealBot sends negative to cancel
SetIncomingHeal(sender_id, amount, "HealBot", unitname)
end
elseif addon_id == "HealBot" then
local tmpTest, datatype, datamsg, sender
local PName = UnitName("player");
tmpTest, tmpTest, datatype, sender, datamsg = string.find(inc_msg, ">> (%a+) <<=>> (%a+) <<=>> (.+)");
tmpTest, tmpTest, datatype, sender, datamsg = string.find(inc_msg, ">> (.-) <<=>> (.-) <<=>> (.+)");
if datatype == "RequestVersion" then
HealBot_SendAddonMessage("HealBot", ">> SendVersion <<=>> " .. sender .. " <<=>> Version=" .. HEALBOT_VERSION);
elseif datatype == "SendVersion" and PName == sender then
HealBot_AddChat(sender_id .. ": " .. datamsg);
end
elseif addon_id == "CTRA" then
if ( string.sub(inc_msg, 1, 3) == "RES" ) then
if ( inc_msg == "RESNO" ) then
+29 -28
View File
@@ -3,6 +3,8 @@
HealBot_View_DirtyUnits = {}
HealBot_View_DirtyPower = {}
local unitsToRefresh = {}
local powerToRefresh = {}
local HealBot_Timer1, HealsIn_Timer = 0, 0;
HealBot_LastModState = ""
@@ -67,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
@@ -110,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
@@ -152,7 +154,7 @@ function HealBot_OnUpdate(this, arg1)
end
-- Process Dirty Queue for MVC View
local unitsToRefresh = {}
for k in pairs(unitsToRefresh) do unitsToRefresh[k] = nil end
for unitID in pairs(HealBot_View_DirtyUnits) do
unitsToRefresh[unitID] = true
HealBot_View_DirtyUnits[unitID] = nil
@@ -162,7 +164,7 @@ function HealBot_OnUpdate(this, arg1)
HealBot_Action_Refresh(unitID)
end
local powerToRefresh = {}
for k in pairs(powerToRefresh) do powerToRefresh[k] = nil end
for unitID in pairs(HealBot_View_DirtyPower) do
powerToRefresh[unitID] = true
HealBot_View_DirtyPower[unitID] = nil
@@ -298,9 +300,6 @@ local HealBot_EventHandlers = {
["PLAYER_ENTERING_WORLD"] = function(this)
HealBot_Model:RefreshUnit("player")
HealBot_Model:RefreshUnit("pet")
if HealBot_UnitClass("player") == "DRUID" then
HealBot_UpdateShapeshiftForm()
end
HealBot_OnEvent_PlayerEnteringWorld(this)
end,
["VARIABLES_LOADED"] = function(this)
@@ -329,9 +328,7 @@ local HealBot_EventHandlers = {
HealBot_OnEvent_PlayerEquipmentChanged2(this, arg1)
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,
["UPDATE_SHAPESHIFT_FORMS"] = function(this) HealBot_UpdateShapeshiftForm() end
["SPELLS_CHANGED"] = function(this, arg1) HealBot_OnEvent_SpellsChanged(this, arg1) end
}
-- HealBot_OnEvent: Event dispatcher for WoW UI events.
@@ -348,18 +345,19 @@ end
function HealBot_OnEvent_VariablesLoaded(this)
local class = HealBot_UnitClass("player")
table.foreach(HealBot_ConfigDefaults, function (key, val)
if not HealBot_Config[key] then
HealBot_Config[key] = val;
end
if type(val) == "table" and type(HealBot_Config[key]) == "table" then
for k, v in pairs(val) do
if HealBot_Config[key][k] == nil then
HealBot_Config[key][k] = v
local function DeepCopyMissing(src, dest)
for k, v in pairs(src) do
if type(v) == "table" then
if type(dest[k]) ~= "table" then dest[k] = {} end
DeepCopyMissing(v, dest[k])
else
if dest[k] == nil then
dest[k] = v
end
end
end
end);
end
DeepCopyMissing(HealBot_ConfigDefaults, HealBot_Config)
local foundModern = false
if HealBot_Config.Skins then
@@ -420,11 +418,6 @@ function HealBot_OnEvent_VariablesLoaded(this)
this:RegisterEvent("CHAT_MSG_ADDON");
this:RegisterEvent("CHAT_MSG_SYSTEM");
this:RegisterEvent("PLAYER_ENTERING_WORLD");
if class == "DRUID" then
this:RegisterEvent("UPDATE_SHAPESHIFT_FORM");
this:RegisterEvent("UPDATE_SHAPESHIFT_FORMS");
HealBot_UpdateShapeshiftForm();
end
HealBot_SpellsInitFlag = 2;
end
end
@@ -490,6 +483,14 @@ end
function HealBot_OnEvent_PlayerRegenEnabled(this)
HealBot_IsFighting = false;
HealBot_Delay_RecalcParty = 1;
if HealBot_IncomingHealers then
for sender, data in pairs(HealBot_IncomingHealers) do
if not HealBot_FindUnitID(sender) then
HealBot_IncomingHealers[sender] = nil
end
end
end
end
-- HealBot_OnEvent_PlayerTargetChanged: Internal utility: HealBot_OnEvent_PlayerTargetChanged
+113 -27
View File
@@ -3,6 +3,7 @@
HealBot_CastingSpell = nil;
HealBot_CastingTarget = nil;
HealBot_CastingGroupMembers = nil;
HealBot_TargetRestorePending = nil;
HealBot_TargetRestoreTimer = 0;
@@ -158,12 +159,52 @@ function HealBot_Process_HealValue(spell, target)
end
local uname = UnitName(target)
if uname then
HealBot_SendAddonMessage(HEALBOT_ADDON_ID, ">> " .. uname .. " <<=>> " .. HealBot_HealValue .. " << ");
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
@@ -216,13 +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 .. " << ");
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;
@@ -235,7 +287,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];
@@ -301,7 +353,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
@@ -326,7 +378,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
@@ -337,11 +397,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
@@ -470,7 +530,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);
@@ -496,6 +556,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
@@ -566,7 +627,15 @@ 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
if HealBot_Action_UnitButtons then
for u, _ in pairs(HealBot_Action_UnitButtons) do
HealBot_View_DirtyUnits[u] = true;
end
end
end
end
-- HealBot_RecalcParty: Triggers group layout rebuild.
@@ -671,8 +740,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;
@@ -696,7 +772,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;
@@ -857,10 +937,7 @@ function HealBot_Generic_Patten(matchStr, matchPattern)
return tmpTest, _HealsMin, _HealsMax;
end
-- HealBot_UpdateShapeshiftForm: Called on UPDATE_SHAPESHIFT_FORM
function HealBot_UpdateShapeshiftForm()
-- Deprecated
end
-- HealBot_GetShapeshiftForm: Detects active druid form to prevent invalid casts.
function HealBot_GetShapeshiftForm()
@@ -870,9 +947,18 @@ function HealBot_GetShapeshiftForm()
for i=1,forms do
local icon,name,active = GetShapeshiftFormInfo(i);
if active then
return i;
if icon then
local icon_lower = string.lower(icon)
-- 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
return nil;
end
else
return i;
end
end
end
end
return nil;
end
-5
View File
@@ -264,11 +264,6 @@ HealBot_ConfigDefaults = {
HealBot_Config = {};
--HealBot_EmergIncMelee = {};
--HealBot_EmergIncRange = {};
--HealBot_EmergIncHealers = {};
--HealBot_EmergIncCustom = {};
--HealBot_KeyCombo = {};
HealBot_HealsIn = {};
HealBot_Healers = {};
HealBot_UnitDebuff = {};
+22 -17
View File
@@ -36,22 +36,24 @@ function HealBot_Integrations_Toggle()
HealBot_NampowerFrame:RegisterEvent("AURA_CAST_ON_OTHER")
HealBot_NampowerFrame:SetScript("OnEvent", function()
if not HealBot_Integrations_Nampower_Active then return end
local spellID, caster, target, _, _, _, _, duration = arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8
if not caster or not target or duration <= 0 then return end
local spellName = GetSpellRecField(spellID, "name")
if not spellName then return end
if not HealBot_Nampower_Auras[target] then
HealBot_Nampower_Auras[target] = {}
end
local expirationTime = GetTime() + (duration / 1000)
HealBot_Nampower_Auras[target][spellName] = expirationTime
local unitID = HealBot_Model:GetUnitIDByName(target)
if unitID then
HealBot_OnEvent_UnitAura(nil, unitID)
if event == "AURA_CAST_ON_SELF" or event == "AURA_CAST_ON_OTHER" then
local spellID, caster, target, _, _, _, _, duration = arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8
if not caster or not target or duration <= 0 then return end
local spellName = GetSpellRecField(spellID, "name")
if not spellName then return end
if not HealBot_Nampower_Auras[target] then
HealBot_Nampower_Auras[target] = HealBot_GetTable()
end
local expirationTime = GetTime() + (duration / 1000)
HealBot_Nampower_Auras[target][spellName] = expirationTime
local unitID = HealBot_Model:GetUnitIDByName(target)
if unitID then
HealBot_OnEvent_UnitAura(nil, unitID)
end
end
end)
end
@@ -59,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
@@ -74,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
@@ -86,6 +90,7 @@ function HealBot_Integrations_PruneNampower()
end
end
if not hasAuras then
HealBot_ReleaseTable(auras)
HealBot_Nampower_Auras[targetName] = nil
end
end
+36 -11
View File
@@ -1,6 +1,13 @@
-- HealBot_Model.lua
-- Centralized Data Store and Observer System for HealBotBlue
local pool_oldGUIDs = {}
local pool_newUnitForGUID = {}
local pool_stateSwaps = {}
local pool_iconSwaps = {}
local pool_missingBuffSwaps = {}
local pool_debuffSwaps = {}
-- Safe local wrappers to prevent native UIDropDownMenu concatenation crashes
-- when setting selected values on closed dropdowns during initialization.
function HealBot_UIDropDownMenu_SetSelectedID(frame, id, useValue)
@@ -180,14 +187,16 @@ end
function HealBot_Model:PreserveStateByGUID()
if not (HealBot_Integrations_SuperWoW_Active or HealBot_Integrations_ClassicAPI_Active) or not HealBot_GetUnitGUID then return end
local oldGUIDs = {}
for k in pairs(pool_oldGUIDs) do pool_oldGUIDs[k] = nil end
local oldGUIDs = pool_oldGUIDs
for unit, guid in pairs(self.unitGUIDs) do
if string.find(unit, "^party") or string.find(unit, "^raid") or unit == "player" or unit == "pet" then
oldGUIDs[unit] = guid
end
end
local newUnitForGUID = {}
for k in pairs(pool_newUnitForGUID) do pool_newUnitForGUID[k] = nil end
local newUnitForGUID = pool_newUnitForGUID
-- Scan the new roster
for _, unit in ipairs(self.partyMembers) do
local guid = HealBot_GetUnitGUID(unit)
@@ -206,10 +215,14 @@ function HealBot_Model:PreserveStateByGUID()
end
end
local stateSwaps = {}
local iconSwaps = {}
local missingBuffSwaps = {}
local debuffSwaps = {}
for k in pairs(pool_stateSwaps) do pool_stateSwaps[k] = nil end
local stateSwaps = pool_stateSwaps
for k in pairs(pool_iconSwaps) do pool_iconSwaps[k] = nil end
local iconSwaps = pool_iconSwaps
for k in pairs(pool_missingBuffSwaps) do pool_missingBuffSwaps[k] = nil end
local missingBuffSwaps = pool_missingBuffSwaps
for k in pairs(pool_debuffSwaps) do pool_debuffSwaps[k] = nil end
local debuffSwaps = pool_debuffSwaps
for oldUnit, guid in pairs(oldGUIDs) do
local newUnit = newUnitForGUID[guid]
@@ -231,14 +244,26 @@ function HealBot_Model:PreserveStateByGUID()
for targetUnit, stateData in pairs(stateSwaps) do
-- Deep copy to prevent memory aliasing
self.units[targetUnit] = {}
for k, v in pairs(stateData) do
self.units[targetUnit][k] = v
if not self.units[targetUnit] then
self.units[targetUnit] = HealBot_GetTable()
self.units[targetUnit].icons = HealBot_GetTable()
end
self.units[targetUnit].icons = {}
local targetIcons = self.units[targetUnit].icons
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
for k, v in pairs(stateData) do
if k ~= "icons" then
self.units[targetUnit][k] = v
end
end
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
+12 -4
View File
@@ -234,10 +234,18 @@ end
-- HealBot_Options_Defaults_OnClick: UI handler for OnClick options panel.
function HealBot_Options_Defaults_OnClick(this)
HealBot_Options_CastNotify_OnClick(nil,0);
-- HealBot_Config = HealBot_ConfigDefaults;
table.foreach(HealBot_ConfigDefaults, function (key,val)
HealBot_Config[key] = val;
end);
HealBot_Config = {}
local function DeepCopy(src, dest)
for k, v in pairs(src) do
if type(v) == "table" then
dest[k] = {}
DeepCopy(v, dest[k])
else
dest[k] = v
end
end
end
DeepCopy(HealBot_ConfigDefaults, HealBot_Config)
HealBot_Options_OnShow(HealBot_Options);
HealBot_RecalcSpells();
HealBot_Action_Reset();
+7 -25
View File
@@ -45,9 +45,9 @@ function HealBot_WarningSound_OnClick(this,id)
end
-- HealBot_Options_CDCMonitor_DropDown: UI handler for DropDown options panel.
function HealBot_Options_CDCMonitor_DropDown()
for i=1, getn(HealBot_Options_CDCMonitor_List), 1 do
for i=1, getn(HealBot_Options_EmergencyFilter_List), 1 do
local info = {};
info.text = HealBot_Options_CDCMonitor_List[i];
info.text = HealBot_Options_EmergencyFilter_List[i];
info.func = HealBot_Options_CDCMonitor_OnSelect;
UIDropDownMenu_AddButton(info);
end
@@ -85,7 +85,7 @@ function HealBot_Options_CDCMonitor_Reset()
HealBot_CDCInc[HEALBOT_SHAMAN] = 0;
HealBot_CDCInc[HEALBOT_WARLOCK] = 0;
HealBot_CDCInc[HEALBOT_WARRIOR] = 0;
if HealBot_Config.CDCMonitor==2 then
if HealBot_Config.CDCMonitor==1 then
HealBot_CDCInc[HEALBOT_DRUID] = 1;
HealBot_CDCInc[HEALBOT_HUNTER] = 1;
HealBot_CDCInc[HEALBOT_MAGE] = 1;
@@ -95,25 +95,7 @@ function HealBot_Options_CDCMonitor_Reset()
HealBot_CDCInc[HEALBOT_SHAMAN] = 1;
HealBot_CDCInc[HEALBOT_WARLOCK] = 1;
HealBot_CDCInc[HEALBOT_WARRIOR] = 1;
elseif HealBot_Config.CDCMonitor==3 then
HealBot_CDCInc[HEALBOT_DRUID] = 1;
elseif HealBot_Config.CDCMonitor==4 then
HealBot_CDCInc[HEALBOT_HUNTER] = 1;
elseif HealBot_Config.CDCMonitor==5 then
HealBot_CDCInc[HEALBOT_MAGE] = 1;
elseif HealBot_Config.CDCMonitor==6 then
HealBot_CDCInc[HEALBOT_PALADIN] = 1;
elseif HealBot_Config.CDCMonitor==7 then
HealBot_CDCInc[HEALBOT_PRIEST] = 1;
elseif HealBot_Config.CDCMonitor==8 then
HealBot_CDCInc[HEALBOT_ROGUE] = 1;
elseif HealBot_Config.CDCMonitor==9 then
HealBot_CDCInc[HEALBOT_SHAMAN] = 1;
elseif HealBot_Config.CDCMonitor==10 then
HealBot_CDCInc[HEALBOT_WARLOCK] = 1;
elseif HealBot_Config.CDCMonitor==11 then
HealBot_CDCInc[HEALBOT_WARRIOR] = 1;
elseif HealBot_Config.CDCMonitor==12 then
elseif HealBot_Config.CDCMonitor==2 then
HealBot_CDCInc[HEALBOT_DRUID] = HealBot_Config.EmergIncMelee[HEALBOT_DRUID];
HealBot_CDCInc[HEALBOT_HUNTER] = HealBot_Config.EmergIncMelee[HEALBOT_HUNTER];
HealBot_CDCInc[HEALBOT_MAGE] = HealBot_Config.EmergIncMelee[HEALBOT_MAGE];
@@ -123,7 +105,7 @@ function HealBot_Options_CDCMonitor_Reset()
HealBot_CDCInc[HEALBOT_SHAMAN] = HealBot_Config.EmergIncMelee[HEALBOT_SHAMAN];
HealBot_CDCInc[HEALBOT_WARLOCK] = HealBot_Config.EmergIncMelee[HEALBOT_WARLOCK];
HealBot_CDCInc[HEALBOT_WARRIOR] = HealBot_Config.EmergIncMelee[HEALBOT_WARRIOR];
elseif HealBot_Config.CDCMonitor==13 then
elseif HealBot_Config.CDCMonitor==3 then
HealBot_CDCInc[HEALBOT_DRUID] = HealBot_Config.EmergIncRange[HEALBOT_DRUID];
HealBot_CDCInc[HEALBOT_HUNTER] = HealBot_Config.EmergIncRange[HEALBOT_HUNTER];
HealBot_CDCInc[HEALBOT_MAGE] = HealBot_Config.EmergIncRange[HEALBOT_MAGE];
@@ -133,7 +115,7 @@ function HealBot_Options_CDCMonitor_Reset()
HealBot_CDCInc[HEALBOT_SHAMAN] = HealBot_Config.EmergIncRange[HEALBOT_SHAMAN];
HealBot_CDCInc[HEALBOT_WARLOCK] = HealBot_Config.EmergIncRange[HEALBOT_WARLOCK];
HealBot_CDCInc[HEALBOT_WARRIOR] = HealBot_Config.EmergIncRange[HEALBOT_WARRIOR];
elseif HealBot_Config.CDCMonitor==14 then
elseif HealBot_Config.CDCMonitor==4 then
HealBot_CDCInc[HEALBOT_DRUID] = HealBot_Config.EmergIncHealers[HEALBOT_DRUID];
HealBot_CDCInc[HEALBOT_HUNTER] = HealBot_Config.EmergIncHealers[HEALBOT_HUNTER];
HealBot_CDCInc[HEALBOT_MAGE] = HealBot_Config.EmergIncHealers[HEALBOT_MAGE];
@@ -143,7 +125,7 @@ function HealBot_Options_CDCMonitor_Reset()
HealBot_CDCInc[HEALBOT_SHAMAN] = HealBot_Config.EmergIncHealers[HEALBOT_SHAMAN];
HealBot_CDCInc[HEALBOT_WARLOCK] = HealBot_Config.EmergIncHealers[HEALBOT_WARLOCK];
HealBot_CDCInc[HEALBOT_WARRIOR] = HealBot_Config.EmergIncHealers[HEALBOT_WARRIOR];
elseif HealBot_Config.CDCMonitor==15 then
elseif HealBot_Config.CDCMonitor==5 then
HealBot_CDCInc[HEALBOT_DRUID] = HealBot_Config.EmergIncCustom[HEALBOT_DRUID];
HealBot_CDCInc[HEALBOT_HUNTER] = HealBot_Config.EmergIncCustom[HEALBOT_HUNTER];
HealBot_CDCInc[HEALBOT_MAGE] = HealBot_Config.EmergIncCustom[HEALBOT_MAGE];
+1 -1
View File
@@ -102,7 +102,7 @@ function HealBot_Options_EFClass_OnClick(this)
HealBot_Config.EmergIncCustom[HEALBOT_WARLOCK] = HealBot_Options_EFClassWarlock:GetChecked() or 0;
HealBot_Config.EmergIncCustom[HEALBOT_WARRIOR] = HealBot_Options_EFClassWarrior:GetChecked() or 0;
end
if HealBot_Config.EmergIncMonitor>10 then
if HealBot_Config.EmergIncMonitor > 1 then
HealBot_Action_PartyChanged();
end
end
+6 -3
View File
@@ -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);
@@ -1153,7 +1155,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 +1222,5 @@ function HealBot_Action_AppendNewUnits()
HealBot_Action_AppendUnit(unit)
end
end
HealBot_ReleaseTable(unitsToCheck)
end
+16
View File
@@ -49,6 +49,22 @@ 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().
* **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.
* **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).
* **Feature - Standard HealComm Sync** - Implemented lightweight parsing of the standard `HealComm` addon channel. HealBot now perfectly syncs incoming heals with modern raid frames like Luna, Grid, and pfUI, while retaining backwards compatibility with older versions of HealBot.
* **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.
**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**
* **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).