Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Core/GameEngine/Include/GameClient/ParticleSys.h
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,10 @@ class ParticleSystemTemplate : public MemoryPoolObject, protected ParticleSystem
{
MEMORY_POOL_GLUE_WITH_USERLOOKUP_CREATE( ParticleSystemTemplate, "ParticleSystemTemplatePool" )

#if PRESERVE_RETAIL_PARTICLES
friend INI;
#endif

public:
ParticleSystemTemplate( const AsciiString &name );

Expand Down Expand Up @@ -606,7 +610,7 @@ class ParticleSystem : public MemoryPoolObject,
Bool isUsingDrawables() { return (m_particleType == DRAWABLE) ? true : false; }
Bool isUsingStreak() { return (m_particleType == STREAK) ? true : false; }
Bool isUsingSmudge() { return (m_particleType == SMUDGE) ? true : false; }
UnsignedInt getVolumeParticleDepth() { return ( m_particleType == VOLUME_PARTICLE ) ? OPTIMUM_VOLUME_PARTICLE_DEPTH : 0; }
UnsignedInt getVolumeParticleDepth() { return ( m_particleType == VOLUME_PARTICLE ) ? m_volumeParticleDepth : DEFAULT_VOLUME_PARTICLE_DEPTH; }
Comment thread
xezon marked this conversation as resolved.

Bool shouldBillboard() { return !m_isGroundAligned; }

Expand Down
15 changes: 15 additions & 0 deletions Core/GameEngine/Source/Common/INI/INIParticleSys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,19 @@ void INI::parseParticleSystemDefinition( INI* ini )

// parse the ini definition
ini->initFromINI( sysTemplate, sysTemplate->getFieldParse() );

#if PRESERVE_RETAIL_PARTICLES
// TheSuperHackers @info Hack to allow isUsingSmudge() functionality with retail smudge particles
// The retail data template for smudge particles is not correctly configured with the smudge particle type
if (sysTemplate->m_particleType != ParticleSystemInfo::SMUDGE && sysTemplate->m_particleTypeName.startsWithNoCase("SMUDGE."))
{
sysTemplate->m_particleType = ParticleSystemInfo::SMUDGE;
}

// In retail, volume particle depth was not setup through ini and was hard coded to a particle depth of 6
if (sysTemplate->m_particleType == ParticleSystemInfo::VOLUME_PARTICLE && sysTemplate->m_volumeParticleDepth == DEFAULT_VOLUME_PARTICLE_DEPTH)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This means if someone now sets VolParticleDepth to 0 in the INI explicitly, then it overwrites it here. That does not seem right. Perhaps it should only set it if the INI field was not set. Or is 0 an invalid setting for Volume particles?

@Mauller Mauller Aug 22, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Zero and One are invalid settings anyway.

There are tests in the render code for the volume depth being greater than One.

The value is also initialised to zero in the template.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the particle depth is set to zero or one, then the volume particle just gets rendered as a standard particle in this instance.

void PointGroupClass::RenderVolumeParticle(RenderInfoClass &rinfo, unsigned int depth )
{

	if ( depth <= 1 ) //oops,wrong number
	{
		Render( rinfo );
		return;
	}

Which kind of voids the point of it being a volume particle. But seems more like a safety net.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When looking further into the RenderVolumeParticle code the reciprocal of the depth is take which would cause a divide by zero error if 0 was a valid depth. Not sure why One is not considered though from the quick glance i took.

@xezon xezon Aug 23, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about do

#define INVALID_VOLUME_PARTICLE_DEPTH ( 0 )
#define DEFAULT_VOLUME_PARTICLE_DEPTH ( 1 ) // The Default is not to do the volume thing!
#define OPTIMUM_VOLUME_PARTICLE_DEPTH ( 6 )

Then initialize particle template depth with invalid, and then depending on the particle type parsed from ini, choose 1 or 6, regardless of retail.

@Mauller Mauller Aug 23, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well the problem is that we only consider getting as far as the rendering if the volume is 2 or higher anyway.

That's where i added the MIN_VOLUME_PARTICLE_DEPTH ( 2 ) in the particle batching PR since that is what the retail code tests in doParticles to determine if it handles a volume particle.

So even set to 1 the volume particle is never rendered. Even if it the rendering code has a failsafe to render as a regular particle.

The workaround was always more about catching the non configured particles from retail.

For non retail and mod's the particle editor should always put a minimum of 2 as the particle depth if a volume particle is selected. Otherwise it should be considered misconfigured and not render etc.

This is more just a hack to keep retail particles working that lack the configuration essentially while opening up the particle depth option for mods and future etc.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dont quite follow.

The proposed flow is to initialize with invalid, and then set 1 or 6 depending on the type wehn invalid. This way it always works the same way reliably and needs to retail guarding.

{
sysTemplate->m_volumeParticleDepth = OPTIMUM_VOLUME_PARTICLE_DEPTH;
}
#endif
}
14 changes: 4 additions & 10 deletions Core/GameEngine/Source/GameClient/System/ParticleSys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1095,7 +1095,7 @@ ParticleSystem::ParticleSystem( const ParticleSystemTemplate *sysTemplate,


///@todo: further formalize this parameter with an UnsignedInt field in the editor
m_volumeParticleDepth = DEFAULT_VOLUME_PARTICLE_DEPTH;
m_volumeParticleDepth = sysTemplate->m_volumeParticleDepth;


m_driftVelocity = sysTemplate->m_driftVelocity;
Expand Down Expand Up @@ -1190,15 +1190,6 @@ ParticleSystem::ParticleSystem( const ParticleSystemTemplate *sysTemplate,
m_particleType = sysTemplate->m_particleType;
m_particleTypeName = sysTemplate->m_particleTypeName;

#if PRESERVE_RETAIL_PARTICLES
// TheSuperHackers @info Hack to allow isUsingSmudge() functionality with retail smudge particles
// The retail data template for smudge particles is not correctly configured with the smudge particle type
if (m_particleType != ParticleType::SMUDGE && m_particleTypeName.startsWithNoCase("SMUDGE."))
{
m_particleType = ParticleType::SMUDGE;
}
#endif

m_isStopped = false;

// set up slave particle system, if any
Expand Down Expand Up @@ -2698,6 +2689,9 @@ const FieldParse ParticleSystemTemplate::m_fieldParseTable[] =
{ "SizeRate", INI::parseGameClientRandomVariable, nullptr, offsetof( ParticleSystemTemplate, m_sizeRate ) },
{ "SizeRateDamping", INI::parseGameClientRandomVariable, nullptr, offsetof( ParticleSystemTemplate, m_sizeRateDamping ) },

// TheSuperHackers @feature Volume particle depth is now exposed for configuration
{ "VolParticleDepth", INI::parseUnsignedInt, nullptr, offsetof(ParticleSystemTemplate, m_volumeParticleDepth) },

{ "Alpha1", ParticleSystemTemplate::parseRandomKeyframe, nullptr, offsetof( ParticleSystemTemplate, m_alphaKey[0] ) },
{ "Alpha2", ParticleSystemTemplate::parseRandomKeyframe, nullptr, offsetof( ParticleSystemTemplate, m_alphaKey[1] ) },
{ "Alpha3", ParticleSystemTemplate::parseRandomKeyframe, nullptr, offsetof( ParticleSystemTemplate, m_alphaKey[2] ) },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9725,6 +9725,7 @@ static const std::string F_SIZE = "Size";
static const std::string F_STARTSIZERATE ="StartSizeRate";
static const std::string F_SIZERATE = "SizeRate";
static const std::string F_SIZERATEDAMP = "SizeRateDamping";
static const std::string F_VOLPARTICLEDEPTH = "VolParticleDepth";

static const std::string F_ALPHA1 = "Alpha1";
static const std::string F_ALPHA2 = "Alpha2";
Expand Down Expand Up @@ -9887,6 +9888,9 @@ void _writeSingleParticleSystem( File *out, ParticleSystemTemplate *templ )
sprintf(buff2, FORMAT_STRING, templ->m_sizeRateDamping.getMaximumValue());
thisEntry.append(SEP_HEAD).append(F_SIZERATEDAMP).append(EQ_WITH_SPACES).append(buff1).append(SEP_SPACE).append(buff2).append(SEP_EOL);

sprintf(buff1, "%d", templ->m_volumeParticleDepth);
thisEntry.append(SEP_HEAD).append(F_VOLPARTICLEDEPTH).append(EQ_WITH_SPACES).append(buff1).append(SEP_EOL);

sprintf(buff1, FORMAT_STRING, templ->m_alphaKey[0].var.getMinimumValue());
sprintf(buff2, FORMAT_STRING, templ->m_alphaKey[0].var.getMaximumValue());
sprintf(buff3, "%d", templ->m_alphaKey[0].frame);
Expand Down
Loading