diff --git a/Core/MultiBotEvery.lua b/Core/MultiBotEvery.lua
index 6cf3d6c..eebcec9 100644
--- a/Core/MultiBotEvery.lua
+++ b/Core/MultiBotEvery.lua
@@ -331,4 +331,56 @@ MultiBot.addEvery = function(pFrame, pCombat, pNormal)
if(MultiBot.isInside(pNormal, "food")) then pFrame.getButton("Food").setEnable() end
if(MultiBot.isInside(pNormal, "loot")) then pFrame.getButton("Loot").setEnable() end
if(MultiBot.isInside(pNormal, "gather")) then pFrame.getButton("Gather").setEnable() end
+end
+
+local function sendCommonCombatStrategy(pButton, command)
+ local botName = pButton and pButton.getName and pButton.getName() or nil
+ if type(botName) ~= "string" or botName == "" then
+ return false
+ end
+
+ if MultiBot.Comm and type(MultiBot.Comm.RunCombatCommand) == "function" then
+ return MultiBot.Comm.RunCombatCommand("BOT", botName, command)
+ end
+
+ SendChatMessage(command, "WHISPER", nil, botName)
+ return true
+end
+
+local function addCommonCombatStrategyButton(pFrame, pCombat, tFrame, buttonName, y, icon, tipKey, strategyName)
+ if not pFrame or not tFrame or not tFrame.addButton then
+ return
+ end
+
+ local plusCommand = "co +" .. strategyName
+ local minusCommand = "co -" .. strategyName
+
+ local button = tFrame.addButton(
+ buttonName,
+ 0,
+ y,
+ "Interface\\Icons\\" .. icon,
+ MultiBot.L(tipKey)
+ ):setDisable()
+
+ button.doLeft = function(self)
+ if MultiBot.OnOffSwitch(self) then
+ sendCommonCombatStrategy(self, plusCommand)
+ else
+ sendCommonCombatStrategy(self, minusCommand)
+ end
+ end
+
+ if MultiBot.isInside(pCombat, strategyName) then
+ pFrame.getButton(buttonName).setEnable()
+ end
+end
+
+function MultiBot.AddCommonCombatStrategyButtons(pFrame, tFrame, pCombat, yOffset)
+ local y = tonumber(yOffset) or 0
+
+ addCommonCombatStrategyButton(pFrame, pCombat, tFrame, "AvoidAoe", y, "spell_shadow_antishadow.blp", "tips.every.strategy.avoidaoe", "avoid aoe")
+ addCommonCombatStrategyButton(pFrame, pCombat, tFrame, "SaveMana", y + 26, "spell_frost_manarecharge.blp", "tips.every.strategy.savemana", "save mana")
+ addCommonCombatStrategyButton(pFrame, pCombat, tFrame, "Threat", y + 52, "ability_warrior_challange.blp", "tips.every.strategy.threat", "threat")
+ addCommonCombatStrategyButton(pFrame, pCombat, tFrame, "Behind", y + 78, "ability_backstab.blp", "tips.every.strategy.behind", "behind")
end
\ No newline at end of file
diff --git a/Locales/MultiBotAceLocale-deDE.lua b/Locales/MultiBotAceLocale-deDE.lua
index 3997129..e11cbae 100644
--- a/Locales/MultiBotAceLocale-deDE.lua
+++ b/Locales/MultiBotAceLocale-deDE.lua
@@ -38,6 +38,19 @@ local deDEValues = {
["tips.rti.bot.action.attack.body"] = "Alle Bots mit gespeichertem persönlichem RTI-Symbol greifen ihr RTI-Ziel an.",
["tips.rti.bot.action.pull.title"] = "Pullen",
["tips.rti.bot.action.pull.body"] = "Alle Bots mit gespeichertem persönlichem RTI-Symbol pullen ihr RTI-Ziel.",
+ ["tips.main.combat"] = "Kampfstrategien",
+ ["tips.main.combat.party.avoidaoe"] = "Gruppe: Avoid AoE umschalten.",
+ ["tips.main.combat.raid.avoidaoe"] = "Raid: Avoid AoE umschalten.",
+ ["tips.main.combat.party.savemana"] = "Gruppe: Save Mana umschalten.",
+ ["tips.main.combat.raid.savemana"] = "Raid: Save Mana umschalten.",
+ ["tips.main.combat.party.threat"] = "Gruppe: Threat umschalten.",
+ ["tips.main.combat.raid.threat"] = "Raid: Threat umschalten.",
+ ["tips.main.combat.party.behind"] = "Gruppe: Behind umschalten.",
+ ["tips.main.combat.raid.behind"] = "Raid: Behind umschalten.",
+ ["tips.every.strategy.avoidaoe"] = "Avoid AoE",
+ ["tips.every.strategy.savemana"] = "Save Mana",
+ ["tips.every.strategy.threat"] = "Threat",
+ ["tips.every.strategy.behind"] = "Behind",
["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.",
diff --git a/Locales/MultiBotAceLocale-enGB.lua b/Locales/MultiBotAceLocale-enGB.lua
index a0ac2ef..b56a3a9 100644
--- a/Locales/MultiBotAceLocale-enGB.lua
+++ b/Locales/MultiBotAceLocale-enGB.lua
@@ -38,6 +38,19 @@ local enGBValues = {
["tips.rti.bot.action.attack.body"] = "All bots with a stored personal RTI icon attack their RTI target.",
["tips.rti.bot.action.pull.title"] = "Pull",
["tips.rti.bot.action.pull.body"] = "All bots with a stored personal RTI icon pull their RTI target.",
+ ["tips.main.combat"] = "Combat strategies",
+ ["tips.main.combat.party.avoidaoe"] = "Party: toggle Avoid AoE.",
+ ["tips.main.combat.raid.avoidaoe"] = "Raid: toggle Avoid AoE.",
+ ["tips.main.combat.party.savemana"] = "Party: toggle Save Mana.",
+ ["tips.main.combat.raid.savemana"] = "Raid: toggle Save Mana.",
+ ["tips.main.combat.party.threat"] = "Party: toggle Threat.",
+ ["tips.main.combat.raid.threat"] = "Raid: toggle Threat.",
+ ["tips.main.combat.party.behind"] = "Party: toggle Behind.",
+ ["tips.main.combat.raid.behind"] = "Raid: toggle Behind.",
+ ["tips.every.strategy.avoidaoe"] = "Avoid AoE",
+ ["tips.every.strategy.savemana"] = "Save Mana",
+ ["tips.every.strategy.threat"] = "Threat",
+ ["tips.every.strategy.behind"] = "Behind",
["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.",
diff --git a/Locales/MultiBotAceLocale-enUS.lua b/Locales/MultiBotAceLocale-enUS.lua
index 03a04b2..f595d59 100644
--- a/Locales/MultiBotAceLocale-enUS.lua
+++ b/Locales/MultiBotAceLocale-enUS.lua
@@ -38,6 +38,19 @@ local enUSValues = {
["tips.rti.bot.action.attack.body"] = "All bots with a stored personal RTI icon attack their RTI target.",
["tips.rti.bot.action.pull.title"] = "Pull",
["tips.rti.bot.action.pull.body"] = "All bots with a stored personal RTI icon pull their RTI target.",
+ ["tips.main.combat"] = "Combat strategies",
+ ["tips.main.combat.party.avoidaoe"] = "Party: toggle Avoid AoE.",
+ ["tips.main.combat.raid.avoidaoe"] = "Raid: toggle Avoid AoE.",
+ ["tips.main.combat.party.savemana"] = "Party: toggle Save Mana.",
+ ["tips.main.combat.raid.savemana"] = "Raid: toggle Save Mana.",
+ ["tips.main.combat.party.threat"] = "Party: toggle Threat.",
+ ["tips.main.combat.raid.threat"] = "Raid: toggle Threat.",
+ ["tips.main.combat.party.behind"] = "Party: toggle Behind.",
+ ["tips.main.combat.raid.behind"] = "Raid: toggle Behind.",
+ ["tips.every.strategy.avoidaoe"] = "Avoid AoE",
+ ["tips.every.strategy.savemana"] = "Save Mana",
+ ["tips.every.strategy.threat"] = "Threat",
+ ["tips.every.strategy.behind"] = "Behind",
["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.",
diff --git a/Locales/MultiBotAceLocale-esES.lua b/Locales/MultiBotAceLocale-esES.lua
index e13239a..9a894a4 100644
--- a/Locales/MultiBotAceLocale-esES.lua
+++ b/Locales/MultiBotAceLocale-esES.lua
@@ -38,6 +38,19 @@ local esESValues = {
["tips.rti.bot.action.attack.body"] = "Todos los bots con un icono RTI personal guardado atacan su objetivo RTI.",
["tips.rti.bot.action.pull.title"] = "Pull",
["tips.rti.bot.action.pull.body"] = "Todos los bots con un icono RTI personal guardado hacen pull a su objetivo RTI.",
+ ["tips.main.combat"] = "Estrategias de combate",
+ ["tips.main.combat.party.avoidaoe"] = "Grupo: alternar Avoid AoE.",
+ ["tips.main.combat.raid.avoidaoe"] = "Banda: alternar Avoid AoE.",
+ ["tips.main.combat.party.savemana"] = "Grupo: alternar Save Mana.",
+ ["tips.main.combat.raid.savemana"] = "Banda: alternar Save Mana.",
+ ["tips.main.combat.party.threat"] = "Grupo: alternar Threat.",
+ ["tips.main.combat.raid.threat"] = "Banda: alternar Threat.",
+ ["tips.main.combat.party.behind"] = "Grupo: alternar Behind.",
+ ["tips.main.combat.raid.behind"] = "Banda: alternar Behind.",
+ ["tips.every.strategy.avoidaoe"] = "Avoid AoE",
+ ["tips.every.strategy.savemana"] = "Save Mana",
+ ["tips.every.strategy.threat"] = "Threat",
+ ["tips.every.strategy.behind"] = "Behind",
["info.itemdestroyalert"] = "¿REALMENTE quieres destruir este objeto?\n%s",
["info.keydestroyalert"] = "No venderé llaves.",
["info.itemsellalert"] = "No puedo vender este objeto.",
diff --git a/Locales/MultiBotAceLocale-frFR.lua b/Locales/MultiBotAceLocale-frFR.lua
index a3b1963..21e576e 100644
--- a/Locales/MultiBotAceLocale-frFR.lua
+++ b/Locales/MultiBotAceLocale-frFR.lua
@@ -38,6 +38,19 @@ local frFRValues = {
["tips.rti.bot.action.attack.body"] = "Tous les bots avec une icône RTI personnelle mémorisée attaquent leur cible RTI.",
["tips.rti.bot.action.pull.title"] = "Pull",
["tips.rti.bot.action.pull.body"] = "Tous les bots avec une icône RTI personnelle mémorisée pull leur cible RTI.",
+ ["tips.main.combat"] = "Stratégies de combat",
+ ["tips.main.combat.party.avoidaoe"] = "Groupe : activer/désactiver Avoid AoE.",
+ ["tips.main.combat.raid.avoidaoe"] = "Raid : activer/désactiver Avoid AoE.",
+ ["tips.main.combat.party.savemana"] = "Groupe : activer/désactiver Save Mana.",
+ ["tips.main.combat.raid.savemana"] = "Raid : activer/désactiver Save Mana.",
+ ["tips.main.combat.party.threat"] = "Groupe : activer/désactiver Threat.",
+ ["tips.main.combat.raid.threat"] = "Raid : activer/désactiver Threat.",
+ ["tips.main.combat.party.behind"] = "Groupe : activer/désactiver Behind.",
+ ["tips.main.combat.raid.behind"] = "Raid : activer/désactiver Behind.",
+ ["tips.every.strategy.avoidaoe"] = "Avoid AoE",
+ ["tips.every.strategy.savemana"] = "Save Mana",
+ ["tips.every.strategy.threat"] = "Threat",
+ ["tips.every.strategy.behind"] = "Behind",
["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.",
diff --git a/Locales/MultiBotAceLocale-koKR.lua b/Locales/MultiBotAceLocale-koKR.lua
index 3d5f1d9..ea7db72 100644
--- a/Locales/MultiBotAceLocale-koKR.lua
+++ b/Locales/MultiBotAceLocale-koKR.lua
@@ -38,6 +38,19 @@ local koKRValues = {
["tips.rti.bot.action.attack.body"] = "개인 RTI 아이콘이 저장된 모든 봇이 자신의 RTI 대상을 공격합니다.",
["tips.rti.bot.action.pull.title"] = "풀링",
["tips.rti.bot.action.pull.body"] = "개인 RTI 아이콘이 저장된 모든 봇이 자신의 RTI 대상을 풀링합니다.",
+ ["tips.main.combat"] = "전투 전략",
+ ["tips.main.combat.party.avoidaoe"] = "파티: Avoid AoE 전환.",
+ ["tips.main.combat.raid.avoidaoe"] = "레이드: Avoid AoE 전환.",
+ ["tips.main.combat.party.savemana"] = "파티: Save Mana 전환.",
+ ["tips.main.combat.raid.savemana"] = "레이드: Save Mana 전환.",
+ ["tips.main.combat.party.threat"] = "파티: Threat 전환.",
+ ["tips.main.combat.raid.threat"] = "레이드: Threat 전환.",
+ ["tips.main.combat.party.behind"] = "파티: Behind 전환.",
+ ["tips.main.combat.raid.behind"] = "레이드: Behind 전환.",
+ ["tips.every.strategy.avoidaoe"] = "Avoid AoE",
+ ["tips.every.strategy.savemana"] = "Save Mana",
+ ["tips.every.strategy.threat"] = "Threat",
+ ["tips.every.strategy.behind"] = "Behind",
["info.itemdestroyalert"] = "이 아이템을 정말로 파기하시겠습니까?\n%s",
["info.keydestroyalert"] = "열쇠는 판매하지 않습니다.",
["info.itemsellalert"] = "이 아이템은 판매할 수 없습니다.",
diff --git a/Locales/MultiBotAceLocale-ruRU.lua b/Locales/MultiBotAceLocale-ruRU.lua
index 4b82e1b..a3f9b41 100644
--- a/Locales/MultiBotAceLocale-ruRU.lua
+++ b/Locales/MultiBotAceLocale-ruRU.lua
@@ -38,6 +38,19 @@ local ruRUValues = {
["tips.rti.bot.action.attack.body"] = "Все боты с сохранённой личной RTI-иконкой атакуют свою RTI-цель.",
["tips.rti.bot.action.pull.title"] = "Пулл",
["tips.rti.bot.action.pull.body"] = "Все боты с сохранённой личной RTI-иконкой пуллят свою RTI-цель.",
+ ["tips.main.combat"] = "Боевые стратегии",
+ ["tips.main.combat.party.avoidaoe"] = "Группа: переключить Avoid AoE.",
+ ["tips.main.combat.raid.avoidaoe"] = "Рейд: переключить Avoid AoE.",
+ ["tips.main.combat.party.savemana"] = "Группа: переключить Save Mana.",
+ ["tips.main.combat.raid.savemana"] = "Рейд: переключить Save Mana.",
+ ["tips.main.combat.party.threat"] = "Группа: переключить Threat.",
+ ["tips.main.combat.raid.threat"] = "Рейд: переключить Threat.",
+ ["tips.main.combat.party.behind"] = "Группа: переключить Behind.",
+ ["tips.main.combat.raid.behind"] = "Рейд: переключить Behind.",
+ ["tips.every.strategy.avoidaoe"] = "Avoid AoE",
+ ["tips.every.strategy.savemana"] = "Save Mana",
+ ["tips.every.strategy.threat"] = "Threat",
+ ["tips.every.strategy.behind"] = "Behind",
["info.itemdestroyalert"] = "Вы ДЕЙСТВИТЕЛЬНО хотите уничтожить этот предмет?\n%s",
["info.keydestroyalert"] = "Я не продаю ключи.",
["info.itemsellalert"] = "Я не могу продать этот предмет.",
diff --git a/Locales/MultiBotAceLocale-zhCN.lua b/Locales/MultiBotAceLocale-zhCN.lua
index ea9866d..4fb7fed 100644
--- a/Locales/MultiBotAceLocale-zhCN.lua
+++ b/Locales/MultiBotAceLocale-zhCN.lua
@@ -38,6 +38,19 @@ local zhCNValues = {
["tips.rti.bot.action.attack.body"] = "所有保存了个人 RTI 图标的机器人攻击其 RTI 目标。",
["tips.rti.bot.action.pull.title"] = "拉怪",
["tips.rti.bot.action.pull.body"] = "所有保存了个人 RTI 图标的机器人拉取其 RTI 目标。",
+ ["tips.main.combat"] = "战斗策略",
+ ["tips.main.combat.party.avoidaoe"] = "小队:切换 Avoid AoE。",
+ ["tips.main.combat.raid.avoidaoe"] = "团队:切换 Avoid AoE。",
+ ["tips.main.combat.party.savemana"] = "小队:切换 Save Mana。",
+ ["tips.main.combat.raid.savemana"] = "团队:切换 Save Mana。",
+ ["tips.main.combat.party.threat"] = "小队:切换 Threat。",
+ ["tips.main.combat.raid.threat"] = "团队:切换 Threat。",
+ ["tips.main.combat.party.behind"] = "小队:切换 Behind。",
+ ["tips.main.combat.raid.behind"] = "团队:切换 Behind。",
+ ["tips.every.strategy.avoidaoe"] = "Avoid AoE",
+ ["tips.every.strategy.savemana"] = "Save Mana",
+ ["tips.every.strategy.threat"] = "Threat",
+ ["tips.every.strategy.behind"] = "Behind",
["info.itemdestroyalert"] = "你真的要销毁这个物品吗?\n%s",
["info.keydestroyalert"] = "我不会出售钥匙。",
["info.itemsellalert"] = "我无法出售该物品。",
diff --git a/README.md b/README.md
index de845e5..cd796c3 100644
--- a/README.md
+++ b/README.md
@@ -94,6 +94,8 @@ GET~INVENTORY
GET~SPELLBOOK
GET~GLYPHS
GET~OUTFITS
+RUN~RTI
+RUN~COMBAT
```
Manual playerbot commands are still intentionally preserved for diagnostics and gameplay actions.
@@ -157,6 +159,18 @@ The goal is to remove automatic UI-refresh spam.
Outfits |
Bridge-first listing, create/update, reset, equip and replace |
+
+ | RTI controls |
+ Bridge-first icon assignment and RTI target actions |
+
+
+ | Pull Control |
+ Bridge-first wait, focus, DPS assist, AoE and RTI pull/attack controls |
+
+
+ | Combat strategy fine tuning |
+ Bridge-first avoid AoE, save mana, threat and behind controls |
+
| Units / EveryBars |
Improved login, reload and AddClass refresh behavior |
@@ -383,6 +397,9 @@ Implemented bridge-first / chatless areas:
- Glyph refresh with icons and glyph tooltips.
- Outfits refresh and actions through the bridge.
- Outfit equip/replace without detailed `Equipping [item] ...` chat spam.
+- RTI controls through the bridge.
+- Pull Control frame through the bridge.
+- Combat strategy fine tuning through the bridge.
- 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.
@@ -399,11 +416,12 @@ Kept intentionally:
# Remaining Work
-The Outfits migration is complete. The next step is final stabilization and cleanup.
+The Outfits, RTI, Pull Control and Combat Strategy migrations are implemented. The next step is Disperse, followed by final stabilization and cleanup.
Planned follow-up work:
-- Regression test login, `/reload`, large raid groups, Units, EveryBars, Stats, Inventory, Spellbook, Talents, Glyphs and Outfits.
+- Start the Disperse command migration.
+- Regression test login, `/reload`, large raid groups, Units, EveryBars, Stats, Inventory, Spellbook, Talents, Glyphs, Outfits, RTI, Pull Control and Combat Strategies.
- 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.
diff --git a/Strategies/MultiBotDeathKnight.lua b/Strategies/MultiBotDeathKnight.lua
index 79c83dc..660f125 100644
--- a/Strategies/MultiBotDeathKnight.lua
+++ b/Strategies/MultiBotDeathKnight.lua
@@ -91,6 +91,10 @@ MultiBot.addDeathKnight = function(pFrame, pCombat, pNormal)
end
end
+ if MultiBot.AddCommonCombatStrategyButtons then
+ MultiBot.AddCommonCombatStrategyButtons(pFrame, tDpsFrame, pCombat, 104)
+ end
+
-- ASSIST --
pFrame.addButton("TankAssist", -60, 0, "ability_warrior_innerrage", MultiBot.L("tips.deathknight.tankAssist")).setDisable()
diff --git a/Strategies/MultiBotDruid.lua b/Strategies/MultiBotDruid.lua
index 733cc32..bee9517 100644
--- a/Strategies/MultiBotDruid.lua
+++ b/Strategies/MultiBotDruid.lua
@@ -163,6 +163,10 @@ MultiBot.addDruid = function(pFrame, pCombat, pNormal)
end
end
+ if MultiBot.AddCommonCombatStrategyButtons then
+ MultiBot.AddCommonCombatStrategyButtons(pFrame, tDpsFrame, pCombat, 156)
+ end
+
-- ASSIST --
pFrame.addButton("TankAssist", -120, 0, "ability_warrior_innerrage", MultiBot.L("tips.druid.tankAssist")).setDisable()
diff --git a/Strategies/MultiBotHunter.lua b/Strategies/MultiBotHunter.lua
index 190bbf9..aa76124 100644
--- a/Strategies/MultiBotHunter.lua
+++ b/Strategies/MultiBotHunter.lua
@@ -162,6 +162,10 @@ MultiBot.addHunter = function(pFrame, pCombat, pNormal)
MultiBot.OnOffActionToTarget(pButton, "co +trap weave,?", "co -trap weave,?", pButton.getName())
end
+ if MultiBot.AddCommonCombatStrategyButtons then
+ MultiBot.AddCommonCombatStrategyButtons(pFrame, dpsFrame, pCombat, 130)
+ end
+
-- ASSIST --
pFrame.addButton("TankAssist", -90, 0, "ability_warrior_innerrage", MultiBot.L("tips.hunter.tankAssist")).setDisable()
diff --git a/Strategies/MultiBotMage.lua b/Strategies/MultiBotMage.lua
index d0255fe..30302cc 100644
--- a/Strategies/MultiBotMage.lua
+++ b/Strategies/MultiBotMage.lua
@@ -141,6 +141,10 @@ MultiBot.addMage = function(pFrame, pCombat, pNormal)
end
end
+ if MultiBot.AddCommonCombatStrategyButtons then
+ MultiBot.AddCommonCombatStrategyButtons(pFrame, dpsControlFrame, pCombat, 52)
+ end
+
-- ASSIST --
pFrame.addButton("TankAssist", -90, 0, "ability_warrior_innerrage", MultiBot.L("tips.mage.tankAssist")).setDisable()
diff --git a/Strategies/MultiBotPaladin.lua b/Strategies/MultiBotPaladin.lua
index ca9a2ef..b59f244 100644
--- a/Strategies/MultiBotPaladin.lua
+++ b/Strategies/MultiBotPaladin.lua
@@ -322,6 +322,10 @@ MultiBot.addPaladin = function(pFrame, pCombat, pNormal)
end
end
+ if MultiBot.AddCommonCombatStrategyButtons then
+ MultiBot.AddCommonCombatStrategyButtons(pFrame, dpsFrame, pCombat, 130)
+ end
+
-- ASSIST --
pFrame.addButton("TankAssist", -150, 0, "ability_warrior_innerrage", MultiBot.L("tips.paladin.tankAssist")).setDisable()
diff --git a/Strategies/MultiBotPriest.lua b/Strategies/MultiBotPriest.lua
index ed326e6..30e442f 100644
--- a/Strategies/MultiBotPriest.lua
+++ b/Strategies/MultiBotPriest.lua
@@ -118,6 +118,10 @@ MultiBot.addPriest = function(pFrame, pCombat, pNormal)
end
end
+ if MultiBot.AddCommonCombatStrategyButtons then
+ MultiBot.AddCommonCombatStrategyButtons(pFrame, dpsControlFrame, pCombat, 104)
+ end
+
-- ASSIST --
pFrame.addButton("TankAssist", -120, 0, "ability_warrior_innerrage", MultiBot.L("tips.priest.tankAssist")).setDisable()
diff --git a/Strategies/MultiBotRogue.lua b/Strategies/MultiBotRogue.lua
index 8621c2b..d08d4ae 100644
--- a/Strategies/MultiBotRogue.lua
+++ b/Strategies/MultiBotRogue.lua
@@ -52,6 +52,10 @@ MultiBot.addRogue = function(pFrame, pCombat, pNormal)
MultiBot.OnOffActionToTarget(pButton, "co +boost,?", "co -boost,?", pButton.getName())
end
+ if MultiBot.AddCommonCombatStrategyButtons then
+ MultiBot.AddCommonCombatStrategyButtons(pFrame, tFrame, pCombat, 156)
+ end
+
-- ASSIST --
pFrame.addButton("TankAssist", -30, 0, "ability_warrior_innerrage", MultiBot.L("tips.rogue.tankAssist")).setDisable()
diff --git a/Strategies/MultiBotShaman.lua b/Strategies/MultiBotShaman.lua
index 9d5cadc..3ff453c 100644
--- a/Strategies/MultiBotShaman.lua
+++ b/Strategies/MultiBotShaman.lua
@@ -194,6 +194,10 @@ MultiBot.addShaman = function(pFrame, pCombat, pNormal)
end
end
+ if MultiBot.AddCommonCombatStrategyButtons then
+ MultiBot.AddCommonCombatStrategyButtons(pFrame, dpsControlFrame, pCombat, 78)
+ end
+
-- ASSIST --
pFrame.addButton("TankAssist", -150, 0, "ability_warrior_innerrage", MultiBot.L("tips.shaman.tankAssist")).setDisable()
diff --git a/Strategies/MultiBotWarlock.lua b/Strategies/MultiBotWarlock.lua
index c159919..61b7977 100644
--- a/Strategies/MultiBotWarlock.lua
+++ b/Strategies/MultiBotWarlock.lua
@@ -400,7 +400,7 @@ MultiBot.addWarlock = function(pFrame, pCombat, pNormal)
-- META MELEE (Démonologie) --
local btnMeta = tFrame.addButton(
- "MetaMelee", 0, 104, "Spell_Shadow_DemonForm",
+ "MetaMelee", 0, 105, "Spell_Shadow_DemonForm",
(MultiBot.L("tips.warlock.dps.metamelee") ~= "tips.warlock.dps.metamelee" and MultiBot.L("tips.warlock.dps.metamelee") or "Meta Melee")
)
btnMeta.setDisable()
@@ -409,6 +409,10 @@ MultiBot.addWarlock = function(pFrame, pCombat, pNormal)
MultiBot.OnOffActionToTarget(pButton, "co +meta melee,?", "co -meta melee,?", pButton.getName())
end
+ if MultiBot.AddCommonCombatStrategyButtons then
+ MultiBot.AddCommonCombatStrategyButtons(pFrame, tFrame, pCombat, 131)
+ end
+
-- ASSIST --
pFrame.addButton("TankAssist", -60, 0, "ability_warrior_innerrage", MultiBot.L("tips.warlock.tankAssist")).setDisable()
diff --git a/Strategies/MultiBotWarrior.lua b/Strategies/MultiBotWarrior.lua
index 4cb13c0..1ef87f3 100644
--- a/Strategies/MultiBotWarrior.lua
+++ b/Strategies/MultiBotWarrior.lua
@@ -23,6 +23,10 @@ MultiBot.addWarrior = function(pFrame, pCombat, pNormal)
end
end
+ if MultiBot.AddCommonCombatStrategyButtons then
+ MultiBot.AddCommonCombatStrategyButtons(pFrame, tFrame, pCombat, 52)
+ end
+
-- ASSIST --
pFrame.addButton("TankAssist", -30, 0, "ability_warrior_innerrage", MultiBot.L("tips.warrior.tankAssist")).setDisable()
diff --git a/UI/MultiBotMainUI.lua b/UI/MultiBotMainUI.lua
index d613cce..d06c3a8 100644
--- a/UI/MultiBotMainUI.lua
+++ b/UI/MultiBotMainUI.lua
@@ -718,6 +718,143 @@ local function createPullControlFrame(mainFrame, pullButton)
return frame
end
+local function sendMainCombatStrategy(scope, strategyName, enabled)
+ local command = "co " .. (enabled and "+" or "-") .. strategyName
+
+ if MultiBot.Comm and type(MultiBot.Comm.RunCombatCommand) == "function" then
+ return MultiBot.Comm.RunCombatCommand(scope, "", command)
+ end
+
+ if scope == "ALL" then
+ SendChatMessage(command, GetNumRaidMembers() > 0 and "RAID" or "PARTY")
+ else
+ SendChatMessage(command, "PARTY")
+ end
+
+ return true
+end
+
+local function showMainCombatStrategyTooltip(owner)
+ if not owner or not GameTooltip then
+ return
+ end
+
+ GameTooltip:SetOwner(owner, "ANCHOR_RIGHT")
+ GameTooltip:SetText(owner._mbTip or "", 1, 1, 1, true)
+ GameTooltip:Show()
+end
+
+local function hideMainCombatStrategyTooltip()
+ if GameTooltip then
+ GameTooltip:Hide()
+ end
+end
+
+local function addMainCombatStrategyButton(frame, name, x, y, icon, tipKey, scope, strategyName)
+ if not frame then
+ return nil
+ end
+
+ local button = CreateFrame("Button", "MultiBot" .. name, frame)
+ button:SetSize(28, 28)
+ button:SetPoint("TOPLEFT", frame, "TOPLEFT", x, y)
+ button:RegisterForClicks("LeftButtonDown")
+ button:SetHighlightTexture("Interface\\Buttons\\ButtonHilight-Square", "ADD")
+ button:SetPushedTexture("Interface\\Buttons\\UI-Quickslot-Depress")
+ button._mbTip = MultiBot.L(tipKey)
+ button._mbScope = scope
+ button._mbStrategyName = strategyName
+
+ button.icon = button:CreateTexture(nil, "BACKGROUND")
+ button.icon:SetTexture(MultiBot.SafeTexturePath("Interface\\Icons\\" .. icon))
+ button.icon:SetAllPoints(button)
+
+ button.border = button:CreateTexture(nil, "ARTWORK")
+ button.border:SetTexture("Interface\\AddOns\\MultiBot\\Icons\\border.blp")
+ button.border:SetPoint("CENTER", button, "CENTER", 0, 0)
+ button.border:SetSize(34, 34)
+ button.border:Hide()
+
+ button:SetScript("OnEnter", showMainCombatStrategyTooltip)
+ button:SetScript("OnLeave", hideMainCombatStrategyTooltip)
+ button:SetScript("OnClick", function(self)
+ local enabled = not self.state
+ if sendMainCombatStrategy(self._mbScope, self._mbStrategyName, enabled) then
+ setPullControlButtonState(self, enabled)
+ end
+ end)
+
+ setPullControlButtonState(button, false)
+
+ frame.buttons = frame.buttons or {}
+ frame.buttons[name] = button
+ return button
+end
+
+local function createCombatStrategiesHeader(frame, text, x)
+ local label = frame:CreateFontString(nil, "ARTWORK")
+ label:SetFont("Fonts\\ARIALN.ttf", 10, "OUTLINE")
+ label:SetPoint("TOPLEFT", frame, "TOPLEFT", x, -8)
+ label:SetWidth(34)
+ label:SetJustifyH("CENTER")
+ label:SetText(text)
+ return label
+end
+
+local function createCombatStrategiesButton(mainFrame)
+ local controlFrame = CreateFrame("Frame", "MultiBotCombatStrategiesControl", mainFrame)
+ controlFrame:SetSize(92, 138)
+ controlFrame:SetFrameLevel((mainFrame:GetFrameLevel() or 0) + 20)
+ controlFrame:EnableMouse(true)
+ controlFrame._mbDropdownManaged = true
+ controlFrame:Hide()
+
+ controlFrame.bg = controlFrame:CreateTexture(nil, "BACKGROUND")
+ controlFrame.bg:SetTexture("Interface\\Buttons\\WHITE8X8")
+ controlFrame.bg:SetAllPoints(controlFrame)
+ controlFrame.bg:SetVertexColor(0, 0, 0, 0.78)
+
+ controlFrame.edge = CreateFrame("Frame", nil, controlFrame)
+ controlFrame.edge:SetPoint("TOPLEFT", controlFrame, "TOPLEFT", -1, 1)
+ controlFrame.edge:SetPoint("BOTTOMRIGHT", controlFrame, "BOTTOMRIGHT", 1, -1)
+ controlFrame.edge:SetBackdrop({
+ edgeFile = "Interface\\Tooltips\\UI-Tooltip-Border",
+ edgeSize = 12,
+ })
+ controlFrame.edge:SetBackdropBorderColor(0.85, 0.85, 0.85, 0.85)
+
+ createCombatStrategiesHeader(controlFrame, "Party", 10)
+ createCombatStrategiesHeader(controlFrame, "Raid", 50)
+
+ addMainCombatStrategyButton(controlFrame, "CombatPartyAvoidAoe", 12, -26, "spell_shadow_antishadow", "tips.main.combat.party.avoidaoe", "GROUP", "avoid aoe")
+ addMainCombatStrategyButton(controlFrame, "CombatRaidAvoidAoe", 52, -26, "spell_shadow_antishadow.blp", "tips.main.combat.raid.avoidaoe", "ALL", "avoid aoe")
+ addMainCombatStrategyButton(controlFrame, "CombatPartySaveMana", 12, -54, "spell_frost_manarecharge.blp", "tips.main.combat.party.savemana", "GROUP", "save mana")
+ addMainCombatStrategyButton(controlFrame, "CombatRaidSaveMana", 52, -54, "spell_frost_manarecharge.blp", "tips.main.combat.raid.savemana", "ALL", "save mana")
+ addMainCombatStrategyButton(controlFrame, "CombatPartyThreat", 12, -82, "ability_warrior_challange.blp", "tips.main.combat.party.threat", "GROUP", "threat")
+ addMainCombatStrategyButton(controlFrame, "CombatRaidThreat", 52, -82, "ability_warrior_challange.blp", "tips.main.combat.raid.threat", "ALL", "threat")
+ addMainCombatStrategyButton(controlFrame, "CombatPartyBehind", 12, -110, "ability_backstab.blp", "tips.main.combat.party.behind", "GROUP", "behind")
+ addMainCombatStrategyButton(controlFrame, "CombatRaidBehind", 52, -110, "ability_backstab.blp", "tips.main.combat.raid.behind", "ALL", "behind")
+
+ return createMainActionButton(mainFrame, {
+ name = "CombatStrategies",
+ y = 340,
+ icon = "ability_warrior_battleshout",
+ tip = "tips.main.combat",
+ doLeft = function(button)
+ if controlFrame:IsShown() then
+ controlFrame:Hide()
+ button:setDisable()
+ return
+ end
+
+ controlFrame:ClearAllPoints()
+ controlFrame:SetPoint("RIGHT", button, "LEFT", -6, 0)
+ controlFrame:Show()
+ button:setEnable()
+ end,
+ })
+end
+
local function saveMultiBarPosition()
local multiBar = MultiBot.frames and MultiBot.frames["MultiBar"]
if not multiBar or not MultiBot.SetSavedLayoutValue or not MultiBot.toPoint then
@@ -1086,6 +1223,7 @@ function MultiBot.InitializeMainUI(tMultiBar)
"Release",
"Stats",
"Reward",
+ "CombatStrategies",
"PullControl",
"Reset",
"Actions",
@@ -1255,6 +1393,9 @@ function MultiBot.InitializeMainUI(tMultiBar)
local rewardButton = createRewardButton(mainFrame)
wireShiftRightSwap(rewardButton, "Reward")
+
+ local combatStrategiesButton = createCombatStrategiesButton(mainFrame)
+ wireShiftRightSwap(combatStrategiesButton, "CombatStrategies")
local pullControlButton = createMainActionButton(mainFrame, {
name = "PullControl",
diff --git a/docs/multibot_missing_commands_roadmap.md b/docs/multibot_missing_commands_roadmap.md
index 68c6570..79ae027 100644
--- a/docs/multibot_missing_commands_roadmap.md
+++ b/docs/multibot_missing_commands_roadmap.md
@@ -9,7 +9,7 @@ Ce document suit les commandes `mod-playerbots` encore intéressantes à intégr
- les commandes serveur/admin à ne pas intégrer dans l'addon ;
- les priorités d'intégration bridge-first/chatless.
-Le principe reste le même que pour Inventory, Spellbook, Glyphs, Talents, Stats, Quests, Outfits, RTI et Pull Control :
+Le principe reste le même que pour Inventory, Spellbook, Glyphs, Talents, Stats, Quests, Outfits, RTI, Pull Control et Combat Strategies :
**éviter le spam chat automatique**, utiliser le bridge quand c'est possible, et conserver les commandes manuelles utiles comme `who`, `co ?`, `nc ?`, `ss ?`.
---
@@ -31,10 +31,13 @@ Le principe reste le même que pour Inventory, Spellbook, Glyphs, Talents, Stats
| Outfits | Fait | Endpoint bridge + commandes outfits intégrées. |
| RTI / Target Icons | Fait | UI complète + bridge `RUN~RTI`, scopes `ALL`, `GROUP`, `BOT`. |
| Pull Control | Fait / à fignoler | Mini-frame MainBar + bridge `RUN~COMBAT`, séquences de commandes, scopes et presets. |
+| Combat Strategies | Fait / à tester large | Toggles individuels dans les EveryBars + mini-frame Party/Raid, via `RUN~COMBAT`. |
---
-## Dernier lot terminé : Pull Control
+## Derniers lots terminés : Pull Control + Combat Strategies
+
+### Pull Control
Le panneau `Pull Control` a été ajouté comme mini-frame ouverte depuis la MainBar. Il utilise le bridge et ne repose pas sur le parsing chat automatique.
@@ -71,11 +74,35 @@ Fonctionnalités terminées :
- vérification de chaque preset en conditions réelles donjon/raid ;
- éventuelle sauvegarde persistante du dernier scope et de la dernière valeur de wait.
+### Combat Strategies
+
+Le bloc `Combat Strategies` a été ajouté pour les stratégies permanentes ou semi-permanentes qui ne sont pas strictement liées au pull.
+
+Fonctionnalités terminées :
+
+- les stratégies déjà couvertes par des boutons dédiés n'ont pas été dupliquées inutilement ;
+- les nouvelles stratégies ajoutées sont :
+ - `co +avoid aoe` / `co -avoid aoe` ;
+ - `co +save mana` / `co -save mana` ;
+ - `co +threat` / `co -threat` ;
+ - `co +behind` / `co -behind` ;
+- côté individuel, les toggles sont ajoutés dans le menu/mini-frame déjà lié au bouton `Strategies DPS` de chaque EveryBar ;
+- côté groupe/raid, une mini-frame séparée depuis la MainBar permet d'appliquer les mêmes toggles en scope `GROUP` ou `ALL` ;
+- le bridge accepte maintenant ces commandes dans la whitelist `RUN~COMBAT` ;
+- les commandes sont routées sans parsing automatique du retour `co ?`.
+
+Choix volontaire :
+
+- `co +tank face` / `co -tank face` n'a pas été ajouté ici, car le comportement tank a déjà des boutons dédiés dans les EveryBars ;
+- `co +healer dps` / `co -healer dps` n'a pas été ajouté ici, car un contrôle dédié existe déjà côté EveryBar ;
+- `co +boost` / `co -boost` n'a pas été ajouté ici, car `Boost` est déjà exposé ailleurs.
+
Notes fonctionnelles importantes :
- Les commandes `co ?`, `nc ?`, `ss ?` restent manuelles et ne doivent pas devenir une source de parsing automatique.
-- Le fait qu'une stratégie apparaisse ou non dans `co ?` dépend du nom exact réellement reconnu côté playerbots. Pour le Pull Control, on garde les noms qui ont été validés via bridge/serveur.
+- Le fait qu'une stratégie apparaisse ou non dans `co ?` dépend du nom exact réellement reconnu côté playerbots.
- `wait for attack time X` n'est pas une stratégie `co`, donc il ne faut pas attendre qu'elle apparaisse forcément dans `co ?`.
+- Pour les nouvelles stratégies, le test principal est le comportement réel du bot et la présence d'un `COMBAT_ACK` côté bridge, pas uniquement l'affichage dans `co ?`.
---
@@ -139,7 +166,7 @@ RUN~RTI~BOT~Dollu~~attack rti target
- Le reset remet l'icône par défaut.
- `Attack` / `Pull` déclenchent les groupes configurés ou tous les bots selon le scope.
-#### Everybar de bot
+#### EveryBar de bot
```text
[RTI bot]
@@ -148,19 +175,21 @@ RUN~RTI~BOT~Dollu~~attack rti target
- Chaque bot peut recevoir son RTI personnel.
- Le choix est mémorisé visuellement pendant l'ouverture/fermeture des Units.
-- Le bouton batch de la main bar permet d'envoyer tous les bots personnels en même temps.
+- Le bouton batch de la MainBar permet d'envoyer tous les bots personnels en même temps.
-#### Main bar
+#### MainBar
```text
-[Bot RTI Action] [Pull Control] [Attaque Tank]
+[Bot RTI Action] [Pull Control] [Combat Strategies] [Attaque Tank]
└─ Bot RTI Action : Attaquer / Pull pour les bots ayant une RTI personnelle
└─ Pull Control : mini-frame de pull, wait, focus, assist, AoE et actions RTI
+ └─ Combat Strategies : mini-frame Party/Raid pour stratégies combat avancées
```
- `Attaquer` envoie `attack rti target` à tous les bots ayant une RTI personnelle mémorisée.
- `Pull` envoie `pull rti target` à tous les bots ayant une RTI personnelle mémorisée.
- `Pull Control` permet d'envoyer les mêmes actions RTI avec un scope choisi.
+- `Combat Strategies` permet d'appliquer les stratégies avancées au groupe ou au raid.
---
@@ -217,55 +246,77 @@ RUN~COMBAT~GROUP~~~wait for attack time 3
### Statut
-**Prochaine étape logique.**
+**Terminé côté MultiBot + bridge, à tester en conditions réelles.**
-Pull Control a posé la base technique : l'addon sait maintenant envoyer des commandes combat simples via `RUN~COMBAT`. La suite naturelle est donc d'exposer les stratégies combat utiles qui ne sont pas strictement liées au pull.
+Pull Control a posé la base technique avec `RUN~COMBAT`. Cette étape a été utilisée pour exposer les stratégies combat utiles qui ne sont pas strictement liées au pull.
### Pourquoi
-Ces stratégies existent côté playerbots mais ne sont pas toutes exposées clairement dans MultiBot. Elles ont une vraie utilité en raid/donjon, mais ne doivent pas encombrer la MainBar.
+Ces stratégies existent côté playerbots mais n'étaient pas toutes exposées clairement dans MultiBot. Elles ont une vraie utilité en raid/donjon, mais ne doivent pas encombrer la MainBar.
-### Commandes à couvrir
+### Commandes couvertes
| Stratégie | Commande | Statut MultiBot | Priorité | Intérêt |
|---|---|---:|---:|---|
-| Avoid AoE | `co +avoid aoe` / `co -avoid aoe` | À vérifier / probablement partiel | Haute | Évite les AoE dangereuses |
-| Save Mana | `co +save mana` / `co -save mana` | Manquant | Haute | Gestion mana healers/casters |
-| Threat | `co +threat` / `co -threat` | Manquant | Haute | Limite la prise d'aggro selon comportement playerbots |
-| Tank Face | `co +tank face` / `co -tank face` | Manquant | Moyenne | Gestion orientation tank, cleaves, breaths |
-| Behind | `co +behind` / `co -behind` | Manquant ou déjà visible selon states | Moyenne | Placement melee derrière la cible |
-| Healer DPS | `co +healer dps` / `co -healer dps` | À vérifier | Moyenne | Autorise/interdit le DPS des healers |
-| Boost | `co +boost` / `co -boost` | Probablement partiel | Moyenne | Burst cooldowns |
+| Avoid AoE | `co +avoid aoe` / `co -avoid aoe` | Fait | Haute | Évite les AoE dangereuses |
+| Save Mana | `co +save mana` / `co -save mana` | Fait | Haute | Gestion mana healers/casters |
+| Threat | `co +threat` / `co -threat` | Fait | Haute | Limite la prise d'aggro selon comportement playerbots |
+| Behind | `co +behind` / `co -behind` | Fait | Moyenne | Placement melee derrière la cible |
+| Tank Face | `co +tank face` / `co -tank face` | Non ajouté volontairement | Moyenne | Déjà couvert par boutons dédiés EveryBar |
+| Healer DPS | `co +healer dps` / `co -healer dps` | Non ajouté volontairement | Moyenne | Déjà couvert par boutons dédiés EveryBar |
+| Boost | `co +boost` / `co -boost` | Non ajouté volontairement | Moyenne | Déjà exposé ailleurs |
| Focus | `co +focus` / `co -focus` | Fait via Pull Control | Référence | Focus mono-cible |
| DPS Assist | `co +dps assist` / `co -dps assist` | Fait via Pull Control | Référence | Assist DPS |
| DPS AoE | `co +dps aoe` / `co -dps aoe` | Fait via Pull Control | Référence | Autorise AoE DPS |
| Wait for attack | `wait for attack time X` | Fait via Pull Control | Référence | Pull contrôlé |
-### Proposition UI
+### UX actuelle
-Créer une page ou mini-frame `Advanced Combat`, séparée de Pull Control :
+#### EveryBar / bot individuel
+
+Les stratégies individuelles sont ajoutées au menu existant `Strategies DPS` de chaque bot.
```text
-Combat Strategies
-├─ Scope: Selected / Party / Raid
-├─ Survivability: Avoid AoE, Threat
-├─ Positioning: Behind, Tank Face
-├─ Resource: Save Mana
-├─ Damage policy: Healer DPS, Boost
-└─ Apply toggles via RUN~COMBAT
+EveryBar bot
+└─ Strategies DPS
+ ├─ Avoid AoE
+ ├─ Save Mana
+ ├─ Threat
+ └─ Behind
```
-Recommandation UX :
+Ce choix évite d'ajouter une mini-frame globale pour du fine-tuning individuel : chaque bot reste configurable depuis sa propre barre.
+
+#### MainBar / groupe et raid
+
+Une mini-frame séparée sert uniquement aux scopes collectifs.
+
+```text
+MainBar
+└─ Combat Strategies
+ ├─ Scope: Party / Raid
+ ├─ Avoid AoE
+ ├─ Save Mana
+ ├─ Threat
+ └─ Behind
+```
+
+Recommandation UX conservée :
- ne pas ajouter ces toggles directement sur la MainBar ;
-- créer un panneau repliable ou une sous-page accessible depuis un bouton existant de stratégies/combat ;
-- réutiliser les scopes `BOT`, `GROUP`, `ALL` déjà validés par Pull Control ;
+- garder les actions individuelles dans les EveryBars ;
+- garder la frame MainBar pour les actions Party/Raid ;
+- réutiliser les scopes `GROUP` et `ALL` déjà validés par Pull Control ;
- garder `co ?` comme vérification manuelle, sans parser automatiquement son retour.
---
## Priorité 4 - Disperse
+### Statut
+
+**Prochaine étape logique.**
+
### Pourquoi
Très utile pour les mécaniques AoE ou les combats où les bots doivent s'espacer.
@@ -288,7 +339,7 @@ Disperse distance: [ 8 ] yards
### Note
-À faire après `Advanced Combat`, sauf si un besoin immédiat de mécaniques AoE impose de le passer avant.
+À faire après stabilisation RTI/Pull Control/Combat Strategies, sauf si un autre besoin gameplay devient prioritaire.
---
@@ -296,7 +347,7 @@ Disperse distance: [ 8 ] yards
### Pourquoi
-Le contrôle du loot est utile, mais moins prioritaire que RTI/pull/combat.
+Le contrôle du loot est utile, mais moins prioritaire que RTI/pull/combat/disperse.
### Commandes à couvrir
@@ -445,8 +496,8 @@ Ces commandes sont plutôt serveur/admin/debug ou trop dangereuses pour une UI u
|---:|---|---|---:|---:|
| 1 | RTI bridge-first | UI + bridge command | Haute | Fait |
| 2 | Pull Control avancé | Nouvelle UI + séquences commandes | Haute | Fait / à fignoler |
-| 3 | Advanced Combat Strategies | UI toggles réutilisant `RUN~COMBAT` | Haute/Moyenne | Prochaine étape |
-| 4 | Disperse | Petite UI + commande combat/mouvement | Moyenne | À faire |
+| 3 | Advanced Combat Strategies | EveryBars + mini-frame Party/Raid via `RUN~COMBAT` | Haute/Moyenne | Fait / à tester |
+| 4 | Disperse | Petite UI + commande combat/mouvement | Moyenne | Prochaine étape |
| 5 | Loot Rules | Petite UI profils | Moyenne | À faire |
| 6 | Trainer / Maintenance extras | UI maintenance | Moyenne/Basse | À faire |
| 7 | Items avancés | Extensions inventaire | Basse/Moyenne | À faire |
@@ -462,15 +513,21 @@ Ces commandes sont plutôt serveur/admin/debug ou trop dangereuses pour une UI u
- Pour les commandes qui doivent alimenter une frame, préférer un endpoint structuré dédié.
- Les commandes serveur/admin ne doivent pas être exposées dans l'addon utilisateur.
- Les boutons ajoutés dans les barres doivent conserver une position cohérente avec `MultiBotLeftCoreUI.lua` et la position par défaut de `MultiBar` dans `MultiBotInit.lua` / reset dans `MultiBotMainUI.lua`.
-- Les tooltips nouvellement ajoutés doivent passer par AceLocale, comme les tooltips RTI et Pull Control.
+- Les tooltips nouvellement ajoutés doivent passer par AceLocale, comme les tooltips RTI, Pull Control et Combat Strategies.
- `RUN~COMBAT` doit rester whitelisté côté bridge : ne pas en faire un exécuteur libre de n'importe quelle commande chat.
+- Éviter les doublons UI : si une stratégie dispose déjà d'un bouton EveryBar dédié, ne pas la rajouter dans une nouvelle frame sauf besoin UX clairement identifié.
---
## Point logique suivant
-Le prochain bloc logique est **Advanced Combat Strategies**.
+Le prochain bloc logique est **Disperse**.
+
+Raison : les blocs RTI, Pull Control et Combat Strategies couvrent maintenant le ciblage, le pull et les stratégies combat de base. `Disperse` complète naturellement ce trio en ajoutant un contrôle de positionnement collectif très utile contre les AoE et les mécaniques de donjon/raid.
-Raison : `RUN~COMBAT` existe maintenant, les scopes sont validés, et Pull Control a déjà prouvé que l'addon peut envoyer proprement des toggles de stratégie sans spam chat. Le plus rentable est donc d'ajouter une UI dédiée aux stratégies combat permanentes ou semi-permanentes : `avoid aoe`, `save mana`, `threat`, `behind`, `tank face`, `healer dps`, `boost`.
+Proposition de prochaine itération :
-Ce bloc doit rester séparé de Pull Control : Pull Control sert aux séquences de pull, tandis qu'Advanced Combat sert aux comportements généraux des bots pendant les combats.
+- vérifier d'abord la syntaxe exacte supportée par playerbots : `disperse set ` et `disperse disable` ;
+- décider si l'action doit passer par `RUN~COMBAT` ou par un endpoint plus neutre, par exemple `RUN~MOVE` / `RUN~POSITION` si on veut garder `RUN~COMBAT` réservé aux stratégies combat ;
+- ajouter une mini-frame simple avec distance configurable et bouton disable ;
+- garder le fonctionnement chatless, sans parsing automatique de réponse.