cs16-client-legacy/cl_dll/events/ev_cs16.cpp

776 lines
20 KiB
C++

/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
#include "hud.h"
#include "cl_util.h"
#include "const.h"
#include "entity_state.h"
#include "cl_entity.h"
#include "entity_types.h"
#include "usercmd.h"
#include "pm_defs.h"
#include "pm_materials.h"
#include "eventscripts.h"
#include "ev_hldm.h"
#include "r_efx.h"
#include "triangleapi.h"
#include "event_api.h"
#include "event_args.h"
#include "in_defs.h"
#include <string.h>
#include "r_studioint.h"
#include "com_model.h"
#include <assert.h>
static int tracerCount[ 32 ];
extern float g_flRoundTime;
extern "C" char PM_FindTextureType( char *name );
// play a strike sound based on the texture that was hit by the attack traceline. VecSrc/VecEnd are the
// original traceline endpoints used by the attacker, iBulletType is the type of bullet that hit the texture.
// returns volume of strike instrument (crowbar) to play
void EV_HLDM_NewExplode( float x, float y, float z, float ScaleExplode1 )
{
int iNewExplode = gEngfuncs.pEventAPI->EV_FindModelIndex ("sprites/dexplo.spr");
TEMPENTITY *pTemp = gEngfuncs.pEfxAPI->R_TempSprite( Vector( x, y, z + 5 ),
Vector( 0, 0, 0 ),
ScaleExplode1, iNewExplode, kRenderTransAdd, kRenderFxNone, 1.0, 0.5, FTENT_SPRANIMATE | FTENT_FADEOUT | FTENT_COLLIDEKILL );
if(pTemp)
{
pTemp->fadeSpeed = 90.0;
pTemp->entity.curstate.framerate = 37.0;
pTemp->entity.curstate.renderamt = 155;
pTemp->entity.curstate.rendercolor.r = 255;
pTemp->entity.curstate.rendercolor.g = 255;
pTemp->entity.curstate.rendercolor.b = 255;
}
iNewExplode = gEngfuncs.pEventAPI->EV_FindModelIndex ("sprites/fexplo.spr");
pTemp = gEngfuncs.pEfxAPI->R_TempSprite( Vector( x, y, z + 10),
Vector( 0, 0, 0 ),
ScaleExplode1, iNewExplode, kRenderTransAdd, kRenderFxNone, 1.0, 0.5, FTENT_SPRANIMATE | FTENT_FADEOUT | FTENT_COLLIDEKILL );
if(pTemp)
{
pTemp->fadeSpeed = 90.0;
pTemp->entity.curstate.framerate = 35.0;
pTemp->entity.curstate.renderamt = 150;
pTemp->entity.curstate.rendercolor.r = 255;
pTemp->entity.curstate.rendercolor.g = 255;
pTemp->entity.curstate.rendercolor.b = 255;
pTemp->entity.angles = Vector( 90, 0, 0 );
}
for( int i = 1; i <= 10; i++ )
{
int iSmokeSprite = gEngfuncs.pEventAPI->EV_FindModelIndex ("sprites/smoke.spr");
TEMPENTITY *pTemp = gEngfuncs.pEfxAPI->R_TempSprite( Vector( x, y, z ),
Vector( (int)gEngfuncs.pfnRandomLong( -100, 100 ), (int)gEngfuncs.pfnRandomLong( -100, 100 ), (int)gEngfuncs.pfnRandomLong( -100, 100 ) ),
5, iSmokeSprite, kRenderTransAlpha, kRenderFxNone, 1.0, 0.5, FTENT_FADEOUT | FTENT_PERSIST );
if(pTemp)
{
pTemp->fadeSpeed = 0.6;
pTemp->entity.curstate.framerate = 1;
pTemp->entity.curstate.renderamt = 255;
int Color = gEngfuncs.pfnRandomLong( 0, 140 );
pTemp->entity.curstate.rendercolor.r = Color;
pTemp->entity.curstate.rendercolor.g = Color;
pTemp->entity.curstate.rendercolor.b = Color;
}
}
}
char EV_HLDM_PlayTextureSound( int idx, pmtrace_t *ptr, float *vecSrc, float *vecEnd, int iBulletType )
{
// hit the world, try to play sound based on texture material type
char chTextureType = CHAR_TEX_CONCRETE;
float fvol;
float fvolbar;
char *rgsz[4];
int cnt;
float fattn = ATTN_NORM;
int entity;
char *pTextureName;
char texname[ 64 ];
char szbuffer[ 64 ];
entity = gEngfuncs.pEventAPI->EV_IndexFromTrace( ptr );
// FIXME check if playtexture sounds movevar is set
//
chTextureType = 0;
// Player
if ( entity >= 1 && entity <= gEngfuncs.GetMaxClients() )
{
// hit body
chTextureType = CHAR_TEX_FLESH;
}
else if ( entity == 0 )
{
// get texture from entity or world (world is ent(0))
pTextureName = (char *)gEngfuncs.pEventAPI->EV_TraceTexture( ptr->ent, vecSrc, vecEnd );
if ( pTextureName )
{
strncpy( texname, pTextureName, sizeof( texname ) );
pTextureName = texname;
// strip leading '-0' or '+0~' or '{' or '!'
if (*pTextureName == '-' || *pTextureName == '+')
{
pTextureName += 2;
}
if (*pTextureName == '{' || *pTextureName == '!' || *pTextureName == '~' || *pTextureName == ' ')
{
pTextureName++;
}
// '}}'
strncpy( szbuffer, pTextureName, sizeof(szbuffer) );
szbuffer[ CBTEXTURENAMEMAX - 1 ] = 0;
// get texture type
chTextureType = PM_FindTextureType( szbuffer );
}
}
switch (chTextureType)
{
default:
case CHAR_TEX_CONCRETE:
{
fvol = 0.9;
fvolbar = 0.6;
rgsz[0] = "player/pl_step1.wav";
rgsz[1] = "player/pl_step2.wav";
cnt = 2;
break;
}
case CHAR_TEX_METAL:
{
fvol = 0.9;
fvolbar = 0.3;
rgsz[0] = "player/pl_metal1.wav";
rgsz[1] = "player/pl_metal2.wav";
cnt = 2;
break;
}
case CHAR_TEX_DIRT:
{
fvol = 0.9;
fvolbar = 0.1;
rgsz[0] = "player/pl_dirt1.wav";
rgsz[1] = "player/pl_dirt2.wav";
rgsz[2] = "player/pl_dirt3.wav";
cnt = 3;
break;
}
case CHAR_TEX_VENT:
{
fvol = 0.5;
fvolbar = 0.3;
rgsz[0] = "player/pl_duct1.wav";
rgsz[1] = "player/pl_duct1.wav";
cnt = 2;
break;
}
case CHAR_TEX_GRATE:
{
fvol = 0.9;
fvolbar = 0.5;
rgsz[0] = "player/pl_grate1.wav";
rgsz[1] = "player/pl_grate4.wav";
cnt = 2;
break;
}
case CHAR_TEX_TILE:
{
fvol = 0.8;
fvolbar = 0.2;
rgsz[0] = "player/pl_tile1.wav";
rgsz[1] = "player/pl_tile3.wav";
rgsz[2] = "player/pl_tile2.wav";
rgsz[3] = "player/pl_tile4.wav";
cnt = 4;
break;
}
case CHAR_TEX_SLOSH:
{
fvol = 0.9;
fvolbar = 0;
rgsz[0] = "player/pl_slosh1.wav";
rgsz[1] = "player/pl_slosh3.wav";
rgsz[2] = "player/pl_slosh2.wav";
rgsz[3] = "player/pl_slosh4.wav";
cnt = 4;
break;
}
case CHAR_TEX_SNOW:
{
fvol = 0.7;
fvolbar = 0.4;
rgsz[0] = "debris/pl_snow1.wav";
rgsz[1] = "debris/pl_snow2.wav";
rgsz[2] = "debris/pl_snow3.wav";
rgsz[3] = "debris/pl_snow4.wav";
cnt = 4;
break;
}
case CHAR_TEX_WOOD:
{
fvol = 0.9;
fvolbar = 0.2;
rgsz[0] = "debris/wood1.wav";
rgsz[1] = "debris/wood2.wav";
rgsz[2] = "debris/wood3.wav";
cnt = 3;
break;
}
case CHAR_TEX_GLASS:
case CHAR_TEX_COMPUTER:
{
fvol = 0.8;
fvolbar = 0.2;
rgsz[0] = "debris/glass1.wav";
rgsz[1] = "debris/glass2.wav";
rgsz[2] = "debris/glass3.wav";
cnt = 3;
break;
}
case CHAR_TEX_FLESH:
{
fvol = 1.0;fvolbar = 0.2;
rgsz[0] = "weapons/bullet_hit1.wav";
rgsz[1] = "weapons/bullet_hit2.wav";
fattn = 1.0;
cnt = 2;
break;
}
}
// play material hit sound
gEngfuncs.pEventAPI->EV_PlaySound( 0, ptr->endpos, CHAN_STATIC, rgsz[gEngfuncs.pfnRandomLong(0,cnt-1)], fvol, fattn, 0, 96 + gEngfuncs.pfnRandomLong(0,0xf) );
return chTextureType;
}
char *EV_HLDM_DamageDecal( physent_t *pe )
{
static char decalname[ 32 ];
int idx;
if ( pe->classnumber == 1 )
{
idx = gEngfuncs.pfnRandomLong( 0, 2 );
sprintf( decalname, "{break%i", idx + 1 );
}
else if ( pe->rendermode != kRenderNormal )
{
sprintf( decalname, "{bproof1" );
}
else
{
idx = gEngfuncs.pfnRandomLong( 0, 4 );
sprintf( decalname, "{shot%i", idx + 1 );
}
return decalname;
}
void EV_HLDM_GunshotDecalTrace( pmtrace_t *pTrace, char *decalName, char chTextureType )
{
int iRand;
physent_t *pe;
gEngfuncs.pEfxAPI->R_BulletImpactParticles( pTrace->endpos );
iRand = gEngfuncs.pfnRandomLong(0,0x7FFF);
if ( iRand < (0x7fff/2) )// not every bullet makes a sound.
{
if( chTextureType == CHAR_TEX_VENT || chTextureType == CHAR_TEX_METAL )
{
switch( iRand % 2 )
{
case 0: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric_metal-1.wav", 1.0f, ATTN_NORM, 0, PITCH_NORM); break;
case 1: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric_metal-2.wav", 1.0f, ATTN_NORM, 0, PITCH_NORM); break;
}
}
else
{
switch( iRand % 7)
{
case 0: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
case 1: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
case 2: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric3.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
case 3: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric4.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
case 4: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric5.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
case 5: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric_conc-1.wav", 1.0f, ATTN_NORM, 0, PITCH_NORM); break;
case 6: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "weapons/ric_conc-2.wav", 1.0f, ATTN_NORM, 0, PITCH_NORM); break;
}
}
}
pe = gEngfuncs.pEventAPI->EV_GetPhysent( pTrace->ent );
// Only decal brush models such as the world etc.
if ( decalName && decalName[0] && pe && ( pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP ) )
{
if ( CVAR_GET_FLOAT( "r_decals" ) )
{
gEngfuncs.pEfxAPI->R_DecalShoot(
gEngfuncs.pEfxAPI->Draw_DecalIndex( gEngfuncs.pEfxAPI->Draw_DecalIndexFromName( decalName ) ),
gEngfuncs.pEventAPI->EV_IndexFromTrace( pTrace ), 0, pTrace->endpos, 0 );
}
}
}
void EV_HLDM_DecalGunshot(pmtrace_t *pTrace, int iBulletType, float scale, int r, int g, int b, bool bCreateSparks, char cTextureType)
{
physent_t *pe;
pe = gEngfuncs.pEventAPI->EV_GetPhysent( pTrace->ent );
if ( pe && pe->solid == SOLID_BSP )
{
EV_HLDM_GunshotDecalTrace( pTrace, EV_HLDM_DamageDecal( pe ), cTextureType );
Vector dir = pTrace->plane.normal;
dir = dir * gEngfuncs.pfnRandomFloat(4.0f, 12.0f );
if( bCreateSparks )
{
gEngfuncs.pEfxAPI->R_StreakSplash( pTrace->endpos, dir, 4, gEngfuncs.pfnRandomLong( 15, 30 ), dir.z, -75.0f, 75.0f );
}
int wallPuffSprite;
switch( gEngfuncs.pfnRandomLong( 0, 4 ) ) // every bullet makes a wall puff
{
case 0: wallPuffSprite = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/wall_puff1.spr"); break;
case 1: wallPuffSprite = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/wall_puff2.spr"); break;
case 2: wallPuffSprite = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/wall_puff3.spr"); break;
case 3: wallPuffSprite = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/wall_puff4.spr"); break;
}
TEMPENTITY *te = gEngfuncs.pEfxAPI->R_DefaultSprite( pTrace->endpos, wallPuffSprite, 30.0f );
if( te )
{
te->flags = FTENT_SPRANIMATE | FTENT_FADEOUT;
te->entity.curstate.rendermode = kRenderTransAdd;
te->entity.curstate.rendercolor.r = r;
te->entity.curstate.rendercolor.g = g;
te->entity.curstate.rendercolor.b = b;
te->entity.curstate.renderamt = 255;
te->entity.curstate.scale = 0.25;
te->entity.baseline.origin = 10 * pTrace->plane.normal;
}
}
}
int EV_HLDM_CheckTracer( int idx, float *vecSrc, float *end, float *forward, float *right, int iBulletType, int iTracerFreq, int *tracerCount )
{
int tracer = 0;
int i;
qboolean player = idx >= 1 && idx <= gEngfuncs.GetMaxClients() ? true : false;
if ( iTracerFreq != 0 && ( (*tracerCount)++ % iTracerFreq) == 0 )
{
vec3_t vecTracerSrc;
if ( player )
{
vec3_t offset( 0, 0, -4 );
// adjust tracer position for player
for ( i = 0; i < 3; i++ )
{
vecTracerSrc[ i ] = vecSrc[ i ] + offset[ i ] + right[ i ] * 2 + forward[ i ] * 16;
}
}
else
{
VectorCopy( vecSrc, vecTracerSrc );
}
if ( iTracerFreq != 1 ) // guns that always trace also always decal
tracer = 1;
EV_CreateTracer( vecTracerSrc, end );
}
return tracer;
}
/*
============
EV_DescribeBulletTypeParameters
Sets iPenetrationPower and flPenetrationDistance.
If iBulletType is unknown, calls assert() and sets these two vars to 0
============
*/
void EV_DescribeBulletTypeParameters(int iBulletType, int &iPenetrationPower, float &flPenetrationDistance)
{
switch (iBulletType)
{
case BULLET_PLAYER_9MM:
{
iPenetrationPower = 21;
flPenetrationDistance = 800;
break;
}
case BULLET_PLAYER_45ACP:
{
iPenetrationPower = 15;
flPenetrationDistance = 500;
break;
}
case BULLET_PLAYER_50AE:
{
iPenetrationPower = 30;
flPenetrationDistance = 1000;
break;
}
case BULLET_PLAYER_762MM:
{
iPenetrationPower = 39;
flPenetrationDistance = 5000;
break;
}
case BULLET_PLAYER_556MM:
{
iPenetrationPower = 35;
flPenetrationDistance = 4000;
break;
}
case BULLET_PLAYER_338MAG:
{
iPenetrationPower = 45;
flPenetrationDistance = 8000;
break;
}
case BULLET_PLAYER_57MM:
{
iPenetrationPower = 30;
flPenetrationDistance = 2000;
break;
}
case BULLET_PLAYER_357SIG:
{
iPenetrationPower = 25;
flPenetrationDistance = 800;
break;
}
default:
{
iPenetrationPower = 0;
flPenetrationDistance = 0;
break;
}
}
}
/*
================
FireBullets
Go to the trouble of combining multiple pellets into a single damage call.
================
*/
void EV_HLDM_FireBullets(int idx,
float *forward, float *right, float *up,
int cShots,
float *vecSrc, float *vecDirShooting, float *vecSpread,
float flDistance, int iBulletType, int iTracerFreq, int *tracerCount, int iPenetration)
{
int i;
pmtrace_t tr;
int iShot;
int tracer;
int iPenetrationPower;
float flPenetrationDistance;
EV_DescribeBulletTypeParameters( iBulletType, iPenetrationPower, flPenetrationDistance );
for ( iShot = 1; iShot <= cShots; iShot++ )
{
Vector vecShotSrc = vecSrc;
int iShotPenetration = iPenetration;
Vector vecDir, vecEnd;
if ( iBulletType == BULLET_PLAYER_BUCKSHOT )
{
//We randomize for the Shotgun.
float x, y, z;
do {
x = gEngfuncs.pfnRandomFloat(-0.5,0.5) + gEngfuncs.pfnRandomFloat(-0.5,0.5);
y = gEngfuncs.pfnRandomFloat(-0.5,0.5) + gEngfuncs.pfnRandomFloat(-0.5,0.5);
z = x*x+y*y;
} while (z > 1);
for ( i = 0 ; i < 3; i++ )
{
vecDir[i] = vecDirShooting[i] + x * vecSpread[0] * right[ i ] + y * vecSpread[1] * up [ i ];
vecEnd[i] = vecShotSrc[ i ] + flDistance * vecDir[ i ];
}
}
else //But other guns already have their spread randomized in the synched spread.
{
for ( i = 0 ; i < 3; i++ )
{
vecDir[i] = vecDirShooting[i] + vecSpread[0] * right[ i ] + vecSpread[1] * up [ i ];
vecEnd[i] = vecShotSrc[ i ] + flDistance * vecDir[ i ];
}
}
gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true );
// Store off the old count
gEngfuncs.pEventAPI->EV_PushPMStates();
// Now add in all of the players.
gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
while (iShotPenetration != 0)
{
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace(vecShotSrc, vecEnd, 0, -1, &tr);
tracer = EV_HLDM_CheckTracer( idx, vecShotSrc, tr.endpos, forward, right, iBulletType, iTracerFreq, tracerCount );
float flCurrentDistance = tr.fraction * flDistance;
#ifdef _DEBUG
// absolute end
gEngfuncs.pEfxAPI->R_ParticleLine( vecEnd, vecEnd, 255, 255, 255, 20.0f);
#endif
if( flCurrentDistance == 0.0f )
{
#ifdef _DEBUG
// absolute start ( don't traceline after )
gEngfuncs.pEfxAPI->R_ParticleLine( vecShotSrc, vecShotSrc, 255, 255, 0, 20.0f );
#endif
break;
}
#ifdef _DEBUG
// absoulute start
gEngfuncs.pEfxAPI->R_ParticleLine( vecShotSrc, vecShotSrc, 0, 0, 255, 20.0f);
// trace
gEngfuncs.pEfxAPI->R_ParticleLine( vecShotSrc, tr.endpos, 0, 255, 0, 20.0f );
// hit
gEngfuncs.pEfxAPI->R_ParticleLine( tr.endpos, tr.endpos, 255, 0, 0, 20.0f);
#endif
if ( flCurrentDistance > flPenetrationDistance )
iShotPenetration = 0;
else iShotPenetration--;
char cTextureType = EV_HLDM_PlayTextureSound(idx, &tr, vecShotSrc, vecEnd, iBulletType );
bool bSparks = true;
int r_smoke, g_smoke, b_smoke;
r_smoke = g_smoke = b_smoke = 40;
switch (cTextureType)
{
case CHAR_TEX_METAL:
iPenetrationPower *= 0.15;
break;
case CHAR_TEX_CONCRETE:
r_smoke = g_smoke = b_smoke = 65;
iPenetrationPower *= 0.25;
break;
case CHAR_TEX_VENT:
case CHAR_TEX_GRATE:
iPenetrationPower *= 0.5;
break;
case CHAR_TEX_TILE:
iPenetrationPower *= 0.65;
break;
case CHAR_TEX_COMPUTER:
iPenetrationPower *= 0.4;
break;
case CHAR_TEX_WOOD:
bSparks = false;
r_smoke = 75;
g_smoke = 42;
b_smoke = 15;
break;
}
// do damage, paint decals
EV_HLDM_DecalGunshot( &tr, iBulletType, 0, r_smoke, g_smoke, b_smoke, bSparks, cTextureType );
if( iBulletType == BULLET_PLAYER_BUCKSHOT || iShotPenetration == 0 )
{
break;
}
flDistance = (flDistance - flCurrentDistance) * 0.5;
for( int i = 0; i < 3; i++ )
{
vecShotSrc[i] = tr.endpos[i] + iPenetrationPower * vecDir[i];
vecEnd[i] = vecShotSrc[i] + flDistance * vecDir[i];
}
Vector vStartPos, vEndPos;
pmtrace_t trOriginal;
int i;
for( i = 1; i <= iPenetrationPower; i++ )
{
for( int j = 0; j < 3; j++ )
{
vStartPos[j] = tr.endpos[j] + i * vecDir[j];
vEndPos[j] = vecDir[j] + vStartPos[j];
}
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace(vStartPos, vEndPos, 0, -1, &trOriginal);
if ( trOriginal.startsolid && trOriginal.inopen )
break;
}
if( i != iPenetrationPower )
{
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace(vEndPos, vStartPos, 0, -1, &trOriginal);
EV_HLDM_DecalGunshot( &trOriginal, iBulletType, 0, r_smoke, g_smoke, b_smoke, bSparks, cTextureType );
}
}
gEngfuncs.pEventAPI->EV_PopPMStates();
}
}
void EV_TrainPitchAdjust( event_args_t *args )
{
int idx;
vec3_t origin;
unsigned short us_params;
int noise;
float m_flVolume;
int pitch;
int stop;
char sz[ 256 ];
idx = args->entindex;
VectorCopy( args->origin, origin );
us_params = (unsigned short)args->iparam1;
stop = args->bparam1;
m_flVolume = (float)(us_params & 0x003f)/40.0;
noise = (int)(((us_params) >> 12 ) & 0x0007);
pitch = (int)( 10.0 * (float)( ( us_params >> 6 ) & 0x003f ) );
switch ( noise )
{
case 1: strncpy( sz, "plats/ttrain1.wav", sizeof(sz)); break;
case 2: strncpy( sz, "plats/ttrain2.wav", sizeof(sz)); break;
case 3: strncpy( sz, "plats/ttrain3.wav", sizeof(sz)); break;
case 4: strncpy( sz, "plats/ttrain4.wav", sizeof(sz)); break;
case 5: strncpy( sz, "plats/ttrain6.wav", sizeof(sz)); break;
case 6: strncpy( sz, "plats/ttrain7.wav", sizeof(sz)); break;
default:
// no sound
strncpy( sz, "", sizeof(sz) );
return;
}
if ( stop )
{
gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_STATIC, sz );
}
else
{
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, sz, m_flVolume, ATTN_NORM, 0, pitch );
}
}
void EV_CS16Client_KillEveryRound( TEMPENTITY *te, float frametime, float current_time )
{
if( g_flRoundTime > te->entity.curstate.fuser4 )
{
// Mark it die on next TempEntUpdate
te->die = 0.0f;
// Set null renderamt, so it will be invisible now
// Also it will die immediately, if FTEMP_FADEOUT was set
te->entity.curstate.renderamt = 0;
}
}
void RemoveBody(TEMPENTITY *te, float frametime, float current_time)
{
// go underground...
/*if ( current_time >= 2 * te->entity.curstate.fuser2 + 5.0 )
te->entity.origin.z -= 5.0 * frametime;*/
}
void HitBody(TEMPENTITY *ent, pmtrace_s *ptr)
{
/*if ( ptr->plane.normal.z > 0.0 )
ent->flags |= FTENT_NONE;*/
}
void CreateCorpse(Vector *p_vOrigin, Vector *p_vAngles, const char *pModel, float flAnimTime, int iSequence, int iBody)
{
int modelIdx = gEngfuncs.pEventAPI->EV_FindModelIndex(pModel);
vec3_t null(0, 0, 0);
TEMPENTITY *model = gEngfuncs.pEfxAPI->R_TempModel( (float*)p_vOrigin,
null,
(float*)p_vAngles,
gEngfuncs.pfnGetCvarFloat("cl_corpsestay"),
modelIdx,
0 );
if(model)
{
//model->frameMax = -1;
model->entity.curstate.animtime = flAnimTime;
model->entity.curstate.framerate = 1.0;
model->entity.curstate.frame = 0;
model->entity.curstate.sequence = iSequence;
model->entity.curstate.body = iBody;
model->entity.curstate.fuser1 = gHUD.m_flTime + 1.0;
model->entity.curstate.fuser2 = gEngfuncs.pfnGetCvarFloat("cl_corpsestay") + gHUD.m_flTime;
model->hitcallback = HitBody;
model->callback = RemoveBody;
}
}