@@ -212,16 +212,16 @@ void ParticleUplinkCannonUpdate::killEverything()
212
212
removeAllEffects ();
213
213
214
214
// 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 )
216
216
{
217
217
Drawable *beam = TheGameClient->findDrawableByID ( m_orbitToTargetBeamID );
218
218
if ( beam )
219
219
{
220
220
TheGameClient->destroyDrawable ( beam );
221
221
}
222
222
m_orbitToTargetBeamID = INVALID_DRAWABLE_ID;
223
- m_orbitToTargetLaserRadius = LaserRadiusUpdate ();
224
223
}
224
+ m_orbitToTargetLaserRadius = LaserRadiusUpdate ();
225
225
226
226
TheAudio->removeAudioEvent ( m_powerupSound.getPlayingHandle () );
227
227
TheAudio->removeAudioEvent ( m_unpackToReadySound.getPlayingHandle () );
@@ -457,40 +457,43 @@ UpdateSleepTime ParticleUplinkCannonUpdate::update()
457
457
break ;
458
458
case LASERSTATUS_BORN:
459
459
{
460
- Drawable *beam = TheGameClient->findDrawableByID ( m_orbitToTargetBeamID );
461
- if ( beam )
460
+ if ( orbitalDecayStart <= now )
462
461
{
463
- // m_annihilationSound.setPosition( beam->getPosition() );
464
- if ( orbitalDecayStart <= now )
462
+ Drawable * beam = TheGameClient-> findDrawableByID ( m_orbitToTargetBeamID );
463
+ if ( beam )
465
464
{
465
+ // m_annihilationSound.setPosition( beam->getPosition() );
466
466
static NameKeyType nameKeyClientUpdate = NAMEKEY ( " LaserUpdate" );
467
467
LaserUpdate *update = (LaserUpdate*)beam->findClientUpdateModule ( nameKeyClientUpdate );
468
468
if ( update )
469
469
{
470
470
update->setDecayFrames ( data->m_widthGrowFrames );
471
- m_orbitToTargetLaserRadius.setDecayFrames ( data->m_widthGrowFrames );
472
471
}
473
- m_laserStatus = LASERSTATUS_DECAYING;
474
472
}
473
+ m_orbitToTargetLaserRadius.setDecayFrames ( data->m_widthGrowFrames );
474
+ m_laserStatus = LASERSTATUS_DECAYING;
475
475
}
476
476
break ;
477
477
}
478
478
case LASERSTATUS_DECAYING:
479
479
{
480
- Drawable *beam = TheGameClient->findDrawableByID ( m_orbitToTargetBeamID );
481
- if ( beam )
480
+ if ( orbitalDeathFrame <= now )
482
481
{
483
- // m_annihilationSound.setPosition( beam->getPosition() );
484
482
TheAudio->removeAudioEvent ( m_annihilationSound.getPlayingHandle () );
485
- if ( orbitalDeathFrame <= now )
483
+ if ( m_orbitToTargetBeamID != INVALID_DRAWABLE_ID )
486
484
{
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
+ }
488
491
m_orbitToTargetBeamID = INVALID_DRAWABLE_ID;
489
- m_orbitToTargetLaserRadius = LaserRadiusUpdate ();
490
- m_laserStatus = LASERSTATUS_DEAD;
491
- m_startAttackFrame = 0 ;
492
- setLogicalStatus ( STATUS_IDLE );
493
492
}
493
+ m_orbitToTargetLaserRadius = LaserRadiusUpdate ();
494
+ m_laserStatus = LASERSTATUS_DEAD;
495
+ m_startAttackFrame = 0 ;
496
+ setLogicalStatus ( STATUS_IDLE );
494
497
}
495
498
break ;
496
499
}
@@ -499,8 +502,13 @@ UpdateSleepTime ParticleUplinkCannonUpdate::update()
499
502
break ;
500
503
}
501
504
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 )
504
512
{
505
513
506
514
if ( !m_manualTargetMode && !m_scriptedWaypointMode )
@@ -609,27 +617,35 @@ UpdateSleepTime ParticleUplinkCannonUpdate::update()
609
617
610
618
Real scorchRadius = 0 .0f ;
611
619
Real damageRadius = 0 .0f ;
620
+ Real templateLaserRadius = 13 .0f ;
621
+ Real visualLaserRadius = 0 .0f ;
612
622
613
623
// 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 )
617
626
{
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
+ }
632
637
}
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
633
649
634
650
// Create scorch marks periodically
635
651
if ( m_nextScorchMarkFrame <= now )
@@ -988,13 +1004,15 @@ void ParticleUplinkCannonUpdate::createOrbitToTargetLaser( UnsignedInt growthFra
988
1004
{
989
1005
const ParticleUplinkCannonUpdateModuleData *data = getParticleUplinkCannonUpdateModuleData ();
990
1006
991
- Drawable *beam = TheGameClient->findDrawableByID ( m_orbitToTargetBeamID );
992
- if ( beam )
1007
+ if ( m_orbitToTargetBeamID != INVALID_DRAWABLE_ID )
993
1008
{
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
+ }
996
1015
m_orbitToTargetBeamID = INVALID_DRAWABLE_ID;
997
- m_orbitToTargetLaserRadius = LaserRadiusUpdate ();
998
1016
}
999
1017
1000
1018
if ( data->m_particleBeamLaserName .isNotEmpty () )
@@ -1014,7 +1032,6 @@ void ParticleUplinkCannonUpdate::createOrbitToTargetLaser( UnsignedInt growthFra
1014
1032
orbitPosition.set ( &m_initialTargetPosition );
1015
1033
orbitPosition.z += 500 .0f ;
1016
1034
update->initLaser ( NULL , NULL , &orbitPosition, &m_initialTargetPosition, " " , growthFrames );
1017
- m_orbitToTargetLaserRadius.initRadius ( growthFrames );
1018
1035
}
1019
1036
}
1020
1037
}
@@ -1025,6 +1042,9 @@ void ParticleUplinkCannonUpdate::createOrbitToTargetLaser( UnsignedInt growthFra
1025
1042
m_annihilationSound.setPlayingHandle ( TheAudio->addAudioEvent ( &m_annihilationSound ) );
1026
1043
}
1027
1044
}
1045
+
1046
+ m_orbitToTargetLaserRadius = LaserRadiusUpdate ();
1047
+ m_orbitToTargetLaserRadius.initRadius ( growthFrames );
1028
1048
}
1029
1049
1030
1050
// -------------------------------------------------------------------------------------------------
0 commit comments