Scenarios : le premier critere achevé cloturait toute l etape

Signale en jeu, capture a l appui : a la Brasserie brune d Orage, la
liste des trois boss disparaissait entierement des qu Ook-Ook tombait,
au lieu de cocher 1/1 et de conserver les deux autres.

Le scenario 537 n a qu UNE etape (972), dont l arbre de criteres 36317
porte trois feuilles : 36318 Ook-Ook, 36319 Hoptallus, 36320 Yan-Zhu.

CriteriaMgr::LoadCriteriaList attribue l etape via GetEntry, qui REMONTE
la chaine des parents jusqu a trouver une correspondance -- chaque
feuille herite donc de l etape 972. Et le moteur n evalue que les
feuilles : GetCriteriaTreesByCriteria ne renvoie que les arbres portant
directement le critere, jamais la racine.

Resultat : la premiere feuille achevee marquait l ETAPE ENTIERE
terminee. CompleteStep ne trouvait alors aucune etape suivante,
IsComplete() repondait oui, et le scenario etait cloture des le premier
boss.

On verifie desormais l arbre RACINE de l etape avant de conclure. Un
garde naif sur « tree doit etre la racine » ne conviendrait pas : la
racine n etant jamais transmise ici, l etape ne s acheverait alors
JAMAIS. CheckCompletedCriteriaTree pouvant rappeler cette fonction avec
la racine, on relit l etat de l etape ensuite -- sans quoi CompleteStep
serait execute deux fois et la quete de recompense octroyee en double.

Correctif dans le moteur partage : il vaut pour tous les scenarios dont
une etape porte plusieurs criteres.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
SylvaniaCore deploy
2026-08-27 11:46:52 +02:00
parent 8238ca0925
commit 85b0251bc1
+48 -1
View File
@@ -192,7 +192,7 @@ bool Scenario::CanCompleteCriteriaTree(CriteriaTree const* tree)
return true;
}
void Scenario::CompletedCriteriaTree(CriteriaTree const* tree, Player* /*referencePlayer*/)
void Scenario::CompletedCriteriaTree(CriteriaTree const* tree, Player* referencePlayer)
{
ScenarioStepEntry const* step = tree->ScenarioStep;
if (!step)
@@ -204,6 +204,53 @@ void Scenario::CompletedCriteriaTree(CriteriaTree const* tree, Player* /*referen
if (GetStepState(step) == SCENARIO_STEP_DONE)
return;
// =================================================================
// SylvaniaCore - une etape ne s'acheve que si TOUS ses criteres le
// sont.
//
// SIGNALE EN JEU : a la Brasserie brune d'Orage, la liste des boss
// disparaissait entierement des qu'Ook-Ook tombait, au lieu de
// cocher « 1/1 » et de conserver les deux autres.
//
// POURQUOI. Le scenario 537 n'a qu'UNE etape (972), dont l'arbre de
// criteres 36317 porte trois feuilles :
// 36318 Ook-Ook, 36319 Hoptallus, 36320 Yan-Zhu.
//
// Or `CriteriaMgr::LoadCriteriaList` attribue l'etape via une aide
// qui REMONTE la chaine des parents jusqu'a trouver une
// correspondance. Chaque feuille herite donc de l'etape 972. Et le
// moteur n'evalue que les feuilles : `GetCriteriaTreesByCriteria`
// ne renvoie que les arbres portant directement le critere, jamais
// la racine.
//
// Resultat : la premiere feuille achevee marquait l'ETAPE ENTIERE
// terminee. `CompleteStep` ne trouvait alors aucune etape suivante,
// `IsComplete()` repondait oui, et le scenario etait cloture des le
// premier boss.
//
// On verifie donc l'arbre RACINE de l'etape avant de conclure. Un
// garde naif sur « tree doit etre la racine » ne conviendrait pas :
// la racine n'etant jamais transmise ici, l'etape ne s'acheverait
// alors JAMAIS.
//
// `CheckCompletedCriteriaTree` peut, en cas de succes, rappeler
// cette fonction avec la racine : on relit donc l'etat de l'etape
// ensuite, faute de quoi `CompleteStep` serait execute deux fois et
// la quete de recompense octroyee en double.
// =================================================================
if (step->Criteriatreeid && step->Criteriatreeid != tree->Entry->ID)
{
CriteriaTree const* racine = sCriteriaMgr->GetCriteriaTree(step->Criteriatreeid);
if (!racine)
return;
if (!CheckCompletedCriteriaTree(racine, referencePlayer))
return;
if (GetStepState(step) == SCENARIO_STEP_DONE)
return;
}
SetStepState(step, SCENARIO_STEP_DONE);
CompleteStep(step);
}