From 3fb81c08a0f8edfb614856c736b1a67d96cbfd95 Mon Sep 17 00:00:00 2001 From: Florian Berthold Date: Sun, 24 May 2026 17:39:15 +0200 Subject: [PATCH] fix: enable stance/state bars for CoA custom classes with shapeshift forms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Vanilla Bartender4 assumes only DRUID/WARRIOR/WARLOCK/PRIEST/ROGUE/HERO have shapeshift forms. CoA custom classes (Witchdoctor, Templar, …) can register forms late at runtime and aren't in the whitelist, so the stance/state bar never came up for them. StanceBar.lua: - ApplyConfig() no longer Disable()s the module when GetNumShapeshiftForms() is 0 at config time. A disabled module never re-enables on UPDATE_SHAPESHIFT_FORMS, so late-registered forms were lost. We now just hide the bar frame. - Register UPDATE_SHAPESHIFT_FORMS and PLAYER_ENTERING_WORLD on the module itself and re-Enable() / show the bar when forms appear after the fact. Options/Bar.lua: - The 'Hide in Stance/Form' visibility option was gated by a hard-coded stanceClasses whitelist. Add an OR-fallback on GetNumShapeshiftForms() > 0 so CoA classes with forms get the UI. StateBar.lua: - DefaultStanceMap only had vanilla entries. For unknown classes with live forms, synthesise a generic { id="formN", index=N } map at runtime so UpdateStates() can wire stance-based action bar swaps. --- Bartender4/Options/Bar.lua | 5 ++++- Bartender4/StanceBar.lua | 27 ++++++++++++++++++++++++++- Bartender4/StateBar.lua | 26 ++++++++++++++++++++++++-- 3 files changed, 54 insertions(+), 4 deletions(-) diff --git a/Bartender4/Options/Bar.lua b/Bartender4/Options/Bar.lua index 537abd4..d61bab1 100644 --- a/Bartender4/Options/Bar.lua +++ b/Bartender4/Options/Bar.lua @@ -344,7 +344,10 @@ function Bar:GetOptionObject() name = L["Hide in Stance/Form"], desc = L["Hide this bar in a specific Stance or Form."], values = getStanceTable, - hidden = function() return (not stanceClasses[class]) end, + -- CoA: custom classes (Witchdoctor, Templar, …) may have forms + -- but aren't in the vanilla stanceClasses whitelist. Show the + -- option whenever the player currently has any form available. + hidden = function() return (not (stanceClasses[class] or GetNumShapeshiftForms() > 0)) end, disabled = customEnabled, }, customNl = { diff --git a/Bartender4/StanceBar.lua b/Bartender4/StanceBar.lua index 23c03a9..83c9f86 100644 --- a/Bartender4/StanceBar.lua +++ b/Bartender4/StanceBar.lua @@ -48,18 +48,43 @@ function StanceBarMod:OnEnable() self.bar:RegisterEvent("PLAYER_REGEN_ENABLED") self.bar:RegisterEvent("ACTIONBAR_PAGE_CHANGED") self:RegisterEvent("UPDATE_BINDINGS", "ReassignBindings") + -- CoA: re-enable / refresh when forms appear late (custom classes) + self:RegisterEvent("UPDATE_SHAPESHIFT_FORMS", "OnShapeshiftFormsUpdate") + self:RegisterEvent("PLAYER_ENTERING_WORLD", "OnShapeshiftFormsUpdate") self:ReassignBindings() self:ApplyConfig() end +function StanceBarMod:OnShapeshiftFormsUpdate() + -- CoA: if the module is disabled but forms now exist (custom class form + -- registered after login), bring it back online. + if not self:IsEnabled() and GetNumShapeshiftForms() > 0 then + self:Enable() + return + end + if self:IsEnabled() and self.bar then + if GetNumShapeshiftForms() > 0 then + if self.bar.Show then self.bar:Show() end + else + if self.bar.Hide then self.bar:Hide() end + end + end +end + StanceBarMod.button_count = 10 function StanceBarMod:ApplyConfig() if not self:IsEnabled() then return end self.bar:ApplyConfig(self.db.profile) + -- CoA: custom classes (Witchdoctor, Templar, …) may register forms late. + -- Don't Disable() the module if there are 0 forms right now — once disabled + -- we'd never come back when UPDATE_SHAPESHIFT_FORMS arrives. Just hide the bar + -- frame; UpdateStanceButtons() will re-show it when forms appear. if GetNumShapeshiftForms() == 0 then - self:Disable() + if self.bar.Hide then self.bar:Hide() end + else + if self.bar.Show then self.bar:Show() end end end diff --git a/Bartender4/StateBar.lua b/Bartender4/StateBar.lua index cc3bca0..1b0d867 100644 --- a/Bartender4/StateBar.lua +++ b/Bartender4/StateBar.lua @@ -116,12 +116,34 @@ local DefaultStanceMap = setmetatable({}, { __index = function(t,k) end}) Bartender4.StanceMap = DefaultStanceMap +-- CoA: build a generic runtime stance map for classes the addon doesn't know +-- about (Witchdoctor, Templar, …). We don't have spell-id metadata for them, +-- so synthesise { id = "formN", index = N } entries based on live form count. +local function BuildGenericStanceMap() + local num = GetNumShapeshiftForms() + if not num or num == 0 then return nil end + local map = {} + for i = 1, num do + map[i] = { id = ("form%d"):format(i), name = ("Form %d"):format(i), index = i } + end + return map +end + local stancemap function StateBar:UpdateStates(returnOnly) if not self.buttons then return end self.statebutton = {} - if not stancemap and DefaultStanceMap[playerclass] then - stancemap = DefaultStanceMap[playerclass] + -- CoA: rebuild generic stance maps each call so late-registered forms get + -- picked up; vanilla classes keep their cached DefaultStanceMap entry. + if not stancemap then + if DefaultStanceMap[playerclass] then + stancemap = DefaultStanceMap[playerclass] + elseif GetNumShapeshiftForms() > 0 then + stancemap = BuildGenericStanceMap() + end + elseif not DefaultStanceMap[playerclass] then + -- generic map: refresh on every call in case form count changed + stancemap = BuildGenericStanceMap() end local statedriver