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 <noreply@anthropic.com>
This commit is contained in:
Sylvania
2026-09-03 10:19:57 +02:00
parent 6d98d5cbbd
commit 5205a9b5f0
2 changed files with 10 additions and 16 deletions
+6 -5
View File
@@ -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)
+4 -11
View File
@@ -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)
{