From c50bcd54f3f99b2f53c6e2278bcd1d4ce8ae5644 Mon Sep 17 00:00:00 2001 From: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com> Date: Mon, 6 Jul 2026 22:15:41 +0200 Subject: [PATCH 1/3] Hotfix - prevent legacy UIDropDownMenu crashes by patching refresh and selection functions --- HealBotBlue.toc | 2 +- HealBot_Localization.en.lua | 2 +- HealBot_Model.lua | 104 ++++++++++++++++++++++++++++++++++++ README.md | 3 ++ 4 files changed, 109 insertions(+), 2 deletions(-) diff --git a/HealBotBlue.toc b/HealBotBlue.toc index eafa611..94b7783 100644 --- a/HealBotBlue.toc +++ b/HealBotBlue.toc @@ -1,6 +1,6 @@ ## Interface: 11200 ## Title: HealBotBlue -## Version: 1.3.1 +## Version: 1.3.2 ## Author: Bluewhale ## Notes: Adds panel with skinable bars for healing and decursive ## SavedVariables: HealBot_Config diff --git a/HealBot_Localization.en.lua b/HealBot_Localization.en.lua index 6d81d92..53f8071 100644 --- a/HealBot_Localization.en.lua +++ b/HealBot_Localization.en.lua @@ -1,4 +1,4 @@ -HEALBOT_VERSION = "1.3.1"; +HEALBOT_VERSION = "1.3.2"; ------------- -- ENGLISH -- diff --git a/HealBot_Model.lua b/HealBot_Model.lua index 0154eb1..0a1fc38 100644 --- a/HealBot_Model.lua +++ b/HealBot_Model.lua @@ -1,6 +1,110 @@ -- HealBot_Model.lua -- Centralized Data Store and Observer System for HealBotBlue +-- Fix legacy client UIDropDownMenu crash when setting value/id/refreshing while dropdown is not open +if UIDropDownMenu_Refresh and not HealBot_UIDropDownMenu_Refresh_Fixed then + local orig_UIDropDownMenu_Refresh = UIDropDownMenu_Refresh + UIDropDownMenu_Refresh = function(frame, useValue, group) + local targetFrame = frame or this + if not targetFrame or type(targetFrame) ~= "table" then return end + if not UIDROPDOWNMENU_OPEN_MENU or (targetFrame.GetName and targetFrame:GetName() ~= UIDROPDOWNMENU_OPEN_MENU) then + return + end + orig_UIDropDownMenu_Refresh(targetFrame, useValue, group) + end + HealBot_UIDropDownMenu_Refresh_Fixed = true +end + +if UIDropDownMenu_Initialize and not HealBot_UIDropDownMenu_Initialize_Fixed then + local orig_UIDropDownMenu_Initialize = UIDropDownMenu_Initialize + UIDropDownMenu_Initialize = function(frame, initFunction, displayMode, level) + local targetFrame = frame or this + if not targetFrame or type(targetFrame) ~= "table" then return end + + local name = targetFrame.GetName and targetFrame:GetName() + if UIDROPDOWNMENU_OPEN_MENU and name and name == UIDROPDOWNMENU_OPEN_MENU then + orig_UIDropDownMenu_Initialize(targetFrame, initFunction, displayMode, level) + else + local orig_AddButton = UIDropDownMenu_AddButton + UIDropDownMenu_AddButton = function(info, lvl) + -- Do nothing to prevent button accumulation in DropDownList1 + end + orig_UIDropDownMenu_Initialize(targetFrame, initFunction, displayMode, level) + UIDropDownMenu_AddButton = orig_AddButton + end + end + HealBot_UIDropDownMenu_Initialize_Fixed = true +end + +if UIDropDownMenu_SetSelectedID and not HealBot_UIDropDownMenu_SetSelectedID_Fixed then + local orig_UIDropDownMenu_SetSelectedID = UIDropDownMenu_SetSelectedID + UIDropDownMenu_SetSelectedID = function(frame, id, useValue) + local targetFrame = frame or this + if not targetFrame or type(targetFrame) ~= "table" then return end + + local name = targetFrame.GetName and targetFrame:GetName() + if UIDROPDOWNMENU_OPEN_MENU and name and name == UIDROPDOWNMENU_OPEN_MENU then + orig_UIDropDownMenu_SetSelectedID(targetFrame, id, useValue) + else + targetFrame.selectedID = id + targetFrame.selectedValue = nil + targetFrame.selectedName = nil + if targetFrame.initialize then + local buttons = {} + local orig_AddButton = UIDropDownMenu_AddButton + UIDropDownMenu_AddButton = function(info, level) + table.insert(buttons, info) + end + local temp_this = this + this = targetFrame + targetFrame.initialize(1) + this = temp_this + UIDropDownMenu_AddButton = orig_AddButton + if buttons[id] then + UIDropDownMenu_SetText(buttons[id].text, targetFrame) + end + end + end + end + HealBot_UIDropDownMenu_SetSelectedID_Fixed = true +end + +if UIDropDownMenu_SetSelectedValue and not HealBot_UIDropDownMenu_SetSelectedValue_Fixed then + local orig_UIDropDownMenu_SetSelectedValue = UIDropDownMenu_SetSelectedValue + UIDropDownMenu_SetSelectedValue = function(frame, value, useValue) + local targetFrame = frame or this + if not targetFrame or type(targetFrame) ~= "table" then return end + + local name = targetFrame.GetName and targetFrame:GetName() + if UIDROPDOWNMENU_OPEN_MENU and name and name == UIDROPDOWNMENU_OPEN_MENU then + orig_UIDropDownMenu_SetSelectedValue(targetFrame, value, useValue) + else + targetFrame.selectedID = nil + targetFrame.selectedValue = value + targetFrame.selectedName = nil + if targetFrame.initialize then + local buttons = {} + local orig_AddButton = UIDropDownMenu_AddButton + UIDropDownMenu_AddButton = function(info, level) + table.insert(buttons, info) + end + local temp_this = this + this = targetFrame + targetFrame.initialize(1) + this = temp_this + UIDropDownMenu_AddButton = orig_AddButton + for _, btn in ipairs(buttons) do + if btn.value == value then + UIDropDownMenu_SetText(btn.text, targetFrame) + break + end + end + end + end + end + HealBot_UIDropDownMenu_SetSelectedValue_Fixed = true +end + HealBot_Model = { observers = {}, units = {}, diff --git a/README.md b/README.md index 904faff..0b7412c 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,9 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\ ### Change Log +**1.3.2** +* **UIDropDownMenu Fixes:** Fixed client crash and button accumulation error on unopened dropdown menus in options. + **1.3.1** * **Hotfix: missing helper function restored** Fixed issue with lua error for druids. From 01a8e3bc6c399e6c8974d9f6fa70d4052637ec45 Mon Sep 17 00:00:00 2001 From: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com> Date: Thu, 9 Jul 2026 08:13:34 +0200 Subject: [PATCH 2/3] Update README.md Known issues section added --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 0b7412c..948f0de 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,11 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\ * **Curse & Debuff Warning (CDC):** Dynamic visual and audio alerts for cleanable debuffs. Customizable colors based on debuff type (Curse, Poison, Disease, Magic). * **Highly Customizable Skins:** Fully configure dimensions (width, height), row spacing, column layouts, custom textures, opacity, class-colored frames, and outline of fonts. +### Known issues + +* **New spell rank bug** you may experience lua error spaming your chat frame after learning new healing spells. /reload will clear the issue. To be fixed next release + + ### Change Log **1.3.2** From f8c6c3493b0f7064d522b317840144c94f6935fd Mon Sep 17 00:00:00 2001 From: Bluewhale1337 <295648290+Bluewhale1337@users.noreply.github.com> Date: Fri, 10 Jul 2026 15:54:36 +0200 Subject: [PATCH 3/3] Refactor + Horfixes: replace UIDropDownMenu calls with wrapper functions and redesign chat option UI to support spell-based configuration. --- HealBot_Controller_Events.lua | 4 + HealBot_Controller_Spells.lua | 17 ++- HealBot_Model.lua | 116 +++-------------- HealBot_Options.lua | 3 +- HealBot_Options_Buffs.lua | 14 +- HealBot_Options_CDC.lua | 6 +- HealBot_Options_Chat.lua | 83 ++---------- HealBot_Options_Chat.xml | 237 ++++++++++++++++++++-------------- HealBot_Options_General.lua | 3 +- HealBot_Options_Healing.lua | 6 +- HealBot_Options_Skins.lua | 2 +- HealBot_Options_Spells.lua | 2 +- README.md | 7 +- 13 files changed, 220 insertions(+), 280 deletions(-) diff --git a/HealBot_Controller_Events.lua b/HealBot_Controller_Events.lua index f6078c3..6190b9c 100644 --- a/HealBot_Controller_Events.lua +++ b/HealBot_Controller_Events.lua @@ -415,6 +415,10 @@ end function HealBot_OnEvent_PlayerEnteringWorld(this) HealBot_IsFighting = false; + -- Re-apply the refresh hook late in case another addon overrode it during load + if HealBot_ApplyRefreshHook then + HealBot_ApplyRefreshHook() + end end function HealBot_OnEvent_SpellcastStart(this, spell, duration) diff --git a/HealBot_Controller_Spells.lua b/HealBot_Controller_Spells.lua index 44a00e3..8bdf961 100644 --- a/HealBot_Controller_Spells.lua +++ b/HealBot_Controller_Spells.lua @@ -95,13 +95,26 @@ function HealBot_StartCasting(spell, target, ttype) 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, "%(") + 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 + + -- Strip trailing spaces from base spell + baseSpell = string.gsub(baseSpell, "%s+$", "") + for i = 1, 5 do local msgConf = HealBot_Config.ChatMessages[i] - if msgConf and msgConf.Spell == baseSpell and msgConf.Channel ~= "None" then + local configSpell = msgConf and msgConf.Spell or "" + -- Strip trailing spaces from config spell just in case + configSpell = string.gsub(configSpell, "%s+$", "") + + if msgConf and configSpell ~= "" and msgConf.Channel ~= "None" and (configSpell == spell or configSpell == baseSpell) then local msg = msgConf.Message or "" msg = string.gsub(msg, "#Spell#", spell) msg = string.gsub(msg, "#Target#", tName) diff --git a/HealBot_Model.lua b/HealBot_Model.lua index 0a1fc38..7fca64a 100644 --- a/HealBot_Model.lua +++ b/HealBot_Model.lua @@ -1,108 +1,30 @@ -- HealBot_Model.lua -- Centralized Data Store and Observer System for HealBotBlue --- Fix legacy client UIDropDownMenu crash when setting value/id/refreshing while dropdown is not open -if UIDropDownMenu_Refresh and not HealBot_UIDropDownMenu_Refresh_Fixed then - local orig_UIDropDownMenu_Refresh = UIDropDownMenu_Refresh - UIDropDownMenu_Refresh = function(frame, useValue, group) - local targetFrame = frame or this - if not targetFrame or type(targetFrame) ~= "table" then return end - if not UIDROPDOWNMENU_OPEN_MENU or (targetFrame.GetName and targetFrame:GetName() ~= UIDROPDOWNMENU_OPEN_MENU) then - return +-- Safe local wrappers to prevent native UIDropDownMenu concatenation crashes +-- when setting selected values on closed dropdowns during initialization. +function HealBot_UIDropDownMenu_SetSelectedID(frame, id, useValue) + local wasNil = false + if not UIDROPDOWNMENU_OPEN_MENU then + UIDROPDOWNMENU_OPEN_MENU = "DropDownList1" + wasNil = true + end + UIDropDownMenu_SetSelectedID(frame, id, useValue) + if wasNil then + UIDROPDOWNMENU_OPEN_MENU = nil end - orig_UIDropDownMenu_Refresh(targetFrame, useValue, group) - end - HealBot_UIDropDownMenu_Refresh_Fixed = true end -if UIDropDownMenu_Initialize and not HealBot_UIDropDownMenu_Initialize_Fixed then - local orig_UIDropDownMenu_Initialize = UIDropDownMenu_Initialize - UIDropDownMenu_Initialize = function(frame, initFunction, displayMode, level) - local targetFrame = frame or this - if not targetFrame or type(targetFrame) ~= "table" then return end - - local name = targetFrame.GetName and targetFrame:GetName() - if UIDROPDOWNMENU_OPEN_MENU and name and name == UIDROPDOWNMENU_OPEN_MENU then - orig_UIDropDownMenu_Initialize(targetFrame, initFunction, displayMode, level) - else - local orig_AddButton = UIDropDownMenu_AddButton - UIDropDownMenu_AddButton = function(info, lvl) - -- Do nothing to prevent button accumulation in DropDownList1 - end - orig_UIDropDownMenu_Initialize(targetFrame, initFunction, displayMode, level) - UIDropDownMenu_AddButton = orig_AddButton +function HealBot_UIDropDownMenu_SetSelectedValue(frame, value, useValue) + local wasNil = false + if not UIDROPDOWNMENU_OPEN_MENU then + UIDROPDOWNMENU_OPEN_MENU = "DropDownList1" + wasNil = true end - end - HealBot_UIDropDownMenu_Initialize_Fixed = true -end - -if UIDropDownMenu_SetSelectedID and not HealBot_UIDropDownMenu_SetSelectedID_Fixed then - local orig_UIDropDownMenu_SetSelectedID = UIDropDownMenu_SetSelectedID - UIDropDownMenu_SetSelectedID = function(frame, id, useValue) - local targetFrame = frame or this - if not targetFrame or type(targetFrame) ~= "table" then return end - - local name = targetFrame.GetName and targetFrame:GetName() - if UIDROPDOWNMENU_OPEN_MENU and name and name == UIDROPDOWNMENU_OPEN_MENU then - orig_UIDropDownMenu_SetSelectedID(targetFrame, id, useValue) - else - targetFrame.selectedID = id - targetFrame.selectedValue = nil - targetFrame.selectedName = nil - if targetFrame.initialize then - local buttons = {} - local orig_AddButton = UIDropDownMenu_AddButton - UIDropDownMenu_AddButton = function(info, level) - table.insert(buttons, info) - end - local temp_this = this - this = targetFrame - targetFrame.initialize(1) - this = temp_this - UIDropDownMenu_AddButton = orig_AddButton - if buttons[id] then - UIDropDownMenu_SetText(buttons[id].text, targetFrame) - end - end + UIDropDownMenu_SetSelectedValue(frame, value, useValue) + if wasNil then + UIDROPDOWNMENU_OPEN_MENU = nil end - end - HealBot_UIDropDownMenu_SetSelectedID_Fixed = true -end - -if UIDropDownMenu_SetSelectedValue and not HealBot_UIDropDownMenu_SetSelectedValue_Fixed then - local orig_UIDropDownMenu_SetSelectedValue = UIDropDownMenu_SetSelectedValue - UIDropDownMenu_SetSelectedValue = function(frame, value, useValue) - local targetFrame = frame or this - if not targetFrame or type(targetFrame) ~= "table" then return end - - local name = targetFrame.GetName and targetFrame:GetName() - if UIDROPDOWNMENU_OPEN_MENU and name and name == UIDROPDOWNMENU_OPEN_MENU then - orig_UIDropDownMenu_SetSelectedValue(targetFrame, value, useValue) - else - targetFrame.selectedID = nil - targetFrame.selectedValue = value - targetFrame.selectedName = nil - if targetFrame.initialize then - local buttons = {} - local orig_AddButton = UIDropDownMenu_AddButton - UIDropDownMenu_AddButton = function(info, level) - table.insert(buttons, info) - end - local temp_this = this - this = targetFrame - targetFrame.initialize(1) - this = temp_this - UIDropDownMenu_AddButton = orig_AddButton - for _, btn in ipairs(buttons) do - if btn.value == value then - UIDropDownMenu_SetText(btn.text, targetFrame) - break - end - end - end - end - end - HealBot_UIDropDownMenu_SetSelectedValue_Fixed = true end HealBot_Model = { diff --git a/HealBot_Options.lua b/HealBot_Options.lua index d599b52..bdb5371 100644 --- a/HealBot_Options.lua +++ b/HealBot_Options.lua @@ -315,7 +315,8 @@ function HealBot_Options_SetSkins() HealBot_Options_FontHeight:SetValue(HealBot_Config.btextheight[HealBot_Config.Current_Skin]) HealBot_Options_BarAlphaDis:SetValue(HealBot_Config.bardisa[HealBot_Config.Current_Skin]) HealBot_Options_AbortBarSize:SetValue(HealBot_Config.abortsize[HealBot_Config.Current_Skin]) - HealBot_Options_ShowHeaders:SetChecked(HealBot_Config.ShowHeader[HealBot_Config.Current_Skin] or 0) + local isShowHeaders = (HealBot_Config.ShowHeader[HealBot_Config.Current_Skin] == 1) + HealBot_Options_ShowHeaders:SetChecked(isShowHeaders and 1 or nil) local isColorMode = (HealBot_Config.bcolormode[HealBot_Config.Current_Skin] == 2) HealBot_Options_BarColorMode:SetChecked(isColorMode and 1 or nil) diff --git a/HealBot_Options_Buffs.lua b/HealBot_Options_Buffs.lua index 2be1da1..d849705 100644 --- a/HealBot_Options_Buffs.lua +++ b/HealBot_Options_Buffs.lua @@ -21,9 +21,10 @@ function HealBot_Options_BuffSelf_OnLoad(self) getglobal(this:GetName().."Text"):SetText("Self Only") local id = this:GetID() if HealBot_Config.BuffWatchSelf and HealBot_Config.BuffWatchSelf[id] then - this:SetChecked(HealBot_Config.BuffWatchSelf[id]) + local isSelf = (HealBot_Config.BuffWatchSelf[id] == 1) + this:SetChecked(isSelf and 1 or nil) else - this:SetChecked(0) + this:SetChecked(nil) end end function HealBot_Options_BuffSelf_OnClick(self) @@ -77,7 +78,7 @@ function HealBot_Options_Buff_OnClick() text = HealBot_Buff_Spells[myClass][this.value] end - UIDropDownMenu_SetSelectedID(frame, this.value + 1) + HealBot_UIDropDownMenu_SetSelectedID(frame, this.value + 1) UIDropDownMenu_SetText(text, frame) HealBot_RecalcParty(); end @@ -101,15 +102,16 @@ function HealBot_Options_SetBuffs() if dropDown then local val = HealBot_Config.BuffDropDowns[myClass][i] or 0 UIDropDownMenu_Initialize(dropDown, HealBot_Options_Buff_Initialize) - UIDropDownMenu_SetSelectedID(dropDown, val + 1) + HealBot_UIDropDownMenu_SetSelectedID(dropDown, val + 1) end local selfCheck = getglobal("HealBot_Options_BuffSelf" .. i) if selfCheck then if HealBot_Config.BuffWatchSelf and HealBot_Config.BuffWatchSelf[i] then - selfCheck:SetChecked(HealBot_Config.BuffWatchSelf[i]) + local isSelf = (HealBot_Config.BuffWatchSelf[i] == 1) + selfCheck:SetChecked(isSelf and 1 or nil) else - selfCheck:SetChecked(0) + selfCheck:SetChecked(nil) end end end diff --git a/HealBot_Options_CDC.lua b/HealBot_Options_CDC.lua index 3fbffd9..14e81c4 100644 --- a/HealBot_Options_CDC.lua +++ b/HealBot_Options_CDC.lua @@ -51,7 +51,7 @@ end function HealBot_Options_CDCMonitor_Refresh(onselect) if not HealBot_Config.CDCMonitor then return end if not onselect then HealBot_Options_CDCMonitor_Initialize() end -- or wrong menu may be used ! - UIDropDownMenu_SetSelectedID(HealBot_Options_CDCMonitor,HealBot_Config.CDCMonitor) + HealBot_UIDropDownMenu_SetSelectedID(HealBot_Options_CDCMonitor,HealBot_Config.CDCMonitor) end function HealBot_Options_CDCMonitor_OnLoad() UIDropDownMenu_Initialize(this, HealBot_Options_CDCMonitor_DropDown) @@ -200,14 +200,14 @@ function HealBot_Options_CDCButLeft_Refresh(onselect) local class=UnitClass("Player"); if not onselect then HealBot_Options_CDCButLeft_Initialize() end set_id = HealBot_Config.Debuff_Left[class]; - UIDropDownMenu_SetSelectedID(HealBot_Options_CDCButLeft,set_id) + HealBot_UIDropDownMenu_SetSelectedID(HealBot_Options_CDCButLeft,set_id) end function HealBot_Options_CDCButRight_Refresh(onselect) local set_id; local class=UnitClass("Player"); if not onselect then HealBot_Options_CDCButRight_Initialize() end set_id = HealBot_Config.Debuff_Right[class]; - UIDropDownMenu_SetSelectedID(HealBot_Options_CDCButRight,set_id) + HealBot_UIDropDownMenu_SetSelectedID(HealBot_Options_CDCButRight,set_id) end function HealBot_Options_CDCButLeft_OnLoad() UIDropDownMenu_Initialize(this, HealBot_Options_CDCButLeft_DropDown) diff --git a/HealBot_Options_Chat.lua b/HealBot_Options_Chat.lua index d95eb7f..7e49fa3 100644 --- a/HealBot_Options_Chat.lua +++ b/HealBot_Options_Chat.lua @@ -1,69 +1,10 @@ -- HealBot Options panel file: HealBot_Options_Chat.lua -- Split from original HealBot_Options.lua -local HealBot_PlayerSpells = nil - -function HealBot_GetPlayerSpells() - if HealBot_PlayerSpells then return HealBot_PlayerSpells end - local spellSet = {} - local i = 1 - while true do - local spellName, spellRank = GetSpellName(i, BOOKTYPE_SPELL) - if not spellName then - break - end - spellSet[spellName] = true - i = i + 1 - end - local sortedSpells = {} - for k, _ in pairs(spellSet) do - table.insert(sortedSpells, k) - end - table.sort(sortedSpells) - HealBot_PlayerSpells = sortedSpells - return sortedSpells -end - -function HealBot_Options_ChatMsg_Spell_Initialize() - local info - - info = { text = "None", func = HealBot_Options_ChatMsg_Spell_OnClick, value = "None" } - UIDropDownMenu_AddButton(info) - - local spells = HealBot_GetPlayerSpells() - for _, spellName in ipairs(spells) do - info = { - text = spellName, - func = HealBot_Options_ChatMsg_Spell_OnClick, - value = spellName - } - UIDropDownMenu_AddButton(info) - end -end - -function HealBot_Options_ChatMsg_Spell_OnClick() - local frameName = UIDROPDOWNMENU_OPEN_MENU - local frame = getglobal(frameName) - local id = frame:GetID() - - if not HealBot_Config.ChatMessages then HealBot_Config.ChatMessages = {} end - if not HealBot_Config.ChatMessages[id] then - HealBot_Config.ChatMessages[id] = { Spell = "None", Message = "Casting #Spell# on #Target#", Channel = "None" } - end - - HealBot_Config.ChatMessages[id].Spell = this.value - - local text = this.value - if text == "None" then text = "None" end - - UIDropDownMenu_SetSelectedValue(frame, this.value) - UIDropDownMenu_SetText(text, frame) -end - function HealBot_Options_ChatMsg_Channel_OnClick(id, buttonFrame) if not HealBot_Config.ChatMessages then HealBot_Config.ChatMessages = {} end if not HealBot_Config.ChatMessages[id] then - HealBot_Config.ChatMessages[id] = { Spell = "None", Message = "Casting #Spell# on #Target#", Channel = "None" } + HealBot_Config.ChatMessages[id] = { Spell = "", Message = "Casting #Spell# on #Target#", Channel = "None" } end local current = HealBot_Config.ChatMessages[id].Channel @@ -91,24 +32,26 @@ function HealBot_Options_SetChatMessages() end for i = 1, 5 do if not HealBot_Config.ChatMessages[i] then - HealBot_Config.ChatMessages[i] = { Spell = "None", Message = "Casting #Spell# on #Target#", Channel = "None" } + HealBot_Config.ChatMessages[i] = { Spell = "", Message = "Casting #Spell# on #Target#", Channel = "None" } end end for i = 1, 5 do local msgConfig = HealBot_Config.ChatMessages[i] if msgConfig then - local dropDown = getglobal("HealBot_Options_ChatMsg"..i) - local editBox = getglobal("HealBot_Options_ChatMsg"..i.."_Text") + local spellEdit = getglobal("HealBot_Options_ChatMsg"..i.."_Spell") + local textEdit = getglobal("HealBot_Options_ChatMsg"..i.."_Text") local chanButton = getglobal("HealBot_Options_ChatMsg"..i.."_Channel") - if dropDown then - UIDropDownMenu_Initialize(dropDown, HealBot_Options_ChatMsg_Spell_Initialize) - UIDropDownMenu_SetSelectedValue(dropDown, msgConfig.Spell) - UIDropDownMenu_SetWidth(110, dropDown) - UIDropDownMenu_SetText(msgConfig.Spell, dropDown) + if spellEdit then + if msgConfig.Spell == "None" then + spellEdit:SetText("") + msgConfig.Spell = "" + else + spellEdit:SetText(msgConfig.Spell or "") + end end - if editBox then - editBox:SetText(msgConfig.Message or "") + if textEdit then + textEdit:SetText(msgConfig.Message or "") end if chanButton then chanButton:SetText(msgConfig.Channel or "None") diff --git a/HealBot_Options_Chat.xml b/HealBot_Options_Chat.xml index ee51447..eb11d34 100644 --- a/HealBot_Options_Chat.xml +++ b/HealBot_Options_Chat.xml @@ -5,23 +5,50 @@ - + + + + - + - - + + + if HealBot_Config.ChatMessages then + HealBot_Config.ChatMessages[1].Spell = this:GetText(); + end + + + + + + + + + + + + @@ -33,41 +60,51 @@ - - - - - - - - - - - - + - + - + @@ -79,41 +116,51 @@ - - - - - - - - - - - - + - + - + @@ -125,41 +172,51 @@ - - - - - - - - - - - - + - + - + @@ -171,41 +228,51 @@ - - - - - - - - - - - - + - + - + @@ -217,24 +284,6 @@ - - - + \ No newline at end of file diff --git a/HealBot_Options_General.lua b/HealBot_Options_General.lua index 15b1f2c..1bb5a40 100644 --- a/HealBot_Options_General.lua +++ b/HealBot_Options_General.lua @@ -5,7 +5,8 @@ function HealBot_Options_ShowHeaders_OnLoad(this) getglobal(this:GetName().."Text"):SetText(HEALBOT_OPTIONS_SHOWHEADERS); end function HealBot_Options_ShowHeaders_OnClick(this) - HealBot_Config.ShowHeader[HealBot_Config.Current_Skin] = this:GetChecked(); + local isChecked = this:GetChecked() + HealBot_Config.ShowHeader[HealBot_Config.Current_Skin] = isChecked and 1 or 0; HealBot_Action_ResetSkin() end function HealBot_Options_BarTextureS_OnValueChanged(this) diff --git a/HealBot_Options_Healing.lua b/HealBot_Options_Healing.lua index b923c58..8de4897 100644 --- a/HealBot_Options_Healing.lua +++ b/HealBot_Options_Healing.lua @@ -108,7 +108,7 @@ end function HealBot_Options_EmergencyFClass_Refresh(onselect) if not HealBot_Config.EmergencyFClass then return end if not onselect then HealBot_Options_EmergencyFClass_Initialize() end -- or wrong menu may be used ! - UIDropDownMenu_SetSelectedID(HealBot_Options_EmergencyFClass,HealBot_Config.EmergencyFClass) + HealBot_UIDropDownMenu_SetSelectedID(HealBot_Options_EmergencyFClass,HealBot_Config.EmergencyFClass) end function HealBot_Options_EmergencyFClass_OnLoad() @@ -191,7 +191,7 @@ end function HealBot_Options_ExtraSort_Refresh(onselect) if not HealBot_Config.ExtraOrder then return end if not onselect then HealBot_Options_ExtraSort_Initialize() end -- or wrong menu may be used ! - UIDropDownMenu_SetSelectedID(HealBot_Options_ExtraSort,HealBot_Config.ExtraOrder) + HealBot_UIDropDownMenu_SetSelectedID(HealBot_Options_ExtraSort,HealBot_Config.ExtraOrder) end function HealBot_Options_ExtraSort_OnLoad() @@ -225,7 +225,7 @@ end function HealBot_Options_EmergencyFilter_Refresh(onselect) if not HealBot_Config.EmergIncMonitor then return end if not onselect then HealBot_Options_EmergencyFilter_Initialize() end -- or wrong menu may be used ! - UIDropDownMenu_SetSelectedID(HealBot_Options_EmergencyFilter,HealBot_Config.EmergIncMonitor) + HealBot_UIDropDownMenu_SetSelectedID(HealBot_Options_EmergencyFilter,HealBot_Config.EmergIncMonitor) end diff --git a/HealBot_Options_Skins.lua b/HealBot_Options_Skins.lua index 02c685a..00ec5a2 100644 --- a/HealBot_Options_Skins.lua +++ b/HealBot_Options_Skins.lua @@ -112,7 +112,7 @@ end function HealBot_Options_Skins_Refresh(onselect) if not HealBot_Config.Skin_ID then return end if not onselect then HealBot_Options_Skins_Initialize() end -- or wrong menu may be used ! - UIDropDownMenu_SetSelectedID(HealBot_Options_Skins,HealBot_Config.Skin_ID) + HealBot_UIDropDownMenu_SetSelectedID(HealBot_Options_Skins,HealBot_Config.Skin_ID) end function HealBot_Options_Skins_OnLoad() UIDropDownMenu_Initialize(this, HealBot_Options_Skins_DropDown) diff --git a/HealBot_Options_Spells.lua b/HealBot_Options_Spells.lua index f98a668..4c63e8b 100644 --- a/HealBot_Options_Spells.lua +++ b/HealBot_Options_Spells.lua @@ -62,7 +62,7 @@ end function HealBot_Options_TooltipPos_Refresh(onselect) if not HealBot_Config.TooltipPos then return end if not onselect then HealBot_Options_TooltipPos_Initialize() end -- or wrong menu may be used ! - UIDropDownMenu_SetSelectedID(HealBot_Options_TooltipPos,HealBot_Config.TooltipPos) + HealBot_UIDropDownMenu_SetSelectedID(HealBot_Options_TooltipPos,HealBot_Config.TooltipPos) end function HealBot_Options_TooltipPos_OnLoad() diff --git a/README.md b/README.md index 0b7412c..7fa9b07 100644 --- a/README.md +++ b/README.md @@ -30,8 +30,13 @@ Default installation path: `C:\Program Files\World of Warcraft\Interface\AddOns\ ### Change Log +**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. +* **UI Persistence Bug Fixes:** Fixed a Vanilla WoW API quirk where unchecking the "Show Headers" or "Self Only" (Buffs) checkboxes caused the UI to either visually re-check itself or overwrite the setting with defaults upon a `/reload`. + **1.3.2** -* **UIDropDownMenu Fixes:** Fixed client crash and button accumulation error on unopened dropdown menus in options. +* **UIDropDownMenu Fixes:** Resolved native client crash (`UIDROPDOWNMENU_OPEN_MENU` nil concatenation) when setting values on closed dropdowns. **1.3.1** * **Hotfix: missing helper function restored** Fixed issue with lua error for druids.