//====================================================================================================================== // PARTICLE SYSTEM STOP EFFECT //====================================================================================================================== //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void ParticleEffectStopCallback( const CEffectData &data ) { if ( data.m_hEntity.Get() ) { C_BaseEntity *pEnt = C_BaseEntity::Instance( data.m_hEntity ); if ( pEnt ) { if ( data.m_nHitBox > 0 ) { if ( pEnt->IsWorld() ) { if ( data.m_nHitBox > 0 ) { CNewParticleEffect::RemoveParticleEffect( data.m_nHitBox ); } } else { CParticleSystemDefinition *pDef = g_pParticleSystemMgr->FindPrecachedParticleSystem( data.m_nHitBox ); if ( pDef ) { pEnt->ParticleProp()->StopParticlesNamed( pDef->GetName(), true ); } } } else { pEnt->ParticleProp()->StopEmission(); } } } }
//====================================================================================================================== // PARTICLE SYSTEM DISPATCH EFFECT //====================================================================================================================== //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void ParticleEffectCallback( const CEffectData &data ) { if ( SuppressingParticleEffects() ) return; // this needs to be before using data.m_nHitBox, since that may be a serialized value that's past the end of the current particle system string table const char *pszName = GetParticleSystemNameFromIndex( data.m_nHitBox ); if ( data.m_fFlags & PARTICLE_DISPATCH_FROM_ENTITY ) { if ( data.m_hEntity.Get() ) { C_BaseEntity *pEnt = C_BaseEntity::Instance( data.m_hEntity ); if ( pEnt && !pEnt->IsDormant() ) { if ( data.m_fFlags & PARTICLE_DISPATCH_RESET_PARTICLES ) { pEnt->ParticleProp()->StopEmission(); } CSmartPtr<CNewParticleEffect> pEffect = pEnt->ParticleProp()->Create( pszName, (ParticleAttachment_t)data.m_nDamageType, data.m_nAttachmentIndex ); AssertMsg2( pEffect.IsValid() && pEffect->IsValid(), "%s could not create particle effect %s", C_BaseEntity::Instance( data.m_hEntity )->GetDebugName(), pszName ); if ( pEffect.IsValid() && pEffect->IsValid() ) { if ( (ParticleAttachment_t)data.m_nDamageType == PATTACH_CUSTOMORIGIN ) { pEffect->SetSortOrigin( data.m_vOrigin ); pEffect->SetControlPoint( 0, data.m_vOrigin ); pEffect->SetControlPoint( 1, data.m_vStart ); Vector vecForward, vecRight, vecUp; AngleVectors( data.m_vAngles, &vecForward, &vecRight, &vecUp ); pEffect->SetControlPointOrientation( 0, vecForward, vecRight, vecUp ); } } } } } else { CSmartPtr<CNewParticleEffect> pEffect = CNewParticleEffect::Create( NULL, pszName ); if ( pEffect->IsValid() ) { pEffect->SetSortOrigin( data.m_vOrigin ); pEffect->SetControlPoint( 0, data.m_vOrigin ); pEffect->SetControlPoint( 1, data.m_vStart ); Vector vecForward, vecRight, vecUp; AngleVectors( data.m_vAngles, &vecForward, &vecRight, &vecUp ); pEffect->SetControlPointOrientation( 0, vecForward, vecRight, vecUp ); } } }
//====================================================================================================================== // PARTICLE SYSTEM STOP EFFECT //====================================================================================================================== //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void ParticleEffectStopCallback( const CEffectData &data ) { if ( data.m_hEntity.Get() ) { C_BaseEntity *pEnt = C_BaseEntity::Instance( data.m_hEntity ); if ( pEnt ) { pEnt->ParticleProp()->StopEmission(); } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFMinigun::StopMuzzleEffect() { C_BaseEntity *pEffectOwner = GetWeaponForEffect(); if ( !pEffectOwner ) return; // Stop the muzzle flash. if ( m_pMuzzleEffect ) { pEffectOwner->ParticleProp()->StopEmission( m_pMuzzleEffect ); m_pMuzzleEffect = NULL; } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFMinigun::StopBrassEffect() { C_BaseEntity *pEffectOwner = GetWeaponForEffect(); if ( !pEffectOwner ) return; // Stop the brass ejection. if ( m_pEjectBrassEffect ) { pEffectOwner->ParticleProp()->StopEmission( m_pEjectBrassEffect ); m_pEjectBrassEffect = NULL; } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFFlameThrower::RestartParticleEffect( void ) { CTFPlayer *pOwner = ToTFPlayer( GetPlayerOwner() ); if ( !pOwner ) return; if ( m_pFlameEffect && m_hFlameEffectHost.Get() ) { m_hFlameEffectHost->ParticleProp()->StopEmission( m_pFlameEffect ); } m_iParticleWaterLevel = pOwner->GetWaterLevel(); int iTeam = pOwner->GetTeamNumber(); // Start the appropriate particle effect const char *pszParticleEffect; if ( pOwner->GetWaterLevel() == WL_Eyes ) { pszParticleEffect = "flamethrower_underwater"; } else { if ( m_bCritFire ) { pszParticleEffect = ConstructTeamParticle( "flamethrower_crit_%s", iTeam, true ); } else { pszParticleEffect = iTeam == TF_TEAM_RED ? "flamethrower" : ConstructTeamParticle( "flamethrower_%s", pOwner->GetTeamNumber(), true ); } } // Start the effect on the viewmodel if our owner is the local player C_BaseEntity *pModel = GetWeaponForEffect(); if ( pModel ) { m_pFlameEffect = pModel->ParticleProp()->Create( pszParticleEffect, PATTACH_POINT_FOLLOW, "muzzle" ); m_hFlameEffectHost = pModel; } pOwner->m_Shared.SetParticleToMercColor( m_pFlameEffect ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFMinigun::StartMuzzleEffect() { C_BaseEntity *pEffectOwner = GetWeaponForEffect(); if ( !pEffectOwner ) return; // Try and setup the attachment point if it doesn't already exist. // This caching will mess up if we go third person from first - we only do this in taunts and don't fire so we should // be okay for now. if ( m_iMuzzleAttachment == -1 ) { m_iMuzzleAttachment = pEffectOwner->LookupAttachment( "muzzle" ); } // Start the muzzle flash, if a system hasn't already been started. if ( m_iMuzzleAttachment != -1 && m_pMuzzleEffect == NULL ) { m_pMuzzleEffect = pEffectOwner->ParticleProp()->Create( "muzzle_minigun_constant", PATTACH_POINT_FOLLOW, m_iMuzzleAttachment ); } }
//====================================================================================================================== // PARTICLE SYSTEM DISPATCH EFFECT //====================================================================================================================== //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void StartParticleEffect( const CEffectData &data, int nSplitScreenPlayerSlot /*= -1*/ ) { // this needs to be before using data.m_nHitBox, // since that may be a serialized value that's past the end of the current particle system string table if ( SuppressingParticleEffects() ) return; // Don't crash if we're passed an invalid particle system if ( data.m_nHitBox == 0 ) return; if ( data.m_fFlags & PARTICLE_DISPATCH_FROM_ENTITY ) { if ( data.m_hEntity.Get() ) { C_BaseEntity *pEnt = C_BaseEntity::Instance( data.m_hEntity ); // commented out assert. dormant entities have their particle system spawns stopped. //Assert( pEnt && !pEnt->IsDormant() ); if ( pEnt && !pEnt->IsDormant() ) { if ( data.m_fFlags & PARTICLE_DISPATCH_RESET_PARTICLES ) { pEnt->ParticleProp()->StopEmission(); } CUtlReference<CNewParticleEffect> pEffect = pEnt->ParticleProp()->CreatePrecached( data.m_nHitBox, (ParticleAttachment_t)data.m_nDamageType, data.m_nAttachmentIndex ); if ( pEffect.IsValid() && pEffect->IsValid() ) { if ( (ParticleAttachment_t)data.m_nDamageType == PATTACH_CUSTOMORIGIN || (ParticleAttachment_t)data.m_nDamageType == PATTACH_CUSTOMORIGIN_FOLLOW ) { pEffect->SetDrawOnlyForSplitScreenUser( nSplitScreenPlayerSlot ); pEffect->SetSortOrigin( data.m_vOrigin ); if ( (ParticleAttachment_t)data.m_nDamageType == PATTACH_CUSTOMORIGIN_FOLLOW ) { Vector vecCtrl1 = (data.m_vStart - pEnt->GetAbsOrigin() ); pEffect->SetControlPoint( 1, vecCtrl1 ); pEffect->SetControlPointEntity( 1, pEnt ); Vector vecCtrl0 = (data.m_vOrigin - pEnt->GetAbsOrigin() ); matrix3x4_t mat; AngleMatrix( data.m_vAngles, mat ); pEnt->ParticleProp()->AddControlPoint( pEffect, 0, pEnt, PATTACH_CUSTOMORIGIN_FOLLOW, NULL, vecCtrl0, &mat ); } else { pEffect->SetControlPoint( 0, data.m_vOrigin ); pEffect->SetControlPoint( 1, data.m_vStart ); Vector vecForward, vecRight, vecUp; AngleVectors( data.m_vAngles, &vecForward, &vecRight, &vecUp ); pEffect->SetControlPointOrientation( 0, vecForward, vecRight, vecUp ); } } else if ( data.m_nOtherEntIndex > 0 ) { C_BaseEntity *pOtherEnt = ClientEntityList().GetEnt( data.m_nOtherEntIndex ); if ( pOtherEnt ) { pEnt->ParticleProp()->AddControlPoint( pEffect, 1, pOtherEnt, PATTACH_ABSORIGIN_FOLLOW, NULL, Vector( 0, 0, 50 ) ); } } } } } } else { CParticleSystemDefinition *pDef = g_pParticleSystemMgr->FindPrecachedParticleSystem( data.m_nHitBox ); if ( pDef ) { CUtlReference<CNewParticleEffect> pEffect = CNewParticleEffect::CreateOrAggregate( NULL, pDef, data.m_vOrigin, NULL, nSplitScreenPlayerSlot ); if ( pEffect.IsValid() && pEffect->IsValid() ) { pEffect->SetSortOrigin( data.m_vOrigin ); pEffect->SetControlPoint( 0, data.m_vOrigin ); pEffect->SetControlPoint( 1, data.m_vStart ); Vector vecForward, vecRight, vecUp; AngleVectors( data.m_vAngles, &vecForward, &vecRight, &vecUp ); pEffect->SetControlPointOrientation( 0, vecForward, vecRight, vecUp ); } } else { Warning( "StartParticleEffect: Failed to find precached particle system for %d!!\n", data.m_nHitBox ); } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponMedigun::ManageChargeEffect( void ) { C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); C_BaseEntity *pEffectOwner = this; if ( pLocalPlayer == NULL ) return; if ( pLocalPlayer == GetTFPlayerOwner() ) { pEffectOwner = pLocalPlayer->GetViewModel(); if ( !pEffectOwner ) return; } bool bOwnerTaunting = false; if ( GetTFPlayerOwner() && GetTFPlayerOwner()->m_Shared.InCond( TF_COND_TAUNTING ) == true ) { bOwnerTaunting = true; } if ( GetTFPlayerOwner() && bOwnerTaunting == false && m_bHolstered == false && ( m_flChargeLevel >= 1.0f || m_bChargeRelease == true ) ) { if ( m_pChargeEffect == NULL ) { char *pszEffectName = NULL; switch( GetTFPlayerOwner()->GetTeamNumber() ) { case TF_TEAM_BLUE: pszEffectName = "medicgun_invulnstatus_fullcharge_blue"; break; case TF_TEAM_RED: pszEffectName = "medicgun_invulnstatus_fullcharge_red"; break; case TF_TEAM_GREEN: pszEffectName = "medicgun_invulnstatus_fullcharge_green"; break; case TF_TEAM_YELLOW: pszEffectName = "medicgun_invulnstatus_fullcharge_yellow"; break; default: pszEffectName = ""; break; } m_pChargeEffect = pEffectOwner->ParticleProp()->Create( pszEffectName, PATTACH_POINT_FOLLOW, "muzzle" ); } if ( m_pChargedSound == NULL ) { CLocalPlayerFilter filter; CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); m_pChargedSound = controller.SoundCreate( filter, entindex(), "WeaponMedigun.Charged" ); controller.Play( m_pChargedSound, 1.0, 100 ); } } else { if ( m_pChargeEffect != NULL ) { pEffectOwner->ParticleProp()->StopEmission( m_pChargeEffect ); m_pChargeEffect = NULL; } if ( m_pChargedSound != NULL ) { CSoundEnvelopeController::GetController().SoundDestroy( m_pChargedSound ); m_pChargedSound = NULL; } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CWeaponMedigun::UpdateEffects( void ) { CTFPlayer *pFiringPlayer = ToTFPlayer( GetOwnerEntity() ); if ( !pFiringPlayer ) return; C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer(); C_BaseEntity *pEffectOwner = this; if ( pLocalPlayer == pFiringPlayer ) { pEffectOwner = pLocalPlayer->GetViewModel(); if ( !pEffectOwner ) return; } // Remove all the effects if ( pEffectOwner ) { pEffectOwner->ParticleProp()->StopEmission( m_hHealingTargetEffect.pEffect ); } else { m_hHealingTargetEffect.pEffect->StopEmission(); } m_hHealingTargetEffect.pTarget = NULL; m_hHealingTargetEffect.pEffect = NULL; // Don't add targets if the medic is dead if ( !pEffectOwner || pFiringPlayer->IsPlayerDead() || !pFiringPlayer->IsPlayerClass( TF_CLASS_MEDIC ) ) return; // Add our targets // Loops through the healing targets, and make sure we have an effect for each of them if ( m_hHealingTarget ) { if ( m_hHealingTargetEffect.pTarget == m_hHealingTarget ) return; const char *pszEffectName; if (m_bChargeRelease) { switch (GetTeamNumber()) { case TF_TEAM_BLUE: pszEffectName = "medicgun_beam_blue_invun"; break; case TF_TEAM_RED: pszEffectName = "medicgun_beam_red_invun"; break; case TF_TEAM_GREEN: pszEffectName = "medicgun_beam_green_invun"; break; case TF_TEAM_YELLOW: pszEffectName = "medicgun_beam_yellow_invun"; break; default: pszEffectName = "medicgun_beam_blue"; break; } } else { switch (GetTeamNumber()) { case TF_TEAM_BLUE: pszEffectName = "medicgun_beam_blue"; break; case TF_TEAM_RED: pszEffectName = "medicgun_beam_red"; break; case TF_TEAM_GREEN: pszEffectName = "medicgun_beam_green"; break; case TF_TEAM_YELLOW: pszEffectName = "medicgun_beam_yellow"; break; default: pszEffectName = "medicgun_beam_blue"; break; } } CNewParticleEffect *pEffect = pEffectOwner->ParticleProp()->Create( pszEffectName, PATTACH_POINT_FOLLOW, "muzzle" ); pEffectOwner->ParticleProp()->AddControlPoint( pEffect, 1, m_hHealingTarget, PATTACH_ABSORIGIN_FOLLOW, NULL, Vector(0,0,50) ); m_hHealingTargetEffect.pTarget = m_hHealingTarget; m_hHealingTargetEffect.pEffect = pEffect; } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void C_EntityDissolve::ClientThink( void ) { C_BaseEntity *pEnt = GetMoveParent(); if ( !pEnt ) return; bool bIsRagdoll; #ifdef TF_CLIENT_DLL bIsRagdoll = true; #else C_BaseAnimating *pAnimating = GetMoveParent() ? GetMoveParent()->GetBaseAnimating() : NULL; if (!pAnimating) return; bIsRagdoll = pAnimating->IsRagdoll(); #endif // NOTE: IsRagdoll means *client-side* ragdoll. We shouldn't be trying to fight // the server ragdoll (or any server physics) on the client if (( !m_pController ) && ( m_nDissolveType == ENTITY_DISSOLVE_NORMAL ) && bIsRagdoll ) { IPhysicsObject *ppList[VPHYSICS_MAX_OBJECT_LIST_COUNT]; int nCount = pEnt->VPhysicsGetObjectList( ppList, ARRAYSIZE(ppList) ); if ( nCount > 0 ) { m_pController = physenv->CreateMotionController( this ); for ( int i = 0; i < nCount; ++i ) { m_pController->AttachObject( ppList[i], true ); } } } color32 color; color.r = ( 1.0f - GetFadeInPercentage() ) * m_vEffectColor.x; color.g = ( 1.0f - GetFadeInPercentage() ) * m_vEffectColor.y; color.b = ( 1.0f - GetFadeInPercentage() ) * m_vEffectColor.z; color.a = GetModelFadeOutPercentage() * 255.0f; // Setup the entity fade pEnt->SetRenderMode( kRenderTransColor ); pEnt->SetRenderColor( color.r, color.g, color.b, color.a ); if ( GetModelFadeOutPercentage() <= 0.2f ) { m_bCoreExplode = true; } // If we're dead, fade out if ( GetFadeOutPercentage() <= 0.0f ) { // Do NOT remove from the client entity list. It'll confuse the local network backdoor, and the entity will never get destroyed // because when the server says to destroy it, the client won't be able to find it. // ClientEntityList().RemoveEntity( GetClientHandle() ); partition->Remove( PARTITION_CLIENT_SOLID_EDICTS | PARTITION_CLIENT_RESPONSIVE_EDICTS | PARTITION_CLIENT_NON_STATIC_EDICTS, CollisionProp()->GetPartitionHandle() ); RemoveFromLeafSystem(); //FIXME: Ick! //Adrian: I'll assume we don't need the ragdoll either so I'll remove that too. if ( m_bLinkedToServerEnt == false ) { Release(); C_ClientRagdoll *pRagdoll = dynamic_cast <C_ClientRagdoll *> ( pEnt ); if ( pRagdoll ) { pRagdoll->ReleaseRagdoll(); } #ifdef TF_CLIENT_DLL else { // Hide the ragdoll -- don't actually delete it or else things get unhappy when // we get a message from the server telling us to delete it pEnt->AddEffects( EF_NODRAW ); pEnt->ParticleProp()->StopEmission(); } #endif } } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CTFFlameThrower::StartFlame() { if ( m_iWeaponState == FT_STATE_AIRBLASTING ) { C_BaseEntity *pModel = GetWeaponForEffect(); if ( pModel ) { pModel->ParticleProp()->Create( "pyro_blast", PATTACH_POINT_FOLLOW, "muzzle" ); } //CLocalPlayerFilter filter; //EmitSound( filter, entindex(), "Weapon_FlameThrower.AirBurstAttack" ); } else { CSoundEnvelopeController &controller = CSoundEnvelopeController::GetController(); // normally, crossfade between start sound & firing loop in 3.5 sec float flCrossfadeTime = 3.5; if ( m_pFiringLoop && ( m_bCritFire != m_bFiringLoopCritical ) ) { // If we're firing and changing between critical & noncritical, just need to change the firing loop. // Set crossfade time to zero so we skip the start sound and go to the loop immediately. flCrossfadeTime = 0; StopFlame( true ); } StopPilotLight(); if ( !m_pFiringStartSound && !m_pFiringLoop ) { RestartParticleEffect(); CLocalPlayerFilter filter; // Play the fire start sound const char *shootsound = GetShootSound( SINGLE ); if ( flCrossfadeTime > 0.0 ) { // play the firing start sound and fade it out m_pFiringStartSound = controller.SoundCreate( filter, entindex(), shootsound ); controller.Play( m_pFiringStartSound, 1.0, 100 ); controller.SoundChangeVolume( m_pFiringStartSound, 0.0, flCrossfadeTime ); } // Start the fire sound loop and fade it in if ( m_bCritFire ) { shootsound = GetShootSound( BURST ); } else { shootsound = GetShootSound( SPECIAL1 ); } m_pFiringLoop = controller.SoundCreate( filter, entindex(), shootsound ); m_bFiringLoopCritical = m_bCritFire; // play the firing loop sound and fade it in if ( flCrossfadeTime > 0.0 ) { controller.Play( m_pFiringLoop, 0.0, 100 ); controller.SoundChangeVolume( m_pFiringLoop, 1.0, flCrossfadeTime ); } else { controller.Play( m_pFiringLoop, 1.0, 100 ); } } if( m_bHitTarget != m_bOldHitTarget ) { if ( m_bHitTarget ) { CLocalPlayerFilter filter; m_pHitTargetSound = controller.SoundCreate( filter, entindex(), "Weapon_FlameThrower.FireHit" ); controller.Play( m_pHitTargetSound, 1.0f, 100.0f ); } else if ( m_pHitTargetSound ) { controller.SoundDestroy( m_pHitTargetSound ); m_pHitTargetSound = NULL; } m_bOldHitTarget = m_bHitTarget; } } }