Skip to content

tweak(particlesys): Cleanup volume particle depth handling and add INI field to control it - #3188

Merged
xezon merged 1 commit into
TheSuperHackers:mainfrom
Mauller:Mauller/chore-cleanup-vol-particle-depth-handling
Aug 26, 2026
Merged

tweak(particlesys): Cleanup volume particle depth handling and add INI field to control it#3188
xezon merged 1 commit into
TheSuperHackers:mainfrom
Mauller:Mauller/chore-cleanup-vol-particle-depth-handling

Conversation

@Mauller

@Mauller Mauller commented Aug 22, 2026

Copy link
Copy Markdown

This PR is a refactor to cleanup the handling of volume depth for volume type and normal particles.

The particle system class originally returned a hard coded value from getVolumeParticleDepth() instead of returning the variable m_volumeParticleDepth.

This value is now retrieved from the particle template and exposed to configuration through the ini field of VolParticleDepth.

To preserve the retail particle behaviour, we identify uninitialised volume particles and set their particle depth to the original hard coded value. Otherwise the configured by ini value will be used.

EDIT - For normal particles we now also initialise their depth to 1.

@Mauller Mauller self-assigned this Aug 22, 2026
@Mauller Mauller added Minor Severity: Minor < Major < Critical < Blocker Gen Relates to Generals ZH Relates to Zero Hour Refactor Edits the code with insignificant behavior changes, is never user facing labels Aug 22, 2026
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

ParticleSys: Make volume particle depth configurable while preserving retail defaults

🐞 Bug fix ⚙️ Configuration changes 🕐 10-20 Minutes

Grey Divider

AI Description

• Read volume particle depth from particle templates instead of using a hard-coded constant.
• Add INI support for configuring volume particle depth via "VolParticleDepth".
• Preserve retail behavior by defaulting legacy volume particles to the original depth.
Diagram

graph TD
  A[/"INI: VolParticleDepth"/] --> B["ParticleSystemTemplate"] --> C["ParticleSystem ctor"] --> D["m_volumeParticleDepth"] --> E["getVolumeParticleDepth()"] --> F["Volume particle render"]
  C --> G{"PRESERVE_RETAIL_PARTICLES && depth==DEFAULT?"} --> H["Force OPTIMUM depth (6)"] --> D
  subgraph Legend
    direction LR
    _in[/"INI field"/] ~~~ _proc["Runtime/template" ] ~~~ _dec{"Decision"}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Move retail defaulting into template initialization/parsing
  • ➕ Keeps runtime constructor logic simpler (no retail-specific override in ParticleSystem ctor).
  • ➕ Ensures any other users of the template value see the same retail default consistently.
  • ➖ May require careful ordering to know particle type/name at parse time.
  • ➖ Could be harder to reason about if parsing and compatibility logic become intertwined.
2. Use OPTIMUM as the default and treat explicit INI as override
  • ➕ Eliminates the special-case check for DEFAULT implying retail.
  • ➕ Simplifies behavior: depth is always sensible unless explicitly changed.
  • ➖ Risky if DEFAULT has meaning beyond volume particles elsewhere.
  • ➖ Could unintentionally change non-retail assets that relied on DEFAULT semantics.

Recommendation: Current approach is reasonable for a low-risk refactor: it makes depth configurable while explicitly guarding retail parity. If retail-compatibility logic grows, consider relocating the defaulting into template initialization/parsing to keep ParticleSystem construction focused on value transfer.

Files changed (2) +10 / -2

Bug fix (1) +1 / -1
ParticleSys.hUse configured volume particle depth in accessor +1/-1

Use configured volume particle depth in accessor

• Updates ParticleSystem::getVolumeParticleDepth() to return the instance member m_volumeParticleDepth for VOLUME_PARTICLE instead of a hard-coded constant. Non-volume particles continue to return the default depth value.

Core/GameEngine/Include/GameClient/ParticleSys.h

Other (1) +9 / -1
ParticleSys.cppWire volume depth from template/INI and preserve retail default +9/-1

Wire volume depth from template/INI and preserve retail default

• Initializes ParticleSystem::m_volumeParticleDepth from the template value rather than forcing the default. Adds a retail-compatibility fallback that restores the legacy OPTIMUM depth when no INI depth is configured, and introduces the new INI field parse entry "VolParticleDepth" to populate ParticleSystemTemplate::m_volumeParticleDepth.

Core/GameEngine/Source/GameClient/System/ParticleSys.cpp

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Vol depth 0 ignored 🐞 Bug ≡ Correctness
Description
When PRESERVE_RETAIL_PARTICLES is enabled, any VOLUME_PARTICLE with m_volumeParticleDepth equal to
DEFAULT_VOLUME_PARTICLE_DEPTH (0) is forcibly changed to OPTIMUM_VOLUME_PARTICLE_DEPTH (6), so an
INI value of VolParticleDepth=0 cannot be honored. This makes it impossible to explicitly configure
depth 0 for volume particles and can unintentionally enable expensive volume rendering when authors
expected depth 0 to disable it.
Code

Core/GameEngine/Source/GameClient/System/ParticleSys.cpp[R1201-1204]

+	// In retail, volume particle depth was not setup through ini and was hard coded to a particle depth of 6
+	if (m_particleType == ParticleType::VOLUME_PARTICLE && m_volumeParticleDepth == DEFAULT_VOLUME_PARTICLE_DEPTH)
+	{
+		m_volumeParticleDepth = OPTIMUM_VOLUME_PARTICLE_DEPTH;
Evidence
The PR’s new retail-compatibility block forces depth 0 to 6 for all volume particles, while the
codebase documents 0 as the default “disable volume” depth and the renderer only uses volume
rendering when depth > 1. Because INI parsing cannot distinguish “unset” from an explicit 0, the
override prevents intentionally configuring depth 0.

Core/GameEngine/Source/GameClient/System/ParticleSys.cpp[1193-1205]
Core/GameEngine/Include/GameClient/ParticleSys.h[60-62]
Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DParticleSys.cpp[328-334]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`VolParticleDepth` is parsed into `m_volumeParticleDepth` with a default of `DEFAULT_VOLUME_PARTICLE_DEPTH` (0). Under `PRESERVE_RETAIL_PARTICLES`, the constructor treats `m_volumeParticleDepth == 0` as “retail/unset” and overwrites it to 6, which also overwrites an explicit INI configuration of `VolParticleDepth=0`.

### Issue Context
- `DEFAULT_VOLUME_PARTICLE_DEPTH` is documented as “not to do the volume thing” (0).
- Volume rendering is only used when depth > 1.
- Current logic cannot tell whether depth==0 came from “field missing” or “field explicitly set to 0”.

### Fix Focus Areas
- Implement an explicit "was specified" signal (or sentinel value) for `VolParticleDepth`, and only apply the retail override when the field was not specified.
- file: Core/GameEngine/Source/GameClient/System/ParticleSys.cpp[2756-2760]
- file: Core/GameEngine/Source/GameClient/System/ParticleSys.cpp[1193-1205]
- file: Core/GameEngine/Include/GameClient/ParticleSys.h[60-63]

### Suggested approach
- Add a `bool m_volumeParticleDepthSpecified` (or similar) to `ParticleSystemTemplate` (or `ParticleSystemInfo` if appropriate).
- Replace the parse-table entry for `VolParticleDepth` with a custom parser that sets both `m_volumeParticleDepth` and `m_volumeParticleDepthSpecified=true`.
- Change the retail-compat block to:
 - if volume particle AND `!m_volumeParticleDepthSpecified` then set to `OPTIMUM_VOLUME_PARTICLE_DEPTH`.
 - otherwise honor the configured value, including 0.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can commit Qodo's fix in one click with committable suggestions (GitHub & GitLab)

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread Core/GameEngine/Source/GameClient/System/ParticleSys.cpp Outdated
Comment thread Core/GameEngine/Include/GameClient/ParticleSys.h Outdated
Comment thread Core/GameEngine/Source/GameClient/System/ParticleSys.cpp Outdated
Comment thread Core/GameEngine/Source/GameClient/System/ParticleSys.cpp Outdated
Comment thread Core/GameEngine/Source/GameClient/System/ParticleSys.cpp Outdated
@Mauller
Mauller force-pushed the Mauller/chore-cleanup-vol-particle-depth-handling branch from bbbc607 to a596261 Compare August 22, 2026 14:53
Comment thread Core/GameEngine/Source/Common/INI/INIParticleSys.cpp Outdated
@OmarAglan

Copy link
Copy Markdown

The overall direction looks good, but I think two issues should be addressed before merging:

  1. The retail fallback cannot distinguish an omitted VolParticleDepth from an explicitly configured value of 0. Depths 0 and 1 are handled safely by the rendering path by falling back to standard particle rendering, so 0 appears to be a meaningful way to disable volume rendering. It may be cleaner to default volume templates to OPTIMUM_VOLUME_PARTICLE_DEPTH and allow the INI value to override it, including with 0.

  2. VolParticleDepth is parsed, but the Generals and Zero Hour _writeSingleParticleSystem() implementations do not write it. Because the particle editor regenerates ParticleSystem.ini, saving the file would silently discard a configured depth.

Other than these configuration and round-trip concerns, the change looks clean and the CI results are good.

@Mauller
Mauller force-pushed the Mauller/chore-cleanup-vol-particle-depth-handling branch from a596261 to 291a2e3 Compare August 22, 2026 21:48
Comment thread GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp Outdated
Comment thread Core/GameEngine/Source/Common/INI/INIParticleSys.cpp Outdated
@Mauller
Mauller force-pushed the Mauller/chore-cleanup-vol-particle-depth-handling branch from 291a2e3 to 53eef90 Compare August 23, 2026 08:38
@Mauller

Mauller commented Aug 23, 2026

Copy link
Copy Markdown
Author

Here's a test showing different levels of volume particle depth.

One appears to not work very well in this instance if you let the volume particle code work. but this could also be down to placement of the particle emitter on the microwave tank. It looks like the particle is there but it pretty much renders billboard and flat, you can partly see the line of it across the top of the flat portion of the microwave emitter / turret.

Screenshots

This is as volume particle set to 1
image

This is letting it render as a normal particle in this instance using the escape code.
image

Two you can minimally start to see the particle effect
image

Three is significantly more noticeable
image

depth four
image

depth five
image

Retail depth of "Optimal" at 6
image

I am going to jump a bit for the next ones to every second level to 16 which is considered the max.

Depth 8
image

Depth 10
image

Depth 12
image

Going to jump to 16 here as i think people get the point
image

image

Brighter than the SUN! if only we had HDR for this we could blind people.

@Mauller
Mauller force-pushed the Mauller/chore-cleanup-vol-particle-depth-handling branch from 53eef90 to c32d92c Compare August 23, 2026 13:37
@Mauller

Mauller commented Aug 23, 2026

Copy link
Copy Markdown
Author

Fixed based on feedback and did a little more cleanup around it as well.

Comment thread Core/GameEngine/Include/GameClient/ParticleSys.h Outdated
Comment thread Core/GameEngine/Source/Common/INI/INIParticleSys.cpp Outdated
@Mauller
Mauller force-pushed the Mauller/chore-cleanup-vol-particle-depth-handling branch from c32d92c to ffa3dc6 Compare August 23, 2026 21:23
@Mauller

Mauller commented Aug 23, 2026

Copy link
Copy Markdown
Author

Updated with recent suggestions along with a little extra cleanup around the same area.

Comment thread Core/GameEngine/Include/GameClient/ParticleSys.h Outdated
Comment thread Core/GameEngine/Include/GameClient/ParticleSys.h Outdated
Comment thread Core/GameEngine/Include/GameClient/ParticleSys.h Outdated
@Mauller
Mauller force-pushed the Mauller/chore-cleanup-vol-particle-depth-handling branch from ffa3dc6 to 1034a5b Compare August 24, 2026 19:39
Comment thread Core/GameEngine/Include/GameClient/ParticleSys.h Outdated
@Mauller
Mauller force-pushed the Mauller/chore-cleanup-vol-particle-depth-handling branch from 1034a5b to 34eb57d Compare August 25, 2026 16:29
@Mauller
Mauller force-pushed the Mauller/chore-cleanup-vol-particle-depth-handling branch from 34eb57d to 7b77fd1 Compare August 26, 2026 16:05
@Mauller

Mauller commented Aug 26, 2026

Copy link
Copy Markdown
Author

Merged to generals, i didn't realise at first that one of the files was not in core.

Should be good to merge now.

@greptile-apps

greptile-apps Bot commented Aug 26, 2026

Copy link
Copy Markdown

Greptile Summary

The PR exposes volume-particle depth through particle INI definitions while preserving retail defaults and initializing normal-particle depth separately.

  • Adds parsing and serialization for VolParticleDepth.
  • Validates missing volume depth as 6 and normal-particle depth as 1.
  • Carries the validated template value into particle instances and selects volume rendering by particle type and depth.
  • Moves the retail smudge compatibility adjustment into template validation.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains; the previously reported configured-depth overwrite is fixed by preserving nonzero volume-particle depths in the dedicated volume branch.

Important Files Changed

Filename Overview
Core/GameEngine/Include/GameClient/ParticleSys.h Defines explicit depth constants and exposes the stored depth and volume-particle type through const accessors.
Core/GameEngine/Source/Common/INI/INIParticleSys.cpp Runs template validation after all particle-system INI fields have been parsed.
Core/GameEngine/Source/GameClient/System/ParticleSys.cpp Parses configurable depth, preserves configured volume values, applies retail and normal defaults, and copies the result into runtime particle systems.
Core/GameEngineDevice/Source/W3DDevice/GameClient/W3DParticleSys.cpp Selects volume rendering only for volume-particle systems whose validated depth exceeds the normal-render default.
Core/Libraries/Source/WWVegas/WW3D2/pointgr.cpp Names the normal-render depth threshold while retaining the renderer’s existing upper clamp.
Generals/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp Serializes particle depth into Generals particle-system INI output.
GeneralsMD/Code/GameEngine/Source/GameLogic/ScriptEngine/ScriptEngine.cpp Mirrors particle-depth serialization for the Zero Hour variant.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
    INI[Particle INI definition] --> Parse[Parse Type and VolParticleDepth]
    Parse --> Validate{Particle type}
    Validate -- Volume and depth 0 --> RetailDefault[Set depth to 6]
    Validate -- Volume and configured --> Preserve[Preserve configured depth]
    Validate -- Non-volume --> NormalDefault[Set depth to 1]
    RetailDefault --> Instance[Create ParticleSystem]
    Preserve --> Instance
    NormalDefault --> Instance
    Instance --> Gate{Volume type and depth above 1?}
    Gate -- Yes --> VolumeRender[RenderVolumeParticle]
    Gate -- No --> NormalRender[Render]
Loading

Reviews (2): Last reviewed commit: "refactor(particlesys): Cleanup retail vo..." | Re-trigger Greptile

Comment thread Core/GameEngine/Source/GameClient/System/ParticleSys.cpp
@Mauller
Mauller force-pushed the Mauller/chore-cleanup-vol-particle-depth-handling branch from 7b77fd1 to 99a9983 Compare August 26, 2026 17:56
@xezon xezon changed the title refactor(particlesys): Cleanup retail volume particle depth handling tweak(particlesys): Cleanup retail volume particle depth handling Aug 26, 2026
@xezon xezon added the Enhancement Is new feature or request label Aug 26, 2026
@xezon xezon changed the title tweak(particlesys): Cleanup retail volume particle depth handling tweak(particlesys): Cleanup retail volume particle depth handling and add INI field to control it Aug 26, 2026
@xezon xezon changed the title tweak(particlesys): Cleanup retail volume particle depth handling and add INI field to control it tweak(particlesys): Cleanup volume particle depth handling and add INI field to control it Aug 26, 2026
@xezon
xezon merged commit 45178ee into TheSuperHackers:main Aug 26, 2026
17 checks passed
@xezon
xezon deleted the Mauller/chore-cleanup-vol-particle-depth-handling branch August 26, 2026 18:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Enhancement Is new feature or request Gen Relates to Generals Minor Severity: Minor < Major < Critical < Blocker Refactor Edits the code with insignificant behavior changes, is never user facing ZH Relates to Zero Hour

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants