8 Commits

Author SHA1 Message Date
Bluewhale1337 178d1184a3 docs: add Talents.md 2026-07-26 13:59:23 +02:00
Bluewhale1337 f1b7e3950f chore: bump version to 1.6.2 in TOC file 2026-07-26 13:48:35 +02:00
Bluewhale1337 faf040997e feat: refactor spell tooltip scanning and update version to 1.6.2 2026-07-24 20:22:49 +02:00
Bluewhale1337 4c9f50770a fix: remove redundant end statement in layout refresh function 2026-07-22 11:19:21 +02:00
Bluewhale1337 ed11046eda Cleaning up some leftovers 2026-07-22 09:55:17 +02:00
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
7 changed files with 313 additions and 58 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
## Interface: 11200 ## Interface: 11200
## Title: HealBotBlue ## Title: HealBotBlue
## Version: 1.6.0 ## Version: 1.6.2
## Author: Bluewhale ## Author: Bluewhale
## Notes: Adds panel with skinable bars for healing and decursive ## Notes: Adds panel with skinable bars for healing and decursive
## SavedVariablesPerCharacter: HealBot_Config ## SavedVariablesPerCharacter: HealBot_Config
+49
View File
@@ -232,6 +232,15 @@
<Button name="HealBot_Action_HealUnit39" inherits="HealingButtonTemplate" text="Unit not set"/> <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_HealUnit40" inherits="HealingButtonTemplate" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit41" 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_HealUnit51" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit52" 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_HealUnit58" inherits="HealingButtonTemplate2" text="Unit not set"/>
<Button name="HealBot_Action_HealUnit59" 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_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_Header1" inherits="HealingButtonTemplate4" text="Unit not set"/>
<Button name="HealBot_Action_Header2" inherits="HealingButtonTemplate4" text="Unit not set"/> <Button name="HealBot_Action_Header2" inherits="HealingButtonTemplate4" text="Unit not set"/>
+12 -1
View File
@@ -181,6 +181,16 @@ local HealBot_EventHandlers = {
HealBot_Model:NotifyObservers("ROSTER_CHANGED") HealBot_Model:NotifyObservers("ROSTER_CHANGED")
HealBot_OnEvent_PartyMembersChanged(this) HealBot_OnEvent_PartyMembersChanged(this)
end, 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) ["PLAYER_ENTERING_WORLD"] = function(this)
HealBot_Model:RefreshUnit("player") HealBot_Model:RefreshUnit("player")
HealBot_Model:RefreshUnit("pet") HealBot_Model:RefreshUnit("pet")
@@ -282,6 +292,7 @@ function HealBot_OnEvent_VariablesLoaded(this)
this:RegisterEvent("PLAYER_REGEN_ENABLED"); this:RegisterEvent("PLAYER_REGEN_ENABLED");
this:RegisterEvent("PLAYER_TARGET_CHANGED"); this:RegisterEvent("PLAYER_TARGET_CHANGED");
this:RegisterEvent("PARTY_MEMBERS_CHANGED"); this:RegisterEvent("PARTY_MEMBERS_CHANGED");
this:RegisterEvent("RAID_ROSTER_UPDATE");
this:RegisterEvent("PARTY_MEMBER_DISABLE"); this:RegisterEvent("PARTY_MEMBER_DISABLE");
this:RegisterEvent("PARTY_MEMBER_ENABLE"); this:RegisterEvent("PARTY_MEMBER_ENABLE");
this:RegisterEvent("UNIT_PET"); this:RegisterEvent("UNIT_PET");
@@ -365,7 +376,7 @@ end
function HealBot_OnEvent_PlayerRegenEnabled(this) function HealBot_OnEvent_PlayerRegenEnabled(this)
HealBot_IsFighting = false; HealBot_IsFighting = false;
-- Removed HealBot_Delay_RecalcParty = 1; HealBot_Delay_RecalcParty = 1;
end end
function HealBot_OnEvent_PlayerTargetChanged(this) function HealBot_OnEvent_PlayerTargetChanged(this)
+35 -35
View File
@@ -608,47 +608,47 @@ function HealBot_InitGetSpellData(spell, id, class)
HealBot_ScanTooltip:SetOwner(HealBot_ScanTooltip, "ANCHOR_NONE") HealBot_ScanTooltip:SetOwner(HealBot_ScanTooltip, "ANCHOR_NONE")
HealBot_ScanTooltip:SetSpell(id, BOOKTYPE_SPELL); HealBot_ScanTooltip:SetSpell(id, BOOKTYPE_SPELL);
tmpText = getglobal("HealBot_ScanTooltipTextLeft2"); _mana = 0;
if (tmpText:GetText()) then _range = 40;
line = tmpText:GetText();
tmpTest, tmpTest, _mana = string.find(line, HEALBOT_TOOLTIP_MANA);
else
HealBot_Report_Error("================================");
HealBot_Report_Error("ERROR: HealBot_ScanTooltip is lost");
HealBot_Report_Error("ERROR: If BonusScanner is used, try disabling BonusScanner");
end
tmpText = getglobal("HealBot_ScanTooltipTextRight2");
if (tmpText:GetText()) then
line = tmpText:GetText();
tmpTest, tmpTest, _range = string.find(line, HEALBOT_TOOLTIP_RANGE);
else
HealBot_Report_Error("================================");
HealBot_Report_Error("ERROR: HealBot_ScanTooltip is lost");
HealBot_Report_Error("ERROR: If BonusScanner is used, try disabling BonusScanner");
end
tmpText = getglobal("HealBot_ScanTooltipTextLeft3");
_cast = nil;
if (tmpText:GetText()) then
line = tmpText:GetText();
if (line == HEALBOT_TOOLTIP_INSTANT_CAST) then
_cast = 0; _cast = 0;
elseif line == HEALBOT_TOOLTIP_CHANNELED then line = nil;
for lineNum = 2, 6 do
local lText = getglobal("HealBot_ScanTooltipTextLeft"..lineNum);
if lText and lText:IsVisible() and lText:GetText() then
local txt = lText:GetText();
local t1, t2, match;
t1, t2, match = string.find(txt, HEALBOT_TOOLTIP_MANA);
if match then _mana = match; end
if txt == HEALBOT_TOOLTIP_INSTANT_CAST or txt == "Instant" then
_cast = 0;
elseif txt == HEALBOT_TOOLTIP_CHANNELED then
_cast = 0; _cast = 0;
elseif (tmpText) then
tmpTest, tmpTest, _cast = string.find(line, HEALBOT_TOOLTIP_CAST_TIME);
end
else else
HealBot_Report_Error("================================"); t1, t2, match = string.find(txt, HEALBOT_TOOLTIP_CAST_TIME);
HealBot_Report_Error("ERROR: HealBot_ScanTooltip is lost"); if match then _cast = match; end
HealBot_Report_Error("ERROR: If BonusScanner is used, try disabling BonusScanner"); end
t1, t2, match = string.find(txt, HEALBOT_TOOLTIP_RANGE);
if match then _range = match; end
if not string.find(txt, HEALBOT_TOOLTIP_MANA) and txt ~= HEALBOT_TOOLTIP_INSTANT_CAST and txt ~= "Instant" and txt ~= HEALBOT_TOOLTIP_CHANNELED and not string.find(txt, HEALBOT_TOOLTIP_CAST_TIME) and not string.find(txt, HEALBOT_TOOLTIP_RANGE) then
if not line then line = txt; end
end
end
local rText = getglobal("HealBot_ScanTooltipTextRight"..lineNum);
if rText and rText:IsVisible() and rText:GetText() then
local txt = rText:GetText();
local t1, t2, match;
t1, t2, match = string.find(txt, HEALBOT_TOOLTIP_RANGE);
if match then _range = match; end
end
end end
tmpText = getglobal("HealBot_ScanTooltipTextLeft4");
tmpTest = nil; tmpTest = nil;
if (tmpText:GetText()) then if line then
line = tmpText:GetText();
if class == "PRIEST" then if class == "PRIEST" then
if string.sub(spell, 1, 14) == string.sub(HEALBOT_POWER_WORD_SHIELD, 1, 14) then if string.sub(spell, 1, 14) == string.sub(HEALBOT_POWER_WORD_SHIELD, 1, 14) then
tmpTest, tmpTest, _HealsMin, _shield = string.find(line, HEALBOT_SPELL_PATTERN_SHIELD); tmpTest, tmpTest, _HealsMin, _shield = string.find(line, HEALBOT_SPELL_PATTERN_SHIELD);
+157 -9
View File
@@ -70,13 +70,13 @@ function HealBot_HealthColor(unit, hlth, maxhlth)
end end
local colorMode = HealBot_Config.bcolormode[HealBot_Config.Current_Skin] or 1 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 local engClass = HealBot_Model.units[unit].englishClass
if RAID_CLASS_COLORS and RAID_CLASS_COLORS[engClass] then
r = RAID_CLASS_COLORS[engClass].r r = RAID_CLASS_COLORS[engClass].r
g = RAID_CLASS_COLORS[engClass].g g = RAID_CLASS_COLORS[engClass].g
b = RAID_CLASS_COLORS[engClass].b b = RAID_CLASS_COLORS[engClass].b
end elseif colorMode == 2 and string.find(unit, "pet") then
r, g, b = 0.4, 0.9, 0.6 -- Mint color
else else
if pct >= 0.98 then r = 0.0; end if pct >= 0.98 then r = 0.0; end
if pct < 0.98 and pct >= 0.65 then r = 2.94 - (pct * 3); end if pct < 0.98 and pct >= 0.65 then r = 2.94 - (pct * 3); end
@@ -110,6 +110,11 @@ function HealBot_Action_EnableButton(button)
local name = state.name local name = state.name
if not name then name = UnitName(unit) end -- fallback 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 bar = HealBot_Action_HealthBar(button);
local bar2 = HealBot_Action_HealthBar2(button); local bar2 = HealBot_Action_HealthBar2(button);
if not button.bar3 then button.bar3 = getglobal(button:GetName() .. "Bar3") end if not button.bar3 then button.bar3 = getglobal(button:GetName() .. "Bar3") end
@@ -402,6 +407,7 @@ function HealBot_Action_SetHealButton(index, unit)
return nil return nil
end end
local button = getglobal("HealBot_Action_HealUnit" .. index); local button = getglobal("HealBot_Action_HealUnit" .. index);
if not button then return nil end
button.unit = unit; button.unit = unit;
if unit then if unit then
table.insert(HealBot_Action_HealButtons, button); table.insert(HealBot_Action_HealButtons, button);
@@ -414,7 +420,11 @@ function HealBot_Action_SetHealButton(index, unit)
end end
function HealBot_Action_PartyChanged() function HealBot_Action_PartyChanged()
if not HealBot_IsFighting then if HealBot_IsFighting then
HealBot_Action_AppendNewUnits()
return
end
local numBars = 0; local numBars = 0;
local numHeaders = 0; local numHeaders = 0;
local TempMaxH = 0; local TempMaxH = 0;
@@ -466,10 +476,7 @@ function HealBot_Action_PartyChanged()
local checked_end = 0; local checked_end = 0;
headerno = 0; headerno = 0;
for j = 1, 41 do for j = 1, 100 do
HealBot_Action_SetHealButton(j, nil);
end
for j = 51, 60 do
HealBot_Action_SetHealButton(j, nil); HealBot_Action_SetHealButton(j, nil);
end end
HealBot_Action_SetHealButton(); HealBot_Action_SetHealButton();
@@ -628,6 +635,9 @@ function HealBot_Action_PartyChanged()
else else
for _, unit in ipairs(HealBot_Action_HealGroup) do for _, unit in ipairs(HealBot_Action_HealGroup) do
if not HealBot_Action_UnitButtons[unit] and HealBot_MayHeal(unit) then if not HealBot_Action_UnitButtons[unit] and HealBot_MayHeal(unit) then
local name = UnitName(unit) or "not known"
local class = UnitClass(unit) or "not known"
local subgroup = 1
if HealBot_Config.ExtraOrder == 1 then if HealBot_Config.ExtraOrder == 1 then
order[unit] = name; order[unit] = name;
elseif HealBot_Config.ExtraOrder == 2 then elseif HealBot_Config.ExtraOrder == 2 then
@@ -726,6 +736,9 @@ function HealBot_Action_PartyChanged()
else else
for _, unit in ipairs(HealBot_Action_HealGroup) do for _, unit in ipairs(HealBot_Action_HealGroup) do
if not HealBot_Action_UnitButtons[unit] and HealBot_MayHeal(unit) then if not HealBot_Action_UnitButtons[unit] and HealBot_MayHeal(unit) then
local name = UnitName(unit) or "not known"
local class = UnitClass(unit) or "not known"
local subgroup = 1
if HealBot_Config.ExtraOrder == 1 then if HealBot_Config.ExtraOrder == 1 then
order[unit] = name; order[unit] = name;
elseif HealBot_Config.ExtraOrder == 2 then elseif HealBot_Config.ExtraOrder == 2 then
@@ -901,6 +914,16 @@ function HealBot_Action_PartyChanged()
end end
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 if HealBot_Config.HideOptions == 1 then
HealBot_Action_OptionsButton:Hide(); HealBot_Action_OptionsButton:Hide();
else else
@@ -945,7 +968,6 @@ function HealBot_Action_PartyChanged()
if HealBot_Config.HideParty == 1 and HidePartyFrame then if HealBot_Config.HideParty == 1 and HidePartyFrame then
HidePartyFrame(); HidePartyFrame();
end end
end
HealBot_Action_RefreshButtons(); HealBot_Action_RefreshButtons();
HealBot_Action_ShowFrame(); HealBot_Action_ShowFrame();
end end
@@ -995,3 +1017,129 @@ function HealBot_Action_Refresh(unit)
end end
end 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
+12 -5
View File
@@ -1,10 +1,11 @@
**HealBotBlue** **HealBotBlue**
By Bluewhale. 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. 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.
> **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.
> **NOTE:** For HealBot to work correctly, the **Selfcast** feature in WoW options needs to be disabled.
### Reporting Errors ### Reporting Errors
Major errors will pop up a frame with error information. Take a screenshot and post comments. Major errors will pop up a frame with error information. Take a screenshot and post comments.
@@ -19,12 +20,15 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\
* `/hb reset` - Resets the contents of the main HealBot panel * `/hb reset` - Resets the contents of the main HealBot panel
### Key Features & Current Functionality ### 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). * **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. * **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). * **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. * **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). * **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. * **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). * **Customizable Health Text:** Dynamic unit health display (Name Only, Percentage, Real Health, or Health Deficit).
@@ -37,11 +41,14 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\
### Known issues ### 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 ### 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** **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. * **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.
+40
View File
@@ -0,0 +1,40 @@
Druid:
Name - Rank - Effect
Genesis - 1 - increase damage and healing of periodic spells by 5%
Genesis - 2 - increase damage and healing of periodic spells by 10%
Genesis - 3 -increase damage and healing of periodic spells by 15%
Gift of Nature - 1- Increases effectivenes of all healing spells by 2%
Gift of Nature - 2- Increases effectivenes of all healing spells by 4%
Gift of Nature - 3- Increases effectivenes of all healing spells by 6%
Gift of Nature - 4- Increases effectivenes of all healing spells by 8%
Gift of Nature - 5- Increases effectivenes of all healing spells by 10%
Preservation - 1 - Increases the periodic healing of Regrowth by 10% if target is affected by Rejuvenation
Preservation - 2 - Increases the periodic healing of Regrowth by 20% if target is affected by Rejuvenation
Preservation - 3 - Increases the periodic healing of Regrowth by 30% if target is affected by Rejuvenation
Paladin:
Healing Light - 1 - Increases the amount of healed by Holy Light, Flash of Light and Holy Shock by 4%
Healing Light - 2 - Increases the amount of healed by Holy Light, Flash of Light and Holy Shock by 8%
Healing Light - 3 - Increases the amount of healed by Holy Light, Flash of Light and Holy Shock by 12%
Ironclad - 1 - Improves healing done by 1% of current armour from items
Ironclad - 2 - Improves healing done by 2% of current armour from items
Priest:
Improved Renew - 1 - Improves amount healed by renew by 5%
Improved Renew - 2 - Improves amount healed by renew by 10%
Improved Renew - 3 - Improves amount healed by renew by 15%
Spiritual Healing - 1 - Improves amount healed by all healing spells by 6%
Spiritual Healing - 2 - Improves amount healed by all healing spells by 12%
Spiritual Healing - 3 - Improves amount healed by all healing spells by 18%
Spiritual Healing - 4 - Improves amount healed by all healing spells by 24%
Spiritual Healing - 5 - Improves amount healed by all healing spells by 30%
Shaman:
none