Rivage brise 1460 : le phasage rendait les creatures inattaquables

Signale en jeu : creatures visibles, hostiles, mais impossibles a cibler
-- alors qu elles pouvaient attaquer le joueur.

J avais enchaine trois hypotheses (phase, factions, modeles souches).
Les trois etaient de VRAIS defauts et meritaient correction, mais aucune
n etait la cause. J aurais du poser la sonde d abord.

VERDICT DE LA SONDE, dans _IsValidAttackTarget :
    Felblade Destroyer | vivante=1 | aucun drapeau bloquant
    reaction=1 (hostile) | mesPhases=0  sesPhases=1

Le joueur n a AUCUNE phase, la creature en a une. PhaseShift::CanSee
exige une intersection des phases, et UpdateUnphasedFlag retire le
statut « non phase » des qu un objet en possede une. Aucune intersection
possible.

C est MA modification precedente qui a introduit ce decalage : j avais
place les 757 spawns en phase 169 en croyant que le joueur y etait,
en me fiant a un commentaire du script. Il ne l etait pas.

CORRECTIF : suppression du phasage des deux cotes, ce qui rejoint la
configuration de la reference -- le dump laisse les 757 placements de
cette carte SANS phase. La phase 169 n existe d ailleurs pas dans
Phase.db2 du build 7.3.5.26972.
  - PhaseId remis a 0 sur les 757 creatures et les 101 objets ;
  - AddPhase retire de OnPlayerEnter ;
  - FinalizeSummon ne phase plus rien (conservee comme point de passage
    unique, sans quoi les invocations deviendraient invisibles a un
    joueur non phase -- le meme probleme en sens inverse).

La sonde ATTDBG est CONSERVEE le temps de la validation en jeu.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
SylvaniaCore deploy
2026-08-30 22:11:21 +02:00
parent 6219d00c06
commit 0ac509e421
2 changed files with 57 additions and 3 deletions
+28
View File
@@ -8314,6 +8314,34 @@ bool Unit::_IsValidAttackTarget(Unit const* target, SpellInfo const* bySpell, Wo
{
ASSERT(target);
// SONDE TEMPORAIRE - carte 1460 uniquement, et seulement quand un
// JOUEUR vise une CREATURE. Volume borne : quelques lignes par seconde
// au plus, et uniquement dans ce scenario.
if (GetTypeId() == TYPEID_PLAYER && target->GetTypeId() == TYPEID_UNIT && GetMapId() == 1460)
{
static uint32 sondeAtt = 0;
if ((++sondeAtt % 20) == 1)
{
TC_LOG_ERROR("misc",
"ATTDBG cible %s (entree %u) | vivante=%u etatInattaquable=%u | drapeaux=%u "
"(NON_ATTACKABLE=%u NOT_ATTACKABLE_1=%u UNK_16=%u IMMUNE_PC=%u NOT_SELECTABLE=%u) "
"| reaction=%d | jeLaVois=%u | mesPhases=%u sesPhases=%u",
target->GetName().c_str(), target->GetEntry(),
uint32(target->IsAlive() ? 1 : 0),
uint32(target->HasUnitState(UNIT_STATE_UNATTACKABLE) ? 1 : 0),
target->GetUInt32Value(UNIT_FIELD_FLAGS),
uint32(target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE) ? 1 : 0),
uint32(target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_ATTACKABLE_1) ? 1 : 0),
uint32(target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_UNK_16) ? 1 : 0),
uint32(target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC) ? 1 : 0),
uint32(target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE) ? 1 : 0),
int32(GetReactionTo(target)),
uint32(CanSeeOrDetect(target, true) ? 1 : 0),
uint32(GetPhaseShift().GetPhases().size()),
uint32(target->GetPhaseShift().GetPhases().size()));
}
}
// can't attack self
if (this == target)
return false;
@@ -172,7 +172,30 @@ struct scenario_broken_shore_intro : public InstanceScript
if (player->GetMapId() != 1460)
return;
PhasingHandler::AddPhase(player, PHASE_NORMAL, true);
// ==========================================================
// SylvaniaCore : phasage retire.
//
// SIGNALE EN JEU : les creatures etaient visibles, hostiles, mais
// impossibles a cibler. Une sonde posee dans _IsValidAttackTarget
// a donne le verdict :
// reaction=1 (hostile), aucun drapeau bloquant, vivante,
// mesPhases=0 sesPhases=1
//
// Deux objets ne se voient que s'ils PARTAGENT une phase
// (PhaseShift::CanSee, intersection des phases), et
// UpdateUnphasedFlag retire le statut « non phase » des qu'un
// objet en possede une. Le joueur n'en avait aucune : aucune
// intersection possible.
//
// Le phasage etait de toute facon une invention locale : le dump
// de reference laisse les 757 placements de cette carte SANS
// phase (PhaseId vide). On revient donc a cette configuration --
// tout le monde non phase, tout le monde se voit.
//
// La phase 169 n'existe d'ailleurs pas dans Phase.db2 du build
// 7.3.5.26972, ce qui la rendait d'autant plus douteuse.
// ==========================================================
// objectif « embarquement » (Alliance) : credite aussi ici au cas ou
player->KilledMonsterCredit(NPC_CREDIT_SHIP);
@@ -207,10 +230,13 @@ struct scenario_broken_shore_intro : public InstanceScript
// Toute invocation doit partager la phase des joueurs (OnPlayerEnter les met en 169),
// sinon elle est invisible/intangible : cible de quete introuvable, vague intuable.
// (defaut systemique detecte par le harnais bot le 26/07, deja corrige dans le runner d artefacts)
// SylvaniaCore : ne phase plus rien. Laisser la phase 169 ici alors
// que le joueur n'en a aucune rendrait les invocations invisibles --
// le probleme meme qu'on vient de corriger, en sens inverse.
// Conservee comme point de passage unique pour les invocations, au
// cas ou un traitement commun redevienne necessaire.
TempSummon* FinalizeSummon(TempSummon* summon) const
{
if (summon)
PhasingHandler::AddPhase(summon, PHASE_NORMAL, true);
return summon;
}