Skip to content
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
73 changes: 73 additions & 0 deletions Core/MultiBotComm.lua
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ local function ensureBridgeState()
state.rtiSeq = state.rtiSeq or 0
state.combatSeq = state.combatSeq or 0
state.positionSeq = state.positionSeq or 0
state.lootSeq = state.lootSeq or 0
return state
end

Expand Down Expand Up @@ -317,6 +318,31 @@ function Comm.RunCombatCommand(scope, target, command)
return Comm.Send("RUN", "COMBAT~" .. scope .. "~" .. urlEncodeField(target) .. "~" .. token .. "~" .. urlEncodeField(command))
end

function Comm.RunLootCommand(scope, target, command)
local state = ensureBridgeState()

if not state.connected then
return false
end

command = trim(command or "")
if command == "" then
return false
end

scope = string.upper(trim(scope or "ALL"))
target = trim(target or "")

if scope ~= "ALL" and scope ~= "GROUP" and scope ~= "BOT" then
return false
end

state.lootSeq = (tonumber(state.lootSeq) or 0) + 1
local token = tostring(math.floor(safeNow() * 1000)) .. "-loot-" .. tostring(state.lootSeq)

return Comm.Send("RUN", "LOOT~" .. scope .. "~" .. urlEncodeField(target) .. "~" .. token .. "~" .. urlEncodeField(command))
end

function Comm.RunPositionCommand(scope, target, command)
local state = ensureBridgeState()

Expand Down Expand Up @@ -1723,6 +1749,53 @@ function Comm.HandleAddonMessage(prefix, message, distribution, sender)
return true
end

if opcode == "LOOT_ACK" then
state.connected = true
state.lastError = nil
debugPrint("ADDON:RX", "LOOT_ACK", payload or "")

local scope, rest = splitOnce(payload or "", "~")
local encodedTarget, rest2 = splitOnce(rest, "~")
local token, rest3 = splitOnce(rest2, "~")
local executedText, encodedCommand = splitOnce(rest3, "~")
local executed = tonumber(executedText) or 0
local command = string.lower(trim(urlDecodeField(encodedCommand)))

if executed <= 0 then
systemMessage(L("loot.confirm.none", "Loot command was not applied to any bot."))
return true
end

if MultiBot.OnLootCommandApplied then
MultiBot.OnLootCommandApplied(command, executed)
end

if command == "nc +loot" then
systemMessage(string.format(L("loot.confirm.enable", "Loot enabled for %d bot(s)."), executed))
return true
end

if command == "nc -loot" then
systemMessage(string.format(L("loot.confirm.disable", "Loot disabled for %d bot(s)."), executed))
return true
end

local profile = command:match("^ll%s+([%w_%-]+)$")
if profile then
local profileName = ({
all = L("loot.profile.all", "All"),
normal = L("loot.profile.normal", "Normal"),
gray = L("loot.profile.gray", "Gray"),
quest = L("loot.profile.quest", "Quest"),
skill = L("loot.profile.skill", "Skill"),
})[profile] or profile

systemMessage(string.format(L("loot.confirm.profile", "Loot profile set to %s for %d bot(s)."), profileName, executed))
end

return true
end

if opcode == "ERR" then
state.lastError = payload
debugPrint("ADDON:RX", "ERR", payload or "")
Expand Down
18 changes: 18 additions & 0 deletions Locales/MultiBotAceLocale-deDE.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,24 @@ local deDEValues = {
["tips.disperse.main"] = "Disperse",
["tips.disperse.set"] = "Disperse-Distanz setzen",
["tips.disperse.disable"] = "Disperse deaktivieren",
["tips.loot.main"] = "Beuteregeln",
["tips.loot.enable"] = "Beute aktivieren",
["tips.loot.disable"] = "Beute deaktivieren",
["tips.loot.all"] = "Beuteprofil: Alles",
["tips.loot.normal"] = "Beuteprofil: Normal",
["tips.loot.gray"] = "Beuteprofil: Grau",
["tips.loot.quest"] = "Beuteprofil: Quest",
["tips.loot.skill"] = "Beuteprofil: Beruf",
["loot.bridge.required"] = "Die Beute-Bridge ist nicht verbunden.",
["loot.confirm.none"] = "Der Beutebefehl wurde auf keinen Bot angewendet.",
["loot.confirm.enable"] = "Beute für %d Bot(s) aktiviert.",
["loot.confirm.disable"] = "Beute für %d Bot(s) deaktiviert.",
["loot.confirm.profile"] = "Beuteprofil auf %s für %d Bot(s) gesetzt.",
["loot.profile.all"] = "Alles",
["loot.profile.normal"] = "Normal",
["loot.profile.gray"] = "Grau",
["loot.profile.quest"] = "Quest",
["loot.profile.skill"] = "Beruf",
["disperse.bridge.required"] = "Position-Bridge ist nicht verbunden.",
["disperse.invalid_distance"] = "Gib eine Distanz zwischen 1 und 100 Yards ein.",
["disperse.confirm.set"] = "Disperse auf %s Yards gesetzt.",
Expand Down
18 changes: 18 additions & 0 deletions Locales/MultiBotAceLocale-enGB.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,24 @@ local enGBValues = {
["tips.disperse.main"] = "Disperse",
["tips.disperse.set"] = "Set disperse distance",
["tips.disperse.disable"] = "Disable disperse",
["tips.loot.main"] = "Loot rules",
["tips.loot.enable"] = "Enable loot",
["tips.loot.disable"] = "Disable loot",
["tips.loot.all"] = "Loot profile: All",
["tips.loot.normal"] = "Loot profile: Normal",
["tips.loot.gray"] = "Loot profile: Gray",
["tips.loot.quest"] = "Loot profile: Quest",
["tips.loot.skill"] = "Loot profile: Skill",
["loot.bridge.required"] = "Loot bridge is not connected.",
["loot.confirm.none"] = "Loot command was not applied to any bot.",
["loot.confirm.enable"] = "Loot enabled for %d bot(s).",
["loot.confirm.disable"] = "Loot disabled for %d bot(s).",
["loot.confirm.profile"] = "Loot profile set to %s for %d bot(s).",
["loot.profile.all"] = "All",
["loot.profile.normal"] = "Normal",
["loot.profile.gray"] = "Gray",
["loot.profile.quest"] = "Quest",
["loot.profile.skill"] = "Skill",
["disperse.bridge.required"] = "Position bridge is not connected.",
["disperse.invalid_distance"] = "Enter a distance between 1 and 100 yards.",
["disperse.confirm.set"] = "Disperse set to %s yards.",
Expand Down
18 changes: 18 additions & 0 deletions Locales/MultiBotAceLocale-enUS.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,24 @@ local enUSValues = {
["tips.disperse.main"] = "Disperse",
["tips.disperse.set"] = "Set disperse distance",
["tips.disperse.disable"] = "Disable disperse",
["tips.loot.main"] = "Loot rules",
["tips.loot.enable"] = "Enable loot",
["tips.loot.disable"] = "Disable loot",
["tips.loot.all"] = "Loot profile: All",
["tips.loot.normal"] = "Loot profile: Normal",
["tips.loot.gray"] = "Loot profile: Gray",
["tips.loot.quest"] = "Loot profile: Quest",
["tips.loot.skill"] = "Loot profile: Skill",
["loot.bridge.required"] = "Loot bridge is not connected.",
["loot.confirm.none"] = "Loot command was not applied to any bot.",
["loot.confirm.enable"] = "Loot enabled for %d bot(s).",
["loot.confirm.disable"] = "Loot disabled for %d bot(s).",
["loot.confirm.profile"] = "Loot profile set to %s for %d bot(s).",
["loot.profile.all"] = "All",
["loot.profile.normal"] = "Normal",
["loot.profile.gray"] = "Gray",
["loot.profile.quest"] = "Quest",
["loot.profile.skill"] = "Skill",
["disperse.bridge.required"] = "Position bridge is not connected.",
["disperse.invalid_distance"] = "Enter a distance between 1 and 100 yards.",
["disperse.confirm.set"] = "Disperse set to %s yards.",
Expand Down
18 changes: 18 additions & 0 deletions Locales/MultiBotAceLocale-esES.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,24 @@ local esESValues = {
["tips.disperse.main"] = "Dispersar",
["tips.disperse.set"] = "Definir distancia de dispersión",
["tips.disperse.disable"] = "Desactivar dispersión",
["tips.loot.main"] = "Reglas de botín",
["tips.loot.enable"] = "Activar botín",
["tips.loot.disable"] = "Desactivar botín",
["tips.loot.all"] = "Perfil de botín: Todo",
["tips.loot.normal"] = "Perfil de botín: Normal",
["tips.loot.gray"] = "Perfil de botín: Gris",
["tips.loot.quest"] = "Perfil de botín: Misión",
["tips.loot.skill"] = "Perfil de botín: Profesión",
["loot.bridge.required"] = "El bridge de botín no está conectado.",
["loot.confirm.none"] = "El comando de botín no se aplicó a ningún bot.",
["loot.confirm.enable"] = "Botín activado para %d bot(s).",
["loot.confirm.disable"] = "Botín desactivado para %d bot(s).",
["loot.confirm.profile"] = "Perfil de botín establecido en %s para %d bot(s).",
["loot.profile.all"] = "Todo",
["loot.profile.normal"] = "Normal",
["loot.profile.gray"] = "Gris",
["loot.profile.quest"] = "Misión",
["loot.profile.skill"] = "Profesión",
["disperse.bridge.required"] = "El puente de posición no está conectado.",
["disperse.invalid_distance"] = "Introduce una distancia entre 1 y 100 yardas.",
["disperse.confirm.set"] = "Dispersión establecida a %s yardas.",
Expand Down
18 changes: 18 additions & 0 deletions Locales/MultiBotAceLocale-frFR.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,24 @@ local frFRValues = {
["tips.disperse.main"] = "Disperse",
["tips.disperse.set"] = "Définir la distance de disperse",
["tips.disperse.disable"] = "Désactiver disperse",
["tips.loot.main"] = "Règles de butin",
["tips.loot.enable"] = "Activer le butin",
["tips.loot.disable"] = "Désactiver le butin",
["tips.loot.all"] = "Profil de butin : Tout",
["tips.loot.normal"] = "Profil de butin : Normal",
["tips.loot.gray"] = "Profil de butin : Gris",
["tips.loot.quest"] = "Profil de butin : Quête",
["tips.loot.skill"] = "Profil de butin : Métier",
["loot.bridge.required"] = "Le bridge du butin n’est pas connecté.",
["loot.confirm.none"] = "La commande de butin n’a été appliquée à aucun bot.",
["loot.confirm.enable"] = "Butin activé pour %d bot(s).",
["loot.confirm.disable"] = "Butin désactivé pour %d bot(s).",
["loot.confirm.profile"] = "Profil de butin défini sur %s pour %d bot(s).",
["loot.profile.all"] = "Tout",
["loot.profile.normal"] = "Normal",
["loot.profile.gray"] = "Gris",
["loot.profile.quest"] = "Quête",
["loot.profile.skill"] = "Métier",
["disperse.bridge.required"] = "Le bridge de position n’est pas connecté.",
["disperse.invalid_distance"] = "Entre une distance entre 1 et 100 yards.",
["disperse.confirm.set"] = "Disperse défini à %s yards.",
Expand Down
18 changes: 18 additions & 0 deletions Locales/MultiBotAceLocale-koKR.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,24 @@ local koKRValues = {
["tips.disperse.main"] = "분산",
["tips.disperse.set"] = "분산 거리 설정",
["tips.disperse.disable"] = "분산 비활성화",
["tips.loot.main"] = "전리품 규칙",
["tips.loot.enable"] = "전리품 켜기",
["tips.loot.disable"] = "전리품 끄기",
["tips.loot.all"] = "전리품 프로필: 전체",
["tips.loot.normal"] = "전리품 프로필: 일반",
["tips.loot.gray"] = "전리품 프로필: 회색",
["tips.loot.quest"] = "전리품 프로필: 퀘스트",
["tips.loot.skill"] = "전리품 프로필: 전문기술",
["loot.bridge.required"] = "전리품 브리지가 연결되어 있지 않습니다.",
["loot.confirm.none"] = "전리품 명령이 어떤 봇에도 적용되지 않았습니다.",
["loot.confirm.enable"] = "%d 봇에게 전리품을 켰습니다.",
["loot.confirm.disable"] = "%d 봇에게 전리품을 껐습니다.",
["loot.confirm.profile"] = "전리품 프로필을 %s로 설정했습니다. 대상 봇: %d.",
["loot.profile.all"] = "전체",
["loot.profile.normal"] = "일반",
["loot.profile.gray"] = "회색",
["loot.profile.quest"] = "퀘스트",
["loot.profile.skill"] = "전문기술",
["disperse.bridge.required"] = "위치 브리지가 연결되어 있지 않습니다.",
["disperse.invalid_distance"] = "1에서 100 야드 사이의 거리를 입력하세요.",
["disperse.confirm.set"] = "분산 거리가 %s 야드로 설정되었습니다.",
Expand Down
18 changes: 18 additions & 0 deletions Locales/MultiBotAceLocale-ruRU.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,24 @@ local ruRUValues = {
["tips.disperse.main"] = "Рассредоточение",
["tips.disperse.set"] = "Задать дистанцию рассредоточения",
["tips.disperse.disable"] = "Отключить рассредоточение",
["tips.loot.main"] = "Правила добычи",
["tips.loot.enable"] = "Включить добычу",
["tips.loot.disable"] = "Отключить добычу",
["tips.loot.all"] = "Профиль добычи: Всё",
["tips.loot.normal"] = "Профиль добычи: Обычное",
["tips.loot.gray"] = "Профиль добычи: Серое",
["tips.loot.quest"] = "Профиль добычи: Задания",
["tips.loot.skill"] = "Профиль добычи: Профессии",
["loot.bridge.required"] = "Мост добычи не подключён.",
["loot.confirm.none"] = "Команда добычи не применена ни к одному боту.",
["loot.confirm.enable"] = "Добыча включена для %d бот(ов).",
["loot.confirm.disable"] = "Добыча отключена для %d бот(ов).",
["loot.confirm.profile"] = "Профиль добычи установлен на %s для %d бот(ов).",
["loot.profile.all"] = "Всё",
["loot.profile.normal"] = "Обычное",
["loot.profile.gray"] = "Серое",
["loot.profile.quest"] = "Задания",
["loot.profile.skill"] = "Профессии",
["disperse.bridge.required"] = "Мост позиционирования не подключен.",
["disperse.invalid_distance"] = "Введите дистанцию от 1 до 100 ярдов.",
["disperse.confirm.set"] = "Рассредоточение установлено на %s ярдов.",
Expand Down
18 changes: 18 additions & 0 deletions Locales/MultiBotAceLocale-zhCN.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,24 @@ local zhCNValues = {
["tips.disperse.main"] = "分散",
["tips.disperse.set"] = "设置分散距离",
["tips.disperse.disable"] = "禁用分散",
["tips.loot.main"] = "拾取规则",
["tips.loot.enable"] = "启用拾取",
["tips.loot.disable"] = "禁用拾取",
["tips.loot.all"] = "拾取配置:全部",
["tips.loot.normal"] = "拾取配置:普通",
["tips.loot.gray"] = "拾取配置:灰色",
["tips.loot.quest"] = "拾取配置:任务",
["tips.loot.skill"] = "拾取配置:专业",
["loot.bridge.required"] = "拾取桥接未连接。",
["loot.confirm.none"] = "拾取命令未应用到任何机器人。",
["loot.confirm.enable"] = "已为 %d 个机器人启用拾取。",
["loot.confirm.disable"] = "已为 %d 个机器人禁用拾取。",
["loot.confirm.profile"] = "已将拾取配置设置为 %s,影响 %d 个机器人。",
["loot.profile.all"] = "全部",
["loot.profile.normal"] = "普通",
["loot.profile.gray"] = "灰色",
["loot.profile.quest"] = "任务",
["loot.profile.skill"] = "专业",
["disperse.bridge.required"] = "位置桥接未连接。",
["disperse.invalid_distance"] = "请输入 1 到 100 码之间的距离。",
["disperse.confirm.set"] = "分散距离已设置为 %s 码。",
Expand Down
1 change: 1 addition & 0 deletions MultiBot.toc
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ UI\MultiBotGmUI.lua
UI\MultiBotRTSCUI.lua
UI\MultiBotRTIUI.lua
UI\MultiBotDisperseUI.lua
UI\MultiBotLootUI.lua
Core\MultiBotInit.lua
Data\MultiBotIconos.lua
Data\MultiBotItemus.lua
Expand Down
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ GET~OUTFITS
RUN~RTI
RUN~COMBAT
RUN~POSITION
RUN~LOOT
```

Manual playerbot commands are still intentionally preserved for diagnostics and gameplay actions.
Expand Down Expand Up @@ -176,6 +177,10 @@ The goal is to remove automatic UI-refresh spam.
<td>Disperse controls</td>
<td><strong>Bridge-first</strong> distance set and disable actions through <code>RUN~POSITION</code></td>
</tr>
<tr>
<td>Loot rules</td>
<td><strong>Bridge-first</strong> loot enable/disable and loot list profiles through <code>RUN~LOOT</code></td>
</tr>
<tr>
<td>Units / EveryBars</td>
<td><strong>Improved</strong> login, reload and AddClass refresh behavior</td>
Expand Down Expand Up @@ -406,6 +411,7 @@ Implemented bridge-first / chatless areas:
- Pull Control frame through the bridge.
- Combat strategy fine tuning through the bridge.
- Disperse controls through the bridge with `disperse set <yards>` and `disperse disable`.
- Loot rules through the bridge with `nc +loot`, `nc -loot` and `ll all|normal|gray|quest|skill`.
- Custom glyph socket mapping and apply order.
- Talent tab navigation stability after switching between tabs.
- Automatic bot reconnect on login/reload for bots already present in the group or raid.
Expand All @@ -422,11 +428,11 @@ Kept intentionally:

# Remaining Work

The Outfits, RTI, Pull Control, Combat Strategy and Disperse migrations are implemented. The next step is final stabilization and cleanup.
The Outfits, RTI, Pull Control, Combat Strategy, Disperse and Loot Rules migrations are implemented. The next step is final stabilization and cleanup.

Planned follow-up work:

- Regression test login, `/reload`, large raid groups, Units, EveryBars, Stats, Inventory, Spellbook, Talents, Glyphs, Outfits, RTI, Pull Control, Combat Strategies and Disperse.
- Regression test login, `/reload`, large raid groups, Units, EveryBars, Stats, Inventory, Spellbook, Talents, Glyphs, Outfits, RTI, Pull Control, Combat Strategies, Disperse and Loot Rules.
- Verify that `MultiBot.allowLegacyChatFallback = false` prevents automatic legacy refresh spam on all migrated UI paths.
- Keep manual diagnostic commands documented and functional.
- Remove obsolete debug prints.
Expand Down
4 changes: 4 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
ATTENTION: Nouveau outfit par bridge il faut voire le cas de deux armes deux mains, le bot ne les équipe pas!
* J'ai l'impression que le disperse ne fait rien
* Passer les gobject dans la bridge
* Recentrer les icones des glyphes
* Mettre un bouton à raidus pour enlever les bots inconnus et les virer en même temps de saved variables
Expand All @@ -18,6 +19,9 @@ ATTENTION: Nouveau outfit par bridge il faut voire le cas de deux armes deux mai
* trouver un moyen de charger tous les skins des pets hunter
* Implémenter Focus
* Implémenter new pull
* Voir pour l'inventaire bridge si pas limité à 16 places
* Ne pas faire apparaitre les quick bares pour les joueurs humain
* Remplacer dans le menu loot Quest et Skill par desanchante

-- Nouvelles fonctions:
Gestion des Outfits
Expand Down
6 changes: 3 additions & 3 deletions UI/MultiBotDisperseUI.lua
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,9 @@ function MultiBot.BuildDisperseUI(tLeft)
local input = CreateFrame("EditBox", "MultiBotDisperseDistanceEditBox", menu, "InputBoxTemplate")
input:SetAutoFocus(false)
input:SetMaxLetters(3)
input:SetWidth(25)
input:SetWidth(40)
input:SetHeight(20)
input:SetPoint("TOPLEFT", menu, "TOPLEFT", 30, -23)
input:SetPoint("TOPLEFT", menu, "TOPLEFT", 23, -23)
input:SetText(lastDistance)
input:SetFrameLevel(menu:GetFrameLevel() + 3)
input:SetScript("OnEscapePressed", function(self)
Expand Down Expand Up @@ -152,7 +152,7 @@ function MultiBot.BuildDisperseUI(tLeft)
hideDisperseMenu()
else
showDisperseMenu()
end
end
end

button.doRight = function()
Expand Down
5 changes: 5 additions & 0 deletions UI/MultiBotLeftCoreUI.lua
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,10 @@ function MultiBot.InitializeLeftCoreUI(tLeft)
MultiBot.BuildDisperseUI(tLeft)
end

if MultiBot.BuildLootUI then
MultiBot.BuildLootUI(tLeft)
end

tLeft.addButton("Tanker", -170, 0, "ability_warrior_shieldbash", MultiBot.L("tips.tanker.master")).doLeft = function()
if MultiBot.isTarget() then
MultiBot.ActionToGroup("@tank do attack my target")
Expand All @@ -105,6 +109,7 @@ function MultiBot.InitializeLeftCoreUI(tLeft)
MultiBot.BindShiftRightSwapButtons(tLeft, "LeftRoot", {
{ name = "BotRTI", id = "BotRTIActionButton", frameName = "BotRTIAction" },
{ name = "Disperse", frameName = "DisperseMenu" },
{ name = "Loot", frameName = "LootMenu" },
{ name = "Tanker" },
{ name = "Mode", frameName = "Mode" },
{ name = "Stay" },
Expand Down
Loading
Loading