From 19c0cf034533b522cd98f3894ba44df86c043632 Mon Sep 17 00:00:00 2001 From: BlaMacfly <165155133+BlaMacfly@users.noreply.github.com> Date: Wed, 9 Sep 2026 22:52:35 +0200 Subject: [PATCH] Mercenaires : re-resoudre les sorts une fois l IA de groupe creee MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signale en jeu : les mercenaires n utilisent presque aucune de leurs capacites. Chaque IA de classe resout ses poignees de sorts UNE seule fois, a sa construction, par FindMaxRankSpellByExist. Ce qui n est pas connu du personnage a cet instant renvoie zero et reste eteint pour toute la vie du bot, chaque usage etant garde par un « if (poignee) ». Mesure a la sonde, le 09/09/2026, sur une escorte de quatre mercenaires tous montes au niveau 110 : l IA avait resolu ses sorts au niveau 1 pour l un d eux, au niveau 100 pour deux autres. Le quatrieme, re-resolu par hasard a 110 parce qu il avait gagne un niveau pendant que son IA existait deja, n avait plus que quatre capacites indisponibles -- et toutes les quatre appartenaient a une autre specialisation, donc parfaitement normales. Les tables de sorts ne sont donc pas en cause, contrairement a ce que laissait croire un premier releve : c est un probleme d ordre. Le core prevoyait la reparation. Quand la mise en place s acheve, PlayerBotSetting pousse un BGSType_DelayLevelup qui reapprend les sorts et rappelle InitializeSpells. Mais OnLevelupToBotAI() commence par un dynamic_cast et ne fait rien tant que l IA de groupe n existe pas -- or le module ne la cree qu ensuite. La tache partait avant sa cible et tombait dans le vide. On en repousse donc une juste apres SwitchPlayerBotAI, quand l IA existe. Elle attend que le bot soit hors combat avant d agir, le rehabillage complet faisant partie du meme passage. Co-Authored-By: Claude Opus 5 --- src/server/game/Mercenary/MercenaryMgr.cpp | 34 ++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/server/game/Mercenary/MercenaryMgr.cpp b/src/server/game/Mercenary/MercenaryMgr.cpp index 5075e4f..7d3044d 100644 --- a/src/server/game/Mercenary/MercenaryMgr.cpp +++ b/src/server/game/Mercenary/MercenaryMgr.cpp @@ -769,6 +769,40 @@ void MercenaryMgr::Update(uint32 diff) PlayerBotMgr::SwitchPlayerBotAI(bot, PlayerBotAIType::PBAIT_GROUP, true); + // ============================================================= + // RERESOLUTION_DES_SORTS + // + // MESURE (sonde SORTDBG, 09/09/2026) : sur quatre mercenaires tous + // montes au niveau 110, l IA avait resolu ses sorts au niveau 1 pour + // l un, au niveau 100 pour deux autres. Seul le quatrieme, re-resolu + // par hasard a 110, n avait plus que quatre capacites indisponibles + // -- et les quatre appartenaient a une autre specialisation, donc + // parfaitement normales. + // + // Les tables de sorts ne sont donc pas en cause. Le defaut est un + // probleme d ordre : chaque IA de classe resout ses poignees UNE + // fois, a sa construction, via FindMaxRankSpellByExist ; ce qui n + // est pas connu a cet instant reste eteint a vie, chaque usage etant + // garde par un « if (poignee) ». + // + // Le core prevoit pourtant la reparation : quand la mise en place s + // acheve, PlayerBotSetting pousse un BGSType_DelayLevelup qui + // reapprend les sorts et rappelle InitializeSpells. Mais + // OnLevelupToBotAI() commence par un dynamic_cast et ne + // fait rien si l IA de groupe n existe pas encore -- or nous venons + // seulement de la creer, la ligne au-dessus. La tache partait avant + // sa cible et tombait dans le vide. + // + // On en repousse donc une maintenant que l IA existe. Elle attend + // que le bot soit hors combat avant d agir, le rehabillage complet + // faisant partie du meme passage. + // ============================================================= + if (PlayerBotSession* botSession = dynamic_cast(bot->GetSession())) + { + BotGlobleSchedule reresolution(BotGlobleScheduleType::BGSType_DelayLevelup, bot->GetGUID()); + botSession->PushScheduleToQueue(reresolution); + } + // Des maintenant, pas au tick suivant : l IA de groupe, en decouvrant // un maitre lointain, armerait le sien vers l employeur, et SetTeleport // refuse d ecraser un teleport en cours. Notre ordre serait perdu et le