mirror of
https://github.com/Bluewhale1337/HealBotBlue.git
synced 2026-10-27 06:00:54 +00:00
+49
-19
@@ -103,6 +103,21 @@ function HealBot_SlashCmd(cmd)
|
||||
HealBot_AddDebug( "Channel active" );
|
||||
return;
|
||||
end
|
||||
if (cmd=="debug" or cmd=="dbg") then
|
||||
if not HealBot_Config then return; end
|
||||
if HealBot_Config.DebugMode == 1 then
|
||||
HealBot_Config.DebugMode = 0;
|
||||
if DEFAULT_CHAT_FRAME then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cFFFFD100HealBot|r: Debug mode |cFFFF0000DISABLED|r.");
|
||||
end
|
||||
else
|
||||
HealBot_Config.DebugMode = 1;
|
||||
if DEFAULT_CHAT_FRAME then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cFFFFD100HealBot|r: Debug mode |cFF00FF00ENABLED|r.");
|
||||
end
|
||||
end
|
||||
return;
|
||||
end
|
||||
end
|
||||
|
||||
-- HealBot_SendAddonMessage moved to HealBot_Controller_Comms.lua
|
||||
@@ -222,27 +237,42 @@ end
|
||||
|
||||
-- SpiBonus and GetBonus functions moved to HealBot_Controller_Spells.lua
|
||||
|
||||
local HealBot_RaidUnitTokens = {}
|
||||
for i=1, 40 do HealBot_RaidUnitTokens[i] = "raid"..i end
|
||||
|
||||
HealBot_NameToUnitID = {}
|
||||
|
||||
function HealBot_UpdateUnitIDCache()
|
||||
HealBot_NameToUnitID = {}
|
||||
local name = UnitName("player")
|
||||
if name then HealBot_NameToUnitID[name] = "player" end
|
||||
|
||||
for i=1, 4 do
|
||||
local unit = "party"..i
|
||||
name = UnitName(unit)
|
||||
if name then HealBot_NameToUnitID[name] = unit end
|
||||
unit = "partypet"..i
|
||||
name = UnitName(unit)
|
||||
if name then HealBot_NameToUnitID[name] = unit end
|
||||
end
|
||||
|
||||
local petName = UnitName("pet")
|
||||
if petName then HealBot_NameToUnitID[petName] = "pet" end
|
||||
|
||||
for i=1, 40 do
|
||||
local unit = "raid"..i
|
||||
name = UnitName(unit)
|
||||
if name then HealBot_NameToUnitID[name] = unit end
|
||||
unit = "raidpet"..i
|
||||
name = UnitName(unit)
|
||||
if name then HealBot_NameToUnitID[name] = unit end
|
||||
end
|
||||
end
|
||||
|
||||
-- HealBot_FindUnitID: Finds a unit token for a given player name.
|
||||
function HealBot_FindUnitID(unitname)
|
||||
local text;
|
||||
for _,unit in ipairs(HealBot_Action_HealGroup) do
|
||||
text = UnitName(unit);
|
||||
if text then
|
||||
if text==unitname then
|
||||
return unit;
|
||||
end
|
||||
end
|
||||
end
|
||||
for i=1,40 do
|
||||
local unit = "raid"..i;
|
||||
text = UnitName(unit);
|
||||
if text then
|
||||
if text==unitname then
|
||||
return unit;
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil;
|
||||
if not unitname then return nil end
|
||||
return HealBot_NameToUnitID[unitname]
|
||||
end
|
||||
|
||||
-- HealBot_PlaySound: Plays an audio alert based on ID.
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
## Interface: 11200
|
||||
## Title: HealBotBlue
|
||||
## Version: 1.7.3
|
||||
## Version: 1.7.4
|
||||
## Author: Bluewhale
|
||||
## Notes: Raidframe replacement for healing, decursing, resource tracking and buffing with optional support for SuperWow, ClassicAPI, UnitXP_SP3 and Nampower.
|
||||
## SavedVariablesPerCharacter: HealBot_Config
|
||||
|
||||
@@ -107,13 +107,25 @@ function HealBot_CheckBuffs(unit)
|
||||
hasBuff[k] = nil
|
||||
end
|
||||
local i = 1
|
||||
if not HealBot_TextureToName then HealBot_TextureToName = {} end
|
||||
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()
|
||||
|
||||
local buffName = HealBot_TextureToName[buffTexture]
|
||||
if buffName == nil then
|
||||
HealBot_ScanTooltip:SetOwner(UIParent, "ANCHOR_NONE")
|
||||
HealBot_ScanTooltip:ClearLines()
|
||||
HealBot_ScanTooltip:SetUnitBuff(unit, i)
|
||||
local textObj = HealBot_ScanTooltipTextLeft1
|
||||
if textObj then
|
||||
buffName = textObj:GetText()
|
||||
end
|
||||
if buffName then
|
||||
HealBot_TextureToName[buffTexture] = buffName
|
||||
end
|
||||
end
|
||||
|
||||
if buffName then
|
||||
hasBuff[buffName] = true
|
||||
end
|
||||
@@ -260,9 +272,11 @@ function HealBot_OnEvent_UnitAura(this, unit)
|
||||
end
|
||||
|
||||
local b = 1
|
||||
local activeBuffs = HealBot_GetTable()
|
||||
while true do
|
||||
local buff = UnitBuff(unit, b)
|
||||
if not buff then break end
|
||||
activeBuffs[buff] = true
|
||||
if HealBot_TrackedHoTs[buff] and iconCount < 10 then
|
||||
iconCount = iconCount + 1
|
||||
HealBot_UnitIcons[unit][iconCount] = buff
|
||||
@@ -270,6 +284,30 @@ function HealBot_OnEvent_UnitAura(this, unit)
|
||||
b = b + 1
|
||||
end
|
||||
|
||||
if HealBot_Integrations_Nampower_Active and HealBot_Nampower_Auras then
|
||||
local guid = HealBot_GetUnitGUID and HealBot_GetUnitGUID(unit)
|
||||
if guid then
|
||||
if not HealBot_Nampower_NameCache then HealBot_Nampower_NameCache = HealBot_GetTable() end
|
||||
HealBot_Nampower_NameCache[guid] = UnitName(unit)
|
||||
|
||||
if HealBot_Nampower_Auras[guid] then
|
||||
local validHoTs = {
|
||||
["Renew"] = "Interface\\Icons\\Spell_Holy_Renew",
|
||||
["Rejuvenation"] = "Interface\\Icons\\Spell_Nature_Rejuvenation",
|
||||
["Regrowth"] = "Interface\\Icons\\Spell_Nature_ResistNature",
|
||||
["Power Word: Shield"] = "Interface\\Icons\\Spell_Holy_PowerWordShield",
|
||||
}
|
||||
for spellName, _ in pairs(HealBot_Nampower_Auras[guid]) do
|
||||
local tex = validHoTs[spellName]
|
||||
if tex and not activeBuffs[tex] then
|
||||
HealBot_Nampower_Auras[guid][spellName] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
HealBot_ReleaseTable(activeBuffs)
|
||||
|
||||
local d = 1
|
||||
while true do
|
||||
local debuff = UnitDebuff(unit, d)
|
||||
|
||||
@@ -30,8 +30,15 @@ function HealBot_AddChat(msg)
|
||||
end
|
||||
end
|
||||
|
||||
-- HealBot_AddDebug: Prints debug messages to internal chat channel.
|
||||
-- HealBot_AddDebug: Prints debug messages to chat or internal debug channel.
|
||||
function HealBot_AddDebug(msg)
|
||||
if HealBot_Config and HealBot_Config.DebugMode == 1 then
|
||||
if DEFAULT_CHAT_FRAME then
|
||||
DEFAULT_CHAT_FRAME:AddMessage("|cFFFFD100[HB Debug]|r " .. msg);
|
||||
end
|
||||
return;
|
||||
end
|
||||
|
||||
local chanid = HealBot_Get_DebugChan();
|
||||
if chanid and HealBot_SpamCnt < 3 then
|
||||
HealBot_SpamCnt = HealBot_SpamCnt + 1;
|
||||
@@ -136,9 +143,17 @@ function HealBot_OnEvent_AddonMsg(this, addon_id, inc_msg, dist_target, sender_i
|
||||
-- Clear reusable args array
|
||||
for i=1, 10 do HealBot_Comms_Args[i] = nil end
|
||||
local argCount = 0
|
||||
for word in string.gfind(inc_msg, "[^/]+") do
|
||||
local start_pos = 1
|
||||
local next_pos = string.find(inc_msg, "/", start_pos, true)
|
||||
while next_pos do
|
||||
argCount = argCount + 1
|
||||
HealBot_Comms_Args[argCount] = word
|
||||
HealBot_Comms_Args[argCount] = string.sub(inc_msg, start_pos, next_pos - 1)
|
||||
start_pos = next_pos + 1
|
||||
next_pos = string.find(inc_msg, "/", start_pos, true)
|
||||
end
|
||||
if start_pos <= string.len(inc_msg) then
|
||||
argCount = argCount + 1
|
||||
HealBot_Comms_Args[argCount] = string.sub(inc_msg, start_pos)
|
||||
end
|
||||
local cmd = HealBot_Comms_Args[1]
|
||||
|
||||
|
||||
@@ -173,13 +173,6 @@ function HealBot_OnUpdate(this, arg1)
|
||||
HealBot_Action_RefreshPower(unitID)
|
||||
end
|
||||
|
||||
local powerID, _ = next(HealBot_View_DirtyPower)
|
||||
while powerID do
|
||||
HealBot_Action_RefreshPower(powerID)
|
||||
HealBot_View_DirtyPower[powerID] = nil
|
||||
powerID, _ = next(HealBot_View_DirtyPower)
|
||||
end
|
||||
|
||||
if HealBot_EquipChangeTimer > 0 then
|
||||
HealBot_EquipChangeTimer = HealBot_EquipChangeTimer - arg1
|
||||
if HealBot_EquipChangeTimer <= 0 then
|
||||
@@ -189,6 +182,16 @@ function HealBot_OnUpdate(this, arg1)
|
||||
HealBot_RecalcSpells();
|
||||
end
|
||||
end
|
||||
if HealBot_Config.HealBot_Integrations_ShowHoTTimers == 1 then
|
||||
if not HealBot_HoT_Update_Timer or GetTime() >= HealBot_HoT_Update_Timer then
|
||||
HealBot_HoT_Update_Timer = GetTime() + 0.25
|
||||
if HealBot_Action_UpdatePlayerHoTs then
|
||||
HealBot_Action_UpdatePlayerHoTs()
|
||||
end
|
||||
end
|
||||
elseif HealBot_PlayerHoTsListFrame and HealBot_PlayerHoTsListFrame:IsVisible() then
|
||||
HealBot_PlayerHoTsListFrame:Hide()
|
||||
end
|
||||
|
||||
HealBot_Timer1 = HealBot_Timer1 + arg1;
|
||||
if HealBot_Timer1 >= 2.5 then
|
||||
@@ -505,6 +508,7 @@ end
|
||||
function HealBot_OnEvent_PartyMembersChanged(this)
|
||||
HealBot_Model:PreserveStateByGUID()
|
||||
HealBot_Integrations_PruneNampower()
|
||||
if HealBot_UpdateUnitIDCache then HealBot_UpdateUnitIDCache() end
|
||||
if HealBot_IsFighting then
|
||||
HealBot_Action_PartyChanged()
|
||||
end
|
||||
@@ -564,12 +568,14 @@ end
|
||||
function HealBot_OnEvent_SpellsChanged(this, arg1)
|
||||
if arg1 then return; end
|
||||
HealBot_AddDebug("HB: SpellsChanged");
|
||||
if HealBot_CacheSpellIDs then HealBot_CacheSpellIDs() end
|
||||
HealBot_SpellsInitFlag = 2;
|
||||
end
|
||||
|
||||
-- HealBot_OnEvent_TalentsChanged: Internal utility: HealBot_OnEvent_TalentsChanged
|
||||
function HealBot_OnEvent_TalentsChanged(this, arg1)
|
||||
HealBot_AddDebug("HB: TalentsChanged");
|
||||
if HealBot_UpdateTalentRanks then HealBot_UpdateTalentRanks() end
|
||||
end
|
||||
|
||||
-- HealBot_OnEvent_PlayerEnteringWorld: Internal utility: HealBot_OnEvent_PlayerEnteringWorld
|
||||
@@ -579,6 +585,7 @@ function HealBot_OnEvent_PlayerEnteringWorld(this)
|
||||
if HealBot_ApplyRefreshHook then
|
||||
HealBot_ApplyRefreshHook()
|
||||
end
|
||||
if HealBot_UpdateUnitIDCache then HealBot_UpdateUnitIDCache() end
|
||||
end
|
||||
|
||||
-- HealBot_OnEvent_SpellcastStart: Internal utility: HealBot_OnEvent_SpellcastStart
|
||||
|
||||
@@ -8,12 +8,31 @@ function HealBot_ResetRangeScale()
|
||||
_scale = 0
|
||||
end
|
||||
|
||||
local _rangeCache = {}
|
||||
local _lastFrameTime = 0
|
||||
|
||||
-- HealBot_Range_Check: Checks if unit is in range via map distance or API.
|
||||
function HealBot_Range_Check(unit, range)
|
||||
local currentTime = GetTime()
|
||||
if _lastFrameTime ~= currentTime then
|
||||
for r, cacheTable in pairs(_rangeCache) do
|
||||
for u in pairs(cacheTable) do
|
||||
cacheTable[u] = nil
|
||||
end
|
||||
end
|
||||
_lastFrameTime = currentTime
|
||||
end
|
||||
|
||||
local return_val = 0;
|
||||
if not range then
|
||||
range = 40;
|
||||
end
|
||||
|
||||
_rangeCache[range] = _rangeCache[range] or {}
|
||||
if _rangeCache[range][unit] ~= nil then
|
||||
return _rangeCache[range][unit]
|
||||
end
|
||||
|
||||
if ( unit == "player" ) then
|
||||
return_val = 1;
|
||||
elseif HealBot_Integrations_ClassicAPI_Active and UnitDistanceSquared and UnitInLineOfSight then
|
||||
@@ -56,5 +75,7 @@ function HealBot_Range_Check(unit, range)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
_rangeCache[range][unit] = return_val
|
||||
return return_val;
|
||||
end
|
||||
|
||||
@@ -34,28 +34,27 @@ function HealBot_GetSpellName(id)
|
||||
return spellName .. " (" .. subSpellName .. ")";
|
||||
end
|
||||
|
||||
HealBot_SpellNameToId = {}
|
||||
|
||||
function HealBot_CacheSpellIDs()
|
||||
HealBot_SpellNameToId = {}
|
||||
local id = 1
|
||||
while true do
|
||||
local spellName, subSpellName = GetSpellName(id, BOOKTYPE_SPELL)
|
||||
if not spellName then break end
|
||||
if subSpellName and subSpellName ~= "" then
|
||||
HealBot_SpellNameToId[spellName .. " (" .. subSpellName .. ")"] = id
|
||||
HealBot_SpellNameToId[spellName .. "(" .. subSpellName .. ")"] = id
|
||||
end
|
||||
HealBot_SpellNameToId[spellName] = id
|
||||
id = id + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- HealBot_GetSpellId: Internal utility: HealBot_GetSpellId
|
||||
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
|
||||
if not spell then return nil end
|
||||
return HealBot_SpellNameToId[spell]
|
||||
end
|
||||
|
||||
-- HealBot_CastSpellByName: Internal utility: HealBot_CastSpellByName
|
||||
@@ -212,18 +211,6 @@ end
|
||||
-- HealBot_StartCasting: Initiates spell cast and broadcasts incoming heal.
|
||||
function HealBot_StartCasting(spell, target, ttype)
|
||||
HealBot_CastFailed = false;
|
||||
|
||||
-- Extract base spell for internal tracking
|
||||
local baseSpell = spell
|
||||
local parenIndex = string.find(spell, " %(")
|
||||
if parenIndex then
|
||||
baseSpell = string.sub(spell, 1, parenIndex - 1)
|
||||
else
|
||||
parenIndex = string.find(spell, "%(")
|
||||
if parenIndex then
|
||||
baseSpell = string.sub(spell, 1, parenIndex - 1)
|
||||
end
|
||||
end
|
||||
|
||||
HealBot_CastSpellByName(spell);
|
||||
if ( SpellCanTargetUnit(target) ) then
|
||||
@@ -238,11 +225,11 @@ function HealBot_StartCasting(spell, target, ttype)
|
||||
end
|
||||
end
|
||||
|
||||
if ttype == "fired" and HealBot_Spells[baseSpell] then
|
||||
if ttype == "fired" and HealBot_Spells[spell] then
|
||||
if not HealBot_CastFailed then
|
||||
HealBot_CastingSpell = baseSpell;
|
||||
HealBot_CastingSpell = spell;
|
||||
HealBot_CastingTarget = target;
|
||||
HealBot_Process_HealValue(baseSpell, target);
|
||||
HealBot_Process_HealValue(spell, target);
|
||||
HealBot_AnnounceCast(spell, target);
|
||||
end
|
||||
end
|
||||
@@ -648,7 +635,6 @@ function HealBot_RecalcParty()
|
||||
end
|
||||
end
|
||||
end
|
||||
HealBot_Action_RefreshButtons();
|
||||
end
|
||||
|
||||
-- HealBot_RecalcSpells: Recalculates spells and updates layout.
|
||||
@@ -657,17 +643,24 @@ function HealBot_RecalcSpells()
|
||||
HealBot_RecalcParty();
|
||||
end
|
||||
|
||||
-- HealBot_GetTalentRank: Internal utility: HealBot_GetTalentRank
|
||||
function HealBot_GetTalentRank(talentName)
|
||||
HealBot_TalentRanks = {}
|
||||
|
||||
function HealBot_UpdateTalentRanks()
|
||||
HealBot_TalentRanks = {}
|
||||
for t = 1, GetNumTalentTabs() do
|
||||
for i = 1, GetNumTalents(t) do
|
||||
local nameTalent, icon, tier, column, currRank, maxRank = GetTalentInfo(t, i);
|
||||
if nameTalent == talentName then
|
||||
return currRank;
|
||||
local nameTalent, icon, tier, column, currRank, maxRank = GetTalentInfo(t, i)
|
||||
if nameTalent then
|
||||
HealBot_TalentRanks[nameTalent] = currRank
|
||||
end
|
||||
end
|
||||
end
|
||||
return 0;
|
||||
end
|
||||
|
||||
-- HealBot_GetTalentRank: Internal utility: HealBot_GetTalentRank
|
||||
function HealBot_GetTalentRank(talentName)
|
||||
if not next(HealBot_TalentRanks) then HealBot_UpdateTalentRanks() end
|
||||
return HealBot_TalentRanks[talentName] or 0
|
||||
end
|
||||
|
||||
-- HealBot_SpiBonus: Internal utility: HealBot_SpiBonus
|
||||
@@ -702,6 +695,7 @@ end
|
||||
|
||||
-- HealBot_InitSpells: Scans spellbook to find available heals.
|
||||
function HealBot_InitSpells()
|
||||
HealBot_CacheSpellIDs()
|
||||
local id = 1
|
||||
local cnt = 0;
|
||||
local class = HealBot_UnitClass("player")
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
HealBot_ConfigDefaults = {
|
||||
DebugMode = 0,
|
||||
ShowManaBars=0,
|
||||
ManaBarsHealersOnly=0,
|
||||
Version = HEALBOT_VERSION,
|
||||
@@ -260,6 +261,7 @@ HealBot_ConfigDefaults = {
|
||||
HealBot_Integrations_Nampower = 0,
|
||||
HealBot_Integrations_SuperWoW = 0,
|
||||
HealBot_Integrations_ClassicAPI = 0,
|
||||
HealBot_Integrations_ShowHoTTimers = 0,
|
||||
};
|
||||
|
||||
HealBot_Config = {};
|
||||
|
||||
@@ -10,6 +10,8 @@ function HealBot_GetUnitGUID(unit)
|
||||
return UnitGUID(unit)
|
||||
elseif HealBot_Integrations_SuperWoW_Active and GetUnitGUID then
|
||||
return GetUnitGUID(unit)
|
||||
elseif HealBot_Integrations_Nampower_Active and GetUnitGUID then
|
||||
return GetUnitGUID(unit)
|
||||
end
|
||||
return nil
|
||||
end
|
||||
@@ -40,6 +42,11 @@ function HealBot_Integrations_Toggle()
|
||||
local spellID, caster, target, _, _, _, _, duration = arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8
|
||||
if not caster or not target or duration <= 0 then return end
|
||||
|
||||
-- The player is ALWAYS the caster in these events for Nampower
|
||||
if not HealBot_PlayerGUID then
|
||||
HealBot_PlayerGUID = caster
|
||||
end
|
||||
|
||||
local spellName = GetSpellRecField(spellID, "name")
|
||||
if not spellName then return end
|
||||
|
||||
@@ -76,7 +83,7 @@ function HealBot_Integrations_PruneNampower()
|
||||
local currentTime = GetTime()
|
||||
for targetName, auras in pairs(HealBot_Nampower_Auras) do
|
||||
-- Check if target is still in the raid/party
|
||||
if not HealBot_Model:GetUnitIDByName(targetName) then
|
||||
if not HealBot_Model:GetUnitByGUID(targetName) and not HealBot_Model:GetUnitIDByName(targetName) then
|
||||
HealBot_ReleaseTable(auras)
|
||||
HealBot_Nampower_Auras[targetName] = nil
|
||||
else
|
||||
@@ -127,4 +134,16 @@ end
|
||||
HealBot_Integrations_ClassicAPI_Active = false;
|
||||
HealBot_AddDebug("ClassicAPI Integration: DISABLED");
|
||||
end
|
||||
|
||||
if HealBot_Options_Integrations_ShowHoTTimers then
|
||||
if HealBot_Integrations_Nampower_Active or HealBot_Integrations_SuperWoW_Active or HealBot_Integrations_ClassicAPI_Active then
|
||||
HealBot_Options_Integrations_ShowHoTTimers:Enable()
|
||||
getglobal(HealBot_Options_Integrations_ShowHoTTimers:GetName().."Text"):SetTextColor(1, 1, 1)
|
||||
else
|
||||
HealBot_Options_Integrations_ShowHoTTimers:Disable()
|
||||
getglobal(HealBot_Options_Integrations_ShowHoTTimers:GetName().."Text"):SetTextColor(0.5, 0.5, 0.5)
|
||||
HealBot_Options_Integrations_ShowHoTTimers:SetChecked(0)
|
||||
HealBot_Config.HealBot_Integrations_ShowHoTTimers = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -18,7 +18,7 @@ if (GetLocale() == "frFR") then
|
||||
|
||||
HEALBOT_DRUID = "Druide";
|
||||
HEALBOT_HUNTER = "Chasseur";
|
||||
HEALBOT_MAGE = "Magier";
|
||||
HEALBOT_MAGE = "Mage";
|
||||
HEALBOT_PALADIN = "Paladin";
|
||||
HEALBOT_PRIEST = "Pr\195\170tre";
|
||||
HEALBOT_ROGUE = "Voleur";
|
||||
|
||||
+2
-2
@@ -156,7 +156,7 @@ function HealBot_Model:UpdateUnitIdentity(unit)
|
||||
self.units[unit].englishClass = englishClass
|
||||
self.units[unit].class = UnitClass(unit)
|
||||
|
||||
if (HealBot_Integrations_SuperWoW_Active or HealBot_Integrations_ClassicAPI_Active) and HealBot_GetUnitGUID then
|
||||
if (HealBot_Integrations_SuperWoW_Active or HealBot_Integrations_ClassicAPI_Active or HealBot_Integrations_Nampower_Active) and HealBot_GetUnitGUID then
|
||||
local guid = HealBot_GetUnitGUID(unit)
|
||||
if guid and guid ~= "0" and guid ~= "0x0000000000000000" then
|
||||
self.unitGUIDs[unit] = guid
|
||||
@@ -185,7 +185,7 @@ end
|
||||
|
||||
-- HealBot_Model:PreserveStateByGUID: Preserves icon and debuff state when group indices shift during combat.
|
||||
function HealBot_Model:PreserveStateByGUID()
|
||||
if not (HealBot_Integrations_SuperWoW_Active or HealBot_Integrations_ClassicAPI_Active) or not HealBot_GetUnitGUID then return end
|
||||
if not (HealBot_Integrations_SuperWoW_Active or HealBot_Integrations_ClassicAPI_Active or HealBot_Integrations_Nampower_Active) or not HealBot_GetUnitGUID then return end
|
||||
|
||||
for k in pairs(pool_oldGUIDs) do pool_oldGUIDs[k] = nil end
|
||||
local oldGUIDs = pool_oldGUIDs
|
||||
|
||||
@@ -4,4 +4,5 @@ function HealBot_Options_Integrations_OnShow(this)
|
||||
HealBot_Options_Integrations_Nampower:SetChecked(HealBot_Config.HealBot_Integrations_Nampower);
|
||||
HealBot_Options_Integrations_SuperWoW:SetChecked(HealBot_Config.HealBot_Integrations_SuperWoW);
|
||||
HealBot_Options_Integrations_ClassicAPI:SetChecked(HealBot_Config.HealBot_Integrations_ClassicAPI);
|
||||
HealBot_Options_Integrations_ShowHoTTimers:SetChecked(HealBot_Config.HealBot_Integrations_ShowHoTTimers);
|
||||
end
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="HealBot_Options_Integrations_SuperWoW" relativePoint="BOTTOMLEFT">
|
||||
<Offset>
|
||||
<AbsDimension x="0" y="5"/>
|
||||
<AbsDimension x="0" y="-5"/>
|
||||
</Offset>
|
||||
</Anchor>
|
||||
</Anchors>
|
||||
@@ -80,6 +80,24 @@
|
||||
</Scripts>
|
||||
</CheckButton>
|
||||
|
||||
<CheckButton name="HealBot_Options_Integrations_ShowHoTTimers" inherits="OptionsCheckButtonTemplate">
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="HealBot_Options_Integrations_ClassicAPI" relativePoint="BOTTOMLEFT">
|
||||
<Offset>
|
||||
<AbsDimension x="0" y="-5"/>
|
||||
</Offset>
|
||||
</Anchor>
|
||||
</Anchors>
|
||||
<Scripts>
|
||||
<OnLoad>
|
||||
getglobal(this:GetName().."Text"):SetText("Track Player HoT Timers");
|
||||
</OnLoad>
|
||||
<OnClick>
|
||||
HealBot_Config.HealBot_Integrations_ShowHoTTimers = this:GetChecked() and 1 or 0;
|
||||
</OnClick>
|
||||
</Scripts>
|
||||
</CheckButton>
|
||||
|
||||
</Frames>
|
||||
<Layers>
|
||||
<Layer level="ARTWORK">
|
||||
@@ -94,6 +112,17 @@
|
||||
</Anchors>
|
||||
<Color r="0.7" g="0.7" b="0.7"/>
|
||||
</FontString>
|
||||
<FontString name="HealBot_Options_Integrations_HoTInfo" inherits="GameFontHighlightSmall" justifyH="LEFT" justifyV="TOP" text="Note: HoT Timers require Nampower, SuperWoW, or ClassicAPI to be enabled and active to provide accurate aura times.">
|
||||
<Size x="330" y="30"/>
|
||||
<Anchors>
|
||||
<Anchor point="TOPLEFT" relativeTo="HealBot_Options_Integrations_ShowHoTTimers" relativePoint="BOTTOMLEFT">
|
||||
<Offset>
|
||||
<AbsDimension x="34" y="-2"/>
|
||||
</Offset>
|
||||
</Anchor>
|
||||
</Anchors>
|
||||
<Color r="0.7" g="0.7" b="0.7"/>
|
||||
</FontString>
|
||||
</Layer>
|
||||
</Layers>
|
||||
<Scripts>
|
||||
|
||||
+177
-10
@@ -246,23 +246,38 @@ function HealBot_Action_EnableButton(button)
|
||||
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, "")
|
||||
local expectedFlags = fontOutline == 1 and "OUTLINE" or ""
|
||||
if fontFlags ~= expectedFlags then
|
||||
bar.txt:SetFont(fontName, fontHeight, expectedFlags)
|
||||
end
|
||||
|
||||
local iconSize = HealBot_Config.biconsize[HealBot_Config.Current_Skin] or 12
|
||||
for i = 1, 10 do
|
||||
local icon = getglobal(button:GetName() .. "BarIcon" .. i)
|
||||
local icon = button["icon"..i]
|
||||
if not icon then
|
||||
icon = getglobal(button:GetName() .. "BarIcon" .. i)
|
||||
button["icon"..i] = icon
|
||||
end
|
||||
if icon then
|
||||
if HealBot_UnitIcons and HealBot_UnitIcons[unit] and HealBot_UnitIcons[unit][i] then
|
||||
icon:SetTexture(HealBot_UnitIcons[unit][i])
|
||||
icon:SetWidth(iconSize)
|
||||
icon:SetHeight(iconSize)
|
||||
icon:Show()
|
||||
local currentTexture = icon:GetTexture()
|
||||
local newTexture = HealBot_UnitIcons[unit][i]
|
||||
if currentTexture ~= newTexture then
|
||||
icon:SetTexture(newTexture)
|
||||
end
|
||||
|
||||
if icon:GetWidth() ~= iconSize then
|
||||
icon:SetWidth(iconSize)
|
||||
icon:SetHeight(iconSize)
|
||||
end
|
||||
|
||||
if not icon:IsVisible() then
|
||||
icon:Show()
|
||||
end
|
||||
else
|
||||
icon:Hide()
|
||||
if icon:IsVisible() then
|
||||
icon:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1224,3 +1239,155 @@ function HealBot_Action_AppendNewUnits()
|
||||
end
|
||||
HealBot_ReleaseTable(unitsToCheck)
|
||||
end
|
||||
|
||||
local HealBot_PlayerHoTsListFrame = nil
|
||||
local HealBot_PlayerHoTFrames = {}
|
||||
|
||||
local HealBot_PlayerHoTs_ValidHoTs = {
|
||||
["Renew"] = "Interface\\Icons\\Spell_Holy_Renew",
|
||||
["Rejuvenation"] = "Interface\\Icons\\Spell_Nature_Rejuvenation",
|
||||
["Regrowth"] = "Interface\\Icons\\Spell_Nature_ResistNature",
|
||||
["Power Word: Shield"] = "Interface\\Icons\\Spell_Holy_PowerWordShield",
|
||||
}
|
||||
|
||||
local HealBot_PlayerHoTs_ListCache = {}
|
||||
|
||||
function HealBot_Action_UpdatePlayerHoTs()
|
||||
if not HealBot_PlayerHoTsListFrame then
|
||||
HealBot_PlayerHoTsListFrame = CreateFrame("Frame", "HealBot_PlayerHoTsListFrame", HealBot_Action)
|
||||
HealBot_PlayerHoTsListFrame:SetWidth(128)
|
||||
HealBot_PlayerHoTsListFrame:SetHeight(1)
|
||||
HealBot_PlayerHoTsListFrame:SetPoint("TOPLEFT", HealBot_Action, "BOTTOMLEFT", 0, -2)
|
||||
HealBot_PlayerHoTsListFrame:Show()
|
||||
end
|
||||
|
||||
if HealBot_Config.HealBot_Integrations_ShowHoTTimers ~= 1 then
|
||||
HealBot_PlayerHoTsListFrame:Hide()
|
||||
return
|
||||
else
|
||||
HealBot_PlayerHoTsListFrame:Show()
|
||||
end
|
||||
|
||||
local currentTime = GetTime()
|
||||
|
||||
-- Clear cache instead of reallocating
|
||||
local numHoTs = 0
|
||||
|
||||
if HealBot_Integrations_Nampower_Active and HealBot_Nampower_Auras then
|
||||
for targetName, auras in pairs(HealBot_Nampower_Auras) do
|
||||
for spellName, expiration in pairs(auras) do
|
||||
if HealBot_PlayerHoTs_ValidHoTs[spellName] then
|
||||
if expiration > currentTime then
|
||||
numHoTs = numHoTs + 1
|
||||
if not HealBot_PlayerHoTs_ListCache[numHoTs] then
|
||||
HealBot_PlayerHoTs_ListCache[numHoTs] = {}
|
||||
end
|
||||
HealBot_PlayerHoTs_ListCache[numHoTs].name = targetName
|
||||
HealBot_PlayerHoTs_ListCache[numHoTs].spell = spellName
|
||||
HealBot_PlayerHoTs_ListCache[numHoTs].expires = expiration
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Blank out remaining cache entries so sort doesn't read them
|
||||
for i = numHoTs + 1, table.getn(HealBot_PlayerHoTs_ListCache) do
|
||||
HealBot_PlayerHoTs_ListCache[i].expires = 9999999999
|
||||
end
|
||||
|
||||
-- Sort only the active portion by shifting expired ones to the end
|
||||
table.sort(HealBot_PlayerHoTs_ListCache, function(a, b)
|
||||
return (a.expires or 0) < (b.expires or 0)
|
||||
end)
|
||||
|
||||
for i = 1, math.max(numHoTs, table.getn(HealBot_PlayerHoTFrames)) do
|
||||
local frame = HealBot_PlayerHoTFrames[i]
|
||||
if i <= numHoTs then
|
||||
if not frame then
|
||||
frame = CreateFrame("Frame", "HealBot_PlayerHoT" .. i, HealBot_PlayerHoTsListFrame)
|
||||
frame:SetWidth(128)
|
||||
frame:SetHeight(16)
|
||||
if i == 1 then
|
||||
frame:SetPoint("TOPLEFT", HealBot_PlayerHoTsListFrame, "TOPLEFT", 0, 0)
|
||||
else
|
||||
frame:SetPoint("TOPLEFT", HealBot_PlayerHoTFrames[i-1], "BOTTOMLEFT", 0, -2)
|
||||
end
|
||||
|
||||
local icon = frame:CreateTexture(nil, "ARTWORK")
|
||||
icon:SetWidth(14)
|
||||
icon:SetHeight(14)
|
||||
icon:SetPoint("LEFT", frame, "LEFT", 2, 0)
|
||||
frame.icon = icon
|
||||
|
||||
local text = frame:CreateFontString(nil, "OVERLAY", "GameFontNormalSmall")
|
||||
text:SetPoint("LEFT", icon, "RIGHT", 4, 0)
|
||||
text:SetJustifyH("LEFT")
|
||||
frame.text = text
|
||||
|
||||
HealBot_PlayerHoTFrames[i] = frame
|
||||
end
|
||||
|
||||
local hot = HealBot_PlayerHoTs_ListCache[i]
|
||||
local timeLeft = math.floor(hot.expires - currentTime)
|
||||
|
||||
-- Resolve GUID to Name
|
||||
if not HealBot_Nampower_NameCache then HealBot_Nampower_NameCache = HealBot_GetTable() end
|
||||
|
||||
local dispName = HealBot_Nampower_NameCache[hot.name]
|
||||
|
||||
if not dispName then
|
||||
dispName = hot.name
|
||||
local resolved = false
|
||||
|
||||
local unitID = HealBot_Model:GetUnitByGUID(hot.name) or HealBot_Model:GetUnitIDByName(hot.name)
|
||||
if unitID then
|
||||
local n = UnitName(unitID)
|
||||
if n then
|
||||
dispName = n
|
||||
resolved = true
|
||||
end
|
||||
elseif string.sub(hot.name, 1, 2) == "0x" or string.sub(hot.name, 1, 2) == "0X" then
|
||||
if HealBot_PlayerGUID and string.lower(HealBot_PlayerGUID) == string.lower(hot.name) then
|
||||
dispName = UnitName("player") or "Player"
|
||||
resolved = true
|
||||
elseif HealBot_GetUnitGUID then
|
||||
if string.lower(HealBot_GetUnitGUID("player") or "") == string.lower(hot.name) then
|
||||
dispName = UnitName("player") or "Player"
|
||||
resolved = true
|
||||
elseif string.lower(HealBot_GetUnitGUID("target") or "") == string.lower(hot.name) then
|
||||
dispName = UnitName("target") or "Target"
|
||||
resolved = true
|
||||
elseif string.lower(HealBot_GetUnitGUID("mouseover") or "") == string.lower(hot.name) then
|
||||
dispName = UnitName("mouseover") or "Mouseover"
|
||||
resolved = true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if resolved then
|
||||
HealBot_Nampower_NameCache[hot.name] = dispName
|
||||
elseif string.sub(hot.name, 1, 2) == "0x" then
|
||||
dispName = "Unknown"
|
||||
end
|
||||
end
|
||||
|
||||
local spellId = HealBot_GetSpellId and HealBot_GetSpellId(hot.spell) or nil
|
||||
local tex = HealBot_PlayerHoTs_ValidHoTs[hot.spell] or "Interface\\Icons\\INV_Misc_QuestionMark"
|
||||
if spellId then
|
||||
tex = GetSpellTexture(spellId, "BOOKTYPE_SPELL") or tex
|
||||
end
|
||||
|
||||
frame.icon:SetTexture(tex)
|
||||
frame.text:SetText(dispName .. ": " .. timeLeft .. "s")
|
||||
frame.text:SetTextColor(0.8, 1, 0.8)
|
||||
frame:Show()
|
||||
else
|
||||
if frame then
|
||||
frame:Hide()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
HealBot_PlayerHoTsListFrame:SetHeight(math.max(1, numHoTs * 18))
|
||||
end
|
||||
|
||||
@@ -21,6 +21,7 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\
|
||||
* `/hb` - Toggles the main HealBot panel on and off
|
||||
* `/hb options` - Toggles the HealBot options panel on and off
|
||||
* `/hb reset` - Resets the contents of the main HealBot panel
|
||||
* `/hb debug` - Toggles in-game debug message output to the main chat frame
|
||||
|
||||
### Key Features & Current Functionality
|
||||
* **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.
|
||||
@@ -30,7 +31,7 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\
|
||||
* **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.
|
||||
* **Modifier-Aware Tooltips:** Tooltips dynamically update to show exact bound actions (Shift/Ctrl/Alt) and required mana costs (turns red if insufficient mana).
|
||||
* **Blizzard Party Frame Toggle:** Toggle to automatically hide Blizzard's default party frames when in a group in favor of HealBot's layouts.
|
||||
* **HoT & Buff Tracking:** Intelligently track active HoTs and buffs directly on the grid frames with custom icons (e.g., Renew, Rejuvenation, Regrowth, Fear Ward).
|
||||
* **HoT & Buff Tracking:** Intelligently track active HoTs and buffs directly on the grid frames with custom icons (e.g., Renew, Rejuvenation, Regrowth, Fear Ward). Optional extended HoT timer tracker togglable below frames.
|
||||
* **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.
|
||||
* **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.
|
||||
@@ -49,6 +50,20 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\
|
||||
|
||||
### Change Log
|
||||
|
||||
**v1.7.4**
|
||||
* **Performance Fix - CPU Spikes** - Fixed massive FPS drops during raid combat. The `HealBot_CheckBuffs` function previously forced the client to generate hidden UI tooltips for up to 32 buffs per player on every single `UNIT_AURA` event. Tooltip parsing is now cached per texture, bypassing thousands of redundant API calls per second.
|
||||
* **Performance Fix - Frame Rendering** - Eliminated redundant UI layout recalculations in `HealBot_Action_EnableButton`. The UI no longer forces `SetFont`, `SetWidth`, `SetHeight`, and `GetGlobal` lookups on every single combat tick (which previously caused 4,000+ layout updates per second in 40-man raids).
|
||||
* **Performance Fix - Range Checking** - Greatly reduced CPU stutter caused by range calculations. `HealBot_Range_Check` now caches map positioning math and API calls per-frame, preventing the addon from calculating the exact same `math.sqrt` distance up to 5 times per unit during heavy combat.
|
||||
* **Performance Fix - Unit ID Lookup** - Optimized `HealBot_FindUnitID` by pre-allocating raid unit tokens, preventing massive string concatenation and garbage collection spam during high-frequency combat events like `CHAT_MSG_ADDON` (HealComm).
|
||||
* **Performance Fix - String GC Leak** - Fixed garbage collection hitches caused by `string.gfind` closures in the HealComm parsing loop by rewriting it to use closure-free `string.find` native loops.
|
||||
* **Debug Output Command** - Added `/hb debug` (or `/hb dbg`) slash command to toggle real-time debug message printing directly into the standard chat frame without requiring custom chat channels.
|
||||
* **Performance Fix - Spell Lookup** - Fixed a massive CPU drain and garbage generation issue where the entire spellbook was linearly scanned every frame per unit. Spell IDs are now cached via O(1) dictionary lookup on login and talent/spell changes.
|
||||
* **Performance Fix - Unit Hash Lookup** - Eliminated heavy C-API calls to `UnitName()` during incoming heals by caching raid and party unit tokens in a fast O(1) hash table that updates on roster changes.
|
||||
* **Performance Fix - Range Cache GC Leak** - Fixed a continuous memory leak in the range checker caused by string concatenation (`unit .. "_" .. range`) running every frame. Range states are now stored in a nested numeric table cache.
|
||||
* **Performance Fix - Talent Rank Scan** - Fixed severe CPU stutter when gaining or losing auras that affect stats. Previously, inventory updates forced a full equipment and spell recalculation which linearly scanned the entire talent tree multiple times per rank. Talent ranks are now cached natively.
|
||||
* **Feature - HoT Tracking** - Added an option in the Integrations tab to track Player-cast HoT timers in a dedicated list below the main HealBot frame. Requires Nampower, SuperWoW, or ClassicAPI to fetch exact durations. Added support for tracking Power Word: Shield. Implemented with a pre-allocated static cache array for zero GC leaks, and precise GUID trapping for instant name resolution on self and non-party members.
|
||||
|
||||
|
||||
**v1.7.3**
|
||||
* **Performance Fix - Table Pooling Part 2** - Fixed remaining un-pooled table allocations in layout updates, macro parsing, nampower integration, and aura tracking by utilizing HealBot_GetTable().
|
||||
* **Performance Fix - HealComm Networking** - Fixed issue where incoming `HealComm` messages triggered synchronous UI redraws, causing massive lag in 40-man raids during combat. `HealBot_RecalcHeals` is now decoupled and deferred through the `HealBot_OnUpdate` dirty queue, allowing multiple network events to collapse into a single frame redraw.
|
||||
@@ -144,7 +159,6 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\
|
||||
* **Chat Announcements & Mouseover Casts:** Chat announcements are now correctly fired when using native Hovercasting (Mouseover). Additionally, added safety checks to prevent spamming chat announcements when accidentally clicking on a dead player (unless casting a resurrection spell).
|
||||
* **New Priest Buff (Enlighten):** Added the custom "Enlighten" buff to Priest trackable buffs, complete with the `btnholyscriptures` icon on unit frames.
|
||||
|
||||
|
||||
**1.3.3**
|
||||
* **Chat Panel Refactor:** Completely replaced the spell selection dropdowns in the Chat tab with manual text input boxes, allowing users to type exact spell names (with or without ranks) directly, matching the behavior of the key-bindings configuration. Fixed a string matching bug caused by Vanilla WoW's hidden trailing spaces when comparing spell names, ensuring that both rankless (e.g. `Flash Heal`) and ranked inputs trigger correctly.
|
||||
* **Chat Layout Stack:** Restructured the Chat Options XML layout to correctly stack the inputs into neat rows, preventing horizontal overlap and providing more space for typing long announce messages.
|
||||
|
||||
Reference in New Issue
Block a user