void CTEParticleRenderer::SimulateParticles( CParticleSimulateIterator *pIterator ) { StandardParticle_t *pParticle = (StandardParticle_t*)pIterator->GetFirst(); while ( pParticle ) { // Remove the particle? SetParticleLifetime(pParticle, GetParticleLifetime(pParticle) - pIterator->GetTimeDelta()); if(GetParticleLifetime(pParticle) < 0) { pIterator->RemoveParticle( pParticle ); } else { float ft = pIterator->GetTimeDelta(); float time3 = 15.0 * ft; float time2 = 10.0 * ft; float time1 = 5.0 * ft; float dvel = 4* ft ; float grav = ft * sv_gravity.GetFloat() * 0.05f; int (*colorIndex)[3]; int iRamp; switch(GetParticleType(pParticle)) { case pt_static: break; case pt_fire: pParticle->m_EffectDataWord += (unsigned short)(time1 * (1 << SIMSHIFT)); iRamp = pParticle->m_EffectDataWord >> SIMSHIFT; if(iRamp >= 6) { pParticle->m_Lifetime = -1; } else { colorIndex = &ramp3[ iRamp ]; pParticle->SetColor((float)(*colorIndex)[0] / 255.0f, (float)(*colorIndex)[1] / 255.0f, (float)(*colorIndex)[2] / 255.0f); } pParticle->m_Velocity[2] += grav; break; case pt_explode: pParticle->m_EffectDataWord += (unsigned short)(time2 * (1 << SIMSHIFT)); iRamp = pParticle->m_EffectDataWord >> SIMSHIFT; if(iRamp >= 8) { pParticle->m_Lifetime = -1; } else { colorIndex = &ramp1[ iRamp ]; pParticle->SetColor((float)(*colorIndex)[0] / 255.0f, (float)(*colorIndex)[1] / 255.0f, (float)(*colorIndex)[2] / 255.0f); } pParticle->m_Velocity = pParticle->m_Velocity + pParticle->m_Velocity * dvel; pParticle->m_Velocity[2] -= grav; break; case pt_explode2: pParticle->m_EffectDataWord += (unsigned short)(time3 * (1 << SIMSHIFT)); iRamp = pParticle->m_EffectDataWord >> SIMSHIFT; if(iRamp >= 8) { pParticle->m_Lifetime = -1; } else { colorIndex = &ramp2[ iRamp ]; pParticle->SetColor((float)(*colorIndex)[0] / 255.0f, (float)(*colorIndex)[1] / 255.0f, (float)(*colorIndex)[2] / 255.0f); } pParticle->m_Velocity = pParticle->m_Velocity - pParticle->m_Velocity * ft; pParticle->m_Velocity[2] -= grav; break; case pt_grav: pParticle->m_Velocity[2] -= grav * 20; break; case pt_slowgrav: pParticle->m_Velocity[2] = grav; break; case pt_vox_grav: pParticle->m_Velocity[2] -= grav * 8; break; case pt_vox_slowgrav: pParticle->m_Velocity[2] -= grav * 4; break; case pt_blob: case pt_blob2: pParticle->m_EffectDataWord += (unsigned short)(time2 * (1 << SIMSHIFT)); iRamp = pParticle->m_EffectDataWord >> SIMSHIFT; if(iRamp >= SPARK_COLORCOUNT) { pParticle->m_EffectDataWord = 0; iRamp = 0; } colorIndex = &gSparkRamp[ iRamp ]; pParticle->SetColor((float)(*colorIndex)[0] / 255.0f, (float)(*colorIndex)[1] / 255.0f, (float)(*colorIndex)[2] / 255.0f); pParticle->m_Velocity[0] -= pParticle->m_Velocity[0]*0.5*ft; pParticle->m_Velocity[1] -= pParticle->m_Velocity[1]*0.5*ft; pParticle->m_Velocity[2] -= grav * 5; if ( random->RandomInt(0,3) ) { SetParticleType(pParticle, pt_blob); pParticle->SetAlpha(0); } else { SetParticleType(pParticle, pt_blob2); pParticle->SetAlpha(255.9f); } break; } // Update position. pParticle->m_Pos = pParticle->m_Pos + pParticle->m_Velocity * ft; } pParticle = (StandardParticle_t*)pIterator->GetNext(); } }
void PartSysParser::ParseEmitter(const TabFileRecord& record) { auto systemName = record[COL_PARTSYS_NAME].AsString(); auto& system = mSpecs[tolower(systemName)]; // Create it on demand if (!system) { system = std::make_shared<PartSysSpec>(systemName); } // Add the emitter auto emitter = system->CreateEmitter(record[COL_EMITTER_NAME].AsString()); ParseOptionalFloat(record, COL_DELAY, "Delay", [&] (float value) { emitter->SetDelay(value / 30.0f); }); ParseLifespan(record, emitter); ParseParticleLifespan(record, emitter); ParseParticleRate(record, emitter); ParseOptionalEnum<PartSysEmitterSpace>(record, COL_EMITTER_SPACE, "emitter space", EmitterSpaceMapping, [&](auto space) { emitter->SetSpace(space); }); ParseEmitterNodeName(record, emitter); ParseOptionalEnum<PartSysCoordSys>(record, COL_EMITTER_COORD_SYS, "emitter coord sys", CoordSysMapping, [&](auto coordSys) { emitter->SetCoordSys(coordSys); }); ParseOptionalEnum<PartSysCoordSys>(record, COL_EMITTER_OFFSET_COORD_SYS, "emitter offset coord sys", CoordSysMapping, [&](auto coordSys) { emitter->SetOffsetCoordSys(coordSys); }); ParseOptionalEnum<PartSysParticleType>(record, COL_PARTICLE_TYPE, "particle type", ParticleTypeMapping, [&](PartSysParticleType type) { emitter->SetParticleType(type); }); ParseOptionalEnum<PartSysBlendMode>(record, COL_BLEND_MODE, "blend mode", BlendModeMapping, [&](auto mode) { emitter->SetBlendMode(mode); }); ParseMaterial(record, emitter); ParseOptionalEnum<PartSysCoordSys>(record, COL_PARTICLE_POS_COORD_SYS, "particle pos coord sys", CoordSysMapping, [&](auto coordSys) { emitter->SetParticlePosCoordSys(coordSys); }); ParseOptionalEnum<PartSysCoordSys>(record, COL_PARTICLE_VELOCITY_COORD_SYS, "particle velocity coord sys", CoordSysMapping, [&](auto coordSys) { emitter->SetParticleVelocityCoordSys(coordSys); }); ParseOptionalEnum<PartSysParticleSpace>(record, COL_PARTICLE_SPACE, "particle space", ParticleSpaceMapping, [&](auto space) { emitter->SetParticleSpace(space); }); ParseMesh(record, emitter); // Parse the bounding box ParseOptionalFloat(record, COL_BB_LEFT, "bb left", [&](float val) { emitter->SetBoxLeft(val); }); ParseOptionalFloat(record, COL_BB_TOP, "bb top", [&](float val) { emitter->SetBoxTop(val); }); ParseOptionalFloat(record, COL_BB_RIGHT, "bb right", [&](float val) { emitter->SetBoxRight(val); }); ParseOptionalFloat(record, COL_BB_BOTTOM, "bb bottom", [&](float val) { emitter->SetBoxBottom(val); }); for (int paramId = 0; paramId <= part_attractorBlend; paramId++) { int colIdx = 22 + paramId; auto col = record[colIdx]; if (col) { bool success; std::unique_ptr<PartSysParam> param(ParserParams::Parse((PartSysParamId) paramId, col, emitter->GetLifespan(), emitter->GetParticleLifespan(), success)); if (success) { emitter->SetParam((PartSysParamId)paramId, param); } else { logger->warn("Unable to parse particle system param {} for particle system {} and emitter {} with value {}", paramId, systemName, emitter->GetName(), col.AsString()); } } } }