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:
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user