From 845a0a3a35e6c318af4ee8b2d86d63cbc96baa37 Mon Sep 17 00:00:00 2001 From: stm <14291421+stephanmeesters@users.noreply.github.com> Date: Sun, 17 May 2026 12:36:29 +0200 Subject: [PATCH 1/4] fix(particlesys): Add or optimize null-checks to createParticleSystem calls --- .../Drawable/Update/BeaconClientUpdate.cpp | 18 +++---- .../Source/GameClient/System/ParticleSys.cpp | 8 ++- .../Drawable/Draw/W3DTankTruckDraw.cpp | 5 +- .../GameClient/Drawable/Draw/W3DTruckDraw.cpp | 5 +- .../Object/Behavior/AutoHealBehavior.cpp | 9 ++-- .../GameLogic/Object/ObjectCreationList.cpp | 4 +- .../Update/AIUpdate/ChinookAIUpdate.cpp | 14 ++--- .../GameLogic/Object/Update/EMPUpdate.cpp | 9 ++-- .../Update/HelicopterSlowDeathUpdate.cpp | 41 +++++++------- .../GameLogic/Object/Update/LaserUpdate.cpp | 18 +++---- .../Update/ParticleUplinkCannonUpdate.cpp | 23 +++----- .../GameLogic/Object/Update/SlavedUpdate.cpp | 39 +++++++------- .../Object/Update/StealthDetectorUpdate.cpp | 53 ++++++++----------- .../GameLogic/ScriptEngine/ScriptEngine.cpp | 15 +++--- 14 files changed, 108 insertions(+), 153 deletions(-) diff --git a/Core/GameEngine/Source/GameClient/Drawable/Update/BeaconClientUpdate.cpp b/Core/GameEngine/Source/GameClient/Drawable/Update/BeaconClientUpdate.cpp index c76e3dc3528..d9589c35cbb 100644 --- a/Core/GameEngine/Source/GameClient/Drawable/Update/BeaconClientUpdate.cpp +++ b/Core/GameEngine/Source/GameClient/Drawable/Update/BeaconClientUpdate.cpp @@ -97,25 +97,21 @@ static ParticleSystem* createParticleSystem( Drawable *draw ) DEBUG_ASSERTCRASH(particleTemplate, ("Could not find particle system %s", templateName.str())); - if (particleTemplate) + system = TheParticleSystemManager->createParticleSystem( particleTemplate ); + if (system) { - system = TheParticleSystemManager->createParticleSystem( particleTemplate ); - if (system) - system->attachToDrawable( draw ); + system->attachToDrawable( draw ); } else// This is a failsafe... if someone has monkeyed with the particle system names, or the MP house colors {// THis this will whip up a new particle system to match the house color provided templateName.format("BeaconSmokeFFFFFF"); const ParticleSystemTemplate *failsafeTemplate = TheParticleSystemManager->findTemplate( templateName ); DEBUG_ASSERTCRASH(failsafeTemplate, ("Doh, this is bad \n I Could not even find the white particle system to make a failsafe system out of.")); - if (failsafeTemplate) + system = TheParticleSystemManager->createParticleSystem( failsafeTemplate ); + if (system) { - system = TheParticleSystemManager->createParticleSystem( failsafeTemplate ); - if (system) - { - system->attachToDrawable( draw ); - system->tintAllColors( obj->getIndicatorColor() ); - } + system->attachToDrawable( draw ); + system->tintAllColors( obj->getIndicatorColor() ); } } } diff --git a/Core/GameEngine/Source/GameClient/System/ParticleSys.cpp b/Core/GameEngine/Source/GameClient/System/ParticleSys.cpp index b516a335000..da316af3bdb 100644 --- a/Core/GameEngine/Source/GameClient/System/ParticleSys.cpp +++ b/Core/GameEngine/Source/GameClient/System/ParticleSys.cpp @@ -2061,9 +2061,9 @@ Bool ParticleSystem::update( Int localPlayerIndex ) if (m_attachedSystemName.isEmpty() == false) { const ParticleSystemTemplate *tmp = TheParticleSystemManager->findTemplate( m_attachedSystemName ); - if (tmp) + ParticleSystem *sys = TheParticleSystemManager->createParticleSystem( tmp, TRUE ); + if (sys) { - ParticleSystem *sys = TheParticleSystemManager->createParticleSystem( tmp, TRUE ); sys->setControlParticle( p ); p->controlParticleSystem( sys ); } @@ -2867,9 +2867,7 @@ ParticleSystem *ParticleSystemTemplate::createSlaveSystem( Bool createSlaves ) c if (m_slaveTemplate == nullptr && m_slaveSystemName.isEmpty() == false) m_slaveTemplate = TheParticleSystemManager->findTemplate( m_slaveSystemName ); - ParticleSystem *slave = nullptr; - if (m_slaveTemplate) - slave = TheParticleSystemManager->createParticleSystem( m_slaveTemplate, createSlaves ); + ParticleSystem *slave = TheParticleSystemManager->createParticleSystem( m_slaveTemplate, createSlaves ); return slave; } diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DTankTruckDraw.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DTankTruckDraw.cpp index 5638cd1b3fb..8d936948ed6 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DTankTruckDraw.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DTankTruckDraw.cpp @@ -247,9 +247,10 @@ void W3DTankTruckDraw::createWheelEmitters() { if (m_truckEffectIDs[i] == INVALID_PARTICLE_SYSTEM_ID) { - if (const ParticleSystemTemplate *sysTemplate = TheParticleSystemManager->findTemplate(*effectNames[i])) + const ParticleSystemTemplate *sysTemplate = TheParticleSystemManager->findTemplate(*effectNames[i]); + ParticleSystem *particleSys = TheParticleSystemManager->createParticleSystem( sysTemplate ); + if (particleSys) { - ParticleSystem *particleSys = TheParticleSystemManager->createParticleSystem( sysTemplate ); particleSys->attachToObject(getDrawable()->getObject()); // important: mark it as do-not-save, since we'll just re-create it when we reload. particleSys->setSaveable(FALSE); diff --git a/Core/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DTruckDraw.cpp b/Core/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DTruckDraw.cpp index afcb3d11110..4e4f59ef93d 100644 --- a/Core/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DTruckDraw.cpp +++ b/Core/GameEngineDevice/Source/W3DDevice/GameClient/Drawable/Draw/W3DTruckDraw.cpp @@ -170,9 +170,10 @@ void W3DTruckDraw::createWheelEmitters() { if (m_truckEffectIDs[i] == INVALID_PARTICLE_SYSTEM_ID) { - if (const ParticleSystemTemplate *sysTemplate = TheParticleSystemManager->findTemplate(*effectNames[i])) + const ParticleSystemTemplate *sysTemplate = TheParticleSystemManager->findTemplate(*effectNames[i]); + ParticleSystem *particleSys = TheParticleSystemManager->createParticleSystem( sysTemplate ); + if (particleSys) { - ParticleSystem *particleSys = TheParticleSystemManager->createParticleSystem( sysTemplate ); particleSys->attachToObject(getDrawable()->getObject()); // important: mark it as do-not-save, since we'll just re-create it when we reload. particleSys->setSaveable(FALSE); diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/AutoHealBehavior.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/AutoHealBehavior.cpp index ce73fb30c47..16607a97a1a 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/AutoHealBehavior.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Behavior/AutoHealBehavior.cpp @@ -294,13 +294,10 @@ void AutoHealBehavior::pulseHealObject( Object *obj ) obj->attemptHealingFromSoleBenefactor( data->m_healingAmount, getObject(), data->m_healingDelay ); - if( data->m_unitHealPulseParticleSystemTmpl ) + ParticleSystem *system = TheParticleSystemManager->createParticleSystem( data->m_unitHealPulseParticleSystemTmpl ); + if( system ) { - ParticleSystem *system = TheParticleSystemManager->createParticleSystem( data->m_unitHealPulseParticleSystemTmpl ); - if( system ) - { - system->setPosition( obj->getPosition() ); - } + system->setPosition( obj->getPosition() ); } m_soonestHealFrame = TheGameLogic->getFrame() + data->m_healingDelay;// In case onDamage tries to wake us up early diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp index 892c1f120ab..b12781e6589 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp @@ -974,9 +974,9 @@ class GenericObjectCreationNugget : public ObjectCreationNugget if (!m_particleSysName.isEmpty()) { const ParticleSystemTemplate *tmp = TheParticleSystemManager->findTemplate(m_particleSysName); - if (tmp) + ParticleSystem *sys = TheParticleSystemManager->createParticleSystem(tmp); + if (sys) { - ParticleSystem *sys = TheParticleSystemManager->createParticleSystem(tmp); sys->attachToObject(obj); } } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp index 8ce9bff6ba1..48146964e19 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/AIUpdate/ChinookAIUpdate.cpp @@ -1199,15 +1199,11 @@ UpdateSleepTime ChinookAIUpdate::update() if ( GameClientRandomValueReal( 0.0f, chopperElevation ) < 5.0f ) { const ParticleSystemTemplate *tmp = TheParticleSystemManager->findTemplate( getChinookAIUpdateModuleData()->m_rotorWashParticleSystem ); - ParticleSystem *system; - if( tmp ) - { - system = TheParticleSystemManager->createParticleSystem( tmp ); - if( system ) - { - system->setPosition( &pos ); - } - } + ParticleSystem *system = TheParticleSystemManager->createParticleSystem( tmp ); + if( system ) + { + system->setPosition( &pos ); + } } } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/EMPUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/EMPUpdate.cpp index 12718e114b1..7bb0a907522 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/EMPUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/EMPUpdate.cpp @@ -449,12 +449,9 @@ UpdateSleepTime LeafletDropBehavior::update() // start shoveling out those leaflets, boys. const LeafletDropBehaviorModuleData *data = getLeafletDropBehaviorModuleData(); const ParticleSystemTemplate *tmp = data->m_leafletFXParticleSystem; - if (tmp) - { - ParticleSystem *sys = TheParticleSystemManager->createParticleSystem(tmp); - if (sys) - sys->attachToObject(getObject()); - } + ParticleSystem *sys = TheParticleSystemManager->createParticleSystem(tmp); + if (sys) + sys->attachToObject(getObject()); m_fxFired = TRUE; // hey, at least we tried. } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/HelicopterSlowDeathUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/HelicopterSlowDeathUpdate.cpp index e3a86fb24b4..1be0c57ed25 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/HelicopterSlowDeathUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/HelicopterSlowDeathUpdate.cpp @@ -229,44 +229,41 @@ void HelicopterSlowDeathBehavior::beginSlowDeath( const DamageInfo *damageInfo ) locomotor->setMaxBraking( modData->m_maxBraking ); // attach particle system to bone if present - if( modData->m_attachParticleSystem ) + ParticleSystem *pSys = TheParticleSystemManager->createParticleSystem( modData->m_attachParticleSystem ); + if( pSys ) { - ParticleSystem *pSys = TheParticleSystemManager->createParticleSystem( modData->m_attachParticleSystem ); - if( pSys ) + + // where do the offset attachment to + if( modData->m_attachParticleBone.isEmpty() == FALSE ) { + Drawable *draw = getObject()->getDrawable(); - // where do the offset attachment to - if( modData->m_attachParticleBone.isEmpty() == FALSE ) + if( draw ) { - Drawable *draw = getObject()->getDrawable(); - - if( draw ) - { - Coord3D pos; - - if( draw->getPristineBonePositions( modData->m_attachParticleBone.str(), 0, &pos, nullptr, 1 ) ) - pSys->setPosition( &pos ); + Coord3D pos; - } + if( draw->getPristineBonePositions( modData->m_attachParticleBone.str(), 0, &pos, nullptr, 1 ) ) + pSys->setPosition( &pos ); } - else - { - - // use location coord specified ... it will be zero if not given which is center of obj anyway - pSys->setPosition( &modData->m_attachParticleLoc ); - } + } + else + { - // attach the particle system to the object - pSys->attachToObject( getObject() ); + // use location coord specified ... it will be zero if not given which is center of obj anyway + pSys->setPosition( &modData->m_attachParticleLoc ); } + // attach the particle system to the object + pSys->attachToObject( getObject() ); + } + } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/LaserUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/LaserUpdate.cpp index 613d46a2146..87697c9e546 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/LaserUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/LaserUpdate.cpp @@ -357,13 +357,10 @@ void LaserUpdate::initLaser( const Object *parent, const Object *target, const C if( data->m_particleSystemName.isNotEmpty() ) { const ParticleSystemTemplate *tmp = TheParticleSystemManager->findTemplate( data->m_particleSystemName ); - if( tmp ) + system = TheParticleSystemManager->createParticleSystem( tmp ); + if( system ) { - system = TheParticleSystemManager->createParticleSystem( tmp ); - if( system ) - { - m_particleSystemID = system->getSystemID(); - } + m_particleSystemID = system->getSystemID(); } } @@ -371,13 +368,10 @@ void LaserUpdate::initLaser( const Object *parent, const Object *target, const C if( data->m_targetParticleSystemName.isNotEmpty() ) { const ParticleSystemTemplate *tmp = TheParticleSystemManager->findTemplate( data->m_targetParticleSystemName ); - if( tmp ) + system = TheParticleSystemManager->createParticleSystem( tmp ); + if( system ) { - system = TheParticleSystemManager->createParticleSystem( tmp ); - if( system ) - { - m_targetParticleSystemID = system->getSystemID(); - } + m_targetParticleSystemID = system->getSystemID(); } } } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ParticleUplinkCannonUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ParticleUplinkCannonUpdate.cpp index 9b9f5275b38..8819f34d815 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ParticleUplinkCannonUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ParticleUplinkCannonUpdate.cpp @@ -934,15 +934,11 @@ void ParticleUplinkCannonUpdate::createConnectorFlare( IntensityTypes intensity if( str.isNotEmpty() ) { const ParticleSystemTemplate *tmp = TheParticleSystemManager->findTemplate( str ); - ParticleSystem *system; - if( tmp ) + ParticleSystem *system = TheParticleSystemManager->createParticleSystem( tmp ); + if( system ) { - system = TheParticleSystemManager->createParticleSystem( tmp ); - if( system ) - { - m_connectorSystemID = system->getSystemID(); - system->setPosition( &m_connectorNodePosition ); - } + m_connectorSystemID = system->getSystemID(); + system->setPosition( &m_connectorNodePosition ); } } } @@ -970,14 +966,11 @@ void ParticleUplinkCannonUpdate::createLaserBaseFlare( IntensityTypes intensity if( str.isNotEmpty() ) { const ParticleSystemTemplate *tmp = TheParticleSystemManager->findTemplate( str ); - if( tmp ) + ParticleSystem *system = TheParticleSystemManager->createParticleSystem( tmp ); + if( system ) { - ParticleSystem *system = TheParticleSystemManager->createParticleSystem( tmp ); - if( system ) - { - m_laserBaseSystemID = system->getSystemID(); - system->setPosition( &m_laserOriginPosition ); - } + m_laserBaseSystemID = system->getSystemID(); + system->setPosition( &m_laserOriginPosition ); } } } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/SlavedUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/SlavedUpdate.cpp index 27303efcc5b..4e50e5d7985 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/SlavedUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/SlavedUpdate.cpp @@ -621,30 +621,27 @@ void SlavedUpdate::setRepairState( RepairStates repairState ) if( !data->m_weldingSysName.isEmpty() ) { const ParticleSystemTemplate *tmp = TheParticleSystemManager->findTemplate( data->m_weldingSysName ); - if( tmp ) + ParticleSystem *weldingSys = TheParticleSystemManager->createParticleSystem(tmp); + if( weldingSys ) { - ParticleSystem *weldingSys = TheParticleSystemManager->createParticleSystem(tmp); - if( weldingSys ) + Coord3D pos; + //Get the bone position + if( draw->getPristineBonePositions( data->m_weldingFXBone.str(), 0, &pos, nullptr, 1 ) ) { - Coord3D pos; - //Get the bone position - if( draw->getPristineBonePositions( data->m_weldingFXBone.str(), 0, &pos, nullptr, 1 ) ) - { - pos.add( obj->getPosition() ); - } - else - { - pos.set( obj->getPosition() ); - } - - weldingSys->setPosition( &pos ); - Real time = (Real)(m_framesToWait * LOGICFRAMES_PER_SECOND); - weldingSys->setLifetimeRange( time, time ); - - AudioEventRTS soundToPlay = TheAudio->getMiscAudio()->m_repairSparks; - soundToPlay.setPosition( &pos ); - TheAudio->addAudioEvent( &soundToPlay ); + pos.add( obj->getPosition() ); } + else + { + pos.set( obj->getPosition() ); + } + + weldingSys->setPosition( &pos ); + Real time = (Real)(m_framesToWait * LOGICFRAMES_PER_SECOND); + weldingSys->setLifetimeRange( time, time ); + + AudioEventRTS soundToPlay = TheAudio->getMiscAudio()->m_repairSparks; + soundToPlay.setPosition( &pos ); + TheAudio->addAudioEvent( &soundToPlay ); } } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/StealthDetectorUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/StealthDetectorUpdate.cpp index 7be96b7a61f..746730dc27d 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/StealthDetectorUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/StealthDetectorUpdate.cpp @@ -312,18 +312,15 @@ UpdateSleepTime StealthDetectorUpdate::update() if (data->m_IRGridParticleSysTmpl) { const ParticleSystemTemplate *gridTemplate = data->m_IRGridParticleSysTmpl; - if (gridTemplate) + ParticleSystem *sys = TheParticleSystemManager->createParticleSystem( gridTemplate );//GRID + if (sys) { - ParticleSystem *sys = TheParticleSystemManager->createParticleSystem( gridTemplate );//GRID - if (sys) - { - Coord3D gridPosition = *them->getPosition(); - gridPosition.z = self->getPosition()->z + 17; - gridPosition.x -= ((Int)gridPosition.x)%12; - gridPosition.y -= ((Int)gridPosition.y)%12; + Coord3D gridPosition = *them->getPosition(); + gridPosition.z = self->getPosition()->z + 17; + gridPosition.x -= ((Int)gridPosition.x)%12; + gridPosition.y -= ((Int)gridPosition.y)%12; - sys->setPosition( &gridPosition ); - } + sys->setPosition( &gridPosition ); } } @@ -373,34 +370,28 @@ UpdateSleepTime StealthDetectorUpdate::update() else pingTemplate = data->m_IRParticleSysTmpl; - if (pingTemplate) + ParticleSystem *sys = TheParticleSystemManager->createParticleSystem( pingTemplate ); + if (sys) { - ParticleSystem *sys = TheParticleSystemManager->createParticleSystem( pingTemplate ); - if (sys) - { - if (myDraw) - sys->attachToDrawable( myDraw ); - else - sys->attachToObject( self ); - - sys->setPosition( &bonePosition ); - } + if (myDraw) + sys->attachToDrawable( myDraw ); + else + sys->attachToObject( self ); + + sys->setPosition( &bonePosition ); } const ParticleSystemTemplate *beaconTemplate = data->m_IRBeaconParticleSysTmpl; - if (beaconTemplate) + sys = TheParticleSystemManager->createParticleSystem( beaconTemplate );//BEACON + if (sys) { - ParticleSystem *sys = TheParticleSystemManager->createParticleSystem( beaconTemplate );//BEACON - if (sys) - { - if (myDraw) - sys->attachToDrawable( myDraw ); - else - sys->attachToObject( self ); + if (myDraw) + sys->attachToDrawable( myDraw ); + else + sys->attachToObject( self ); - sys->setPosition( &bonePosition ); + sys->setPosition( &bonePosition ); - } } AudioEventRTS IRPingSound; diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp index 7c9c612245c..d10dff653a1 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp @@ -10145,15 +10145,12 @@ static void _updateAndSetCurrentSystem() // to be a tiny memory overwrite, now it is a crash since destroy() now has a function call. ParticleSystemTemplate *parentTemp = TheParticleSystemManager->findParentTemplate(pTemp->getName(), 0); - if (parentTemp) { - ParticleSystem *parentSystem = nullptr; - parentSystem = TheParticleSystemManager->createParticleSystem(parentTemp); - - if (parentSystem) { - ParticleSystem::mergeRelatedParticleSystems(parentSystem, st_particleSystem, true); - parentSystem->stop(); - parentSystem->destroy(); - } + ParticleSystem *parentSystem = TheParticleSystemManager->createParticleSystem(parentTemp); + + if (parentSystem) { + ParticleSystem::mergeRelatedParticleSystems(parentSystem, st_particleSystem, true); + parentSystem->stop(); + parentSystem->destroy(); } Coord3D pos; From 6dd0b8f1971ed0eba46f76afcc655195a88da584 Mon Sep 17 00:00:00 2001 From: stm <14291421+stephanmeesters@users.noreply.github.com> Date: Mon, 18 May 2026 22:24:50 +0200 Subject: [PATCH 2/4] Process review comments --- .../GameEngine/Source/GameLogic/Object/Update/EMPUpdate.cpp | 2 ++ .../GameLogic/Object/Update/HelicopterSlowDeathUpdate.cpp | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/EMPUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/EMPUpdate.cpp index 7bb0a907522..aba51b4c2ee 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/EMPUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/EMPUpdate.cpp @@ -451,7 +451,9 @@ UpdateSleepTime LeafletDropBehavior::update() const ParticleSystemTemplate *tmp = data->m_leafletFXParticleSystem; ParticleSystem *sys = TheParticleSystemManager->createParticleSystem(tmp); if (sys) + { sys->attachToObject(getObject()); + } m_fxFired = TRUE; // hey, at least we tried. } diff --git a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/HelicopterSlowDeathUpdate.cpp b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/HelicopterSlowDeathUpdate.cpp index 1be0c57ed25..0569bca3e84 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/HelicopterSlowDeathUpdate.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/HelicopterSlowDeathUpdate.cpp @@ -263,7 +263,6 @@ void HelicopterSlowDeathBehavior::beginSlowDeath( const DamageInfo *damageInfo ) - } From 9c7958abe9f6769c2f0b7eaa1f8f7c30f434fdd8 Mon Sep 17 00:00:00 2001 From: stm <14291421+stephanmeesters@users.noreply.github.com> Date: Tue, 19 May 2026 22:56:09 +0200 Subject: [PATCH 3/4] Revert change affecting failsafe branch --- .../GameClient/Drawable/Update/BeaconClientUpdate.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Core/GameEngine/Source/GameClient/Drawable/Update/BeaconClientUpdate.cpp b/Core/GameEngine/Source/GameClient/Drawable/Update/BeaconClientUpdate.cpp index d9589c35cbb..63071f8340c 100644 --- a/Core/GameEngine/Source/GameClient/Drawable/Update/BeaconClientUpdate.cpp +++ b/Core/GameEngine/Source/GameClient/Drawable/Update/BeaconClientUpdate.cpp @@ -97,10 +97,11 @@ static ParticleSystem* createParticleSystem( Drawable *draw ) DEBUG_ASSERTCRASH(particleTemplate, ("Could not find particle system %s", templateName.str())); - system = TheParticleSystemManager->createParticleSystem( particleTemplate ); - if (system) + if (particleTemplate) { - system->attachToDrawable( draw ); + system = TheParticleSystemManager->createParticleSystem( particleTemplate ); + if (system) + system->attachToDrawable( draw ); } else// This is a failsafe... if someone has monkeyed with the particle system names, or the MP house colors {// THis this will whip up a new particle system to match the house color provided From 97bcdd700f0bbd7a9df0783d75ac4fdf7c1b97ea Mon Sep 17 00:00:00 2001 From: stm <14291421+stephanmeesters@users.noreply.github.com> Date: Tue, 19 May 2026 23:19:22 +0200 Subject: [PATCH 4/4] Replicate in Generals --- .../Object/Behavior/AutoHealBehavior.cpp | 9 +-- .../GameLogic/Object/ObjectCreationList.cpp | 4 +- .../Update/HelicopterSlowDeathUpdate.cpp | 40 ++++++------- .../GameLogic/Object/Update/LaserUpdate.cpp | 18 ++---- .../Update/ParticleUplinkCannonUpdate.cpp | 23 +++----- .../GameLogic/Object/Update/SlavedUpdate.cpp | 39 ++++++------- .../Object/Update/StealthDetectorUpdate.cpp | 56 ++++++++----------- .../GameLogic/ScriptEngine/ScriptEngine.cpp | 15 ++--- 8 files changed, 83 insertions(+), 121 deletions(-) diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/AutoHealBehavior.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/AutoHealBehavior.cpp index 2ba064bcf06..2fb184d1234 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/AutoHealBehavior.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Behavior/AutoHealBehavior.cpp @@ -279,13 +279,10 @@ void AutoHealBehavior::pulseHealObject( Object *obj ) obj->attemptHealingFromSoleBenefactor( data->m_healingAmount, getObject(), data->m_healingDelay ); - if( data->m_unitHealPulseParticleSystemTmpl ) + ParticleSystem *system = TheParticleSystemManager->createParticleSystem( data->m_unitHealPulseParticleSystemTmpl ); + if( system ) { - ParticleSystem *system = TheParticleSystemManager->createParticleSystem( data->m_unitHealPulseParticleSystemTmpl ); - if( system ) - { - system->setPosition( obj->getPosition() ); - } + system->setPosition( obj->getPosition() ); } m_soonestHealFrame = TheGameLogic->getFrame() + data->m_healingDelay;// In case onDamage tries to wake us up early diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp index 0e802efaadb..fc2cf7a7e3d 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/ObjectCreationList.cpp @@ -959,9 +959,9 @@ class GenericObjectCreationNugget : public ObjectCreationNugget if (!m_particleSysName.isEmpty()) { const ParticleSystemTemplate *tmp = TheParticleSystemManager->findTemplate(m_particleSysName); - if (tmp) + ParticleSystem *sys = TheParticleSystemManager->createParticleSystem(tmp); + if (sys) { - ParticleSystem *sys = TheParticleSystemManager->createParticleSystem(tmp); sys->attachToObject(obj); } } diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/HelicopterSlowDeathUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/HelicopterSlowDeathUpdate.cpp index b8c2be438f5..78210364329 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/HelicopterSlowDeathUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/HelicopterSlowDeathUpdate.cpp @@ -229,40 +229,36 @@ void HelicopterSlowDeathBehavior::beginSlowDeath( const DamageInfo *damageInfo ) locomotor->setMaxBraking( modData->m_maxBraking ); // attach particle system to bone if present - if( modData->m_attachParticleSystem ) + ParticleSystem *pSys = TheParticleSystemManager->createParticleSystem( modData->m_attachParticleSystem ); + if( pSys ) { - ParticleSystem *pSys = TheParticleSystemManager->createParticleSystem( modData->m_attachParticleSystem ); - if( pSys ) + + // where do the offset attachment to + if( modData->m_attachParticleBone.isEmpty() == FALSE ) { + Drawable *draw = getObject()->getDrawable(); - // where do the offset attachment to - if( modData->m_attachParticleBone.isEmpty() == FALSE ) + if( draw ) { - Drawable *draw = getObject()->getDrawable(); + Coord3D pos; - if( draw ) - { - Coord3D pos; - - if( draw->getPristineBonePositions( modData->m_attachParticleBone.str(), 0, &pos, nullptr, 1 ) ) - pSys->setPosition( &pos ); - - } + if( draw->getPristineBonePositions( modData->m_attachParticleBone.str(), 0, &pos, nullptr, 1 ) ) + pSys->setPosition( &pos ); } - else - { - // use location coord specified ... it will be zero if not given which is center of obj anyway - pSys->setPosition( &modData->m_attachParticleLoc ); - - } + } + else + { - // attach the particle system to the object - pSys->attachToObject( getObject() ); + // use location coord specified ... it will be zero if not given which is center of obj anyway + pSys->setPosition( &modData->m_attachParticleLoc ); } + // attach the particle system to the object + pSys->attachToObject( getObject() ); + } diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/LaserUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/LaserUpdate.cpp index fb1276731fd..13083d4cc31 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/LaserUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/LaserUpdate.cpp @@ -258,13 +258,10 @@ void LaserUpdate::initLaser( const Object *parent, const Coord3D *startPos, cons if( data->m_particleSystemName.isNotEmpty() ) { const ParticleSystemTemplate *tmp = TheParticleSystemManager->findTemplate( data->m_particleSystemName ); - if( tmp ) + system = TheParticleSystemManager->createParticleSystem( tmp ); + if( system ) { - system = TheParticleSystemManager->createParticleSystem( tmp ); - if( system ) - { - m_particleSystemID = system->getSystemID(); - } + m_particleSystemID = system->getSystemID(); } } @@ -272,13 +269,10 @@ void LaserUpdate::initLaser( const Object *parent, const Coord3D *startPos, cons if( data->m_targetParticleSystemName.isNotEmpty() ) { const ParticleSystemTemplate *tmp = TheParticleSystemManager->findTemplate( data->m_targetParticleSystemName ); - if( tmp ) + system = TheParticleSystemManager->createParticleSystem( tmp ); + if( system ) { - system = TheParticleSystemManager->createParticleSystem( tmp ); - if( system ) - { - m_targetParticleSystemID = system->getSystemID(); - } + m_targetParticleSystemID = system->getSystemID(); } } } diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ParticleUplinkCannonUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ParticleUplinkCannonUpdate.cpp index 980a9c525af..7441ff504c2 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ParticleUplinkCannonUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/ParticleUplinkCannonUpdate.cpp @@ -849,15 +849,11 @@ void ParticleUplinkCannonUpdate::createConnectorFlare( IntensityTypes intensity if( str.isNotEmpty() ) { const ParticleSystemTemplate *tmp = TheParticleSystemManager->findTemplate( str ); - ParticleSystem *system; - if( tmp ) + ParticleSystem *system = TheParticleSystemManager->createParticleSystem( tmp ); + if( system ) { - system = TheParticleSystemManager->createParticleSystem( tmp ); - if( system ) - { - m_connectorSystemID = system->getSystemID(); - system->setPosition( &m_connectorNodePosition ); - } + m_connectorSystemID = system->getSystemID(); + system->setPosition( &m_connectorNodePosition ); } } } @@ -885,14 +881,11 @@ void ParticleUplinkCannonUpdate::createLaserBaseFlare( IntensityTypes intensity if( str.isNotEmpty() ) { const ParticleSystemTemplate *tmp = TheParticleSystemManager->findTemplate( str ); - if( tmp ) + ParticleSystem *system = TheParticleSystemManager->createParticleSystem( tmp ); + if( system ) { - ParticleSystem *system = TheParticleSystemManager->createParticleSystem( tmp ); - if( system ) - { - m_laserBaseSystemID = system->getSystemID(); - system->setPosition( &m_laserOriginPosition ); - } + m_laserBaseSystemID = system->getSystemID(); + system->setPosition( &m_laserOriginPosition ); } } } diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/SlavedUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/SlavedUpdate.cpp index 6ffef8dc861..7441f62a78d 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/SlavedUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/SlavedUpdate.cpp @@ -616,30 +616,27 @@ void SlavedUpdate::setRepairState( RepairStates repairState ) if( !data->m_weldingSysName.isEmpty() ) { const ParticleSystemTemplate *tmp = TheParticleSystemManager->findTemplate( data->m_weldingSysName ); - if( tmp ) + ParticleSystem *weldingSys = TheParticleSystemManager->createParticleSystem(tmp); + if( weldingSys ) { - ParticleSystem *weldingSys = TheParticleSystemManager->createParticleSystem(tmp); - if( weldingSys ) + Coord3D pos; + //Get the bone position + if( draw->getPristineBonePositions( data->m_weldingFXBone.str(), 0, &pos, nullptr, 1 ) ) { - Coord3D pos; - //Get the bone position - if( draw->getPristineBonePositions( data->m_weldingFXBone.str(), 0, &pos, nullptr, 1 ) ) - { - pos.add( obj->getPosition() ); - } - else - { - pos.set( obj->getPosition() ); - } - - weldingSys->setPosition( &pos ); - Real time = (Real)(m_framesToWait * LOGICFRAMES_PER_SECOND); - weldingSys->setLifetimeRange( time, time ); - - AudioEventRTS soundToPlay = TheAudio->getMiscAudio()->m_repairSparks; - soundToPlay.setPosition( &pos ); - TheAudio->addAudioEvent( &soundToPlay ); + pos.add( obj->getPosition() ); } + else + { + pos.set( obj->getPosition() ); + } + + weldingSys->setPosition( &pos ); + Real time = (Real)(m_framesToWait * LOGICFRAMES_PER_SECOND); + weldingSys->setLifetimeRange( time, time ); + + AudioEventRTS soundToPlay = TheAudio->getMiscAudio()->m_repairSparks; + soundToPlay.setPosition( &pos ); + TheAudio->addAudioEvent( &soundToPlay ); } } diff --git a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/StealthDetectorUpdate.cpp b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/StealthDetectorUpdate.cpp index d96c5a8a32f..4f8fbbdef21 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/Object/Update/StealthDetectorUpdate.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/Object/Update/StealthDetectorUpdate.cpp @@ -290,22 +290,16 @@ UpdateSleepTime StealthDetectorUpdate::update() theirDraw->setHeatVisionOpacity( 1.0f ); } - if (data->m_IRGridParticleSysTmpl) + const ParticleSystemTemplate *gridTemplate = data->m_IRGridParticleSysTmpl; + ParticleSystem *sys = TheParticleSystemManager->createParticleSystem( gridTemplate );//GRID + if (sys) { - const ParticleSystemTemplate *gridTemplate = data->m_IRGridParticleSysTmpl; - if (gridTemplate) - { - ParticleSystem *sys = TheParticleSystemManager->createParticleSystem( gridTemplate );//GRID - if (sys) - { - Coord3D gridPosition = *them->getPosition(); - gridPosition.z = self->getPosition()->z + 17; - gridPosition.x -= ((Int)gridPosition.x)%12; - gridPosition.y -= ((Int)gridPosition.y)%12; + Coord3D gridPosition = *them->getPosition(); + gridPosition.z = self->getPosition()->z + 17; + gridPosition.x -= ((Int)gridPosition.x)%12; + gridPosition.y -= ((Int)gridPosition.y)%12; - sys->setPosition( &gridPosition ); - } - } + sys->setPosition( &gridPosition ); } } @@ -352,34 +346,28 @@ UpdateSleepTime StealthDetectorUpdate::update() else pingTemplate = data->m_IRParticleSysTmpl; - if (pingTemplate) + ParticleSystem *sys = TheParticleSystemManager->createParticleSystem( pingTemplate ); + if (sys) { - ParticleSystem *sys = TheParticleSystemManager->createParticleSystem( pingTemplate ); - if (sys) - { - if (myDraw) - sys->attachToDrawable( myDraw ); - else - sys->attachToObject( self ); + if (myDraw) + sys->attachToDrawable( myDraw ); + else + sys->attachToObject( self ); - sys->setPosition( &bonePosition ); - } + sys->setPosition( &bonePosition ); } const ParticleSystemTemplate *beaconTemplate = data->m_IRBeaconParticleSysTmpl; - if (beaconTemplate) + sys = TheParticleSystemManager->createParticleSystem( beaconTemplate );//BEACON + if (sys) { - ParticleSystem *sys = TheParticleSystemManager->createParticleSystem( beaconTemplate );//BEACON - if (sys) - { - if (myDraw) - sys->attachToDrawable( myDraw ); - else - sys->attachToObject( self ); + if (myDraw) + sys->attachToDrawable( myDraw ); + else + sys->attachToObject( self ); - sys->setPosition( &bonePosition ); + sys->setPosition( &bonePosition ); - } } AudioEventRTS IRPingSound; diff --git a/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp b/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp index 7775245e531..1622c63b0d2 100644 --- a/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp +++ b/Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp @@ -9442,15 +9442,12 @@ static void _updateAndSetCurrentSystem() // to be a tiny memory overwrite, now it is a crash since destroy() now has a function call. ParticleSystemTemplate *parentTemp = TheParticleSystemManager->findParentTemplate(pTemp->getName(), 0); - if (parentTemp) { - ParticleSystem *parentSystem = nullptr; - parentSystem = TheParticleSystemManager->createParticleSystem(parentTemp); - - if (parentSystem) { - ParticleSystem::mergeRelatedParticleSystems(parentSystem, st_particleSystem, true); - parentSystem->stop(); - parentSystem->destroy(); - } + ParticleSystem *parentSystem = TheParticleSystemManager->createParticleSystem(parentTemp); + + if (parentSystem) { + ParticleSystem::mergeRelatedParticleSystems(parentSystem, st_particleSystem, true); + parentSystem->stop(); + parentSystem->destroy(); } Coord3D pos;