From ba0caeece2ede21cef745ab3027c2109f8ddc5e4 Mon Sep 17 00:00:00 2001 From: BlaMacfly Date: Sat, 5 Sep 2026 09:51:54 +0200 Subject: [PATCH] Playerbots : la formation de groupe n'a jamais fonctionne MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SIGNALE EN JEU : « les bots restent les uns sur les autres, il n existe pas des commandes de strategie de placement ? ». Le systeme existait bien -- il etait casse. GetPositionFromGroup calcule correctement une place propre a chaque membre : un angle reparti sur le cercle, a quatre metres du meneur. Mais son resultat n etait jamais renvoye : Position resultPos(distX, distY, distZ, ...); // calculee Position pos; // vide pCenterPlayer->GetFirstCollisionPosition(...); // resultat jete return pos; // (0,0,0) GetFirstCollisionPosition REND une Position ; son retour etait ignore et l on renvoyait une variable jamais renseignee. La fonction rendait donc l origine du monde a tous ses appelants -- BotGroupAI comme BotAITool. Par-dessus, les deux MoveFollow de BotGroupAI employaient la meme distance et le meme angle pour tout le monde : un metre devant le meneur, a son orientation. Meme reparee, la formation aurait ete ecrasee deux lignes plus loin. Chaque bot y prend desormais l angle de son rang dans le groupe, a trois ou quatre metres selon l effectif. Le defaut ne touchait pas que le scenario : il vaut pour tous les playerbots du serveur, champs de bataille et donjons compris. Co-Authored-By: Claude Opus 5 --- src/server/game/AI/PlayerAI/BotAITool.cpp | 25 ++++++++++++++-- .../AI/PlayerAI/BotGroupAI/BotGroupAI.cpp | 30 +++++++++++++++++-- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/server/game/AI/PlayerAI/BotAITool.cpp b/src/server/game/AI/PlayerAI/BotAITool.cpp index 1803e30..aeb0c5b 100644 --- a/src/server/game/AI/PlayerAI/BotAITool.cpp +++ b/src/server/game/AI/PlayerAI/BotAITool.cpp @@ -502,9 +502,30 @@ Position BotUtility::GetPositionFromGroup(Player* pCenterPlayer, ObjectGuid self float distZ = centerPos.GetPositionZ(); if (!pCenterPlayer->IsFlying()) distZ = pCenterPlayer->GetMap()->GetHeight(pCenterPlayer->GetPhaseShift(), distX, distY, distZ); + // ================================================================= + // SylvaniaCore : la position calculee etait JETEE. + // + // SIGNALE EN JEU : « les bots restent les uns sur les autres ». + // + // Tout le calcul ci-dessus est juste -- un angle propre a chaque + // membre, reparti sur le cercle, a quatre metres du meneur. Mais le + // resultat n'etait jamais renvoye : + // + // Position resultPos(distX, distY, distZ, ...); // calculee + // Position pos; // vide + // pCenterPlayer->GetFirstCollisionPosition(...); // jete + // return pos; // (0,0,0) + // + // GetFirstCollisionPosition REND une Position ; son resultat etait + // ignore, et l'on renvoyait une variable jamais renseignee. La + // fonction rendait donc l'origine du monde a tous les appelants, et + // la formation n'a jamais fonctionne -- nulle part, pas seulement + // dans ce scenario. + // ================================================================= Position resultPos(distX, distY, distZ, pCenterPlayer->GetOrientation()); - Position pos; - pCenterPlayer->GetFirstCollisionPosition(pCenterPlayer->GetDistance(resultPos), pCenterPlayer->GetRelativeAngle(&resultPos)); + Position pos = pCenterPlayer->GetFirstCollisionPosition( + pCenterPlayer->GetDistance(resultPos), pCenterPlayer->GetRelativeAngle(&resultPos)); + pos.SetOrientation(pCenterPlayer->GetOrientation()); return pos; } diff --git a/src/server/game/AI/PlayerAI/BotGroupAI/BotGroupAI.cpp b/src/server/game/AI/PlayerAI/BotGroupAI/BotGroupAI.cpp index d17dd04..6315f53 100644 --- a/src/server/game/AI/PlayerAI/BotGroupAI/BotGroupAI.cpp +++ b/src/server/game/AI/PlayerAI/BotGroupAI/BotGroupAI.cpp @@ -1528,18 +1528,44 @@ void BotGroupAI::ProcessFollowToMaster() } Position targetPos = BotUtility::GetPositionFromGroup(m_MasterPlayer, me->GetGUID(), me->GetGroup()); m_Movement->MovementTo(targetPos.GetPositionX(), targetPos.GetPositionY(), targetPos.GetPositionZ(), 0); + // ================================================================= + // ANGLE PROPRE A CHAQUE MEMBRE. + // + // Les deux MoveFollow ci-dessous employaient la MEME distance et le + // MEME angle pour tout le monde -- un metre devant le meneur, a son + // orientation. Tous les bots convergeaient donc vers un point unique + // et se superposaient, quand bien meme GetPositionFromGroup leur + // avait calcule une place distincte deux lignes plus haut. + // + // On reprend l'angle de cette formation : chacun garde son secteur. + float suiviAngle = 0.0f; + float suiviDistance = 3.0f; + { + uint32 index = 0; + uint32 count = 0; + ObjectGuid monGuid = me->GetGUID(); + if (me->GetGroup() && me->GetGroup()->GiveAtGroupPos(monGuid, index, count)) + { + if (count > 1) + --count; + if (count) + suiviAngle = (float(M_PI) * 2.0f / float(count)) * float(index); + suiviDistance = (count > 3) ? 4.0f : 3.0f; + } + } + float distance = me->GetDistance(m_MasterPlayer->GetPosition()); if (distance <= NEEDFLEE_CHECKRANGE && distance > 0.1f) { me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveFollow(m_MasterPlayer, 1.0f, m_MasterPlayer->GetOrientation()); + me->GetMotionMaster()->MoveFollow(m_MasterPlayer, suiviDistance, suiviAngle); return; } if (me->IsWithinLOSInMap(m_MasterPlayer)) { me->GetMotionMaster()->Clear(); - me->GetMotionMaster()->MoveFollow(m_MasterPlayer, 1.0f, m_MasterPlayer->GetOrientation()); + me->GetMotionMaster()->MoveFollow(m_MasterPlayer, suiviDistance, suiviAngle); } else m_Movement->MovementTo(m_MasterPlayer->GetPositionX(), m_MasterPlayer->GetPositionY(), m_MasterPlayer->GetPositionZ(), 1);