mirror of
https://github.com/Bluewhale1337/HealBotBlue.git
synced 2026-09-11 09:50:21 +00:00
fix: resolve UI rendering crashes, address unit frame aliasing bugs, and implement automatic debuff tracking with lazy-load identity fetches.
This commit is contained in:
@@ -205,6 +205,12 @@ function HealBot_Action_HealUnit_OnClick(this,button)
|
||||
end
|
||||
end
|
||||
|
||||
-- Special cases for targeting
|
||||
if string.lower(pattern) == "target" or string.lower(pattern) == "/target" then
|
||||
TargetUnit(this.unit)
|
||||
return
|
||||
end
|
||||
|
||||
-- Priority 1: Inline Scripts (starts with /)
|
||||
if string.sub(pattern, 1, 1) == "/" then
|
||||
local oldTarget = nil
|
||||
|
||||
+57
-14
@@ -155,10 +155,21 @@ local HealBot_TrackedHoTs = {
|
||||
["Interface\\Icons\\Spell_Holy_AshesToAshes"] = true,
|
||||
}
|
||||
|
||||
local HealBot_DebuffTypeMap = nil
|
||||
|
||||
function HealBot_OnEvent_UnitAura(this, unit)
|
||||
if not HealBot_DebuffTypeMap then
|
||||
HealBot_DebuffTypeMap = {
|
||||
[HEALBOT_DISEASE] = HEALBOT_DISEASE_en,
|
||||
[HEALBOT_MAGIC] = HEALBOT_MAGIC_en,
|
||||
[HEALBOT_POISON] = HEALBOT_POISON_en,
|
||||
[HEALBOT_CURSE] = HEALBOT_CURSE_en
|
||||
}
|
||||
end
|
||||
|
||||
local DebuffType;
|
||||
|
||||
if HealBot_Heals[unit] and unit ~= "target" then
|
||||
if HealBot_Heals[unit] then
|
||||
if not HealBot_UnitIcons[unit] then
|
||||
HealBot_UnitIcons[unit] = {}
|
||||
end
|
||||
@@ -168,17 +179,43 @@ function HealBot_OnEvent_UnitAura(this, unit)
|
||||
local iconCount = 0
|
||||
local i = 1;
|
||||
HealBot_UnitDebuff[unit] = nil;
|
||||
|
||||
while true do
|
||||
local debuff, tmp, debuff_type = UnitDebuff(unit, i, 1)
|
||||
local debuff, tmp, debuff_type = UnitDebuff(unit, i)
|
||||
if debuff then
|
||||
if iconCount < 10 then
|
||||
iconCount = iconCount + 1
|
||||
HealBot_UnitIcons[unit][iconCount] = debuff
|
||||
local mapped_type = nil
|
||||
if debuff_type then
|
||||
mapped_type = HealBot_DebuffTypeMap[debuff_type] or debuff_type
|
||||
end
|
||||
if HealBot_CDCInc[UnitClass(unit)] == 1 and debuff_type and HealBot_DebuffWatch[debuff_type] then
|
||||
HealBot_UnitDebuff[unit] = debuff_type
|
||||
DebuffType = debuff_type;
|
||||
if HealBot_DebuffPriority[debuff_type] then
|
||||
|
||||
local unitClass = HealBot_Model.units[unit] and HealBot_Model.units[unit].class or UnitClass(unit)
|
||||
local shouldTrack = false
|
||||
if unit == "target" then
|
||||
shouldTrack = true
|
||||
elseif HealBot_CDCInc[unitClass] == 1 then
|
||||
shouldTrack = true
|
||||
elseif not unitClass or HealBot_CDCInc[unitClass] == nil then
|
||||
shouldTrack = true
|
||||
end
|
||||
|
||||
if shouldTrack and mapped_type and HealBot_DebuffWatch[mapped_type] then
|
||||
if iconCount < 10 then
|
||||
iconCount = iconCount + 1
|
||||
HealBot_UnitIcons[unit][iconCount] = debuff
|
||||
end
|
||||
HealBot_UnitDebuff[unit] = mapped_type
|
||||
DebuffType = mapped_type;
|
||||
|
||||
local isPriority = false
|
||||
if HealBot_DebuffPriority then
|
||||
for _, pType in ipairs(HealBot_DebuffPriority) do
|
||||
if pType == mapped_type then
|
||||
isPriority = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if isPriority then
|
||||
break
|
||||
end
|
||||
end
|
||||
@@ -213,16 +250,22 @@ function HealBot_OnEvent_UnitAura(this, unit)
|
||||
if HealBot_UnitDebuff[unit] then
|
||||
if DebuffType and HealBot_Range_Check(unit, 27) == 1 then
|
||||
if HealBot_Config.ShowDebuffWarning == 1 then
|
||||
local color = HealBot_Config.CDCBarColour[DebuffType]
|
||||
local r, g, b = 1, 0, 0
|
||||
if color then
|
||||
r, g, b = color.R, color.G, color.B
|
||||
end
|
||||
UIErrorsFrame:AddMessage(UnitName(unit) .. " suffers from " .. DebuffType,
|
||||
HealBot_Config.CDCBarColour[DebuffType].R,
|
||||
HealBot_Config.CDCBarColour[DebuffType].G,
|
||||
HealBot_Config.CDCBarColour[DebuffType].B,
|
||||
r, g, 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);
|
||||
-- Check buffs synchronously because tooltip scanning fails in OnUpdate
|
||||
HealBot_CheckBuffs(unit)
|
||||
|
||||
-- Defer UI updates
|
||||
HealBot_View_DirtyUnits[unit] = true
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
-- Manages WoW Frame events and periodic updates, routing to respective services
|
||||
|
||||
HealBot_View_DirtyUnits = {}
|
||||
HealBot_View_DirtyPower = {}
|
||||
local HealBot_Timer1, HealsIn_Timer = 0, 0;
|
||||
HealBot_LastModState = ""
|
||||
|
||||
@@ -20,7 +21,7 @@ function HealBot_OnLoad(this)
|
||||
HealBot_View_DirtyUnits[unitID] = true
|
||||
end)
|
||||
HealBot_Model:RegisterObserver("UNIT_POWER_CHANGED", function(unitID)
|
||||
HealBot_View_DirtyUnits[unitID] = true
|
||||
HealBot_View_DirtyPower[unitID] = true
|
||||
end)
|
||||
HealBot_Model:RegisterObserver("UNIT_AURA_CHANGED", function(unitID)
|
||||
HealBot_View_DirtyUnits[unitID] = true
|
||||
@@ -74,11 +75,23 @@ function HealBot_OnUpdate(this, arg1)
|
||||
end
|
||||
|
||||
-- Process Dirty Queue for MVC View
|
||||
local unitID, _ = next(HealBot_View_DirtyUnits)
|
||||
while unitID do
|
||||
HealBot_Action_RefreshButtons(unitID)
|
||||
local unitsToRefresh = {}
|
||||
for unitID in pairs(HealBot_View_DirtyUnits) do
|
||||
unitsToRefresh[unitID] = true
|
||||
HealBot_View_DirtyUnits[unitID] = nil
|
||||
unitID, _ = next(HealBot_View_DirtyUnits)
|
||||
HealBot_View_DirtyPower[unitID] = nil -- No need to do power-only if full refresh is queued
|
||||
end
|
||||
for unitID in pairs(unitsToRefresh) do
|
||||
HealBot_Action_Refresh(unitID)
|
||||
end
|
||||
|
||||
local powerToRefresh = {}
|
||||
for unitID in pairs(HealBot_View_DirtyPower) do
|
||||
powerToRefresh[unitID] = true
|
||||
HealBot_View_DirtyPower[unitID] = nil
|
||||
end
|
||||
for unitID in pairs(powerToRefresh) do
|
||||
HealBot_Action_RefreshPower(unitID)
|
||||
end
|
||||
|
||||
if HealBot_EquipChangeTimer > 0 then
|
||||
|
||||
+17
-7
@@ -146,7 +146,7 @@ function HealBot_Model:UpdateUnitIdentity(unit)
|
||||
|
||||
if (HealBot_Integrations_SuperWoW_Active or HealBot_Integrations_ClassicAPI_Active) and HealBot_GetUnitGUID then
|
||||
local guid = HealBot_GetUnitGUID(unit)
|
||||
if guid then
|
||||
if guid and guid ~= "0" and guid ~= "0x0000000000000000" then
|
||||
self.unitGUIDs[unit] = guid
|
||||
self.guidUnits[guid] = unit
|
||||
end
|
||||
@@ -174,14 +174,16 @@ function HealBot_Model:PreserveStateByGUID()
|
||||
|
||||
local oldGUIDs = {}
|
||||
for unit, guid in pairs(self.unitGUIDs) do
|
||||
oldGUIDs[unit] = guid
|
||||
if string.find(unit, "^party") or string.find(unit, "^raid") or unit == "player" or unit == "pet" then
|
||||
oldGUIDs[unit] = guid
|
||||
end
|
||||
end
|
||||
|
||||
local newUnitForGUID = {}
|
||||
-- Scan the new roster
|
||||
for _, unit in ipairs(self.partyMembers) do
|
||||
local guid = HealBot_GetUnitGUID(unit)
|
||||
if guid then
|
||||
if guid and guid ~= "0" and guid ~= "0x0000000000000000" then
|
||||
newUnitForGUID[guid] = unit
|
||||
self.unitGUIDs[unit] = guid
|
||||
self.guidUnits[guid] = unit
|
||||
@@ -189,7 +191,7 @@ function HealBot_Model:PreserveStateByGUID()
|
||||
end
|
||||
for _, unit in ipairs(self.raidMembers) do
|
||||
local guid = HealBot_GetUnitGUID(unit)
|
||||
if guid then
|
||||
if guid and guid ~= "0" and guid ~= "0x0000000000000000" then
|
||||
newUnitForGUID[guid] = unit
|
||||
self.unitGUIDs[unit] = guid
|
||||
self.guidUnits[guid] = unit
|
||||
@@ -220,10 +222,18 @@ function HealBot_Model:PreserveStateByGUID()
|
||||
end
|
||||
|
||||
for targetUnit, stateData in pairs(stateSwaps) do
|
||||
self.units[targetUnit] = stateData
|
||||
-- Deep copy to prevent memory aliasing
|
||||
self.units[targetUnit] = {}
|
||||
for k, v in pairs(stateData) do
|
||||
self.units[targetUnit][k] = v
|
||||
end
|
||||
self.units[targetUnit].icons = {}
|
||||
|
||||
if HealBot_UnitIcons then
|
||||
HealBot_UnitIcons[targetUnit] = iconSwaps[targetUnit]
|
||||
if HealBot_UnitIcons and iconSwaps[targetUnit] then
|
||||
if not HealBot_UnitIcons[targetUnit] then HealBot_UnitIcons[targetUnit] = {} end
|
||||
for j=1, 10 do
|
||||
HealBot_UnitIcons[targetUnit][j] = iconSwaps[targetUnit][j]
|
||||
end
|
||||
end
|
||||
if HealBot_MissingBuffs then
|
||||
HealBot_MissingBuffs[targetUnit] = missingBuffSwaps[targetUnit]
|
||||
|
||||
+6
-16
@@ -244,22 +244,12 @@ function HealBot_Options_CDC_SetCombo(spell, button, class)
|
||||
HealBot_Options_KeyCombo_Change()
|
||||
end
|
||||
function HealBot_Options_Debuff_Reset()
|
||||
local classEN=HealBot_UnitClass("player")
|
||||
if classEN=="PRIEST" or classEN=="DRUID" or classEN=="PALADIN" or classEN=="SHAMAN" then
|
||||
local spell = HealBot_Config.CDCLeftText[UnitClass("player")];
|
||||
HealBot_DebuffWatch = {[HEALBOT_DISEASE_en]=false, [HEALBOT_MAGIC_en]=false, [HEALBOT_POISON_en]=false, [HEALBOT_CURSE_en]=false }
|
||||
if spell ~= "None" then
|
||||
table.foreach(HealBot_Debuff_Types[spell], function (index,debuff)
|
||||
HealBot_DebuffWatch[debuff]=true;
|
||||
end)
|
||||
end
|
||||
spell = HealBot_Config.CDCRightText[UnitClass("player")];
|
||||
if spell ~= "None" then
|
||||
table.foreach(HealBot_Debuff_Types[spell], function (index,debuff)
|
||||
HealBot_DebuffWatch[debuff]=true;
|
||||
end)
|
||||
end
|
||||
end
|
||||
HealBot_DebuffWatch = {
|
||||
[HEALBOT_DISEASE_en] = true,
|
||||
[HEALBOT_MAGIC_en] = true,
|
||||
[HEALBOT_POISON_en] = true,
|
||||
[HEALBOT_CURSE_en] = true
|
||||
}
|
||||
end
|
||||
function HealBot_Colorpick_OnClick(CDCType)
|
||||
HealBot_ColourObjWaiting=CDCType;
|
||||
|
||||
+33
-12
@@ -12,7 +12,6 @@ HealBot_Action_HealGroup = {
|
||||
"party4",
|
||||
};
|
||||
|
||||
HealBot_Action_HealGroup = {};
|
||||
HealBot_Action_HealTarget = {};
|
||||
HealBot_Action_HealFocus = {};
|
||||
HealBot_Action_HealButtons = {};
|
||||
@@ -30,18 +29,21 @@ end
|
||||
function HealBot_HealthColor(unit, hlth, maxhlth)
|
||||
if HealBot_UnitDebuff[unit] then
|
||||
local debuff_type = HealBot_UnitDebuff[unit]
|
||||
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
|
||||
local color = HealBot_Config.CDCBarColour[debuff_type]
|
||||
if color then
|
||||
local dr = color.R
|
||||
local dg = color.G
|
||||
local db = color.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
|
||||
return dr, dg, db, HealBot_Config.Barcola[HealBot_Config.Current_Skin];
|
||||
end
|
||||
|
||||
local text = UnitName(unit);
|
||||
@@ -102,6 +104,10 @@ function HealBot_Action_EnableButton(button)
|
||||
local state = HealBot_Model.units[unit]
|
||||
if not state then return end
|
||||
|
||||
if not state.englishClass then
|
||||
HealBot_Model:UpdateUnitIdentity(unit)
|
||||
end
|
||||
|
||||
local hlth = state.health
|
||||
local maxhlth = state.maxHealth
|
||||
local name = state.name
|
||||
@@ -305,6 +311,21 @@ function HealBot_Action_RefreshButtons(unit)
|
||||
end
|
||||
end
|
||||
|
||||
function HealBot_Action_RefreshPower(unit)
|
||||
if not unit or not HealBot_Action_UnitButtons[unit] then return end
|
||||
local state = HealBot_Model.units[unit]
|
||||
if not state then return end
|
||||
|
||||
for index, button in pairs(HealBot_Action_UnitButtons[unit]) do
|
||||
if not button.bar3 then button.bar3 = getglobal(button:GetName() .. "Bar3") end
|
||||
local bar3 = button.bar3
|
||||
if bar3 and bar3:IsVisible() then
|
||||
bar3:SetMinMaxValues(0, state.maxMana)
|
||||
bar3:SetValue(state.mana)
|
||||
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
|
||||
|
||||
@@ -49,15 +49,14 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\
|
||||
### Change Log
|
||||
|
||||
**v1.7.0**
|
||||
* **Integrations UI** - Added a new 'Extras' tab in the Options menu to easily toggle external mod integrations.
|
||||
* **UnitXP_SP3 Integration** - Added optional support for UnitXP's API to provide ultra-precise 3D range finding and strict Line of Sight (LoS) checks. This completely bypasses the limitations of Vanilla's 2D map coordinate distance checks.
|
||||
* **Nampower Integration** - Implemented background aura tracking to map explicit HoT expiration timestamps directly from nampower. This allows for accurate real-time heal and buff tracking instead of estimating based on cast times.
|
||||
* **SuperWoW Integration** - Added robust GUID-based state tracking leveraging SuperWoW's enhanced API. This tracks players by their unique IDs rather than volatile unit strings.
|
||||
* **ClassicAPI Integration** - Added support for ClassicAPI to natively inject accurate +Healing bonuses, ultra-fast 3D distance checks (`UnitDistanceSquared`), and a dedicated Focus frame for pinning Main Tanks without requiring additional memory-heavy addons.
|
||||
* **External Addon Integrations** - Added a new 'Extras' tab in Options to optionally enable integrations with `UnitXP_SP3` (for ultra-precise 3D range and Line of Sight checks) and `nampower` (for accurate real-time heal/buff tracking).
|
||||
* **UI Layout** - Widened the Options UI and neatly centered elements to accommodate the new integrations tab.
|
||||
* **Bug Fix - Class Colors** - Fixed a bug where class colors failed to apply to new units due to a delayed server response.
|
||||
* **Bug Fix - Combat Updates** - Fixed an issue where new party members joining mid-combat failed to append to the grid without dropping combat.
|
||||
* **Bug Fix - Target Swaps** - Implemented optional SuperWoW GUID-based state preservation to prevent UI tracking bugs when group members are rearranged during combat.
|
||||
* **Bug Fix - Rendering Crash** - Fixed a critical UI issue where unrecognized debuff types would crash the rendering loop, causing unit frames to disappear.
|
||||
* **Bug Fix - Missing Group Frames** - Fixed a layout initialization bug where the group unit array was accidentally cleared, causing the panel to draw 0 bars and shrink to a floating "Options" button.
|
||||
* **Bug Fix - Target State Aliasing** - Fixed a bug in `PreserveStateByGUID` where targeting a party member caused their frame to alias the target's state table in memory. This previously caused party frames to adopt enemy mob names and lose their class colors when changing targets.
|
||||
* **Bug Fix - Group Aliasing** - Fixed a bug where roster updates caused frames to share memory references, causing the UI to display the same player across multiple group slots.
|
||||
* **Bug Fix - Slow Client Init** - Fixed missing class colors after `/reload` by adding lazy-load identity fetches directly into the render pipeline for when `UnitClass` data is delayed by the server.
|
||||
* **Bug Fix - Debuff Tracking** - HealBot now automatically tracks all curable debuffs for the player's class out of the box. Previously, users had to manually assign a cure spell to a click binding to enable CDC debuff tracking.
|
||||
|
||||
**v1.6.3**
|
||||
* **Hotfix string splitter** - added falback for string splitter if the the string is empty or nil.
|
||||
|
||||
Reference in New Issue
Block a user