PlayerChoice : boutons vides (choix de specialisation chasseur de demons)

Signale en jeu : le tome des secrets gangrenes ouvre le choix de
specialisation, la question saffiche mais les deux boutons sont vides.

Trois defauts cumules dans Player::SendPlayerChoice :
1. Le filtre exigeait une recompense avec un sort VALIDE pour quune
   reponse soit envoyee. Le choix 231 (Devastation / Vengeance) a
   SpellID=0 : les deux reponses etaient silencieusement ecartees.
2. displayPlayerChoice.Responses etait redimensionne AVANT le filtrage,
   laissant une entree vide par reponse ecartee - do les boutons vides.
3. Reward->SpellID etait dereference sans controle alors que Reward peut
   etre nul, comme le montre le test plus bas dans la meme fonction :
   un plantage en attente pour toute reponse sans ligne de recompense.

Correctif general, valable pour tous les choix, pas seulement celui-ci.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
SylvaniaCore deploy
2026-08-18 00:56:55 +02:00
parent b671ae3c10
commit c9f4c87e61
+12 -5
View File
@@ -30187,7 +30187,6 @@ void Player::SendPlayerChoice(ObjectGuid sender, int32 choiceId)
if (playerChoiceLocale)
ObjectMgr::GetLocaleString(playerChoiceLocale->Question, locale, displayPlayerChoice.Question);
displayPlayerChoice.Responses.resize(playerChoice->Responses.size());
displayPlayerChoice.CloseChoiceFrame = false;
displayPlayerChoice.HideWarboardHeader = playerChoice->HideWarboardHeader;
@@ -30198,12 +30197,16 @@ void Player::SendPlayerChoice(ObjectGuid sender, int32 choiceId)
if (!_playerChoiceResponseTemplate.ResponseId)
continue;
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(_playerChoiceResponseTemplate.Reward->SpellID);
if (!spellInfo)
continue;
// Une reponse n'a pas forcement de recompense : sans ce garde, toute
// reponse sans sort de recompense etait silencieusement ecartee, ce qui
// laissait des boutons vides (ex. choix de specialisation demoniste 231).
// Reward peut aussi etre nul : le dereferencer ici plantait le serveur.
SpellInfo const* spellInfo = _playerChoiceResponseTemplate.Reward
? sSpellMgr->GetSpellInfo(_playerChoiceResponseTemplate.Reward->SpellID)
: nullptr;
bool playerEligible = true;
for (SpellEffectInfo const* effect : spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE))
for (SpellEffectInfo const* effect : spellInfo ? spellInfo->GetEffectsForDifficulty(DIFFICULTY_NONE) : SpellEffectInfoVector())
{
Quest const* quest = sObjectMgr->GetQuestTemplate(effect->MiscValue);
if (!quest)
@@ -30236,6 +30239,10 @@ void Player::SendPlayerChoice(ObjectGuid sender, int32 choiceId)
return;
}
// Dimensionner APRES le filtrage : redimensionner avant laissait des
// entrees vides pour chaque reponse ecartee.
displayPlayerChoice.Responses.resize(playerChoiceResponses.size());
for (std::size_t i = 0; i < playerChoiceResponses.size(); ++i)
{
auto const& playerChoiceResponseTemplate = playerChoiceResponses[i];