From 4e5e0b94fa6304cbd82c138b183ade8bf5930494 Mon Sep 17 00:00:00 2001 From: Okladnoj Date: Mon, 3 Aug 2026 19:55:28 +0300 Subject: [PATCH] chore(crcdebug): Log DieOnDetonate on projectile detonation addCRCDebugLineNoCounter had no macro wrapper, so it could not be used. Add CRCDEBUG_LOG_NOCOUNTER next to CRCDEBUG_LOG and use it in MissileAIUpdate::detonate to record the weapon's DieOnDetonate flag. The flag decides whether the projectile dies right there or a frame later in doKillSelfState, which moves its die modules to a different frame, so two clients that disagree on it desync at that frame. The no-counter variant keeps the ordinals in the frame identical to a client without this change. --- Core/GameEngine/Include/Common/CRCDebug.h | 2 ++ .../GameLogic/Object/Update/AIUpdate/MissileAIUpdate.cpp | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/Core/GameEngine/Include/Common/CRCDebug.h b/Core/GameEngine/Include/Common/CRCDebug.h index b4bda92b2c6..1eaff931f52 100644 --- a/Core/GameEngine/Include/Common/CRCDebug.h +++ b/Core/GameEngine/Include/Common/CRCDebug.h @@ -73,6 +73,7 @@ void addCRCDumpLine(const char *fmt, ...); void addCRCGenLine(const char *fmt, ...); #define CRCDEBUG_LOG(x) addCRCDebugLine x + #define CRCDEBUG_LOG_NOCOUNTER(x) addCRCDebugLineNoCounter x #define CRCDUMP_LOG(x) addCRCDumpLine x #define CRCGEN_LOG(x) addCRCGenLine x @@ -116,6 +117,7 @@ #define DUMPREALNAMED(x, y) #define CRCDEBUG_LOG(x) + #define CRCDEBUG_LOG_NOCOUNTER(x) #define CRCDUMP_LOG(x) #define CRCGEN_LOG(x) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/MissileAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/MissileAIUpdate.cpp index 78b44dc99ca..191fe3c5c59 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/MissileAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/MissileAIUpdate.cpp @@ -32,6 +32,7 @@ #include "Common/ThingTemplate.h" #include "Common/RandomValue.h" #include "Common/BitFlagsIO.h" +#include "Common/CRCDebug.h" #include "GameLogic/AIPathfind.h" #include "GameLogic/ExperienceTracker.h" @@ -386,6 +387,11 @@ void MissileAIUpdate::detonate() if (m_detonationWeaponTmpl) { + // TheSuperHackers @info Okladnoj 03/08/2026 DieOnDetonate decides whether the projectile dies here + // or a frame later in doKillSelfState, which moves its die modules to a different frame. Record it, + // because a client that disagrees on this flag desyncs at the frame the projectile detonates. + CRCDEBUG_LOG_NOCOUNTER(("MissileAIUpdate::detonate() obj=%d weapon=%s dieOnDetonate=%d", + obj->getID(), m_detonationWeaponTmpl->getName().str(), m_detonationWeaponTmpl->getDieOnDetonate() ? 1 : 0)); TheWeaponStore->handleProjectileDetonation(m_detonationWeaponTmpl, obj, obj->getPosition(), m_extraBonusFlags, !m_noDamage );