void C_ParticleSmokeGrenade::Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs) { if(!pParticleMgr->AddEffect( &m_ParticleEffect, this )) return; m_SmokeTrail.Start(pParticleMgr, pArgs); m_SmokeTrail.m_ParticleLifetime = 0.5; m_SmokeTrail.SetSpawnRate(40); m_SmokeTrail.m_MinSpeed = 0; m_SmokeTrail.m_MaxSpeed = 0; m_SmokeTrail.m_StartSize = 3; m_SmokeTrail.m_EndSize = 10; m_SmokeTrail.m_SpawnRadius = 0; m_SmokeTrail.SetLocalOrigin( GetAbsOrigin() ); for(int i=0; i < NUM_MATERIAL_HANDLES; i++) { char str[256]; Q_snprintf(str, sizeof( str ), "particle/particle_smokegrenade%d", i+1); m_MaterialHandles[i] = m_ParticleEffect.FindOrAddMaterial(str); } if( m_CurrentStage == 2 ) { FillVolume(); } // Go straight into "fill volume" mode if they want. if(pArgs) { if(pArgs->FindArg("-FillVolume")) { FillVolume(); } } m_bStarted = true; SetNextClientThink( CLIENT_THINK_ALWAYS ); #if CSTRIKE_DLL C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer(); if ( pPlayer ) { pPlayer->m_SmokeGrenades.AddToTail( this ); } #endif }
void C_ParticleSmokeGrenade::Start(CParticleMgr *pParticleMgr, IPrototypeArgAccess *pArgs) { if(!pParticleMgr->AddEffect( &m_ParticleEffect, this )) return; m_LifetimeCounter = 0; m_SmokeTrail.Start(pParticleMgr, pArgs); m_SmokeTrail.m_ParticleLifetime = 0.5; m_SmokeTrail.SetSpawnRate(40); m_SmokeTrail.m_MinSpeed = 0; m_SmokeTrail.m_MaxSpeed = 0; m_SmokeTrail.m_StartSize = 3; m_SmokeTrail.m_EndSize = 10; m_SmokeTrail.m_SpawnRadius = 0; m_SmokeTrail.SetLocalOrigin( GetAbsOrigin() ); for(int i=0; i < NUM_MATERIAL_HANDLES; i++) { char str[256]; Q_snprintf(str, sizeof( str ), "particle/particle_smokegrenade%d", i+1); m_MaterialHandles[i] = m_ParticleEffect.FindOrAddMaterial(str); } if( m_CurrentStage == 2 ) { FillVolume(); } // Go straight into "fill volume" mode if they want. if(pArgs) { if(pArgs->FindArg("-FillVolume")) { FillVolume(); } } m_bStarted = true; }
void C_ParticleSmokeGrenade::UpdateSmokeTrail( float fTimeDelta ) { C_BaseEntity *pAimEnt = GetFollowedEntity(); if ( pAimEnt ) { Vector forward, right, up; // Update the smoke particle color. if(m_CurrentStage == 0) { m_SmokeTrail.m_StartColor = EngineGetLightForPoint(GetAbsOrigin()) * 0.5f; m_SmokeTrail.m_EndColor = m_SmokeTrail.m_StartColor; } // Spin the smoke trail. AngleVectors(pAimEnt->GetAbsAngles(), &forward, &right, &up); m_SmokeTrail.m_VelocityOffset = forward * 30 + GetAbsVelocity(); m_SmokeTrail.SetLocalOrigin( GetAbsOrigin() ); m_SmokeTrail.Update(fTimeDelta); } }
void C_ParticleSmokeGrenade::Update(float fTimeDelta) { m_LifetimeCounter += fTimeDelta; // Update the smoke trail. C_BaseEntity *pAimEnt = GetFollowedEntity(); if ( pAimEnt ) { Vector forward, right, up; // Update the smoke particle color. if(m_CurrentStage == 0) { m_SmokeTrail.m_StartColor = EngineGetLightForPoint(GetAbsOrigin()) * 0.5f; m_SmokeTrail.m_EndColor = m_SmokeTrail.m_StartColor; } // Spin the smoke trail. AngleVectors(pAimEnt->GetAbsAngles(), &forward, &right, &up); m_SmokeTrail.m_VelocityOffset = forward * 30 + GetAbsVelocity(); m_SmokeTrail.SetLocalOrigin( GetAbsOrigin() ); m_SmokeTrail.Update(fTimeDelta); } // Update our fade alpha. if(m_LifetimeCounter < m_FadeStartTime) { m_FadeAlpha = 1; } else if(m_LifetimeCounter < m_FadeEndTime) { float fadePercent = (m_LifetimeCounter - m_FadeStartTime) / (m_FadeEndTime - m_FadeStartTime); m_FadeAlpha = cos(fadePercent * 3.14159) * 0.5 + 0.5; } else { m_FadeAlpha = 0; } // Scale by the amount the sphere has grown. m_FadeAlpha *= m_ExpandRadius / SMOKESPHERE_MAX_RADIUS; if(m_CurrentStage == 1) { // Update the expanding sphere. m_ExpandTimeCounter += fTimeDelta; if(m_ExpandTimeCounter > SMOKESPHERE_EXPAND_TIME) m_ExpandTimeCounter = SMOKESPHERE_EXPAND_TIME; m_ExpandRadius = SMOKESPHERE_MAX_RADIUS * (float)sin(m_ExpandTimeCounter * 3.14159265358 * 0.5 / SMOKESPHERE_EXPAND_TIME); // Add our influence to the global smoke fog alpha. float testDist = (EngineGetVecRenderOrigin() - m_SmokeBasePos).Length(); float fadeEnd = m_ExpandRadius * 0.75; if(testDist < fadeEnd) { EngineGetSmokeFogOverlayAlpha() += 1 - testDist / fadeEnd; } // This is used to randomize the direction it chooses to move a particle in. int offsetLookup[3] = {-1,0,1}; // Update all the moving traders and establish new ones. int nTotal = m_xCount * m_yCount * m_zCount; for(int i=0; i < nTotal; i++) { SmokeParticleInfo *pInfo = &m_SmokeParticleInfos[i]; if(!pInfo->m_pParticle) continue; if(pInfo->m_TradeIndex == -1) { pInfo->m_pParticle->m_FadeAlpha = pInfo->m_FadeAlpha; pInfo->m_pParticle->m_Color[0] = pInfo->m_Color[0]; pInfo->m_pParticle->m_Color[1] = pInfo->m_Color[1]; pInfo->m_pParticle->m_Color[2] = pInfo->m_Color[2]; // Is there an adjacent one that's not trading? int x, y, z; GetParticleInfoXYZ(i, x, y, z); int xCountOffset = rand(); int yCountOffset = rand(); int zCountOffset = rand(); bool bFound = false; for(int xCount=0; xCount < 3 && !bFound; xCount++) { for(int yCount=0; yCount < 3 && !bFound; yCount++) { for(int zCount=0; zCount < 3; zCount++) { int testX = x + offsetLookup[(xCount+xCountOffset) % 3]; int testY = y + offsetLookup[(yCount+yCountOffset) % 3]; int testZ = z + offsetLookup[(zCount+zCountOffset) % 3]; if(testX == x && testY == y && testZ == z) continue; if(IsValidXYZCoords(testX, testY, testZ)) { SmokeParticleInfo *pOther = GetSmokeParticleInfo(testX, testY, testZ); if(pOther->m_pParticle && pOther->m_TradeIndex == -1) { // Ok, this one is looking to trade also. pInfo->m_TradeIndex = GetSmokeParticleIndex(testX, testY, testZ); pOther->m_TradeIndex = i; pInfo->m_TradeClock = pOther->m_TradeClock = 0; pInfo->m_TradeDuration = FRand(TRADE_DURATION_MIN, TRADE_DURATION_MAX); bFound = true; break; } } } } } } else { SmokeParticleInfo *pOther = &m_SmokeParticleInfos[pInfo->m_TradeIndex]; assert(pOther->m_TradeIndex == i); // This makes sure the trade only gets updated once per frame. if(pInfo < pOther) { // Increment the trade clock.. pInfo->m_TradeClock = (pOther->m_TradeClock += fTimeDelta); int x, y, z; GetParticleInfoXYZ(i, x, y, z); Vector myPos = GetSmokeParticlePos(x, y, z); int otherX, otherY, otherZ; GetParticleInfoXYZ(pInfo->m_TradeIndex, otherX, otherY, otherZ); Vector otherPos = GetSmokeParticlePos(otherX, otherY, otherZ); // Is the trade finished? if(pInfo->m_TradeClock >= pInfo->m_TradeDuration) { pInfo->m_TradeIndex = pOther->m_TradeIndex = -1; pInfo->m_pParticle->m_Pos = otherPos; pOther->m_pParticle->m_Pos = myPos; SmokeGrenadeParticle *temp = pInfo->m_pParticle; pInfo->m_pParticle = pOther->m_pParticle; pOther->m_pParticle = temp; } else { // Ok, move them closer. float percent = (float)cos(pInfo->m_TradeClock * 2 * 1.57079632f / pInfo->m_TradeDuration); percent = percent * 0.5 + 0.5; pInfo->m_pParticle->m_FadeAlpha = pInfo->m_FadeAlpha + (pOther->m_FadeAlpha - pInfo->m_FadeAlpha) * (1 - percent); pOther->m_pParticle->m_FadeAlpha = pInfo->m_FadeAlpha + (pOther->m_FadeAlpha - pInfo->m_FadeAlpha) * percent; InterpColor(pInfo->m_pParticle->m_Color, pInfo->m_Color, pOther->m_Color, 1-percent); InterpColor(pOther->m_pParticle->m_Color, pInfo->m_Color, pOther->m_Color, percent); pInfo->m_pParticle->m_Pos = myPos + (otherPos - myPos) * (1 - percent); pOther->m_pParticle->m_Pos = myPos + (otherPos - myPos) * percent; } } } } } }