//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $Workfile: $
// $NoKeywords: $
//=============================================================================//
# include "cbase.h"
# include "model_types.h"
# include "view_shared.h"
# include "iviewrender.h"
# include "tempentity.h"
# include "dlight.h"
# include "tempent.h"
# include "c_te_legacytempents.h"
# include "clientsideeffects.h"
# include "cl_animevent.h"
# include "iefx.h"
# include "engine/IEngineSound.h"
# include "env_wind_shared.h"
# include "clienteffectprecachesystem.h"
# include "fx_sparks.h"
# include "fx.h"
# include "movevars_shared.h"
# include "engine/ivmodelinfo.h"
# include "SoundEmitterSystem/isoundemittersystembase.h"
# include "view.h"
# include "tier0/vprof.h"
# include "particles_localspace.h"
# include "physpropclientside.h"
# include "tier0/icommandline.h"
# include "datacache/imdlcache.h"
# include "engine/ivdebugoverlay.h"
# include "effect_dispatch_data.h"
# include "c_te_effect_dispatch.h"
# include "c_props.h"
# include "c_basedoor.h"
// NOTE: Always include this last!
# include "tier0/memdbgon.h"
extern ConVar muzzleflash_light ;
# define TENT_WIND_ACCEL 50
//Precache the effects
# ifndef TF_CLIENT_DLL
CLIENTEFFECT_REGISTER_BEGIN ( PrecacheEffectMuzzleFlash )
CLIENTEFFECT_MATERIAL ( " effects/muzzleflash1 " )
CLIENTEFFECT_MATERIAL ( " effects/muzzleflash2 " )
CLIENTEFFECT_MATERIAL ( " effects/muzzleflash3 " )
CLIENTEFFECT_MATERIAL ( " effects/muzzleflash4 " )
CLIENTEFFECT_MATERIAL ( " effects/muzzleflash1_noz " )
CLIENTEFFECT_MATERIAL ( " effects/muzzleflash2_noz " )
CLIENTEFFECT_MATERIAL ( " effects/muzzleflash3_noz " )
CLIENTEFFECT_MATERIAL ( " effects/muzzleflash4_noz " )
# ifndef CSTRIKE_DLL
CLIENTEFFECT_MATERIAL ( " effects/combinemuzzle1 " )
CLIENTEFFECT_MATERIAL ( " effects/combinemuzzle2 " )
CLIENTEFFECT_MATERIAL ( " effects/combinemuzzle1_noz " )
CLIENTEFFECT_MATERIAL ( " effects/combinemuzzle2_noz " )
CLIENTEFFECT_MATERIAL ( " effects/strider_muzzle " )
# endif
CLIENTEFFECT_REGISTER_END ( )
# endif
//Whether or not to eject brass from weapons
ConVar cl_ejectbrass ( " cl_ejectbrass " , " 1 " ) ;
ConVar func_break_max_pieces ( " func_break_max_pieces " , " 15 " , FCVAR_ARCHIVE | FCVAR_REPLICATED ) ;
ConVar cl_fasttempentcollision ( " cl_fasttempentcollision " , " 5 " ) ;
# if !defined( HL1_CLIENT_DLL ) // HL1 implements a derivative of CTempEnts
// Temp entity interface
static CTempEnts g_TempEnts ;
// Expose to rest of the client .dll
ITempEnts * tempents = ( ITempEnts * ) & g_TempEnts ;
# endif
C_LocalTempEntity : : C_LocalTempEntity ( )
{
# ifdef _DEBUG
tentOffset . Init ( ) ;
m_vecTempEntVelocity . Init ( ) ;
m_vecTempEntAngVelocity . Init ( ) ;
m_vecNormal . Init ( ) ;
# endif
m_vecTempEntAcceleration . Init ( ) ;
m_pfnDrawHelper = 0 ;
m_pszImpactEffect = NULL ;
}
# if defined( CSTRIKE_DLL ) || defined (SDK_DLL )
# define TE_RIFLE_SHELL 1024
# define TE_PISTOL_SHELL 2048
# define TE_SHOTGUN_SHELL 4096
# endif
//-----------------------------------------------------------------------------
// Purpose: Prepare a temp entity for creation
// Input : time -
// *model -
//-----------------------------------------------------------------------------
void C_LocalTempEntity : : Prepare ( const model_t * pmodel , float time )
{
Interp_SetupMappings ( GetVarMapping ( ) ) ;
index = - 1 ;
Clear ( ) ;
// Use these to set per-frame and termination conditions / actions
flags = FTENT_NONE ;
die = time + 0.75 ;
SetModelPointer ( pmodel ) ;
SetRenderMode ( kRenderNormal ) ;
m_nRenderFX = kRenderFxNone ;
m_nBody = 0 ;
m_nSkin = 0 ;
fadeSpeed = 0.5 ;
hitSound = 0 ;
clientIndex = - 1 ;
bounceFactor = 1 ;
m_nFlickerFrame = 0 ;
m_bParticleCollision = false ;
}
//-----------------------------------------------------------------------------
// Sets the velocity
//-----------------------------------------------------------------------------
void C_LocalTempEntity : : SetVelocity ( const Vector & vecVelocity )
{
m_vecTempEntVelocity = vecVelocity ;
}
//-----------------------------------------------------------------------------
// Sets the velocity
//-----------------------------------------------------------------------------
void C_LocalTempEntity : : SetAcceleration ( const Vector & vecVelocity )
{
m_vecTempEntAcceleration = vecVelocity ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : int
//-----------------------------------------------------------------------------
int C_LocalTempEntity : : DrawStudioModel ( int flags )
{
VPROF_BUDGET ( " C_LocalTempEntity::DrawStudioModel " , VPROF_BUDGETGROUP_MODEL_RENDERING ) ;
int drawn = 0 ;
if ( ! GetModel ( ) | | modelinfo - > GetModelType ( GetModel ( ) ) ! = mod_studio )
return drawn ;
// Make sure m_pstudiohdr is valid for drawing
MDLCACHE_CRITICAL_SECTION ( ) ;
if ( ! GetModelPtr ( ) )
return drawn ;
if ( m_pfnDrawHelper )
{
drawn = ( * m_pfnDrawHelper ) ( this , flags ) ;
}
else
{
drawn = modelrender - > DrawModel (
flags ,
this ,
MODEL_INSTANCE_INVALID ,
index ,
GetModel ( ) ,
GetAbsOrigin ( ) ,
GetAbsAngles ( ) ,
m_nSkin ,
m_nBody ,
m_nHitboxSet ) ;
}
return drawn ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : flags -
//-----------------------------------------------------------------------------
int C_LocalTempEntity : : DrawModel ( int flags )
{
int drawn = 0 ;
if ( ! GetModel ( ) )
{
return drawn ;
}
if ( GetRenderMode ( ) = = kRenderNone )
return drawn ;
if ( this - > flags & FTENT_BEOCCLUDED )
{
// Check normal
Vector vecDelta = ( GetAbsOrigin ( ) - MainViewOrigin ( ) ) ;
VectorNormalize ( vecDelta ) ;
float flDot = DotProduct ( m_vecNormal , vecDelta ) ;
if ( flDot > 0 )
{
float flAlpha = RemapVal ( MIN ( flDot , 0.3 ) , 0 , 0.3 , 0 , 1 ) ;
flAlpha = MAX ( 1.0 , tempent_renderamt - ( tempent_renderamt * flAlpha ) ) ;
SetRenderColorA ( flAlpha ) ;
}
}
switch ( modelinfo - > GetModelType ( GetModel ( ) ) )
{
case mod_sprite :
drawn = DrawSprite (
this ,
GetModel ( ) ,
GetAbsOrigin ( ) ,
GetAbsAngles ( ) ,
m_flFrame , // sprite frame to render
m_nBody > 0 ? cl_entitylist - > GetBaseEntity ( m_nBody ) : NULL , // attach to
m_nSkin , // attachment point
GetRenderMode ( ) , // rendermode
m_nRenderFX , // renderfx
m_clrRender - > a , // alpha
m_clrRender - > r ,
m_clrRender - > g ,
m_clrRender - > b ,
m_flSpriteScale // sprite scale
) ;
break ;
case mod_studio :
drawn = DrawStudioModel ( flags ) ;
break ;
default :
break ;
}
return drawn ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool C_LocalTempEntity : : IsActive ( void )
{
bool active = true ;
float life = die - gpGlobals - > curtime ;
if ( life < 0 )
{
if ( flags & FTENT_FADEOUT )
{
int alpha ;
if ( GetRenderMode ( ) = = kRenderNormal )
{
SetRenderMode ( kRenderTransTexture ) ;
}
alpha = tempent_renderamt * ( 1 + life * fadeSpeed ) ;
if ( alpha < = 0 )
{
active = false ;
alpha = 0 ;
}
SetRenderColorA ( alpha ) ;
}
else
{
active = false ;
}
}
// Never die tempents only die when their die is cleared
if ( flags & FTENT_NEVERDIE )
{
active = ( die ! = 0 ) ;
}
return active ;
}
bool C_LocalTempEntity : : Frame ( float frametime , int framenumber )
{
float fastFreq = gpGlobals - > curtime * 5.5 ;
float gravity = - frametime * GetCurrentGravity ( ) ;
float gravitySlow = gravity * 0.5 ;
float traceFraction = 1 ;
Assert ( ! GetMoveParent ( ) ) ;
m_vecPrevLocalOrigin = GetLocalOrigin ( ) ;
m_vecTempEntVelocity = m_vecTempEntVelocity + ( m_vecTempEntAcceleration * frametime ) ;
if ( flags & FTENT_PLYRATTACHMENT )
{
if ( IClientEntity * pClient = cl_entitylist - > GetClientEntity ( clientIndex ) )
{
SetLocalOrigin ( pClient - > GetAbsOrigin ( ) + tentOffset ) ;
}
}
else if ( flags & FTENT_SINEWAVE )
{
x + = m_vecTempEntVelocity [ 0 ] * frametime ;
y + = m_vecTempEntVelocity [ 1 ] * frametime ;
SetLocalOrigin ( Vector (
x + sin ( m_vecTempEntVelocity [ 2 ] + gpGlobals - > curtime /* * anim.prevframe */ ) * ( 10 * m_flSpriteScale ) ,
y + sin ( m_vecTempEntVelocity [ 2 ] + fastFreq + 0.7 ) * ( 8 * m_flSpriteScale ) ,
GetLocalOriginDim ( Z_INDEX ) + m_vecTempEntVelocity [ 2 ] * frametime ) ) ;
}
else if ( flags & FTENT_SPIRAL )
{
float s , c ;
SinCos ( m_vecTempEntVelocity [ 2 ] + fastFreq , & s , & c ) ;
SetLocalOrigin ( GetLocalOrigin ( ) + Vector (
m_vecTempEntVelocity [ 0 ] * frametime + 8 * sin ( gpGlobals - > curtime * 20 ) ,
m_vecTempEntVelocity [ 1 ] * frametime + 4 * sin ( gpGlobals - > curtime * 30 ) ,
m_vecTempEntVelocity [ 2 ] * frametime ) ) ;
}
else
{
SetLocalOrigin ( GetLocalOrigin ( ) + m_vecTempEntVelocity * frametime ) ;
}
if ( flags & FTENT_SPRANIMATE )
{
m_flFrame + = frametime * m_flFrameRate ;
if ( m_flFrame > = m_flFrameMax )
{
m_flFrame = m_flFrame - ( int ) ( m_flFrame ) ;
if ( ! ( flags & FTENT_SPRANIMATELOOP ) )
{
// this animating sprite isn't set to loop, so destroy it.
die = 0.0f ;
return false ;
}
}
}
else if ( flags & FTENT_SPRCYCLE )
{
m_flFrame + = frametime * 10 ;
if ( m_flFrame > = m_flFrameMax )
{
m_flFrame = m_flFrame - ( int ) ( m_flFrame ) ;
}
}
if ( flags & FTENT_SMOKEGROWANDFADE )
{
m_flSpriteScale + = frametime * 0.5f ;
//m_clrRender.a -= frametime * 1500;
}
if ( flags & FTENT_ROTATE )
{
SetLocalAngles ( GetLocalAngles ( ) + m_vecTempEntAngVelocity * frametime ) ;
}
else if ( flags & FTENT_ALIGNTOMOTION )
{
if ( m_vecTempEntVelocity . Length ( ) > 0.0f )
{
QAngle angles ;
VectorAngles ( m_vecTempEntVelocity , angles ) ;
SetAbsAngles ( angles ) ;
}
}
if ( flags & ( FTENT_COLLIDEALL | FTENT_COLLIDEWORLD | FTENT_COLLIDEPROPS ) )
{
Vector traceNormal ;
traceNormal . Init ( ) ;
bool bShouldCollide = true ;
trace_t trace ;
if ( flags & ( FTENT_COLLIDEALL | FTENT_COLLIDEPROPS ) )
{
Vector vPrevOrigin = m_vecPrevLocalOrigin ;
if ( cl_fasttempentcollision . GetInt ( ) > 0 & & flags & FTENT_USEFASTCOLLISIONS )
{
if ( m_iLastCollisionFrame + cl_fasttempentcollision . GetInt ( ) > gpGlobals - > framecount )
{
bShouldCollide = false ;
}
else
{
if ( m_vLastCollisionOrigin ! = vec3_origin )
{
vPrevOrigin = m_vLastCollisionOrigin ;
}
m_iLastCollisionFrame = gpGlobals - > framecount ;
bShouldCollide = true ;
}
}
if ( bShouldCollide = = true )
{
// If the FTENT_COLLISIONGROUP flag is set, use the entity's collision group
int collisionGroup = COLLISION_GROUP_NONE ;
if ( flags & FTENT_COLLISIONGROUP )
{
collisionGroup = GetCollisionGroup ( ) ;
}
UTIL_TraceLine ( vPrevOrigin , GetLocalOrigin ( ) , MASK_SOLID , GetOwnerEntity ( ) , collisionGroup , & trace ) ;
if ( ( flags & FTENT_COLLIDEPROPS ) & & trace . m_pEnt )
{
bool bIsDynamicProp = ( NULL ! = dynamic_cast < CDynamicProp * > ( trace . m_pEnt ) ) ;
bool bIsDoor = ( NULL ! = dynamic_cast < CBaseDoor * > ( trace . m_pEnt ) ) ;
if ( ! bIsDynamicProp & & ! bIsDoor & & ! trace . m_pEnt - > IsWorld ( ) ) // Die on props, doors, and the world.
return true ;
}
// Make sure it didn't bump into itself... (?!?)
if (
( trace . fraction ! = 1 ) & &
( ( trace . DidHitWorld ( ) ) | |
( trace . m_pEnt ! = ClientEntityList ( ) . GetEnt ( clientIndex ) ) )
)
{
traceFraction = trace . fraction ;
VectorCopy ( trace . plane . normal , traceNormal ) ;
}
m_vLastCollisionOrigin = trace . endpos ;
}
}
else if ( flags & FTENT_COLLIDEWORLD )
{
CTraceFilterWorldOnly traceFilter ;
UTIL_TraceLine ( m_vecPrevLocalOrigin , GetLocalOrigin ( ) , MASK_SOLID , & traceFilter , & trace ) ;
if ( trace . fraction ! = 1 )
{
traceFraction = trace . fraction ;
VectorCopy ( trace . plane . normal , traceNormal ) ;
}
}
if ( traceFraction ! = 1 ) // Decent collision now, and damping works
{
float proj , damp ;
SetLocalOrigin ( trace . endpos ) ;
// Damp velocity
damp = bounceFactor ;
if ( flags & ( FTENT_GRAVITY | FTENT_SLOWGRAVITY ) )
{
damp * = 0.5 ;
if ( traceNormal [ 2 ] > 0.9 ) // Hit floor?
{
if ( m_vecTempEntVelocity [ 2 ] < = 0 & & m_vecTempEntVelocity [ 2 ] > = gravity * 3 )
{
damp = 0 ; // Stop
flags & = ~ ( FTENT_ROTATE | FTENT_GRAVITY | FTENT_SLOWGRAVITY | FTENT_COLLIDEWORLD | FTENT_SMOKETRAIL ) ;
SetLocalAnglesDim ( X_INDEX , 0 ) ;
SetLocalAnglesDim ( Z_INDEX , 0 ) ;
}
}
}
if ( flags & ( FTENT_CHANGERENDERONCOLLIDE ) )
{
m_RenderGroup = RENDER_GROUP_OTHER ;
flags & = ~ FTENT_CHANGERENDERONCOLLIDE ;
}
if ( hitSound )
{
tempents - > PlaySound ( this , damp ) ;
}
if ( m_pszImpactEffect )
{
CEffectData data ;
//data.m_vOrigin = newOrigin;
data . m_vOrigin = trace . endpos ;
data . m_vStart = trace . startpos ;
data . m_nSurfaceProp = trace . surface . surfaceProps ;
data . m_nHitBox = trace . hitbox ;
data . m_nDamageType = TEAM_UNASSIGNED ;
IClientNetworkable * pClient = cl_entitylist - > GetClientEntity ( clientIndex ) ;
if ( pClient )
{
C_BasePlayer * pPlayer = dynamic_cast < C_BasePlayer * > ( pClient ) ;
if ( pPlayer )
{
data . m_nDamageType = pPlayer - > GetTeamNumber ( ) ;
}
}
if ( trace . m_pEnt )
{
data . m_hEntity = ClientEntityList ( ) . EntIndexToHandle ( trace . m_pEnt - > entindex ( ) ) ;
}
DispatchEffect ( m_pszImpactEffect , data ) ;
}
// Check for a collision and stop the particle system.
if ( flags & FTENT_CLIENTSIDEPARTICLES )
{
// Stop the emission of particles on collision - removed from the ClientEntityList on removal from the tempent pool.
ParticleProp ( ) - > StopEmission ( ) ;
m_bParticleCollision = true ;
}
if ( flags & FTENT_COLLIDEKILL )
{
// die on impact
flags & = ~ FTENT_FADEOUT ;
die = gpGlobals - > curtime ;
}
else if ( flags & FTENT_ATTACHTOTARGET )
{
// If we've hit the world, just stop moving
if ( trace . DidHitWorld ( ) & & ! ( trace . surface . flags & SURF_SKY ) )
{
m_vecTempEntVelocity = vec3_origin ;
m_vecTempEntAcceleration = vec3_origin ;
// Remove movement flags so we don't keep tracing
flags & = ~ ( FTENT_COLLIDEALL | FTENT_COLLIDEWORLD ) ;
}
else
{
// Couldn't attach to this entity. Die.
flags & = ~ FTENT_FADEOUT ;
die = gpGlobals - > curtime ;
}
}
else
{
// Reflect velocity
if ( damp ! = 0 )
{
proj = ( ( Vector ) m_vecTempEntVelocity ) . Dot ( traceNormal ) ;
VectorMA ( m_vecTempEntVelocity , - proj * 2 , traceNormal , m_vecTempEntVelocity ) ;
// Reflect rotation (fake)
SetLocalAnglesDim ( Y_INDEX , - GetLocalAnglesDim ( Y_INDEX ) ) ;
}
if ( damp ! = 1 )
{
VectorScale ( m_vecTempEntVelocity , damp , m_vecTempEntVelocity ) ;
SetLocalAngles ( GetLocalAngles ( ) * 0.9 ) ;
}
}
}
}
if ( ( flags & FTENT_FLICKER ) & & framenumber = = m_nFlickerFrame )
{
dlight_t * dl = effects - > CL_AllocDlight ( LIGHT_INDEX_TE_DYNAMIC ) ;
VectorCopy ( GetLocalOrigin ( ) , dl - > origin ) ;
dl - > radius = 60 ;
dl - > color . r = 255 ;
dl - > color . g = 120 ;
dl - > color . b = 0 ;
dl - > die = gpGlobals - > curtime + 0.01 ;
}
if ( flags & FTENT_SMOKETRAIL )
{
Assert ( ! " FIXME: Rework smoketrail to be client side \n " ) ;
}
// add gravity if we didn't collide in this frame
if ( traceFraction = = 1 )
{
if ( flags & FTENT_GRAVITY )
m_vecTempEntVelocity [ 2 ] + = gravity ;
else if ( flags & FTENT_SLOWGRAVITY )
m_vecTempEntVelocity [ 2 ] + = gravitySlow ;
}
if ( flags & FTENT_WINDBLOWN )
{
Vector vecWind ;
GetWindspeedAtTime ( gpGlobals - > curtime , vecWind ) ;
for ( int i = 0 ; i < 2 ; i + + )
{
if ( m_vecTempEntVelocity [ i ] < vecWind [ i ] )
{
m_vecTempEntVelocity [ i ] + = ( frametime * TENT_WIND_ACCEL ) ;
// clamp
if ( m_vecTempEntVelocity [ i ] > vecWind [ i ] )
m_vecTempEntVelocity [ i ] = vecWind [ i ] ;
}
else if ( m_vecTempEntVelocity [ i ] > vecWind [ i ] )
{
m_vecTempEntVelocity [ i ] - = ( frametime * TENT_WIND_ACCEL ) ;
// clamp.
if ( m_vecTempEntVelocity [ i ] < vecWind [ i ] )
m_vecTempEntVelocity [ i ] = vecWind [ i ] ;
}
}
}
return true ;
}
//-----------------------------------------------------------------------------
// Purpose: Attach a particle effect to a temp entity.
//-----------------------------------------------------------------------------
CNewParticleEffect * C_LocalTempEntity : : AddParticleEffect ( const char * pszParticleEffect )
{
// Do we have a valid particle effect.
if ( ! pszParticleEffect | | ( pszParticleEffect [ 0 ] = = ' \0 ' ) )
return NULL ;
// Check to see that we don't already have a particle effect.
if ( ( flags & FTENT_CLIENTSIDEPARTICLES ) ! = 0 )
return NULL ;
// Add the entity to the ClientEntityList and create the particle system.
ClientEntityList ( ) . AddNonNetworkableEntity ( this ) ;
CNewParticleEffect * pEffect = ParticleProp ( ) - > Create ( pszParticleEffect , PATTACH_ABSORIGIN_FOLLOW ) ;
// Set the particle flag on the temp entity and save the name of the particle effect.
flags | = FTENT_CLIENTSIDEPARTICLES ;
SetParticleEffect ( pszParticleEffect ) ;
return pEffect ;
}
//-----------------------------------------------------------------------------
// Purpose: This helper keeps track of batches of "breakmodels" so that they can all share the lighting origin
// of the first of the group (because the server sends down 15 chunks at a time, and rebuilding 15 light cache
// entries for a map with a lot of worldlights is really slow).
//-----------------------------------------------------------------------------
class CBreakableHelper
{
public :
void Insert ( C_LocalTempEntity * entity , bool isSlave ) ;
void Remove ( C_LocalTempEntity * entity ) ;
void Clear ( ) ;
const Vector * GetLightingOrigin ( C_LocalTempEntity * entity ) ;
private :
// A context is the first master until the next one, which starts a new context
struct BreakableList_t
{
unsigned int context ;
C_LocalTempEntity * entity ;
} ;
CUtlLinkedList < BreakableList_t , unsigned short > m_Breakables ;
unsigned int m_nCurrentContext ;
} ;
//-----------------------------------------------------------------------------
// Purpose: Adds brekable to list, starts new context if needed
// Input : *entity -
// isSlave -
//-----------------------------------------------------------------------------
void CBreakableHelper : : Insert ( C_LocalTempEntity * entity , bool isSlave )
{
// A master signifies the start of a new run of broken objects
if ( ! isSlave )
{
+ + m_nCurrentContext ;
}
BreakableList_t entry ;
entry . context = m_nCurrentContext ;
entry . entity = entity ;
m_Breakables . AddToTail ( entry ) ;
}
//-----------------------------------------------------------------------------
// Purpose: Removes all instances of entity in the list
// Input : *entity -
//-----------------------------------------------------------------------------
void CBreakableHelper : : Remove ( C_LocalTempEntity * entity )
{
for ( unsigned short i = m_Breakables . Head ( ) ; i ! = m_Breakables . InvalidIndex ( ) ; )
{
unsigned short n = m_Breakables . Next ( i ) ;
if ( m_Breakables [ i ] . entity = = entity )
{
m_Breakables . Remove ( i ) ;
}
i = n ;
}
}
//-----------------------------------------------------------------------------
// Purpose: For a given breakable, find the "first" or head object and use it's current
// origin as the lighting origin for the entire group of objects
// Input : *entity -
// Output : const Vector
//-----------------------------------------------------------------------------
const Vector * CBreakableHelper : : GetLightingOrigin ( C_LocalTempEntity * entity )
{
unsigned int nCurContext = 0 ;
C_LocalTempEntity * head = NULL ;
FOR_EACH_LL ( m_Breakables , i )
{
BreakableList_t & e = m_Breakables [ i ] ;
if ( e . context ! = nCurContext )
{
nCurContext = e . context ;
head = e . entity ;
}
if ( e . entity = = entity )
{
Assert ( head ) ;
return head ? & head - > GetAbsOrigin ( ) : NULL ;
}
}
return NULL ;
}
//-----------------------------------------------------------------------------
// Purpose: Wipe breakable helper list
// Input : -
//-----------------------------------------------------------------------------
void CBreakableHelper : : Clear ( )
{
m_Breakables . RemoveAll ( ) ;
m_nCurrentContext = 0 ;
}
static CBreakableHelper g_BreakableHelper ;
//-----------------------------------------------------------------------------
// Purpose: See if it's in the breakable helper list and, if so, remove
// Input : -
//-----------------------------------------------------------------------------
void C_LocalTempEntity : : OnRemoveTempEntity ( )
{
g_BreakableHelper . Remove ( this ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTempEnts : : CTempEnts ( void ) :
m_TempEntsPool ( ( MAX_TEMP_ENTITIES / 20 ) , CUtlMemoryPool : : GROW_SLOW )
{
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
CTempEnts : : ~ CTempEnts ( void )
{
m_TempEntsPool . Clear ( ) ;
m_TempEnts . RemoveAll ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose: Create a fizz effect
// Input : *pent -
// modelIndex -
// density -
//-----------------------------------------------------------------------------
void CTempEnts : : FizzEffect ( C_BaseEntity * pent , int modelIndex , int density , int current )
{
C_LocalTempEntity * pTemp ;
const model_t * model ;
int i , width , depth , count , frameCount ;
float maxHeight , speed , xspeed , yspeed ;
Vector origin ;
Vector mins , maxs ;
if ( ! pent - > GetModel ( ) | | ! modelIndex )
return ;
model = modelinfo - > GetModel ( modelIndex ) ;
if ( ! model )
return ;
count = density + 1 ;
density = count * 3 + 6 ;
modelinfo - > GetModelBounds ( pent - > GetModel ( ) , mins , maxs ) ;
maxHeight = maxs [ 2 ] - mins [ 2 ] ;
width = maxs [ 0 ] - mins [ 0 ] ;
depth = maxs [ 1 ] - mins [ 1 ] ;
speed = current ;
SinCos ( pent - > GetLocalAngles ( ) [ 1 ] * M_PI / 180 , & yspeed , & xspeed ) ;
xspeed * = speed ;
yspeed * = speed ;
frameCount = modelinfo - > GetModelFrameCount ( model ) ;
for ( i = 0 ; i < count ; i + + )
{
origin [ 0 ] = mins [ 0 ] + random - > RandomInt ( 0 , width - 1 ) ;
origin [ 1 ] = mins [ 1 ] + random - > RandomInt ( 0 , depth - 1 ) ;
origin [ 2 ] = mins [ 2 ] ;
pTemp = TempEntAlloc ( origin , model ) ;
if ( ! pTemp )
return ;
pTemp - > flags | = FTENT_SINEWAVE ;
pTemp - > x = origin [ 0 ] ;
pTemp - > y = origin [ 1 ] ;
float zspeed = random - > RandomInt ( 80 , 140 ) ;
pTemp - > SetVelocity ( Vector ( xspeed , yspeed , zspeed ) ) ;
pTemp - > die = gpGlobals - > curtime + ( maxHeight / zspeed ) - 0.1 ;
pTemp - > m_flFrame = random - > RandomInt ( 0 , frameCount - 1 ) ;
// Set sprite scale
pTemp - > m_flSpriteScale = 1.0 / random - > RandomFloat ( 2 , 5 ) ;
pTemp - > SetRenderMode ( kRenderTransAlpha ) ;
pTemp - > SetRenderColorA ( 255 ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Create bubbles
// Input : *mins -
// *maxs -
// height -
// modelIndex -
// count -
// speed -
//-----------------------------------------------------------------------------
void CTempEnts : : Bubbles ( const Vector & mins , const Vector & maxs , float height , int modelIndex , int count , float speed )
{
C_LocalTempEntity * pTemp ;
const model_t * model ;
int i , frameCount ;
float sine , cosine ;
Vector origin ;
if ( ! modelIndex )
return ;
model = modelinfo - > GetModel ( modelIndex ) ;
if ( ! model )
return ;
frameCount = modelinfo - > GetModelFrameCount ( model ) ;
for ( i = 0 ; i < count ; i + + )
{
origin [ 0 ] = random - > RandomInt ( mins [ 0 ] , maxs [ 0 ] ) ;
origin [ 1 ] = random - > RandomInt ( mins [ 1 ] , maxs [ 1 ] ) ;
origin [ 2 ] = random - > RandomInt ( mins [ 2 ] , maxs [ 2 ] ) ;
pTemp = TempEntAlloc ( origin , model ) ;
if ( ! pTemp )
return ;
pTemp - > flags | = FTENT_SINEWAVE ;
pTemp - > x = origin [ 0 ] ;
pTemp - > y = origin [ 1 ] ;
SinCos ( random - > RandomInt ( - 3 , 3 ) , & sine , & cosine ) ;
float zspeed = random - > RandomInt ( 80 , 140 ) ;
pTemp - > SetVelocity ( Vector ( speed * cosine , speed * sine , zspeed ) ) ;
pTemp - > die = gpGlobals - > curtime + ( ( height - ( origin [ 2 ] - mins [ 2 ] ) ) / zspeed ) - 0.1 ;
pTemp - > m_flFrame = random - > RandomInt ( 0 , frameCount - 1 ) ;
// Set sprite scale
pTemp - > m_flSpriteScale = 1.0 / random - > RandomFloat ( 4 , 16 ) ;
pTemp - > SetRenderMode ( kRenderTransAlpha ) ;
pTemp - > SetRenderColor ( 255 , 255 , 255 , 192 ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Create bubble trail
// Input : *start -
// *end -
// height -
// modelIndex -
// count -
// speed -
//-----------------------------------------------------------------------------
void CTempEnts : : BubbleTrail ( const Vector & start , const Vector & end , float flWaterZ , int modelIndex , int count , float speed )
{
C_LocalTempEntity * pTemp ;
const model_t * model ;
int i , frameCount ;
float dist , angle ;
Vector origin ;
if ( ! modelIndex )
return ;
model = modelinfo - > GetModel ( modelIndex ) ;
if ( ! model )
return ;
frameCount = modelinfo - > GetModelFrameCount ( model ) ;
for ( i = 0 ; i < count ; i + + )
{
dist = random - > RandomFloat ( 0 , 1.0 ) ;
VectorLerp ( start , end , dist , origin ) ;
pTemp = TempEntAlloc ( origin , model ) ;
if ( ! pTemp )
return ;
pTemp - > flags | = FTENT_SINEWAVE ;
pTemp - > x = origin [ 0 ] ;
pTemp - > y = origin [ 1 ] ;
angle = random - > RandomInt ( - 3 , 3 ) ;
float zspeed = random - > RandomInt ( 80 , 140 ) ;
pTemp - > SetVelocity ( Vector ( speed * cos ( angle ) , speed * sin ( angle ) , zspeed ) ) ;
pTemp - > die = gpGlobals - > curtime + ( ( flWaterZ - origin [ 2 ] ) / zspeed ) - 0.1 ;
pTemp - > m_flFrame = random - > RandomInt ( 0 , frameCount - 1 ) ;
// Set sprite scale
pTemp - > m_flSpriteScale = 1.0 / random - > RandomFloat ( 4 , 8 ) ;
pTemp - > SetRenderMode ( kRenderTransAlpha ) ;
pTemp - > SetRenderColor ( 255 , 255 , 255 , 192 ) ;
}
}
# define SHARD_VOLUME 12.0 // on shard ever n^3 units
//-----------------------------------------------------------------------------
// Purpose: Only used by BreakModel temp ents for now. Allows them to share a single
// lighting origin amongst a group of objects. If the master object goes away, the next object
// in the group becomes the new lighting origin, etc.
// Input : *entity -
// flags -
// Output : int
//-----------------------------------------------------------------------------
int BreakModelDrawHelper ( C_LocalTempEntity * entity , int flags )
{
ModelRenderInfo_t sInfo ;
sInfo . flags = flags ;
sInfo . pRenderable = entity ;
sInfo . instance = MODEL_INSTANCE_INVALID ;
sInfo . entity_index = entity - > index ;
sInfo . pModel = entity - > GetModel ( ) ;
sInfo . origin = entity - > GetRenderOrigin ( ) ;
sInfo . angles = entity - > GetRenderAngles ( ) ;
sInfo . skin = entity - > m_nSkin ;
sInfo . body = entity - > m_nBody ;
sInfo . hitboxset = entity - > m_nHitboxSet ;
// This is the main change, look up a lighting origin from the helper singleton
const Vector * pLightingOrigin = g_BreakableHelper . GetLightingOrigin ( entity ) ;
if ( pLightingOrigin )
{
sInfo . pLightingOrigin = pLightingOrigin ;
}
int drawn = modelrender - > DrawModelEx ( sInfo ) ;
return drawn ;
}
//-----------------------------------------------------------------------------
// Purpose: Create model shattering shards
// Input : *pos -
// *size -
// *dir -
// random -
// life -
// count -
// modelIndex -
// flags -
//-----------------------------------------------------------------------------
void CTempEnts : : BreakModel ( const Vector & pos , const QAngle & angles , const Vector & size , const Vector & dir ,
float randRange , float life , int count , int modelIndex , char flags )
{
int i , frameCount ;
C_LocalTempEntity * pTemp ;
const model_t * pModel ;
if ( ! modelIndex )
return ;
pModel = modelinfo - > GetModel ( modelIndex ) ;
if ( ! pModel )
return ;
// See g_BreakableHelper above for notes...
bool isSlave = ( flags & BREAK_SLAVE ) ? true : false ;
frameCount = modelinfo - > GetModelFrameCount ( pModel ) ;
if ( count = = 0 )
{
// assume surface (not volume)
count = ( size [ 0 ] * size [ 1 ] + size [ 1 ] * size [ 2 ] + size [ 2 ] * size [ 0 ] ) / ( 3 * SHARD_VOLUME * SHARD_VOLUME ) ;
}
if ( count > func_break_max_pieces . GetInt ( ) )
{
count = func_break_max_pieces . GetInt ( ) ;
}
matrix3x4_t transform ;
AngleMatrix ( angles , pos , transform ) ;
for ( i = 0 ; i < count ; i + + )
{
Vector vecLocalSpot , vecSpot ;
// fill up the box with stuff
vecLocalSpot [ 0 ] = random - > RandomFloat ( - 0.5 , 0.5 ) * size [ 0 ] ;
vecLocalSpot [ 1 ] = random - > RandomFloat ( - 0.5 , 0.5 ) * size [ 1 ] ;
vecLocalSpot [ 2 ] = random - > RandomFloat ( - 0.5 , 0.5 ) * size [ 2 ] ;
VectorTransform ( vecLocalSpot , transform , vecSpot ) ;
pTemp = TempEntAlloc ( vecSpot , pModel ) ;
if ( ! pTemp )
return ;
// keep track of break_type, so we know how to play sound on collision
pTemp - > hitSound = flags ;
if ( modelinfo - > GetModelType ( pModel ) = = mod_sprite )
{
pTemp - > m_flFrame = random - > RandomInt ( 0 , frameCount - 1 ) ;
}
else if ( modelinfo - > GetModelType ( pModel ) = = mod_studio )
{
pTemp - > m_nBody = random - > RandomInt ( 0 , frameCount - 1 ) ;
}
pTemp - > flags | = FTENT_COLLIDEWORLD | FTENT_FADEOUT | FTENT_SLOWGRAVITY ;
if ( random - > RandomInt ( 0 , 255 ) < 200 )
{
pTemp - > flags | = FTENT_ROTATE ;
pTemp - > m_vecTempEntAngVelocity [ 0 ] = random - > RandomFloat ( - 256 , 255 ) ;
pTemp - > m_vecTempEntAngVelocity [ 1 ] = random - > RandomFloat ( - 256 , 255 ) ;
pTemp - > m_vecTempEntAngVelocity [ 2 ] = random - > RandomFloat ( - 256 , 255 ) ;
}
if ( ( random - > RandomInt ( 0 , 255 ) < 100 ) & & ( flags & BREAK_SMOKE ) )
{
pTemp - > flags | = FTENT_SMOKETRAIL ;
}
if ( ( flags & BREAK_GLASS ) | | ( flags & BREAK_TRANS ) )
{
pTemp - > SetRenderMode ( kRenderTransTexture ) ;
pTemp - > SetRenderColorA ( 128 ) ;
pTemp - > tempent_renderamt = 128 ;
pTemp - > bounceFactor = 0.3f ;
}
else
{
pTemp - > SetRenderMode ( kRenderNormal ) ;
pTemp - > tempent_renderamt = 255 ; // Set this for fadeout
}
pTemp - > SetVelocity ( Vector ( dir [ 0 ] + random - > RandomFloat ( - randRange , randRange ) ,
dir [ 1 ] + random - > RandomFloat ( - randRange , randRange ) ,
dir [ 2 ] + random - > RandomFloat ( 0 , randRange ) ) ) ;
pTemp - > die = gpGlobals - > curtime + life + random - > RandomFloat ( 0 , 1 ) ; // Add an extra 0-1 secs of life
// We use a special rendering function because these objects will want to share their lighting
// origin with the first/master object. Prevents a huge spike in Light Cache building in maps
// with many worldlights.
pTemp - > SetDrawHelper ( BreakModelDrawHelper ) ;
g_BreakableHelper . Insert ( pTemp , isSlave ) ;
}
}
void CTempEnts : : PhysicsProp ( int modelindex , int skin , const Vector & pos , const QAngle & angles , const Vector & vel , int flags , int effects )
{
C_PhysPropClientside * pEntity = C_PhysPropClientside : : CreateNew ( ) ;
if ( ! pEntity )
return ;
const model_t * model = modelinfo - > GetModel ( modelindex ) ;
if ( ! model )
{
DevMsg ( " CTempEnts::PhysicsProp: model index %i not found \n " , modelindex ) ;
return ;
}
pEntity - > SetModelName ( modelinfo - > GetModelName ( model ) ) ;
pEntity - > m_nSkin = skin ;
pEntity - > SetAbsOrigin ( pos ) ;
pEntity - > SetAbsAngles ( angles ) ;
pEntity - > SetPhysicsMode ( PHYSICS_MULTIPLAYER_CLIENTSIDE ) ;
pEntity - > SetEffects ( effects ) ;
if ( ! pEntity - > Initialize ( ) )
{
pEntity - > Release ( ) ;
return ;
}
IPhysicsObject * pPhysicsObject = pEntity - > VPhysicsGetObject ( ) ;
if ( pPhysicsObject )
{
pPhysicsObject - > AddVelocity ( & vel , NULL ) ;
}
else
{
// failed to create a physics object
pEntity - > Release ( ) ;
return ;
}
if ( flags & 1 )
{
pEntity - > SetHealth ( 0 ) ;
pEntity - > Break ( ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Create a clientside projectile
// Input : vecOrigin -
// vecVelocity -
// modelindex -
// lifetime -
// *pOwner -
//-----------------------------------------------------------------------------
C_LocalTempEntity * CTempEnts : : ClientProjectile ( const Vector & vecOrigin , const Vector & vecVelocity , const Vector & vecAcceleration , int modelIndex , int lifetime , CBaseEntity * pOwner , const char * pszImpactEffect , const char * pszParticleEffect )
{
C_LocalTempEntity * pTemp ;
const model_t * model ;
if ( ! modelIndex )
return NULL ;
model = modelinfo - > GetModel ( modelIndex ) ;
if ( ! model )
{
Warning ( " ClientProjectile: No model %d! \n " , modelIndex ) ;
return NULL ;
}
pTemp = TempEntAlloc ( vecOrigin , model ) ;
if ( ! pTemp )
return NULL ;
pTemp - > SetVelocity ( vecVelocity ) ;
pTemp - > SetAcceleration ( vecAcceleration ) ;
QAngle angles ;
VectorAngles ( vecVelocity , angles ) ;
pTemp - > SetAbsAngles ( angles ) ;
pTemp - > SetAbsOrigin ( vecOrigin ) ;
pTemp - > die = gpGlobals - > curtime + lifetime ;
pTemp - > flags = FTENT_COLLIDEALL | FTENT_ATTACHTOTARGET | FTENT_ALIGNTOMOTION ;
pTemp - > clientIndex = ( pOwner ! = NULL ) ? pOwner - > entindex ( ) : 0 ;
pTemp - > SetOwnerEntity ( pOwner ) ;
pTemp - > SetImpactEffect ( pszImpactEffect ) ;
if ( pszParticleEffect )
{
// Add the entity to the ClientEntityList and create the particle system.
ClientEntityList ( ) . AddNonNetworkableEntity ( pTemp ) ;
pTemp - > ParticleProp ( ) - > Create ( pszParticleEffect , PATTACH_ABSORIGIN_FOLLOW ) ;
// Set the particle flag on the temp entity and save the name of the particle effect.
pTemp - > flags | = FTENT_CLIENTSIDEPARTICLES ;
pTemp - > SetParticleEffect ( pszParticleEffect ) ;
}
return pTemp ;
}
//-----------------------------------------------------------------------------
// Purpose: Create sprite TE
// Input : *pos -
// *dir -
// scale -
// modelIndex -
// rendermode -
// renderfx -
// a -
// life -
// flags -
// Output : C_LocalTempEntity
//-----------------------------------------------------------------------------
C_LocalTempEntity * CTempEnts : : TempSprite ( const Vector & pos , const Vector & dir , float scale , int modelIndex , int rendermode , int renderfx , float a , float life , int flags , const Vector & normal )
{
C_LocalTempEntity * pTemp ;
const model_t * model ;
int frameCount ;
if ( ! modelIndex )
return NULL ;
model = modelinfo - > GetModel ( modelIndex ) ;
if ( ! model )
{
Warning ( " No model %d! \n " , modelIndex ) ;
return NULL ;
}
frameCount = modelinfo - > GetModelFrameCount ( model ) ;
pTemp = TempEntAlloc ( pos , model ) ;
if ( ! pTemp )
return NULL ;
pTemp - > m_flFrameMax = frameCount - 1 ;
pTemp - > m_flFrameRate = 10 ;
pTemp - > SetRenderMode ( ( RenderMode_t ) rendermode ) ;
pTemp - > m_nRenderFX = renderfx ;
pTemp - > m_flSpriteScale = scale ;
pTemp - > tempent_renderamt = a * 255 ;
pTemp - > m_vecNormal = normal ;
pTemp - > SetRenderColor ( 255 , 255 , 255 , a * 255 ) ;
pTemp - > flags | = flags ;
pTemp - > SetVelocity ( dir ) ;
pTemp - > SetLocalOrigin ( pos ) ;
if ( life )
pTemp - > die = gpGlobals - > curtime + life ;
else
pTemp - > die = gpGlobals - > curtime + ( frameCount * 0.1 ) + 1 ;
pTemp - > m_flFrame = 0 ;
return pTemp ;
}
//-----------------------------------------------------------------------------
// Purpose: Spray sprite
// Input : *pos -
// *dir -
// modelIndex -
// count -
// speed -
// iRand -
//-----------------------------------------------------------------------------
void CTempEnts : : Sprite_Spray ( const Vector & pos , const Vector & dir , int modelIndex , int count , int speed , int iRand )
{
C_LocalTempEntity * pTemp ;
const model_t * pModel ;
float noise ;
float znoise ;
int frameCount ;
int i ;
noise = ( float ) iRand / 100 ;
// more vertical displacement
znoise = noise * 1.5 ;
if ( znoise > 1 )
{
znoise = 1 ;
}
pModel = modelinfo - > GetModel ( modelIndex ) ;
if ( ! pModel )
{
Warning ( " No model %d! \n " , modelIndex ) ;
return ;
}
frameCount = modelinfo - > GetModelFrameCount ( pModel ) - 1 ;
for ( i = 0 ; i < count ; i + + )
{
pTemp = TempEntAlloc ( pos , pModel ) ;
if ( ! pTemp )
return ;
pTemp - > SetRenderMode ( kRenderTransAlpha ) ;
pTemp - > SetRenderColor ( 255 , 255 , 255 , 255 ) ;
pTemp - > tempent_renderamt = 255 ;
pTemp - > m_nRenderFX = kRenderFxNoDissipation ;
//pTemp->scale = random->RandomFloat( 0.1, 0.25 );
pTemp - > m_flSpriteScale = 0.5 ;
pTemp - > flags | = FTENT_FADEOUT | FTENT_SLOWGRAVITY ;
pTemp - > fadeSpeed = 2.0 ;
// make the spittle fly the direction indicated, but mix in some noise.
Vector velocity ;
velocity . x = dir [ 0 ] + random - > RandomFloat ( - noise , noise ) ;
velocity . y = dir [ 1 ] + random - > RandomFloat ( - noise , noise ) ;
velocity . z = dir [ 2 ] + random - > RandomFloat ( 0 , znoise ) ;
velocity * = random - > RandomFloat ( ( speed * 0.8 ) , ( speed * 1.2 ) ) ;
pTemp - > SetVelocity ( velocity ) ;
pTemp - > SetLocalOrigin ( pos ) ;
pTemp - > die = gpGlobals - > curtime + 0.35 ;
pTemp - > m_flFrame = random - > RandomInt ( 0 , frameCount ) ;
}
}
void CTempEnts : : Sprite_Trail ( const Vector & vecStart , const Vector & vecEnd , int modelIndex , int nCount , float flLife , float flSize , float flAmplitude , int nRenderamt , float flSpeed )
{
C_LocalTempEntity * pTemp ;
const model_t * pModel ;
int flFrameCount ;
pModel = modelinfo - > GetModel ( modelIndex ) ;
if ( ! pModel )
{
Warning ( " No model %d! \n " , modelIndex ) ;
return ;
}
flFrameCount = modelinfo - > GetModelFrameCount ( pModel ) ;
Vector vecDelta ;
VectorSubtract ( vecEnd , vecStart , vecDelta ) ;
Vector vecDir ;
VectorCopy ( vecDelta , vecDir ) ;
VectorNormalize ( vecDir ) ;
flAmplitude / = 256.0 ;
for ( int i = 0 ; i < nCount ; i + + )
{
Vector vecPos ;
// Be careful of divide by 0 when using 'count' here...
if ( i = = 0 )
{
VectorMA ( vecStart , 0 , vecDelta , vecPos ) ;
}
else
{
VectorMA ( vecStart , i / ( nCount - 1.0 ) , vecDelta , vecPos ) ;
}
pTemp = TempEntAlloc ( vecPos , pModel ) ;
if ( ! pTemp )
return ;
pTemp - > flags | = FTENT_COLLIDEWORLD | FTENT_SPRCYCLE | FTENT_FADEOUT | FTENT_SLOWGRAVITY ;
Vector vecVel = vecDir * flSpeed ;
vecVel . x + = random - > RandomInt ( - 127 , 128 ) * flAmplitude ;
vecVel . y + = random - > RandomInt ( - 127 , 128 ) * flAmplitude ;
vecVel . z + = random - > RandomInt ( - 127 , 128 ) * flAmplitude ;
pTemp - > SetVelocity ( vecVel ) ;
pTemp - > SetLocalOrigin ( vecPos ) ;
pTemp - > m_flSpriteScale = flSize ;
pTemp - > SetRenderMode ( kRenderGlow ) ;
pTemp - > m_nRenderFX = kRenderFxNoDissipation ;
pTemp - > tempent_renderamt = nRenderamt ;
pTemp - > SetRenderColor ( 255 , 255 , 255 ) ;
pTemp - > m_flFrame = random - > RandomInt ( 0 , flFrameCount - 1 ) ;
pTemp - > m_flFrameMax = flFrameCount - 1 ;
pTemp - > die = gpGlobals - > curtime + flLife + random - > RandomFloat ( 0 , 4 ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Attaches entity to player
// Input : client -
// modelIndex -
// zoffset -
// life -
//-----------------------------------------------------------------------------
void CTempEnts : : AttachTentToPlayer ( int client , int modelIndex , float zoffset , float life )
{
C_LocalTempEntity * pTemp ;
const model_t * pModel ;
Vector position ;
int frameCount ;
if ( client < = 0 | | client > gpGlobals - > maxClients )
{
Warning ( " Bad client in AttachTentToPlayer()! \n " ) ;
return ;
}
IClientEntity * clientClass = cl_entitylist - > GetClientEntity ( client ) ;
if ( ! clientClass )
{
Warning ( " Couldn't get IClientEntity for %i \n " , client ) ;
return ;
}
pModel = modelinfo - > GetModel ( modelIndex ) ;
if ( ! pModel )
{
Warning ( " No model %d! \n " , modelIndex ) ;
return ;
}
VectorCopy ( clientClass - > GetAbsOrigin ( ) , position ) ;
position [ 2 ] + = zoffset ;
pTemp = TempEntAllocHigh ( position , pModel ) ;
if ( ! pTemp )
{
Warning ( " No temp ent. \n " ) ;
return ;
}
pTemp - > SetRenderMode ( kRenderNormal ) ;
pTemp - > SetRenderColorA ( 255 ) ;
pTemp - > tempent_renderamt = 255 ;
pTemp - > m_nRenderFX = kRenderFxNoDissipation ;
pTemp - > clientIndex = client ;
pTemp - > tentOffset [ 0 ] = 0 ;
pTemp - > tentOffset [ 1 ] = 0 ;
pTemp - > tentOffset [ 2 ] = zoffset ;
pTemp - > die = gpGlobals - > curtime + life ;
pTemp - > flags | = FTENT_PLYRATTACHMENT | FTENT_PERSIST ;
// is the model a sprite?
if ( modelinfo - > GetModelType ( pTemp - > GetModel ( ) ) = = mod_sprite )
{
frameCount = modelinfo - > GetModelFrameCount ( pModel ) ;
pTemp - > m_flFrameMax = frameCount - 1 ;
pTemp - > flags | = FTENT_SPRANIMATE | FTENT_SPRANIMATELOOP ;
pTemp - > m_flFrameRate = 10 ;
}
else
{
// no animation support for attached clientside studio models.
pTemp - > m_flFrameMax = 0 ;
}
pTemp - > m_flFrame = 0 ;
}
//-----------------------------------------------------------------------------
// Purpose: Detach entity from player
//-----------------------------------------------------------------------------
void CTempEnts : : KillAttachedTents ( int client )
{
if ( client < = 0 | | client > gpGlobals - > maxClients )
{
Warning ( " Bad client in KillAttachedTents()! \n " ) ;
return ;
}
FOR_EACH_LL ( m_TempEnts , i )
{
C_LocalTempEntity * pTemp = m_TempEnts [ i ] ;
if ( pTemp - > flags & FTENT_PLYRATTACHMENT )
{
// this TENT is player attached.
// if it is attached to this client, set it to die instantly.
if ( pTemp - > clientIndex = = client )
{
pTemp - > die = gpGlobals - > curtime ; // good enough, it will die on next tent update.
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Create ricochet sprite
// Input : *pos -
// *pmodel -
// duration -
// scale -
//-----------------------------------------------------------------------------
void CTempEnts : : RicochetSprite ( const Vector & pos , model_t * pmodel , float duration , float scale )
{
C_LocalTempEntity * pTemp ;
pTemp = TempEntAlloc ( pos , pmodel ) ;
if ( ! pTemp )
return ;
pTemp - > SetRenderMode ( kRenderGlow ) ;
pTemp - > m_nRenderFX = kRenderFxNoDissipation ;
pTemp - > SetRenderColorA ( 200 ) ;
pTemp - > tempent_renderamt = 200 ;
pTemp - > m_flSpriteScale = scale ;
pTemp - > flags = FTENT_FADEOUT ;
pTemp - > SetVelocity ( vec3_origin ) ;
pTemp - > SetLocalOrigin ( pos ) ;
pTemp - > fadeSpeed = 8 ;
pTemp - > die = gpGlobals - > curtime ;
pTemp - > m_flFrame = 0 ;
pTemp - > SetLocalAnglesDim ( Z_INDEX , 45 * random - > RandomInt ( 0 , 7 ) ) ;
}
//-----------------------------------------------------------------------------
// Purpose: Create blood sprite
// Input : *org -
// colorindex -
// modelIndex -
// modelIndex2 -
// size -
//-----------------------------------------------------------------------------
void CTempEnts : : BloodSprite ( const Vector & org , int r , int g , int b , int a , int modelIndex , int modelIndex2 , float size )
{
const model_t * model ;
//Validate the model first
if ( modelIndex & & ( model = modelinfo - > GetModel ( modelIndex ) ) ! = NULL )
{
C_LocalTempEntity * pTemp ;
int frameCount = modelinfo - > GetModelFrameCount ( model ) ;
color32 impactcolor = { ( uint8 ) r , ( uint8 ) g , ( uint8 ) b , ( uint8 ) a } ;
//Large, single blood sprite is a high-priority tent
if ( ( pTemp = TempEntAllocHigh ( org , model ) ) ! = NULL )
{
pTemp - > SetRenderMode ( kRenderTransTexture ) ;
pTemp - > m_nRenderFX = kRenderFxClampMinScale ;
pTemp - > m_flSpriteScale = random - > RandomFloat ( size / 25 , size / 35 ) ;
pTemp - > flags = FTENT_SPRANIMATE ;
pTemp - > m_clrRender = impactcolor ;
pTemp - > tempent_renderamt = pTemp - > m_clrRender - > a ;
pTemp - > SetVelocity ( vec3_origin ) ;
pTemp - > m_flFrameRate = frameCount * 4 ; // Finish in 0.250 seconds
pTemp - > die = gpGlobals - > curtime + ( frameCount / pTemp - > m_flFrameRate ) ; // Play the whole thing Once
pTemp - > m_flFrame = 0 ;
pTemp - > m_flFrameMax = frameCount - 1 ;
pTemp - > bounceFactor = 0 ;
pTemp - > SetLocalAnglesDim ( Z_INDEX , random - > RandomInt ( 0 , 360 ) ) ;
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Create default sprite TE
// Input : *pos -
// spriteIndex -
// framerate -
// Output : C_LocalTempEntity
//-----------------------------------------------------------------------------
C_LocalTempEntity * CTempEnts : : DefaultSprite ( const Vector & pos , int spriteIndex , float framerate )
{
C_LocalTempEntity * pTemp ;
int frameCount ;
const model_t * pSprite ;
// don't spawn while paused
if ( gpGlobals - > frametime = = 0.0 )
return NULL ;
pSprite = modelinfo - > GetModel ( spriteIndex ) ;
if ( ! spriteIndex | | ! pSprite | | modelinfo - > GetModelType ( pSprite ) ! = mod_sprite )
{
DevWarning ( 1 , " No Sprite %d! \n " , spriteIndex ) ;
return NULL ;
}
frameCount = modelinfo - > GetModelFrameCount ( pSprite ) ;
pTemp = TempEntAlloc ( pos , pSprite ) ;
if ( ! pTemp )
return NULL ;
pTemp - > m_flFrameMax = frameCount - 1 ;
pTemp - > m_flSpriteScale = 1.0 ;
pTemp - > flags | = FTENT_SPRANIMATE ;
if ( framerate = = 0 )
framerate = 10 ;
pTemp - > m_flFrameRate = framerate ;
pTemp - > die = gpGlobals - > curtime + ( float ) frameCount / framerate ;
pTemp - > m_flFrame = 0 ;
pTemp - > SetLocalOrigin ( pos ) ;
return pTemp ;
}
//-----------------------------------------------------------------------------
// Purpose: Create sprite smoke
// Input : *pTemp -
// scale -
//-----------------------------------------------------------------------------
void CTempEnts : : Sprite_Smoke ( C_LocalTempEntity * pTemp , float scale )
{
if ( ! pTemp )
return ;
pTemp - > SetRenderMode ( kRenderTransAlpha ) ;
pTemp - > m_nRenderFX = kRenderFxNone ;
pTemp - > SetVelocity ( Vector ( 0 , 0 , 30 ) ) ;
int iColor = random - > RandomInt ( 20 , 35 ) ;
pTemp - > SetRenderColor ( iColor ,
iColor ,
iColor ,
255 ) ;
pTemp - > SetLocalOriginDim ( Z_INDEX , pTemp - > GetLocalOriginDim ( Z_INDEX ) + 20 ) ;
pTemp - > m_flSpriteScale = scale ;
pTemp - > flags = FTENT_WINDBLOWN ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : pos1 -
// angles -
// type -
//-----------------------------------------------------------------------------
void CTempEnts : : EjectBrass ( const Vector & pos1 , const QAngle & angles , const QAngle & gunAngles , int type )
{
if ( cl_ejectbrass . GetBool ( ) = = false )
return ;
const model_t * pModel = m_pShells [ type ] ;
if ( pModel = = NULL )
return ;
C_LocalTempEntity * pTemp = TempEntAlloc ( pos1 , pModel ) ;
if ( pTemp = = NULL )
return ;
//Keep track of shell type
if ( type = = 2 )
{
pTemp - > hitSound = BOUNCE_SHOTSHELL ;
}
else
{
pTemp - > hitSound = BOUNCE_SHELL ;
}
pTemp - > m_nBody = 0 ;
pTemp - > flags | = ( FTENT_COLLIDEWORLD | FTENT_FADEOUT | FTENT_GRAVITY | FTENT_ROTATE ) ;
pTemp - > m_vecTempEntAngVelocity [ 0 ] = random - > RandomFloat ( - 1024 , 1024 ) ;
pTemp - > m_vecTempEntAngVelocity [ 1 ] = random - > RandomFloat ( - 1024 , 1024 ) ;
pTemp - > m_vecTempEntAngVelocity [ 2 ] = random - > RandomFloat ( - 1024 , 1024 ) ;
//Face forward
pTemp - > SetAbsAngles ( gunAngles ) ;
pTemp - > SetRenderMode ( kRenderNormal ) ;
pTemp - > tempent_renderamt = 255 ; // Set this for fadeout
Vector dir ;
AngleVectors ( angles , & dir ) ;
dir * = random - > RandomFloat ( 150.0f , 200.0f ) ;
pTemp - > SetVelocity ( Vector ( dir [ 0 ] + random - > RandomFloat ( - 64 , 64 ) ,
dir [ 1 ] + random - > RandomFloat ( - 64 , 64 ) ,
dir [ 2 ] + random - > RandomFloat ( 0 , 64 ) ) ) ;
pTemp - > die = gpGlobals - > curtime + 1.0f + random - > RandomFloat ( 0.0f , 1.0f ) ; // Add an extra 0-1 secs of life
}
//-----------------------------------------------------------------------------
// Purpose: Create some simple physically simulated models
//-----------------------------------------------------------------------------
C_LocalTempEntity * CTempEnts : : SpawnTempModel ( const model_t * pModel , const Vector & vecOrigin , const QAngle & vecAngles , const Vector & vecVelocity , float flLifeTime , int iFlags )
{
Assert ( pModel ) ;
// Alloc a new tempent
C_LocalTempEntity * pTemp = TempEntAlloc ( vecOrigin , pModel ) ;
if ( ! pTemp )
return NULL ;
pTemp - > SetAbsAngles ( vecAngles ) ;
pTemp - > m_nBody = 0 ;
pTemp - > flags | = iFlags ;
pTemp - > m_vecTempEntAngVelocity [ 0 ] = random - > RandomFloat ( - 255 , 255 ) ;
pTemp - > m_vecTempEntAngVelocity [ 1 ] = random - > RandomFloat ( - 255 , 255 ) ;
pTemp - > m_vecTempEntAngVelocity [ 2 ] = random - > RandomFloat ( - 255 , 255 ) ;
pTemp - > SetRenderMode ( kRenderNormal ) ;
pTemp - > tempent_renderamt = 255 ;
pTemp - > SetVelocity ( vecVelocity ) ;
pTemp - > die = gpGlobals - > curtime + flLifeTime ;
return pTemp ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : type -
// entityIndex -
// attachmentIndex -
// firstPerson -
//-----------------------------------------------------------------------------
void CTempEnts : : MuzzleFlash ( int type , ClientEntityHandle_t hEntity , int attachmentIndex , bool firstPerson )
{
switch ( type )
{
case MUZZLEFLASH_COMBINE :
if ( firstPerson )
{
MuzzleFlash_Combine_Player ( hEntity , attachmentIndex ) ;
}
else
{
MuzzleFlash_Combine_NPC ( hEntity , attachmentIndex ) ;
}
break ;
case MUZZLEFLASH_SMG1 :
if ( firstPerson )
{
MuzzleFlash_SMG1_Player ( hEntity , attachmentIndex ) ;
}
else
{
MuzzleFlash_SMG1_NPC ( hEntity , attachmentIndex ) ;
}
break ;
case MUZZLEFLASH_PISTOL :
if ( firstPerson )
{
MuzzleFlash_Pistol_Player ( hEntity , attachmentIndex ) ;
}
else
{
MuzzleFlash_Pistol_NPC ( hEntity , attachmentIndex ) ;
}
break ;
case MUZZLEFLASH_SHOTGUN :
if ( firstPerson )
{
MuzzleFlash_Shotgun_Player ( hEntity , attachmentIndex ) ;
}
else
{
MuzzleFlash_Shotgun_NPC ( hEntity , attachmentIndex ) ;
}
break ;
case MUZZLEFLASH_357 :
if ( firstPerson )
{
MuzzleFlash_357_Player ( hEntity , attachmentIndex ) ;
}
break ;
case MUZZLEFLASH_RPG :
if ( firstPerson )
{
// MuzzleFlash_RPG_Player( hEntity, attachmentIndex );
}
else
{
MuzzleFlash_RPG_NPC ( hEntity , attachmentIndex ) ;
}
break ;
break ;
default :
{
//NOTENOTE: This means you specified an invalid muzzleflash type, check your spelling?
Assert ( 0 ) ;
}
break ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Play muzzle flash
// Input : *pos1 -
// type -
//-----------------------------------------------------------------------------
void CTempEnts : : MuzzleFlash ( const Vector & pos1 , const QAngle & angles , int type , ClientEntityHandle_t hEntity , bool firstPerson )
{
# ifdef CSTRIKE_DLL
return ;
# else
//NOTENOTE: This function is becoming obsolete as the muzzles are moved over to being local to attachments
switch ( type )
{
//
// Shotgun
//
case MUZZLEFLASH_SHOTGUN :
if ( firstPerson )
{
MuzzleFlash_Shotgun_Player ( hEntity , 1 ) ;
}
else
{
MuzzleFlash_Shotgun_NPC ( hEntity , 1 ) ;
}
break ;
// UNDONE: These need their own effects/sprites. For now use the pistol
// SMG1
case MUZZLEFLASH_SMG1 :
if ( firstPerson )
{
MuzzleFlash_SMG1_Player ( hEntity , 1 ) ;
}
else
{
MuzzleFlash_SMG1_NPC ( hEntity , 1 ) ;
}
break ;
// SMG2
case MUZZLEFLASH_SMG2 :
case MUZZLEFLASH_PISTOL :
if ( firstPerson )
{
MuzzleFlash_Pistol_Player ( hEntity , 1 ) ;
}
else
{
MuzzleFlash_Pistol_NPC ( hEntity , 1 ) ;
}
break ;
case MUZZLEFLASH_COMBINE :
if ( firstPerson )
{
//FIXME: These should go away
MuzzleFlash_Combine_Player ( hEntity , 1 ) ;
}
else
{
//FIXME: These should go away
MuzzleFlash_Combine_NPC ( hEntity , 1 ) ;
}
break ;
default :
// There's no supported muzzle flash for the type specified!
Assert ( 0 ) ;
break ;
}
# endif
}
//-----------------------------------------------------------------------------
// Purpose: Create explosion sprite
// Input : *pTemp -
// scale -
// flags -
//-----------------------------------------------------------------------------
void CTempEnts : : Sprite_Explode ( C_LocalTempEntity * pTemp , float scale , int flags )
{
if ( ! pTemp )
return ;
if ( flags & TE_EXPLFLAG_NOADDITIVE )
{
// solid sprite
pTemp - > SetRenderMode ( kRenderNormal ) ;
pTemp - > SetRenderColorA ( 255 ) ;
}
else if ( flags & TE_EXPLFLAG_DRAWALPHA )
{
// alpha sprite
pTemp - > SetRenderMode ( kRenderTransAlpha ) ;
pTemp - > SetRenderColorA ( 180 ) ;
}
else
{
// additive sprite
pTemp - > SetRenderMode ( kRenderTransAdd ) ;
pTemp - > SetRenderColorA ( 180 ) ;
}
if ( flags & TE_EXPLFLAG_ROTATE )
{
pTemp - > SetLocalAnglesDim ( Z_INDEX , random - > RandomInt ( 0 , 360 ) ) ;
}
pTemp - > m_nRenderFX = kRenderFxNone ;
pTemp - > SetVelocity ( Vector ( 0 , 0 , 8 ) ) ;
pTemp - > SetRenderColor ( 255 , 255 , 255 ) ;
pTemp - > SetLocalOriginDim ( Z_INDEX , pTemp - > GetLocalOriginDim ( Z_INDEX ) + 10 ) ;
pTemp - > m_flSpriteScale = scale ;
}
enum
{
SHELL_NONE = 0 ,
SHELL_SMALL ,
SHELL_BIG ,
SHELL_SHOTGUN ,
} ;
//-----------------------------------------------------------------------------
// Purpose: Clear existing temp entities
//-----------------------------------------------------------------------------
void CTempEnts : : Clear ( void )
{
FOR_EACH_LL ( m_TempEnts , i )
{
C_LocalTempEntity * p = m_TempEnts [ i ] ;
m_TempEntsPool . Free ( p ) ;
}
m_TempEnts . RemoveAll ( ) ;
g_BreakableHelper . Clear ( ) ;
}
C_LocalTempEntity * CTempEnts : : FindTempEntByID ( int nID , int nSubID )
{
// HACK HACK: We're using skin and hitsounds as a hacky way to store an ID and sub-ID for later identification
FOR_EACH_LL ( m_TempEnts , i )
{
C_LocalTempEntity * p = m_TempEnts [ i ] ;
if ( p & & p - > m_nSkin = = nID & & p - > hitSound = = nSubID )
{
return p ;
}
}
return NULL ;
}
//-----------------------------------------------------------------------------
// Purpose: Allocate temp entity ( normal/low priority )
// Input : *org -
// *model -
// Output : C_LocalTempEntity
//-----------------------------------------------------------------------------
C_LocalTempEntity * CTempEnts : : TempEntAlloc ( const Vector & org , const model_t * model )
{
C_LocalTempEntity * pTemp ;
if ( ! model )
{
DevWarning ( 1 , " Can't create temporary entity with NULL model! \n " ) ;
return NULL ;
}
pTemp = TempEntAlloc ( ) ;
if ( ! pTemp )
{
DevWarning ( 1 , " Overflow %d temporary ents! \n " , MAX_TEMP_ENTITIES ) ;
return NULL ;
}
m_TempEnts . AddToTail ( pTemp ) ;
pTemp - > Prepare ( model , gpGlobals - > curtime ) ;
pTemp - > priority = TENTPRIORITY_LOW ;
pTemp - > SetAbsOrigin ( org ) ;
pTemp - > m_RenderGroup = RENDER_GROUP_OTHER ;
pTemp - > AddToLeafSystem ( pTemp - > m_RenderGroup ) ;
if ( CommandLine ( ) - > CheckParm ( " -tools " ) ! = NULL )
{
# ifdef _DEBUG
static bool first = true ;
if ( first )
{
Msg ( " Currently not recording tempents, since recording them as entites causes them to be deleted as entities, even though they were allocated through the tempent pool. (crash) \n " ) ;
first = false ;
}
# endif
// ClientEntityList().AddNonNetworkableEntity( pTemp );
}
return pTemp ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : C_LocalTempEntity
//-----------------------------------------------------------------------------
C_LocalTempEntity * CTempEnts : : TempEntAlloc ( )
{
if ( m_TempEnts . Count ( ) > = MAX_TEMP_ENTITIES )
return NULL ;
C_LocalTempEntity * pTemp = m_TempEntsPool . AllocZero ( ) ;
return pTemp ;
}
void CTempEnts : : TempEntFree ( int index )
{
C_LocalTempEntity * pTemp = m_TempEnts [ index ] ;
if ( pTemp )
{
// Remove from the active list.
m_TempEnts . Remove ( index ) ;
// Cleanup its data.
pTemp - > RemoveFromLeafSystem ( ) ;
// Remove the tempent from the ClientEntityList before removing it from the pool.
if ( ( pTemp - > flags & FTENT_CLIENTSIDEPARTICLES ) )
{
// Stop the particle emission if this hasn't happened already - collision or system timing out on its own.
if ( ! pTemp - > m_bParticleCollision )
{
pTemp - > ParticleProp ( ) - > StopEmission ( ) ;
}
ClientEntityList ( ) . RemoveEntity ( pTemp - > GetRefEHandle ( ) ) ;
}
pTemp - > OnRemoveTempEntity ( ) ;
m_TempEntsPool . Free ( pTemp ) ;
}
}
// Free the first low priority tempent it finds.
bool CTempEnts : : FreeLowPriorityTempEnt ( )
{
int next = 0 ;
for ( int i = m_TempEnts . Head ( ) ; i ! = m_TempEnts . InvalidIndex ( ) ; i = next )
{
next = m_TempEnts . Next ( i ) ;
C_LocalTempEntity * pActive = m_TempEnts [ i ] ;
if ( pActive - > priority = = TENTPRIORITY_LOW )
{
TempEntFree ( i ) ;
return true ;
}
}
return false ;
}
//-----------------------------------------------------------------------------
// Purpose: Allocate a temp entity, if there are no slots, kick out a low priority
// one if possible
// Input : *org -
// *model -
// Output : C_LocalTempEntity
//-----------------------------------------------------------------------------
C_LocalTempEntity * CTempEnts : : TempEntAllocHigh ( const Vector & org , const model_t * model )
{
C_LocalTempEntity * pTemp ;
if ( ! model )
{
DevWarning ( 1 , " temporary ent model invalid \n " ) ;
return NULL ;
}
pTemp = TempEntAlloc ( ) ;
if ( ! pTemp )
{
// no temporary ents free, so find the first active low-priority temp ent
// and overwrite it.
FreeLowPriorityTempEnt ( ) ;
pTemp = TempEntAlloc ( ) ;
}
if ( ! pTemp )
{
// didn't find anything? The tent list is either full of high-priority tents
// or all tents in the list are still due to live for > 10 seconds.
DevWarning ( 1 , " Couldn't alloc a high priority TENT (max %i)! \n " , MAX_TEMP_ENTITIES ) ;
return NULL ;
}
m_TempEnts . AddToTail ( pTemp ) ;
pTemp - > Prepare ( model , gpGlobals - > curtime ) ;
pTemp - > priority = TENTPRIORITY_HIGH ;
pTemp - > SetLocalOrigin ( org ) ;
pTemp - > m_RenderGroup = RENDER_GROUP_OTHER ;
pTemp - > AddToLeafSystem ( pTemp - > m_RenderGroup ) ;
if ( CommandLine ( ) - > CheckParm ( " -tools " ) ! = NULL )
{
ClientEntityList ( ) . AddNonNetworkableEntity ( pTemp ) ;
}
return pTemp ;
}
//-----------------------------------------------------------------------------
// Purpose: Play sound when temp ent collides with something
// Input : *pTemp -
// damp -
//-----------------------------------------------------------------------------
void CTempEnts : : PlaySound ( C_LocalTempEntity * pTemp , float damp )
{
const char * soundname = NULL ;
float fvol ;
bool isshellcasing = false ;
int zvel ;
switch ( pTemp - > hitSound )
{
default :
return ; // null sound
case BOUNCE_GLASS :
{
soundname = " Bounce.Glass " ;
}
break ;
case BOUNCE_METAL :
{
soundname = " Bounce.Metal " ;
}
break ;
case BOUNCE_FLESH :
{
soundname = " Bounce.Flesh " ;
}
break ;
case BOUNCE_WOOD :
{
soundname = " Bounce.Wood " ;
}
break ;
case BOUNCE_SHRAP :
{
soundname = " Bounce.Shrapnel " ;
}
break ;
case BOUNCE_SHOTSHELL :
{
soundname = " Bounce.ShotgunShell " ;
isshellcasing = true ; // shell casings have different playback parameters
}
break ;
case BOUNCE_SHELL :
{
soundname = " Bounce.Shell " ;
isshellcasing = true ; // shell casings have different playback parameters
}
break ;
case BOUNCE_CONCRETE :
{
soundname = " Bounce.Concrete " ;
}
break ;
# ifdef CSTRIKE_DLL
case TE_PISTOL_SHELL :
{
soundname = " Bounce.PistolShell " ;
}
break ;
case TE_RIFLE_SHELL :
{
soundname = " Bounce.RifleShell " ;
}
break ;
case TE_SHOTGUN_SHELL :
{
soundname = " Bounce.ShotgunShell " ;
}
break ;
# endif
}
zvel = abs ( pTemp - > GetVelocity ( ) [ 2 ] ) ;
// only play one out of every n
if ( isshellcasing )
{
// play first bounce, then 1 out of 3
if ( zvel < 200 & & random - > RandomInt ( 0 , 3 ) )
return ;
}
else
{
if ( random - > RandomInt ( 0 , 5 ) )
return ;
}
CSoundParameters params ;
if ( ! C_BaseEntity : : GetParametersForSound ( soundname , params , NULL ) )
return ;
fvol = params . volume ;
if ( damp > 0.0 )
{
int pitch ;
if ( isshellcasing )
{
fvol * = MIN ( 1.0 , ( ( float ) zvel ) / 350.0 ) ;
}
else
{
fvol * = MIN ( 1.0 , ( ( float ) zvel ) / 450.0 ) ;
}
if ( ! random - > RandomInt ( 0 , 3 ) & & ! isshellcasing )
{
pitch = random - > RandomInt ( params . pitchlow , params . pitchhigh ) ;
}
else
{
pitch = params . pitch ;
}
CLocalPlayerFilter filter ;
EmitSound_t ep ;
ep . m_nChannel = params . channel ;
ep . m_pSoundName = params . soundname ;
ep . m_flVolume = fvol ;
ep . m_SoundLevel = params . soundlevel ;
ep . m_nPitch = pitch ;
ep . m_pOrigin = & pTemp - > GetAbsOrigin ( ) ;
C_BaseEntity : : EmitSound ( filter , SOUND_FROM_WORLD , ep ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Add temp entity to visible entities list of it's in PVS
// Input : *pEntity -
// Output : int
//-----------------------------------------------------------------------------
int CTempEnts : : AddVisibleTempEntity ( C_LocalTempEntity * pEntity )
{
int i ;
Vector mins , maxs ;
Vector model_mins , model_maxs ;
if ( ! pEntity - > GetModel ( ) )
return 0 ;
modelinfo - > GetModelBounds ( pEntity - > GetModel ( ) , model_mins , model_maxs ) ;
for ( i = 0 ; i < 3 ; i + + )
{
mins [ i ] = pEntity - > GetAbsOrigin ( ) [ i ] + model_mins [ i ] ;
maxs [ i ] = pEntity - > GetAbsOrigin ( ) [ i ] + model_maxs [ i ] ;
}
// FIXME: Vis isn't setup by the time we get here, so this call fails if
// you try to add a tempent before the first frame is drawn, and it's
// one frame behind the rest of the time. Fix this.
// does the box intersect a visible leaf?
//if ( engine->IsBoxInViewCluster( mins, maxs ) )
{
// Temporary entities have no corresponding element in cl_entitylist
pEntity - > index = - 1 ;
// Add to list
if ( pEntity - > m_RenderGroup = = RENDER_GROUP_OTHER )
{
pEntity - > AddToLeafSystem ( ) ;
}
else
{
pEntity - > AddToLeafSystem ( pEntity - > m_RenderGroup ) ;
}
return 1 ;
}
return 0 ;
}
//-----------------------------------------------------------------------------
// Purpose: Runs Temp Ent simulation routines
//-----------------------------------------------------------------------------
void CTempEnts : : Update ( void )
{
VPROF_ ( " CTempEnts::Update " , 1 , VPROF_BUDGETGROUP_CLIENT_SIM , false , BUDGETFLAG_CLIENT ) ;
static int gTempEntFrame = 0 ;
float frametime ;
// Don't simulate while loading
if ( ( m_TempEnts . Count ( ) = = 0 ) | | ! engine - > IsInGame ( ) )
{
return ;
}
// !!!BUGBUG -- This needs to be time based
gTempEntFrame = ( gTempEntFrame + 1 ) & 31 ;
frametime = gpGlobals - > frametime ;
// in order to have tents collide with players, we have to run the player prediction code so
// that the client has the player list. We run this code once when we detect any COLLIDEALL
// tent, then set this BOOL to true so the code doesn't get run again if there's more than
// one COLLIDEALL ent for this update. (often are).
// !!! Don't simulate while paused.... This is sort of a hack, revisit.
if ( frametime = = 0 )
{
FOR_EACH_LL ( m_TempEnts , i )
{
C_LocalTempEntity * current = m_TempEnts [ i ] ;
AddVisibleTempEntity ( current ) ;
}
}
else
{
int next = 0 ;
for ( int i = m_TempEnts . Head ( ) ; i ! = m_TempEnts . InvalidIndex ( ) ; i = next )
{
next = m_TempEnts . Next ( i ) ;
C_LocalTempEntity * current = m_TempEnts [ i ] ;
// Kill it
if ( ! current - > IsActive ( ) | | ! current - > Frame ( frametime , gTempEntFrame ) )
{
TempEntFree ( i ) ;
}
else
{
// Cull to PVS (not frustum cull, just PVS)
if ( ! AddVisibleTempEntity ( current ) )
{
if ( ! ( current - > flags & FTENT_PERSIST ) )
{
// If we can't draw it this frame, just dump it.
current - > die = gpGlobals - > curtime ;
// Don't fade out, just die
current - > flags & = ~ FTENT_FADEOUT ;
TempEntFree ( i ) ;
}
}
}
}
}
}
// Recache tempents which might have been flushed
void CTempEnts : : LevelInit ( )
{
# ifndef TF_CLIENT_DLL
m_pSpriteMuzzleFlash [ 0 ] = ( model_t * ) engine - > LoadModel ( " sprites/ar2_muzzle1.vmt " ) ;
m_pSpriteMuzzleFlash [ 1 ] = ( model_t * ) engine - > LoadModel ( " sprites/muzzleflash4.vmt " ) ;
m_pSpriteMuzzleFlash [ 2 ] = ( model_t * ) engine - > LoadModel ( " sprites/muzzleflash4.vmt " ) ;
m_pSpriteAR2Flash [ 0 ] = ( model_t * ) engine - > LoadModel ( " sprites/ar2_muzzle1b.vmt " ) ;
m_pSpriteAR2Flash [ 1 ] = ( model_t * ) engine - > LoadModel ( " sprites/ar2_muzzle2b.vmt " ) ;
m_pSpriteAR2Flash [ 2 ] = ( model_t * ) engine - > LoadModel ( " sprites/ar2_muzzle3b.vmt " ) ;
m_pSpriteAR2Flash [ 3 ] = ( model_t * ) engine - > LoadModel ( " sprites/ar2_muzzle4b.vmt " ) ;
m_pSpriteCombineFlash [ 0 ] = ( model_t * ) engine - > LoadModel ( " effects/combinemuzzle1.vmt " ) ;
m_pSpriteCombineFlash [ 1 ] = ( model_t * ) engine - > LoadModel ( " effects/combinemuzzle2.vmt " ) ;
m_pShells [ 0 ] = ( model_t * ) engine - > LoadModel ( " models/weapons/shell.mdl " ) ;
m_pShells [ 1 ] = ( model_t * ) engine - > LoadModel ( " models/weapons/rifleshell.mdl " ) ;
m_pShells [ 2 ] = ( model_t * ) engine - > LoadModel ( " models/weapons/shotgun_shell.mdl " ) ;
# endif
# if defined( HL1_CLIENT_DLL )
m_pHL1Shell = ( model_t * ) engine - > LoadModel ( " models/shell.mdl " ) ;
m_pHL1ShotgunShell = ( model_t * ) engine - > LoadModel ( " models/shotgunshell.mdl " ) ;
# endif
# if defined( CSTRIKE_DLL ) || defined ( SDK_DLL )
m_pCS_9MMShell = ( model_t * ) engine - > LoadModel ( " models/Shells/shell_9mm.mdl " ) ;
m_pCS_57Shell = ( model_t * ) engine - > LoadModel ( " models/Shells/shell_57.mdl " ) ;
m_pCS_12GaugeShell = ( model_t * ) engine - > LoadModel ( " models/Shells/shell_12gauge.mdl " ) ;
m_pCS_556Shell = ( model_t * ) engine - > LoadModel ( " models/Shells/shell_556.mdl " ) ;
m_pCS_762NATOShell = ( model_t * ) engine - > LoadModel ( " models/Shells/shell_762nato.mdl " ) ;
m_pCS_338MAGShell = ( model_t * ) engine - > LoadModel ( " models/Shells/shell_338mag.mdl " ) ;
# endif
}
//-----------------------------------------------------------------------------
// Purpose: Initialize TE system
//-----------------------------------------------------------------------------
void CTempEnts : : Init ( void )
{
m_pSpriteMuzzleFlash [ 0 ] = NULL ;
m_pSpriteMuzzleFlash [ 1 ] = NULL ;
m_pSpriteMuzzleFlash [ 2 ] = NULL ;
m_pSpriteAR2Flash [ 0 ] = NULL ;
m_pSpriteAR2Flash [ 1 ] = NULL ;
m_pSpriteAR2Flash [ 2 ] = NULL ;
m_pSpriteAR2Flash [ 3 ] = NULL ;
m_pSpriteCombineFlash [ 0 ] = NULL ;
m_pSpriteCombineFlash [ 1 ] = NULL ;
m_pShells [ 0 ] = NULL ;
m_pShells [ 1 ] = NULL ;
m_pShells [ 2 ] = NULL ;
# if defined( HL1_CLIENT_DLL )
m_pHL1Shell = NULL ;
m_pHL1ShotgunShell = NULL ;
# endif
# if defined( CSTRIKE_DLL ) || defined ( SDK_DLL )
m_pCS_9MMShell = NULL ;
m_pCS_57Shell = NULL ;
m_pCS_12GaugeShell = NULL ;
m_pCS_556Shell = NULL ;
m_pCS_762NATOShell = NULL ;
m_pCS_338MAGShell = NULL ;
# endif
// Clear out lists to start
Clear ( ) ;
}
void CTempEnts : : LevelShutdown ( )
{
// Free all active tempents.
Clear ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTempEnts : : Shutdown ( )
{
LevelShutdown ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose: Cache off all material references
// Input : *pEmitter - Emitter used for material lookup
//-----------------------------------------------------------------------------
inline void CTempEnts : : CacheMuzzleFlashes ( void )
{
int i ;
for ( i = 0 ; i < 4 ; i + + )
{
if ( m_Material_MuzzleFlash_Player [ i ] = = NULL )
{
m_Material_MuzzleFlash_Player [ i ] = ParticleMgr ( ) - > GetPMaterial ( VarArgs ( " effects/muzzleflash%d_noz " , i + 1 ) ) ;
}
}
for ( i = 0 ; i < 4 ; i + + )
{
if ( m_Material_MuzzleFlash_NPC [ i ] = = NULL )
{
m_Material_MuzzleFlash_NPC [ i ] = ParticleMgr ( ) - > GetPMaterial ( VarArgs ( " effects/muzzleflash%d " , i + 1 ) ) ;
}
}
for ( i = 0 ; i < 2 ; i + + )
{
if ( m_Material_Combine_MuzzleFlash_Player [ i ] = = NULL )
{
m_Material_Combine_MuzzleFlash_Player [ i ] = ParticleMgr ( ) - > GetPMaterial ( VarArgs ( " effects/combinemuzzle%d_noz " , i + 1 ) ) ;
}
}
for ( i = 0 ; i < 2 ; i + + )
{
if ( m_Material_Combine_MuzzleFlash_NPC [ i ] = = NULL )
{
m_Material_Combine_MuzzleFlash_NPC [ i ] = ParticleMgr ( ) - > GetPMaterial ( VarArgs ( " effects/combinemuzzle%d " , i + 1 ) ) ;
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : entityIndex -
// attachmentIndex -
//-----------------------------------------------------------------------------
void CTempEnts : : MuzzleFlash_Combine_Player ( ClientEntityHandle_t hEntity , int attachmentIndex )
{
VPROF_BUDGET ( " MuzzleFlash_Combine_Player " , VPROF_BUDGETGROUP_PARTICLE_RENDERING ) ;
CSmartPtr < CLocalSpaceEmitter > pSimple = CLocalSpaceEmitter : : Create ( " MuzzleFlash " , hEntity , attachmentIndex , FLE_VIEWMODEL ) ;
CacheMuzzleFlashes ( ) ;
SimpleParticle * pParticle ;
Vector forward ( 1 , 0 , 0 ) , offset ; //NOTENOTE: All coords are in local space
float flScale = random - > RandomFloat ( 2.0f , 2.25f ) ;
pSimple - > SetDrawBeforeViewModel ( true ) ;
// Flash
for ( int i = 1 ; i < 6 ; i + + )
{
offset = ( forward * ( i * 8.0f * flScale ) ) ;
pParticle = ( SimpleParticle * ) pSimple - > AddParticle ( sizeof ( SimpleParticle ) , m_Material_Combine_MuzzleFlash_Player [ random - > RandomInt ( 0 , 1 ) ] , offset ) ;
if ( pParticle = = NULL )
return ;
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = 0.025f ;
pParticle - > m_vecVelocity . Init ( ) ;
pParticle - > m_uchColor [ 0 ] = 255 ;
pParticle - > m_uchColor [ 1 ] = 255 ;
pParticle - > m_uchColor [ 2 ] = 200 + random - > RandomInt ( 0 , 55 ) ;
pParticle - > m_uchStartAlpha = 255 ;
pParticle - > m_uchEndAlpha = 255 ;
pParticle - > m_uchStartSize = ( ( random - > RandomFloat ( 6.0f , 8.0f ) * ( 12 - ( i ) ) / 12 ) * flScale ) ;
pParticle - > m_uchEndSize = pParticle - > m_uchStartSize ;
pParticle - > m_flRoll = random - > RandomInt ( 0 , 360 ) ;
pParticle - > m_flRollDelta = 0.0f ;
}
// Tack on the smoke
pParticle = ( SimpleParticle * ) pSimple - > AddParticle ( sizeof ( SimpleParticle ) , m_Material_Combine_MuzzleFlash_Player [ random - > RandomInt ( 0 , 1 ) ] , vec3_origin ) ;
if ( pParticle = = NULL )
return ;
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = 0.025f ;
pParticle - > m_vecVelocity . Init ( ) ;
pParticle - > m_uchColor [ 0 ] = 255 ;
pParticle - > m_uchColor [ 1 ] = 255 ;
pParticle - > m_uchColor [ 2 ] = 255 ;
pParticle - > m_uchStartAlpha = random - > RandomInt ( 64 , 128 ) ;
pParticle - > m_uchEndAlpha = 32 ;
pParticle - > m_uchStartSize = random - > RandomFloat ( 10.0f , 16.0f ) ;
pParticle - > m_uchEndSize = pParticle - > m_uchStartSize ;
pParticle - > m_flRoll = random - > RandomInt ( 0 , 360 ) ;
pParticle - > m_flRollDelta = 0.0f ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : &origin -
// &angles -
// entityIndex -
//-----------------------------------------------------------------------------
void CTempEnts : : MuzzleFlash_Combine_NPC ( ClientEntityHandle_t hEntity , int attachmentIndex )
{
VPROF_BUDGET ( " MuzzleFlash_Combine_NPC " , VPROF_BUDGETGROUP_PARTICLE_RENDERING ) ;
// If the material isn't available, let's not do anything.
if ( g_Mat_Combine_Muzzleflash [ 0 ] = = NULL )
{
return ;
}
CSmartPtr < CLocalSpaceEmitter > pSimple = CLocalSpaceEmitter : : Create ( " MuzzleFlash_Combine_NPC " , hEntity , attachmentIndex ) ;
SimpleParticle * pParticle ;
Vector forward ( 1 , 0 , 0 ) , offset ; //NOTENOTE: All coords are in local space
float flScale = random - > RandomFloat ( 1.0f , 1.5f ) ;
float burstSpeed = random - > RandomFloat ( 50.0f , 150.0f ) ;
# define FRONT_LENGTH 6
// Front flash
for ( int i = 1 ; i < FRONT_LENGTH ; i + + )
{
offset = ( forward * ( i * 2.0f * flScale ) ) ;
pParticle = ( SimpleParticle * ) pSimple - > AddParticle ( sizeof ( SimpleParticle ) , g_Mat_Combine_Muzzleflash [ random - > RandomInt ( 0 , 1 ) ] , offset ) ;
if ( pParticle = = NULL )
return ;
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = 0.1f ;
pParticle - > m_vecVelocity = forward * burstSpeed ;
pParticle - > m_uchColor [ 0 ] = 255 ;
pParticle - > m_uchColor [ 1 ] = 255 ;
pParticle - > m_uchColor [ 2 ] = 255 ;
pParticle - > m_uchStartAlpha = 255.0f ;
pParticle - > m_uchEndAlpha = 0 ;
pParticle - > m_uchStartSize = ( ( random - > RandomFloat ( 6.0f , 8.0f ) * ( FRONT_LENGTH * 1.25f - ( i ) ) / ( FRONT_LENGTH ) ) * flScale ) ;
pParticle - > m_uchEndSize = pParticle - > m_uchStartSize ;
pParticle - > m_flRoll = random - > RandomInt ( 0 , 360 ) ;
pParticle - > m_flRollDelta = 0.0f ;
}
Vector right ( 0 , 1 , 0 ) , up ( 0 , 0 , 1 ) ;
Vector dir = right - up ;
# define SIDE_LENGTH 6
burstSpeed = random - > RandomFloat ( 50.0f , 150.0f ) ;
// Diagonal flash
for ( int i = 1 ; i < SIDE_LENGTH ; i + + )
{
offset = ( dir * ( i * flScale ) ) ;
pParticle = ( SimpleParticle * ) pSimple - > AddParticle ( sizeof ( SimpleParticle ) , g_Mat_Combine_Muzzleflash [ random - > RandomInt ( 0 , 1 ) ] , offset ) ;
if ( pParticle = = NULL )
return ;
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = 0.2f ;
pParticle - > m_vecVelocity = dir * burstSpeed * 0.25f ;
pParticle - > m_uchColor [ 0 ] = 255 ;
pParticle - > m_uchColor [ 1 ] = 255 ;
pParticle - > m_uchColor [ 2 ] = 255 ;
pParticle - > m_uchStartAlpha = 255 ;
pParticle - > m_uchEndAlpha = 0 ;
pParticle - > m_uchStartSize = ( ( random - > RandomFloat ( 2.0f , 4.0f ) * ( SIDE_LENGTH - ( i ) ) / ( SIDE_LENGTH * 0.5f ) ) * flScale ) ;
pParticle - > m_uchEndSize = pParticle - > m_uchStartSize ;
pParticle - > m_flRoll = random - > RandomInt ( 0 , 360 ) ;
pParticle - > m_flRollDelta = 0.0f ;
}
dir = right + up ;
burstSpeed = random - > RandomFloat ( 50.0f , 150.0f ) ;
// Diagonal flash
for ( int i = 1 ; i < SIDE_LENGTH ; i + + )
{
offset = ( - dir * ( i * flScale ) ) ;
pParticle = ( SimpleParticle * ) pSimple - > AddParticle ( sizeof ( SimpleParticle ) , g_Mat_Combine_Muzzleflash [ random - > RandomInt ( 0 , 1 ) ] , offset ) ;
if ( pParticle = = NULL )
return ;
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = 0.2f ;
pParticle - > m_vecVelocity = dir * - burstSpeed * 0.25f ;
pParticle - > m_uchColor [ 0 ] = 255 ;
pParticle - > m_uchColor [ 1 ] = 255 ;
pParticle - > m_uchColor [ 2 ] = 255 ;
pParticle - > m_uchStartAlpha = 255 ;
pParticle - > m_uchEndAlpha = 0 ;
pParticle - > m_uchStartSize = ( ( random - > RandomFloat ( 2.0f , 4.0f ) * ( SIDE_LENGTH - ( i ) ) / ( SIDE_LENGTH * 0.5f ) ) * flScale ) ;
pParticle - > m_uchEndSize = pParticle - > m_uchStartSize ;
pParticle - > m_flRoll = random - > RandomInt ( 0 , 360 ) ;
pParticle - > m_flRollDelta = 0.0f ;
}
dir = up ;
burstSpeed = random - > RandomFloat ( 50.0f , 150.0f ) ;
// Top flash
for ( int i = 1 ; i < SIDE_LENGTH ; i + + )
{
offset = ( dir * ( i * flScale ) ) ;
pParticle = ( SimpleParticle * ) pSimple - > AddParticle ( sizeof ( SimpleParticle ) , g_Mat_Combine_Muzzleflash [ random - > RandomInt ( 0 , 1 ) ] , offset ) ;
if ( pParticle = = NULL )
return ;
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = 0.2f ;
pParticle - > m_vecVelocity = dir * burstSpeed * 0.25f ;
pParticle - > m_uchColor [ 0 ] = 255 ;
pParticle - > m_uchColor [ 1 ] = 255 ;
pParticle - > m_uchColor [ 2 ] = 255 ;
pParticle - > m_uchStartAlpha = 255 ;
pParticle - > m_uchEndAlpha = 0 ;
pParticle - > m_uchStartSize = ( ( random - > RandomFloat ( 2.0f , 4.0f ) * ( SIDE_LENGTH - ( i ) ) / ( SIDE_LENGTH * 0.5f ) ) * flScale ) ;
pParticle - > m_uchEndSize = pParticle - > m_uchStartSize ;
pParticle - > m_flRoll = random - > RandomInt ( 0 , 360 ) ;
pParticle - > m_flRollDelta = 0.0f ;
}
pParticle = ( SimpleParticle * ) pSimple - > AddParticle ( sizeof ( SimpleParticle ) , g_Mat_Combine_Muzzleflash [ 2 ] , vec3_origin ) ;
if ( pParticle = = NULL )
return ;
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = random - > RandomFloat ( 0.3f , 0.4f ) ;
pParticle - > m_vecVelocity . Init ( ) ;
pParticle - > m_uchColor [ 0 ] = 255 ;
pParticle - > m_uchColor [ 1 ] = 255 ;
pParticle - > m_uchColor [ 2 ] = 255 ;
pParticle - > m_uchStartAlpha = 255 ;
pParticle - > m_uchEndAlpha = 0 ;
pParticle - > m_uchStartSize = flScale * random - > RandomFloat ( 12.0f , 16.0f ) ;
pParticle - > m_uchEndSize = 0.0f ;
pParticle - > m_flRoll = random - > RandomInt ( 0 , 360 ) ;
pParticle - > m_flRollDelta = 0.0f ;
matrix3x4_t matAttachment ;
Vector origin ;
// Grab the origin out of the transform for the attachment
if ( FX_GetAttachmentTransform ( hEntity , attachmentIndex , matAttachment ) )
{
origin . x = matAttachment [ 0 ] [ 3 ] ;
origin . y = matAttachment [ 1 ] [ 3 ] ;
origin . z = matAttachment [ 2 ] [ 3 ] ;
}
else
{
//NOTENOTE: If you're here, you've specified an entity or an attachment that is invalid
Assert ( 0 ) ;
return ;
}
if ( muzzleflash_light . GetBool ( ) )
{
C_BaseEntity * pEnt = ClientEntityList ( ) . GetBaseEntityFromHandle ( hEntity ) ;
if ( pEnt )
{
dlight_t * el = effects - > CL_AllocElight ( LIGHT_INDEX_MUZZLEFLASH + pEnt - > entindex ( ) ) ;
el - > origin = origin ;
el - > color . r = 64 ;
el - > color . g = 128 ;
el - > color . b = 255 ;
el - > color . exponent = 5 ;
el - > radius = random - > RandomInt ( 32 , 128 ) ;
el - > decay = el - > radius / 0.05f ;
el - > die = gpGlobals - > curtime + 0.05f ;
}
}
}
//==================================================
// Purpose:
// Input:
//==================================================
void CTempEnts : : MuzzleFlash_AR2_NPC ( const Vector & origin , const QAngle & angles , ClientEntityHandle_t hEntity )
{
//Draw the cloud of fire
FX_MuzzleEffect ( origin , angles , 1.0f , hEntity ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTempEnts : : MuzzleFlash_SMG1_NPC ( ClientEntityHandle_t hEntity , int attachmentIndex )
{
//Draw the cloud of fire
FX_MuzzleEffectAttached ( 1.0f , hEntity , attachmentIndex , NULL , true ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CTempEnts : : MuzzleFlash_SMG1_Player ( ClientEntityHandle_t hEntity , int attachmentIndex )
{
VPROF_BUDGET ( " MuzzleFlash_SMG1_Player " , VPROF_BUDGETGROUP_PARTICLE_RENDERING ) ;
CSmartPtr < CLocalSpaceEmitter > pSimple = CLocalSpaceEmitter : : Create ( " MuzzleFlash_SMG1_Player " , hEntity , attachmentIndex , FLE_VIEWMODEL ) ;
CacheMuzzleFlashes ( ) ;
SimpleParticle * pParticle ;
Vector forward ( 1 , 0 , 0 ) , offset ; //NOTENOTE: All coords are in local space
float flScale = random - > RandomFloat ( 1.25f , 1.5f ) ;
pSimple - > SetDrawBeforeViewModel ( true ) ;
// Flash
for ( int i = 1 ; i < 6 ; i + + )
{
offset = ( forward * ( i * 8.0f * flScale ) ) ;
pParticle = ( SimpleParticle * ) pSimple - > AddParticle ( sizeof ( SimpleParticle ) , m_Material_MuzzleFlash_Player [ random - > RandomInt ( 0 , 3 ) ] , offset ) ;
if ( pParticle = = NULL )
return ;
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = 0.025f ;
pParticle - > m_vecVelocity . Init ( ) ;
pParticle - > m_uchColor [ 0 ] = 255 ;
pParticle - > m_uchColor [ 1 ] = 255 ;
pParticle - > m_uchColor [ 2 ] = 200 + random - > RandomInt ( 0 , 55 ) ;
pParticle - > m_uchStartAlpha = 255 ;
pParticle - > m_uchEndAlpha = 255 ;
pParticle - > m_uchStartSize = ( ( random - > RandomFloat ( 6.0f , 8.0f ) * ( 8 - ( i ) ) / 6 ) * flScale ) ;
pParticle - > m_uchEndSize = pParticle - > m_uchStartSize ;
pParticle - > m_flRoll = random - > RandomInt ( 0 , 360 ) ;
pParticle - > m_flRollDelta = 0.0f ;
}
}
//==================================================
// Purpose:
// Input:
//==================================================
void CTempEnts : : MuzzleFlash_Shotgun_Player ( ClientEntityHandle_t hEntity , int attachmentIndex )
{
VPROF_BUDGET ( " MuzzleFlash_Shotgun_Player " , VPROF_BUDGETGROUP_PARTICLE_RENDERING ) ;
CSmartPtr < CSimpleEmitter > pSimple = CSimpleEmitter : : Create ( " MuzzleFlash_Shotgun_Player " ) ;
pSimple - > SetDrawBeforeViewModel ( true ) ;
CacheMuzzleFlashes ( ) ;
Vector origin ;
QAngle angles ;
// Get our attachment's transformation matrix
FX_GetAttachmentTransform ( hEntity , attachmentIndex , & origin , & angles ) ;
pSimple - > GetBinding ( ) . SetBBox ( origin - Vector ( 4 , 4 , 4 ) , origin + Vector ( 4 , 4 , 4 ) ) ;
Vector forward ;
AngleVectors ( angles , & forward , NULL , NULL ) ;
SimpleParticle * pParticle ;
Vector offset ;
float flScale = random - > RandomFloat ( 1.25f , 1.5f ) ;
// Flash
for ( int i = 1 ; i < 6 ; i + + )
{
offset = origin + ( forward * ( i * 8.0f * flScale ) ) ;
pParticle = ( SimpleParticle * ) pSimple - > AddParticle ( sizeof ( SimpleParticle ) , m_Material_MuzzleFlash_Player [ random - > RandomInt ( 0 , 3 ) ] , offset ) ;
if ( pParticle = = NULL )
return ;
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = 0.0001f ;
pParticle - > m_vecVelocity . Init ( ) ;
pParticle - > m_uchColor [ 0 ] = 255 ;
pParticle - > m_uchColor [ 1 ] = 255 ;
pParticle - > m_uchColor [ 2 ] = 200 + random - > RandomInt ( 0 , 55 ) ;
pParticle - > m_uchStartAlpha = 255 ;
pParticle - > m_uchEndAlpha = 255 ;
pParticle - > m_uchStartSize = ( ( random - > RandomFloat ( 6.0f , 8.0f ) * ( 8 - ( i ) ) / 6 ) * flScale ) ;
pParticle - > m_uchEndSize = pParticle - > m_uchStartSize ;
pParticle - > m_flRoll = random - > RandomInt ( 0 , 360 ) ;
pParticle - > m_flRollDelta = 0.0f ;
}
}
//==================================================
// Purpose:
// Input:
//==================================================
void CTempEnts : : MuzzleFlash_Shotgun_NPC ( ClientEntityHandle_t hEntity , int attachmentIndex )
{
//Draw the cloud of fire
FX_MuzzleEffectAttached ( 0.75f , hEntity , attachmentIndex ) ;
// If the material isn't available, let's not do anything else.
if ( g_Mat_SMG_Muzzleflash [ 0 ] = = NULL )
{
return ;
}
QAngle angles ;
Vector forward ;
int i ;
// Setup the origin.
Vector origin ;
IClientRenderable * pRenderable = ClientEntityList ( ) . GetClientRenderableFromHandle ( hEntity ) ;
if ( ! pRenderable )
return ;
pRenderable - > GetAttachment ( attachmentIndex , origin , angles ) ;
AngleVectors ( angles , & forward ) ;
//Embers less often
if ( random - > RandomInt ( 0 , 2 ) = = 0 )
{
//Embers
CSmartPtr < CEmberEffect > pEmbers = CEmberEffect : : Create ( " muzzle_embers " ) ;
pEmbers - > SetSortOrigin ( origin ) ;
SimpleParticle * pParticle ;
int numEmbers = random - > RandomInt ( 0 , 4 ) ;
for ( int i = 0 ; i < numEmbers ; i + + )
{
pParticle = ( SimpleParticle * ) pEmbers - > AddParticle ( sizeof ( SimpleParticle ) , g_Mat_SMG_Muzzleflash [ 0 ] , origin ) ;
if ( pParticle = = NULL )
return ;
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = random - > RandomFloat ( 0.2f , 0.4f ) ;
pParticle - > m_vecVelocity . Random ( - 0.05f , 0.05f ) ;
pParticle - > m_vecVelocity + = forward ;
VectorNormalize ( pParticle - > m_vecVelocity ) ;
pParticle - > m_vecVelocity * = random - > RandomFloat ( 64.0f , 256.0f ) ;
pParticle - > m_uchColor [ 0 ] = 255 ;
pParticle - > m_uchColor [ 1 ] = 128 ;
pParticle - > m_uchColor [ 2 ] = 64 ;
pParticle - > m_uchStartAlpha = 255 ;
pParticle - > m_uchEndAlpha = 0 ;
pParticle - > m_uchStartSize = 1 ;
pParticle - > m_uchEndSize = 0 ;
pParticle - > m_flRoll = 0 ;
pParticle - > m_flRollDelta = 0 ;
}
}
//
// Trails
//
CSmartPtr < CTrailParticles > pTrails = CTrailParticles : : Create ( " MuzzleFlash_Shotgun_NPC " ) ;
pTrails - > SetSortOrigin ( origin ) ;
TrailParticle * pTrailParticle ;
pTrails - > SetFlag ( bitsPARTICLE_TRAIL_FADE ) ;
pTrails - > m_ParticleCollision . SetGravity ( 0.0f ) ;
int numEmbers = random - > RandomInt ( 4 , 8 ) ;
for ( i = 0 ; i < numEmbers ; i + + )
{
pTrailParticle = ( TrailParticle * ) pTrails - > AddParticle ( sizeof ( TrailParticle ) , g_Mat_SMG_Muzzleflash [ 0 ] , origin ) ;
if ( pTrailParticle = = NULL )
return ;
pTrailParticle - > m_flLifetime = 0.0f ;
pTrailParticle - > m_flDieTime = random - > RandomFloat ( 0.1f , 0.2f ) ;
float spread = 0.05f ;
pTrailParticle - > m_vecVelocity . Random ( - spread , spread ) ;
pTrailParticle - > m_vecVelocity + = forward ;
VectorNormalize ( pTrailParticle - > m_vecVelocity ) ;
VectorNormalize ( forward ) ;
float dot = forward . Dot ( pTrailParticle - > m_vecVelocity ) ;
dot = ( 1.0f - fabs ( dot ) ) / spread ;
pTrailParticle - > m_vecVelocity * = ( random - > RandomFloat ( 256.0f , 1024.0f ) * ( 1.0f - dot ) ) ;
Color32Init ( pTrailParticle - > m_color , 255 , 242 , 191 , 255 ) ;
pTrailParticle - > m_flLength = 0.05f ;
pTrailParticle - > m_flWidth = random - > RandomFloat ( 0.25f , 0.5f ) ;
}
}
//==================================================
// Purpose:
//==================================================
void CTempEnts : : MuzzleFlash_357_Player ( ClientEntityHandle_t hEntity , int attachmentIndex )
{
VPROF_BUDGET ( " MuzzleFlash_357_Player " , VPROF_BUDGETGROUP_PARTICLE_RENDERING ) ;
CSmartPtr < CSimpleEmitter > pSimple = CSimpleEmitter : : Create ( " MuzzleFlash_357_Player " ) ;
pSimple - > SetDrawBeforeViewModel ( true ) ;
CacheMuzzleFlashes ( ) ;
Vector origin ;
QAngle angles ;
// Get our attachment's transformation matrix
FX_GetAttachmentTransform ( hEntity , attachmentIndex , & origin , & angles ) ;
pSimple - > GetBinding ( ) . SetBBox ( origin - Vector ( 4 , 4 , 4 ) , origin + Vector ( 4 , 4 , 4 ) ) ;
Vector forward ;
AngleVectors ( angles , & forward , NULL , NULL ) ;
SimpleParticle * pParticle ;
Vector offset ;
// Smoke
offset = origin + forward * 8.0f ;
pParticle = ( SimpleParticle * ) pSimple - > AddParticle ( sizeof ( SimpleParticle ) , g_Mat_DustPuff [ 0 ] , offset ) ;
if ( pParticle = = NULL )
return ;
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = random - > RandomFloat ( 0.5f , 1.0f ) ;
pParticle - > m_vecVelocity . Init ( ) ;
pParticle - > m_vecVelocity = forward * random - > RandomFloat ( 8.0f , 64.0f ) ;
pParticle - > m_vecVelocity [ 2 ] + = random - > RandomFloat ( 4.0f , 16.0f ) ;
int color = random - > RandomInt ( 200 , 255 ) ;
pParticle - > m_uchColor [ 0 ] = color ;
pParticle - > m_uchColor [ 1 ] = color ;
pParticle - > m_uchColor [ 2 ] = color ;
pParticle - > m_uchStartAlpha = random - > RandomInt ( 64 , 128 ) ;
pParticle - > m_uchEndAlpha = 0 ;
pParticle - > m_uchStartSize = random - > RandomInt ( 2 , 4 ) ;
pParticle - > m_uchEndSize = pParticle - > m_uchStartSize * 8.0f ;
pParticle - > m_flRoll = random - > RandomInt ( 0 , 360 ) ;
pParticle - > m_flRollDelta = random - > RandomFloat ( - 0.5f , 0.5f ) ;
float flScale = random - > RandomFloat ( 1.25f , 1.5f ) ;
// Flash
for ( int i = 1 ; i < 6 ; i + + )
{
offset = origin + ( forward * ( i * 8.0f * flScale ) ) ;
pParticle = ( SimpleParticle * ) pSimple - > AddParticle ( sizeof ( SimpleParticle ) , m_Material_MuzzleFlash_Player [ random - > RandomInt ( 0 , 3 ) ] , offset ) ;
if ( pParticle = = NULL )
return ;
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = 0.01f ;
pParticle - > m_vecVelocity . Init ( ) ;
pParticle - > m_uchColor [ 0 ] = 255 ;
pParticle - > m_uchColor [ 1 ] = 255 ;
pParticle - > m_uchColor [ 2 ] = 200 + random - > RandomInt ( 0 , 55 ) ;
pParticle - > m_uchStartAlpha = 255 ;
pParticle - > m_uchEndAlpha = 255 ;
pParticle - > m_uchStartSize = ( ( random - > RandomFloat ( 6.0f , 8.0f ) * ( 8 - ( i ) ) / 6 ) * flScale ) ;
pParticle - > m_uchEndSize = pParticle - > m_uchStartSize ;
pParticle - > m_flRoll = random - > RandomInt ( 0 , 360 ) ;
pParticle - > m_flRollDelta = 0.0f ;
}
}
//==================================================
// Purpose:
// Input:
//==================================================
void CTempEnts : : MuzzleFlash_Pistol_Player ( ClientEntityHandle_t hEntity , int attachmentIndex )
{
VPROF_BUDGET ( " MuzzleFlash_Pistol_Player " , VPROF_BUDGETGROUP_PARTICLE_RENDERING ) ;
CSmartPtr < CSimpleEmitter > pSimple = CSimpleEmitter : : Create ( " MuzzleFlash_Pistol_Player " ) ;
pSimple - > SetDrawBeforeViewModel ( true ) ;
CacheMuzzleFlashes ( ) ;
Vector origin ;
QAngle angles ;
// Get our attachment's transformation matrix
FX_GetAttachmentTransform ( hEntity , attachmentIndex , & origin , & angles ) ;
pSimple - > GetBinding ( ) . SetBBox ( origin - Vector ( 4 , 4 , 4 ) , origin + Vector ( 4 , 4 , 4 ) ) ;
Vector forward ;
AngleVectors ( angles , & forward , NULL , NULL ) ;
SimpleParticle * pParticle ;
Vector offset ;
// Smoke
offset = origin + forward * 8.0f ;
if ( random - > RandomInt ( 0 , 3 ) ! = 0 )
{
pParticle = ( SimpleParticle * ) pSimple - > AddParticle ( sizeof ( SimpleParticle ) , g_Mat_DustPuff [ 0 ] , offset ) ;
if ( pParticle = = NULL )
return ;
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = random - > RandomFloat ( 0.25f , 0.5f ) ;
pParticle - > m_vecVelocity . Init ( ) ;
pParticle - > m_vecVelocity = forward * random - > RandomFloat ( 48.0f , 64.0f ) ;
pParticle - > m_vecVelocity [ 2 ] + = random - > RandomFloat ( 4.0f , 16.0f ) ;
int color = random - > RandomInt ( 200 , 255 ) ;
pParticle - > m_uchColor [ 0 ] = color ;
pParticle - > m_uchColor [ 1 ] = color ;
pParticle - > m_uchColor [ 2 ] = color ;
pParticle - > m_uchStartAlpha = random - > RandomInt ( 64 , 128 ) ;
pParticle - > m_uchEndAlpha = 0 ;
pParticle - > m_uchStartSize = random - > RandomInt ( 2 , 4 ) ;
pParticle - > m_uchEndSize = pParticle - > m_uchStartSize * 4.0f ;
pParticle - > m_flRoll = random - > RandomInt ( 0 , 360 ) ;
pParticle - > m_flRollDelta = random - > RandomFloat ( - 0.1f , 0.1f ) ;
}
float flScale = random - > RandomFloat ( 1.0f , 1.25f ) ;
// Flash
for ( int i = 1 ; i < 6 ; i + + )
{
offset = origin + ( forward * ( i * 4.0f * flScale ) ) ;
pParticle = ( SimpleParticle * ) pSimple - > AddParticle ( sizeof ( SimpleParticle ) , m_Material_MuzzleFlash_Player [ random - > RandomInt ( 0 , 3 ) ] , offset ) ;
if ( pParticle = = NULL )
return ;
pParticle - > m_flLifetime = 0.0f ;
pParticle - > m_flDieTime = 0.01f ;
pParticle - > m_vecVelocity . Init ( ) ;
pParticle - > m_uchColor [ 0 ] = 255 ;
pParticle - > m_uchColor [ 1 ] = 255 ;
pParticle - > m_uchColor [ 2 ] = 200 + random - > RandomInt ( 0 , 55 ) ;
pParticle - > m_uchStartAlpha = 255 ;
pParticle - > m_uchEndAlpha = 255 ;
pParticle - > m_uchStartSize = ( ( random - > RandomFloat ( 6.0f , 8.0f ) * ( 8 - ( i ) ) / 6 ) * flScale ) ;
pParticle - > m_uchEndSize = pParticle - > m_uchStartSize ;
pParticle - > m_flRoll = random - > RandomInt ( 0 , 360 ) ;
pParticle - > m_flRollDelta = 0.0f ;
}
}
//==================================================
// Purpose:
// Input:
//==================================================
void CTempEnts : : MuzzleFlash_Pistol_NPC ( ClientEntityHandle_t hEntity , int attachmentIndex )
{
FX_MuzzleEffectAttached ( 0.5f , hEntity , attachmentIndex , NULL , true ) ;
}
//==================================================
// Purpose:
// Input:
//==================================================
void CTempEnts : : MuzzleFlash_RPG_NPC ( ClientEntityHandle_t hEntity , int attachmentIndex )
{
//Draw the cloud of fire
FX_MuzzleEffectAttached ( 1.5f , hEntity , attachmentIndex ) ;
}
void CTempEnts : : RocketFlare ( const Vector & pos )
{
C_LocalTempEntity * pTemp ;
const model_t * model ;
int nframeCount ;
model = ( model_t * ) engine - > LoadModel ( " sprites/animglow01.vmt " ) ;
if ( ! model )
{
return ;
}
nframeCount = modelinfo - > GetModelFrameCount ( model ) ;
pTemp = TempEntAlloc ( pos , model ) ;
if ( ! pTemp )
return ;
pTemp - > m_flFrameMax = nframeCount - 1 ;
pTemp - > SetRenderMode ( kRenderGlow ) ;
pTemp - > m_nRenderFX = kRenderFxNoDissipation ;
pTemp - > tempent_renderamt = 255 ;
pTemp - > m_flFrameRate = 1.0 ;
pTemp - > m_flFrame = random - > RandomInt ( 0 , nframeCount - 1 ) ;
pTemp - > m_flSpriteScale = 1.0 ;
pTemp - > SetAbsOrigin ( pos ) ;
pTemp - > die = gpGlobals - > curtime + 0.01 ;
}
void CTempEnts : : HL1EjectBrass ( const Vector & vecPosition , const QAngle & angAngles , const Vector & vecVelocity , int nType )
{
const model_t * pModel = NULL ;
# if defined( HL1_CLIENT_DLL )
switch ( nType )
{
case 0 :
default :
pModel = m_pHL1Shell ;
break ;
case 1 :
pModel = m_pHL1ShotgunShell ;
break ;
}
# endif
if ( pModel = = NULL )
return ;
C_LocalTempEntity * pTemp = TempEntAlloc ( vecPosition , pModel ) ;
if ( pTemp = = NULL )
return ;
switch ( nType )
{
case 0 :
default :
pTemp - > hitSound = BOUNCE_SHELL ;
break ;
case 1 :
pTemp - > hitSound = BOUNCE_SHOTSHELL ;
break ;
}
pTemp - > m_nBody = 0 ;
pTemp - > flags | = ( FTENT_COLLIDEWORLD | FTENT_FADEOUT | FTENT_GRAVITY | FTENT_ROTATE ) ;
pTemp - > m_vecTempEntAngVelocity [ 0 ] = random - > RandomFloat ( - 512 , 511 ) ;
pTemp - > m_vecTempEntAngVelocity [ 1 ] = random - > RandomFloat ( - 256 , 255 ) ;
pTemp - > m_vecTempEntAngVelocity [ 2 ] = random - > RandomFloat ( - 256 , 255 ) ;
//Face forward
pTemp - > SetAbsAngles ( angAngles ) ;
pTemp - > SetRenderMode ( kRenderNormal ) ;
pTemp - > tempent_renderamt = 255 ; // Set this for fadeout
pTemp - > SetVelocity ( vecVelocity ) ;
pTemp - > die = gpGlobals - > curtime + 2.5 ;
}
# define SHELLTYPE_PISTOL 0
# define SHELLTYPE_RIFLE 1
# define SHELLTYPE_SHOTGUN 2
void CTempEnts : : CSEjectBrass ( const Vector & vecPosition , const QAngle & angVelocity , int nVelocity , int shellType , CBasePlayer * pShooter )
{
const model_t * pModel = NULL ;
int hitsound = TE_BOUNCE_SHELL ;
# if defined ( CSTRIKE_DLL ) || defined ( SDK_DLL )
switch ( shellType )
{
default :
case CS_SHELL_9MM :
hitsound = TE_PISTOL_SHELL ;
pModel = m_pCS_9MMShell ;
break ;
case CS_SHELL_57 :
hitsound = TE_PISTOL_SHELL ;
pModel = m_pCS_57Shell ;
break ;
case CS_SHELL_12GAUGE :
hitsound = TE_SHOTGUN_SHELL ;
pModel = m_pCS_12GaugeShell ;
break ;
case CS_SHELL_556 :
hitsound = TE_RIFLE_SHELL ;
pModel = m_pCS_556Shell ;
break ;
case CS_SHELL_762NATO :
hitsound = TE_RIFLE_SHELL ;
pModel = m_pCS_762NATOShell ;
break ;
case CS_SHELL_338MAG :
hitsound = TE_RIFLE_SHELL ;
pModel = m_pCS_338MAGShell ;
break ;
}
# endif
if ( pModel = = NULL )
return ;
Vector forward , right , up ;
Vector velocity ;
Vector origin ;
QAngle angle ;
// Add some randomness to the velocity
AngleVectors ( angVelocity , & forward , & right , & up ) ;
velocity = forward * nVelocity * random - > RandomFloat ( 1.2 , 2.8 ) +
up * random - > RandomFloat ( - 10 , 10 ) +
right * random - > RandomFloat ( - 20 , 20 ) ;
if ( pShooter )
velocity + = pShooter - > GetAbsVelocity ( ) ;
C_LocalTempEntity * pTemp = TempEntAlloc ( vecPosition , pModel ) ;
if ( ! pTemp )
return ;
if ( pShooter )
pTemp - > SetAbsAngles ( pShooter - > EyeAngles ( ) ) ;
else
pTemp - > SetAbsAngles ( vec3_angle ) ;
pTemp - > SetVelocity ( velocity ) ;
pTemp - > hitSound = hitsound ;
pTemp - > SetGravity ( 0.4 ) ;
pTemp - > m_nBody = 0 ;
pTemp - > flags = FTENT_FADEOUT | FTENT_GRAVITY | FTENT_COLLIDEALL | FTENT_HITSOUND | FTENT_ROTATE | FTENT_CHANGERENDERONCOLLIDE ;
pTemp - > m_vecTempEntAngVelocity [ 0 ] = random - > RandomFloat ( - 256 , 256 ) ;
pTemp - > m_vecTempEntAngVelocity [ 1 ] = random - > RandomFloat ( - 256 , 256 ) ;
pTemp - > m_vecTempEntAngVelocity [ 2 ] = 0 ;
pTemp - > SetRenderMode ( kRenderNormal ) ;
pTemp - > tempent_renderamt = 255 ;
pTemp - > die = gpGlobals - > curtime + 10 ;
bool bViewModelBrass = false ;
if ( pShooter & & pShooter - > GetObserverMode ( ) = = OBS_MODE_IN_EYE )
{
// we are spectating the shooter in first person view
pShooter = ToBasePlayer ( pShooter - > GetObserverTarget ( ) ) ;
bViewModelBrass = true ;
}
if ( pShooter )
{
pTemp - > clientIndex = pShooter - > entindex ( ) ;
bViewModelBrass | = pShooter - > IsLocalPlayer ( ) ;
}
else
{
pTemp - > clientIndex = 0 ;
}
if ( bViewModelBrass )
{
// for viewmodel brass put it in the viewmodel renderer group
pTemp - > m_RenderGroup = RENDER_GROUP_VIEW_MODEL_OPAQUE ;
}
}