Brasserie : roulement des tonneaux, et sonde sur le reveil d Ook-Ook

Signale en jeu : « les tonneaux sont completement bugges, ils se
deplacent bizarrement ».

Deux defauts certains dans npc_barrel :

1. Le trajet etait reinitialise en plein vol. Move() relancait un
   MovePoint vers un point a 5 m devant TOUTES LES 300 ms, alors que le
   tonneau avance a 0,85 de vitesse (environ 5,95 m/s) : parcourir ces
   5 m lui demande 840 ms. Le trajet etait donc ecrase au tiers, quatre
   fois par segment. Cote client chaque reinitialisation est une rupture
   de trajectoire, d ou le roulement saccade. Le deplacement est
   desormais relance A L ARRIVEE via MovementInform, par segments de
   20 m.

2. L orientation de depart n etait jamais fixee. Le tonneau est invoque
   par un sort a 5-10 m devant le Hurleur, mais rien ne lui donnait de
   cap propre. Il part maintenant dans la direction du lancer.

Arbitrage assume : la generation de chemin de MovePoint est CONSERVEE.
Un tonneau devrait rouler droit et la couper serait plus juste sur le
papier, mais c est elle qui le maintient sur le sol praticable -- sans
elle il traverserait les murs. Sur sol degage le chemin est de toute
facon quasi rectiligne.

Sonde OOKDBG ajoutee (4 points) : Ook-Ook se reveille avant le seuil de
40 hozens alors qu InitializeAI le pose en NON_ATTACKABLE et en reaction
passive, et que le chemin scripte (SEUIL ATTEINT) n apparait jamais dans
les traces. Pistes deja ecartees : les evenements 2 et 3 de l instance
ne le concernent pas, et EVENT_INTROCHECK est programme mais traite
nulle part -- evenement mort.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
SylvaniaCore deploy
2026-08-25 12:21:14 +02:00
parent 0a105df163
commit 8e9b65291f
@@ -121,8 +121,19 @@ public:
initializedBarrels = false;
events.ScheduleEvent(EVENT_INTROCHECK, 3000);
// SONDE TEMPORAIRE
TC_LOG_ERROR("misc",
"OOKDBG InitializeAI : etatBoss=%u nonAttaquable=%u reactState=%u",
instance ? uint32(instance->GetBossState(DATA_OOK_OOK)) : 999,
uint32(me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE) ? 1 : 0),
uint32(me->GetReactState()));
if (instance && instance->GetBossState(DATA_OOK_OOK) == SPECIAL)
{
// SONDE TEMPORAIRE
TC_LOG_ERROR("misc", "OOKDBG etat SPECIAL persistant -> intro lancee des l initialisation");
me->AI()->DoAction(0);
}
}
void Reset() override
@@ -146,6 +157,9 @@ public:
void StartIntro()
{
// SONDE TEMPORAIRE
TC_LOG_ERROR("misc", "OOKDBG StartIntro appelee (introDone valait %u)", uint32(introDone ? 1 : 0));
introDone = true;
events.CancelEvent(EVENT_INTROCHECK);
@@ -160,8 +174,19 @@ public:
me->SetHomePosition(ookJumpPos);
}
void EnterCombat(Unit* /*who*/) override
void EnterCombat(Unit* who) override
{
// SONDE TEMPORAIRE - c'est la question centrale : qui l'engage,
// et dans quel etat etait-il a ce moment-la ?
TC_LOG_ERROR("misc",
"OOKDBG EnterCombat par %s (type=%u entree=%u) | nonAttaquable=%u reactState=%u introDone=%u",
who ? who->GetName().c_str() : "INCONNU",
who ? uint32(who->GetTypeId()) : 999,
(who && who->GetTypeId() == TYPEID_UNIT) ? who->GetEntry() : 0,
uint32(me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE) ? 1 : 0),
uint32(me->GetReactState()),
uint32(introDone ? 1 : 0));
_EnterCombat();
Talk(TALK_AGGRO);
@@ -175,6 +200,9 @@ public:
void DoAction(int32 actionId) override
{
// SONDE TEMPORAIRE
TC_LOG_ERROR("misc", "OOKDBG DoAction(%d)", actionId);
if (actionId == 0)
StartIntro();
else if (actionId == 1)
@@ -301,6 +329,18 @@ public:
{
me->SetReactState(REACT_PASSIVE);
me->AddAura(SPELL_ROLLING_BARREL_COSMETIC, me);
// SylvaniaCore : le tonneau part desormais dans la direction du
// lancer. Il est invoque par un sort a 5-10 m devant le Hurleur
// (npc_hozen_hollerer::DoCastBarrel), mais son orientation
// propre n'etait jamais fixee : rien ne garantissait qu'il
// roule vers la salle plutot que dans n'importe quel sens.
if (summoner)
{
float const cap = summoner->GetOrientation();
me->SetOrientation(cap);
me->SetFacingTo(cap, true);
}
me->SetSpeed(MOVE_WALK, 0.85f);
me->SetSpeed(MOVE_RUN, 0.85f);
me->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
@@ -317,14 +357,47 @@ public:
me->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPELLCLICK);
}
// SylvaniaCore - deplacement des tonneaux.
//
// SIGNALE EN JEU : « les tonneaux sont completement bugges, ils se
// deplacent bizarrement ».
//
// L'ancienne version relancait un MovePoint vers un point situe a
// 5 m devant, TOUTES LES 300 ms. Or le tonneau avance a 0,85 de
// vitesse, soit environ 5,95 m/s : parcourir ces 5 m lui demande
// 840 ms. Le trajet etait donc reinitialise alors qu'il n'en avait
// effectue qu'un tiers, et cela quatre fois de suite pour chaque
// segment. Cote client, chaque reinitialisation est une rupture de
// trajectoire : d'ou le roulement saccade.
//
// On ne relance donc plus au chronometre mais A L'ARRIVEE, via
// MovementInform. Le segment est aussi allonge : moins de coutures,
// donc un roulement continu.
static uint32 const POINT_ROULEMENT = 100;
void Move()
{
// 20 m par segment : assez long pour que le roulement paraisse
// continu, assez court pour que le tonneau reste reactif.
float const DISTANCE_ROULEMENT = 20.0f;
float x = 0, y = 0;
GetPositionWithDistInOrientation(me, 5.0f, me->GetOrientation(), x, y);
GetPositionWithDistInOrientation(me, DISTANCE_ROULEMENT, me->GetOrientation(), x, y);
me->GetMotionMaster()->MovePoint(100, x, y, me->GetPositionZ());
// On conserve volontairement la generation de chemin. Un tonneau
// devrait rouler en ligne droite, et la couper ferait mieux sur
// le papier -- mais elle est aussi ce qui garde le tonneau sur
// le sol praticable. Sans elle il traverserait les murs et
// sortirait de la salle, ce qui serait pire que le defaut
// corrige. Sur un sol degage, le chemin calcule est de toute
// facon quasi rectiligne.
me->GetMotionMaster()->MovePoint(POINT_ROULEMENT, x, y, me->GetPositionZ());
}
events.ScheduleEvent(EVENT_MOVE, 300);
void MovementInform(uint32 type, uint32 id) override
{
if (type == POINT_MOTION_TYPE && id == POINT_ROULEMENT)
Move();
}
void UpdateAI(uint32 diff) override
@@ -338,9 +411,6 @@ public:
{
switch (eventId)
{
case EVENT_MOVE:
Move();
break;
case EVENT_EXPLOSION_BREAK:
initiate = true;
break;