From 537e6df7cd641427ae46b626e1b654ed5a52b4a2 Mon Sep 17 00:00:00 2001 From: SylvaniaCore deploy Date: Tue, 18 Aug 2026 09:46:16 +0200 Subject: [PATCH] BG BotFill : laisse tactique autour de l objectif + escorte du porteur 1. Laisse : un bot ne se laisse plus entrainer loin de son objectif par un fuyard. Au-dela de 50 m du point a tenir la cible est fortement deprioritisee, sauf le porteur de drapeau qu il faut poursuivre partout. Sans cette regle les defenseurs desertaient leur base des le premier ennemi croise, defaut classique des IA de champ de bataille. 2. Escorte a Chanteguerres : jusqu a trois allies deja proches (60 m) collent le porteur pour intercepter ses poursuivants. L Oeil du cyclone avait deja ce comportement, Chanteguerres laissait le porteur rentrer seul. Co-Authored-By: Claude Fable 5 --- src/server/game/AI/PlayerAI/BotAI.cpp | 15 +++++++ src/server/game/AI/PlayerAI/BotBGAIMovement.h | 2 + .../Battlegrounds/CommandBG/CommandWS.cpp | 40 +++++++++++++++++++ .../game/Battlegrounds/CommandBG/CommandWS.h | 1 + 4 files changed, 58 insertions(+) diff --git a/src/server/game/AI/PlayerAI/BotAI.cpp b/src/server/game/AI/PlayerAI/BotAI.cpp index 5f37808..81edd49 100644 --- a/src/server/game/AI/PlayerAI/BotAI.cpp +++ b/src/server/game/AI/PlayerAI/BotAI.cpp @@ -851,6 +851,21 @@ Unit* BotBGAI::SearchEnemy(float range) if (!me->IsWithinLOSInMap(pVisionPlayer)) score -= 250.0f; + // SylvaniaCore (module BG BotFill): laisse tactique. Un bot ne se laisse + // pas entrainer loin de son objectif par un fuyard : au-dela de 50 m du + // point a tenir, la cible est fortement depriorisee (sauf porteur de + // drapeau, qu il faut poursuivre partout). Sans cette regle les defenseurs + // desertaient leur base des le premier ennemi croise. + if (AIWaypoint* objective = m_Movement->GetTargetWaypoint()) + { + if (!TargetIsFlagCarrier(pVisionPlayer)) + { + Position objPos = objective->GetPosition(); + if (pVisionPlayer->GetDistance(objPos.GetPositionX(), objPos.GetPositionY(), objPos.GetPositionZ()) > 50.0f) + score -= 500.0f; + } + } + if (!minHealthPlayer || score > bestScore) { bestScore = score; diff --git a/src/server/game/AI/PlayerAI/BotBGAIMovement.h b/src/server/game/AI/PlayerAI/BotBGAIMovement.h index 8dc8cba..dfd8790 100644 --- a/src/server/game/AI/PlayerAI/BotBGAIMovement.h +++ b/src/server/game/AI/PlayerAI/BotBGAIMovement.h @@ -58,6 +58,8 @@ public: ~BotBGAIMovement(); ObjectGuid GetTargetObjectID() { return targetGuid; } + // SylvaniaCore (module BG BotFill): objectif de position en cours, pour la laisse + AIWaypoint* GetTargetWaypoint() { return pTargetAIWP; } void ClearMovement(); void AcceptCommand(AIWaypoint* targetAIWP, bool isFlag = false); void AcceptCommand(ObjectGuid guid, bool isFlag = false); diff --git a/src/server/game/Battlegrounds/CommandBG/CommandWS.cpp b/src/server/game/Battlegrounds/CommandBG/CommandWS.cpp index 5551d00..2c4e979 100644 --- a/src/server/game/Battlegrounds/CommandBG/CommandWS.cpp +++ b/src/server/game/Battlegrounds/CommandBG/CommandWS.cpp @@ -154,9 +154,49 @@ void CommandWS::RndStartCommand() } } +// SylvaniaCore (module BG BotFill): escorte du porteur. Doctrine PvP : le porteur court, +// ses alliers proches le collent pour intercepter ses poursuivants ("peel"). L Oeil du +// cyclone avait deja ce comportement, Chanteguerres non : le porteur rentrait seul. +void CommandWS::ProcessEscortFlagCarrier() +{ + if (!m_pBattleground) + return; + BattlegroundWS* pBGWS = dynamic_cast(m_pBattleground); + if (!pBGWS) + return; + // notre porteur = celui qui detient le drapeau de l equipe adverse + ObjectGuid carrierGuid = pBGWS->GetFlagPickerGUID((m_TeamID == TEAM_ALLIANCE) ? TEAM_HORDE : TEAM_ALLIANCE); + if (carrierGuid.IsEmpty()) + return; + Player* carrier = ObjectAccessor::FindPlayer(carrierGuid); + if (!carrier || !carrier->IsAlive() || carrier->GetTeamId() != m_TeamID) + return; + + uint32 escortCount = 0; + for (PlayerStatus::iterator itGuid = m_PlayerGUIDs.begin(); itGuid != m_PlayerGUIDs.end(); itGuid++) + { + if (escortCount >= 3) // trois escorteurs suffisent, le reste tient les objectifs + break; + if (itGuid->first == carrierGuid) + continue; + Player* escort = GetBGPlayer(itGuid->first); + if (!escort || !escort->IsAlive()) + continue; + // seuls les allies deja proches escortent : on ne rappelle pas la defense + if (escort->GetDistance(carrier) > 60.0f) + continue; + if (BotBGAI* pBotAI = GetBotBGAI(itGuid->first)) + { + pBotAI->GetAIMovement()->AcceptCommand(carrierGuid, true); + ++escortCount; + } + } +} + void CommandWS::ProcessRegulation() { InsureAttackAndDefance(7); + ProcessEscortFlagCarrier(); ObjectGuid needGuaredTarget = EnemyBGFlagPicker(); ObjectGuid needAttackTarget = SelfBGFlagPicker(); bool pickedFlagTarget = (needAttackTarget.IsEmpty()) ? true : false; diff --git a/src/server/game/Battlegrounds/CommandBG/CommandWS.h b/src/server/game/Battlegrounds/CommandBG/CommandWS.h index d1aab4d..6a0cb16 100644 --- a/src/server/game/Battlegrounds/CommandBG/CommandWS.h +++ b/src/server/game/Battlegrounds/CommandBG/CommandWS.h @@ -57,6 +57,7 @@ private: void TryPickEnemyFlag(ObjectGuid guid); void TryPickSelfFlag(ObjectGuid guid); void TryCaptureFlag(ObjectGuid guid); + void ProcessEscortFlagCarrier(); // SylvaniaCore (module BG BotFill) ObjectGuid SelfBGFlagPicker(); ObjectGuid EnemyBGFlagPicker(); ObjectGuid GetBGFlagFromSelf();