Skip to content
This repository was archived by the owner on May 13, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .luacheckrc
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ globals = {
"GameFontNormal", "_G", "SetDesaturation", "WOW_PROJECT_ID", "WOW_PROJECT_MAINLINE", "ColorPickerFrame", "fixstrata", "UIDropDownMenu_HandleGlobalMouseEvent", "EventRegistry", "BackdropTemplateMixin",
"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",
"RAID_CLASS_COLORS", "INSPECT"
"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"
}

read_globals = {
Expand Down
4 changes: 4 additions & 0 deletions Core/MultiBotEngine.lua
Original file line number Diff line number Diff line change
Expand Up @@ -1552,6 +1552,10 @@ end
-- Rafraîchit l’inventaire du bot actuellement affiché dans la frame Inventory
-- en rejouant le même flux que le bouton "Inventory" (waitFor = "INVENTORY" + "items").
MultiBot.RefreshInventory = function(delay)
if MultiBot.inventory and MultiBot.inventory.refresh then
return MultiBot.inventory:refresh(delay)
end

-- Si la frame d’inventaire n’est pas visible ou pas encore initialisée, on ne fait rien
if not MultiBot.inventory or not MultiBot.inventory:IsVisible() then
return false
Expand Down
17 changes: 6 additions & 11 deletions Core/MultiBotEvery.lua
Original file line number Diff line number Diff line change
Expand Up @@ -144,19 +144,14 @@ MultiBot.addEvery = function(pFrame, pCombat, pNormal)
if(pButton.state) then
MultiBot.inventory:Hide()
pButton.setDisable()
else
local tUnits = MultiBot.frames["MultiBar"].frames["Units"]
for key, value in pairs(MultiBot.index.actives) do
if(tUnits.buttons[value].name ~= UnitName("player")) then
tUnits.frames[value].getButton("Inventory").setDisable()
end
end
return
end

pButton.setEnable()
MultiBot.inventory.name = pButton.getName()
tUnits.buttons[MultiBot.inventory.name].waitFor = "INVENTORY"
SendChatMessage("items", "WHISPER", nil, pButton.getName())
if(MultiBot.RequestBotInventory and MultiBot.RequestBotInventory(pButton.getName())) then
return
end

pButton.setEnable()
end

pFrame.addButton("Spellbook", 274, 0, "inv_misc_book_09", MultiBot.L("tips.every.spellbook")).setDisable()
Expand Down
46 changes: 38 additions & 8 deletions Core/MultiBotHandler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,14 @@ local function setSavedLayoutValue(key, value)
return value
end

MultiBot.GetSavedLayoutValue = function(key)
return getSavedLayoutValue(key)
end

MultiBot.SetSavedLayoutValue = function(key, value)
return setSavedLayoutValue(key, value)
end

-- HANDLER --


Expand Down Expand Up @@ -1496,12 +1504,20 @@ function MultiBot.HandleMultiBotEvent(event, ...)
-- Inventory --

if(tButton.waitFor == "INVENTORY" and MultiBot.isInside(arg1, "Inventory", "背包")) then
local tItems = MultiBot.inventory.frames["Items"]
for key, value in pairs(tItems.buttons) do value:Hide() end
for key in pairs(tItems.buttons) do tItems.buttons[key] = nil end
MultiBot.inventory.setText("Title", MultiBot.doReplace(MultiBot.L("info.inventory"), "NAME", arg2))
MultiBot.inventory.name = arg2
tItems.index = 0
if(MultiBot.inventory and MultiBot.inventory.beginPayload) then
MultiBot.inventory:beginPayload(arg2)
else
local tItems = MultiBot.inventory.frames["Items"]
if(tItems.clear) then
tItems:clear()
else
for key, value in pairs(tItems.buttons) do value:Hide() end
for key in pairs(tItems.buttons) do tItems.buttons[key] = nil end
end
MultiBot.inventory.setText("Title", MultiBot.doReplace(MultiBot.L("info.inventory"), "NAME", arg2))
MultiBot.inventory.name = arg2
tItems.index = 0
end
tButton.waitFor = "ITEM"
SendChatMessage("stats", "WHISPER", nil, arg2)
return
Expand All @@ -1516,7 +1532,11 @@ function MultiBot.HandleMultiBotEvent(event, ...)

if(tButton.waitFor == "ITEM") then
if(string.sub(arg1, 1, 3) == "---") then return end
MultiBot.addItem(MultiBot.inventory.frames["Items"], arg1)
if(MultiBot.inventory and MultiBot.inventory.appendItem) then
MultiBot.inventory:appendItem(arg1)
else
MultiBot.addItem(MultiBot.inventory.frames["Items"], arg1)
end
return
end

Expand All @@ -1542,7 +1562,11 @@ function MultiBot.HandleMultiBotEvent(event, ...)
end

if(MultiBot.inventory:IsVisible() and MultiBot.isInside(string.lower(arg1), "opened")) then
tButton.waitFor = "LOOT"
if(MultiBot.inventory and MultiBot.inventory.markLootPending) then
MultiBot.inventory:markLootPending(tButton.name)
else
tButton.waitFor = "LOOT"
end
return
end
end
Expand All @@ -1564,6 +1588,12 @@ function MultiBot.HandleMultiBotEvent(event, ...)
tButton = MultiBot.frames["MultiBar"].frames["Units"].buttons[tName]
end

if(tButton ~= nil and MultiBot.inventory and MultiBot.inventory.handleLootReceived
and MultiBot.inventory:handleLootReceived(tButton.name)) then
tButton.waitFor = ""
return
end

if(tButton ~= nil and tButton.waitFor == "LOOT" and tButton ~= nil) then
tButton.waitFor = "INVENTORY"
SendChatMessage("items", "WHISPER", nil, tButton.name)
Expand Down
155 changes: 1 addition & 154 deletions Core/MultiBotInit.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3162,158 +3162,7 @@ end

-- INVENTORY --

MultiBot.inventory = MultiBot.newFrame(MultiBot, -700, -144, 32, 442, 884)
MultiBot.inventory.addTexture("Interface\\AddOns\\MultiBot\\Textures\\Inventory.blp")
MultiBot.inventory.addText("Title", MB_INVENTORY_LABEL, "CENTER", -58, 429, 12)
MultiBot.inventory.action = "s"
MultiBot.inventory:SetMovable(true)
MultiBot.inventory:Hide()

MultiBot.inventory.movButton("Move", -406, 849, 34, MultiBot.L("tips.move.inventory"))

MultiBot.inventory.wowButton("X", -126, 862, 15, 18, 13)
.doLeft = function(pButton)
local tUnits = MultiBot.frames and MultiBot.frames["MultiBar"] and MultiBot.frames["MultiBar"].frames and MultiBot.frames["MultiBar"].frames["Units"]
local tName = MultiBot.inventory and MultiBot.inventory.name
if(tUnits == nil or tName == nil or tUnits.buttons == nil or tUnits.buttons[tName] == nil) then
MultiBot.inventory:Hide()
return
end

local tButton = tUnits.buttons[tName].buttons and tUnits.buttons[tName].buttons["Inventory"]
if(tButton ~= nil and tButton.doLeft ~= nil) then
tButton.doLeft(tButton)
else
MultiBot.inventory:Hide()
end
end

MultiBot.inventory.addButton("Sell", -94, 806, "inv_misc_coin_16", MultiBot.L("tips.inventory.sell")).setEnable()
.doLeft = function(pButton)
if(pButton.state) then
MultiBot.inventory.action = ""
pButton.setDisable()
else
CancelTrade()
MultiBot.inventory.action = "s"
pButton.getButton("Destroy").setDisable()
pButton.getButton("Equip").setDisable()
pButton.getButton("Trade").setDisable()
pButton.getButton("Use").setDisable()
pButton.setEnable()
end
end

-- Bouton vendre tous les objets gris (s *)
MultiBot.inventory.addButton("SellGrey", -94, 768, "inv_misc_coin_03", MultiBot.L("tips.inventory.sellgrey"))
.doLeft = function(pButton)
if not MultiBot.isTarget() then
return
end
CancelTrade()
MultiBot.inventory.action = ""
pButton.getButton("Destroy").setDisable()
pButton.getButton("Equip").setDisable()
pButton.getButton("Trade").setDisable()
pButton.getButton("Sell").setDisable()
pButton.getButton("Use").setDisable()
SendChatMessage("s *", "WHISPER", nil, pButton.getName())
if MultiBot.RefreshInventory then
MultiBot.RefreshInventory(0.5)
end
end

-- Bouton vendre tous les objets vendables (s vendor)
MultiBot.inventory.addButton("SellVendor", -94, 731, "inv_misc_coin_04", MultiBot.L("tips.inventory.sellvendor"))
.doLeft = function(pButton)
if not MultiBot.isTarget() then
return
end
CancelTrade()
MultiBot.inventory.action = ""
pButton.getButton("Destroy").setDisable()
pButton.getButton("Equip").setDisable()
pButton.getButton("Trade").setDisable()
pButton.getButton("Sell").setDisable()
pButton.getButton("Use").setDisable()
SendChatMessage("s vendor", "WHISPER", nil, pButton.getName())
if MultiBot.RefreshInventory then
MultiBot.RefreshInventory()
end
end

MultiBot.inventory.addButton("Equip", -94, 694, "inv_helmet_22", MultiBot.L("tips.inventory.equip")).setDisable()
.doLeft = function(pButton)
if(pButton.state) then
MultiBot.inventory.action = ""
pButton.setDisable()
else
CancelTrade()
MultiBot.inventory.action = "e"
pButton.getButton("Destroy").setDisable()
pButton.getButton("Trade").setDisable()
pButton.getButton("Sell").setDisable()
pButton.getButton("Use").setDisable()
pButton.setEnable()
end
end

MultiBot.inventory.addButton("Use", -94, 657, "inv_gauntlets_25", MultiBot.L("tips.inventory.use")).setDisable()
.doLeft = function(pButton)
if(pButton.state) then
MultiBot.inventory.action = ""
pButton.setDisable()
else
CancelTrade()
MultiBot.inventory.action = "u"
pButton.getButton("Destroy").setDisable()
pButton.getButton("Equip").setDisable()
pButton.getButton("Trade").setDisable()
pButton.getButton("Sell").setDisable()
pButton.setEnable()
end
end

MultiBot.inventory.addButton("Trade", -94, 620, "achievement_reputation_01", MultiBot.L("tips.inventory.trade")).setDisable()
.doLeft = function(pButton)
if(pButton.state) then
MultiBot.inventory.action = ""
pButton.setDisable()
CancelTrade()
else
InitiateTrade(pButton.getName())
MultiBot.inventory.action = "give"
pButton.getButton("Destroy").setDisable()
pButton.getButton("Equip").setDisable()
pButton.getButton("Sell").setDisable()
pButton.getButton("Use").setDisable()
pButton.setEnable()
end
end

MultiBot.inventory.addButton("Destroy", -94, 583, "inv_hammer_15", MultiBot.L("tips.inventory.drop")).setDisable()
.doLeft = function(pButton)
if(pButton.state) then
MultiBot.inventory.action = ""
pButton.setDisable()
else
CancelTrade()
MultiBot.inventory.action = "destroy"
pButton.getButton("Equip").setDisable()
pButton.getButton("Trade").setDisable()
pButton.getButton("Sell").setDisable()
pButton.getButton("Use").setDisable()
pButton.setEnable()
end
end

MultiBot.inventory.addButton("Open", -94, 322.5, "inv_misc_gift_05", MultiBot.L("tips.inventory.open"))
.doLeft = function(pButton)
SendChatMessage("open items", "WHISPER", nil, pButton.getName())
end

local tFrame = MultiBot.inventory.addFrame("Items", -397, 807, 32)
tFrame:Show()
MultiBot.InitializeInventoryFrame()

-- STATS --

Expand Down Expand Up @@ -4795,8 +4644,6 @@ if MultiBot.TimerAfter then
end)
end

-- Minimap bootstrap is handled by OnEnable via LIFECYCLE_ENABLE_STEPS.

-- FINISH --

MultiBot.state = true
Expand Down
2 changes: 1 addition & 1 deletion Core/MultiBotLocale.lua
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ function MultiBot.GetLocaleString(key, fallback)

if aceLocale then
local activeLocale = aceLocale:GetLocale(LOCALE_NAMESPACE, true)
local activeValue = activeLocale and activeLocale[key]
local activeValue = type(activeLocale) == "table" and rawget(activeLocale, key) or nil
if type(activeValue) == "string" then
return activeValue
end
Expand Down
1 change: 1 addition & 0 deletions Locales/MultiBotAceLocale-deDE.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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.inventoryvendortarget"] = "Sie müssen zuerst einen Händler auswählen.",
["info.butttitle"] = "|cffffd100MultiBot|r",
["info.buttontoggle"] = "|cff00ff00Linksklick: UI umschalten|r",
["info.buttonoptions"] = "|cffff0000Rechtsklick: Optionen|r",
Expand Down
1 change: 1 addition & 0 deletions Locales/MultiBotAceLocale-enGB.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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.inventoryvendortarget"] = "You must select a vendor first.",
["info.butttitle"] = "|cffffd100MultiBot|r",
["info.buttontoggle"] = "|cff00ff00Left-click: toggle UI|r",
["info.buttonoptions"] = "|cffff0000Right-click: options|r",
Expand Down
1 change: 1 addition & 0 deletions Locales/MultiBotAceLocale-enUS.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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.inventoryvendortarget"] = "You must select a vendor first.",
["info.butttitle"] = "|cffffd100MultiBot|r",
["info.buttontoggle"] = "|cff00ff00Left-click: toggle UI|r",
["info.buttonoptions"] = "|cffff0000Right-click: options|r",
Expand Down
1 change: 1 addition & 0 deletions Locales/MultiBotAceLocale-esES.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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.inventoryvendortarget"] = "Primero debes seleccionar un vendedor.",
["info.butttitle"] = "|cffffd100MultiBot|r",
["info.buttontoggle"] = "|cff00ff00Clic izquierdo: alternar la interfaz|r",
["info.buttonoptions"] = "|cffff0000Clic derecho: opciones|r",
Expand Down
1 change: 1 addition & 0 deletions Locales/MultiBotAceLocale-frFR.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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.inventoryvendortarget"] = "Vous devez dabord sélectionner un vendeur.",
["info.butttitle"] = "|cffffd100MultiBot|r",
["info.buttontoggle"] = "|cff00ff00Clic gauche : afficher/masquer l’interface|r",
["info.buttonoptions"] = "|cffff0000Clic droit : options|r",
Expand Down
1 change: 1 addition & 0 deletions Locales/MultiBotAceLocale-koKR.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ local koKRValues = {
["info.itemdestroyalert"] = "이 아이템을 정말로 파기하시겠습니까?\n%s",
["info.keydestroyalert"] = "열쇠는 판매하지 않습니다.",
["info.itemsellalert"] = "이 아이템은 판매할 수 없습니다.",
["info.inventoryvendortarget"] = "먼저 판매자를 선택해야 합니다.",
["info.butttitle"] = "|cffffd100MultiBot|r",
["info.buttontoggle"] = "|cff00ff00좌클릭: UI 전환|r",
["info.buttonoptions"] = "|cffff0000우클릭: 옵션|r",
Expand Down
1 change: 1 addition & 0 deletions Locales/MultiBotAceLocale-ruRU.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ local ruRUValues = {
["info.itemdestroyalert"] = "Вы ДЕЙСТВИТЕЛЬНО хотите уничтожить этот предмет?\n%s",
["info.keydestroyalert"] = "Я не продаю ключи.",
["info.itemsellalert"] = "Я не могу продать этот предмет.",
["info.inventoryvendortarget"] = "Сначала вы должны выбрать продавца.",
["info.butttitle"] = "|cffffd100MultiBot|r",
["info.buttontoggle"] = "|cff00ff00ЛКМ: переключить интерфейс|r",
["info.buttonoptions"] = "|cffff0000ПКМ: настройки|r",
Expand Down
1 change: 1 addition & 0 deletions Locales/MultiBotAceLocale-zhCN.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ local zhCNValues = {
["info.itemdestroyalert"] = "你真的要销毁这个物品吗?\n%s",
["info.keydestroyalert"] = "我不会出售钥匙。",
["info.itemsellalert"] = "我无法出售该物品。",
["info.inventoryvendortarget"] = "您必须先选择一位商人。",
["info.butttitle"] = "|cffffd100MultiBot|r",
["info.buttontoggle"] = "|cff00ff00左键:切换界面|r",
["info.buttonoptions"] = "|cffff0000右键:选项|r",
Expand Down
2 changes: 2 additions & 0 deletions MultiBot.toc
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ UI\MultiBotStats.lua
UI\MultiBotSpell.lua
UI\MultiBotSpellBookFrame.lua
UI\MultiBotRewardFrame.lua
UI\MultiBotInventoryFrame.lua
UI\MultiBotInventoryItem.lua
UI\MultiBotItem.lua
UI\MultiBotTalentFrame.lua
Core\MultiBotInit.lua
Expand Down
10 changes: 5 additions & 5 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@
- `UI/MultiBotPVPUI.lua` migration slice is completed for the targeted controls (bot selector dropdown + tab group with localized fallback compatibility).
- `UI/MultiBotSpecUI.lua` migration slice is completed for the spec popup/inspect helper controls (AceGUI window path finalized: close-cross UX, layering fix, compact size, and position persistence on AceDB path).
- `Features/MultiBotRaidus.lua` migration/polish slice is completed (AceGUI window hosting path, close state sync with main button, slot/group score badges, drag/drop feedback, and interactive contrast pass).
- `UI/MultiBotTalentFrame.lua` Talents/Glyphs host path is active on AceGUI (`Window` container + host layout + tab context updates), with legacy visual tab chrome intentionally preserved (`ChatFrameTab-*`) by design choice for now.
- Milestone 8 Talents/Glyphs remains **GO partiel**: ACE3 hosting path is in place, but full "no legacy dependency" validation is not yet declared closed.
- `UI/MultiBotTalentFrame.lua` Talents/Glyphs migration slice is completed for the targeted host workflow with preserved tab/copy/apply behavior and custom glyph interactions.
- `UI/MultiBotSpellBookFrame.lua` + `UI/MultiBotSpell.lua` SpellBook migration slice is completed (AceGUI window host, dynamic slot/check generation, page-size normalization, and stateful chat-collection parsing/finish flow).
- Reward frame migration slice is completed (`UI/MultiBotRewardFrame.lua` + `Features/MultiBotReward.lua` + main-bar integration): native AceGUI host, deduped module API, saved-state-aware popup trigger, and parity close/paging behavior are in place.
- Remaining screens continue screen-by-screen (quest popups and auxiliary prompts still pending).
- **Milestone 9 (Localization and text pipeline):** Completed.
- Reward frame migration slice is completed (`UI/MultiBotRewardFrame.lua` + `Features/MultiBotReward.lua` + main-bar integration): native AceGUI host, deduped module API, saved-state-aware popup trigger, and parity close/paging behavior are in place.
- Inventory migration slice is completed (`UI/MultiBotInventoryFrame.lua` + `UI/MultiBotInventoryItem.lua` + handler/request integration): native AceGUI host, controller API, hybrid dense-icon grid, inventory-button sync, and final UI/header polish are validated in game.
- Quest popups, prompts, hunter family/search windows, and related AceGUI popup migrations are completed;
- **Milestone 9 (Localization and text pipeline):** Completed.
- Core locale loader + per-locale payload files are integrated (`Core/MultiBotLocale.lua`, `Locales/MultiBotAceLocale-*.lua`).
- `Core/MultiBotInit.lua`, `Features/MultiBotRaidus.lua`, `Core/MultiBotEvery.lua`, `Core/MultiBotEngine.lua`, `Core/MultiBotHandler.lua`, `Strategies/MultiBotDruid.lua`, `Strategies/MultiBotPaladin.lua`, `Strategies/MultiBotMage.lua`, `Strategies/MultiBotWarlock.lua`, `Strategies/MultiBotPriest.lua`, `Strategies/MultiBotShaman.lua`, `Strategies/MultiBotHunter.lua`, `Strategies/MultiBotRogue.lua`, `Strategies/MultiBotDeathKnight.lua`, and `Strategies/MultiBotWarrior.lua` migration sweeps are completed for legacy `MultiBot.tips.*` runtime reads.
- `Core/MultiBot.lua` bootstrap `MultiBot.tips` initialization lines were validated/documented as intentional non-runtime-tooltip compatibility paths.
Expand Down
Loading
Loading