From 5613710ca5ddcc48a4c7cf711164f48fbc9a97ab Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Fri, 3 Apr 2026 16:44:21 +0100 Subject: [PATCH 1/6] Add auto colaps function to everybare --- Core/MultiBotEngine.lua | 76 ++++++++++++++++++++++ Core/MultiBotEvery.lua | 6 +- TODO.md | 122 +---------------------------------- UI/MultiBotInventoryItem.lua | 100 +++++++++++++++++++++++++++- 4 files changed, 179 insertions(+), 125 deletions(-) diff --git a/Core/MultiBotEngine.lua b/Core/MultiBotEngine.lua index 7cc8985..c8cb857 100644 --- a/Core/MultiBotEngine.lua +++ b/Core/MultiBotEngine.lua @@ -563,16 +563,84 @@ end MultiBot.ShowHideSwitch = function(pFrame) if(pFrame:IsVisible()) then + if MultiBot.RestoreCollapsedUnitBarsFromDropdown then + MultiBot.RestoreCollapsedUnitBarsFromDropdown(pFrame) + end pFrame:Hide() if(MultiBot.RequestClickBlockerUpdate) then MultiBot.RequestClickBlockerUpdate(pFrame) end return false end + if MultiBot.CollapseOtherUnitBarsForDropdown then + MultiBot.CollapseOtherUnitBarsForDropdown(pFrame) + end + pFrame:Show() if(MultiBot.RequestClickBlockerUpdate) then MultiBot.RequestClickBlockerUpdate(pFrame) end return true end +MultiBot.RestoreCollapsedUnitBarsFromDropdown = function(targetFrame) + if not targetFrame then + return + end + + local collapsedBars = targetFrame._mbCollapsedBars + if type(collapsedBars) ~= "table" then + return + end + + for index = 1, #collapsedBars do + local frame = collapsedBars[index] + if frame and frame.Show then + frame:Show() + end + end + + targetFrame._mbCollapsedBars = nil +end + +MultiBot.CollapseOtherUnitBarsForDropdown = function(targetFrame) + if not targetFrame or not targetFrame.parent then + return + end + + local unitsFrame = MultiBot.frames + and MultiBot.frames["MultiBar"] + and MultiBot.frames["MultiBar"].frames + and MultiBot.frames["MultiBar"].frames["Units"] + if not unitsFrame or not unitsFrame.frames then + return + end + + local ownerBar = targetFrame.parent + while ownerBar and ownerBar.parent and ownerBar.parent ~= unitsFrame do + ownerBar = ownerBar.parent + end + + if not ownerBar or ownerBar.parent ~= unitsFrame then + return + end + + -- On ne collapse les autres barres que pour l'ouverture d'un sous-menu + -- (pas lors de l'ouverture/fermeture de la barre du bot elle-même). + if targetFrame == ownerBar then + return + end + + local collapsedBars = {} + for key, frame in pairs(unitsFrame.frames) do + if frame ~= ownerBar and key ~= "Alliance" and key ~= "Control" + and frame and frame.Hide and frame.IsShown and frame:IsShown() then + table.insert(collapsedBars, frame) + frame:Hide() + end + end + + targetFrame._mbDropdownManaged = true + targetFrame._mbCollapsedBars = collapsedBars +end + MultiBot.OnOffActionToTarget = function(pButton, pOn, pOff, pTarget) if(pButton.state) then MultiBot.ActionToTarget(pOff, pTarget) @@ -1080,6 +1148,14 @@ MultiBot.newButton = function(pParent, pX, pY, pSize, pTexture, pTip, oTemplate) if(pEvent == "RightButton" and button.doRight ~= nil) then button.doRight(button) end if(pEvent == "LeftButton" and button.doLeft ~= nil) then button.doLeft(button) end + + if button.parent and button.parent._mbDropdownManaged then + if MultiBot.RestoreCollapsedUnitBarsFromDropdown then + MultiBot.RestoreCollapsedUnitBarsFromDropdown(button.parent) + end + button.parent:Hide() + if(MultiBot.RequestClickBlockerUpdate) then MultiBot.RequestClickBlockerUpdate(button.parent) end + end end) return button diff --git a/Core/MultiBotEvery.lua b/Core/MultiBotEvery.lua index d784d8e..6bb6878 100644 --- a/Core/MultiBotEvery.lua +++ b/Core/MultiBotEvery.lua @@ -26,11 +26,7 @@ MultiBot.addEvery = function(pFrame, pCombat, pNormal) -- Bouton parent « Misc » local btnMisc = pFrame.addButton("Misc", 64, 0, "inv_misc_enggizmos_swissarmy", MultiBot.L("tips.every.misc")) btnMisc.doLeft = function(self) - if tMisc:IsShown() then - tMisc:Hide() - else - tMisc:Show() - end + MultiBot.ShowHideSwitch(tMisc) end -- Texture étoile diff --git a/TODO.md b/TODO.md index 06ae089..b8eeaf9 100644 --- a/TODO.md +++ b/TODO.md @@ -1,5 +1,6 @@ TODO +* Vente d'items de quetes, ça les vends quand même mais le bot les récupère, normallement ça devrait dire qu'il ne peux pas vendre un item de quête * Voir si y'a pas d'autres appels à pageLabel:SetText(MB_PAGE_DEFAULT) dans les fichiers et remplacer par : + pageLabel:SetText(MultiBot.MB_PAGE_DEFAULT or "0/0") * Uniformiser le template des frame quetes comme celle de Itemus * Uniformiser le template de la frame reward comme celle de itemus @@ -12,122 +13,5 @@ TODO * creer le multilangue pour le tooltip: setTooltip(self, "Show / Hide / Move Quick Shaman") des fichiers quickshaman et quickhunter * Finir les options de déplacement des boutons * Debuguer le blocage de la barre principale en déplacement ça a l'air de ne pas persister apres une deco reco - - - Ajouter la fonction unequipe à Multibit: -“unequip” est une action orientée équipement, donc elle colle naturellement à une vue d’inspection / slots d’équipement, alors que la réorganisation des sacs demande une logique de bag/slot bien plus lourde. -Pourquoi c’est un bon candidat pour la fenêtre d’inspection - -1) L’inspection est déjà centrée sur les slots d’équipement -Le code existant manipule déjà très bien la notion de slot d’équipement : -dans le calcul d’ilvl, on parcourt explicitement les slots 1..18 ; -dans itemus, il existe déjà une cartographie claire des slots d’équipement (S00, S01, etc.). -Donc si la commande ue fonctionne par slot ou peut être reliée à un slot, l’intégration UI est très naturelle. - -2) On a déjà un point d’entrée “Inspect” -L’addon sait déjà lancer l’inspection d’un bot via InspectUnit(...) : -depuis le bouton Inspect dans la Reward frame, et ailleurs dans l’addon. -Donc graphiquement, il y a déjà un flux utilisateur existant : -ouvrir l’inspection du bot, -voir son équipement, -déclencher une action sur un slot équipé. - -Là où il faut être prudent -Le vrai point clé : comment fonctionne exactement ue -C’est ça qui détermine la qualité de l’intégration. - -Cas A — si ue fonctionne par slot -Exemple conceptuel : -ue head -ue 1 -ue S01 - -Dans ce cas, c’est idéal. -Parce que la fenêtre d’inspection affiche précisément des slots. Tu peux donc faire une UI très propre : -clic droit sur un slot équipé → unequip ; -ou petit bouton contextuel sur chaque slot ; -ou mode “Unequip” activable, puis clic sur le slot. - -Cas B — si ue fonctionne par item -Exemple conceptuel : -ue [ItemLink] -C’est encore faisable, mais un peu moins robuste : -s’il y a ambiguïté, -si deux objets identiques existent, -ou si la commande backend attend autre chose qu’un lien standard. - -Cas C — si ue a une syntaxe spéciale côté playerbots -Alors il faudra juste aligner l’UI sur cette syntaxe. -Mais dans tous les cas, le concept UI reste pertinent. - -“unequip” est une action sur : -un slot équipé, -ou un item actuellement porté. - -Donc conceptuellement, la fenêtre d’inspection est le meilleur endroit : -plus logique pour l’utilisateur ; -plus lisible ; -moins ambigu ; -plus proche du modèle métier. - -Est-ce que l’addon actuel est déjà prêt pour ça ? -Partiellement oui, mais pas complètement -Ce qui existe déjà : -l’addon sait ouvrir une inspection ; -l’addon sait envoyer des commandes whisper à un bot ; -l’addon a déjà des représentations de slots d’équipement dans d’autres zones du code. - -Ce qui manque encore : -une action UI dédiée “unequip” dans la vue d’inspection ; -un mapping propre entre slot UI et payload ue ; -et probablement un refresh fiable après l’action. - -Le point technique le plus important à ne pas oublier -Le refresh après ue -Aujourd’hui, le handler refresh l’inventaire lorsqu’il détecte des messages du bot du genre : -equipping -using -destroyed -etc. - -Donc si la commande ue renvoie un message différent, par exemple : -unequipping -removed -taking off -ou autre -alors il faudra penser à raccrocher ce retour au refresh. -Sinon l’action pourra marcher côté bot, mais l’UI ne se resynchronisera pas proprement. - -C’est probablement le principal piège de cette feature. - -UX recommandé -Je verrais plutôt : - -Option 1 — clic droit sur slot équipé -Très naturel : -clic gauche = comportement standard / tooltip ; -clic droit = ue sur le slot. - -Option 2 — mode “Unequip” -Comme dans INVENTORY avec les modes d’action : -tu actives “Unequip” ; -puis tu cliques un slot inspecté. -C’est cohérent avec la philosophie existante de MultiBot, mais probablement un peu plus lourd que nécessaire. - -Option 3 — petit bouton contextuel / menu sur slot -Plus explicite, mais visuellement plus chargé. -Mon avis -Le clic droit sur le slot équipé est probablement la meilleure UX : -rapide, -lisible, -très cohérent avec une frame d’inspection. - -Au final -Condition indispensable -Il faut juste confirmer précisément : -la syntaxe réelle de ue, -si elle cible un slot ou un item, -quel message de retour elle produit, pour rebrancher le refresh. -Si ces 3 points sont clairs, alors oui, ça vaut complètement le coup de l’exposer graphiquement dans l’inspection d’un bot. - - +* Menu misc: faire en sorte que les barres horizontales des autres bots se ferment et que le menu se referme après avoir selectionné une action et que quand ce menu se referme toutes les barres de réouvrent. +* faite aussi ceci pour tout les menus deroulants de la every barre \ No newline at end of file diff --git a/UI/MultiBotInventoryItem.lua b/UI/MultiBotInventoryItem.lua index dd94cf3..746f62a 100644 --- a/UI/MultiBotInventoryItem.lua +++ b/UI/MultiBotInventoryItem.lua @@ -78,7 +78,7 @@ local function buildInventoryItemRecord(itemInfo) end local itemIcon = GetItemIcon(itemId) - local itemName, itemLink, itemRare = GetItemInfo(itemId) + local itemName, itemLink, itemRare, _, _, itemType, itemSubType, _, _, _, _, itemClassId = GetItemInfo(itemId) return { id = itemId, @@ -86,6 +86,9 @@ local function buildInventoryItemRecord(itemInfo) name = resolveInventoryItemName(parts, itemName), link = resolveInventoryItemLink(parts, itemLink), rare = resolveInventoryItemRarity(itemRare), + itemType = itemType, + itemSubType = itemSubType, + itemClassId = itemClassId, count = extractInventoryItemCount(parts), info = itemInfo, parts = parts, @@ -139,6 +142,96 @@ local function isInventoryProtectedHearthstone(item) return item and item.id == "6948" end +local inventorySellGuardTooltipName = "MB_InventorySellGuardTooltip" +local function getInventorySellGuardTooltip() + if MultiBot.AceUI and MultiBot.AceUI.EnsureHiddenTooltip then + return MultiBot.AceUI.EnsureHiddenTooltip(inventorySellGuardTooltipName, UIParent) + end + + local tooltip = _G[inventorySellGuardTooltipName] + if tooltip then + return tooltip + end + + tooltip = CreateFrame("GameTooltip", inventorySellGuardTooltipName, UIParent, "GameTooltipTemplate") + tooltip:SetOwner(UIParent, "ANCHOR_NONE") + return tooltip +end + +local function tooltipContainsQuestHint(itemLink) + if type(itemLink) ~= "string" or itemLink == "" then + return false + end + + local tooltip = getInventorySellGuardTooltip() + if not tooltip then + return false + end + + tooltip:ClearLines() + tooltip:SetHyperlink(itemLink) + + local questMarkers = { + ITEM_STARTS_QUEST, + QUESTS_LABEL, + TRACKER_HEADER_QUESTS, + "Quest", + "Quête", + "任务", + "퀘스트", + } + + for lineIndex = 1, 12 do + local line = _G[inventorySellGuardTooltipName .. "TextLeft" .. lineIndex] + local text = line and line.GetText and line:GetText() or nil + if text and text ~= "" then + for _, marker in ipairs(questMarkers) do + if type(marker) == "string" and marker ~= "" and string.find(text, marker, 1, true) then + return true + end + end + end + end + + return false +end + +local function isInventoryQuestType(item) + if not item then + return false + end + + local itemType = tostring(item.itemType or "") + local questTypeTokens = { + QUESTS_LABEL, + TRACKER_HEADER_QUESTS, + "Quest", + "Quête", + "任务", + "퀘스트", + } + + for _, token in ipairs(questTypeTokens) do + if type(token) == "string" and token ~= "" and itemType == token then + return true + end + end + + return false +end + +local function isInventoryProtectedQuestItem(item) + if not item then + return false + end + + if isInventoryQuestType(item) then + return true + end + + return tooltipContainsQuestHint(item.link) +end + local function needsInventoryDestroyConfirmation(item) return isInventoryProtectedHearthstone(item) or isInventoryProtectedKey(item) @@ -196,6 +289,11 @@ local function handleInventoryItemClick(button) return end + if isInventoryProtectedQuestItem(item) then + sendInventoryFeedback("itemsellalert", "I will not sell quest items.") + return + end + sendInventoryItemCommand(action, button, botName, { hideButton = true, refreshDelay = 0.3, From 3b8292b0551162c8aa713fa5250b243655d695d8 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Fri, 3 Apr 2026 17:17:07 +0100 Subject: [PATCH 2/6] Add collaps desactivation option --- .luacheckrc | 2 +- Core/MultiBotConfig.lua | 25 ++++++++++++++++++++++ Core/MultiBotEngine.lua | 6 ++++++ Locales/MultiBotAceLocale-deDE.lua | 2 ++ Locales/MultiBotAceLocale-enGB.lua | 2 ++ Locales/MultiBotAceLocale-enUS.lua | 2 ++ Locales/MultiBotAceLocale-esES.lua | 2 ++ Locales/MultiBotAceLocale-frFR.lua | 2 ++ Locales/MultiBotAceLocale-koKR.lua | 2 ++ Locales/MultiBotAceLocale-ruRU.lua | 2 ++ Locales/MultiBotAceLocale-zhCN.lua | 2 ++ TODO.md | 2 +- UI/MultiBotOptions.lua | 33 ++++++++++++++++++++++++++++-- 13 files changed, 80 insertions(+), 4 deletions(-) diff --git a/.luacheckrc b/.luacheckrc index 160778e..5312ea9 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -36,7 +36,7 @@ globals = { "TooltipBackdropTemplateMixin", "NORMAL_FONT_COLOR", "HIGHLIGHT_FONT_COLOR", "GameTooltip_SetDefaultAnchor", "ChatFrame1", "UISpecialFrames", "GetMouseFocus", "ShowUIPanel", "tremove", "min", "max", "GetMinimapShape", "GetMinimapShape", "PanelTemplates_TabResize", "GetGuildRosterShowOffline", "SetGuildRosterShowOffline", "IsInGuild", "GetGuildInfo", "SetGuildRosterShowOffline", "PLAYER", "INVENTORY_TOOLTIP", "BAGSLOT", "UNKNOWN", "UnitIsDead", "ShowPrompt", "_MB_GetOrCreateShamanPos", "ensureHiddenTooltip", "MB_TAB_TITLE_DEFAULT", "SPELLBOOK", "MB_PAGE_DEFAULT", "SPELLBOOK_END_NON_SPELL_STREAK", "sendInventoryItemCommand", - "RAID_CLASS_COLORS", "INSPECT", "MB_INVENTORY_LABEL", "LOADING", "ITEM", "ITEMS", "SEARCH", "NO_QUESTS_LABEL", "QUESTS_LABEL", "QUEST_LOG", "UnitIsUnit" + "RAID_CLASS_COLORS", "INSPECT", "MB_INVENTORY_LABEL", "LOADING", "ITEM", "ITEMS", "SEARCH", "NO_QUESTS_LABEL", "QUESTS_LABEL", "QUEST_LOG", "UnitIsUnit", "ITEM_STARTS_QUEST", "TRACKER_HEADER_QUESTS" } read_globals = { diff --git a/Core/MultiBotConfig.lua b/Core/MultiBotConfig.lua index 840778f..8044f7c 100644 --- a/Core/MultiBotConfig.lua +++ b/Core/MultiBotConfig.lua @@ -20,6 +20,7 @@ local THROTTLE_DEFAULTS = { local UI_DEFAULTS = { mainBar = { moveLocked = true, + disableAutoCollapse = false, }, } @@ -79,6 +80,9 @@ local function migrateLegacyConfigIntoProfile(profile) if type(profile.ui.mainBar.moveLocked) ~= "boolean" then profile.ui.mainBar.moveLocked = UI_DEFAULTS.mainBar.moveLocked end + if type(profile.ui.mainBar.disableAutoCollapse) ~= "boolean" then + profile.ui.mainBar.disableAutoCollapse = UI_DEFAULTS.mainBar.disableAutoCollapse + end end local function getConfigStore(createIfMissing) @@ -140,6 +144,9 @@ function MultiBot.Config_Ensure() if type(config.ui.mainBar.moveLocked) ~= "boolean" then config.ui.mainBar.moveLocked = UI_DEFAULTS.mainBar.moveLocked end + if type(config.ui.mainBar.disableAutoCollapse) ~= "boolean" then + config.ui.mainBar.disableAutoCollapse = UI_DEFAULTS.mainBar.disableAutoCollapse + end end -- Copy saved values into runtime timers. @@ -252,4 +259,22 @@ function MultiBot.SetMainBarMoveLocked(value) config.ui.mainBar = config.ui.mainBar or {} config.ui.mainBar.moveLocked = value and true or false return config.ui.mainBar.moveLocked +end + +function MultiBot.GetDisableAutoCollapse() + local config = getConfigStore(false) + local value = config and config.ui and config.ui.mainBar and config.ui.mainBar.disableAutoCollapse + if type(value) == "boolean" then + return value + end + + return UI_DEFAULTS.mainBar.disableAutoCollapse +end + +function MultiBot.SetDisableAutoCollapse(value) + local config = getConfigStore(true) + config.ui = config.ui or {} + config.ui.mainBar = config.ui.mainBar or {} + config.ui.mainBar.disableAutoCollapse = value and true or false + return config.ui.mainBar.disableAutoCollapse end \ No newline at end of file diff --git a/Core/MultiBotEngine.lua b/Core/MultiBotEngine.lua index c8cb857..2262618 100644 --- a/Core/MultiBotEngine.lua +++ b/Core/MultiBotEngine.lua @@ -605,6 +605,12 @@ MultiBot.CollapseOtherUnitBarsForDropdown = function(targetFrame) return end + if MultiBot.GetDisableAutoCollapse and MultiBot.GetDisableAutoCollapse() then + targetFrame._mbDropdownManaged = nil + targetFrame._mbCollapsedBars = nil + return + end + local unitsFrame = MultiBot.frames and MultiBot.frames["MultiBar"] and MultiBot.frames["MultiBar"].frames diff --git a/Locales/MultiBotAceLocale-deDE.lua b/Locales/MultiBotAceLocale-deDE.lua index 6eae9e8..cd12913 100644 --- a/Locales/MultiBotAceLocale-deDE.lua +++ b/Locales/MultiBotAceLocale-deDE.lua @@ -197,6 +197,8 @@ local deDEValues = { ["options.minimap.explainer"] = "Blendet den MultiBot-Minimap-Button ein oder aus.", ["options.layout.lock_mainbar"] = "Bewegung der Hauptleiste sperren", ["options.layout.lock_mainbar_desc"] = "Aktiviert: Strg + Rechtsklick zum Verschieben der Leiste. Deaktiviert: Rechtsklick genügt.", + ["options.layout.disable_autocollapse"] = "Automatisches Einklappen für Bot-Leisten deaktivieren", + ["options.layout.disable_autocollapse_desc"] = "Aktiviert: Das Öffnen von Bot-Untermenüs klappt andere Bot-Leisten nicht ein.", ["options.layout.owner_import"] = "Spieler-Layout zum Importieren", ["options.layout.export"] = "Layout exportieren", ["options.layout.import"] = "Layout importieren", diff --git a/Locales/MultiBotAceLocale-enGB.lua b/Locales/MultiBotAceLocale-enGB.lua index 890e77c..ffc1152 100644 --- a/Locales/MultiBotAceLocale-enGB.lua +++ b/Locales/MultiBotAceLocale-enGB.lua @@ -199,6 +199,8 @@ local enGBValues = { ["options.minimap.explainer"] = "Hide or show the MultiBot minimap button.", ["options.layout.lock_mainbar"] = "Lock main bar movement", ["options.layout.lock_mainbar_desc"] = "Checked: Ctrl + right-click to move the bar. Unchecked: right-click is enough.", + ["options.layout.disable_autocollapse"] = "Disable auto-collapse for bot bars", + ["options.layout.disable_autocollapse_desc"] = "Checked: opening bot submenus will not collapse other bot bars.", ["options.layout.owner_import"] = "Player layout to import", ["options.layout.export"] = "Export layout", ["options.layout.import"] = "Import layout", diff --git a/Locales/MultiBotAceLocale-enUS.lua b/Locales/MultiBotAceLocale-enUS.lua index a2f6619..2f68b86 100644 --- a/Locales/MultiBotAceLocale-enUS.lua +++ b/Locales/MultiBotAceLocale-enUS.lua @@ -199,6 +199,8 @@ local enUSValues = { ["options.minimap.explainer"] = "Hide or show the MultiBot minimap button.", ["options.layout.lock_mainbar"] = "Lock main bar movement", ["options.layout.lock_mainbar_desc"] = "Checked: Ctrl + right-click to move the bar. Unchecked: right-click is enough.", + ["options.layout.disable_autocollapse"] = "Disable auto-collapse for bot bars", + ["options.layout.disable_autocollapse_desc"] = "Checked: opening bot submenus will not collapse other bot bars.", ["options.layout.owner_import"] = "Player layout to import", ["options.layout.export"] = "Export layout", ["options.layout.import"] = "Import layout", diff --git a/Locales/MultiBotAceLocale-esES.lua b/Locales/MultiBotAceLocale-esES.lua index 892ca76..2b8269d 100644 --- a/Locales/MultiBotAceLocale-esES.lua +++ b/Locales/MultiBotAceLocale-esES.lua @@ -197,6 +197,8 @@ local esESValues = { ["options.minimap.explainer"] = "Muestra u oculta el botón del minimapa de MultiBot.", ["options.layout.lock_mainbar"] = "Bloquear movimiento de la barra principal", ["options.layout.lock_mainbar_desc"] = "Marcado: Ctrl + clic derecho para mover la barra. Desmarcado: clic derecho suficiente.", + ["options.layout.disable_autocollapse"] = "Desactivar el auto-colapso de las barras de bots", + ["options.layout.disable_autocollapse_desc"] = "Marcado: al abrir submenús de bots no se colapsarán otras barras de bots.", ["options.layout.owner_import"] = "Layout de jugador para importar", ["options.layout.export"] = "Exportar diseño", ["options.layout.import"] = "Importar diseño", diff --git a/Locales/MultiBotAceLocale-frFR.lua b/Locales/MultiBotAceLocale-frFR.lua index 3a51071..062de53 100644 --- a/Locales/MultiBotAceLocale-frFR.lua +++ b/Locales/MultiBotAceLocale-frFR.lua @@ -197,6 +197,8 @@ local frFRValues = { ["options.minimap.explainer"] = "Affiche ou masque le bouton minimap de MultiBot.", ["options.layout.lock_mainbar"] = "Verrouiller déplacement barre principale", ["options.layout.lock_mainbar_desc"] = "Coché : Ctrl + clic droit pour déplacer la barre. Décoché : clic droit suffit.", + ["options.layout.disable_autocollapse"] = "Désactiver l'auto-repli des barres bots", + ["options.layout.disable_autocollapse_desc"] = "Coché : l'ouverture d'un sous-menu bot ne replie plus les autres barres bots.", ["options.layout.owner_import"] = "Layout joueur à importer", ["options.layout.export"] = "Exporter le layout", ["options.layout.import"] = "Importer le layout", diff --git a/Locales/MultiBotAceLocale-koKR.lua b/Locales/MultiBotAceLocale-koKR.lua index bf1de3e..6d5a5e5 100644 --- a/Locales/MultiBotAceLocale-koKR.lua +++ b/Locales/MultiBotAceLocale-koKR.lua @@ -196,6 +196,8 @@ local koKRValues = { ["options.minimap.explainer"] = "MultiBot 미니맵 버튼을 숨기거나 표시합니다.", ["options.layout.lock_mainbar"] = "기본 바 이동 잠금", ["options.layout.lock_mainbar_desc"] = "체크: Ctrl + 우클릭으로 바 이동. 해제: 우클릭만으로 이동.", + ["options.layout.disable_autocollapse"] = "봇 바 자동 접기 비활성화", + ["options.layout.disable_autocollapse_desc"] = "선택 시: 봇 하위 메뉴를 열어도 다른 봇 바가 접히지 않습니다.", ["options.layout.owner_import"] = "가져올 플레이어 레이아웃", ["options.layout.export"] = "레이아웃 내보내기", ["options.layout.import"] = "레이아웃 가져오기", diff --git a/Locales/MultiBotAceLocale-ruRU.lua b/Locales/MultiBotAceLocale-ruRU.lua index 0ee35ed..92dbfbb 100644 --- a/Locales/MultiBotAceLocale-ruRU.lua +++ b/Locales/MultiBotAceLocale-ruRU.lua @@ -197,6 +197,8 @@ local ruRUValues = { ["options.minimap.explainer"] = "Скрывает или показывает кнопку миникарты MultiBot.", ["options.layout.lock_mainbar"] = "Заблокировать перемещение главной панели", ["options.layout.lock_mainbar_desc"] = "Включено: Ctrl + ПКМ для перемещения панели. Выключено: достаточно ПКМ.", + ["options.layout.disable_autocollapse"] = "Отключить авто-сворачивание панелей ботов", + ["options.layout.disable_autocollapse_desc"] = "Включено: при открытии подменю ботов другие панели ботов не будут сворачиваться.", ["options.layout.owner_import"] = "Макет игрока для импорта", ["options.layout.export"] = "Экспорт макета", ["options.layout.import"] = "Импорт макета", diff --git a/Locales/MultiBotAceLocale-zhCN.lua b/Locales/MultiBotAceLocale-zhCN.lua index 10b8d8d..9d11035 100644 --- a/Locales/MultiBotAceLocale-zhCN.lua +++ b/Locales/MultiBotAceLocale-zhCN.lua @@ -197,6 +197,8 @@ local zhCNValues = { ["options.minimap.explainer"] = "显示或隐藏 MultiBot 小地图按钮。", ["options.layout.lock_mainbar"] = "锁定主动作条移动", ["options.layout.lock_mainbar_desc"] = "勾选:Ctrl + 右键拖动动作条。取消勾选:仅右键即可。", + ["options.layout.disable_autocollapse"] = "禁用机器人栏的自动折叠", + ["options.layout.disable_autocollapse_desc"] = "勾选:打开机器人子菜单时不会折叠其他机器人栏。", ["options.layout.owner_import"] = "要导入的玩家布局", ["options.layout.export"] = "导出布局", ["options.layout.import"] = "导入布局", diff --git a/TODO.md b/TODO.md index b8eeaf9..84783d4 100644 --- a/TODO.md +++ b/TODO.md @@ -14,4 +14,4 @@ TODO * Finir les options de déplacement des boutons * Debuguer le blocage de la barre principale en déplacement ça a l'air de ne pas persister apres une deco reco * Menu misc: faire en sorte que les barres horizontales des autres bots se ferment et que le menu se referme après avoir selectionné une action et que quand ce menu se referme toutes les barres de réouvrent. -* faite aussi ceci pour tout les menus deroulants de la every barre \ No newline at end of file +* faite aussi ceci pour tout les menus deroulants de la every main \ No newline at end of file diff --git a/UI/MultiBotOptions.lua b/UI/MultiBotOptions.lua index ee671a1..d21f15a 100644 --- a/UI/MultiBotOptions.lua +++ b/UI/MultiBotOptions.lua @@ -153,7 +153,8 @@ local function buildLegacyOptionsContent(panel) local minimapConfig = MultiBot.GetMinimapConfig and MultiBot.GetMinimapConfig() or { hide = false } local mainBarMoveLocked = MultiBot.GetMainBarMoveLocked and MultiBot.GetMainBarMoveLocked() or true - + local disableAutoCollapse = MultiBot.GetDisableAutoCollapse and MultiBot.GetDisableAutoCollapse() or false + local strataDropDown = CreateFrame("Frame", "MultiBotStrataDropDown", scrollChild, "UIDropDownMenuTemplate") local chkMinimapHide = CreateFrame("CheckButton", "MultiBot_MinimapHideCheck", scrollChild, "InterfaceOptionsCheckButtonTemplate") @@ -187,15 +188,27 @@ local function buildLegacyOptionsContent(panel) end end) + local chkDisableAutoCollapse = CreateFrame("CheckButton", "MultiBot_DisableAutoCollapseCheck", scrollChild, "InterfaceOptionsCheckButtonTemplate") + chkDisableAutoCollapse:SetPoint("TOPLEFT", chkMainBarMoveLocked, "BOTTOMLEFT", 0, -8) + _G[chkDisableAutoCollapse:GetName() .. "Text"]:SetText(optL("options.layout.disable_autocollapse")) + chkDisableAutoCollapse.tooltipText = optL("options.layout.disable_autocollapse_desc") + chkDisableAutoCollapse:SetChecked(disableAutoCollapse and true or false) + chkDisableAutoCollapse:SetScript("OnClick", function(btn) + if MultiBot.SetDisableAutoCollapse then + MultiBot.SetDisableAutoCollapse(btn:GetChecked() and true or false) + end + end) + panel.chkMinimapHide = chkMinimapHide panel.chkMainBarMoveLocked = chkMainBarMoveLocked + panel.chkDisableAutoCollapse = chkDisableAutoCollapse local selectedOwnerKey = nil local refreshOwnerDropdown local exportBtn = CreateFrame("Button", nil, scrollChild, "UIPanelButtonTemplate") exportBtn:SetSize(110, 22) - exportBtn:SetPoint("TOPLEFT", chkMainBarMoveLocked, "BOTTOMLEFT", 0, -14) + exportBtn:SetPoint("TOPLEFT", chkDisableAutoCollapse, "BOTTOMLEFT", 0, -14) exportBtn:SetText(optL("options.layout.export")) exportBtn:SetScript("OnClick", function() if MultiBot.SaveMainBarLayoutForCurrentPlayer then @@ -516,6 +529,7 @@ function MultiBot.BuildOptionsPanel() local function buildLayoutTab(tabGroup) local scroll = addTabScroll(tabGroup) local mainBarMoveLocked = MultiBot.GetMainBarMoveLocked and MultiBot.GetMainBarMoveLocked() or true + local disableAutoCollapse = MultiBot.GetDisableAutoCollapse and MultiBot.GetDisableAutoCollapse() or false local chkMainBarMoveLocked = AceGUI:Create("CheckBox") chkMainBarMoveLocked:SetLabel(mainBarMoveLockLabel) @@ -532,6 +546,21 @@ function MultiBot.BuildOptionsPanel() scroll:AddChild(chkMainBarMoveLocked) panel.chkMainBarMoveLocked = chkMainBarMoveLocked + local chkDisableAutoCollapse = AceGUI:Create("CheckBox") + chkDisableAutoCollapse:SetLabel(optL("options.layout.disable_autocollapse")) + if chkDisableAutoCollapse.SetDescription then + chkDisableAutoCollapse:SetDescription(optL("options.layout.disable_autocollapse_desc")) + end + chkDisableAutoCollapse:SetValue(disableAutoCollapse and true or false) + chkDisableAutoCollapse:SetFullWidth(true) + chkDisableAutoCollapse:SetCallback("OnValueChanged", function(_, _, value) + if MultiBot.SetDisableAutoCollapse then + MultiBot.SetDisableAutoCollapse(value and true or false) + end + end) + scroll:AddChild(chkDisableAutoCollapse) + panel.chkDisableAutoCollapse = chkDisableAutoCollapse + local ownerTitle = AceGUI:Create("Label") ownerTitle:SetFullWidth(true) ownerTitle:SetText(layoutOwnerLabel) From ba42876645d73102810bb4e7af50d613d05d65d8 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Fri, 3 Apr 2026 17:28:58 +0100 Subject: [PATCH 3/6] Add autocollaps to quest menu --- Locales/MultiBotAceLocale-enGB.lua | 2 +- UI/MultiBotOptions.lua | 2 +- UI/MultiBotQuestsMenu.lua | 69 +++++++++++++++++++++++++----- 3 files changed, 61 insertions(+), 12 deletions(-) diff --git a/Locales/MultiBotAceLocale-enGB.lua b/Locales/MultiBotAceLocale-enGB.lua index ffc1152..a9187fb 100644 --- a/Locales/MultiBotAceLocale-enGB.lua +++ b/Locales/MultiBotAceLocale-enGB.lua @@ -200,7 +200,7 @@ local enGBValues = { ["options.layout.lock_mainbar"] = "Lock main bar movement", ["options.layout.lock_mainbar_desc"] = "Checked: Ctrl + right-click to move the bar. Unchecked: right-click is enough.", ["options.layout.disable_autocollapse"] = "Disable auto-collapse for bot bars", - ["options.layout.disable_autocollapse_desc"] = "Checked: opening bot submenus will not collapse other bot bars.", + ["options.layout.disable_autocollapse_desc"] = "Checked: opening bot submenus will not collapse other bot bars.", ["options.layout.owner_import"] = "Player layout to import", ["options.layout.export"] = "Export layout", ["options.layout.import"] = "Import layout", diff --git a/UI/MultiBotOptions.lua b/UI/MultiBotOptions.lua index d21f15a..4809434 100644 --- a/UI/MultiBotOptions.lua +++ b/UI/MultiBotOptions.lua @@ -154,7 +154,7 @@ local function buildLegacyOptionsContent(panel) local minimapConfig = MultiBot.GetMinimapConfig and MultiBot.GetMinimapConfig() or { hide = false } local mainBarMoveLocked = MultiBot.GetMainBarMoveLocked and MultiBot.GetMainBarMoveLocked() or true local disableAutoCollapse = MultiBot.GetDisableAutoCollapse and MultiBot.GetDisableAutoCollapse() or false - + local strataDropDown = CreateFrame("Frame", "MultiBotStrataDropDown", scrollChild, "UIDropDownMenuTemplate") local chkMinimapHide = CreateFrame("CheckButton", "MultiBot_MinimapHideCheck", scrollChild, "InterfaceOptionsCheckButtonTemplate") diff --git a/UI/MultiBotQuestsMenu.lua b/UI/MultiBotQuestsMenu.lua index 1fd708e..77a45d2 100644 --- a/UI/MultiBotQuestsMenu.lua +++ b/UI/MultiBotQuestsMenu.lua @@ -3,15 +3,63 @@ if not MultiBot then return end local QuestsMenu = MultiBot.QuestsMenu or {} MultiBot.QuestsMenu = QuestsMenu -local function toggleButtons(buttonA, buttonB) - if buttonA:IsShown() then - buttonA:doHide() - buttonB:doHide() +local function setSubButtonsVisible(buttonA, buttonB, visible) + if visible then + buttonA:doShow() + buttonB:doShow() return end - buttonA:doShow() - buttonB:doShow() + buttonA:doHide() + buttonB:doHide() +end + +local function shouldAutoCollapseQuestGroups() + if MultiBot.GetDisableAutoCollapse then + return not MultiBot.GetDisableAutoCollapse() + end + return true +end + +local function collapseOtherQuestGroups(activeGroup) + if not shouldAutoCollapseQuestGroups() then + return + end + + local groups = QuestsMenu.expandableGroups + if type(groups) ~= "table" then + return + end + + for index = 1, #groups do + local group = groups[index] + if group ~= activeGroup then + setSubButtonsVisible(group.buttonA, group.buttonB, false) + end + end +end + +local function registerExpandableGroup(rootButton, buttonA, buttonB) + QuestsMenu.expandableGroups = QuestsMenu.expandableGroups or {} + local group = { + root = rootButton, + buttonA = buttonA, + buttonB = buttonB, + } + table.insert(QuestsMenu.expandableGroups, group) + + rootButton.doLeft = function() + local isOpen = buttonA:IsShown() or buttonB:IsShown() + if isOpen then + setSubButtonsVisible(buttonA, buttonB, false) + return + end + + collapseOtherQuestGroups(group) + setSubButtonsVisible(buttonA, buttonB, true) + end + + return group end local function sendIncomplete(method) @@ -133,6 +181,7 @@ function MultiBot.InitializeQuestsMenu(tRight) local button = tRight.addButton("Quests Menu", 0, 0, "achievement_quests_completed_06", MultiBot.L("tips.quests.main")) local menu = tRight.addFrame("QuestMenu", -2, 64) menu:Hide() + QuestsMenu.expandableGroups = {} button.doLeft = function(owner) MultiBot.ShowHideSwitch(owner.parent.frames["QuestMenu"]) @@ -161,7 +210,7 @@ function MultiBot.InitializeQuestsMenu(tRight) local incompWhisper = menu.addButton("BotQuestsIncompWhisper", 61, 90, "Interface\\Icons\\INV_Crate_08", MultiBot.L("tips.quests.sendwhisp")) incompGroup:doHide() incompWhisper:doHide() - incompButton.doLeft = function() toggleButtons(incompGroup, incompWhisper) end + registerExpandableGroup(incompButton, incompGroup, incompWhisper) incompGroup.doLeft = function() sendIncomplete("GROUP") end incompWhisper.doLeft = function() sendIncomplete("WHISPER") end tRight.buttons["BotQuestsIncomp"] = incompButton @@ -173,7 +222,7 @@ function MultiBot.InitializeQuestsMenu(tRight) local completedWhisper = menu.addButton("BotQuestsCompWhisper", 61, 60, "Interface\\Icons\\INV_Crate_09", MultiBot.L("tips.quests.sendwhisp")) completedGroup:doHide() completedWhisper:doHide() - completedButton.doLeft = function() toggleButtons(completedGroup, completedWhisper) end + registerExpandableGroup(completedButton, completedGroup, completedWhisper) completedGroup.doLeft = function() sendCompleted("GROUP") end completedWhisper.doLeft = function() sendCompleted("WHISPER") end tRight.buttons["BotQuestsComp"] = completedButton @@ -195,7 +244,7 @@ function MultiBot.InitializeQuestsMenu(tRight) local allWhisper = menu.addButton("BotQuestsAllWhisper", 61, 120, "Interface\\Icons\\INV_Misc_Book_09", MultiBot.L("tips.quests.sendwhisp")) allGroup:doHide() allWhisper:doHide() - allButton.doLeft = function() toggleButtons(allGroup, allWhisper) end + registerExpandableGroup(allButton, allGroup, allWhisper) allGroup.doLeft = function() sendAll("GROUP") end allWhisper.doLeft = function() sendAll("WHISPER") end tRight.buttons["BotQuestsAll"] = allButton @@ -207,7 +256,7 @@ function MultiBot.InitializeQuestsMenu(tRight) local gobSearchButton = menu.addButton("BotUseGOBSearch", 61, 150, "Interface\\Icons\\inv_misc_spyglass_02", MultiBot.L("tips.quests.gobsearch")) gobNameButton:doHide() gobSearchButton:doHide() - gobButton.doLeft = function() toggleButtons(gobNameButton, gobSearchButton) end + registerExpandableGroup(gobButton, gobNameButton, gobSearchButton) gobNameButton.doLeft = function() if not ShowPrompt then return From c86d8b4b5fd73c0fc993459ba46932ba56fa65b5 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Fri, 3 Apr 2026 17:39:42 +0100 Subject: [PATCH 4/6] 1mainbare lock fixe --- Core/MultiBotConfig.lua | 3 +++ TODO.md | 3 ++- UI/MultiBotMainUI.lua | 31 +++++++++++++++++-------------- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/Core/MultiBotConfig.lua b/Core/MultiBotConfig.lua index 8044f7c..0992846 100644 --- a/Core/MultiBotConfig.lua +++ b/Core/MultiBotConfig.lua @@ -258,6 +258,9 @@ function MultiBot.SetMainBarMoveLocked(value) config.ui = config.ui or {} config.ui.mainBar = config.ui.mainBar or {} config.ui.mainBar.moveLocked = value and true or false + if MultiBot.ApplyMainBarMoveLockState then + MultiBot.ApplyMainBarMoveLockState(config.ui.mainBar.moveLocked) + end return config.ui.mainBar.moveLocked end diff --git a/TODO.md b/TODO.md index 84783d4..d5d5c0d 100644 --- a/TODO.md +++ b/TODO.md @@ -14,4 +14,5 @@ TODO * Finir les options de déplacement des boutons * Debuguer le blocage de la barre principale en déplacement ça a l'air de ne pas persister apres une deco reco * Menu misc: faire en sorte que les barres horizontales des autres bots se ferment et que le menu se referme après avoir selectionné une action et que quand ce menu se referme toutes les barres de réouvrent. -* faite aussi ceci pour tout les menus deroulants de la every main \ No newline at end of file +* faite aussi ceci pour tout les menus deroulants de la every main +* probleme avec la vente des objets de quete, on arrive quand même à le vendre et il réapparait dans le sac, normallement je devrais avoir un message comme avec les clés, que je ne peux pas vendre. \ No newline at end of file diff --git a/UI/MultiBotMainUI.lua b/UI/MultiBotMainUI.lua index 318916b..cf811ae 100644 --- a/UI/MultiBotMainUI.lua +++ b/UI/MultiBotMainUI.lua @@ -315,19 +315,6 @@ local function createMainActionButton(mainFrame, definition) return button end -local function isMainBarMoveAllowed() - local moveLocked = MultiBot.GetMainBarMoveLocked and MultiBot.GetMainBarMoveLocked() - if moveLocked == nil then - moveLocked = true - end - - if moveLocked then - return IsControlKeyDown() - end - - return true -end - local function saveMultiBarPosition() local multiBar = MultiBot.frames and MultiBot.frames["MultiBar"] if not multiBar or not MultiBot.SetSavedLayoutValue or not MultiBot.toPoint then @@ -410,8 +397,24 @@ function MultiBot.InitializeMainUI(tMultiBar) local mainButton = tMultiBar.addButton(MAIN_BUTTON_NAME, 0, 0, MAIN_BUTTON_ICON, MultiBot.L("tips.main.master")) mainButton:RegisterForDrag("RightButton") + + local function applyMoveLockState(moveLocked) + local locked = moveLocked + if locked == nil and MultiBot.GetMainBarMoveLocked then + locked = MultiBot.GetMainBarMoveLocked() + end + if locked == nil then + locked = true + end + mainButton.__mbMoveLocked = locked and true or false + end + + MultiBot.ApplyMainBarMoveLockState = applyMoveLockState + applyMoveLockState() + mainButton:SetScript("OnDragStart", function() - if not isMainBarMoveAllowed() then + local moveLocked = mainButton.__mbMoveLocked + if moveLocked and not IsControlKeyDown() then if UIErrorsFrame then UIErrorsFrame:AddMessage(MultiBot.L("mainbar.swap.locked"), 1, 0.25, 0.25, 1) end From 26b4e3c26479ebbbf4f3bc503d916f52c3362b62 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Fri, 3 Apr 2026 18:38:41 +0100 Subject: [PATCH 5/6] Bugs correction --- Locales/MultiBotAceLocale-deDE.lua | 1 + Locales/MultiBotAceLocale-enGB.lua | 1 + Locales/MultiBotAceLocale-enUS.lua | 1 + Locales/MultiBotAceLocale-esES.lua | 1 + Locales/MultiBotAceLocale-frFR.lua | 1 + Locales/MultiBotAceLocale-koKR.lua | 1 + Locales/MultiBotAceLocale-ruRU.lua | 1 + Locales/MultiBotAceLocale-zhCN.lua | 1 + TODO.md | 8 +-- UI/MultiBotInventoryFrame.lua | 70 +++++++++++++++++- UI/MultiBotInventoryItem.lua | 109 ++++++----------------------- 11 files changed, 98 insertions(+), 97 deletions(-) diff --git a/Locales/MultiBotAceLocale-deDE.lua b/Locales/MultiBotAceLocale-deDE.lua index cd12913..503b9dd 100644 --- a/Locales/MultiBotAceLocale-deDE.lua +++ b/Locales/MultiBotAceLocale-deDE.lua @@ -7,6 +7,7 @@ local deDEValues = { ["info.itemdestroyalert"] = "Möchtest du diesen Gegenstand WIRKLICH zerstören?\n%s", ["info.keydestroyalert"] = "Ich verkaufe keine Schlüssel.", ["info.itemsellalert"] = "Ich kann diesen Gegenstand nicht verkaufen.", + ["info.questitemsellalert"] = "Ich kann Questgegenstände nicht verkaufen.", ["info.inventoryvendortarget"] = "Sie müssen zuerst einen Händler auswählen.", ["info.butttitle"] = "|cffffd100MultiBot|r", ["info.buttontoggle"] = "|cff00ff00Linksklick: UI umschalten|r", diff --git a/Locales/MultiBotAceLocale-enGB.lua b/Locales/MultiBotAceLocale-enGB.lua index a9187fb..af1a002 100644 --- a/Locales/MultiBotAceLocale-enGB.lua +++ b/Locales/MultiBotAceLocale-enGB.lua @@ -7,6 +7,7 @@ local enGBValues = { ["info.itemdestroyalert"] = "Do you REALLY want to destroy this item?\n%s", ["info.keydestroyalert"] = "I will not sell Keys.", ["info.itemsellalert"] = "I cant sell this Item.", + ["info.questitemsellalert"] = "I cannot sell quest items.", ["info.inventoryvendortarget"] = "You must select a vendor first.", ["info.butttitle"] = "|cffffd100MultiBot|r", ["info.buttontoggle"] = "|cff00ff00Left-click: toggle UI|r", diff --git a/Locales/MultiBotAceLocale-enUS.lua b/Locales/MultiBotAceLocale-enUS.lua index 2f68b86..878936f 100644 --- a/Locales/MultiBotAceLocale-enUS.lua +++ b/Locales/MultiBotAceLocale-enUS.lua @@ -7,6 +7,7 @@ local enUSValues = { ["info.itemdestroyalert"] = "Do you REALLY want to destroy this item?\n%s", ["info.keydestroyalert"] = "I will not sell Keys.", ["info.itemsellalert"] = "I cant sell this Item.", + ["info.questitemsellalert"] = "I cannot sell quest items.", ["info.inventoryvendortarget"] = "You must select a vendor first.", ["info.butttitle"] = "|cffffd100MultiBot|r", ["info.buttontoggle"] = "|cff00ff00Left-click: toggle UI|r", diff --git a/Locales/MultiBotAceLocale-esES.lua b/Locales/MultiBotAceLocale-esES.lua index 2b8269d..71bd8fe 100644 --- a/Locales/MultiBotAceLocale-esES.lua +++ b/Locales/MultiBotAceLocale-esES.lua @@ -7,6 +7,7 @@ local esESValues = { ["info.itemdestroyalert"] = "¿REALMENTE quieres destruir este objeto?\n%s", ["info.keydestroyalert"] = "No venderé llaves.", ["info.itemsellalert"] = "No puedo vender este objeto.", + ["info.questitemsellalert"] = "No puedo vender objetos de misión.", ["info.inventoryvendortarget"] = "Primero debes seleccionar un vendedor.", ["info.butttitle"] = "|cffffd100MultiBot|r", ["info.buttontoggle"] = "|cff00ff00Clic izquierdo: alternar la interfaz|r", diff --git a/Locales/MultiBotAceLocale-frFR.lua b/Locales/MultiBotAceLocale-frFR.lua index 062de53..1a5a86a 100644 --- a/Locales/MultiBotAceLocale-frFR.lua +++ b/Locales/MultiBotAceLocale-frFR.lua @@ -7,6 +7,7 @@ local frFRValues = { ["info.itemdestroyalert"] = "Voulez-vous VRAIMENT détruire cet objet ?\n%s", ["info.keydestroyalert"] = "Je ne peux pas vendre des clés.", ["info.itemsellalert"] = "Je ne peux pas vendre cet item.", + ["info.questitemsellalert"] = "Je ne peux pas vendre les objets de quête.", ["info.inventoryvendortarget"] = "Vous devez dabord sélectionner un vendeur.", ["info.butttitle"] = "|cffffd100MultiBot|r", ["info.buttontoggle"] = "|cff00ff00Clic gauche : afficher/masquer l’interface|r", diff --git a/Locales/MultiBotAceLocale-koKR.lua b/Locales/MultiBotAceLocale-koKR.lua index 6d5a5e5..cab522a 100644 --- a/Locales/MultiBotAceLocale-koKR.lua +++ b/Locales/MultiBotAceLocale-koKR.lua @@ -7,6 +7,7 @@ local koKRValues = { ["info.itemdestroyalert"] = "이 아이템을 정말로 파기하시겠습니까?\n%s", ["info.keydestroyalert"] = "열쇠는 판매하지 않습니다.", ["info.itemsellalert"] = "이 아이템은 판매할 수 없습니다.", + ["info.questitemsellalert"] = "퀘스트 아이템은 판매할 수 없습니다.", ["info.inventoryvendortarget"] = "먼저 판매자를 선택해야 합니다.", ["info.butttitle"] = "|cffffd100MultiBot|r", ["info.buttontoggle"] = "|cff00ff00좌클릭: UI 전환|r", diff --git a/Locales/MultiBotAceLocale-ruRU.lua b/Locales/MultiBotAceLocale-ruRU.lua index 92dbfbb..7fe9234 100644 --- a/Locales/MultiBotAceLocale-ruRU.lua +++ b/Locales/MultiBotAceLocale-ruRU.lua @@ -7,6 +7,7 @@ local ruRUValues = { ["info.itemdestroyalert"] = "Вы ДЕЙСТВИТЕЛЬНО хотите уничтожить этот предмет?\n%s", ["info.keydestroyalert"] = "Я не продаю ключи.", ["info.itemsellalert"] = "Я не могу продать этот предмет.", + ["info.questitemsellalert"] = "Я не могу продавать предметы заданий.", ["info.inventoryvendortarget"] = "Сначала вы должны выбрать продавца.", ["info.butttitle"] = "|cffffd100MultiBot|r", ["info.buttontoggle"] = "|cff00ff00ЛКМ: переключить интерфейс|r", diff --git a/Locales/MultiBotAceLocale-zhCN.lua b/Locales/MultiBotAceLocale-zhCN.lua index 9d11035..7b453cb 100644 --- a/Locales/MultiBotAceLocale-zhCN.lua +++ b/Locales/MultiBotAceLocale-zhCN.lua @@ -7,6 +7,7 @@ local zhCNValues = { ["info.itemdestroyalert"] = "你真的要销毁这个物品吗?\n%s", ["info.keydestroyalert"] = "我不会出售钥匙。", ["info.itemsellalert"] = "我无法出售该物品。", + ["info.questitemsellalert"] = "无法出售任务物品。", ["info.inventoryvendortarget"] = "您必须先选择一位商人。", ["info.butttitle"] = "|cffffd100MultiBot|r", ["info.buttontoggle"] = "|cff00ff00左键:切换界面|r", diff --git a/TODO.md b/TODO.md index d5d5c0d..0a2aa7b 100644 --- a/TODO.md +++ b/TODO.md @@ -1,18 +1,12 @@ TODO -* Vente d'items de quetes, ça les vends quand même mais le bot les récupère, normallement ça devrait dire qu'il ne peux pas vendre un item de quête -* Voir si y'a pas d'autres appels à pageLabel:SetText(MB_PAGE_DEFAULT) dans les fichiers et remplacer par : + pageLabel:SetText(MultiBot.MB_PAGE_DEFAULT or "0/0") * Uniformiser le template des frame quetes comme celle de Itemus * Uniformiser le template de la frame reward comme celle de itemus * Essayer de faire disparaitre la barre multibots au bout d'un temps et la faire apparaitre quand on passe la souris dessus. -* Quand on deplace ou fait quelque chose dans l'ui il faudrait que ça se sauvegarde tout de suite dans les variables dans deco reco * Raidus doit se rafraichir à l'ouverture et fermeture * dans la liste des quêtes des fois c'est l'ID de la queête qui apparait et pas le tritre * Mettre une option pour choisir la tailles des icones de la main barre et des quickhunter/shaman * Voir si il y'a pas d'autres option que l'on peut ajouter à la frame options de multibot * creer le multilangue pour le tooltip: setTooltip(self, "Show / Hide / Move Quick Shaman") des fichiers quickshaman et quickhunter * Finir les options de déplacement des boutons -* Debuguer le blocage de la barre principale en déplacement ça a l'air de ne pas persister apres une deco reco -* Menu misc: faire en sorte que les barres horizontales des autres bots se ferment et que le menu se referme après avoir selectionné une action et que quand ce menu se referme toutes les barres de réouvrent. -* faite aussi ceci pour tout les menus deroulants de la every main -* probleme avec la vente des objets de quete, on arrive quand même à le vendre et il réapparait dans le sac, normallement je devrais avoir un message comme avec les clés, que je ne peux pas vendre. \ No newline at end of file +* faire en sorte que les menus déroulants de la main barre se ferment quand on on ouvre un autre \ No newline at end of file diff --git a/UI/MultiBotInventoryFrame.lua b/UI/MultiBotInventoryFrame.lua index 2e9dd7c..33aece9 100644 --- a/UI/MultiBotInventoryFrame.lua +++ b/UI/MultiBotInventoryFrame.lua @@ -426,10 +426,8 @@ end local function formatMoneyLabel(gold, silver, copper) local g = tonumber(gold) or 0 - local s = tonumber(silver) or 0 - local c = tonumber(copper) or 0 local moneyLabel = MultiBot.L("info.inventory.money_label", "Money") - return string.format("|cffffff00%s:|r %d|cffffd700g|r %d|cffc7c7cfs|r %d|cffb87333c|r", moneyLabel, g, s, c) + return string.format("|cffffff00%s:|r %d|cffffd700g|r", moneyLabel, g) end local function formatBagSlotsLabel(used, total) @@ -795,6 +793,72 @@ local function runInventoryInstantAction(botName, command, options) setInventoryActionState(nil, { cancelTrade = false }) end + local function isBulkSellCommand(cmd) + return cmd == "s *" or cmd == "s vendor" + end + + local function shouldSellButtonForBulk(button, cmd) + local item = button and button.item + if not item then + return false + end + + if MultiBot.InventoryIsProtectedSellItem and MultiBot.InventoryIsProtectedSellItem(item) then + return false + end + + if cmd == "s *" then + return tonumber(item.rare or -1) == 0 + end + + return true + end + + local function runFilteredBulkSell(cmd) + local inventory = MultiBot.inventory + local itemsFrame = inventory and inventory.frames and inventory.frames.Items + local itemButtons = itemsFrame and itemsFrame.buttons + if type(itemButtons) ~= "table" then + return false + end + + local sellCount = 0 + local protectedFound = false + for _, itemButton in pairs(itemButtons) do + if itemButton and itemButton.item then + if MultiBot.InventoryIsProtectedSellItem and MultiBot.InventoryIsProtectedSellItem(itemButton.item) then + protectedFound = true + elseif shouldSellButtonForBulk(itemButton, cmd) then + SendChatMessage("s " .. itemButton.tip, "WHISPER", nil, botName) + if itemButton.Hide then + itemButton:Hide() + end + sellCount = sellCount + 1 + end + end + end + + if protectedFound then + SendChatMessage(MultiBot.L("info.questitemsellalert", "I cannot sell quest items."), "SAY") + end + + if sellCount < 1 and not protectedFound then + return false + end + + if options.refreshDelay ~= nil and MultiBot.RefreshInventory then + MultiBot.RefreshInventory(options.refreshDelay) + elseif options.refresh and MultiBot.RefreshInventory then + MultiBot.RefreshInventory() + end + + return true + end + + if isBulkSellCommand(command) then + return runFilteredBulkSell(command) + end + SendChatMessage(command, "WHISPER", nil, botName) if options.refreshDelay ~= nil and MultiBot.RefreshInventory then diff --git a/UI/MultiBotInventoryItem.lua b/UI/MultiBotInventoryItem.lua index 746f62a..2d4c329 100644 --- a/UI/MultiBotInventoryItem.lua +++ b/UI/MultiBotInventoryItem.lua @@ -78,7 +78,11 @@ local function buildInventoryItemRecord(itemInfo) end local itemIcon = GetItemIcon(itemId) - local itemName, itemLink, itemRare, _, _, itemType, itemSubType, _, _, _, _, itemClassId = GetItemInfo(itemId) + local itemName, itemLink, itemRare, _, _, itemType, _, _, _, _, _, itemClassID = GetItemInfo(itemId) + if (itemClassID == nil) and GetItemInfoInstant then + local _, _, _, _, _, instantClassID = GetItemInfoInstant(tonumber(itemId) or itemId) + itemClassID = instantClassID + end return { id = itemId, @@ -86,9 +90,8 @@ local function buildInventoryItemRecord(itemInfo) name = resolveInventoryItemName(parts, itemName), link = resolveInventoryItemLink(parts, itemLink), rare = resolveInventoryItemRarity(itemRare), - itemType = itemType, - itemSubType = itemSubType, - itemClassId = itemClassId, + classID = itemClassID, + type = itemType, count = extractInventoryItemCount(parts), info = itemInfo, parts = parts, @@ -142,96 +145,28 @@ local function isInventoryProtectedHearthstone(item) return item and item.id == "6948" end -local inventorySellGuardTooltipName = "MB_InventorySellGuardTooltip" -local function getInventorySellGuardTooltip() - if MultiBot.AceUI and MultiBot.AceUI.EnsureHiddenTooltip then - return MultiBot.AceUI.EnsureHiddenTooltip(inventorySellGuardTooltipName, UIParent) - end - - local tooltip = _G[inventorySellGuardTooltipName] - if tooltip then - return tooltip - end - - tooltip = CreateFrame("GameTooltip", inventorySellGuardTooltipName, UIParent, "GameTooltipTemplate") - tooltip:SetOwner(UIParent, "ANCHOR_NONE") - return tooltip -end - -local function tooltipContainsQuestHint(itemLink) - if type(itemLink) ~= "string" or itemLink == "" then - return false - end - - local tooltip = getInventorySellGuardTooltip() - if not tooltip then - return false - end - - tooltip:ClearLines() - tooltip:SetHyperlink(itemLink) - - local questMarkers = { - ITEM_STARTS_QUEST, - QUESTS_LABEL, - TRACKER_HEADER_QUESTS, - "Quest", - "Quête", - "任务", - "퀘스트", - } - - for lineIndex = 1, 12 do - local line = _G[inventorySellGuardTooltipName .. "TextLeft" .. lineIndex] - local text = line and line.GetText and line:GetText() or nil - if text and text ~= "" then - for _, marker in ipairs(questMarkers) do - if type(marker) == "string" and marker ~= "" and string.find(text, marker, 1, true) then - return true - end - end - end - end - - return false -end - -local function isInventoryQuestType(item) +local function isInventoryProtectedQuestItem(item) if not item then return false end - local itemType = tostring(item.itemType or "") - local questTypeTokens = { - QUESTS_LABEL, - TRACKER_HEADER_QUESTS, - "Quest", - "Quête", - "任务", - "퀘스트", - } - - for _, token in ipairs(questTypeTokens) do - if type(token) == "string" and token ~= "" and itemType == token then - return true - end + if type(item.classID) == "number" then + local questClassID = (type(LE_ITEM_CLASS_QUESTITEM) == "number") and LE_ITEM_CLASS_QUESTITEM or 12 + return item.classID == questClassID end return false end -local function isInventoryProtectedQuestItem(item) - if not item then - return false - end - - if isInventoryQuestType(item) then - return true - end +MultiBot.InventoryIsProtectedQuestItem = isInventoryProtectedQuestItem - return tooltipContainsQuestHint(item.link) +MultiBot.InventoryIsProtectedSellItem = function(item) + return isInventoryProtectedQuestItem(item) + or isInventoryProtectedHearthstone(item) + or isInventoryProtectedKey(item) end + local function needsInventoryDestroyConfirmation(item) return isInventoryProtectedHearthstone(item) or isInventoryProtectedKey(item) @@ -279,6 +214,11 @@ local function handleInventoryItemClick(button) return end + if isInventoryProtectedQuestItem(item) then + sendInventoryFeedback("questitemsellalert", "I cannot sell quest items.") + return + end + if isInventoryProtectedHearthstone(item) then sendInventoryFeedback("itemsellalert", "You cannot sell this item") return @@ -289,11 +229,6 @@ local function handleInventoryItemClick(button) return end - if isInventoryProtectedQuestItem(item) then - sendInventoryFeedback("itemsellalert", "I will not sell quest items.") - return - end - sendInventoryItemCommand(action, button, botName, { hideButton = true, refreshDelay = 0.3, From 6c84663637ddbd873e70d36c137c330edc284d68 Mon Sep 17 00:00:00 2001 From: Wishmaster117 <140754794+Wishmaster117@users.noreply.github.com> Date: Fri, 3 Apr 2026 18:40:52 +0100 Subject: [PATCH 6/6] Update .luacheckrc --- .luacheckrc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.luacheckrc b/.luacheckrc index 5312ea9..4103bfb 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -36,7 +36,8 @@ globals = { "TooltipBackdropTemplateMixin", "NORMAL_FONT_COLOR", "HIGHLIGHT_FONT_COLOR", "GameTooltip_SetDefaultAnchor", "ChatFrame1", "UISpecialFrames", "GetMouseFocus", "ShowUIPanel", "tremove", "min", "max", "GetMinimapShape", "GetMinimapShape", "PanelTemplates_TabResize", "GetGuildRosterShowOffline", "SetGuildRosterShowOffline", "IsInGuild", "GetGuildInfo", "SetGuildRosterShowOffline", "PLAYER", "INVENTORY_TOOLTIP", "BAGSLOT", "UNKNOWN", "UnitIsDead", "ShowPrompt", "_MB_GetOrCreateShamanPos", "ensureHiddenTooltip", "MB_TAB_TITLE_DEFAULT", "SPELLBOOK", "MB_PAGE_DEFAULT", "SPELLBOOK_END_NON_SPELL_STREAK", "sendInventoryItemCommand", - "RAID_CLASS_COLORS", "INSPECT", "MB_INVENTORY_LABEL", "LOADING", "ITEM", "ITEMS", "SEARCH", "NO_QUESTS_LABEL", "QUESTS_LABEL", "QUEST_LOG", "UnitIsUnit", "ITEM_STARTS_QUEST", "TRACKER_HEADER_QUESTS" + "RAID_CLASS_COLORS", "INSPECT", "MB_INVENTORY_LABEL", "LOADING", "ITEM", "ITEMS", "SEARCH", "NO_QUESTS_LABEL", "QUESTS_LABEL", "QUEST_LOG", "UnitIsUnit", "ITEM_STARTS_QUEST", "TRACKER_HEADER_QUESTS", + "GetItemInfoInstant", "LE_ITEM_CLASS_QUESTITEM" } read_globals = {