//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void DispatchParticleEffect( const char *pszParticleName, ParticleAttachment_t iAttachType, CBaseEntity *pEntity, const char *pszAttachmentName, Vector vecColor1, Vector vecColor2, bool bUseColors, bool bResetAllParticlesOnEntity ) { int iAttachment = -1; if ( pEntity && pEntity->GetBaseAnimating() ) { // Find the attachment point index iAttachment = pEntity->GetBaseAnimating()->LookupAttachment( pszAttachmentName ); if ( iAttachment <= 0 ) { Warning("Model '%s' doesn't have attachment '%s' to attach particle system '%s' to.\n", STRING(pEntity->GetBaseAnimating()->GetModelName()), pszAttachmentName, pszParticleName ); return; } } CEffectData data; data.m_nHitBox = GetParticleSystemIndex( pszParticleName ); if ( pEntity ) { #ifdef CLIENT_DLL data.m_hEntity = pEntity; #else data.m_nEntIndex = pEntity->entindex(); #endif data.m_fFlags |= PARTICLE_DISPATCH_FROM_ENTITY; data.m_vOrigin = pEntity->GetAbsOrigin(); } data.m_nDamageType = iAttachType; data.m_nAttachmentIndex = iAttachment; if ( bResetAllParticlesOnEntity ) { data.m_fFlags |= PARTICLE_DISPATCH_RESET_PARTICLES; } if ( bUseColors ) { data.m_bCustomColors = true; data.m_CustomColors.m_vecColor1 = vecColor1; data.m_CustomColors.m_vecColor2 = vecColor2; } #ifdef GAME_DLL if ( ( data.m_fFlags & PARTICLE_DISPATCH_FROM_ENTITY ) != 0 && ( iAttachType == PATTACH_ABSORIGIN_FOLLOW || iAttachType == PATTACH_POINT_FOLLOW || iAttachType == PATTACH_ROOTBONE_FOLLOW ) ) { CReliableBroadcastRecipientFilter filter; DispatchEffect( "ParticleEffect", data, filter ); } else #endif { DispatchEffect( "ParticleEffect", data ); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CParticleSystem::Activate( void ) { BaseClass::Activate(); // Find our particle effect index m_iEffectIndex = GetParticleSystemIndex( STRING(m_iszEffectName) ); if ( m_bStartActive ) { m_bStartActive = false; StartParticleSystem(); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void TE_TFParticleEffect( IRecipientFilter &filter, float flDelay, const char *pszParticleName, Vector vecOrigin, QAngle vecAngles, CBaseEntity *pEntity /*= NULL*/, int iAttachType /*= PATTACH_CUSTOMORIGIN*/ ) { g_TETFParticleEffect.Init(); g_TETFParticleEffect.m_iParticleSystemIndex = GetParticleSystemIndex( pszParticleName ); VectorCopy( vecOrigin, g_TETFParticleEffect.m_vecOrigin ); VectorCopy( vecAngles, g_TETFParticleEffect.m_vecAngles ); if ( pEntity ) { g_TETFParticleEffect.m_nEntIndex = pEntity->entindex(); g_TETFParticleEffect.m_iAttachType = iAttachType; } // Send it over the wire g_TETFParticleEffect.Create( filter, flDelay ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void TE_TFParticleEffect( IRecipientFilter &filter, float flDelay, const char *pszParticleName, ParticleAttachment_t iAttachType, CBaseEntity *pEntity, int iAttachmentPoint, bool bResetAllParticlesOnEntity ) { g_TETFParticleEffect.Init(); g_TETFParticleEffect.m_iParticleSystemIndex = GetParticleSystemIndex( pszParticleName ); if ( pEntity ) { g_TETFParticleEffect.m_nEntIndex = pEntity->entindex(); } g_TETFParticleEffect.m_iAttachType = iAttachType; g_TETFParticleEffect.m_iAttachmentPointIndex = iAttachmentPoint; if ( bResetAllParticlesOnEntity ) { g_TETFParticleEffect.m_bResetParticles = true; } // Send it over the wire g_TETFParticleEffect.Create( filter, flDelay ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void DispatchParticleEffect( const char *pszParticleName, Vector vecOrigin, QAngle vecAngles, Vector vecColor1, Vector vecColor2, bool bUseColors, CBaseEntity *pEntity, int iAttachType ) { int iEffectIndex = GetParticleSystemIndex( pszParticleName ); CEffectData data; data.m_nHitBox = iEffectIndex; data.m_vOrigin = vecOrigin; data.m_vAngles = vecAngles; if ( pEntity ) { #ifdef CLIENT_DLL data.m_hEntity = pEntity; #else data.m_nEntIndex = pEntity->entindex(); #endif data.m_fFlags |= PARTICLE_DISPATCH_FROM_ENTITY; data.m_nDamageType = PATTACH_CUSTOMORIGIN; } else { #ifdef CLIENT_DLL data.m_hEntity = NULL; #else data.m_nEntIndex = 0; #endif } if ( bUseColors ) { data.m_bCustomColors = true; data.m_CustomColors.m_vecColor1 = vecColor1; data.m_CustomColors.m_vecColor2 = vecColor2; } DispatchEffect( "ParticleEffect", data ); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void DispatchParticleEffect( const char *pszParticleName, ParticleAttachment_t iAttachType, CBaseEntity *pEntity, int iAttachmentPoint, bool bResetAllParticlesOnEntity ) { CEffectData data; data.m_nHitBox = GetParticleSystemIndex( pszParticleName ); if ( pEntity ) { #ifdef CLIENT_DLL data.m_hEntity = pEntity; #else data.m_nEntIndex = pEntity->entindex(); #endif data.m_fFlags |= PARTICLE_DISPATCH_FROM_ENTITY; data.m_vOrigin = pEntity->GetAbsOrigin(); } data.m_nDamageType = iAttachType; data.m_nAttachmentIndex = iAttachmentPoint; if ( bResetAllParticlesOnEntity ) { data.m_fFlags |= PARTICLE_DISPATCH_RESET_PARTICLES; } #ifdef GAME_DLL if ( ( data.m_fFlags & PARTICLE_DISPATCH_FROM_ENTITY ) != 0 && ( iAttachType == PATTACH_ABSORIGIN_FOLLOW || iAttachType == PATTACH_POINT_FOLLOW || iAttachType == PATTACH_ROOTBONE_FOLLOW ) ) { CBroadcastRecipientFilter filter; DispatchEffect( "ParticleEffect", data, filter ); } else #endif { DispatchEffect( "ParticleEffect", data ); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void DispatchParticleEffect( const char *pszParticleName, ParticleAttachment_t iAttachType, CBaseEntity *pEntity, int iAttachmentPoint, bool bResetAllParticlesOnEntity ) { CEffectData data; data.m_nHitBox = GetParticleSystemIndex( pszParticleName ); if ( pEntity ) { #ifdef CLIENT_DLL data.m_hEntity = pEntity; #else data.m_nEntIndex = pEntity->entindex(); #endif data.m_fFlags |= PARTICLE_DISPATCH_FROM_ENTITY; } data.m_nDamageType = iAttachType; data.m_nAttachmentIndex = iAttachmentPoint; if ( bResetAllParticlesOnEntity ) { data.m_fFlags |= PARTICLE_DISPATCH_RESET_PARTICLES; } DispatchEffect( "ParticleEffect", data ); }
//----------------------------------------------------------------------------- // Purpose: Make a tracer using a particle effect //----------------------------------------------------------------------------- void UTIL_ParticleTracer( const char *pszTracerEffectName, const Vector &vecStart, const Vector &vecEnd, int iEntIndex, int iAttachment, bool bWhiz ) { int iParticleIndex = GetParticleSystemIndex( pszTracerEffectName ); UTIL_Tracer( vecStart, vecEnd, iEntIndex, iAttachment, 0, bWhiz, "ParticleTracer", iParticleIndex ); }
//----------------------------------------------------------------------------- // Purpose: Yet another overload, lets us supply vecStart //----------------------------------------------------------------------------- void DispatchParticleEffect( const char *pszParticleName, Vector vecOrigin, Vector vecStart, QAngle vecAngles, CBaseEntity *pEntity ) { int iIndex = GetParticleSystemIndex( pszParticleName ); DispatchParticleEffect( iIndex, vecOrigin, vecStart, vecAngles, pEntity ); }
//----------------------------------------------------------------------------- // Purpose: Yet another overload, lets us supply vecStart //----------------------------------------------------------------------------- void TE_TFParticleEffect( IRecipientFilter &filter, float flDelay, const char *pszParticleName, Vector vecOrigin, Vector vecStart, QAngle vecAngles, CBaseEntity *pEntity ) { int iIndex = GetParticleSystemIndex( pszParticleName ); TE_TFParticleEffect( filter, flDelay, iIndex, vecOrigin, vecStart, vecAngles, pEntity ); }
void CWeaponDrainGrenade::RadiusDamage( const CTakeDamageInfo &inputInfo, const Vector &vecSrcIn, float flRadius ) { CTakeDamageInfo info = inputInfo; CBaseEntity *pEntity = NULL; trace_t tr; float flAdjustedDamage, falloff; Vector vecSpot; Vector vecToTarget; Vector vecEndPos; Vector vecSrc = vecSrcIn; if ( flRadius ) falloff = info.GetDamage() / flRadius; else falloff = 1.0; int bInWater = (UTIL_PointContents ( vecSrc ) & MASK_WATER) ? true : false; vecSrc.z += 1;// in case grenade is lying on the ground // iterate on all entities in the vicinity. for ( CEntitySphereQuery sphere( vecSrc, flRadius ); ( pEntity = sphere.GetCurrentEntity() ) != NULL; sphere.NextEntity() ) { if (!pEntity || !ToCFPlayer(pEntity)) continue; // Don't drain teammates. if (CFGameRules()->PlayerRelationship(GetThrower(), pEntity) == GR_TEAMMATE && ToCFPlayer(pEntity) != ToCFPlayer(GetThrower())) continue; if ( !pEntity->IsAlive() ) continue; if ( pEntity->m_takedamage != DAMAGE_NO ) { // blast's don't tavel into or out of water if (bInWater && pEntity->GetWaterLevel() == 0) continue; if (!bInWater && pEntity->GetWaterLevel() == 3) continue; // radius damage can only be blocked by the world vecSpot = pEntity->BodyTarget( vecSrc ); bool bHit = false; UTIL_TraceLine( vecSrc, vecSpot, MASK_SOLID_BRUSHONLY, info.GetInflictor(), COLLISION_GROUP_NONE, &tr ); if (tr.startsolid) { // if we're stuck inside them, fixup the position and distance tr.endpos = vecSrc; tr.fraction = 0.0; } vecEndPos = tr.endpos; if( tr.fraction == 1.0 || tr.m_pEnt == pEntity ) { bHit = true; } if ( bHit ) { // the explosion can 'see' this entity, so hurt them! vecToTarget = ( vecEndPos - vecSrc ); // decrease damage for an ent that's farther from the blast's center. flAdjustedDamage = vecToTarget.Length() * falloff; flAdjustedDamage = info.GetDrainFocus() - flAdjustedDamage; if ( flAdjustedDamage > 0 ) { CTakeDamageInfo adjustedInfo = info; adjustedInfo.SetDrainFocus( flAdjustedDamage ); Vector dir = vecToTarget; VectorNormalize( dir ); // If we don't have a damage force, manufacture one if ( adjustedInfo.GetDamagePosition() == vec3_origin || adjustedInfo.GetDamageForce() == vec3_origin ) { CalculateExplosiveDamageForce( &adjustedInfo, dir, vecSrc, 1.5 /* explosion scale! */ ); } else { // Assume the force passed in is the maximum force. Decay it based on falloff. float flForce = adjustedInfo.GetDamageForce().Length() * falloff; adjustedInfo.SetDamageForce( dir * flForce ); adjustedInfo.SetDamagePosition( vecSrc ); } float flFocusDrained = adjustedInfo.GetDrainFocus(); float& flFocus = ToCFPlayer(pEntity)->m_pStats->m_flFocus.GetForModify(); if (flFocus > cf_minfocusdrain.GetFloat()) flFocus -= flFocusDrained; if (flFocus < cf_minfocusdrain.GetFloat()) flFocus = cf_minfocusdrain.GetFloat(); CEffectData data; data.m_nHitBox = GetParticleSystemIndex( "grenade_drained" ); data.m_vOrigin = ToCFPlayer(pEntity)->GetCentroid(); data.m_vStart = vecSrc; data.m_vAngles = QAngle(0,0,0); data.m_nEntIndex = pEntity->entindex(); data.m_fFlags |= PARTICLE_DISPATCH_FROM_ENTITY; data.m_nDamageType = PATTACH_CUSTOMORIGIN; DispatchEffect( "ParticleEffect", data ); // Now hit all triggers along the way that respond to damage... pEntity->TraceAttackToTriggers( adjustedInfo, vecSrc, vecEndPos, dir ); } } } } }
//----------------------------------------------------------------------------- // Caches/uncaches resources //----------------------------------------------------------------------------- void CPrecacheHandler::CacheResource( PrecacheResourceType_t nType, const char *pName, bool bPrecache, ResourceList_t hResourceList, int *pIndex ) { if ( bPrecache ) { if ( pIndex ) { *pIndex = 0; } switch( nType ) { case VGUI_RESOURCE: break; case MATERIAL: PrecacheMaterial( pName ); if ( pIndex ) { *pIndex = GetMaterialIndex( pName ); } if ( hResourceList != RESOURCE_LIST_INVALID ) { g_pResourceAccessControl->AddResource( hResourceList, RESOURCE_MATERIAL, pName ); } break; case PARTICLE_MATERIAL: { #ifdef CLIENT_DLL // FIXME: NOTE! This is not 64-bit safe. // Hopefully we can remove PARTICLE_MATERIAL soon though. // It can go away once we retire the old-style particle system int nIndex = (int)( ParticleMgr()->GetPMaterial( pName ) ); #else int nIndex = 0; #endif if ( pIndex ) { *pIndex = nIndex; } } break; case GAME_MATERIAL_DECALS: PrecacheGameMaterialDecals( bPrecache, hResourceList ); break; case PHYSICS_GAMESOUNDS: PrecachePhysicsSounds( pName, bPrecache, hResourceList ); break; case DECAL: { int nIndex = UTIL_PrecacheDecal( pName, true ); if ( pIndex ) { *pIndex = nIndex; } } break; case MODEL: { int nIndex = CBaseEntity::PrecacheModel( pName ); if ( pIndex ) { *pIndex = nIndex; } if ( hResourceList != RESOURCE_LIST_INVALID ) { g_pResourceAccessControl->AddResource( hResourceList, RESOURCE_MODEL, pName ); } } break; case GAMESOUND: { int nIndex = CBaseEntity::PrecacheScriptSound( pName ); if ( pIndex ) { *pIndex = nIndex; } if ( hResourceList != RESOURCE_LIST_INVALID ) { g_pResourceAccessControl->AddResource( hResourceList, RESOURCE_GAMESOUND, pName ); } } break; case PARTICLE_SYSTEM: PrecacheParticleSystem( pName ); if ( pIndex ) { *pIndex = GetParticleSystemIndex( pName ); } if ( hResourceList != RESOURCE_LIST_INVALID ) { g_pResourceAccessControl->AddResource( hResourceList, RESOURCE_PARTICLE_SYSTEM, pName ); } break; case ENTITY: UTIL_PrecacheOther( pName ); break; case SHARED: g_pPrecacheSystem->Cache( this, SHARED_SYSTEM, pName, bPrecache, hResourceList, false ); break; case KV_DEP_FILE: CacheResourceFile( pName, bPrecache, hResourceList ); break; } return; } // Blat out value if ( pIndex ) { *pIndex = 0; } switch( nType ) { case VGUI_RESOURCE: break; case MATERIAL: break; case MODEL: break; case GAMESOUND: break; case PARTICLE_SYSTEM: break; case ENTITY: break; case DECAL: break; case KV_DEP_FILE: break; } }