32 Commits

Author SHA1 Message Date
Bluewhale1337 d36ad994ea feat: add support for dynamic unit appending during combat and improve layout handling 2026-07-22 09:20:22 +02:00
Bluewhale1337 a3f3d9e4c6 feat: expand unit capacity to 100 buttons and add RAID_ROSTER_UPDATE event handling 2026-07-21 22:46:14 +02:00
Bluewhale1337 2b1ccb03c5 hotfix: add pet frame color support and update documentation with latest feature set 2026-07-21 19:01:34 +02:00
Bluewhale1337 bbff4a461c Merge branch 'dev' of https://github.com/Bluewhale1337/HealBotBlue into dev 2026-07-21 13:51:55 +02:00
Bluewhale1337 40ad96ae07 bump version to 1.6.0 in HealBotBlue.toc 2026-07-21 13:51:51 +02:00
Bluewhale1337 611f584b8d docs: update version to v1.6 in changelog 2026-07-21 13:50:07 +02:00
Bluewhale1337 9fd6f47946 Merge pull request #8 from Bluewhale1337/main
Hotfix merge
2026-07-21 13:44:13 +02:00
Bluewhale1337 1f339a8da5 Merge branch 'dev' into main
Signed-off-by: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com>
2026-07-21 13:40:02 +02:00
Bluewhale1337 00f9c3d485 fix(ui): center text, fix menu overlap, relabel extra to raid (hotfix 1.5.1) 2026-07-21 13:28:55 +02:00
Bluewhale1337 41e4a15075 feat: read version dynamically from TOC file 2026-07-21 13:26:43 +02:00
Bluewhale1337 026d4093aa refactor: optimize event processing, move global UI buttons, and reorganize options layout 2026-07-21 11:21:35 +02:00
Bluewhale1337 db07c467a3 chore: dynamically fetch version from add-on metadata instead of hardcoding 2026-07-21 09:31:55 +02:00
Bluewhale1337 c47d17f790 feat: implement auto-swap profile system and add safety null checks for skin configuration data 2026-07-21 09:29:44 +02:00
Bluewhale1337 dd9f9886b4 feat: implement automatic skin swapping based on group size and add horizontal grid layout options 2026-07-21 09:02:33 +02:00
Bluewhale1337 85ad55c1cb perf: optimize CPU and memory usage via boolean state tracking, event filtering, and per-character SavedVariables. 2026-07-20 23:22:15 +02:00
Bluewhale1337 441a45150f feat: add Spell_Holy_AshesToAshes icon and implement debuff tracking loop in UnitAura handler 2026-07-20 18:13:47 +02:00
Bluewhale1337 0b610adaab Merge pull request #7 from Bluewhale1337/Bluewhale1337-patch-1
Update README.md
2026-07-20 08:12:21 +02:00
Bluewhale1337 609e2cc87b Update README.md
Fixed formatting

Signed-off-by: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com>
2026-07-20 08:12:07 +02:00
Bluewhale1337 12838ff250 Update HealBot_Localization.en.lua
in-game displayed version update
2026-07-19 22:43:28 +02:00
Bluewhale1337 e6ad9e7506 perf: eliminate remaining GC spikes by preventing layout rebuilds on combat toggle and zeroing hot-loop table allocations 2026-07-18 23:43:35 +02:00
Bluewhale1337 9f08b356e1 docs: append v1.5.1 changelog detailing memory, mana, and buff tracking fixes 2026-07-18 23:39:07 +02:00
Bluewhale1337 3845ada15f fix: remove artificial mana check to allow 0-mana cost buffs and fix tooltips disappearing instead of turning red 2026-07-18 23:37:51 +02:00
Bluewhale1337 826bf64eda fix: resolve Self Only buff tracking failing on raid frames by replacing direct unit string comparisons with UnitIsUnit 2026-07-18 23:34:20 +02:00
Bluewhale1337 8854cd3caa docs: add release notes for v1.4.2 to README.md 2026-07-18 23:26:14 +02:00
Bluewhale1337 c8a5e4f0eb perf: eliminate string allocation GC spikes in healthbar refreshing and remove full UI rebuilds on target change 2026-07-18 13:35:59 +02:00
Bluewhale1337 2d75406d88 Merge pull request #6 from Bluewhale1337/dev
Merge pull request #5 from Bluewhale1337/main
2026-07-18 12:40:48 +02:00
Bluewhale1337 2e35be6516 Merge pull request #5 from Bluewhale1337/main
Hotfix merge to dev
2026-07-18 12:40:18 +02:00
Bluewhale1337 07a9c3a93d Merge branch 'dev' into main
Signed-off-by: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com>
2026-07-18 12:40:04 +02:00
Bluewhale1337 c8e62fe80e docs: restore v1.4.2 changelog entry 2026-07-18 12:36:38 +02:00
Bluewhale1337 1334fc09bf perf: replace table.foreach with pairs loops to avoid GC spikes during combat 2026-07-18 12:27:51 +02:00
Bluewhale1337 ce594af5fa fix: memory leak in UnitAura and bump version to 1.4.2 2026-07-18 10:47:28 +02:00
Bluewhale1337 f1c5d6a8d1 Features: Expand action handling to support inline scripts, macros, and items while adding dynamic tooltip mana colorization and table memory management. 2026-07-15 14:56:03 +02:00
24 changed files with 1103 additions and 231 deletions
+1 -1
View File
@@ -18,7 +18,7 @@
<FontString name="$parent_text" inherits="GameFontNormalSmall">
<Anchors>
<Anchor point="CENTER">
<Offset> <AbsDimension y="1"/> </Offset>
<Offset> <AbsDimension y="0"/> </Offset>
</Anchor>
</Anchors>
</FontString>
+3 -2
View File
@@ -1,9 +1,9 @@
## Interface: 11200
## Title: HealBotBlue
## Version: 1.4.1
## Version: 1.6.0
## 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
@@ -27,3 +27,4 @@ HealBot_Options_CDC.xml
HealBot_Options_Skins.xml
HealBot_Options_Buffs.xml
HealBot_Options_Chat.xml
HealBot_Options_Auto.xml
+134 -21
View File
@@ -22,9 +22,9 @@ function HealBot_ShouldHeal(unit)
end
function HealBot_Action_ShouldHealSome()
return table.foreach(HealBot_Action_HealButtons, function (index,button)
for index, button in pairs(HealBot_Action_HealButtons) do
if (HealBot_ShouldHeal(button.unit)) then return button.unit; end
end);
end
end
function HealBot_MustHeal(unit)
@@ -32,9 +32,9 @@ function HealBot_MustHeal(unit)
end
function HealBot_Action_MustHealSome()
return table.foreach(HealBot_Action_HealButtons, function (index,button)
for index, button in pairs(HealBot_Action_HealButtons) do
if (HealBot_MustHeal(button.unit)) then return button.unit; end
end);
end
end
function HealBot_GetRezSpellForClass()
@@ -117,11 +117,107 @@ function HealBot_Action_HealUnit_OnLeave(this)
HealBot_Action_HideTooltip(this);
end
--------------------------------------------------------------------------------------------------
-- Puppeteer Utility Ports for Macro and Item Execution
--------------------------------------------------------------------------------------------------
function HealBot_SplitString(str, delimiter)
local result = {}
local start_pos = 1
while true do
local end_pos = string.find(str, delimiter, start_pos, true)
if not end_pos then
table.insert(result, string.sub(str, start_pos))
break
end
table.insert(result, string.sub(str, start_pos, end_pos - 1))
start_pos = end_pos + string.len(delimiter)
end
return result
end
function HealBot_RunMacroText(body)
local commands = HealBot_SplitString(body, "\n")
for i = 1, table.getn(commands) do
ChatFrameEditBox:SetText(commands[i])
ChatEdit_SendText(ChatFrameEditBox)
end
end
function HealBot_RunMacro(name)
if GetMacroIndexByName(name) == 0 then return end
local _, _, body = GetMacroInfo(GetMacroIndexByName(name))
HealBot_RunMacroText(body)
end
function HealBot_GetBagSlotInfo(bag, slot)
local link = GetContainerItemLink(bag, slot)
if not link then return end
local _, _, name = string.find(link, "%[(.*)%]")
local _, count = GetContainerItemInfo(bag, slot)
return name, count
end
function HealBot_FindBagSlot(itemName)
local bestBag, bestSlot, lowestStackSize
for bag = 0, NUM_BAG_FRAMES do
for slot = 1, GetContainerNumSlots(bag) do
local name, count = HealBot_GetBagSlotInfo(bag, slot)
if itemName == name then
if not lowestStackSize or lowestStackSize > count then
bestBag = bag
bestSlot = slot
lowestStackSize = count
end
end
end
end
return bestBag, bestSlot
end
function HealBot_UseItem(itemName)
local bag, slot = HealBot_FindBagSlot(itemName)
if not bag then return false end
UseContainerItem(bag, slot)
return true
end
function HealBot_Action_HealUnit_OnClick(this,button)
local decode_button = HealBot_Decode_Button(button);
local pattern = HealBot_Action_SpellPattern(decode_button);
-- Resurrection override on dead target
if not pattern then return end
-- Buff casting override (Spells only)
if HealBot_Config.BuffWatch == 1 then
local inCombat = UnitAffectingCombat("player")
if (not inCombat) or (HealBot_Config.BuffWatchInCombat == 1) then
if HealBot_MissingBuffs[this.unit] then
local missingBuff = HealBot_MissingBuffs[this.unit]
if decode_button == "Left" or decode_button == "Right" then
HealBot_CastSpellOnFriend(missingBuff, this.unit)
return
end
end
end
end
-- Priority 1: Inline Scripts (starts with /)
if string.sub(pattern, 1, 1) == "/" then
local oldTarget = nil
if UnitExists("target") then oldTarget = UnitName("target") end
TargetUnit(this.unit)
HealBot_RunMacroText(pattern)
if oldTarget then
TargetByName(oldTarget)
else
ClearTarget()
end
return
end
-- Priority 2: Spells
-- Resurrection override on dead target first
if UnitIsDeadOrGhost(this.unit) then
local rezSpell = HealBot_GetRezSpellForClass();
if rezSpell then
@@ -129,24 +225,41 @@ function HealBot_Action_HealUnit_OnClick(this,button)
return
end
end
-- Buff casting override
if HealBot_Config.BuffWatch == 1 then
local inCombat = UnitAffectingCombat("player")
if (not inCombat) or (HealBot_Config.BuffWatchInCombat == 1) then
local myClass = UnitClass("player")
if HealBot_MissingBuffs[this.unit] then
local missingBuff = HealBot_MissingBuffs[this.unit]
if decode_button == "Left" or decode_button == "Right" then
HealBot_CastSpellOnFriend(missingBuff, this.unit)
return
end
end
if HealBot_Spells[pattern] or HealBot_GetSpellId(pattern) then
HealBot_HealUnit(this.unit, pattern);
return
end
-- Priority 3: Named Macros
if GetMacroIndexByName(pattern) ~= 0 then
local oldTarget = nil
if UnitExists("target") then oldTarget = UnitName("target") end
TargetUnit(this.unit)
HealBot_RunMacro(pattern)
if oldTarget then
TargetByName(oldTarget)
else
ClearTarget()
end
end
return
end
-- Priority 4: Items
local bag, slot = HealBot_FindBagSlot(pattern)
if bag then
local oldTarget = nil
if UnitExists("target") then oldTarget = UnitName("target") end
TargetUnit(this.unit)
UseContainerItem(bag, slot)
if SpellIsTargeting() then SpellTargetUnit(this.unit) end
if oldTarget then TargetByName(oldTarget) else ClearTarget() end
return
end
HealBot_HealUnit(this.unit,pattern);
end
-- Fallback attempt
HealBot_HealUnit(this.unit, pattern);
end
function HealBot_Action_HealUnitCheck_OnClick(this)
if not this.unit then return end
+49
View File
@@ -232,6 +232,15 @@
<Button name="HealBot_Action_HealUnit39" inherits="HealingButtonTemplate" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit40" inherits="HealingButtonTemplate" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit41" inherits="HealingButtonTemplate" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit42" inherits="HealingButtonTemplate" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit43" inherits="HealingButtonTemplate" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit44" inherits="HealingButtonTemplate" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit45" inherits="HealingButtonTemplate" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit46" inherits="HealingButtonTemplate" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit47" inherits="HealingButtonTemplate" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit48" inherits="HealingButtonTemplate" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit49" inherits="HealingButtonTemplate" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit50" inherits="HealingButtonTemplate" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit51" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit52" inherits="HealingButtonTemplate2" text="Unit not set"/>
@@ -243,6 +252,46 @@
<Button name="HealBot_Action_HealUnit58" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit59" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit60" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit61" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit62" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit63" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit64" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit65" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit66" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit67" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit68" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit69" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit70" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit71" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit72" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit73" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit74" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit75" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit76" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit77" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit78" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit79" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit80" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit81" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit82" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit83" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit84" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit85" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit86" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit87" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit88" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit89" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit90" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit91" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit92" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit93" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit94" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit95" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit96" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit97" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit98" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit99" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit100" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_Header1" inherits="HealingButtonTemplate4" text="Unit not set"/>
<Button name="HealBot_Action_Header2" inherits="HealingButtonTemplate4" text="Unit not set"/>
+36 -16
View File
@@ -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)
@@ -91,7 +95,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 +104,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
@@ -115,23 +119,28 @@ function HealBot_CheckBuffs(unit)
end
end
local HealBot_TrackedHoTs = {
["Interface\\Icons\\Spell_Holy_Renew"] = true,
["Interface\\Icons\\Spell_Nature_Rejuvenation"] = true,
["Interface\\Icons\\Spell_Nature_ResistNature"] = true,
["Interface\\Icons\\Spell_Holy_PowerWordShield"] = true,
["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)
local DebuffType;
if HealBot_Heals[unit] and unit ~= "target" then
HealBot_UnitIcons[unit] = {}
if not HealBot_UnitIcons[unit] then
HealBot_UnitIcons[unit] = {}
end
for j = 1, 5 do
HealBot_UnitIcons[unit][j] = nil
end
local iconCount = 0
local HealBot_TrackedHoTs = {
["Interface\\Icons\\Spell_Holy_Renew"] = true,
["Interface\\Icons\\Spell_Nature_Rejuvenation"] = true,
["Interface\\Icons\\Spell_Nature_ResistNature"] = true,
["Interface\\Icons\\Spell_Holy_PowerWordShield"] = true,
["Interface\\Icons\\Spell_Holy_SealOfProtection"] = true,
["Interface\\Icons\\Spell_Holy_Excorcism"] = true,
["Interface\\Icons\\btnholyscriptures"] = true,
}
local i = 1;
while true do
local debuff, tmp, debuff_type = UnitDebuff(unit, i, 1)
@@ -140,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
@@ -164,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
+49 -58
View File
@@ -30,9 +30,7 @@ function HealBot_OnLoad(this)
end)
HealBot_Model:RegisterObserver("EQUIPMENT_CHANGED", function(unitID)
if unitID == "player" then
HealBot_BonusScanner:ScanEquipment()
HealBot_CalcEquipBonus = true;
HealBot_RecalcSpells();
HealBot_EquipChangeTimer = 1
end
end)
end
@@ -43,17 +41,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
@@ -73,10 +74,20 @@ function HealBot_OnUpdate(this, arg1)
end
-- Process Dirty Queue for MVC View
if next(HealBot_View_DirtyUnits) ~= nil then
for unitID in pairs(HealBot_View_DirtyUnits) do
HealBot_Action_RefreshButtons(unitID)
HealBot_View_DirtyUnits[unitID] = nil
local unitID, _ = next(HealBot_View_DirtyUnits)
while unitID do
HealBot_Action_RefreshButtons(unitID)
HealBot_View_DirtyUnits[unitID] = nil
unitID, _ = next(HealBot_View_DirtyUnits)
end
if HealBot_EquipChangeTimer > 0 then
HealBot_EquipChangeTimer = HealBot_EquipChangeTimer - arg1
if HealBot_EquipChangeTimer <= 0 then
HealBot_EquipChangeTimer = 0
HealBot_BonusScanner:ScanEquipment()
HealBot_CalcEquipBonus = true;
HealBot_RecalcSpells();
end
end
@@ -85,20 +96,12 @@ 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
if HealBot_EquipChangeTimer > 0 then
HealBot_EquipChangeTimer = HealBot_EquipChangeTimer - arg1
if HealBot_EquipChangeTimer <= 0 then
HealBot_EquipChangeTimer = 0
HealBot_BonusScanner:ScanEquipment()
HealBot_CalcEquipBonus = true;
HealBot_RecalcSpells();
end
end
if HealBot_SpellsInitFlag > 1 then
HealBot_SpellsInitFlag = HealBot_SpellsInitFlag + 1;
@@ -131,32 +134,28 @@ 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
if (arg1 == "player") then HealBot_RecalcHeals(); end
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
if (arg1 == "player") then HealBot_RecalcHeals(); end
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
if (arg1 == "player") then HealBot_RecalcHeals(); end
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
if (arg1 == "player") then HealBot_RecalcHeals(); end
HealBot_Action_RefreshButtons(arg1);
end,
["UNIT_AURA"] = function(this, arg1)
HealBot_Model:MarkAuraChanged(arg1)
@@ -182,6 +181,16 @@ local HealBot_EventHandlers = {
HealBot_Model:NotifyObservers("ROSTER_CHANGED")
HealBot_OnEvent_PartyMembersChanged(this)
end,
["RAID_ROSTER_UPDATE"] = function(this)
for _, unit in ipairs(HealBot_Model.partyMembers) do
HealBot_Model:RefreshUnit(unit)
end
for _, unit in ipairs(HealBot_Model.raidMembers) do
HealBot_Model:RefreshUnit(unit)
end
HealBot_Model:NotifyObservers("ROSTER_CHANGED")
HealBot_OnEvent_PartyMembersChanged(this)
end,
["PLAYER_ENTERING_WORLD"] = function(this)
HealBot_Model:RefreshUnit("player")
HealBot_Model:RefreshUnit("pet")
@@ -201,8 +210,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 +219,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,
@@ -286,10 +292,9 @@ function HealBot_OnEvent_VariablesLoaded(this)
this:RegisterEvent("PLAYER_REGEN_ENABLED");
this:RegisterEvent("PLAYER_TARGET_CHANGED");
this:RegisterEvent("PARTY_MEMBERS_CHANGED");
this:RegisterEvent("RAID_ROSTER_UPDATE");
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 +306,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");
@@ -321,7 +324,6 @@ end
function HealBot_OnEvent_UnitHealth(this, unit)
if (not HealBot_Heals[unit]) then return end
HealBot_CheckCasting(unit);
HealBot_RecalcHeals(unit);
if unit == HealBot_Action_TooltipUnit then
HealBot_Action_RefreshTooltip(HealBot_Action_TooltipUnit);
end
@@ -338,7 +340,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;
@@ -378,7 +380,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_View_DirtyUnits["target"] = true
HealBot_OnEvent_UnitAura(nil, "target");
end
end
function HealBot_OnEvent_PartyMembersChanged(this)
@@ -439,20 +444,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
+36 -13
View File
@@ -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);
@@ -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);
@@ -475,19 +476,43 @@ end
function HealBot_GetHealSpell(unit, pattern)
if (not UnitName(unit)) then return nil end;
if not pattern then return nil end;
if UnitOnTaxi("player") then return nil end;
if HealBot_Config.ProtectPvP == 1 and UnitIsPVP(unit) and not UnitIsPVP("player") then return nil end
if HealBot_UnitClass("player") == "DRUID" then
if HealBot_ActiveShapeshiftStance and HealBot_Config.AutoUnshift ~= 1 then return nil end;
end
local spell = HealBot_GetSpellName(HealBot_GetSpellId(pattern))
local range = 40;
if HealBot_Spells[spell] then
if not HealBot_CanCastSpell(spell, unit) then return nil end;
range = HealBot_Spells[spell].range;
end
if HealBot_Range_Check(unit, range) == 0 then return nil end;
return spell;
-- Handle Inline Scripts
if string.sub(pattern, 1, 1) == "/" then
return pattern;
end
-- Handle Spells
if HealBot_Spells[pattern] or HealBot_GetSpellId(pattern) then
local spell = HealBot_GetSpellName(HealBot_GetSpellId(pattern)) or pattern
local range = 40;
if HealBot_Spells[spell] then
if not HealBot_CanCastSpell(spell, unit) then return nil end;
range = HealBot_Spells[spell].range or 40;
end
if HealBot_Range_Check(unit, range) == 0 then return nil end;
return spell;
end
-- Handle Named Macros
if GetMacroIndexByName(pattern) ~= 0 then
return pattern;
end
-- Handle Items
local bag, slot = HealBot_FindBagSlot(pattern)
if bag then
-- optionally check item range, but skipping for now as it's complex in vanilla
return pattern;
end
return nil;
end
function HealBot_HealUnit(unit, pattern)
@@ -568,9 +593,7 @@ function HealBot_InitSpells()
end
id = id + 1;
end
if class == "PRIEST" or class == "DRUID" or class == "PALADIN" or class == "SHAMAN" then
HealBot_AddChat("Initiated HealBot_CurrentSpells with " .. cnt .. " Spells");
end
return cnt;
end
+45 -1
View File
@@ -2,6 +2,20 @@ HealBot_ConfigDefaults = {
ShowManaBars=0,
ManaBarsHealersOnly=0,
Version = HEALBOT_VERSION,
AutoSwap_Enabled = 0,
AutoSwap_Profiles = {
[1] = HEALBOT_SKINS_STD,
[2] = HEALBOT_SKINS_STD,
[3] = HEALBOT_SKINS_STD,
[4] = HEALBOT_SKINS_STD,
[5] = HEALBOT_SKINS_STD,
},
bmaxrows = {
[HEALBOT_SKINS_STD] = 0,
},
GridOrientation = {
[HEALBOT_SKINS_STD] = 1,
},
AlertLevel = 0.95,
AutoClose = 1,
PanelSounds = 1,
@@ -181,7 +195,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},
@@ -545,7 +569,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 = {};
@@ -559,3 +583,23 @@ HealBot_SpamCnt=0;
HealBot_Action_TooltipUnit=nil;
HealBot_Ressing = {};
HealBot_IamRessing = false;
-- Table Recycling Pool (Puppeteer-inspired)
local tablePool = {}
function HealBot_GetTable()
local t = table.remove(tablePool)
if not t then
t = {}
end
return t
end
function HealBot_ReleaseTable(t)
if type(t) == "table" then
for k in pairs(t) do
t[k] = nil
end
table.insert(tablePool, t)
end
end
+3 -2
View File
@@ -1,4 +1,4 @@
HEALBOT_VERSION = "1.4.1";
HEALBOT_VERSION = GetAddOnMetadata("HealBotBlue", "Version");
-------------
-- ENGLISH --
@@ -323,9 +323,10 @@ HEALBOT_OPTIONS_HEAL_BUTTONS = "Healing bars";
HEALBOT_OPTIONS_EMERGFILTER = "Show extra bars for";
HEALBOT_OPTIONS_GROUPHEALS = "Group";
HEALBOT_OPTIONS_GROUPHEALS_LABEL = "Group Only";
HEALBOT_OPTIONS_TANKHEALS = "Main tanks";
HEALBOT_OPTIONS_TARGETHEALS = "Targets";
HEALBOT_OPTIONS_EMERGENCYHEALS= "Extra";
HEALBOT_OPTIONS_EMERGENCYHEALS= "Raid / Extra";
HEALBOT_OPTIONS_HEALLEVEL = "Healing Level";
HEALBOT_OPTIONS_ALERTLEVEL = "Alert Level";
HEALBOT_OPTIONS_OVERHEAL = "Show Abort button when overhealing"
+3 -1
View File
@@ -234,7 +234,7 @@ function HealBot_Options_OnLoad(this)
table.insert(UISpecialFrames,this:GetName());
-- Tabs
PanelTemplates_SetNumTabs(this,7);
PanelTemplates_SetNumTabs(this,8);
this.selectedTab = 1;
PanelTemplates_UpdateTabs(this);
HealBot_Options_ShowPanel(this.selectedTab);
@@ -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 and HealBot_Config.bmaxrows[HealBot_Config.Current_Skin]) or 0)
HealBot_Options_GridOrientation:SetChecked(((HealBot_Config.GridOrientation and 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)
+5 -27
View File
@@ -94,7 +94,7 @@
<Frame name="HealBot_Options" toplevel="true" frameStrata="DIALOG"
movable="true" parent="UIParent" enableMouse="true" hidden="true">
<Size>
<AbsDimension x="420" y="455"/>
<AbsDimension x="480" y="455"/>
</Size>
<Anchors>
<Anchor point="CENTER">
@@ -206,38 +206,16 @@
</Anchor>
</Anchors>
</Button>
<Button name="HealBot_Options_Defaults" inherits="UIPanelButtonTemplate" text="HEALBOT_OPTIONS_DEFAULTS">
<Size>
<AbsDimension x="80" y="22"/>
</Size>
<Button name="HealBot_OptionsTab8" inherits="HealBot_Options_Tab" id="8" text="Auto">
<Anchors>
<Anchor point="BOTTOM" relativePoint="BOTTOM">
<Anchor point="LEFT" relativeTo="HealBot_OptionsTab7" relativePoint="RIGHT">
<Offset>
<AbsDimension x="-50" y="15"/>
<AbsDimension x="-14" y="0" />
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnClick>HealBot_Options_Defaults_OnClick(this)</OnClick>
</Scripts>
</Button>
<Button name="HealBot_Options_CloseButton" inherits="UIPanelButtonTemplate" text="HEALBOT_OPTIONS_CLOSE">
<Size>
<AbsDimension x="80" y="22"/>
</Size>
<Anchors>
<Anchor point="BOTTOM" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="50" y="15"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnClick>
HideUIPanel(this:GetParent());
</OnClick>
</Scripts>
</Button>
</Frames>
<Scripts>
<OnLoad>HealBot_Options_OnLoad(this);</OnLoad>
+82
View File
@@ -0,0 +1,82 @@
function HealBot_Options_AutoSwap_OnClick(this)
if this:GetChecked() then
HealBot_Config.AutoSwap_Enabled = 1
else
HealBot_Config.AutoSwap_Enabled = 0
end
HealBot_Action_PartyChanged()
end
function HealBot_Options_Auto_Initialize()
local dropdownName = UIDROPDOWNMENU_OPEN_MENU
if not dropdownName then return end
local dropdownFrame = getglobal(dropdownName)
if not dropdownFrame then return end
local id = dropdownFrame:GetID()
if not id then return end
for i=1, getn(HealBot_Config.Skins), 1 do
local info = {}
info.text = HealBot_Config.Skins[i]
info.func = HealBot_Options_Auto_OnSelect
info.value = id
if not HealBot_Config.AutoSwap_Profiles then HealBot_Config.AutoSwap_Profiles = {} end
if HealBot_Config.AutoSwap_Profiles[id] == HealBot_Config.Skins[i] then
info.checked = 1
else
info.checked = nil
end
UIDropDownMenu_AddButton(info)
end
end
function HealBot_Options_Auto_OnSelect()
local skin = this:GetText()
local id = this.value
if not id or not skin then return end
if not HealBot_Config.AutoSwap_Profiles then HealBot_Config.AutoSwap_Profiles = {} end
HealBot_Config.AutoSwap_Profiles[id] = skin
local dropdowns = {
"HealBot_Options_Auto_Solo",
"HealBot_Options_Auto_Party",
"HealBot_Options_Auto_Raid15",
"HealBot_Options_Auto_Raid25",
"HealBot_Options_Auto_Raid40"
}
local dropdownName = dropdowns[id]
local dropdownFrame = getglobal(dropdownName)
HealBot_UIDropDownMenu_SetSelectedValue(dropdownFrame, skin)
UIDropDownMenu_SetText(skin, dropdownFrame)
HealBot_Action_PartyChanged()
end
function HealBot_Options_Auto_OnShow(this)
if HealBot_Config.AutoSwap_Enabled == 1 then
HealBot_Options_AutoSwap:SetChecked(1)
else
HealBot_Options_AutoSwap:SetChecked(nil)
end
local dropdowns = {
"HealBot_Options_Auto_Solo",
"HealBot_Options_Auto_Party",
"HealBot_Options_Auto_Raid15",
"HealBot_Options_Auto_Raid25",
"HealBot_Options_Auto_Raid40"
}
for id, name in ipairs(dropdowns) do
local dropdownFrame = getglobal(name)
if dropdownFrame then
UIDropDownMenu_SetWidth(150, dropdownFrame)
if not HealBot_Config.AutoSwap_Profiles then HealBot_Config.AutoSwap_Profiles = {} end
local skin = HealBot_Config.AutoSwap_Profiles[id]
if skin then
HealBot_UIDropDownMenu_SetSelectedValue(dropdownFrame, skin)
UIDropDownMenu_SetText(skin, dropdownFrame)
end
end
end
end
+152
View File
@@ -0,0 +1,152 @@
<Ui xmlns="http://www.blizzard.com/wow/ui/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.blizzard.com/wow/ui/ ..\FrameXML\UI.xsd">
<Script file="HealBot_Options_Auto.lua" />
<Frame name="HealBot_Options_Panel8" parent="HealBot_Options" hidden="true" setAllPoints="true">
<Frames>
<CheckButton name="HealBot_Options_AutoSwap" inherits="OptionsCheckButtonTemplate">
<Anchors>
<Anchor point="TOPLEFT">
<Offset>
<AbsDimension x="25" y="-30" />
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnLoad>
getglobal(this:GetName().."Text"):SetText("Enable Auto-Swap");
</OnLoad>
<OnClick>
HealBot_Options_AutoSwap_OnClick(this);
</OnClick>
</Scripts>
</CheckButton>
<Frame name="HealBot_Options_Auto_Solo" inherits="UIDropDownMenuTemplate" id="1">
<Layers>
<Layer level="BACKGROUND">
<FontString name="$parentLabel" text="Solo Skin:" inherits="GameFontNormalSmall">
<Anchors>
<Anchor point="TOPLEFT">
<Offset><AbsDimension x="-10" y="15" /></Offset>
</Anchor>
</Anchors>
</FontString>
</Layer>
</Layers>
<Anchors>
<Anchor point="TOPLEFT">
<Offset><AbsDimension x="30" y="-80" /></Offset>
</Anchor>
</Anchors>
<Scripts>
<OnLoad>
UIDropDownMenu_Initialize(this, HealBot_Options_Auto_Initialize);
</OnLoad>
</Scripts>
</Frame>
<Frame name="HealBot_Options_Auto_Party" inherits="UIDropDownMenuTemplate" id="2">
<Layers>
<Layer level="BACKGROUND">
<FontString name="$parentLabel" text="Party Skin:" inherits="GameFontNormalSmall">
<Anchors>
<Anchor point="TOPLEFT">
<Offset><AbsDimension x="-10" y="15" /></Offset>
</Anchor>
</Anchors>
</FontString>
</Layer>
</Layers>
<Anchors>
<Anchor point="TOPLEFT">
<Offset><AbsDimension x="30" y="-130" /></Offset>
</Anchor>
</Anchors>
<Scripts>
<OnLoad>
UIDropDownMenu_Initialize(this, HealBot_Options_Auto_Initialize);
</OnLoad>
</Scripts>
</Frame>
<Frame name="HealBot_Options_Auto_Raid15" inherits="UIDropDownMenuTemplate" id="3">
<Layers>
<Layer level="BACKGROUND">
<FontString name="$parentLabel" text="Raid 15 Skin:" inherits="GameFontNormalSmall">
<Anchors>
<Anchor point="TOPLEFT">
<Offset><AbsDimension x="-10" y="15" /></Offset>
</Anchor>
</Anchors>
</FontString>
</Layer>
</Layers>
<Anchors>
<Anchor point="TOPLEFT">
<Offset><AbsDimension x="30" y="-180" /></Offset>
</Anchor>
</Anchors>
<Scripts>
<OnLoad>
UIDropDownMenu_Initialize(this, HealBot_Options_Auto_Initialize);
</OnLoad>
</Scripts>
</Frame>
<Frame name="HealBot_Options_Auto_Raid25" inherits="UIDropDownMenuTemplate" id="4">
<Layers>
<Layer level="BACKGROUND">
<FontString name="$parentLabel" text="Raid 25 Skin:" inherits="GameFontNormalSmall">
<Anchors>
<Anchor point="TOPLEFT">
<Offset><AbsDimension x="-10" y="15" /></Offset>
</Anchor>
</Anchors>
</FontString>
</Layer>
</Layers>
<Anchors>
<Anchor point="TOPLEFT">
<Offset><AbsDimension x="30" y="-230" /></Offset>
</Anchor>
</Anchors>
<Scripts>
<OnLoad>
UIDropDownMenu_Initialize(this, HealBot_Options_Auto_Initialize);
</OnLoad>
</Scripts>
</Frame>
<Frame name="HealBot_Options_Auto_Raid40" inherits="UIDropDownMenuTemplate" id="5">
<Layers>
<Layer level="BACKGROUND">
<FontString name="$parentLabel" text="Raid 40 Skin:" inherits="GameFontNormalSmall">
<Anchors>
<Anchor point="TOPLEFT">
<Offset><AbsDimension x="-10" y="15" /></Offset>
</Anchor>
</Anchors>
</FontString>
</Layer>
</Layers>
<Anchors>
<Anchor point="TOPLEFT">
<Offset><AbsDimension x="30" y="-280" /></Offset>
</Anchor>
</Anchors>
<Scripts>
<OnLoad>
UIDropDownMenu_Initialize(this, HealBot_Options_Auto_Initialize);
</OnLoad>
</Scripts>
</Frame>
</Frames>
<Scripts>
<OnShow>
HealBot_Options_Auto_OnShow(this);
</OnShow>
</Scripts>
</Frame>
</Ui>
+6 -6
View File
@@ -123,7 +123,7 @@
<Anchors>
<Anchor point="TOPLEFT" relativeTo="HealBot_Options_Buff1" relativePoint="BOTTOMLEFT">
<Offset>
<AbsDimension x="0" y="-20" />
<AbsDimension x="0" y="-35" />
</Offset>
</Anchor>
</Anchors>
@@ -160,7 +160,7 @@
<Anchors>
<Anchor point="TOPLEFT" relativeTo="HealBot_Options_Buff2" relativePoint="BOTTOMLEFT">
<Offset>
<AbsDimension x="0" y="-20" />
<AbsDimension x="0" y="-35" />
</Offset>
</Anchor>
</Anchors>
@@ -197,7 +197,7 @@
<Anchors>
<Anchor point="TOPLEFT" relativeTo="HealBot_Options_Buff3" relativePoint="BOTTOMLEFT">
<Offset>
<AbsDimension x="0" y="-20" />
<AbsDimension x="0" y="-35" />
</Offset>
</Anchor>
</Anchors>
@@ -271,7 +271,7 @@
<Anchors>
<Anchor point="TOPLEFT" relativeTo="HealBot_Options_Buff5" relativePoint="BOTTOMLEFT">
<Offset>
<AbsDimension x="0" y="-20" />
<AbsDimension x="0" y="-35" />
</Offset>
</Anchor>
</Anchors>
@@ -308,7 +308,7 @@
<Anchors>
<Anchor point="TOPLEFT" relativeTo="HealBot_Options_Buff6" relativePoint="BOTTOMLEFT">
<Offset>
<AbsDimension x="0" y="-20" />
<AbsDimension x="0" y="-35" />
</Offset>
</Anchor>
</Anchors>
@@ -345,7 +345,7 @@
<Anchors>
<Anchor point="TOPLEFT" relativeTo="HealBot_Options_Buff7" relativePoint="BOTTOMLEFT">
<Offset>
<AbsDimension x="0" y="-20" />
<AbsDimension x="0" y="-35" />
</Offset>
</Anchor>
</Anchors>
+3 -3
View File
@@ -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
+32 -2
View File
@@ -265,8 +265,38 @@
</Scripts>
</CheckButton>
<Button name="HealBot_Options_Defaults" inherits="UIPanelButtonTemplate" text="HEALBOT_OPTIONS_DEFAULTS">
<Size>
<AbsDimension x="80" y="22"/>
</Size>
<Anchors>
<Anchor point="BOTTOM" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="-50" y="15"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnClick>HealBot_Options_Defaults_OnClick(this)</OnClick>
</Scripts>
</Button>
<Button name="HealBot_Options_CloseButton" inherits="UIPanelButtonTemplate" text="HEALBOT_OPTIONS_CLOSE">
<Size>
<AbsDimension x="80" y="22"/>
</Size>
<Anchors>
<Anchor point="BOTTOM" relativePoint="BOTTOM">
<Offset>
<AbsDimension x="50" y="15"/>
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnClick>
HideUIPanel(this:GetParent():GetParent());
</OnClick>
</Scripts>
</Button>
</Frames>
</Frame>
+1 -1
View File
@@ -52,7 +52,7 @@
</Anchor>
</Anchors>
<Scripts>
<OnLoad>HealBot_Options_GroupHeals_OnLoad(this,HEALBOT_OPTIONS_GROUPHEALS)</OnLoad>
<OnLoad>HealBot_Options_GroupHeals_OnLoad(this,HEALBOT_OPTIONS_GROUPHEALS_LABEL)</OnLoad>
<OnClick>HealBot_Options_GroupHeals_OnClick(this)</OnClick>
</Scripts>
</CheckButton>
+22
View File
@@ -1,6 +1,22 @@
-- HealBot Options panel file: HealBot_Options_Skins.lua
-- Split from original HealBot_Options.lua
function HealBot_Options_BarMaxRowsS_OnValueChanged(this)
if not HealBot_Config.bmaxrows then HealBot_Config.bmaxrows = {} end
HealBot_Config.bmaxrows[HealBot_Config.Current_Skin] = this:GetValue()
HealBot_Action_PartyChanged()
end
function HealBot_Options_GridOrientation_OnClick(this)
if not HealBot_Config.GridOrientation then HealBot_Config.GridOrientation = {} end
if this:GetChecked() then
HealBot_Config.GridOrientation[HealBot_Config.Current_Skin] = 2 -- Horizontal
else
HealBot_Config.GridOrientation[HealBot_Config.Current_Skin] = 1 -- Vertical
end
HealBot_Action_PartyChanged()
end
function HealBot_Options_NewSkin_OnTextChanged(this)
local text= this:GetText()
if string.len(text)>0 then
@@ -11,6 +27,10 @@ function HealBot_Options_NewSkin_OnTextChanged(this)
end
function HealBot_Options_NewSkinb_OnClick(this)
HealBot_Config.numcols[HealBot_Options_NewSkin:GetText()] = HealBot_Config.numcols[HealBot_Config.Current_Skin]
if not HealBot_Config.bmaxrows then HealBot_Config.bmaxrows = {} end
if not HealBot_Config.GridOrientation then HealBot_Config.GridOrientation = {} end
HealBot_Config.bmaxrows[HealBot_Options_NewSkin:GetText()] = HealBot_Config.bmaxrows[HealBot_Config.Current_Skin] or 0
HealBot_Config.GridOrientation[HealBot_Options_NewSkin:GetText()] = HealBot_Config.GridOrientation[HealBot_Config.Current_Skin] or 1
HealBot_Config.btexture[HealBot_Options_NewSkin:GetText()] = HealBot_Config.btexture[HealBot_Config.Current_Skin]
HealBot_Config.bcspace[HealBot_Options_NewSkin:GetText()] = HealBot_Config.bcspace[HealBot_Config.Current_Skin]
HealBot_Config.brspace[HealBot_Options_NewSkin:GetText()] = HealBot_Config.brspace[HealBot_Config.Current_Skin]
@@ -56,6 +76,8 @@ end
function HealBot_Options_DeleteSkin_OnClick(this)
if HealBot_Config.Current_Skin~=HEALBOT_SKINS_STD then
HealBot_Config.numcols[HealBot_Options_SkinsText:GetText()] = nil
if HealBot_Config.bmaxrows then HealBot_Config.bmaxrows[HealBot_Options_SkinsText:GetText()] = nil end
if HealBot_Config.GridOrientation then HealBot_Config.GridOrientation[HealBot_Options_SkinsText:GetText()] = nil end
HealBot_Config.btexture[HealBot_Options_SkinsText:GetText()] = nil
HealBot_Config.bcspace[HealBot_Options_SkinsText:GetText()] = nil
HealBot_Config.brspace[HealBot_Options_SkinsText:GetText()] = nil
+55 -19
View File
@@ -266,9 +266,9 @@
<AbsDimension x="123" y="17" />
</Size>
<Anchors>
<Anchor point="TOPLEFT" relativeTo="HealBot_Options_BarBRSpaceS" relativePoint="TOPLEFT">
<Anchor point="TOPLEFT" relativeTo="HealBot_Options_BarBCSpaceS" relativePoint="TOPRIGHT">
<Offset>
<AbsDimension x="0" y="-35" />
<AbsDimension x="10" y="0" />
</Offset>
</Anchor>
</Anchors>
@@ -277,28 +277,14 @@
<OnValueChanged>HealBot_Options_FramePaddingS_OnValueChanged(this)</OnValueChanged>
</Scripts>
</Slider>
<Slider name="HealBot_Options_BorderThicknessS" inherits="HealBot_Options_SliderTemplate">
<Size>
<AbsDimension x="123" y="17" />
</Size>
<Anchors>
<Anchor point="TOPLEFT" relativeTo="HealBot_Options_FramePaddingS" relativePoint="TOPRIGHT">
<Offset>
<AbsDimension x="10" y="0" />
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnLoad>HealBot_Options_val_OnLoad(this,"Solid Border",1,10)</OnLoad>
<OnValueChanged>HealBot_Options_BorderThicknessS_OnValueChanged(this)</OnValueChanged>
</Scripts>
</Slider>
<Slider name="HealBot_Options_BarAlpha" inherits="HealBot_Options_SliderTemplate">
<Size>
<AbsDimension x="123" y="17" />
</Size>
<Anchors>
<Anchor point="TOPLEFT" relativeTo="HealBot_Options_FramePaddingS" relativePoint="TOPLEFT">
<Anchor point="TOPLEFT" relativeTo="HealBot_Options_BarBRSpaceS" relativePoint="TOPLEFT">
<Offset>
<AbsDimension x="0" y="-35" />
</Offset>
@@ -375,6 +361,56 @@
</Scripts>
</Slider>
<Slider name="HealBot_Options_BorderThicknessS" inherits="HealBot_Options_SliderTemplate">
<Size>
<AbsDimension x="123" y="17" />
</Size>
<Anchors>
<Anchor point="TOPLEFT" relativeTo="HealBot_Options_BarAlphaInHeal" relativePoint="TOPRIGHT">
<Offset>
<AbsDimension x="10" y="0" />
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnLoad>HealBot_Options_val_OnLoad(this,"Solid Border",1,10)</OnLoad>
<OnValueChanged>HealBot_Options_BorderThicknessS_OnValueChanged(this)</OnValueChanged>
</Scripts>
</Slider>
<Slider name="HealBot_Options_BarMaxRowsS" inherits="HealBot_Options_SliderTemplate">
<Size>
<AbsDimension x="123" y="17" />
</Size>
<Anchors>
<Anchor point="TOPLEFT" relativeTo="HealBot_Options_AbortBarSize" relativePoint="TOPRIGHT">
<Offset>
<AbsDimension x="10" y="0" />
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnLoad>HealBot_Options_val_OnLoad(this,"Max Rows",0,40)</OnLoad>
<OnValueChanged>HealBot_Options_BarMaxRowsS_OnValueChanged(this)</OnValueChanged>
</Scripts>
</Slider>
<CheckButton name="HealBot_Options_GridOrientation" inherits="OptionsCheckButtonTemplate">
<Anchors>
<Anchor point="TOPLEFT" relativeTo="HealBot_Options_BarMaxRowsS" relativePoint="BOTTOMLEFT">
<Offset>
<AbsDimension x="-5" y="-10" />
</Offset>
</Anchor>
</Anchors>
<Scripts>
<OnLoad>
getglobal(this:GetName().."Text"):SetText("Horizontal Grid");
</OnLoad>
<OnClick>
HealBot_Options_GridOrientation_OnClick(this);
</OnClick>
</Scripts>
</CheckButton>
<Button name="HealBot_EnTextColorpickb">
<Size>
<AbsDimension x="87" y="20"/>
+296 -43
View File
@@ -70,13 +70,13 @@ function HealBot_HealthColor(unit, hlth, maxhlth)
end
local colorMode = HealBot_Config.bcolormode[HealBot_Config.Current_Skin] or 1
if colorMode == 2 and HealBot_Model and HealBot_Model.units[unit] and HealBot_Model.units[unit].englishClass then
if colorMode == 2 and HealBot_Model and HealBot_Model.units[unit] and HealBot_Model.units[unit].englishClass and RAID_CLASS_COLORS and RAID_CLASS_COLORS[HealBot_Model.units[unit].englishClass] then
local engClass = HealBot_Model.units[unit].englishClass
if RAID_CLASS_COLORS and RAID_CLASS_COLORS[engClass] then
r = RAID_CLASS_COLORS[engClass].r
g = RAID_CLASS_COLORS[engClass].g
b = RAID_CLASS_COLORS[engClass].b
end
r = RAID_CLASS_COLORS[engClass].r
g = RAID_CLASS_COLORS[engClass].g
b = RAID_CLASS_COLORS[engClass].b
elseif colorMode == 2 and string.find(unit, "pet") then
r, g, b = 0.4, 0.9, 0.6 -- Mint color
else
if pct >= 0.98 then r = 0.0; end
if pct < 0.98 and pct >= 0.65 then r = 2.94 - (pct * 3); end
@@ -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)
@@ -105,10 +109,16 @@ function HealBot_Action_EnableButton(button)
local maxhlth = state.maxHealth
local name = state.name
if not name then name = UnitName(unit) end -- fallback
if not name or name == "Unknown" then
button:Hide()
return
end
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 +185,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
@@ -255,9 +265,9 @@ function HealBot_Action_EnableButton(button)
end
function HealBot_Action_EnableButtons()
table.foreach(HealBot_Action_HealButtons, function (index, button)
HealBot_Action_EnableButton(button);
end);
for index, button in pairs(HealBot_Action_HealButtons) do
HealBot_Action_EnableButton(button)
end
end
function HealBot_Action_RefreshButton(button)
@@ -285,13 +295,13 @@ end
function HealBot_Action_RefreshButtons(unit)
if unit and HealBot_Action_UnitButtons[unit] then
table.foreach(HealBot_Action_UnitButtons[unit], function (index, button)
HealBot_Action_RefreshButton(button);
end);
for index, button in pairs(HealBot_Action_UnitButtons[unit]) do
HealBot_Action_RefreshButton(button)
end
else
table.foreach(HealBot_Action_HealButtons, function (index, button)
HealBot_Action_RefreshButton(button);
end);
for index, button in pairs(HealBot_Action_HealButtons) do
HealBot_Action_RefreshButton(button)
end
end
end
@@ -330,6 +340,41 @@ function HealBot_Action_PositionButton(button, OsetX, OsetY, bwidth, bheight, ch
return OsetY;
end
function HealBot_Action_PositionButtonHorizontal(button, OsetX, OsetY, bwidth, bheight, checked, header)
local bcspace = HealBot_Config.bcspace[HealBot_Config.Current_Skin] or 3;
if header then
headerno = headerno + 1;
local headerobj = getglobal("HealBot_Action_Header" .. headerno);
headerobj:SetText(header)
headerobj:Show();
headerobj:ClearAllPoints();
headerobj:SetHeight(bheight);
headerobj:SetWidth(bwidth);
headerobj:SetPoint("TOPLEFT", "HealBot_Action", "TOPLEFT", OsetX, -OsetY);
headerobj:Disable();
OsetX = OsetX + bwidth + bcspace;
else
local unit = button.unit;
button:SetText(" ");
if (HealBot_MayHeal(unit)) then
button:Show();
button:ClearAllPoints();
button:SetHeight(bheight);
if checked then
button:SetWidth(bwidth - 14);
button:SetPoint("TOPLEFT", "HealBot_Action", "TOPLEFT", OsetX + 14, -OsetY);
else
button:SetWidth(bwidth);
button:SetPoint("TOPLEFT", "HealBot_Action", "TOPLEFT", OsetX, -OsetY);
end
OsetX = OsetX + bwidth + bcspace;
else
button:Hide();
end
end
return OsetX;
end
function HealBot_Action_SetHeightWidth(width, height, bwidth)
if HealBot_ActionHeight then
HealBot_Action:SetHeight(HealBot_ActionHeight);
@@ -362,6 +407,7 @@ function HealBot_Action_SetHealButton(index, unit)
return nil
end
local button = getglobal("HealBot_Action_HealUnit" .. index);
if not button then return nil end
button.unit = unit;
if unit then
table.insert(HealBot_Action_HealButtons, button);
@@ -374,12 +420,41 @@ function HealBot_Action_SetHealButton(index, unit)
end
function HealBot_Action_PartyChanged()
if not HealBot_IsFighting then
local numBars = 0;
if HealBot_IsFighting then
HealBot_Action_AppendNewUnits()
return
end
local numBars = 0;
local numHeaders = 0;
local TempMaxH = 0;
local HeaderPos = {};
if HealBot_Config.AutoSwap_Enabled == 1 then
local totalMembers = GetNumRaidMembers()
if totalMembers == 0 then totalMembers = GetNumPartyMembers() end
local threshold = 1
if totalMembers == 0 then
threshold = 1 -- Solo
elseif totalMembers > 0 and totalMembers <= 5 then
threshold = 2 -- Party
elseif totalMembers > 5 and totalMembers <= 15 then
threshold = 3 -- Raid15
elseif totalMembers > 15 and totalMembers <= 25 then
threshold = 4 -- Raid25
else
threshold = 5 -- Raid40
end
if not HealBot_Config.AutoSwap_Profiles then HealBot_Config.AutoSwap_Profiles = {} end
local swapSkin = HealBot_Config.AutoSwap_Profiles[threshold]
if swapSkin and swapSkin ~= HealBot_Config.Current_Skin then
HealBot_Config.Current_Skin = swapSkin
HealBot_Options_SetSkins()
end
end
for j = 1, 15 do
local headerobj = getglobal("HealBot_Action_Header" .. j);
headerobj:SetText(" ")
@@ -401,10 +476,7 @@ function HealBot_Action_PartyChanged()
local checked_end = 0;
headerno = 0;
for j = 1, 41 do
HealBot_Action_SetHealButton(j, nil);
end
for j = 51, 60 do
for j = 1, 100 do
HealBot_Action_SetHealButton(j, nil);
end
HealBot_Action_SetHealButton();
@@ -738,8 +810,12 @@ function HealBot_Action_PartyChanged()
local OffsetY = bpadding;
local OffsetX = bpadding;
local MaxOffsetY = 0;
local MaxOffsetX = 0;
if cols > (numBars - numHeaders) then
local maxRows = (HealBot_Config.bmaxrows and HealBot_Config.bmaxrows[HealBot_Config.Current_Skin]) or 0
local orientation = (HealBot_Config.GridOrientation and HealBot_Config.GridOrientation[HealBot_Config.Current_Skin]) or 1
if cols > (numBars - numHeaders) and maxRows == 0 then
cols = numBars - numHeaders;
end
if cols <= 0 then cols = 1 end
@@ -747,33 +823,64 @@ function HealBot_Action_PartyChanged()
local h = 1;
local i = 0;
local z = 1;
local brspace = HealBot_Config.brspace[HealBot_Config.Current_Skin] or 3;
local bcspace = HealBot_Config.bcspace[HealBot_Config.Current_Skin] or 3;
table.foreach(HealBot_Action_HealButtons, function (index, button)
local limit = math.ceil((numBars) / cols)
if orientation == 1 and maxRows > 0 then
limit = maxRows
elseif orientation == 2 then
limit = cols
end
for index, button in pairs(HealBot_Action_HealButtons) do
i = i + 1;
local checked = false;
local header;
if HeaderPos[i] then
header = HeaderPos[i];
OffsetY = HealBot_Action_PositionButton(nil, OffsetX, OffsetY, bwidth, bheight, checked, header);
if h == math.ceil((numBars) / cols) and z < numBars then
h = 0;
if MaxOffsetY < OffsetY then MaxOffsetY = OffsetY; end
OffsetY = bpadding;
OffsetX = OffsetX + bwidth + bcspace;
if orientation == 1 then
OffsetY = HealBot_Action_PositionButton(nil, OffsetX, OffsetY, bwidth, bheight, checked, header);
if h == limit and z < numBars then
h = 0;
if MaxOffsetY < OffsetY then MaxOffsetY = OffsetY; end
OffsetY = bpadding;
OffsetX = OffsetX + bwidth + bcspace;
end
else
OffsetX = HealBot_Action_PositionButtonHorizontal(nil, OffsetX, OffsetY, bwidth, bheight, checked, header);
if h == limit and z < numBars then
h = 0;
if MaxOffsetX < OffsetX then MaxOffsetX = OffsetX; end
OffsetX = bpadding;
OffsetY = OffsetY + bheight + brspace;
end
end
h = h + 1;
z = z + 1;
end
if checked_start <= i and checked_end >= i then checked = true; end
OffsetY = HealBot_Action_PositionButton(button, OffsetX, OffsetY, bwidth, bheight, checked, nil);
if h == math.ceil((numBars) / cols) and z < numBars then
h = 0;
if MaxOffsetY < OffsetY then MaxOffsetY = OffsetY; end
OffsetY = bpadding;
OffsetX = OffsetX + bwidth + bcspace;
if orientation == 1 then
OffsetY = HealBot_Action_PositionButton(button, OffsetX, OffsetY, bwidth, bheight, checked, nil);
if h == limit and z < numBars then
h = 0;
if MaxOffsetY < OffsetY then MaxOffsetY = OffsetY; end
OffsetY = bpadding;
OffsetX = OffsetX + bwidth + bcspace;
end
else
OffsetX = HealBot_Action_PositionButtonHorizontal(button, OffsetX, OffsetY, bwidth, bheight, checked, nil);
if h == limit and z < numBars then
h = 0;
if MaxOffsetX < OffsetX then MaxOffsetX = OffsetX; end
OffsetX = bpadding;
OffsetY = OffsetY + bheight + brspace;
end
end
z = z + 1;
h = h + 1;
local bar = HealBot_Action_HealthBar(button);
@@ -787,9 +894,29 @@ function HealBot_Action_PartyChanged()
bar:SetScale(barScale);
bar2:SetHeight(bheight);
HealBot_Action_SetTexture(bar2, btexture);
end);
end
if MaxOffsetY < OffsetY then MaxOffsetY = OffsetY; end
if orientation == 1 then
if MaxOffsetY < OffsetY then MaxOffsetY = OffsetY; end
else
if MaxOffsetX < OffsetX then MaxOffsetX = OffsetX; end
-- In horizontal mode, OffsetY represents the active row. We need to measure total height.
MaxOffsetY = OffsetY + bheight + brspace
OffsetX = MaxOffsetX
if numBars > 0 then
OffsetX = OffsetX - bwidth - bcspace
end
end
HealBot_Grid_LastI = i;
HealBot_Grid_LastH = h;
HealBot_Grid_LastZ = z;
HealBot_Grid_OffsetX = OffsetX;
HealBot_Grid_OffsetY = OffsetY;
HealBot_Grid_MaxOffsetX = MaxOffsetX;
HealBot_Grid_MaxOffsetY = MaxOffsetY;
HealBot_Grid_Limit = limit;
HealBot_Grid_NumBars = numBars;
if HealBot_Config.HideOptions == 1 then
HealBot_Action_OptionsButton:Hide();
@@ -885,3 +1012,129 @@ function HealBot_Action_Refresh(unit)
end
end
end
function HealBot_Action_AppendUnit(unit)
if not HealBot_Grid_LastI then return end
if HealBot_Grid_LastI >= 100 then return end
HealBot_Grid_LastI = HealBot_Grid_LastI + 1
HealBot_Grid_NumBars = HealBot_Grid_NumBars + 1
local button = HealBot_Action_SetHealButton(HealBot_Grid_LastI, unit)
if not button then return end
local orientation = (HealBot_Config.GridOrientation and HealBot_Config.GridOrientation[HealBot_Config.Current_Skin]) or 1
local bwidth = (HealBot_Config.bwidth and HealBot_Config.bwidth[HealBot_Config.Current_Skin]) or 85
local bheight = (HealBot_Config.bheight and HealBot_Config.bheight[HealBot_Config.Current_Skin]) or 18
local bcspace = (HealBot_Config.bcspace and HealBot_Config.bcspace[HealBot_Config.Current_Skin]) or 3
local brspace = (HealBot_Config.brspace and HealBot_Config.brspace[HealBot_Config.Current_Skin]) or 3
local bpadding = (HealBot_Config.bpadding and HealBot_Config.bpadding[HealBot_Config.Current_Skin]) or 10
if orientation == 1 then
HealBot_Grid_OffsetY = HealBot_Action_PositionButton(button, HealBot_Grid_OffsetX, HealBot_Grid_OffsetY, bwidth, bheight, false, nil)
if HealBot_Grid_LastH == HealBot_Grid_Limit then
HealBot_Grid_LastH = 0
if HealBot_Grid_MaxOffsetY < HealBot_Grid_OffsetY then HealBot_Grid_MaxOffsetY = HealBot_Grid_OffsetY end
HealBot_Grid_OffsetY = bpadding
HealBot_Grid_OffsetX = HealBot_Grid_OffsetX + bwidth + bcspace
end
else
HealBot_Grid_OffsetX = HealBot_Action_PositionButtonHorizontal(button, HealBot_Grid_OffsetX, HealBot_Grid_OffsetY, bwidth, bheight, false, nil)
if HealBot_Grid_LastH == HealBot_Grid_Limit then
HealBot_Grid_LastH = 0
if HealBot_Grid_MaxOffsetX < HealBot_Grid_OffsetX then HealBot_Grid_MaxOffsetX = HealBot_Grid_OffsetX end
HealBot_Grid_OffsetX = bpadding
HealBot_Grid_OffsetY = HealBot_Grid_OffsetY + bheight + brspace
end
end
HealBot_Grid_LastH = HealBot_Grid_LastH + 1
HealBot_Grid_LastZ = HealBot_Grid_LastZ + 1
local bar = HealBot_Action_HealthBar(button)
local bar2 = HealBot_Action_HealthBar2(button)
bar.txt = getglobal(bar:GetName() .. "_text")
bar:SetHeight(bheight)
local btexture = (HealBot_Config.btexture and HealBot_Config.btexture[HealBot_Config.Current_Skin]) or 5
HealBot_Action_SetTexture(bar, btexture)
local btextheight = (HealBot_Config.btextheight and HealBot_Config.btextheight[HealBot_Config.Current_Skin]) or 10
bar.txt:SetTextHeight(btextheight)
bar2:SetHeight(bheight)
HealBot_Action_SetTexture(bar2, btexture)
local totalOffsetX = HealBot_Grid_OffsetX
local totalOffsetY = HealBot_Grid_OffsetY
if orientation == 1 then
if HealBot_Grid_MaxOffsetY < totalOffsetY then HealBot_Grid_MaxOffsetY = totalOffsetY end
totalOffsetY = HealBot_Grid_MaxOffsetY
else
if HealBot_Grid_MaxOffsetX < totalOffsetX then HealBot_Grid_MaxOffsetX = totalOffsetX end
totalOffsetX = HealBot_Grid_MaxOffsetX
totalOffsetY = totalOffsetY + bheight + brspace
end
HealBot_Action_SetHeightWidth(totalOffsetX, totalOffsetY + bpadding, bwidth)
end
function HealBot_Action_AppendNewUnits()
if not HealBot_Grid_LastI then return end
local unitsToCheck = {}
-- Gather units based on config, similar to PartyChanged
if HealBot_Config.GroupHeals == 1 then
for _, unit in ipairs(HealBot_Action_HealGroup) do
table.insert(unitsToCheck, unit)
end
end
if HealBot_Config.TankHeals == 1 and GetNumRaidMembers() > 0 and CT_RA_MainTanks then
for j = 1, 10 do
if CT_RA_MainTanks[j] then
for k = 1, GetNumRaidMembers() do
local unit = "raid" .. k
if UnitName(unit) == CT_RA_MainTanks[j] then
table.insert(unitsToCheck, unit)
end
end
end
end
end
if HealBot_Config.TargetHeals == 1 then
for _, unit in ipairs(HealBot_Action_HealTarget) do
table.insert(unitsToCheck, unit)
end
table.insert(unitsToCheck, "target")
end
if HealBot_Config.EmergencyHeals == 1 then
if GetNumRaidMembers() > 0 then
for j = 1, 40 do
table.insert(unitsToCheck, "raid" .. j)
end
else
for j = 1, 4 do
table.insert(unitsToCheck, "party" .. j)
end
table.insert(unitsToCheck, "player")
end
end
if HealBot_Config.PetHeals == 1 then
if GetNumRaidMembers() > 0 then
for j = 1, 40 do
table.insert(unitsToCheck, "raidpet" .. j)
end
else
for j = 1, 4 do
table.insert(unitsToCheck, "partypet" .. j)
end
table.insert(unitsToCheck, "pet")
end
end
for _, unit in ipairs(unitsToCheck) do
if not HealBot_Action_UnitButtons[unit] and HealBot_MayHeal(unit) then
HealBot_Action_AppendUnit(unit)
end
end
end
+30 -10
View File
@@ -3,6 +3,16 @@
HealBot_Action_TooltipUnit = nil
function HealBot_Tooltip_GetSpellColor(spell)
local r, g, b = 1, 1, 0 -- default yellow
if spell and HealBot_Spells and HealBot_Spells[spell] and HealBot_Spells[spell].Mana then
if UnitMana("player") < HealBot_Spells[spell].Mana then
r, g, b = 1, 0, 0 -- red if not enough mana
end
end
return r, g, b
end
function HealBot_Action_RefreshTooltip(unit)
if HealBot_Config.ShowTooltip==0 then return end
if not unit then unit = HealBot_Action_TooltipUnit end
@@ -33,53 +43,63 @@ function HealBot_Action_RefreshTooltip(unit)
if HealBot_Config.Tooltip_ShowSpellDetail==1 then
if spellLeft then
linenum=linenum+2
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_OPTIONS_BUTTONLEFT.." "..HEALBOT_OPTIONS_COMBOBUTTON..": "..spellLeft,1,1,0,linenum)
local sr, sg, sb = HealBot_Tooltip_GetSpellColor(spellLeft)
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_OPTIONS_BUTTONLEFT.." "..HEALBOT_OPTIONS_COMBOBUTTON..": "..spellLeft,sr,sg,sb,linenum)
linenum=HealBot_Action_Tooltip_SpellInfo(spellLeft,linenum);
end
if spellMiddle then
linenum=linenum+2
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_OPTIONS_BUTTONMIDDLE.." "..HEALBOT_OPTIONS_COMBOBUTTON..": "..spellMiddle,1,1,0,linenum)
local sr, sg, sb = HealBot_Tooltip_GetSpellColor(spellMiddle)
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_OPTIONS_BUTTONMIDDLE.." "..HEALBOT_OPTIONS_COMBOBUTTON..": "..spellMiddle,sr,sg,sb,linenum)
linenum=HealBot_Action_Tooltip_SpellInfo(spellMiddle,linenum);
end
if spellRight then
linenum=linenum+2
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_OPTIONS_BUTTONRIGHT.." "..HEALBOT_OPTIONS_COMBOBUTTON..": "..spellRight,1,1,0,linenum)
local sr, sg, sb = HealBot_Tooltip_GetSpellColor(spellRight)
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_OPTIONS_BUTTONRIGHT.." "..HEALBOT_OPTIONS_COMBOBUTTON..": "..spellRight,sr,sg,sb,linenum)
linenum=HealBot_Action_Tooltip_SpellInfo(spellRight,linenum);
end
if spellButton4 then
linenum=linenum+2
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_OPTIONS_BUTTON4.." "..HEALBOT_OPTIONS_COMBOBUTTON..": "..spellButton4,1,1,0,linenum)
local sr, sg, sb = HealBot_Tooltip_GetSpellColor(spellButton4)
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_OPTIONS_BUTTON4.." "..HEALBOT_OPTIONS_COMBOBUTTON..": "..spellButton4,sr,sg,sb,linenum)
linenum=HealBot_Action_Tooltip_SpellInfo(spellButton4,linenum);
end
if spellButton5 then
linenum=linenum+2
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_OPTIONS_BUTTON5.." "..HEALBOT_OPTIONS_COMBOBUTTON..": "..spellButton5,1,1,0,linenum)
local sr, sg, sb = HealBot_Tooltip_GetSpellColor(spellButton5)
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_OPTIONS_BUTTON5.." "..HEALBOT_OPTIONS_COMBOBUTTON..": "..spellButton5,sr,sg,sb,linenum)
linenum=HealBot_Action_Tooltip_SpellInfo(spellButton5,linenum);
end
else
if spellLeft then
linenum=linenum+1
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_OPTIONS_BUTTONLEFT..":",1,1,0,linenum)
local sr, sg, sb = HealBot_Tooltip_GetSpellColor(spellLeft)
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_OPTIONS_BUTTONLEFT..":",sr,sg,sb,linenum)
HealBot_Action_Tooltip_SetLineRight(HealBot_Action_Tooltip_SpellSummary(spellLeft),1,1,1,linenum)
end
if spellMiddle then
linenum=linenum+1
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_OPTIONS_BUTTONMIDDLE..":",1,1,0,linenum)
local sr, sg, sb = HealBot_Tooltip_GetSpellColor(spellMiddle)
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_OPTIONS_BUTTONMIDDLE..":",sr,sg,sb,linenum)
HealBot_Action_Tooltip_SetLineRight(HealBot_Action_Tooltip_SpellSummary(spellMiddle),1,1,1,linenum)
end
if spellRight then
linenum=linenum+1
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_OPTIONS_BUTTONRIGHT..":",1,1,0,linenum)
local sr, sg, sb = HealBot_Tooltip_GetSpellColor(spellRight)
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_OPTIONS_BUTTONRIGHT..":",sr,sg,sb,linenum)
HealBot_Action_Tooltip_SetLineRight(HealBot_Action_Tooltip_SpellSummary(spellRight),1,1,1,linenum)
end
if spellButton4 then
linenum=linenum+1
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_OPTIONS_BUTTON4..":",1,1,0,linenum)
local sr, sg, sb = HealBot_Tooltip_GetSpellColor(spellButton4)
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_OPTIONS_BUTTON4..":",sr,sg,sb,linenum)
HealBot_Action_Tooltip_SetLineRight(HealBot_Action_Tooltip_SpellSummary(spellButton4),1,1,1,linenum)
end
if spellButton5 then
linenum=linenum+1
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_OPTIONS_BUTTON5..":",1,1,0,linenum)
local sr, sg, sb = HealBot_Tooltip_GetSpellColor(spellButton5)
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_OPTIONS_BUTTON5..":",sr,sg,sb,linenum)
HealBot_Action_Tooltip_SetLineRight(HealBot_Action_Tooltip_SpellSummary(spellButton5),1,1,1,linenum)
end
end
+37 -5
View File
@@ -1,10 +1,11 @@
**HealBotBlue**
By Bluewhale.
> **NOTE:** For HealBot to work correctly, the **Selfcast** feature in WoW options needs to be disabled.
Original HealBot, while being a staple healing addon in Wrath and later expansions, was in its infancy during Vanilla WoW. It was a memory and CPU hog that ate up resources, featured a clunky UI, and offered limited functions. To fix all of the above while still using it as a base framework, I refactored the entire codebase. The monolithic code structure was split to follow a more modern approach (MVC design pattern), making it more stable and easily editable. Additionally, the inefficient AURA scanning was replaced with lightweight (Observer Pattern) reactive programming. It now updates only what is necessary when a trigger fires, rather than performing clumsy, continuous scans of a 40-man raid. By doing so, I managed to throttle down CPU and memory usage significantly, placing it on par with modern addons. Additional functionalities are being added over time to provide a holistic, healer-centered raid frame.
> **NOTE:** For HealBot to work correctly, the **Selfcast** feature in WoW options needs to be disabled.
> **Performance First:** The raidframe is not library reliant - unlike popular raidframe replacement addons it doesn't rely at all on external frameworks. While this makes my work a bit harder this allows complete control over garbage collection and CPU use which makes it multiple times more stable and lightweight.
### Reporting Errors
Major errors will pop up a frame with error information. Take a screenshot and post comments.
@@ -19,24 +20,55 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\
* `/hb reset` - Resets the contents of the main HealBot panel
### Key Features & Current Functionality
* **MVC & Observer Architecture:** High-performance, reactive engine that updates frames dynamically on state changes, drastically reducing CPU and memory overhead compared to traditional polling.
* **MVC & Observer Architecture:** High-performance, reactive engine that updates frames dynamically on state changes, drastically reducing CPU and memory overhead. Features memory recycling pool and event loop decoupling for zero-stutter combat.
* **Native Hovercasting (Mouseover):** Cast configured spells on hovered unit frames using keybinds directly from your action bars, without losing your current target. (Toggleable in Options -> General).
* **Macro, Item, & Script Bindings:** Bind named macros, inventory items, and scripts directly to mouse clicks. Supports implicit `@mouseover` targeting natively.
* **Zero-Latency Self-Heals:** Incoming heals for the local player process instantly with zero latency, independent of network lag.
* **Talent-Based Calculations & Equipment Bonus:** Dynamic spell healing calculations for Druid, Priest, and Paladin based on talents, and automatically scans equipped gear to scale healing predictions - currently only TurtleWoW patch 1.18 supported.
* **Modifier-Aware Tooltips:** Tooltips dynamically update to show exact bound actions (Shift/Ctrl/Alt) and required mana costs (turns red if insufficient mana).
* **Blizzard Party Frame Toggle:** Toggle to automatically hide Blizzard's default party frames when in a group in favor of HealBot's layouts.
* **HoT & Buff Tracking:** Intelligently track active HoTs and buffs directly on the grid frames with custom icons (e.g., Renew, Rejuvenation, Regrowth, Fear Ward).
* **Mana Bars for Healers:** Enable and position mini-mana status bars next to unit frames, toggleable to display for healer classes only or all classes.
* **Equipment Bonus Integration:** Automatically scans equipped gear (for classes capable of healing) to dynamically scale healing predictions.
* **Curse & Debuff Warning (CDC):** Dynamic visual and audio alerts for cleanable debuffs. Customizable colors based on debuff type (Curse, Poison, Disease, Magic).
* **Pet & Familiar Frames:** Dedicated, toggleable frames for tracking and healing player pets.
* **Customizable Health Text:** Dynamic unit health display (Name Only, Percentage, Real Health, or Health Deficit).
* **Non-Mana Resource Tracking:** Track Rage, Energy, and Focus for non-mana classes.
* **Highly Customizable Skins:** Fully configure dimensions (width, height), row spacing, column layouts, custom textures, opacity, class-colored frames, and outline of fonts.
### To be implemented
- **GUID-based frame mapping:** Migrate internal state to use lightweight GUID tracking to resolve bugs when targets switch or duplicate names appear (e.g., enemy mobs, warlock pets).
- **Mod Integration Optimization:** Add conditional SuperWoW/UnitXP SP3 integration to reduce GC spikes and improve frame rendering accuracy.
### Known issues
* **New spell rank bug** you may experience lua error spaming your chat frame after learning new healing spells. /reload will clear the issue. To be fixed next release
* **New spell rank bug** you may experience lua error spaming your chat frame after learning new healing spells. /reload will clear the issue.
### Change Log
**v1.6.1**
* **Hotfix - pet frames** - With class colours toggled extra frames for player pets were given some classy mint colour.
* **Hotfi - raidframes in combat** - Modfied how frames behave when player leaves during combat.
**v1.6**
* **Event Loop Decoupling:** Ripped out redundant synchronous UI redraws that were bypassed by the new MVC architecture. High-frequency events (mana regen, health ticks) now fully rely on the `HealBot_OnUpdate` dirty queue, severely reducing CPU bottlenecks.
* **Combat UI Optimizations:** Removed unnecessary full spell recalculations when dropping combat, preventing client stutter after every mob kill.
* **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.
* **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.
Binary file not shown.
+23
View File
@@ -0,0 +1,23 @@
import re
with open('HealBot_Action.xml', 'r') as f:
content = f.read()
buttons_42_50 = '\n'.join([f' <Button name=\"HealBot_Action_HealUnit{i}\" inherits=\"HealingButtonTemplate\" text=\"Unit not set\"/>' for i in range(42, 51)])
buttons_61_100 = '\n'.join([f' <Button name=\"HealBot_Action_HealUnit{i}\" inherits=\"HealingButtonTemplate2\" text=\"Unit not set\"/>' for i in range(61, 101)])
content = re.sub(
r'(<Button name=\"HealBot_Action_HealUnit41\" [^\>]+>\n)',
r'\g<1>' + buttons_42_50 + '\n',
content
)
content = re.sub(
r'(<Button name=\"HealBot_Action_HealUnit60\" [^\>]+>\n)',
r'\g<1>' + buttons_61_100 + '\n',
content
)
with open('HealBot_Action.xml', 'w') as f:
f.write(content)
print('Updated HealBot_Action.xml')