From 28cf5fe276ccc61087da9d1800b9c5738094af6f Mon Sep 17 00:00:00 2001 From: jerrrrycho Date: Thu, 15 Oct 2026 22:26:13 +0200 Subject: [PATCH] fix(gfx): a vehicle taken off the tracks stops smoking (#90) The smoke sources of a vehicle stay in the particle manager when the vehicle is taken off the tracks: one gone through a portal, or a road vehicle waiting in the pool of its spawn point. They kept spawning particles where the vehicle had vanished, for good. A source of a disabled vehicle spawns no more particles now, the ones it let out fade away as usual, and a pooled road vehicle puffs again once it's back on the road. Checked on td.scn with a portal added at the dead end of tdo_n585 and an SM42 driven into it by the AI: on master its smoke source kept about 100 particles where it vanished for the rest of the run (over 200 s); with the fix they were gone within a second. --- rendering/particles.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/rendering/particles.cpp b/rendering/particles.cpp index 5f7158e0..6719eb6d 100644 --- a/rendering/particles.cpp +++ b/rendering/particles.cpp @@ -162,8 +162,15 @@ smoke_source::update( double const Timedelta, bool const Onlydespawn ) { glm::dvec3{ std::numeric_limits::max() }, glm::dvec3{ std::numeric_limits::lowest() } }; + // a vehicle taken off the tracks (gone through a portal, or waiting in the pool of the road traffic) puffs no more, + // the particles it already let out fade away as usual + auto const nospawn { + false == Global.Smoke + || true == Onlydespawn + || ( m_ownertype == owner_type::vehicle && false == m_owner.vehicle->bEnabled ) }; + m_spawncount = ( - ( ( false == Global.Smoke ) || ( true == Onlydespawn ) ) ? + ( true == nospawn ) ? 0.f : std::min( static_cast(m_spawncount + ( m_spawnrate * Timedelta * Global.SmokeFidelity )), @@ -179,7 +186,7 @@ smoke_source::update( double const Timedelta, bool const Onlydespawn ) { if (m_owner.vehicle->MoverParameters->dizel_spinup == true) { m_spawncount = - ((false == Global.Smoke) || (true == Onlydespawn)) ? + (true == nospawn) ? 0.f : std::min( // m_spawncount + ( m_spawnrate * Timedelta * Global.SmokeFidelity ), @@ -191,7 +198,7 @@ smoke_source::update( double const Timedelta, bool const Onlydespawn ) { m_owner.vehicle->MoverParameters->Im == 0) { m_spawncount = - ((false == Global.Smoke) || (true == Onlydespawn)) ? + (true == nospawn) ? 0.f : std::min( // m_spawncount + ( m_spawnrate * Timedelta * Global.SmokeFidelity ), @@ -201,7 +208,7 @@ smoke_source::update( double const Timedelta, bool const Onlydespawn ) { { m_spawncount = - ((false == Global.Smoke) || (true == Onlydespawn)) ? + (true == nospawn) ? 0.f : std::min( // m_spawncount + ( m_spawnrate * Timedelta * Global.SmokeFidelity ),