From a663e1d32d6c815d8c9269f28164091aa1285957 Mon Sep 17 00:00:00 2001 From: Birk Magnussen <6238428+BMagnu@users.noreply.github.com> Date: Sat, 6 Jun 2026 19:48:57 +0900 Subject: [PATCH] Add particles on death of particles --- code/particle/ParticleEffect.cpp | 2 ++ code/particle/ParticleEffect.h | 1 + code/particle/ParticleParse.cpp | 20 ++++++++++++++++++++ code/particle/particle.cpp | 29 +++++++++++++++++++++++++++-- 4 files changed, 50 insertions(+), 2 deletions(-) diff --git a/code/particle/ParticleEffect.cpp b/code/particle/ParticleEffect.cpp index 7a69bd42e59..105ab2fed70 100644 --- a/code/particle/ParticleEffect.cpp +++ b/code/particle/ParticleEffect.cpp @@ -49,6 +49,7 @@ ParticleEffect::ParticleEffect(SCP_string name) m_manual_velocity_offset(std::nullopt), m_light_source(std::nullopt), m_particleTrail(ParticleEffectHandle::invalid()), + m_deathEffect(ParticleEffectHandle::invalid()), m_particleChance(1.f), m_distanceCulled(-1.f) {} @@ -119,6 +120,7 @@ ParticleEffect::ParticleEffect(SCP_string name, m_manual_velocity_offset(velocityOffsetLocal), m_light_source(std::nullopt), m_particleTrail(particleTrail), + m_deathEffect(ParticleEffectHandle::invalid()), m_particleChance(particleChance), m_distanceCulled(distanceCulled) {} diff --git a/code/particle/ParticleEffect.h b/code/particle/ParticleEffect.h index 35708d813fd..7ec25b9b256 100644 --- a/code/particle/ParticleEffect.h +++ b/code/particle/ParticleEffect.h @@ -182,6 +182,7 @@ class ParticleEffect { std::optional m_light_source; ParticleEffectHandle m_particleTrail; + ParticleEffectHandle m_deathEffect; float m_particleChance; //Deprecated. Use particle num random ranges instead. float m_distanceCulled; //Kinda deprecated. Only used by the oldest of legacy effects. diff --git a/code/particle/ParticleParse.cpp b/code/particle/ParticleParse.cpp index 3a619e30451..40e47134c2f 100644 --- a/code/particle/ParticleParse.cpp +++ b/code/particle/ParticleParse.cpp @@ -374,6 +374,25 @@ namespace particle { } } + static void parseModernDeathEffect(ParticleEffect& effect, bool top_layer) { + if (optional_string("$Death Effect:")) { + SCP_string name; + stuff_string(name, F_NAME); + + effect.m_deathEffect = ParticleManager::get()->getEffectByName(name); + } + else if (top_layer && optional_string("$Death Inline Effect:")) { + SCP_string name; + stuff_string(name, F_NAME); + + SCP_vector death {constructModernEffect(name, false)}; + while (optional_string("$Continue Death Effect:")) + death.emplace_back(constructModernEffect(name)); + + effect.m_deathEffect = ParticleManager::get()->addEffect(std::move(death)); + } + } + static ParticleEffect constructModernEffect(const SCP_string& name, bool top_layer = true) { ParticleEffect effect(name); @@ -408,6 +427,7 @@ namespace particle { parseModularCurvesSource(effect); parseModernTrail(effect, top_layer); + parseModernDeathEffect(effect, top_layer); return effect; } diff --git a/code/particle/particle.cpp b/code/particle/particle.cpp index 7b1744bcf99..b3a783cbea3 100644 --- a/code/particle/particle.cpp +++ b/code/particle/particle.cpp @@ -13,6 +13,7 @@ #include "particle/particle.h" #include "particle/ParticleManager.h" #include "particle/ParticleEffect.h" +#include "particle/hosts/EffectHostVector.h" #include "debugconsole/console.h" #include "globalincs/systemvars.h" #include "graphics/2d.h" @@ -250,13 +251,37 @@ namespace particle } } + const auto& source_effect = part->parent_effect.getParticleEffect(); + if (remove_particle) { + if (source_effect.m_deathEffect.isValid()) { + vec3d world_pos = part->pos; + vec3d world_vel = part->velocity; + + // Convert from local to world space if attached to a valid parent + if (part->attached_objnum >= 0 && + part->attached_objnum < MAX_OBJECTS && + part->attached_sig == Objects[part->attached_objnum].signature) { + vec3d local_vel = part->velocity; + vm_vec_unrotate(&world_pos, &world_pos, &Objects[part->attached_objnum].orient); + vm_vec_add2(&world_pos, &Objects[part->attached_objnum].pos); + vm_vec_unrotate(&world_vel, &local_vel, &Objects[part->attached_objnum].orient); + } + + matrix orient = vmd_identity_matrix; + if (vm_vec_mag_squared(&world_vel) > 0.0f) { + vm_vector_2_matrix(&orient, &world_vel); + } + + auto deathSource = ParticleManager::get()->createSource(source_effect.m_deathEffect); + deathSource->setHost(std::make_unique(world_pos, orient, world_vel)); + deathSource->finishCreation(); + } + return true; } - const auto& source_effect = part->parent_effect.getParticleEffect(); - float part_velocity = vm_vec_mag_quick(&part->velocity); float vel_scalar = source_effect.m_lifetime_curves.get_output(ParticleEffect::ParticleLifetimeCurvesOutput::VELOCITY_MULT, std::forward_as_tuple(*part, part_velocity) );