Further modularization of HealBot codebase by splitting core logic into dedicated controller and view components

This commit is contained in:
Bluewhale1337
2026-06-25 19:33:48 +02:00
parent 786e5d66df
commit 3ae3f26f77
12 changed files with 2429 additions and 2453 deletions
+19 -1390
View File
File diff suppressed because it is too large Load Diff
+21 -15
View File
@@ -1,17 +1,24 @@
## Interface: 11200
## Title: HealBotBlue
## Version: 1.3
## Author: Bluewhale
## Notes: Adds panel with skinable bars for healing and decursive
## SavedVariables: HealBot_Config
..\..\FrameXML\Fonts.xml
..\..\FrameXML\OptionsFrameTemplates.xml
..\..\FrameXML\UIPanelTemplates.xml
..\..\FrameXML\UIDropDownMenu.xml
HealBot_Error.xml
HealBot_Model.lua
HealBot.xml
HealBot_Action.xml
## Interface: 11200
## Title: HealBotBlue
## Version: 1.3
## Author: Bluewhale
## Notes: Adds panel with skinable bars for healing and decursive
## SavedVariables: HealBot_Config
..\..\FrameXML\Fonts.xml
..\..\FrameXML\OptionsFrameTemplates.xml
..\..\FrameXML\UIPanelTemplates.xml
..\..\FrameXML\UIDropDownMenu.xml
HealBot_Error.xml
HealBot_Model.lua
HealBot_Controller_Range.lua
HealBot_Controller_Comms.lua
HealBot_Controller_Aura.lua
HealBot_Controller_Spells.lua
HealBot_Controller_Events.lua
HealBot.xml
HealBot_View_Layout.lua
HealBot_View_Tooltip.lua
HealBot_Action.xml
HealBot_Options.xml
HealBot_Options_General.xml
HealBot_Options_Spells.xml
@@ -20,4 +27,3 @@ HealBot_Options_CDC.xml
HealBot_Options_Skins.xml
HealBot_Options_Buffs.xml
HealBot_Options_Chat.xml
+3 -1045
View File
File diff suppressed because it is too large Load Diff
+182
View File
@@ -0,0 +1,182 @@
-- HealBot_Controller_Aura.lua
-- Handles tracking buffs/debuffs (auras) on group/raid units
HealBot_MissingBuffs = {}
function HealBot_UnitAffected(unit, effect)
if not effect then return nil; end
local i = 1
while true do
local buff = UnitBuff(unit, i)
if not buff then
break
end
if buff == effect then
return buff
end
i = i + 1
end
i = 1
while true do
local debuff = UnitDebuff(unit, i)
if not debuff then
break
end
if debuff == effect then
return debuff
end
i = i + 1
end
return nil;
end
function HealBot_CheckShamanWeaponBuff(spellName)
local hasMainHandEnchant, _, _, hasOffHandEnchant = GetWeaponEnchantInfo()
if hasMainHandEnchant or hasOffHandEnchant then
return true
end
return false
end
function HealBot_CheckBuffs(unit)
if HealBot_Config.BuffWatch ~= 1 then
HealBot_MissingBuffs[unit] = nil
return
end
local inCombat = UnitAffectingCombat("player") or UnitAffectingCombat(unit)
if inCombat and HealBot_Config.BuffWatchInCombat ~= 1 then
HealBot_MissingBuffs[unit] = nil
return
end
local myClass = UnitClass("player")
if not HealBot_Buff_Spells[myClass] then return end
if UnitIsDeadOrGhost(unit) or not UnitIsConnected(unit) then
HealBot_MissingBuffs[unit] = nil
return
end
-- Group Buff Equivalents
local HealBot_Buff_Equivalents = {
[HEALBOT_POWER_WORD_FORTITUDE] = HEALBOT_PRAYER_OF_FORTITUDE,
[HEALBOT_DIVINE_SPIRIT] = HEALBOT_PRAYER_OF_SPIRIT,
[HEALBOT_SHADOW_PROTECTION] = HEALBOT_PRAYER_OF_SHADOW_PROTECTION,
[HEALBOT_ARCANE_INTELLECT] = HEALBOT_ARCANE_BRILLIANCE,
[HEALBOT_MARK_OF_THE_WILD] = HEALBOT_GIFT_OF_THE_WILD,
}
-- Gather buffs on unit
local hasBuff = {}
local i = 1
while true do
local buffTexture = UnitBuff(unit, i)
if not buffTexture then break end
HealBot_ScanTooltip:SetOwner(UIParent, "ANCHOR_NONE")
HealBot_ScanTooltip:ClearLines()
HealBot_ScanTooltip:SetUnitBuff(unit, i)
local buffName = HealBot_ScanTooltipTextLeft1:GetText()
if buffName then
hasBuff[buffName] = true
end
i = i + 1
end
HealBot_ScanTooltip:Hide()
HealBot_MissingBuffs[unit] = nil
if HealBot_Config.BuffDropDowns and HealBot_Config.BuffDropDowns[myClass] then
for j = 1, 8 do
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
local spellName = HealBot_Buff_Spells[myClass][val]
local hasIt = hasBuff[spellName]
if not hasIt and HealBot_Buff_Equivalents[spellName] then
hasIt = hasBuff[HealBot_Buff_Equivalents[spellName]]
end
if not hasIt then
if myClass == "SHAMAN" and unit == "player" and string.find(spellName, " Weapon") then
hasIt = HealBot_CheckShamanWeaponBuff(spellName)
end
end
if not hasIt then
HealBot_MissingBuffs[unit] = spellName
break
end
end
end
end
end
end
function HealBot_OnEvent_UnitAura(this, unit)
local DebuffType;
if HealBot_Heals[unit] and unit ~= "target" then
HealBot_UnitIcons[unit] = {}
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,
}
local i = 1;
while true do
local debuff, tmp, debuff_type = UnitDebuff(unit, i, 1)
if debuff then
if iconCount < 5 then
iconCount = iconCount + 1
HealBot_UnitIcons[unit][iconCount] = debuff
end
if HealBot_CDCInc[UnitClass(unit)] == 1 and HealBot_DebuffWatch[debuff_type] == "YES" then
HealBot_UnitDebuff[unit] = debuff_type
DebuffType = debuff_type;
if HealBot_DebuffPriority[debuff_type] then
break
end
end
i = i + 1;
else
if i == 1 then HealBot_UnitDebuff[unit] = nil; end
break
end
end
local b = 1
while true do
local buff = UnitBuff(unit, b)
if not buff then break end
if HealBot_TrackedHoTs[buff] and iconCount < 5 then
iconCount = iconCount + 1
HealBot_UnitIcons[unit][iconCount] = buff
end
b = b + 1
end
if HealBot_UnitDebuff[unit] then
if DebuffType and HealBot_Range_Check(unit, 27) == 1 then
if HealBot_Config.ShowDebuffWarning == 1 then
UIErrorsFrame:AddMessage(UnitName(unit) .. " suffers from " .. DebuffType,
HealBot_Config.CDCBarColour[DebuffType].R,
HealBot_Config.CDCBarColour[DebuffType].G,
HealBot_Config.CDCBarColour[DebuffType].B,
1, UIERRORS_HOLD_TIME);
end
if HealBot_Config.SoundDebuffWarning == 1 then HealBot_PlaySound(HealBot_Config.SoundDebuffPlay); end
end
end
HealBot_CheckBuffs(unit);
HealBot_RecalcHeals(unit);
end
end
+114
View File
@@ -0,0 +1,114 @@
-- HealBot_Controller_Comms.lua
-- Handles network sync (addon messaging), errors, and chat debugging
function HealBot_Get_DebugChan()
local index = GetChannelName("HBmsg");
if (index > 0) then
return index;
else
return nil;
end
end
function HealBot_AddChat(msg)
local chanid = HealBot_Get_DebugChan();
if chanid and HealBot_SpamCnt < 3 then
HealBot_SpamCnt = HealBot_SpamCnt + 1;
local hour, minute = GetGameTime();
if minute == 0 then
msg = "[" .. hour .. ":00] " .. msg;
elseif minute < 10 then
msg = "[" .. hour .. ":0" .. minute .. "] " .. msg;
else
msg = "[" .. hour .. ":" .. minute .. "] " .. msg;
end
SendChatMessage(msg, "CHANNEL", nil, chanid);
elseif ( DEFAULT_CHAT_FRAME ) then
DEFAULT_CHAT_FRAME:AddMessage(msg);
end
end
function HealBot_AddDebug(msg)
local chanid = HealBot_Get_DebugChan();
if chanid and HealBot_SpamCnt < 3 then
HealBot_SpamCnt = HealBot_SpamCnt + 1;
local hour, minute = GetGameTime();
if minute == 0 then
msg = "[" .. hour .. ":00] DEBUG: " .. msg;
elseif minute < 10 then
msg = "[" .. hour .. ":0" .. minute .. "] DEBUG: " .. msg;
else
msg = "[" .. hour .. ":" .. minute .. "] DEBUG: " .. msg;
end
SendChatMessage(msg, "CHANNEL", nil, chanid);
end
end
function HealBot_Report_Error(msg)
if HealBot_ErrorCnt < 28 then
HealBot_ErrorCnt = HealBot_ErrorCnt + 1;
ShowUIPanel(HealBot_Error);
HealBot_ErrorsIn(msg, HealBot_ErrorCnt);
end
end
function HealBot_AddError(msg)
UIErrorsFrame:AddMessage(msg, 1.0, 1.0, 1.0, 1.0, UIERRORS_HOLD_TIME);
HealBot_AddDebug(msg);
end
function HealBot_SendAddonMessage(prefix, text)
if GetNumRaidMembers() > 0 then
SendAddonMessage(prefix, text, "RAID")
elseif GetNumPartyMembers() > 0 then
SendAddonMessage(prefix, text, "PARTY")
end
end
function HealBot_OnEvent_AddonMsg(this, addon_id, inc_msg, dist_target, sender_id)
if addon_id == HEALBOT_ADDON_ID then
local tmpTest, unitname, heal_val
tmpTest, tmpTest, unitname, heal_val = string.find(inc_msg, ">> (%a+) <<=>> (.%d+) <<" );
if heal_val then
if not HealBot_HealsIn[unitname] then
HealBot_HealsIn[unitname] = 0;
end
HealBot_Healers[sender_id] = ">> " .. unitname .. " <<=>> " .. heal_val .. " <<";
HealBot_HealsIn[unitname] = HealBot_HealsIn[unitname] + tonumber(heal_val);
if tonumber(heal_val) > 0 then
HealBot_RecalcHeals(HealBot_FindUnitID(unitname))
elseif HealBot_HealsIn[unitname] < 0 then
HealBot_HealsIn[unitname] = 0;
end
end
elseif addon_id == "HealBot" then
local tmpTest, datatype, datamsg, sender
local PName = UnitName("player");
tmpTest, tmpTest, datatype, sender, datamsg = string.find(inc_msg, ">> (%a+) <<=>> (%a+) <<=>> (.+)");
if datatype == "RequestVersion" then
HealBot_SendAddonMessage("HealBot", ">> SendVersion <<=>> " .. sender .. " <<=>> Version=" .. HEALBOT_VERSION);
elseif datatype == "SendVersion" and PName == sender then
HealBot_AddChat(sender_id .. ": " .. datamsg);
end
elseif addon_id == "CTRA" then
if ( string.sub(inc_msg, 1, 3) == "RES" ) then
if ( inc_msg == "RESNO" ) then
HealBot_AddDebug(sender_id .. " Stopped ressing");
for unit, resser in pairs(HealBot_Ressing) do
if resser == sender_id then
HealBot_Ressing[unit] = nil;
HealBot_RecalcHeals(HealBot_FindUnitID(unit));
end
end
else
local unitname, tmpTest
tmpTest, tmpTest, unitname = string.find(inc_msg, "^RES (.+)$");
if ( unitname ) then
HealBot_AddDebug(sender_id .. " is ressing " .. unitname);
HealBot_Ressing[unitname] = sender_id;
HealBot_RecalcHeals(HealBot_FindUnitID(unitname));
end
end
end
end
end
+383
View File
@@ -0,0 +1,383 @@
-- HealBot_Controller_Events.lua
-- Manages WoW Frame events and periodic updates, routing to respective services
HealBot_View_DirtyUnits = {}
local HealBot_Timer1, HealsIn_Timer = 0, 0;
function HealBot_OnLoad(this)
this:RegisterEvent("VARIABLES_LOADED");
SLASH_HEALBOT1 = "/healbot";
SLASH_HEALBOT2 = "/hb";
SlashCmdList["HEALBOT"] = function(msg)
HealBot_SlashCmd(msg);
end
HealBot_AddError(HEALBOT_ADDON .. HEALBOT_LOADED);
-- Register MVC Observers
HealBot_Model:RegisterObserver("UNIT_HEALTH_CHANGED", function(unitID)
HealBot_View_DirtyUnits[unitID] = true
end)
HealBot_Model:RegisterObserver("UNIT_POWER_CHANGED", function(unitID)
HealBot_View_DirtyUnits[unitID] = true
end)
HealBot_Model:RegisterObserver("UNIT_AURA_CHANGED", function(unitID)
HealBot_View_DirtyUnits[unitID] = true
end)
HealBot_Model:RegisterObserver("ROSTER_CHANGED", function()
Delay_RecalcParty = 1
end)
end
function HealBot_RegisterThis(this)
-- Deprecated / not used
end
function HealBot_OnUpdate(this, arg1)
-- 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
end
end
HealBot_Timer1 = HealBot_Timer1 + arg1;
if HealBot_Timer1 >= 2.5 then
if not HealBot_IsFighting then
HealsIn_Timer = HealsIn_Timer + 1;
if HealsIn_Timer >= 10 then
HealBot_HealsIn = {};
HealBot_Healers = {};
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()
CalcEquipBonus = true;
HealBot_RecalcSpells();
end
end
if InitSpells > 1 then
InitSpells = InitSpells + 1;
if InitSpells > 2 then
local cnt = HealBot_InitSpells();
InitSpells = 0;
HealBot_RecalcSpells();
end
end
if Delay_RecalcParty > 0 then
Delay_RecalcParty = Delay_RecalcParty + 1
if Delay_RecalcParty > 1 then
Delay_RecalcParty = 0;
HealBot_RecalcParty();
end
end
else
HealsIn_Timer = 0;
end
HealBot_Timer1 = 0;
HealBot_SpamCnt = 0;
end
end
local HealBot_EventHandlers = {
["UNIT_HEALTH"] = function(this, arg1)
if HealBot_Model:UpdateUnitHealth(arg1) then
HealBot_Model:NotifyObservers("UNIT_HEALTH_CHANGED", arg1)
end
HealBot_OnEvent_UnitHealth(this, arg1)
end,
["UNIT_MANA"] = function(this, arg1)
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 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 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 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)
HealBot_Model:NotifyObservers("UNIT_AURA_CHANGED", arg1)
HealBot_OnEvent_UnitAura(this, arg1)
end,
["PLAYER_TARGET_CHANGED"] = function(this)
if HealBot_Model:UpdateUnitIdentity("target") then
HealBot_Model:NotifyObservers("ROSTER_CHANGED", "target")
end
HealBot_Model:UpdateUnitStatus("target")
HealBot_Model:UpdateUnitHealth("target")
HealBot_Model:UpdateUnitPower("target")
HealBot_OnEvent_PlayerTargetChanged(this)
end,
["PARTY_MEMBERS_CHANGED"] = 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")
HealBot_OnEvent_PlayerEnteringWorld(this)
end,
["VARIABLES_LOADED"] = function(this)
HealBot_OnEvent_VariablesLoaded(this)
end,
-- Legacy pass-throughs
["CHAT_MSG_ADDON"] = function(this, arg1, arg2, arg3, arg4) HealBot_OnEvent_AddonMsg(this, arg1, arg2, arg3, arg4) end,
["SPELLCAST_START"] = function(this, arg1, arg2) HealBot_OnEvent_SpellcastStart(this, arg1, arg2) end,
["SPELLCAST_STOP"] = function(this) HealBot_OnEvent_SpellcastStop(this) end,
["SPELLCAST_INTERRUPTED"] = function(this) HealBot_OnEvent_SpellcastStop(this) end,
["SPELLCAST_FAILED"] = function(this) HealBot_OnEvent_SpellcastStop(this) 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,
["ZONE_CHANGED_NEW_AREA"] = function(this) HealBot_OnEvent_ZoneChanged(this) end,
["UPDATE_INVENTORY_ALERTS"] = function(this) HealBot_OnEvent_PlayerEquipmentChanged(this) end,
["UNIT_INVENTORY_CHANGED"] = function(this, 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,
["SPELLS_CHANGED"] = function(this, arg1) HealBot_OnEvent_SpellsChanged(this, arg1) end
}
function HealBot_OnEvent(this, event, arg1, arg2, arg3, arg4)
local handler = HealBot_EventHandlers[event]
if handler then
handler(this, arg1, arg2, arg3, arg4)
else
HealBot_AddDebug("OnEvent (" .. event .. ")")
end
end
function HealBot_OnEvent_VariablesLoaded(this)
local class = HealBot_UnitClass("player")
table.foreach(HealBot_ConfigDefaults, function (key, val)
if not HealBot_Config[key] then
HealBot_Config[key] = val;
end
if type(val) == "table" and type(HealBot_Config[key]) == "table" then
for k, v in pairs(val) do
if HealBot_Config[key][k] == nil then
HealBot_Config[key][k] = v
end
end
end
end);
local foundModern = false
if HealBot_Config.Skins then
for _, skin in ipairs(HealBot_Config.Skins) do
if skin == "Modern Flat" then foundModern = true break end
end
if not foundModern then
table.insert(HealBot_Config.Skins, "Modern Flat")
end
end
HealBot_InitData();
if class == "PRIEST" or class == "DRUID" or class == "PALADIN" or class == "SHAMAN" then
HealBot_BonusScanner:ScanEquipment();
if HealBot_Config.ActionVisible == 1 then HealBot_Action:Show() end
this:RegisterEvent("ZONE_CHANGED_NEW_AREA");
this:RegisterEvent("PLAYER_REGEN_DISABLED");
this:RegisterEvent("PLAYER_REGEN_ENABLED");
this:RegisterEvent("PLAYER_TARGET_CHANGED");
this:RegisterEvent("PARTY_MEMBERS_CHANGED");
this:RegisterEvent("PARTY_MEMBER_DISABLE");
this:RegisterEvent("PARTY_MEMBER_ENABLE");
this:RegisterEvent("PET_BAR_SHOWGRID");
this:RegisterEvent("PET_BAR_HIDEGRID");
this:RegisterEvent("UNIT_HEALTH");
this:RegisterEvent("UNIT_MANA");
this:RegisterEvent("UNIT_RAGE");
this:RegisterEvent("UNIT_ENERGY");
this:RegisterEvent("UNIT_DISPLAYPOWER");
this:RegisterEvent("SPELLS_CHANGED");
this:RegisterEvent("SPELLCAST_START");
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");
this:RegisterEvent("CHAT_MSG_ADDON");
this:RegisterEvent("CHAT_MSG_SYSTEM");
this:RegisterEvent("PLAYER_ENTERING_WORLD");
InitSpells = 2;
end
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
end
function HealBot_OnEvent_UnitMana(this, unit)
if (unit ~= "player") then return end
HealBot_RecalcHeals();
end
function HealBot_OnEvent_ZoneChanged(this)
HealBot_ResetRangeScale();
Delay_RecalcParty = 1;
end
function HealBot_OnEvent_PlayerRegenDisabled(this)
HealBot_RecalcParty();
if (UnitIsDeadOrGhost("player")) or (UnitOnTaxi("player")) then
if HealBot_Config.AutoClose == 1 and HealBot_Config.ActionVisible ~= 0 then HealBot_Action:Hide(); end;
else
HealBot_Action:Show();
HealBot_IsFighting = true;
end
end
function HealBot_OnEvent_PlayerRegenEnabled(this)
HealBot_IsFighting = false;
Delay_RecalcParty = 1;
end
function HealBot_OnEvent_PlayerTargetChanged(this)
HealBot_RecalcParty();
end
function HealBot_OnEvent_PartyMembersChanged(this)
Delay_RecalcParty = 1;
end
function HealBot_OnEvent_PartyMemberDisable(this, unit)
HealBot_RecalcHeals();
end
function HealBot_OnEvent_SystemMsg(this, msg)
if type(msg) == "string" then
local tmpTest, tmpTest, deserter = string.find(msg, HB_HASLEFTRAID);
if not deserter then
local tmpTest, tmpTest, deserter = string.find(msg, HB_HASLEFTPARTY);
end
if deserter then
if (HealBot_Healers[deserter]) then
local tmpTest, unitname, heal_val, heal_valn
tmpTest, tmpTest, unitname, heal_val = string.find(HealBot_Healers[deserter], ">> (%a+) <<=>> (.%d+) <<" );
heal_valn = tonumber(heal_val)
HealBot_Healers[deserter] = nil;
HealBot_AddDebug("Healer " .. deserter .. " left the group - Last known activity was heal " .. unitname .. " for " .. heal_val .. " << trapped in event SystemMsg");
if heal_valn > 0 and HealBot_HealsIn[unitname] then
HealBot_HealsIn[unitname] = HealBot_HealsIn[unitname] - heal_valn;
if HealBot_HealsIn[unitname] < 0 then
HealBot_HealsIn[unitname] = 0;
end
end
end
elseif msg == HB_YOULEAVETHEGROUP or msg == HB_YOULEAVETHERAID then
Delay_RecalcParty = 1;
end
end
end
function HealBot_OnEvent_PartyMemberEnable(this, unit)
HealBot_RecalcHeals();
end
function HealBot_OnEvent_PlayerEquipmentChanged(this)
HealBot_EquipChangeTimer = 1;
end
function HealBot_OnEvent_PlayerEquipmentChanged2(this, unit)
if unit == "player" then
HealBot_EquipChangeTimer = 1;
end
end
function HealBot_OnEvent_SpellsChanged(this, arg1)
if arg1 then return; end
HealBot_AddDebug("HB: SpellsChanged");
InitSpells = 2;
end
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;
end
function HealBot_OnEvent_SpellcastStart(this, spell, duration)
HealBot_IsCasting = true;
HealBot_RecalcHeals();
HealBot_CheckCasting();
if spell == HEALBOT_RESURRECTION or spell == HEALBOT_ANCESTRALSPIRIT or spell == HEALBOT_REBIRTH or spell == HEALBOT_REDEMPTION then
if UnitName("Target") then
HealBot_SendAddonMessage("CTRA", "RES " .. UnitName("Target"));
HealBot_IamRessing = true;
end
end
end
function HealBot_OnEvent_SpellcastStop(this)
HealBot_IsCasting = false;
HealBot_StopCasting();
HealBot_RecalcHeals();
if HealBot_IamRessing then
HealBot_SendAddonMessage("CTRA", "RESNO");
HealBot_IamRessing = false;
end
end
+42
View File
@@ -0,0 +1,42 @@
-- HealBot_Controller_Range.lua
-- Handles periodic range checking for units
local _scale = 0
function HealBot_ResetRangeScale()
_scale = 0
end
function HealBot_Range_Check(unit, range)
local return_val = 0;
if not range then
range = 40;
end
if ( unit == "player" ) then
return_val = 1;
elseif ( UnitIsVisible(unit) == 1 ) then
local tx, ty = GetPlayerMapPosition(unit)
local dist
if tx > 0 or ty > 0 then
local px, py = GetPlayerMapPosition("player")
dist = math.sqrt((px - tx)^2 + (py - ty)^2)
if dist > _scale and (px > 0 or py > 0) then
if ( CheckInteractDistance(unit, 4) ) then
_scale = dist
end
end
if dist <= (_scale * range / 27) then
return_val = 1
end
else
if ( HealBot_Config.QualityRange == 1 ) or range <= 27 then
if ( CheckInteractDistance(unit, 4) ) then
return_val = 1;
end
else
return_val = 1;
end
end
end
return return_val;
end
+636
View File
@@ -0,0 +1,636 @@
-- HealBot_Controller_Spells.lua
-- Centralized Spell management, calculation, and casting logic
HealBot_CastingSpell = nil;
HealBot_CastingTarget = nil;
local HealBot_Health60 = {
["DRUID"] = 3500,
["MAGE"] = 2500,
["HUNTER"] = 3500,
["PALADIN"] = 4000,
["PRIEST"] = 2500,
["ROGUE"] = 3500,
["SHAMAN"] = 3800,
["WARLOCK"] = 3500,
["WARRIOR"] = 5000,
}
function HealBot_GetSpellName(id)
if (not id) then
return nil;
end
local spellName, subSpellName = GetSpellName(id, BOOKTYPE_SPELL);
if (not spellName) then
return nil;
end
if (not subSpellName or subSpellName == "") then
return spellName;
end
return spellName .. " (" .. subSpellName .. ")";
end
function HealBot_GetSpellId(spell)
local id, idd = 1, 0;
while true do
local spellName, subSpellName = GetSpellName(id, BOOKTYPE_SPELL);
if (spellName) then
if (spell == spellName .. " (" .. subSpellName .. ")") or (spell == spellName .. "(" .. subSpellName .. ")") then
return id;
end
if (spell == spellName) then
idd = id;
end
else
break
end
id = id + 1;
end
if idd > 0 then
return idd
else
return nil;
end
end
function HealBot_CastSpellByName(spell)
if (HealBot_Spells[spell] and HealBot_Spells[spell].BagSlot) then
HealBot_UseItem(spell);
return;
end
local id;
if not HealBot_Spells[spell] then
id = HealBot_GetSpellId(spell);
elseif HealBot_Spells[spell].id then
id = HealBot_Spells[spell].id
else
id = HealBot_GetSpellId(spell);
end
if (not id) then
return;
end
CastSpell(id, BOOKTYPE_SPELL);
end
function HealBot_StartCasting(spell, target, ttype)
HealBot_CastSpellByName(spell);
HealBot_CastingSpell = spell;
HealBot_CastingTarget = target;
if ( SpellCanTargetUnit(target) ) then
SpellTargetUnit(target);
ttype = "fired";
elseif SpellIsTargeting() then
SpellTargetUnit(target);
SpellStopTargeting()
elseif ttype == "direct" then
if ( CheckInteractDistance(target, 4) ) then
ttype = "fired";
end
end
if HealBot_Config.ChatMessages then
local tName = target
if target == "target" then tName = HealBot_TargetName() or "target" else tName = UnitName(target) end
if not tName then tName = target end
local baseSpell = spell
local parenIndex = string.find(spell, "%(")
if parenIndex then
baseSpell = string.sub(spell, 1, parenIndex - 1)
end
for i = 1, 5 do
local msgConf = HealBot_Config.ChatMessages[i]
if msgConf and msgConf.Spell == baseSpell and msgConf.Channel ~= "None" then
local msg = msgConf.Message or ""
msg = string.gsub(msg, "#Spell#", spell)
msg = string.gsub(msg, "#Target#", tName)
local chan = msgConf.Channel
if chan == "Say" then
SendChatMessage(msg, "SAY")
elseif chan == "Party" and GetNumPartyMembers() > 0 then
SendChatMessage(msg, "PARTY")
elseif chan == "Raid" and GetNumRaidMembers() > 0 then
SendChatMessage(msg, "RAID")
elseif chan == "Whisper" and UnitIsPlayer(target) then
SendChatMessage(msg, "WHISPER", nil, tName)
end
end
end
end
if ttype == "fired" and HealBot_Spells[spell] then
if HealBot_Spells[spell].CastTime > 1 then
HealValue = HealBot_Spells[spell].HealsDur;
HealBot_SendAddonMessage(HEALBOT_ADDON_ID, ">> " .. UnitName(target) .. " <<=>> " .. HealValue .. " << ");
end
end
end
function HealBot_StopCasting()
if HealBot_CastingTarget then
if HealBot_HealsIn[UnitName(HealBot_CastingTarget)] then
if HealValue > 0 then
HealBot_SendAddonMessage(HEALBOT_ADDON_ID, ">> " .. UnitName(HealBot_CastingTarget) .. " <<=>> " .. 0 - HealValue .. " << ");
HealValue = 0;
end
end
end
HealBot_CastingSpell = nil;
HealBot_CastingTarget = nil;
local bar = HealBot_Action_HealthBar(HealBot_Action_AbortButton);
local ar = HealBot_Config.babortcolr[HealBot_Config.Current_Skin] or 0.1;
local ag = HealBot_Config.babortcolg[HealBot_Config.Current_Skin] or 0.1;
local ab = HealBot_Config.babortcolb[HealBot_Config.Current_Skin] or 0.5;
local aa = HealBot_Config.babortcola[HealBot_Config.Current_Skin] or 1;
bar.txt = getglobal(bar:GetName() .. "_text");
bar:SetStatusBarColor(ar, ag, ab, 0);
local sr = HealBot_Config.btextdisbledcolr[HealBot_Config.Current_Skin];
local sg = HealBot_Config.btextdisbledcolg[HealBot_Config.Current_Skin];
local sb = HealBot_Config.btextdisbledcolb[HealBot_Config.Current_Skin];
local sa = HealBot_Config.btextdisbledcola[HealBot_Config.Current_Skin];
bar.txt:SetTextColor(sr, sg, sb, sa);
end
function HealBot_UnitHealth(unit)
local Current, Desired = UnitHealth(unit), UnitHealthMax(unit);
if unit == 'target' and Desired == 100 then
local class, level = HealBot_UnitClass(unit), UnitLevel(unit);
if HealBot_Health60[class] and level > 0 then
Desired = math.floor(HealBot_Health60[class] / 60 * level + 0.5)
else
Desired = UnitHealthMax('player');
end
Current = Desired / 100 * Current;
end
return Current, Desired;
end
function HealBot_CheckCasting(unit)
if not HealBot_CastingSpell or HealBot_AlwaysHeal() then return nil end
if not HealBot_Spells[HealBot_CastingSpell] then return nil end
if not unit then unit = HealBot_CastingTarget end
if unit ~= HealBot_CastingTarget then return nil end
local bar = HealBot_Action_HealthBar(HealBot_Action_AbortButton);
local ar = HealBot_Config.babortcolr[HealBot_Config.Current_Skin] or 0.1;
local ag = HealBot_Config.babortcolg[HealBot_Config.Current_Skin] or 0.1;
local ab = HealBot_Config.babortcolb[HealBot_Config.Current_Skin] or 0.5;
local aa = HealBot_Config.babortcola[HealBot_Config.Current_Skin] or 1;
bar.txt = getglobal(bar:GetName() .. "_text");
if HealBot_IsCasting == false and HealBot_AbortButton == 0 then
bar:SetStatusBarColor(ar, ag, ab, 0);
local sr = HealBot_Config.btextdisbledcolr[HealBot_Config.Current_Skin];
local sg = HealBot_Config.btextdisbledcolg[HealBot_Config.Current_Skin];
local sb = HealBot_Config.btextdisbledcolb[HealBot_Config.Current_Skin];
local sa = HealBot_Config.btextdisbledcola[HealBot_Config.Current_Skin];
bar.txt:SetTextColor(sr, sg, sb, sa);
return nil
end
local Current, Desired = HealBot_UnitHealth(unit)
local Needed = Desired - Current;
Needed = Needed * (1 + (HealBot_Config.OverHeal * 4));
if Needed < 0 then Needed = 0 end
if (Needed > HealBot_Spells[HealBot_CastingSpell].HealsDur) then
local sr = HealBot_Config.btextdisbledcolr[HealBot_Config.Current_Skin];
local sg = HealBot_Config.btextdisbledcolg[HealBot_Config.Current_Skin];
local sb = HealBot_Config.btextdisbledcolb[HealBot_Config.Current_Skin];
local sa = HealBot_Config.btextdisbledcola[HealBot_Config.Current_Skin];
bar.txt:SetTextColor(sr, sg, sb, sa);
bar:SetStatusBarColor(ar, ag, ab, 0);
return nil
elseif HealBot_AbortButton == 1 and HealBot_IsCasting == true then
bar:SetStatusBarColor(ar, ag, ab, aa);
local sr = HealBot_Config.btextenabledcolr[HealBot_Config.Current_Skin];
local sg = HealBot_Config.btextenabledcolg[HealBot_Config.Current_Skin];
local sb = HealBot_Config.btextenabledcolb[HealBot_Config.Current_Skin];
local sa = HealBot_Config.btextenabledcola[HealBot_Config.Current_Skin];
bar.txt = getglobal(bar:GetName() .. "_text");
bar.txt:SetTextColor(sr, sg, sb, sa);
end
end
function HealBot_CastSpellOnFriend(spell, target)
local old;
local ttype = "other";
if (not spell or not target or not UnitName(target)) then
return;
end
if (UnitCanAttack("player", "target")) then
old = "enemy";
else
old = UnitName("target");
if UnitName("target") ~= UnitName(target) then
TargetUnit(target);
else
ttype = "direct";
end
end
HealBot_StartCasting(spell, target, ttype);
if (old == "enemy") then
TargetLastEnemy();
elseif (old) then
TargetByName(old);
else
ClearTarget();
end
end
function HealBot_SetItemDefaults(spell)
if not HealBot_Spells[spell].Target then
HealBot_Spells[spell].Target = {"player", "party", "pet"};
end
if not HealBot_Spells[spell].Price then
HealBot_Spells[spell].Price = 0;
end
if not HealBot_Spells[spell].CastTime then
HealBot_Spells[spell].CastTime = 0;
end
if not HealBot_Spells[spell].Mana then
HealBot_Spells[spell].Mana = 0;
end
if not HealBot_Spells[spell].Channel then
HealBot_Spells[spell].Channel = HealBot_Spells[spell].CastTime;
end
if not HealBot_Spells[spell].Duration then
HealBot_Spells[spell].Duration = HealBot_Spells[spell].Channel;
end
if not HealBot_Spells[spell].HealsMin then
HealBot_Spells[spell].HealsMin = 0;
end
if not HealBot_Spells[spell].HealsMax then
HealBot_Spells[spell].HealsMax = 0;
end
HealBot_Spells[spell].RealHealing = 0;
HealBot_Spells[spell].HealsCast = (HealBot_Spells[spell].HealsMin + HealBot_Spells[spell].HealsMax) / 2;
if not HealBot_Spells[spell].HealsExt then
HealBot_Spells[spell].HealsExt = 0;
end
end
function HealBot_SetSpellDefaults(spell)
HealBot_Spells[spell].HealsDur = math.floor((HealBot_Spells[spell].HealsCast + HealBot_Spells[spell].HealsExt) + HealBot_Spells[spell].RealHealing);
end
function HealBot_AddHeal(spell)
HealBot_SetSpellDefaults(spell);
table.foreachi(HealBot_Spells[spell].Target, function (i, val)
table.insert(HealBot_Heals[val], spell);
end);
HealBot_Spells[spell].BagSlot = HealBot_GetBagSlot(spell);
end
function HealBot_FindHealSpells()
local id = 1;
if InitSpells > 0 then NeedEquipUpdate = 1; return; end
HealBot_Heals = { player = {}, pet = {}, party = {} };
table.foreach(HealBot_CurrentSpells, function (index, spell)
if (HealBot_Spells[spell]) then
if CalcEquipBonus then
local healingbonus_penalty = 1;
if HealBot_Spells[spell].Level < 20 then
healingbonus_penalty = (1 - ((20 - HealBot_Spells[spell].Level) * 0.0375));
end
local temp_Spell_cast = 3.5;
if HealBot_Spells[spell].CastTime == 0 then
temp_Spell_cast = 3.5;
end
if not HealBot_Spells[spell].CastTime then
HealBot_Spells[spell].CastTime = 1.5;
end
if HealBot_Spells[spell].CastTime >= 1.5 and HealBot_Spells[spell].CastTime < 3.5 then
temp_Spell_cast = HealBot_Spells[spell].CastTime;
end
RealHealing = ((HealBot_GetBonus() * healingbonus_penalty) * (temp_Spell_cast / 3.5));
local playerClass, englishClass = UnitClass("player");
local SpiBonus = 0;
if (englishClass == "PRIEST") then
SpiBonus = ((HealBot_SpiBonus(spell) * healingbonus_penalty) * (temp_Spell_cast / 3.5))
RealHealing = RealHealing + SpiBonus;
end
RealHealing = math.floor(RealHealing);
HealBot_Spells[spell].RealHealing = RealHealing;
end
HealBot_AddHeal(spell);
end
end);
local items = {};
for bag = 0, NUM_BAG_FRAMES do
for slot = 1, GetContainerNumSlots(bag) do
local item = HealBot_GetItemName(bag, slot);
if HealBot_Spells[item] and not items[item] then
HealBot_SetItemDefaults(item);
HealBot_AddHeal(item);
items[item] = 1;
end
end
end
table.foreach(HealBot_Heals, function (key, val)
if (table.getn(val) == 0) then
HealBot_Heals[key] = nil;
end
end);
HealBot_Heals.target = HealBot_Heals.party;
for i = 1, 4 do
HealBot_Heals["party" .. i] = HealBot_Heals.party;
HealBot_Heals["partypet" .. i] = HealBot_Heals.party;
end
for i = 1, 40 do
HealBot_Heals["raid" .. i] = HealBot_Heals.party;
HealBot_Heals["raidpet" .. i] = HealBot_Heals.party;
end
if CalcEquipBonus then
HealBot_AddDebug("...Done Equip Bonus:" .. RealHealing);
end
CalcEquipBonus = false;
end
function HealBot_CanCastSpell(spell, unit)
local this = HealBot_Spells[spell];
if this.Mana > UnitMana("player") then return false end;
if this.BagSlot then
local bag, slot = HealBot_UnpackBagSlot(this.BagSlot);
local start, duration, enable = GetContainerItemCooldown(bag, slot);
if (start > 0 and duration > 0 and enable > 0) then
return false;
end
end
return true;
end
function HealBot_GetHealSpell(unit, pattern)
if (not UnitName(unit)) 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_GetShapeshiftForm() 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;
end
function HealBot_HealUnit(unit, pattern)
HealBot_CastSpellOnFriend(HealBot_GetHealSpell(unit, pattern), unit);
end
function HealBot_RecalcHeals(unit)
HealBot_Action_Refresh(unit);
end
function HealBot_RecalcParty()
HealBot_Action_PartyChanged();
HealBot_Action_RefreshButtons();
end
function HealBot_RecalcSpells()
HealBot_FindHealSpells();
HealBot_RecalcParty();
end
function HealBot_SpiBonus(spell)
local heals_modifer = 0;
local base, stat, posBuff, negBuff = UnitStat("player", 5);
nameTalent, icon, tier, column, currRank, maxRank = GetTalentInfo(2, 14); -- Spiritual guidance
spiGuideBonus = stat * 0.05;
heals_modifer = heals_modifer + (currRank * spiGuideBonus);
return heals_modifer;
end
function HealBot_GetBonus()
local HealBonus = HealBot_BonusScanner:GetBonus();
return HealBonus;
end
function HealBot_InitSpells()
local id = 1
local cnt = 0;
local class = HealBot_UnitClass("player")
HealBot_CurrentSpells = {};
while true do
local spell = HealBot_GetSpellName(id);
if not spell then
break
end
if (HealBot_Spells[spell]) then
HealBot_Spells[spell].id = id;
HealBot_InitGetSpellData(spell, id, class);
table.insert(HealBot_CurrentSpells, spell);
cnt = cnt + 1;
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
function HealBot_InitGetSpellData(spell, id, class)
local i, _mana, _cast, _HealsMin, _HealsMax, _HealsExt, _duration, _range, _shield, _channel;
local tooltip = getglobal("HealBot_ScanTooltip");
local tmpText, line, tmpTest
if (not spell) then
return;
end
HealBot_ScanTooltip:SetOwner(HealBot_ScanTooltip, "ANCHOR_NONE")
HealBot_ScanTooltip:SetSpell(id, BOOKTYPE_SPELL);
tmpText = getglobal("HealBot_ScanTooltipTextLeft2");
if (tmpText:GetText()) then
line = tmpText:GetText();
tmpTest, tmpTest, _mana = string.find(line, HB_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, HB_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 == HB_TOOLTIP_INSTANT_CAST) then
_cast = 0;
elseif line == HB_TOOLTIP_CHANNELED then
_cast = 0;
elseif (tmpText) then
tmpTest, tmpTest, _cast = string.find(line, HB_TOOLTIP_CAST_TIME);
end
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_ScanTooltipTextLeft4");
tmpTest = nil;
if (tmpText:GetText()) then
line = tmpText:GetText();
if class == "PRIEST" then
if string.sub(spell, 1, 14) == string.sub(HEALBOT_POWER_WORD_SHIELD, 1, 14) then
tmpTest, tmpTest, _HealsMin, _shield = string.find(line, HB_SPELL_PATTERN_SHIELD);
_HealsExt = 0;
_HealsMax = _HealsMin;
elseif string.sub(spell, 1, 4) == string.sub(HEALBOT_RENEW, 1, 4) then
tmpTest, tmpTest, _HealsExt, tmpTest, _duration = string.find(line, HB_SPELL_PATTERN_RENEW);
_HealsMin = 0;
_HealsMax = 0;
if (_HealsExt == nil) then
tmpTest, tmpTest, _HealsExt, _duration = string.find(line, HB_SPELL_PATTERN_RENEW1);
end
if (_HealsExt == nil) then
tmpTest, tmpTest, _duration, _HealsExt = string.find(line, HB_SPELL_PATTERN_RENEW2);
end
if (_HealsExt == nil) then
tmpTest, tmpTest, _duration, _HealsExt = string.find(line, HB_SPELL_PATTERN_RENEW3);
end
elseif string.sub(spell, 1, 9) == string.sub(HEALBOT_LESSER_HEAL, 1, 9) then
tmpTest, _HealsMin, _HealsMax = HealBot_Generic_Patten(line, HB_SPELL_PATTERN_LESSER_HEAL);
elseif string.sub(spell, 1, 9) == string.sub(HEALBOT_GREATER_HEAL, 1, 9) then
tmpTest, _HealsMin, _HealsMax = HealBot_Generic_Patten(line, HB_SPELL_PATTERN_GREATER_HEAL);
elseif string.sub(spell, 1, 9) == string.sub(HEALBOT_FLASH_HEAL, 1, 9) then
tmpTest, _HealsMin, _HealsMax = HealBot_Generic_Patten(line, HB_SPELL_PATTERN_FLASH_HEAL);
elseif string.sub(spell, 1, 4) == string.sub(HEALBOT_HEAL, 1, 4) then
tmpTest, _HealsMin, _HealsMax = HealBot_Generic_Patten(line, HB_SPELL_PATTERN_HEAL);
end
elseif class == "DRUID" then
if string.sub(spell, 1, 6) == string.sub(HEALBOT_REGROWTH, 1, 6) then
tmpTest, tmpTest, _HealsMin, _HealsMax, _HealsExt = string.find(line, HB_SPELL_PATTERN_REGROWTH);
if (tmpTest == nil) then
tmpTest, tmpTest, _HealsMin, _HealsMax, tmpTest, _HealsExt = string.find(line, HB_SPELL_PATTERN_REGROWTH1);
end
elseif string.sub(spell, 1, 9) == string.sub(HEALBOT_REJUVENATION, 1, 9) then
tmpTest, tmpTest, _HealsExt, _duration = string.find(line, HB_SPELL_PATTERN_REJUVENATION);
_HealsMin = 0;
_HealsMax = 0;
if (_HealsExt == nil) then
tmpTest, tmpTest, _HealsExt, tmpTest, _duration = string.find(line, HB_SPELL_PATTERN_REJUVENATION1);
end
elseif string.sub(spell, 1, 7) == string.sub(HEALBOT_HEALING_TOUCH, 1, 7) then
tmpTest, _HealsMin, _HealsMax = HealBot_Generic_Patten(line, HB_SPELL_PATTERN_HEALING_TOUCH);
end
elseif class == "PALADIN" then
if string.sub(spell, 1, 9) == string.sub(HEALBOT_HOLY_LIGHT, 1, 9) then
tmpTest, _HealsMin, _HealsMax = HealBot_Generic_Patten(line, HB_SPELL_PATTERN_HOLY_LIGHT);
elseif string.sub(spell, 1, 9) == string.sub(HEALBOT_FLASH_OF_LIGHT, 1, 9) then
tmpTest, _HealsMin, _HealsMax = HealBot_Generic_Patten(line, HB_SPELL_PATTERN_FLASH_OF_LIGHT);
end
elseif class == "SHAMAN" then
if string.sub(spell, 1, 9) == string.sub(HEALBOT_HEALING_WAVE, 1, 9) then
tmpTest, _HealsMin, _HealsMax = HealBot_Generic_Patten(line, HB_SPELL_PATTERN_HEALING_WAVE);
elseif string.sub(spell, 1, 9) == string.sub(HEALBOT_LESSER_HEALING_WAVE, 1, 9) then
tmpTest, _HealsMin, _HealsMax = HealBot_Generic_Patten(line, HB_SPELL_PATTERN_LESSER_HEALING_WAVE);
end
end
else
HealBot_Report_Error("================================");
HealBot_Report_Error("ERROR: HealBot_ScanTooltip is lost");
HealBot_Report_Error("ERROR: If BonusScanner is used, try disabling BonusScanner");
end
if (_mana == nil) then
HealBot_Report_Error("================================");
HealBot_Report_Error("ERROR: _mana is NIL");
HealBot_Report_Error("ERROR: Spell: " .. spell);
if HealBot_ScanTooltipTextLeft2:GetText() then
HealBot_Report_Error("ERROR: Tooltip = >> " .. HealBot_ScanTooltipTextLeft2:GetText() .. " <<");
end
HealBot_Report_Error("ERROR: Patten = >> " .. HB_TOOLTIP_MANA .. " <<");
end
if (_range == nil) then
HealBot_Report_Error("================================");
HealBot_Report_Error("ERROR: _range is NIL");
HealBot_Report_Error("ERROR: Spell: " .. spell);
if HealBot_ScanTooltipTextRight2:GetText() then
HealBot_Report_Error("ERROR: Tooltip = >> " .. HealBot_ScanTooltipTextRight2:GetText() .. " <<");
end
HealBot_Report_Error("ERROR: Patten = >> " .. HB_TOOLTIP_RANGE .. " <<");
end
if (_cast == nil) then
HealBot_Report_Error("================================");
HealBot_Report_Error("ERROR: _cast is NIL");
HealBot_Report_Error("ERROR: Spell: " .. spell);
if HealBot_ScanTooltipTextLeft3:GetText() then
HealBot_Report_Error("ERROR: Tooltip = >> " .. HealBot_ScanTooltipTextLeft3:GetText() .. " <<");
end
HealBot_Report_Error("ERROR: Patten = >> " .. HB_TOOLTIP_CAST_TIME .. " <<");
end
if (tmpTest == nil) then
HealBot_Report_Error("================================");
HealBot_Report_Error("ERROR: tmpTest == nil");
HealBot_Report_Error("ERROR: spell = " .. spell);
if line then
HealBot_Report_Error("ERROR: Tooltip = >> " .. line .. " <<");
end
end
HealBot_Spells[spell].CastTime = tonumber(_cast);
HealBot_Spells[spell].Mana = tonumber(_mana);
HealBot_Spells[spell].Range = tonumber(_range);
HealBot_Spells[spell].HealsMin = tonumber(_HealsMin);
HealBot_Spells[spell].HealsMax = tonumber(_HealsMax);
if _HealsExt then
HealBot_Spells[spell].HealsExt = tonumber(_HealsExt);
end
if _duration then
HealBot_Spells[spell].Duration = tonumber(_duration);
end
if _shield then
HealBot_Spells[spell].Shield = tonumber(_shield);
end
if _channel then
HealBot_Spells[spell].Channel = tonumber(_channel);
end
if not HealBot_Spells[spell].Target then
HealBot_Spells[spell].Target = {"player", "party", "pet"};
end
if not HealBot_Spells[spell].Price then
HealBot_Spells[spell].Price = 0;
end
if not HealBot_Spells[spell].Channel then
HealBot_Spells[spell].Channel = HealBot_Spells[spell].CastTime;
end
if not HealBot_Spells[spell].Duration then
HealBot_Spells[spell].Duration = HealBot_Spells[spell].Channel;
end
if not HealBot_Spells[spell].RealHealing then
HealBot_Spells[spell].RealHealing = 0;
end
HealBot_Spells[spell].HealsCast = (HealBot_Spells[spell].HealsMin + HealBot_Spells[spell].HealsMax) / 2;
if not HealBot_Spells[spell].HealsExt then
HealBot_Spells[spell].HealsExt = 0;
end
end
function HealBot_Generic_Patten(matchStr, matchPattern)
local tmpTest, _HealsMin, _HealsMax, _HealsExt, _duration
tmpTest, tmpTest, _HealsMin, _HealsMax = string.find(matchStr, matchPattern);
if (tmpTest == nil) then
HealBot_Report_Error("================================");
HealBot_Report_Error("ERROR: tmpTest == nil");
HealBot_Report_Error("ERROR: pattern = " .. matchPattern);
HealBot_Report_Error("ERROR: Tooltip = >> " .. matchStr .. " <<");
end
return tmpTest, _HealsMin, _HealsMax;
end
+1 -1
View File
@@ -36,7 +36,7 @@ function HealBot_Model:NotifyObservers(event, unitID, ...)
if self.observers[event] then
local len = table.getn(self.observers[event])
for i = 1, len do
self.observers[event][i](unitID, unpack(arg))
self.observers[event][i](unitID, ...)
end
end
end
+772
View File
@@ -0,0 +1,772 @@
-- HealBot_View_Layout.lua
-- Manages skins, status bar layouts, anchoring, and grid rendering for the HealBot panel
local headerno = 0
HealBot_Action_HealGroup = {
"player",
"pet",
"party1",
"party2",
"party3",
"party4",
};
HealBot_Action_HealTarget = {};
HealBot_Action_HealButtons = {};
HealBot_Action_UnitButtons = {};
function HealBot_Action_SetTexture(bar, btexture)
if not bar then return end
if btexture == 10 then
bar:SetStatusBarTexture("Interface\\Buttons\\WHITE8X8");
else
bar:SetStatusBarTexture("Interface\\TargetingFrame\\UI-StatusBar");
end
end
function HealBot_HealthColor(unit, hlth, maxhlth)
if HealBot_UnitDebuff[unit] then
local debuff, tmp, debuff_type = UnitDebuff(unit, 1, 1)
if not debuff then
HealBot_UnitDebuff[unit] = nil;
HealBot_UnitDebuff[unit .. "_debuff_texture"] = nil
else
local dr = HealBot_Config.CDCBarColour[debuff_type].R
local dg = HealBot_Config.CDCBarColour[debuff_type].G
local db = HealBot_Config.CDCBarColour[debuff_type].B
if HealBot_Config.btexture[HealBot_Config.Current_Skin] == 10 then
dr = dr * 4
dg = dg * 4
db = db * 4
if dr > 1 then dr = 1 end
if dg > 1 then dg = 1 end
if db > 1 then db = 1 end
end
return dr, dg, db, HealBot_Config.Barcola[HealBot_Config.Current_Skin];
end
end
local text = UnitName(unit);
if not HealBot_HealsIn[text] then
HealBot_HealsIn[text] = 0;
end
local pct = hlth + HealBot_HealsIn[text];
if maxhlth and maxhlth > 0 then
if pct < maxhlth then
pct = pct / maxhlth;
else
pct = 1;
end
else
pct = 0;
end
local r, g, b = 1.0, 1.0, 0.0;
local a = HealBot_Config.Barcola[HealBot_Config.Current_Skin];
if pct > HealBot_Config.AlertLevel then
a = HealBot_Config.bardisa[HealBot_Config.Current_Skin];
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
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
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
if pct <= 0.64 and pct > 0.31 then g = (pct - 0.31) * 3; end
if pct <= 0.31 then g = 0.0; end
end
return r, g, b, a;
end
function HealBot_Action_HealthBar(button)
local name = button:GetName();
return getglobal(name .. "Bar");
end
function HealBot_Action_HealthBar2(button)
local name = button:GetName();
return getglobal(name .. "Bar2");
end
function HealBot_Action_EnableButton(button)
local unit = button.unit;
local state = HealBot_Model.units[unit]
if not state then return end
local hlth = state.health
local maxhlth = state.maxHealth
local name = state.name
if not name then name = UnitName(unit) end -- fallback
local bar = HealBot_Action_HealthBar(button);
local bar2 = HealBot_Action_HealthBar2(button);
local bar3 = getglobal(button:GetName() .. "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];
local sg = HealBot_Config.btextenabledcolg[HealBot_Config.Current_Skin];
local sb = HealBot_Config.btextenabledcolb[HealBot_Config.Current_Skin];
local sa = HealBot_Config.btextenabledcola[HealBot_Config.Current_Skin];
local r, g, b, a = HealBot_HealthColor(button.unit, hlth, maxhlth)
local btextheight = HealBot_Config.btextheight[HealBot_Config.Current_Skin] or 10;
if btextheight == 0 then btextheight = 10 end
local bwidth = HealBot_Config.bwidth[HealBot_Config.Current_Skin]
local textlen = math.floor(5 + (((bwidth * 1.8) / btextheight) - (btextheight / 2)))
bar:SetMinMaxValues(0, maxhlth);
bar:SetValue(hlth);
local englishClass = state.englishClass
local isHealer = false
if englishClass == "PALADIN" or englishClass == "DRUID" or englishClass == "SHAMAN" or englishClass == "PRIEST" then
isHealer = true
end
local pt = state.powerType
local showMana = false
if HealBot_Config.ShowManaBars == 1 and state.maxMana > 0 and pt == 0 then
if HealBot_Config.ManaBarsHealersOnly == 1 then
if isHealer then showMana = true end
else
showMana = true
end
end
if showMana then
local pr, pg, pb = 0, 0, 1
if bar3 then
bar3:SetMinMaxValues(0, state.maxMana)
bar3:SetValue(state.mana)
bar3:SetStatusBarColor(pr, pg, pb, HealBot_Config.Barcola[HealBot_Config.Current_Skin])
HealBot_Action_SetTexture(bar3, HealBot_Config.btexture[HealBot_Config.Current_Skin])
bar3:Show()
bar3:SetHeight(bheight * 0.2)
end
bar:SetHeight(bheight * 0.8)
bar2:SetHeight(bheight * 0.8)
else
if bar3 then
bar3:Hide()
end
bar:SetHeight(bheight)
bar2:SetHeight(bheight)
end
if HealBot_HealsIn[name] then
bar2:SetMinMaxValues(0, maxhlth);
bar2:SetValue(hlth + HealBot_HealsIn[name]);
else
bar2:SetValue(0);
end
bar.txt = getglobal(bar:GetName() .. "_text");
if (not HealBot_IsCasting and (HealBot_CanHeal(unit) or HealBot_MissingBuffs[unit])) then
button:Enable();
if HealBot_UnitDebuff[unit] then
sr = HealBot_Config.btextcursecolr[HealBot_Config.Current_Skin];
sg = HealBot_Config.btextcursecolg[HealBot_Config.Current_Skin];
sb = HealBot_Config.btextcursecolb[HealBot_Config.Current_Skin];
sa = HealBot_Config.btextcursecola[HealBot_Config.Current_Skin];
elseif HealBot_MissingBuffs[unit] then
r = r * 0.5;
g = g * 0.5;
b = b * 0.5;
sr = 1.0;
sg = 1.0;
sb = 0.0;
end
bar:SetStatusBarColor(r, g, b, HealBot_Config.Barcola[HealBot_Config.Current_Skin]);
bar2:SetStatusBarColor(r, g, b, HealBot_Config.BarcolaInHeal[HealBot_Config.Current_Skin]);
else
button:Disable();
sr = HealBot_Config.btextdisbledcolr[HealBot_Config.Current_Skin];
sg = HealBot_Config.btextdisbledcolg[HealBot_Config.Current_Skin];
sb = HealBot_Config.btextdisbledcolb[HealBot_Config.Current_Skin];
sa = HealBot_Config.btextdisbledcola[HealBot_Config.Current_Skin];
bar:SetStatusBarColor(r, g, b, HealBot_Config.bardisa[HealBot_Config.Current_Skin]);
bar2:SetStatusBarColor(r, g, b, HealBot_Config.bardisa[HealBot_Config.Current_Skin]);
end
if string.len(name) > textlen then
name = string.sub(name, 1, textlen - 3) .. '...';
end
bar.txt:SetText(name);
bar.txt:SetTextColor(sr, sg, sb, sa);
local fontName, fontHeight, fontFlags = bar.txt:GetFont()
local fontOutline = HealBot_Config.bfontoutline[HealBot_Config.Current_Skin] or 0
if fontOutline == 1 then
bar.txt:SetFont(fontName, fontHeight, "OUTLINE")
else
bar.txt:SetFont(fontName, fontHeight, "")
end
for i = 1, 5 do
local icon = getglobal(button:GetName() .. "BarIcon" .. i)
if icon then
if HealBot_UnitIcons and HealBot_UnitIcons[unit] and HealBot_UnitIcons[unit][i] then
icon:SetTexture(HealBot_UnitIcons[unit][i])
icon:Show()
else
icon:Hide()
end
end
end
end
function HealBot_Action_EnableButtons()
table.foreach(HealBot_Action_HealButtons, function (index, button)
HealBot_Action_EnableButton(button);
end);
end
function HealBot_Action_RefreshButton(button)
if not button then return end
local unit = button.unit;
if HealBot_MayHeal(unit) then
HealBot_Action_EnableButton(button)
end
end
function HealBot_Action_ResetSkin()
HealBot_Action_PartyChanged()
if HealBot_Options:IsVisible() then
HealBot_Action_SetTexture(HealBot_DiseaseColorpick, HealBot_Config.btexture[HealBot_Config.Current_Skin])
HealBot_Action_SetTexture(HealBot_MagicColorpick, HealBot_Config.btexture[HealBot_Config.Current_Skin])
HealBot_Action_SetTexture(HealBot_PoisonColorpick, HealBot_Config.btexture[HealBot_Config.Current_Skin])
HealBot_Action_SetTexture(HealBot_CurseColorpick, HealBot_Config.btexture[HealBot_Config.Current_Skin])
HealBot_Action_SetTexture(HealBot_EnTextColorpick, HealBot_Config.btexture[HealBot_Config.Current_Skin])
HealBot_Action_SetTexture(HealBot_EnTextColorpickin, HealBot_Config.btexture[HealBot_Config.Current_Skin])
HealBot_Action_SetTexture(HealBot_DisTextColorpick, HealBot_Config.btexture[HealBot_Config.Current_Skin])
HealBot_Action_SetTexture(HealBot_DebTextColorpick, HealBot_Config.btexture[HealBot_Config.Current_Skin])
HealBot_SetSkinColours()
end
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);
else
table.foreach(HealBot_Action_HealButtons, function (index, button)
HealBot_Action_RefreshButton(button);
end);
end
end
function HealBot_Action_PositionButton(button, OsetX, OsetY, bwidth, bheight, checked, header)
local brspace = HealBot_Config.brspace[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();
OsetY = OsetY + headerobj:GetHeight() + brspace;
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
OsetY = OsetY + button:GetHeight() + brspace;
else
button:Hide();
end
end
return OsetY;
end
function HealBot_Action_SetHeightWidth(width, height, bwidth)
if HealBot_ActionHeight then
HealBot_Action:SetHeight(HealBot_ActionHeight);
end
if HealBot_Config.GrowUpwards == 1 then
local left, bottom = HealBot_Action:GetLeft(), HealBot_Action:GetBottom();
if left and bottom then
if HealBot_Config.PanelAnchorX == -1 then HealBot_Config.PanelAnchorX = left; end
if HealBot_Config.PanelAnchorY == -1 then HealBot_Config.PanelAnchorY = bottom; end
HealBot_Action:ClearAllPoints();
HealBot_Action:SetPoint("BOTTOMLEFT", "UIParent", "BOTTOMLEFT", HealBot_Config.PanelAnchorX, HealBot_Config.PanelAnchorY);
end
else
local left, top = HealBot_Action:GetLeft(), HealBot_Action:GetTop();
if left and top then
HealBot_Action:ClearAllPoints();
HealBot_Action:SetPoint("TOPLEFT", "UIParent", "BOTTOMLEFT", left, top);
end
end
HealBot_Action:SetHeight(height);
HealBot_ActionHeight = height;
local bpadding = (HealBot_Config.bpadding and HealBot_Config.bpadding[HealBot_Config.Current_Skin]) or 10
HealBot_Action:SetWidth(width + bwidth + bpadding)
end
function HealBot_Action_SetHealButton(index, unit)
if not index then
HealBot_Action_HealButtons = {};
HealBot_Action_UnitButtons = {};
return nil
end
local button = getglobal("HealBot_Action_HealUnit" .. index);
button.unit = unit;
if unit then
table.insert(HealBot_Action_HealButtons, button);
if not HealBot_Action_UnitButtons[unit] then HealBot_Action_UnitButtons[unit] = {} end
table.insert(HealBot_Action_UnitButtons[unit], button);
else
button:Hide();
end
return button;
end
function HealBot_Action_PartyChanged()
if not HealBot_IsFighting then
local numBars = 0;
local numHeaders = 0;
local TempMaxH = 0;
local HeaderPos = {};
for j = 1, 15 do
local headerobj = getglobal("HealBot_Action_Header" .. j);
headerobj:SetText(" ")
headerobj:Hide();
end
local bwidth = HealBot_Config.bwidth[HealBot_Config.Current_Skin] or 85;
local sr = HealBot_Config.btextdisbledcolr[HealBot_Config.Current_Skin] or 0.4;
local sg = HealBot_Config.btextdisbledcolg[HealBot_Config.Current_Skin] or 0.4;
local sb = HealBot_Config.btextdisbledcolb[HealBot_Config.Current_Skin] or 0.4;
local sa = HealBot_Config.btextdisbledcola[HealBot_Config.Current_Skin] or 0.6;
local bheight = HealBot_Config.bheight[HealBot_Config.Current_Skin] or 18;
local btexture = HealBot_Config.btexture[HealBot_Config.Current_Skin] or 5;
local bcspace = HealBot_Config.bcspace[HealBot_Config.Current_Skin] or 4;
local cols = HealBot_Config.numcols[HealBot_Config.Current_Skin] or 2;
local btextheight = HealBot_Config.btextheight[HealBot_Config.Current_Skin] or 10;
local abortsize = HealBot_Config.abortsize[HealBot_Config.Current_Skin] or 10;
local checked_start = 0;
local checked_end = 0;
headerno = 0;
for j = 1, 41 do
HealBot_Action_SetHealButton(j, nil);
end
for j = 51, 60 do
HealBot_Action_SetHealButton(j, nil);
end
HealBot_Action_SetHealButton();
local i = 0;
local last = 0;
local GroupValid = numBars;
last = last + 6
if HealBot_Config.GroupHeals == 1 then
if HealBot_Config.ShowHeader[HealBot_Config.Current_Skin] == 1 then
HeaderPos[i + 1] = HEALBOT_OPTIONS_GROUPHEALS
end
for _, unit in ipairs(HealBot_Action_HealGroup) do
if not HealBot_Action_UnitButtons[unit] and HealBot_MayHeal(unit) then
i = i + 1;
HealBot_Action_SetHealButton(i, unit);
numBars = numBars + 1;
end
if i == last then break end
end
end
if numBars > GroupValid and HealBot_Config.ShowHeader[HealBot_Config.Current_Skin] == 1 then
numBars = numBars + 1;
numHeaders = numHeaders + 1;
end
last = last + 10
local TankValid = numBars;
if HealBot_Config.TankHeals == 1 then
if GetNumRaidMembers() > 0 and CT_RA_MainTanks then
if HealBot_Config.ShowHeader[HealBot_Config.Current_Skin] == 1 then
HeaderPos[i + 1] = HEALBOT_OPTIONS_TANKHEALS
end
for j = 1, 10 do
if CT_RA_MainTanks[j] then
for k = 1, GetNumRaidMembers() do
local unit = "raid" .. k;
local PossibleMT = 1;
if UnitInParty(unit) and HealBot_Config.GroupHeals == 1 then
if not UnitIsUnit(unit, "player") then
PossibleMT = 0;
end
end
if PossibleMT == 1 then
if UnitName(unit) == CT_RA_MainTanks[j] then
if not HealBot_Action_UnitButtons[unit] and HealBot_MayHeal(unit) then
i = i + 1;
HealBot_Action_SetHealButton(i, unit);
numBars = numBars + 1;
end
end
end
end
end
if i == last then break end
end
end
end
if numBars > TankValid and HealBot_Config.ShowHeader[HealBot_Config.Current_Skin] == 1 then
numBars = numBars + 1;
numHeaders = numHeaders + 1;
end
last = last + 10;
local h = 50;
local TargetValid = numBars;
if HealBot_Config.TargetHeals == 1 then
if HealBot_Config.ShowHeader[HealBot_Config.Current_Skin] == 1 then
HeaderPos[i + 1] = HEALBOT_OPTIONS_TARGETHEALS
end
for _, unit in ipairs(HealBot_Action_HealTarget) do
if not HealBot_Action_UnitButtons[unit] and HealBot_MayHeal(unit) then
i = i + 1;
h = h + 1;
if checked_start == 0 then checked_start = i; end
checked_end = i;
HealBot_Action_SetHealButton(h, unit);
local check = getglobal("HealBot_Action_HealUnit" .. h .. "Check");
check.unit = unit;
check:SetChecked(1);
check:Show();
numBars = numBars + 1;
end
if i == last then break end
end
last = last + 1
local unit = HealBot_TargetName()
if not HealBot_Action_UnitButtons[unit] and HealBot_MayHeal("target") then
i = i + 1;
h = h + 1;
if h < 61 then
HealBot_Action_SetHealButton(h, "target");
local check = getglobal("HealBot_Action_HealUnit" .. h .. "Check");
check:SetChecked(0);
check.unit = unit;
if check.unit then
if checked_start == 0 then checked_start = i; end
checked_end = i;
check:Show();
else
check:Hide();
end
else
HealBot_Action_SetHealButton(i, "target");
end
numBars = numBars + 1;
end
end
if numBars > TargetValid and HealBot_Config.ShowHeader[HealBot_Config.Current_Skin] == 1 then
numBars = numBars + 1;
numHeaders = numHeaders + 1;
end
last = last + 40
local ExtraValid = numBars;
if HealBot_Config.EmergencyHeals == 1 then
local order = {};
local units = {};
if HealBot_Config.ShowHeader[HealBot_Config.Current_Skin] == 1 and HealBot_Config.ExtraOrder == 1 then
HeaderPos[i + 1] = HEALBOT_OPTIONS_EMERGENCYHEALS
numBars = numBars + 1;
numHeaders = numHeaders + 1;
end
if HealBot_Config.EmergIncMonitor == 1 then
if GetNumRaidMembers() > 0 then
for j = 1, 40 do
local PossibleEmerg = 1;
local unit = "raid" .. j;
local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(j);
if not name then name = "not known" end
if not class then class = "not known" end
if not subgroup then subgroup = "not known" end
if UnitInParty(unit) and HealBot_Config.GroupHeals == 1 then
PossibleEmerg = 0;
end
if PossibleEmerg == 1 then
if not HealBot_Action_UnitButtons[unit] and HealBot_MayHeal(unit) then
if HealBot_Config.ExtraOrder == 1 then
order[unit] = name;
elseif HealBot_Config.ExtraOrder == 2 then
order[unit] = class;
elseif HealBot_Config.ExtraOrder == 3 then
order[unit] = subgroup;
else
order[unit] = 0 - UnitHealthMax(unit);
if UnitHealthMax(unit) > TempMaxH then TempMaxH = UnitHealthMax(unit); end
end
table.insert(units, unit);
numBars = numBars + 1;
end
end
end
else
for _, unit in ipairs(HealBot_Action_HealGroup) do
if not HealBot_Action_UnitButtons[unit] and HealBot_MayHeal(unit) then
if HealBot_Config.ExtraOrder == 1 then
order[unit] = name;
elseif HealBot_Config.ExtraOrder == 2 then
order[unit] = class;
elseif HealBot_Config.ExtraOrder == 3 then
order[unit] = subgroup;
else
order[unit] = 0 - UnitHealthMax(unit);
if UnitHealthMax(unit) > TempMaxH then TempMaxH = UnitHealthMax(unit); end
end
table.insert(units, unit);
numBars = numBars + 1;
end
end
end
else
if GetNumRaidMembers() > 0 then
for j = 1, 40 do
local unit = "raid" .. j;
local Class = UnitClass(unit);
local ProcessUnit = 0;
local PossibleEmerg = 1;
local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(j);
if not name then name = "not known" end
if not class then class = "not known" end
if not subgroup then subgroup = "not known" end
if HealBot_EmergInc[Class] == 1 then
ProcessUnit = 1;
end
if UnitInParty(unit) and HealBot_Config.GroupHeals == 1 then
PossibleEmerg = 0;
end
if ProcessUnit == 1 and PossibleEmerg == 1 then
if not HealBot_Action_UnitButtons[unit] and HealBot_MayHeal(unit) then
if HealBot_Config.ExtraOrder == 1 then
order[unit] = name;
elseif HealBot_Config.ExtraOrder == 2 then
order[unit] = class;
elseif HealBot_Config.ExtraOrder == 3 then
order[unit] = subgroup;
else
order[unit] = 0 - UnitHealthMax(unit);
if UnitHealthMax(unit) > TempMaxH then TempMaxH = UnitHealthMax(unit); end
end
table.insert(units, unit);
numBars = numBars + 1;
end
end
end
else
for _, unit in ipairs(HealBot_Action_HealGroup) do
if not HealBot_Action_UnitButtons[unit] and HealBot_MayHeal(unit) then
if HealBot_Config.ExtraOrder == 1 then
order[unit] = name;
elseif HealBot_Config.ExtraOrder == 2 then
order[unit] = class;
elseif HealBot_Config.ExtraOrder == 3 then
order[unit] = subgroup;
else
order[unit] = 0 - UnitHealthMax(unit);
if UnitHealthMax(unit) > TempMaxH then TempMaxH = UnitHealthMax(unit); end
end
table.insert(units, unit);
numBars = numBars + 1;
end
end
end
end
table.sort(units, function (a, b)
if order[a] < order[b] then return true end
if order[a] > order[b] then return false end
return a < b
end)
local TempSort = "init"
TempMaxH = math.ceil(TempMaxH / 1000) * 1000;
if GetNumRaidMembers() > 0 then
for j = 1, 40 do
if not units[j] then break end
local name, rank, subgroup, level, class, fileName, zone, online, isDead = GetRaidRosterInfo(string.sub(units[j], 5));
if HealBot_Config.ShowHeader[HealBot_Config.Current_Skin] == 1 and HealBot_Config.ExtraOrder == 2 and TempSort ~= class then
TempSort = class
HeaderPos[i + 1] = class
numBars = numBars + 1;
numHeaders = numHeaders + 1;
end
if HealBot_Config.ShowHeader[HealBot_Config.Current_Skin] == 1 and HealBot_Config.ExtraOrder == 3 and TempSort ~= subgroup then
TempSort = subgroup
HeaderPos[i + 1] = HEALBOT_OPTIONS_GROUPHEALS .. subgroup
numBars = numBars + 1;
numHeaders = numHeaders + 1;
end
if HealBot_Config.ShowHeader[HealBot_Config.Current_Skin] == 1 and HealBot_Config.ExtraOrder == 4 and TempMaxH > UnitHealthMax(units[j]) then
TempMaxH = TempMaxH - 1000
HeaderPos[i + 1] = ">" .. tostring(TempMaxH / 1000) .. "k"
numBars = numBars + 1;
numHeaders = numHeaders + 1;
end
i = i + 1;
HealBot_Action_SetHealButton(i, units[j]);
if i == last then break end
end
end
end
if numBars == ExtraValid + 1 and HealBot_Config.ShowHeader[HealBot_Config.Current_Skin] == 1 then
HeaderPos[i + 1] = nil;
numBars = numBars - 1;
end
local bpadding = (HealBot_Config.bpadding and HealBot_Config.bpadding[HealBot_Config.Current_Skin]) or 10
local OffsetY = bpadding;
local OffsetX = bpadding;
local MaxOffsetY = 0;
if cols > (numBars - numHeaders) then
cols = numBars - numHeaders;
end
if cols <= 0 then cols = 1 end
local h = 1;
local i = 0;
local z = 1;
table.foreach(HealBot_Action_HealButtons, function (index, button)
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;
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;
end
z = z + 1;
h = h + 1;
local bar = HealBot_Action_HealthBar(button);
local bar2 = HealBot_Action_HealthBar2(button);
bar.txt = getglobal(bar:GetName() .. "_text");
bar:SetHeight(bheight);
HealBot_Action_SetTexture(bar, btexture);
bar.txt:SetTextHeight(btextheight);
local barScale = bar:GetScale();
bar:SetScale(barScale + 0.01);
bar:SetScale(barScale);
bar2:SetHeight(bheight);
HealBot_Action_SetTexture(bar2, btexture);
end);
if MaxOffsetY < OffsetY then MaxOffsetY = OffsetY; end
if HealBot_Config.HideOptions == 1 then
HealBot_Action_OptionsButton:Hide();
else
HealBot_Action_OptionsButton:SetPoint("BOTTOM", "HealBot_Action", "BOTTOM", 0, bpadding);
HealBot_Action_OptionsButton:Show();
MaxOffsetY = MaxOffsetY + 30;
end
if HealBot_Config.HideAbort == 1 then
HealBot_Action_AbortButton:Hide();
else
local bar = HealBot_Action_HealthBar(HealBot_Action_AbortButton);
local denom = 6 - (abortsize / 3)
if denom == 0 then denom = 1 end
local width = (bwidth - 12) + (OffsetX / denom);
bar.txt = getglobal(bar:GetName() .. "_text");
bar.txt:SetTextColor(sr, sg, sb, sa);
bar.txt:SetText(HEALBOT_ACTION_ABORT);
HealBot_Action_SetTexture(bar, btexture);
bar:SetMinMaxValues(0, 100);
bar:SetValue(100);
bar:ClearAllPoints();
bar:SetHeight(bheight + abortsize);
bar:SetWidth(width);
bar:SetStatusBarColor(0.1, 0.1, 0.4, 0);
MaxOffsetY = MaxOffsetY + 30 + abortsize;
HealBot_Action_AbortButton:ClearAllPoints();
HealBot_Action_AbortButton:SetWidth(width)
HealBot_Action_AbortButton:SetHeight(bheight + abortsize);
if HealBot_Config.HideOptions == 1 then
HealBot_Action_AbortButton:SetPoint("BOTTOM", "HealBot_Action", "BOTTOM", 0, bpadding);
bar:SetPoint("BOTTOM", "HealBot_Action", "BOTTOM", 0, bpadding);
else
HealBot_Action_AbortButton:SetPoint("BOTTOM", "HealBot_Action_OptionsButton", "TOP", 0, 10);
bar:SetPoint("BOTTOM", "HealBot_Action_OptionsButton", "TOP", 0, 10);
end
HealBot_Action_AbortButton:Show();
end
HealBot_Action_SetHeightWidth(OffsetX, MaxOffsetY + bpadding, bwidth);
end
HealBot_Action_RefreshButtons();
end
function HealBot_Action_Reset()
HealBot_Action:ClearAllPoints();
HealBot_Action:SetPoint("TOP", "MinimapCluster", "BOTTOM", 7, 10);
HealBot_Action_HealTarget = {};
HealBot_Action_PartyChanged();
end
function HealBot_Action_Refresh(unit)
if (UnitIsDeadOrGhost("player")) or (UnitOnTaxi("player")) then
if HealBot_Config.AutoClose == 1 and HealBot_Config.ActionVisible ~= 0 then
HealBot_Action:Hide();
else
HealBot_Action_RefreshButtons(unit);
end
return;
end
HealBot_Action_RefreshButtons(unit);
if not HealBot_IsFighting then
if (HealBot_Action_MustHealSome()) then
HealBot_Action:Show();
elseif HealBot_AbortButton == 0 then
HealBot_Action:Show();
elseif (not HealBot_Action_ShouldHealSome()) then
if HealBot_AbortButton == 1 and HealBot_Config.AutoClose == 1 and HealBot_Config.ActionVisible ~= 0 then
HealBot_Action:Hide();
end
end
end
end
+250
View File
@@ -0,0 +1,250 @@
-- HealBot_View_Tooltip.lua
-- Handles rendering of unit and spell tooltips in the HealBot UI
HealBot_Action_TooltipUnit = nil
function HealBot_Action_RefreshTooltip(unit)
if HealBot_Config.ShowTooltip==0 then return end
if not unit then unit = HealBot_Action_TooltipUnit end
if not unit then return end;
local hlth=UnitHealth(unit);
local maxhlth=UnitHealthMax(unit);
local spellLeft = HealBot_GetHealSpell(unit,HealBot_Action_SpellPattern("Left"));
local spellMiddle = HealBot_GetHealSpell(unit,HealBot_Action_SpellPattern("Middle"));
local spellRight = HealBot_GetHealSpell(unit,HealBot_Action_SpellPattern("Right"));
local spellButton4 = HealBot_GetHealSpell(unit,HealBot_Action_SpellPattern("Button4"));
local spellButton5 = HealBot_GetHealSpell(unit,HealBot_Action_SpellPattern("Button5"));
local linenum = 1
HealBot_Action_Tooltip_ClearLines();
if HealBot_Config.Tooltip_ShowTarget==1 then
if UnitName(unit) then
HealBot_Action_Tooltip_SetLineLeft(UnitName(unit),0,1,0,linenum)
if hlth and maxhlth then
local r,g,b,a=HealBot_HealthColor(unit,hlth,maxhlth);
HealBot_Action_Tooltip_SetLineRight(hlth.."/"..maxhlth.." (-"..maxhlth-hlth..")",r,g,b,linenum)
end
end
end
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
HealBot_Action_Tooltip_SetLineRight(HealBot_Action_Tooltip_SpellSummary(spellButton5),1,1,1,linenum)
end
end
if HealBot_Config.Tooltip_Recommend==1 then
local Instant_check=0;
if HealBot_Config.Tooltip_ShowSpellDetail==1 then linenum=linenum+1; end
linenum=linenum+1
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_TOOLTIP_RECOMMENDTEXT,0.8,0.8,0,linenum)
Instant_check=0;
Instant_check,linenum=HealBot_Action_Tooltip_CheckForInstant(unit,spellLeft,"upd",linenum,Instant_check);
Instant_check,linenum=HealBot_Action_Tooltip_CheckForInstant(unit,spellMiddle,"upd",linenum,Instant_check);
Instant_check,linenum=HealBot_Action_Tooltip_CheckForInstant(unit,spellRight,"upd",linenum,Instant_check);
Instant_check,linenum=HealBot_Action_Tooltip_CheckForInstant(unit,spellButton4,"upd",linenum,Instant_check);
Instant_check,linenum=HealBot_Action_Tooltip_CheckForInstant(unit,spellButton5,"upd",linenum,Instant_check);
if Instant_check==0 then
linenum=linenum+1
HealBot_Action_Tooltip_SetLineLeft(" None",0.4,0.4,0.4,linenum)
end
end
local height = 20
local width = 0
for i = 1, linenum do
local txtL = getglobal("HealBot_TooltipTextL" .. i)
local txtR = getglobal("HealBot_TooltipTextR" .. i)
height = height + txtL:GetHeight() + 2
if (txtL:GetWidth() + txtR:GetWidth() + 25 > width) then
width = txtL:GetWidth() + txtR:GetWidth() + 25
end
end
HealBot_Tooltip:SetWidth(width)
HealBot_Tooltip:SetHeight(height)
HealBot_Tooltip:ClearAllPoints();
if HealBot_Config.TooltipPos>1 then
if HealBot_Config.TooltipPos==2 then
HealBot_Tooltip:SetPoint("TOPRIGHT","HealBot_Action","TOPLEFT",0,0);
elseif HealBot_Config.TooltipPos==3 then
HealBot_Tooltip:SetPoint("TOPLEFT","HealBot_Action","RIGHT",0,0);
elseif HealBot_Config.TooltipPos==4 then
HealBot_Tooltip:SetPoint("BOTTOM","HealBot_Action","TOP",0,0);
else
HealBot_Tooltip:SetPoint("TOP","HealBot_Action","BOTTOM",0,0);
end
else
HealBot_Tooltip:SetPoint("BOTTOMRIGHT","WorldFrame","BOTTOMRIGHT",-105,105);
end
HealBot_Tooltip:Show();
end
function HealBot_Action_Tooltip_SpellInfo(spell,linenum)
local text
if HealBot_Spells[spell] then
if HealBot_Spells[spell].HealsDur>0 then
linenum=linenum+1
HealBot_Action_Tooltip_SetLineLeft(HEALBOT_WORDS_CAST..": "..HealBot_Spells[spell].CastTime.." "..HEALBOT_WORDS_SEC..".",0.8,0.8,0.8,linenum)
HealBot_Action_Tooltip_SetLineRight("Mana: "..HealBot_Spells[spell].Mana,0.5,0.5,1,linenum)
if HealBot_Spells[spell].HealsMax>0 then
local Heals = HEALBOT_HEAL.." "
if HealBot_Spells[spell].Shield then
Heals = HEALBOT_TOOLTIP_SHIELD.." "
end
if HealBot_Spells[spell].HealsMin<HealBot_Spells[spell].HealsMax then
text=Heals..format("%d", HealBot_Spells[spell].HealsMin + HealBot_Spells[spell].RealHealing) .." "..HEALBOT_WORDS_TO.." "..format("%d",HealBot_Spells[spell].HealsMax + HealBot_Spells[spell].RealHealing)
else
text=Heals..format("%d", HealBot_Spells[spell].HealsMax + HealBot_Spells[spell].RealHealing)
end
linenum=linenum+1
HealBot_Action_Tooltip_SetLineLeft(text,1,1,1,linenum)
end
if HealBot_Spells[spell].HealsExt>0 then
text=HEALBOT_HEAL.." "..HealBot_Spells[spell].HealsDur.." "..HEALBOT_WORDS_OVER.." "..HealBot_Spells[spell].Duration-HealBot_Spells[spell].CastTime.." sec."
linenum=linenum+1
HealBot_Action_Tooltip_SetLineLeft(text,1,1,1,linenum)
end
if not HealBot_Spells[spell].Shield then
text=HEALBOT_TOOLTIP_ITEMBONUS.." +"..HealBot_GetBonus().." | "..HEALBOT_TOOLTIP_ACTUALBONUS.." +"..HealBot_Spells[spell].RealHealing.." "
linenum=linenum+1
HealBot_Action_Tooltip_SetLineLeft(text,0.8,0.8,0.8,linenum)
end
end
end
return linenum
end
function HealBot_Action_Tooltip_SpellSummary(spell)
local ret_val = " ";
if HealBot_Spells[spell] then
if HealBot_Spells[spell].HealsDur and HealBot_Spells[spell].HealsDur>0 then
if HealBot_Spells[spell].HealsMax and HealBot_Spells[spell].HealsMax>0 then
local Heals = " "..HEALBOT_HEAL.." ";
if HealBot_Spells[spell].Shield then
Heals = " "..HEALBOT_TOOLTIP_SHIELD.." ";
end
if (HealBot_Spells[spell].HealsMin or 0)<(HealBot_Spells[spell].HealsMax or 0) then
ret_val=ret_val..Heals..format("%d", (((HealBot_Spells[spell].HealsMin or 0)+(HealBot_Spells[spell].HealsMax or 0))/2) + (HealBot_Spells[spell].RealHealing or 0));
else
ret_val=ret_val..Heals..format("%d", (HealBot_Spells[spell].HealsMax or 0) + (HealBot_Spells[spell].RealHealing or 0));
end
end
if HealBot_Spells[spell].HealsExt and HealBot_Spells[spell].HealsExt>0 then
ret_val=ret_val.." HoT "..HealBot_Spells[spell].HealsDur;
end
if HealBot_Spells[spell].Mana then
ret_val=ret_val.." "..HEALBOT_WORDS_FOR.." "..HealBot_Spells[spell].Mana.." Mana";
end
end
end
if string.len(ret_val)<5 then ret_val = " - "..spell; end
return ret_val
end
function HealBot_Action_Tooltip_CheckForInstant(unit,spell,upd,linenum,check)
if HealBot_Spells[spell] then
if HealBot_Spells[spell].CastTime == 0 then
if HealBot_UnitAffected(unit,HealBot_Spells[spell].Buff) then return check,linenum end;
if HealBot_UnitAffected(unit,HealBot_Spells[spell].Debuff) then return check,linenum end;
if upd=="upd" then
linenum=linenum+1
HealBot_Action_Tooltip_SetLineLeft(" "..spell,1,1,1,linenum)
end
else
return check,linenum;
end
else
return check,linenum
end
return check+1,linenum;
end
function HealBot_Action_Tooltip_SetLineLeft(Text,R,G,B,linenum)
local txtL = getglobal("HealBot_TooltipTextL" .. linenum)
txtL:SetTextColor(R,G,B)
txtL:SetText(Text)
txtL:Show()
end
function HealBot_Action_Tooltip_SetLineRight(Text,R,G,B,linenum)
local txtR = getglobal("HealBot_TooltipTextR" .. linenum)
txtR:SetTextColor(R,G,B)
txtR:SetText(Text)
txtR:Show()
end
function HealBot_Action_Tooltip_ClearLines()
for j=1,30 do
local txtL = getglobal("HealBot_TooltipTextL" .. j)
local txtR = getglobal("HealBot_TooltipTextR" .. j)
txtL:SetText(" ")
txtR:SetText(" ")
txtL:Hide()
txtR:Hide()
end
end
function HealBot_Action_ShowTooltip(this)
if HealBot_Config.ShowTooltip==0 then return end
if not this.unit then return end;
if not this:IsEnabled() then return end;
HealBot_Action_TooltipUnit = this.unit;
HealBot_Action_RefreshTooltip(this.unit);
end
function HealBot_Action_HideTooltip(this)
if HealBot_Config.ShowTooltip==0 then return end
HealBot_Tooltip:Hide();
HealBot_Action_TooltipUnit = nil;
end
+6 -2
View File
@@ -1,7 +1,7 @@
**HealBotBlue**
By Bluewhale.
Original Vanilla 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.
> **NOTE:** For HealBot to work correctly, the **Selfcast** feature in WoW options needs to be disabled.
@@ -23,8 +23,12 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\
### Change Log
**v1.3**
* **Monolithic Code Modularization:** Split the massive, single-file options system (`HealBot_Options.xml`/`HealBot_Options.lua`) into 7 dedicated, content-named panel subfiles (`General`, `Spells`, `Healing`, `CDC`, `Skins`, `Buffs`, and `Chat`) to improve codebase modularity and stability.
* **Monolithic Code Modularization (Options):** Split the massive, single-file options system (`HealBot_Options.xml`/`HealBot_Options.lua`) into 7 dedicated, content-named panel subfiles (`General`, `Spells`, `Healing`, `CDC`, `Skins`, `Buffs`, and `Chat`) to improve codebase modularity and stability.
* **Core Code Decoupling (MVC & Observer Pattern):** Modularized `HealBot.lua` and `HealBot_Action.lua` by decoupling them into dedicated service files: `Range`, `Comms`, `Aura`, `Spells`, `Events` controllers, and `Layout`, `Tooltip` views.
* **Scope Resolution Fix:** Promoted `HealBot_Options_ComboButtons_Button` to global scope in the base options file to resolve a `nil` comparison error when loading spell settings.
* **Global Scoping & Variable Promotion:** Promoted `CalcEquipBonus`, `HealBot_EquipChangeTimer`, `HealValue`, `InitSpells`, and `Delay_RecalcParty` to global scope in `HealBot.lua` to ensure cross-module visibility.
* **CTRA Resurrection Cancel Bug Fix:** Fixed a nil table indexing crash in the CTRA `RESNO` message handler in `HealBot_Controller_Comms.lua`.
* **Lua 5.1 Compatibility Update:** Forwarded observer parameters directly via vararg forwarding (`...`) in `HealBot_Model.lua` to avoid runtime errors with the deprecated `arg` table.
* **Core Options Layout Correction:** Relocated the "Defaults" and "Close" buttons back into the parent options frame's container, ensuring they display consistently at the bottom of all configuration tabs.
* **Skins Grid Alignment:** Fixed layout overlaps on the Skins panel by setting explicit width/height sizes (`123 x 17`) on the opacity sliders and reorganizing all 13 sliders into a clean, uniform 2-column grid.
* **Startup Refresh Optimization:** Resolved initial loading lag where action bars would be missing by forcing an immediate UI refresh (`HealBot_RecalcSpells()`) once spell data loads.