|
1 | 1 | /* |
2 | | -** Command & Conquer Generals(tm) |
| 2 | +** Command & Conquer Generals Zero Hour(tm) |
3 | 3 | ** Copyright 2025 Electronic Arts Inc. |
4 | 4 | ** |
5 | 5 | ** This program is free software: you can redistribute it and/or modify |
@@ -61,6 +61,10 @@ enum ParticleSystemID CPP_11(: Int) |
61 | 61 | #define DEFAULT_VOLUME_PARTICLE_DEPTH ( 0 )//The Default is not to do the volume thing! |
62 | 62 | #define OPTIMUM_VOLUME_PARTICLE_DEPTH ( 6 ) |
63 | 63 |
|
| 64 | +// TheSuperHackers @info The X and Y angles are not necessary for particles because there are only 2 placement modes: |
| 65 | +// Billboard (always facing camera) and Ground Aligned, which overwrite any rotations on the X and Y axis by design. |
| 66 | +// Therefore particles can only be rotated on the Z axis. Zero Hour never had X and Y angles, but Generals did. |
| 67 | +#define PARTICLE_USE_XY_ROTATION (0) |
64 | 68 |
|
65 | 69 | //-------------------------------------------------------------------------------------------------------------- |
66 | 70 |
|
@@ -122,11 +126,15 @@ class ParticleInfo : public Snapshot |
122 | 126 | Coord3D m_emitterPos; ///< position of the emitter |
123 | 127 | Real m_velDamping; ///< velocity damping coefficient |
124 | 128 |
|
| 129 | +#if PARTICLE_USE_XY_ROTATION |
125 | 130 | Real m_angleX; ///< initial angle around X axis |
126 | 131 | Real m_angleY; ///< initial angle around Y axis |
| 132 | +#endif |
127 | 133 | Real m_angleZ; ///< initial angle around Z axis |
| 134 | +#if PARTICLE_USE_XY_ROTATION |
128 | 135 | Real m_angularRateX; ///< initial angle around X axis |
129 | 136 | Real m_angularRateY; ///< initial angle around Y axis |
| 137 | +#endif |
130 | 138 | Real m_angularRateZ; ///< initial angle around Z axis |
131 | 139 | Real m_angularDamping; ///< angular velocity damping coefficient |
132 | 140 |
|
@@ -174,7 +182,6 @@ class Particle : public MemoryPoolObject, |
174 | 182 | void doWindMotion( void ); ///< do wind motion (if present) from particle system |
175 | 183 |
|
176 | 184 | void applyForce( const Coord3D *force ); ///< add the given acceleration |
177 | | - void detachDrawable( void ) { m_drawable = nullptr; } ///< detach the Drawable pointer from this particle |
178 | 185 |
|
179 | 186 | const Coord3D *getPosition( void ) { return &m_pos; } |
180 | 187 | Real getSize( void ) { return m_size; } |
@@ -231,7 +238,6 @@ class Particle : public MemoryPoolObject, |
231 | 238 | RGBColor m_colorRate; ///< current rate of color change |
232 | 239 | Int m_colorTargetKey; ///< next index into key array |
233 | 240 |
|
234 | | - Drawable * m_drawable; ///< drawable associated with this particle |
235 | 241 |
|
236 | 242 | Bool m_isCulled; ///< status of particle relative to screen bounds |
237 | 243 | public: |
@@ -273,18 +279,22 @@ class ParticleSystemInfo : public Snapshot |
273 | 279 |
|
274 | 280 | enum ParticleType |
275 | 281 | { |
276 | | - INVALID_TYPE=0, PARTICLE, DRAWABLE, STREAK, VOLUME_PARTICLE, ///< is a particle a 2D-screen-facing particle, or a Drawable, or a Segment in a streak? |
| 282 | + INVALID_TYPE=0, PARTICLE, DRAWABLE, STREAK, VOLUME_PARTICLE, SMUDGE, ///< is a particle a 2D-screen-facing particle, or a Drawable, or a Segment in a streak? |
277 | 283 | PARTICLE_TYPE_COUNT |
278 | 284 | } |
279 | 285 | m_particleType; |
280 | 286 |
|
281 | 287 | AsciiString m_particleTypeName; ///< if PARTICLE, texture filename, if DRAWABLE, Drawable name |
282 | 288 |
|
| 289 | +#if PARTICLE_USE_XY_ROTATION |
283 | 290 | GameClientRandomVariable m_angleX; ///< initial angle around X axis |
284 | 291 | GameClientRandomVariable m_angleY; ///< initial angle around Y axis |
| 292 | +#endif |
285 | 293 | GameClientRandomVariable m_angleZ; ///< initial angle around Z axis |
| 294 | +#if PARTICLE_USE_XY_ROTATION |
286 | 295 | GameClientRandomVariable m_angularRateX; ///< initial angle around X axis |
287 | 296 | GameClientRandomVariable m_angularRateY; ///< initial angle around Y axis |
| 297 | +#endif |
288 | 298 | GameClientRandomVariable m_angularRateZ; ///< initial angle around Z axis |
289 | 299 | GameClientRandomVariable m_angularDamping; ///< angular velocity damping coefficient |
290 | 300 |
|
@@ -461,7 +471,7 @@ static_assert(ARRAY_SIZE(ParticleShaderTypeNames) == ParticleSystemInfo::PARTICL |
461 | 471 |
|
462 | 472 | static const char *const ParticleTypeNames[] = |
463 | 473 | { |
464 | | - "NONE", "PARTICLE", "DRAWABLE", "STREAK", "VOLUME_PARTICLE", nullptr |
| 474 | + "NONE", "PARTICLE", "DRAWABLE", "STREAK", "VOLUME_PARTICLE", "SMUDGE", nullptr |
465 | 475 | }; |
466 | 476 | static_assert(ARRAY_SIZE(ParticleTypeNames) == ParticleSystemInfo::PARTICLE_TYPE_COUNT + 1, "Incorrect array size"); |
467 | 477 |
|
@@ -559,6 +569,7 @@ class ParticleSystem : public MemoryPoolObject, |
559 | 569 | void rotateLocalTransformX( Real x ); ///< rotate local transform matrix |
560 | 570 | void rotateLocalTransformY( Real y ); ///< rotate local transform matrix |
561 | 571 | void rotateLocalTransformZ( Real z ); ///< rotate local transform matrix |
| 572 | + void setSkipParentXfrm(Bool enable) { m_skipParentXfrm = enable; } ///<disable transforming particle system with parent matrix. |
562 | 573 |
|
563 | 574 | const Coord3D *getDriftVelocity( void ) { return &m_driftVelocity; } ///< get the drift velocity of the system |
564 | 575 |
|
@@ -594,6 +605,7 @@ class ParticleSystem : public MemoryPoolObject, |
594 | 605 | AsciiString getParticleTypeName( void ) { return m_particleTypeName; } ///< return the name of the particles |
595 | 606 | Bool isUsingDrawables( void ) { return (m_particleType == DRAWABLE) ? true : false; } |
596 | 607 | Bool isUsingStreak( void ) { return (m_particleType == STREAK) ? true : false; } |
| 608 | + Bool isUsingSmudge( void ) { return (m_particleType == SMUDGE) ? true : false; } |
597 | 609 | UnsignedInt getVolumeParticleDepth( void ) { return ( m_particleType == VOLUME_PARTICLE ) ? OPTIMUM_VOLUME_PARTICLE_DEPTH : 0; } |
598 | 610 |
|
599 | 611 | Bool shouldBillboard( void ) { return !m_isGroundAligned; } |
@@ -711,6 +723,7 @@ class ParticleSystem : public MemoryPoolObject, |
711 | 723 | Bool m_isDestroyed; ///< are we destroyed and waiting for particles to die |
712 | 724 | Bool m_isFirstPos; ///< true if this system hasn't been drawn before. |
713 | 725 | Bool m_isSaveable; ///< true if this system should be saved/loaded |
| 726 | + Bool m_skipParentXfrm; ///< true if this system is already in world space. |
714 | 727 |
|
715 | 728 |
|
716 | 729 | // the actual particle system data is inherited from ParticleSystemInfo |
|
0 commit comments