-
Notifications
You must be signed in to change notification settings - Fork 0
fix(particlesys): Decouple creation of particle systems from game logic #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -253,7 +253,7 @@ void TransitionDamageFX::onDelete() | |
| /** Given an FXLoc info struct, return the effect position that we are supposed to use. | ||
| * The position is local to to the object */ | ||
| //------------------------------------------------------------------------------------------------- | ||
| static Coord3D getLocalEffectPos( const FXLocInfo *locInfo, Drawable *draw ) | ||
| static Coord3D getLocalEffectPos( const FXLocInfo *locInfo, Drawable *draw, Bool useGameLogicRandom = TRUE) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we do this more elegantly? I do not have better idea but it is a bit sad to have this as argument. |
||
| { | ||
|
|
||
| DEBUG_ASSERTCRASH( locInfo, ("getLocalEffectPos: locInfo is null") ); | ||
|
|
@@ -290,7 +290,7 @@ static Coord3D getLocalEffectPos( const FXLocInfo *locInfo, Drawable *draw ) | |
| return locInfo->loc; | ||
|
|
||
| // pick one of the bone positions | ||
| Int pick = GameLogicRandomValue( 0, boneCount - 1 ); | ||
| Int pick = useGameLogicRandom ? GameLogicRandomValue( 0, boneCount - 1 ) : GameClientRandomValue( 0, boneCount - 1 ); | ||
| return positions[ pick ]; | ||
|
|
||
| } | ||
|
|
@@ -387,14 +387,12 @@ void TransitionDamageFX::onBodyDamageStateChange( const DamageInfo* damageInfo, | |
| if( lastDamageInfo == nullptr || | ||
| getDamageTypeFlag( modData->m_damageParticleTypes, lastDamageInfo->in.m_damageType ) ) | ||
| { | ||
|
|
||
| // create a new particle system based on the template provided | ||
| ParticleSystem* pSystem = TheParticleSystemManager->createParticleSystem( pSystemT ); | ||
| if( pSystem ) | ||
| { | ||
|
|
||
| // get the what is the position we're going to played the effect at | ||
| pos = getLocalEffectPos( &modData->m_particleSystem[ newState ][ i ].locInfo, draw ); | ||
| pos = getLocalEffectPos( &modData->m_particleSystem[ newState ][ i ].locInfo, draw, FALSE); | ||
|
|
||
| // | ||
| // set position on system given any bone position provided, the bone position is | ||
|
|
@@ -409,13 +407,25 @@ void TransitionDamageFX::onBodyDamageStateChange( const DamageInfo* damageInfo, | |
|
|
||
| // save the id of this particle system so we can remove it later if it still exists | ||
| m_particleSystemID[ newState ][ i ] = pSystem->getSystemID(); | ||
|
|
||
| } | ||
|
|
||
| } | ||
|
|
||
| } | ||
|
|
||
| #ifdef RETAIL_COMPATIBLE_CRC | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Otherwise I think it won't work if it's defined as
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good catch |
||
| // TheSuperHackers @fix stephanmeesters 18/05/2026 Fix issue where the creation of a certain particle system | ||
| // would influence game logic CRC due to the incorrect usage of game logic RNG. This code block is required to | ||
| // forward the game logic RNG and keep things consistent. | ||
| if(pSystemT) // todo: add || TheParticleSystemManager->isDummy() | ||
| { | ||
| if( lastDamageInfo == nullptr || | ||
| getDamageTypeFlag( modData->m_damageParticleTypes, lastDamageInfo->in.m_damageType ) ) | ||
| { | ||
| static_cast<void>(getLocalEffectPos(&modData->m_particleSystem[newState][i].locInfo, draw)); | ||
| } | ||
| } | ||
| #endif | ||
|
|
||
| } | ||
|
|
||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -304,14 +304,12 @@ void EMPUpdate::doDisableAttack() | |
|
|
||
| for (UnsignedInt e = 0 ; e < emitterCount; ++e) | ||
| { | ||
|
|
||
| ParticleSystem *sys = TheParticleSystemManager->createParticleSystem(tmp); | ||
|
|
||
| if (sys) | ||
| { | ||
| Coord3D offs = {0,0,0}; | ||
| curVictim->getGeometryInfo().makeRandomOffsetWithinFootprint( offs ); | ||
| offs.z = GameLogicRandomValue(3, victimHeight); | ||
| curVictim->getGeometryInfo().makeGameClientRandomOffsetWithinFootprint( offs ); | ||
| offs.z = GameClientRandomValue(3, victimHeight); | ||
|
|
||
| //This puts all the sparks within a quadrahemicycloid (rectangular dome) volume | ||
| //The same shape as a four cornered camping dome tent, for those with less Greek | ||
|
|
@@ -328,12 +326,31 @@ void EMPUpdate::doDisableAttack() | |
| sys->attachToObject(curVictim); | ||
| sys->setPosition( &offs ); | ||
| sys->setSystemLifetime(MAX(0, data->m_disabledDuration - 30)); | ||
| sys->setInitialDelay(GameLogicRandomValue(1,100)); | ||
| sys->setInitialDelay(GameClientRandomValue(1,100)); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| #ifdef RETAIL_COMPATIBLE_CRC | ||
| // TheSuperHackers @fix stephanmeesters 18/05/2026 Fix issue where the creation of a certain particle system | ||
| // would influence game logic CRC due to the incorrect usage of game logic RNG. This code block is required to | ||
| // forward the game logic RNG and keep things consistent. | ||
| if(tmp) // todo: add || TheParticleSystemManager->isDummy() | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I dont think
Owner
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| { | ||
| Real victimHeight = curVictim->getGeometryInfo().getMaxHeightAbovePosition(); | ||
| Real victimFootprintArea = curVictim->getGeometryInfo().getFootprintArea(); | ||
| Real victimVolume = victimFootprintArea * MIN(victimHeight, 10.0f); | ||
| UnsignedInt emitterCount = MAX(15, REAL_TO_INT_CEIL(data->m_sparksPerCubicFoot * victimVolume)); | ||
| for (UnsignedInt e = 0 ; e < emitterCount; ++e) | ||
| { | ||
| Coord3D offs = { 0,0,0 }; | ||
| curVictim->getGeometryInfo().makeGameLogicRandomOffsetWithinFootprint(offs); | ||
| static_cast<void>(GameLogicRandomValue(0, 1)); | ||
| static_cast<void>(GameLogicRandomValue(0, 1)); | ||
| } | ||
| } | ||
| #endif | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1404,13 +1404,23 @@ void SpecialAbilityUpdate::triggerAbilityEffect() | |
| if (sys) | ||
| { | ||
| Coord3D offs = {0,0,0}; | ||
| target->getGeometryInfo().makeRandomOffsetWithinFootprint( offs ); | ||
| target->getGeometryInfo().makeGameClientRandomOffsetWithinFootprint( offs ); | ||
|
|
||
| sys->attachToObject(target); | ||
| sys->setPosition( &offs ); | ||
| sys->setSystemLifetime( data->m_effectDuration * durationInterleaveFactor ); //lifetime of the system, not the particles | ||
| } | ||
|
|
||
| #ifdef RETAIL_COMPATIBLE_CRC | ||
| // TheSuperHackers @fix stephanmeesters 18/05/2026 Fix issue where the creation of a certain particle system | ||
| // would influence game logic CRC due to the incorrect usage of game logic RNG. This code block is required to | ||
| // forward the game logic RNG and keep things consistent. | ||
| if(sys) // todo: add || TheParticleSystemManager->isDummy() | ||
| { | ||
| Coord3D offs = { 0,0,0 }; | ||
| target->getGeometryInfo().makeGameLogicRandomOffsetWithinFootprint(offs); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Or just unroll the relevant calls to |
||
| } | ||
| #endif | ||
| } | ||
| } | ||
| break; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can avoid making a duplicate function by passing a function pointer for
GameClientRandomValueRealorGameLogicRandomValueReal. Same for the other function.