From 06539046593836348b8bfa5a6d76134b92c28ff9 Mon Sep 17 00:00:00 2001 From: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com> Date: Mon, 9 Nov 2026 21:05:05 +0100 Subject: [PATCH] feat: add test debuff simulation commands and unit handling --- HealBot.lua | 117 +++++++++++++++++++++++++++++++++++ HealBot_Action.lua | 4 +- HealBot_Controller_Aura.lua | 14 +++++ HealBot_Controller_Range.lua | 2 +- HealBot_Model.lua | 6 +- HealBot_View_Layout.lua | 6 +- README.md | 3 + 7 files changed, 144 insertions(+), 8 deletions(-) diff --git a/HealBot.lua b/HealBot.lua index 86524a1..14fb547 100644 --- a/HealBot.lua +++ b/HealBot.lua @@ -50,12 +50,123 @@ function HealBot_StopMoving(frame) end +-- HealBot_SetTestDebuff: Simulates debuff effects for testing animations and overlays. +function HealBot_SetTestDebuff(debuffType) + local iconMap = { + [HEALBOT_POISON_en] = "Interface\\Icons\\Spell_Nature_NullifyPoison", + [HEALBOT_CURSE_en] = "Interface\\Icons\\Spell_Shadow_GatherShadows", + [HEALBOT_DISEASE_en] = "Interface\\Icons\\Spell_Nature_NullifyDisease", + [HEALBOT_MAGIC_en] = "Interface\\Icons\\Spell_Holy_DispelMagic", + }; + + if debuffType then + HealBot_TestDebuff = debuffType; + if HealBot_Config then + HealBot_Config.CDCOverlay = 5; -- Automatically switch to Animated mode + end + if not HealBot_UnitDebuff then HealBot_UnitDebuff = {} end + HealBot_UnitDebuff["player"] = debuffType; + if not HealBot_UnitIcons then HealBot_UnitIcons = {} end + if not HealBot_UnitIcons["player"] then HealBot_UnitIcons["player"] = {} end + HealBot_UnitIcons["player"][1] = iconMap[debuffType]; + + -- If test bars active, apply to dummy units as well + for i = 1, 40 do + local tUnit = "Test" .. i; + if HealBot_Action_UnitButtons and HealBot_Action_UnitButtons[tUnit] then + HealBot_UnitDebuff[tUnit] = debuffType; + if not HealBot_UnitIcons[tUnit] then HealBot_UnitIcons[tUnit] = {} end + HealBot_UnitIcons[tUnit][1] = iconMap[debuffType]; + end + end + + if HealBot_Options_CDCOverlay_Refresh and HealBot_Options and HealBot_Options:IsVisible() then + HealBot_Options_CDCOverlay_Refresh(true); + end + + if DEFAULT_CHAT_FRAME then + DEFAULT_CHAT_FRAME:AddMessage("|cFFFFD100HealBot|r: Simulating |cFF00FF00" .. debuffType .. "|r debuff animation. (Type |cFFFFFF00/hb test clear|r to stop)"); + end + else + HealBot_TestDebuff = nil; + if HealBot_UnitDebuff then + HealBot_UnitDebuff["player"] = nil; + end + if HealBot_UnitIcons and HealBot_UnitIcons["player"] then + HealBot_UnitIcons["player"][1] = nil; + end + for i = 1, 40 do + local tUnit = "Test" .. i; + if HealBot_UnitDebuff then HealBot_UnitDebuff[tUnit] = nil end + if HealBot_UnitIcons and HealBot_UnitIcons[tUnit] then + HealBot_UnitIcons[tUnit][1] = nil; + end + end + + if DEFAULT_CHAT_FRAME then + DEFAULT_CHAT_FRAME:AddMessage("|cFFFFD100HealBot|r: Test debuff cleared."); + end + end + + HealBot_Action_RefreshButtons(); +end + -- HealBot_SlashCmd: Handles '/hb' or '/healbot' chat commands. function HealBot_SlashCmd(cmd) if (cmd=="") then HealBot_TogglePanel(HealBot_Action); return end + + local lowCmd = string.lower(cmd or ""); + local sub1, sub2 = nil, nil; + for word in string.gfind(lowCmd, "%S+") do + if not sub1 then + sub1 = word; + elseif not sub2 then + sub2 = word; + break; + end + end + + if (sub1 == "test" or sub1 == "debuff" or sub1 == "anim") then + local typeMap = { + ["poison"] = HEALBOT_POISON_en, + ["p"] = HEALBOT_POISON_en, + ["curse"] = HEALBOT_CURSE_en, + ["c"] = HEALBOT_CURSE_en, + ["disease"] = HEALBOT_DISEASE_en, + ["d"] = HEALBOT_DISEASE_en, + ["magic"] = HEALBOT_MAGIC_en, + ["m"] = HEALBOT_MAGIC_en, + ["clear"] = "clear", + ["off"] = "clear", + ["stop"] = "clear", + ["none"] = "clear", + }; + local chosen = sub2 and typeMap[sub2]; + if chosen == "clear" then + HealBot_SetTestDebuff(nil); + elseif chosen then + HealBot_SetTestDebuff(chosen); + else + if DEFAULT_CHAT_FRAME then + DEFAULT_CHAT_FRAME:AddMessage("|cFFFFD100HealBot|r: Usage: /hb test "); + end + end + return; + end + + if (sub1 == "poison" or sub1 == "curse" or sub1 == "disease" or sub1 == "magic") then + local quickMap = { + ["poison"] = HEALBOT_POISON_en, + ["curse"] = HEALBOT_CURSE_en, + ["disease"] = HEALBOT_DISEASE_en, + ["magic"] = HEALBOT_MAGIC_en, + }; + HealBot_SetTestDebuff(quickMap[sub1]); + return; + end if (cmd=="options" or cmd=="opt" or cmd=="config" or cmd=="cfg") then HealBot_TogglePanel(HealBot_Options); return @@ -231,6 +342,12 @@ end -- HealBot_UnitClass: Returns English class string for a unit. function HealBot_UnitClass(unit) if not unit then return nil end + if string.find(unit, "^Test") then + if HealBot_Model and HealBot_Model.units[unit] then + return HealBot_Model.units[unit].englishClass + end + return nil + end if not HealBot_ClassMap then HealBot_InitClassMap() end -- 1. If player self, query "player" directly diff --git a/HealBot_Action.lua b/HealBot_Action.lua index 00cb419..c278632 100644 --- a/HealBot_Action.lua +++ b/HealBot_Action.lua @@ -20,12 +20,13 @@ end -- HealBot_ShouldHeal: Checks if unit needs immediate healing. function HealBot_ShouldHeal(unit) + if not unit then return false end + if string.find(unit, "^Test") then return true end if HealBot_UnitDebuff[unit] and not UnitIsDeadOrGhost(unit) then if HealBot_Range_Check(unit, 30)==1 then return true; end end - if string.find(unit, "^Test") then return true end return HealBot_MayHeal(unit) and UnitHealth(unit)>0 and not UnitIsDeadOrGhost(unit) and (UnitHealth(unit) 1 and overlayMode < 6 then @@ -804,7 +804,7 @@ function HealBot_Action_PartyChanged() local cHealth = math.random(1, mHealth) local pt = 0 if rClass == "WARRIOR" then pt = 1 elseif rClass == "ROGUE" then pt = 3 end - HealBot_Model.units[unit] = { name = rName, guid = "TestGuid"..j, class = rClass, englishClass = rClass, health = cHealth, maxHealth = mHealth, mana = 2000, maxMana = 4000, powerType = pt, incomingHeal = 0, hasAggro = false, range = 1 } + HealBot_Model.units[unit] = { name = rName, guid = "TestGuid"..j, class = rClass, englishClass = rClass, health = cHealth, maxHealth = mHealth, mana = 2000, maxMana = 4000, powerType = pt, incomingHeal = 0, hasAggro = false, range = 1, isDead = false, isGhost = false, isConnected = true } if not HealBot_UnitIcons then HealBot_UnitIcons = {} end HealBot_UnitIcons[unit] = {} local testIcons = { @@ -1821,7 +1821,7 @@ function HealBot_UpdateActiveHoTTimers() -- If player in raid, map under raid token button as well if unitID == "player" and HealBot_Action_UnitButtons then for btnUnit in pairs(HealBot_Action_UnitButtons) do - if btnUnit ~= "player" and UnitIsUnit(btnUnit, "player") then + if btnUnit ~= "player" and not string.find(btnUnit, "^Test") and UnitIsUnit(btnUnit, "player") then if not HealBot_ActiveHoTUnitMap[btnUnit] then HealBot_ActiveHoTUnitMap[btnUnit] = {} end diff --git a/README.md b/README.md index 0b29efe..4a683ca 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\ * `/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 +* `/hb test ` - Simulates a debuff effect on player and test bars to preview visual animation overlays without needing live debuffs (alias: `/hb debuff `) ### 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. @@ -52,12 +53,14 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\ ### Change Log **v1.7.Unreleased** +* **Bug Fix - Test Bars Crash & White Texture Glitch:** Resolved `Unknown unit name: Test1` and `Unknown unit name: Test25` crashes occurring on test bar activation and hover. Fixed non-unit tokens being passed into Vanilla API functions (`UnitIsDeadOrGhost`, `UnitIsUnit`, `UnitClass`) by evaluating `string.find(unit, "^Test")` before native API calls. Initialized default status flags (`isDead`, `isGhost`, `isConnected`) in dummy model entries, allowing test bars to fully style, texture, and color without halting UI layout. * **Bug Fix - Line of Sight & Target Range Resolution:** Resolved Line of Sight regression where the target bar failed to update or dim when obstructed. Fixed `UnitInLineOfSight` parameter mismatch with ClassicAPI (1-arg signature required), added multi-tier fallback chaining to `UnitXP`, and enforced `CheckInteractDistance` on `target` units during Vanilla map coordinate fallbacks. Added range validation to non-healer class bar evaluation. * **Bug Fix - Out-of-Range Bar Glow on Modifier Press:** Decoupled unit bar enable/range evaluation from physical modifier keys (`IsShiftKeyDown()`, etc.) in `HealBot_CanHeal`, preventing out-of-range and obstructed units from falsely brightening to full alpha when holding Shift/Ctrl/Alt. Enforced range checking across all action patterns (`"Target"`, macros, items, scripts) in `HealBot_GetHealSpell`, and fixed table key case sensitivity on spell range extraction (`Range` vs `range`). * **Feature - HoT Timer Display Modes & Positioning:** Added configurable HoT timer list position dropdown (`Below`, `Above`, `Left`, `Right`) relative to raid frames. Added `Icon Overlay` mode rendering countdown timers directly on health bar HoT icons, and a `Both` mode allowing simultaneous timer list and on-bar icon countdown numbers. Excluded pets from HoT timer lists and overlays. Optimized expiration lookups with O(1) texture-to-spell mappings. * **Refactor & Feature - Unified Aura & HoT Tracking:** Unified bar icons and HoT timers into a master dictionary (`HealBot_TrackedAuras`) in `HealBot_Data.lua`. Added Weakened Soul, Fear Ward, Abolish Disease, and Abolish Poison to active timer bars with localized client support and debuff-aware pruning. * **Bug Fix - HoT Tracking Premature Deletion & GUID Resolution:** Resolved issue where synchronous aura scans on spell cast prematurely purged active HoTs before server buff packets arrived. Fixed HoT timer list showing raw GUID strings instead of names by ensuring GUID caches populate immediately on `PLAYER_ENTERING_WORLD` (even when solo) and adding multi-tier name resolution fallbacks. Fixed unit bar icon countdown numbers not rendering by adding explicit overlay frame show triggers and normalized texture lookup fallbacks. * **Feature - Debuff Visual Overlays & Animated Sprite Sheets:** Added selectable visual styles for Cure / Dispel / Cleanse (CDC) debuff alerts in Options -> Cure (`Whole Bar`, `Frame / Border`, `Glow Overlay`, `Glow + Frame`, `Animated`, `Disabled`). Animated flipbook textures for Poison (dripping slime teardrops), Curse (rising shadow wisps), Disease (creeping roots), and Magic(arcane sigils turning). Integrated lightweight, throttled (15 FPS) UV sprite animation engine directly into `HealBot_OnUpdate` with zero garbage allocation. +* **Feature - Debuff Animation Test Slash Commands:** Added `/hb test ` (and `/hb debuff `) commands to simulate active debuff animations on player and dummy test bars out-of-combat. Automatically activates Animated mode and dummy debuff icons, while guarding state against aura event overwrite until stopped. **v1.7.7**