From 5205a9b5f0967b5889ab94d5fe2efcb5294dede0 Mon Sep 17 00:00:00 2001 From: Sylvania Date: Thu, 3 Sep 2026 10:19:57 +0200 Subject: [PATCH] Dompteurs de mascottes : return manquant, le journal de quetes lu hors limites Cliquer sur un dompteur de mascottes (88 PNJ, dont Julia Stevens 64330) tuait le worldserver. Player::QuestObjectiveActiveInPlayerByObject n avait aucun return sur le chemin de sortie de boucle. GCC en deduit que la boucle ne peut pas se terminer normalement -- sinon comportement indefini -- et supprime le test q < MAX_QUEST_LOG_SIZE. Le numero de slot grimpait donc au-dela de 25 jusqu a sortir du tableau de valeurs du joueur : ASSERT dans GetUInt32Value (index 4636, slot 275 dans la pile signalee). Le compilateur le disait deja : "control reaches end of non-void function" dans nos logs de build. C etait le seul cas du core, il n y en a plus. Au passage, PetBattleTrainer.cpp gardait ObjectId et isTrainer comme membres du CreatureScript, or celui-ci est un singleton partage par les 88 PNJ et par tous les joueurs : le dernier interlocuteur decidait de ce que pouvait faire le suivant. La verification se fait desormais sur le joueur et le PNJ courants. Signale sur le Discord avec une pile gdb par un utilisateur du core. Co-Authored-By: Claude Opus 5 --- src/server/game/Entities/Player/Player.cpp | 11 ++++++----- src/server/scripts/World/PetBattleTrainer.cpp | 15 ++++----------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 1c73567..a57f0ca 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -20227,14 +20227,15 @@ bool Player::QuestObjectiveActiveInPlayerByObject(uint32 objectId) continue; for (QuestObjective const& obj : quest->GetObjectives()) - { if ((uint32)obj.ObjectID == objectId) - { return true; - break; - } - } } + + // SylvaniaCore : sans ce return, sortir de la boucle etait un comportement + // indefini -- GCC en deduisait que la boucle ne pouvait pas se terminer et + // supprimait le test q < MAX_QUEST_LOG_SIZE. Le slot grimpait au-dela de 25 + // jusqu a sortir du tableau de valeurs du joueur (ASSERT dans GetUInt32Value). + return false; } PlayerPetData* Player::GetPlayerPetDataById(uint32 petId) diff --git a/src/server/scripts/World/PetBattleTrainer.cpp b/src/server/scripts/World/PetBattleTrainer.cpp index 372657c..632d1d7 100644 --- a/src/server/scripts/World/PetBattleTrainer.cpp +++ b/src/server/scripts/World/PetBattleTrainer.cpp @@ -38,24 +38,17 @@ class npc_TrainerBattlePet : public CreatureScript public: npc_TrainerBattlePet() : CreatureScript("npc_TrainerBattlePet") { } - uint32 ObjectId = 0; - bool isTrainer = false; + // SylvaniaCore : un CreatureScript est un singleton partage par tous les + // joueurs et tous les PNJ qui portent le script -- l etat du dernier + // interlocuteur ne doit pas conditionner ce que fait le suivant. bool OnGossipHello(Player* player, Creature* creature) override { if (sBattlePetDataStore->GetPetBattleTrainerTeam(creature->GetEntry()).empty()) return false; - ObjectId = creature->GetEntry(); - if (creature->IsQuestGiver()) player->PrepareQuestMenu(creature->GetGUID()); - if (player->QuestObjectiveActiveInPlayerByObject(ObjectId)) - { - isTrainer = true; - - } - AddGossipItemFor(player, GOSSIP_ICON_CHAT, "Let`s Go", GOSSIP_SENDER_MAIN, 0); SendGossipMenuFor(player, player->GetGossipTextId(creature), creature->GetGUID()); @@ -66,7 +59,7 @@ public: { player->PlayerTalkClass->ClearMenus(); - if (isTrainer) + if (player->QuestObjectiveActiveInPlayerByObject(creature->GetEntry())) { if (uiAction == 0) {