Skip to content

Commit 1165fff

Browse files
authored
[GEN][ZH] Separate ParticleUplinkCannonUpdate's damage radius calculation from LaserUpdate's client update (2) (#1061)
1 parent 83c058f commit 1165fff

File tree

2 files changed

+124
-84
lines changed

2 files changed

+124
-84
lines changed

Generals/Code/GameEngine/Source/GameLogic/Object/Update/ParticleUplinkCannonUpdate.cpp

Lines changed: 62 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -211,16 +211,16 @@ void ParticleUplinkCannonUpdate::killEverything()
211211
removeAllEffects();
212212

213213
//This laser is independent from the other effects and needs to be specially handled.
214-
if( m_orbitToTargetBeamID )
214+
if( m_orbitToTargetBeamID != INVALID_DRAWABLE_ID )
215215
{
216216
Drawable *beam = TheGameClient->findDrawableByID( m_orbitToTargetBeamID );
217217
if( beam )
218218
{
219219
TheGameClient->destroyDrawable( beam );
220220
}
221221
m_orbitToTargetBeamID = INVALID_DRAWABLE_ID;
222-
m_orbitToTargetLaserRadius = LaserRadiusUpdate();
223222
}
223+
m_orbitToTargetLaserRadius = LaserRadiusUpdate();
224224

225225
TheAudio->removeAudioEvent( m_powerupSound.getPlayingHandle() );
226226
TheAudio->removeAudioEvent( m_unpackToReadySound.getPlayingHandle() );
@@ -410,40 +410,43 @@ UpdateSleepTime ParticleUplinkCannonUpdate::update()
410410
break;
411411
case LASERSTATUS_BORN:
412412
{
413-
Drawable *beam = TheGameClient->findDrawableByID( m_orbitToTargetBeamID );
414-
if( beam )
413+
if( orbitalDecayStart <= now )
415414
{
416-
//m_annihilationSound.setPosition( beam->getPosition() );
417-
if( orbitalDecayStart <= now )
415+
Drawable *beam = TheGameClient->findDrawableByID( m_orbitToTargetBeamID );
416+
if( beam )
418417
{
418+
//m_annihilationSound.setPosition( beam->getPosition() );
419419
static NameKeyType nameKeyClientUpdate = NAMEKEY( "LaserUpdate" );
420420
LaserUpdate *update = (LaserUpdate*)beam->findClientUpdateModule( nameKeyClientUpdate );
421421
if( update )
422422
{
423423
update->setDecayFrames( data->m_widthGrowFrames );
424-
m_orbitToTargetLaserRadius.setDecayFrames( data->m_widthGrowFrames );
425424
}
426-
m_laserStatus = LASERSTATUS_DECAYING;
427425
}
426+
m_orbitToTargetLaserRadius.setDecayFrames( data->m_widthGrowFrames );
427+
m_laserStatus = LASERSTATUS_DECAYING;
428428
}
429429
break;
430430
}
431431
case LASERSTATUS_DECAYING:
432432
{
433-
Drawable *beam = TheGameClient->findDrawableByID( m_orbitToTargetBeamID );
434-
if( beam )
433+
if( orbitalDeathFrame <= now )
435434
{
436-
//m_annihilationSound.setPosition( beam->getPosition() );
437435
TheAudio->removeAudioEvent( m_annihilationSound.getPlayingHandle() );
438-
if( orbitalDeathFrame <= now )
436+
if ( m_orbitToTargetBeamID != INVALID_DRAWABLE_ID )
439437
{
440-
TheGameClient->destroyDrawable( beam );
438+
Drawable *beam = TheGameClient->findDrawableByID( m_orbitToTargetBeamID );
439+
if( beam )
440+
{
441+
//m_annihilationSound.setPosition( beam->getPosition() );
442+
TheGameClient->destroyDrawable( beam );
443+
}
441444
m_orbitToTargetBeamID = INVALID_DRAWABLE_ID;
442-
m_orbitToTargetLaserRadius = LaserRadiusUpdate();
443-
m_laserStatus = LASERSTATUS_DEAD;
444-
m_startAttackFrame = 0;
445-
setLogicalStatus( STATUS_IDLE );
446445
}
446+
m_orbitToTargetLaserRadius = LaserRadiusUpdate();
447+
m_laserStatus = LASERSTATUS_DEAD;
448+
m_startAttackFrame = 0;
449+
setLogicalStatus( STATUS_IDLE );
447450
}
448451
break;
449452
}
@@ -452,8 +455,13 @@ UpdateSleepTime ParticleUplinkCannonUpdate::update()
452455
break;
453456
}
454457

455-
Drawable *beam = TheGameClient->findDrawableByID( m_orbitToTargetBeamID );
456-
if( beam && orbitalBirthFrame <= now && now <= orbitalDeathFrame )
458+
#if RETAIL_COMPATIBLE_CRC
459+
// TheSuperHackers @info helmutbuhler 12/06/2025
460+
// Note that this code is very brittle for retail compatibility. Inlining isFiring
461+
// can cause incompatibility in some circumstances.
462+
#endif
463+
const Bool isFiring = orbitalBirthFrame <= now && now < orbitalDeathFrame;
464+
if ( isFiring )
457465
{
458466

459467
if( !m_manualTargetMode )
@@ -548,27 +556,35 @@ UpdateSleepTime ParticleUplinkCannonUpdate::update()
548556

549557
Real scorchRadius = 0.0f;
550558
Real damageRadius = 0.0f;
559+
Real templateLaserRadius = 13.0f;
560+
Real visualLaserRadius = 0.0f;
551561

552562
//Reset the laser position
553-
static NameKeyType nameKeyClientUpdate = NAMEKEY( "LaserUpdate" );
554-
LaserUpdate *update = (LaserUpdate*)beam->findClientUpdateModule( nameKeyClientUpdate );
555-
if( update )
563+
Drawable *beam = TheGameClient->findDrawableByID( m_orbitToTargetBeamID );
564+
if ( beam )
556565
{
557-
update->initLaser( NULL, &orbitPosition, &m_currentTargetPosition );
558-
const Real visualLaserRadius = update->getCurrentLaserRadius();
559-
scorchRadius = visualLaserRadius * data->m_scorchMarkScalar;
560-
561-
// TheSuperHackers @refactor helmutbuhler/xezon 17/05/2025
562-
// Originally the damage radius was calculated with a value updated by LaserUpdate::clientUpdate().
563-
// To no longer rely on client updates, this class now maintains a logical copy of the visual laser radius.
564-
m_orbitToTargetLaserRadius.updateRadius();
565-
const Real logicalLaserRadius = update->getTemplateLaserRadius() * m_orbitToTargetLaserRadius.getWidthScale();
566-
damageRadius = logicalLaserRadius * data->m_damageRadiusScalar;
567-
#if RETAIL_COMPATIBLE_CRC
568-
DEBUG_ASSERTCRASH(logicalLaserRadius == visualLaserRadius,
569-
("ParticleUplinkCannonUpdate's laser radius does not match LaserUpdate's laser radius - will cause mismatch in VS6 retail compatible builds\n"));
570-
#endif
566+
static NameKeyType nameKeyClientUpdate = NAMEKEY( "LaserUpdate" );
567+
LaserUpdate *update = (LaserUpdate*)beam->findClientUpdateModule( nameKeyClientUpdate );
568+
if( update )
569+
{
570+
update->initLaser( NULL, &orbitPosition, &m_currentTargetPosition );
571+
// TheSuperHackers @logic-client-separation The GameLogic has a dependency on this drawable.
572+
// The logical laser radius for the damage should probably be part of ParticleUplinkCannonUpdateModuleData.
573+
templateLaserRadius = update->getTemplateLaserRadius();
574+
visualLaserRadius = update->getCurrentLaserRadius();
575+
}
571576
}
577+
// TheSuperHackers @refactor helmutbuhler/xezon 17/05/2025
578+
// Originally the damageRadius was calculated with a value updated by LaserUpdate::clientUpdate.
579+
// To no longer rely on GameClient updates, this class now maintains a copy of the LaserRadiusUpdate.
580+
m_orbitToTargetLaserRadius.updateRadius();
581+
const Real logicalLaserRadius = templateLaserRadius * m_orbitToTargetLaserRadius.getWidthScale();
582+
damageRadius = logicalLaserRadius * data->m_damageRadiusScalar;
583+
scorchRadius = logicalLaserRadius * data->m_scorchMarkScalar;
584+
#if defined(RETAIL_COMPATIBLE_CRC)
585+
DEBUG_ASSERTCRASH(logicalLaserRadius == visualLaserRadius,
586+
("ParticleUplinkCannonUpdate's laser radius does not match LaserUpdate's laser radius - will cause mismatch in VS6 retail compatible builds\n"));
587+
#endif
572588

573589
//Create scorch marks periodically
574590
if( m_nextScorchMarkFrame <= now )
@@ -917,13 +933,15 @@ void ParticleUplinkCannonUpdate::createOrbitToTargetLaser( UnsignedInt growthFra
917933
{
918934
const ParticleUplinkCannonUpdateModuleData *data = getParticleUplinkCannonUpdateModuleData();
919935

920-
Drawable *beam = TheGameClient->findDrawableByID( m_orbitToTargetBeamID );
921-
if( beam )
936+
if ( m_orbitToTargetBeamID != INVALID_DRAWABLE_ID )
922937
{
923-
TheAudio->removeAudioEvent( m_annihilationSound.getPlayingHandle() );
924-
TheGameClient->destroyDrawable( beam );
938+
Drawable *beam = TheGameClient->findDrawableByID( m_orbitToTargetBeamID );
939+
if( beam )
940+
{
941+
TheAudio->removeAudioEvent( m_annihilationSound.getPlayingHandle() );
942+
TheGameClient->destroyDrawable( beam );
943+
}
925944
m_orbitToTargetBeamID = INVALID_DRAWABLE_ID;
926-
m_orbitToTargetLaserRadius = LaserRadiusUpdate();
927945
}
928946

929947
if( data->m_particleBeamLaserName.isNotEmpty() )
@@ -943,7 +961,6 @@ void ParticleUplinkCannonUpdate::createOrbitToTargetLaser( UnsignedInt growthFra
943961
orbitPosition.set( &m_initialTargetPosition );
944962
orbitPosition.z += 500.0f;
945963
update->initLaser( NULL, &orbitPosition, &m_initialTargetPosition, growthFrames );
946-
m_orbitToTargetLaserRadius.initRadius( growthFrames );
947964
}
948965
}
949966
}
@@ -954,6 +971,9 @@ void ParticleUplinkCannonUpdate::createOrbitToTargetLaser( UnsignedInt growthFra
954971
m_annihilationSound.setPlayingHandle( TheAudio->addAudioEvent( &m_annihilationSound ) );
955972
}
956973
}
974+
975+
m_orbitToTargetLaserRadius = LaserRadiusUpdate();
976+
m_orbitToTargetLaserRadius.initRadius( growthFrames );
957977
}
958978

959979
//-------------------------------------------------------------------------------------------------

GeneralsMD/Code/GameEngine/Source/GameLogic/Object/Update/ParticleUplinkCannonUpdate.cpp

Lines changed: 62 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -212,16 +212,16 @@ void ParticleUplinkCannonUpdate::killEverything()
212212
removeAllEffects();
213213

214214
//This laser is independent from the other effects and needs to be specially handled.
215-
if( m_orbitToTargetBeamID )
215+
if( m_orbitToTargetBeamID != INVALID_DRAWABLE_ID )
216216
{
217217
Drawable *beam = TheGameClient->findDrawableByID( m_orbitToTargetBeamID );
218218
if( beam )
219219
{
220220
TheGameClient->destroyDrawable( beam );
221221
}
222222
m_orbitToTargetBeamID = INVALID_DRAWABLE_ID;
223-
m_orbitToTargetLaserRadius = LaserRadiusUpdate();
224223
}
224+
m_orbitToTargetLaserRadius = LaserRadiusUpdate();
225225

226226
TheAudio->removeAudioEvent( m_powerupSound.getPlayingHandle() );
227227
TheAudio->removeAudioEvent( m_unpackToReadySound.getPlayingHandle() );
@@ -457,40 +457,43 @@ UpdateSleepTime ParticleUplinkCannonUpdate::update()
457457
break;
458458
case LASERSTATUS_BORN:
459459
{
460-
Drawable *beam = TheGameClient->findDrawableByID( m_orbitToTargetBeamID );
461-
if( beam )
460+
if( orbitalDecayStart <= now )
462461
{
463-
//m_annihilationSound.setPosition( beam->getPosition() );
464-
if( orbitalDecayStart <= now )
462+
Drawable *beam = TheGameClient->findDrawableByID( m_orbitToTargetBeamID );
463+
if( beam )
465464
{
465+
//m_annihilationSound.setPosition( beam->getPosition() );
466466
static NameKeyType nameKeyClientUpdate = NAMEKEY( "LaserUpdate" );
467467
LaserUpdate *update = (LaserUpdate*)beam->findClientUpdateModule( nameKeyClientUpdate );
468468
if( update )
469469
{
470470
update->setDecayFrames( data->m_widthGrowFrames );
471-
m_orbitToTargetLaserRadius.setDecayFrames( data->m_widthGrowFrames );
472471
}
473-
m_laserStatus = LASERSTATUS_DECAYING;
474472
}
473+
m_orbitToTargetLaserRadius.setDecayFrames( data->m_widthGrowFrames );
474+
m_laserStatus = LASERSTATUS_DECAYING;
475475
}
476476
break;
477477
}
478478
case LASERSTATUS_DECAYING:
479479
{
480-
Drawable *beam = TheGameClient->findDrawableByID( m_orbitToTargetBeamID );
481-
if( beam )
480+
if( orbitalDeathFrame <= now )
482481
{
483-
//m_annihilationSound.setPosition( beam->getPosition() );
484482
TheAudio->removeAudioEvent( m_annihilationSound.getPlayingHandle() );
485-
if( orbitalDeathFrame <= now )
483+
if ( m_orbitToTargetBeamID != INVALID_DRAWABLE_ID )
486484
{
487-
TheGameClient->destroyDrawable( beam );
485+
Drawable *beam = TheGameClient->findDrawableByID( m_orbitToTargetBeamID );
486+
if( beam )
487+
{
488+
//m_annihilationSound.setPosition( beam->getPosition() );
489+
TheGameClient->destroyDrawable( beam );
490+
}
488491
m_orbitToTargetBeamID = INVALID_DRAWABLE_ID;
489-
m_orbitToTargetLaserRadius = LaserRadiusUpdate();
490-
m_laserStatus = LASERSTATUS_DEAD;
491-
m_startAttackFrame = 0;
492-
setLogicalStatus( STATUS_IDLE );
493492
}
493+
m_orbitToTargetLaserRadius = LaserRadiusUpdate();
494+
m_laserStatus = LASERSTATUS_DEAD;
495+
m_startAttackFrame = 0;
496+
setLogicalStatus( STATUS_IDLE );
494497
}
495498
break;
496499
}
@@ -499,8 +502,13 @@ UpdateSleepTime ParticleUplinkCannonUpdate::update()
499502
break;
500503
}
501504

502-
Drawable *beam = TheGameClient->findDrawableByID( m_orbitToTargetBeamID );
503-
if( beam && orbitalBirthFrame <= now && now <= orbitalDeathFrame )
505+
#if RETAIL_COMPATIBLE_CRC
506+
// TheSuperHackers @info helmutbuhler 12/06/2025
507+
// Note that this code is very brittle for retail compatibility. Inlining isFiring
508+
// can cause incompatibility in some circumstances.
509+
#endif
510+
const Bool isFiring = orbitalBirthFrame <= now && now < orbitalDeathFrame;
511+
if ( isFiring )
504512
{
505513

506514
if( !m_manualTargetMode && !m_scriptedWaypointMode )
@@ -609,27 +617,35 @@ UpdateSleepTime ParticleUplinkCannonUpdate::update()
609617

610618
Real scorchRadius = 0.0f;
611619
Real damageRadius = 0.0f;
620+
Real templateLaserRadius = 13.0f;
621+
Real visualLaserRadius = 0.0f;
612622

613623
//Reset the laser position
614-
static NameKeyType nameKeyClientUpdate = NAMEKEY( "LaserUpdate" );
615-
LaserUpdate *update = (LaserUpdate*)beam->findClientUpdateModule( nameKeyClientUpdate );
616-
if( update )
624+
Drawable *beam = TheGameClient->findDrawableByID( m_orbitToTargetBeamID );
625+
if ( beam )
617626
{
618-
update->initLaser( NULL, NULL, &orbitPosition, &m_currentTargetPosition, "" );
619-
const Real visualLaserRadius = update->getCurrentLaserRadius();
620-
scorchRadius = visualLaserRadius * data->m_scorchMarkScalar;
621-
622-
// TheSuperHackers @refactor helmutbuhler/xezon 17/05/2025
623-
// Originally the damage radius was calculated with a value updated by LaserUpdate::clientUpdate().
624-
// To no longer rely on client updates, this class now maintains a logical copy of the visual laser radius.
625-
m_orbitToTargetLaserRadius.updateRadius();
626-
const Real logicalLaserRadius = update->getTemplateLaserRadius() * m_orbitToTargetLaserRadius.getWidthScale();
627-
damageRadius = logicalLaserRadius * data->m_damageRadiusScalar;
628-
#if RETAIL_COMPATIBLE_XFER_CRC
629-
DEBUG_ASSERTCRASH(logicalLaserRadius == visualLaserRadius,
630-
("ParticleUplinkCannonUpdate's laser radius does not match LaserUpdate's laser radius - will cause mismatch in VS6 retail compatible builds\n"));
631-
#endif
627+
static NameKeyType nameKeyClientUpdate = NAMEKEY( "LaserUpdate" );
628+
LaserUpdate *update = (LaserUpdate*)beam->findClientUpdateModule( nameKeyClientUpdate );
629+
if( update )
630+
{
631+
update->initLaser( NULL, NULL, &orbitPosition, &m_currentTargetPosition, "" );
632+
// TheSuperHackers @logic-client-separation The GameLogic has a dependency on this drawable.
633+
// The logical laser radius for the damage should probably be part of ParticleUplinkCannonUpdateModuleData.
634+
templateLaserRadius = update->getTemplateLaserRadius();
635+
visualLaserRadius = update->getCurrentLaserRadius();
636+
}
632637
}
638+
// TheSuperHackers @refactor helmutbuhler/xezon 17/05/2025
639+
// Originally the damageRadius was calculated with a value updated by LaserUpdate::clientUpdate.
640+
// To no longer rely on GameClient updates, this class now maintains a copy of the LaserRadiusUpdate.
641+
m_orbitToTargetLaserRadius.updateRadius();
642+
const Real logicalLaserRadius = templateLaserRadius * m_orbitToTargetLaserRadius.getWidthScale();
643+
damageRadius = logicalLaserRadius * data->m_damageRadiusScalar;
644+
scorchRadius = logicalLaserRadius * data->m_scorchMarkScalar;
645+
#if defined(RETAIL_COMPATIBLE_CRC)
646+
DEBUG_ASSERTCRASH(logicalLaserRadius == visualLaserRadius,
647+
("ParticleUplinkCannonUpdate's laser radius does not match LaserUpdate's laser radius - will cause mismatch in VS6 retail compatible builds\n"));
648+
#endif
633649

634650
//Create scorch marks periodically
635651
if( m_nextScorchMarkFrame <= now )
@@ -988,13 +1004,15 @@ void ParticleUplinkCannonUpdate::createOrbitToTargetLaser( UnsignedInt growthFra
9881004
{
9891005
const ParticleUplinkCannonUpdateModuleData *data = getParticleUplinkCannonUpdateModuleData();
9901006

991-
Drawable *beam = TheGameClient->findDrawableByID( m_orbitToTargetBeamID );
992-
if( beam )
1007+
if ( m_orbitToTargetBeamID != INVALID_DRAWABLE_ID )
9931008
{
994-
TheAudio->removeAudioEvent( m_annihilationSound.getPlayingHandle() );
995-
TheGameClient->destroyDrawable( beam );
1009+
Drawable *beam = TheGameClient->findDrawableByID( m_orbitToTargetBeamID );
1010+
if( beam )
1011+
{
1012+
TheAudio->removeAudioEvent( m_annihilationSound.getPlayingHandle() );
1013+
TheGameClient->destroyDrawable( beam );
1014+
}
9961015
m_orbitToTargetBeamID = INVALID_DRAWABLE_ID;
997-
m_orbitToTargetLaserRadius = LaserRadiusUpdate();
9981016
}
9991017

10001018
if( data->m_particleBeamLaserName.isNotEmpty() )
@@ -1014,7 +1032,6 @@ void ParticleUplinkCannonUpdate::createOrbitToTargetLaser( UnsignedInt growthFra
10141032
orbitPosition.set( &m_initialTargetPosition );
10151033
orbitPosition.z += 500.0f;
10161034
update->initLaser( NULL, NULL, &orbitPosition, &m_initialTargetPosition, "", growthFrames );
1017-
m_orbitToTargetLaserRadius.initRadius( growthFrames );
10181035
}
10191036
}
10201037
}
@@ -1025,6 +1042,9 @@ void ParticleUplinkCannonUpdate::createOrbitToTargetLaser( UnsignedInt growthFra
10251042
m_annihilationSound.setPlayingHandle( TheAudio->addAudioEvent( &m_annihilationSound ) );
10261043
}
10271044
}
1045+
1046+
m_orbitToTargetLaserRadius = LaserRadiusUpdate();
1047+
m_orbitToTargetLaserRadius.initRadius( growthFrames );
10281048
}
10291049

10301050
//-------------------------------------------------------------------------------------------------

0 commit comments

Comments
 (0)