Portable Half-Life SDK. GoldSource and Xash3D. Crossplatform.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2514 lines
64 KiB

/***
*
* 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 "event_api.h"
#include "event_args.h"
#include "in_defs.h"
#include <string.h>
#include "r_studioint.h"
#include "com_model.h"
extern engine_studio_api_t IEngineStudio;
static int g_tracerCount[32];
extern "C" char PM_FindTextureType( char *name );
void V_PunchAxis( int axis, float punch );
void VectorAngles( const float *forward, float *angles );
extern cvar_t *cl_lw;
//modif de Julien
void VectorAngles( const float *forward, float *angles );
// modif de julien
// nouveau mat
#define CHAR_TEX_XENO 'X'
extern "C"
{
// HLDM
void EV_FireGlock1( struct event_args_s *args );
void EV_FireGlock2( struct event_args_s *args );
void EV_FireShotGunSingle( struct event_args_s *args );
void EV_FireShotGunDouble( struct event_args_s *args );
void EV_FireMP5( struct event_args_s *args );
void EV_FireMP52( struct event_args_s *args );
void EV_FireM16( struct event_args_s *args ); //modif de julien
void EV_FireFSniper( struct event_args_s *args ); //modif de julien
void EV_FireIRgun( struct event_args_s *args ); //modif de julien
void EV_FireSG( struct event_args_s *args ); //modif de julien
void EV_FirePython( struct event_args_s *args );
void EV_FireGauss( struct event_args_s *args );
void EV_SpinGauss( struct event_args_s *args );
void EV_Crowbar( struct event_args_s *args );
void EV_FireCrossbow( struct event_args_s *args );
void EV_FireCrossbow2( struct event_args_s *args );
void EV_FireRpg( struct event_args_s *args );
void EV_EgonFire( struct event_args_s *args );
void EV_EgonStop( struct event_args_s *args );
void EV_HornetGunFire( struct event_args_s *args );
void EV_TripmineFire( struct event_args_s *args );
void EV_SnarkFire( struct event_args_s *args );
void EV_TrainPitchAdjust( struct event_args_s *args );
}
#define VECTOR_CONE_1DEGREES Vector( 0.00873f, 0.00873f, 0.00873f )
#define VECTOR_CONE_2DEGREES Vector( 0.01745f, 0.01745f, 0.01745f )
#define VECTOR_CONE_3DEGREES Vector( 0.02618f, 0.02618f, 0.02618f )
#define VECTOR_CONE_4DEGREES Vector( 0.03490f, 0.03490f, 0.03490f )
#define VECTOR_CONE_5DEGREES Vector( 0.04362f, 0.04362f, 0.04362f )
#define VECTOR_CONE_6DEGREES Vector( 0.05234f, 0.05234f, 0.05234f )
#define VECTOR_CONE_7DEGREES Vector( 0.06105f, 0.06105f, 0.06105f )
#define VECTOR_CONE_8DEGREES Vector( 0.06976f, 0.06976f, 0.06976f )
#define VECTOR_CONE_9DEGREES Vector( 0.07846f, 0.07846f, 0.07846f )
#define VECTOR_CONE_10DEGREES Vector( 0.08716f, 0.08716f, 0.08716f )
#define VECTOR_CONE_15DEGREES Vector( 0.13053f, 0.13053f, 0.13053f )
#define VECTOR_CONE_20DEGREES Vector( 0.17365f, 0.17365f, 0.17365f )
#define PARTICULES_PRECISION 40
#define ETINCELLES_PRECISION 250
#define PARTICULES_NOMBRE 4
#define PARTICULES_SPEED 32
//--------------------------------------------
// modif de Julien
// ejection des particules
void EV_HLDM_SparkCallback ( struct tempent_s *ent, float frametime, float currenttime )
{
int iSparkModel;
gEngfuncs.CL_LoadModel( "sprites/laserbeam.spr", &iSparkModel );
gEngfuncs.pEfxAPI->R_BeamPoints ( ent->entity.origin, ent->entity.prevstate.origin, iSparkModel,
frametime, 0.1, 0, 255, 0, 0, 1,
255, 255, 255 );
}
void EV_HLDM_EjectParticules ( Vector vecOrigin, Vector vecNormal, char chTextureType, int decal, int iParticules )
{
//--------------------------
//pour la fumee
if ( decal <= 1 && iParticules == 1 )
{
int spriteSmoke = gEngfuncs.pEventAPI->EV_FindModelIndex( "sprites/stmbal1.spr" );
TEMPENTITY *tSmoke = gEngfuncs.pEfxAPI->R_TempSprite ( vecOrigin, vecNormal * PARTICULES_SPEED,
0.75, spriteSmoke, kRenderGlow, kRenderFxNoDissipation,
240, 5, FTENT_SPRANIMATE );
tSmoke->entity.curstate.framerate = 20 / 1.3;
/* gHUD.m_Particules.AddParticule (
vecOrigin,
Vector(0,0,0),
vecNormal * PARTICULES_SPEED,
Vector (0,0,0),
"sprites/stmbal1.spr",
gEngfuncs.GetClientTime() + 4.0,
FLAG_PARTICULE_SMOKE
);*/
}
//----------------------------
//particules
vec3_t v_angdir;
VectorAngles( vecNormal, v_angdir );
vec3_t forward, right, up;
AngleVectors ( v_angdir, forward, right, up );
if ( iParticules == 1 )
{
// particule differente selon la surface
char particule_type [64];
switch (chTextureType)
{
default:
return;
break;
case CHAR_TEX_METAL:
case CHAR_TEX_VENT:
strcpy ( particule_type, "metal" );
break;
case CHAR_TEX_DIRT:
case CHAR_TEX_XENO:
strcpy ( particule_type, "dirt" );
break;
case CHAR_TEX_WOOD:
strcpy ( particule_type, "wood" );
break;
case CHAR_TEX_GLASS:
strcpy ( particule_type, "glass" );
break;
case CHAR_TEX_CONCRETE:
case CHAR_TEX_TILE:
strcpy ( particule_type, "concrete" );
break;
case CHAR_TEX_COMPUTER:
case CHAR_TEX_GRATE:
break; //seulement des
}
for ( int i = 0; i < 10; i++ )
{
// pas de particules
if ( chTextureType == CHAR_TEX_COMPUTER || chTextureType == CHAR_TEX_GRATE || chTextureType == CHAR_TEX_XENO || decal >= 2 )
break;
// particule al
char particule_numero [8];
char particule_name [64];
sprintf ( particule_numero, "%i", gEngfuncs.pfnRandomLong( 1, 6 ) );
strcpy ( particule_name, "sprites/particules/particule_" );
strcat ( particule_name, particule_type );
strcat ( particule_name, "0" );
strcat ( particule_name, particule_numero );
strcat ( particule_name, ".spr" );
// direction al
float x = gEngfuncs.pfnRandomLong( -PARTICULES_PRECISION, PARTICULES_PRECISION );
float y = gEngfuncs.pfnRandomLong( -PARTICULES_PRECISION, PARTICULES_PRECISION );
Vector vecDir = vecNormal * 100 +
x * right +
y * up;
// vitesse et rotation
vec3_t angles ( gEngfuncs.pfnRandomLong(0,179), gEngfuncs.pfnRandomLong(0,179), gEngfuncs.pfnRandomLong(0,179) );
vec3_t velocity = vecDir.Normalize() * gEngfuncs.pfnRandomLong( 100, 250 );
vec3_t avelocity ( gEngfuncs.pfnRandomLong(360,700), gEngfuncs.pfnRandomLong(360,700), gEngfuncs.pfnRandomLong(360,700) ) ;
// lancement
gHUD.m_Particules.AddParticule (
vecOrigin, angles,
velocity, avelocity,
particule_name, // model
gEngfuncs.GetClientTime() + 4.0, // deathtime
chTextureType == CHAR_TEX_WOOD ? FLAG_PARTICULE_WOOD : 0 ); // flags
}
}
//----------------------------
//etincelles
if ( chTextureType == CHAR_TEX_COMPUTER || chTextureType == CHAR_TEX_GRATE )
{
int modelindex;
struct model_s *mod = gEngfuncs.CL_LoadModel( "sprites/laserbeam.spr", &modelindex );
for ( int k = 0; k < 5; k ++ )
{
TEMPENTITY *tentSpark = gEngfuncs.pEfxAPI->CL_TentEntAllocCustom
( vecOrigin, mod, 1, EV_HLDM_SparkCallback );
tentSpark->die += 0.5;
tentSpark->bounceFactor = 1;
tentSpark->flags |= FTENT_GRAVITY;
tentSpark->flags |= FTENT_NOMODEL;
tentSpark->flags |= FTENT_COLLIDEWORLD;
tentSpark->flags |= FTENT_PERSIST;
float x = gEngfuncs.pfnRandomLong( -ETINCELLES_PRECISION, ETINCELLES_PRECISION );
float y = gEngfuncs.pfnRandomLong( -ETINCELLES_PRECISION, ETINCELLES_PRECISION );
Vector vecDir = vecNormal * 100 +
x * right +
y * up;
tentSpark->entity.curstate.origin = vecOrigin;
tentSpark->entity.baseline.origin = vecDir.Normalize() * 600;
}
}
// ------------------------------
//
// decals
if ( chTextureType == CHAR_TEX_XENO )
{
Vector angDir;
VectorAngles ( -vecNormal, angDir );
angDir.y += 180;
gHUD.m_Particules.AddDecal (
vecOrigin + vecNormal.Normalize() * 0.1, //d
angDir,
"sprites/particules/particule_xen.spr",
gHUD.m_flTime + 0.3,
FLAG_DECAL_XENO );
decal = 0; // les d
}
if ( decal >= 1 )
{
char decal_type [64];
int flags = 0;
switch (chTextureType)
{
default:
return;
break;
case CHAR_TEX_METAL:
case CHAR_TEX_VENT:
case CHAR_TEX_COMPUTER:
case CHAR_TEX_GRATE:
strcpy ( decal_type, "metal" );
break;
case CHAR_TEX_DIRT:
strcpy ( decal_type, "dirt" );
break;
case CHAR_TEX_WOOD:
strcpy ( decal_type, "wood" );
break;
case CHAR_TEX_GLASS:
{
strcpy ( decal_type, "glass" );
flags |= FLAG_DECAL_GLASS;
break;
}
case CHAR_TEX_CONCRETE:
case CHAR_TEX_TILE:
strcpy ( decal_type, "concrete" );
break;
}
char decal_numero [8];
char decal_name [64];
sprintf ( decal_numero, "%i", gEngfuncs.pfnRandomLong( 1, 3 ) );
//crowbar
if ( decal >= 2 && chTextureType != CHAR_TEX_GLASS )
{
strcpy ( decal_type, "crowbar" );
sprintf ( decal_numero, "1" );
if ( decal == 2 )
flags |= FLAG_DECAL_CROWBAR_INVERT;
else
flags |= FLAG_DECAL_CROWBAR;
}
strcpy ( decal_name, "sprites/decals/decal_" );
strcat ( decal_name, decal_type );
strcat ( decal_name, "0" );
strcat ( decal_name, decal_numero );
strcat ( decal_name, ".spr" );
Vector angDir;
VectorAngles ( -vecNormal, angDir );
angDir.y += 180;
gHUD.m_Particules.AddDecal (
vecOrigin + vecNormal.Normalize() * 0.1, //d
angDir,
decal_name,
gEngfuncs.GetClientTime() + 600.0, //life
flags );
}
}
void EV_HLDM_BulletImpact ( pmtrace_t *pTrace, float *vecSrc, float *vecEnd, int iParticules )
{
//--------------------------------------------
// determine le type de texture touchee
char szbuffer[ 64 ];
char texname[ 64 ];
char chTextureType = 0;
int entity = gEngfuncs.pEventAPI->EV_IndexFromTrace( pTrace );
physent_s *pe = gEngfuncs.pEventAPI->EV_GetPhysent( pTrace->ent );
if ( entity >= 1 && entity <= gEngfuncs.GetMaxClients() )
return;
else if ( entity == 0 || ( pe && pe->solid == SOLID_BSP ) )
{
char *pTextureName = (char *)gEngfuncs.pEventAPI->EV_TraceTexture( pTrace->ent, vecSrc, vecEnd );
if ( pTextureName )
{
strcpy( texname, pTextureName );
pTextureName = texname;
if (*pTextureName == '-' || *pTextureName == '+')
pTextureName += 2;
if (*pTextureName == '{' || *pTextureName == '!' || *pTextureName == '~' || *pTextureName == ' ')
pTextureName++;
strcpy( szbuffer, pTextureName );
szbuffer[ CBTEXTURENAMEMAX - 1 ] = 0;
chTextureType = PM_FindTextureType( szbuffer );
}
}
// -------------------------
// particules et decals
int decal = 0;
if ( entity == 0 || ( pe && pe->solid == SOLID_BSP ) )
decal = 1;
EV_HLDM_EjectParticules ( pTrace->endpos, pTrace->plane.normal, chTextureType, decal, iParticules );
}
// 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
float 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;
const 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 )
{
strcpy( texname, pTextureName );
pTextureName = texname;
// strip leading '-0' or '+0~' or '{' or '!'
if( *pTextureName == '-' || *pTextureName == '+' )
{
pTextureName += 2;
}
if( *pTextureName == '{' || *pTextureName == '!' || *pTextureName == '~' || *pTextureName == ' ' )
{
pTextureName++;
}
// '}}'
strcpy( szbuffer, pTextureName );
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.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_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:
if( iBulletType == BULLET_PLAYER_CROWBAR )
return 0.0; // crowbar already makes this sound
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 fvolbar;
}
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 )
{
int iRand;
physent_t *pe;
iRand = gEngfuncs.pfnRandomLong( 0, 0x7FFF );
if( iRand < ( 0x7fff / 2 ) )// not every bullet makes a sound.
{
switch( iRand % 5 )
{
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;
}
}
//modif de Julien
return;
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 )
{
physent_t *pe;
// gEngfuncs.pEfxAPI->R_BulletImpactParticles( pTrace->endpos ); //original
pe = gEngfuncs.pEventAPI->EV_GetPhysent( pTrace->ent );
if( pe && ( pe->solid == SOLID_BSP || pe->movetype == MOVETYPE_PUSHSTEP ) )
{
switch( iBulletType )
{
case BULLET_PLAYER_9MM:
case BULLET_MONSTER_9MM:
case BULLET_PLAYER_MP5:
case BULLET_PLAYER_SNIPER : //modif de Julien
case BULLET_PLAYER_M16 : //modif de Julien
case BULLET_PLAYER_IRGUN: //modif de Julien
case BULLET_MONSTER_MP5:
case BULLET_PLAYER_BUCKSHOT:
case BULLET_PLAYER_BUCKSHOT_DOUBLE:
case BULLET_PLAYER_357:
default:
// smoke and decal
EV_HLDM_GunshotDecalTrace( pTrace, EV_HLDM_DamageDecal( pe ) );
break;
}
}
}
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;
switch( iBulletType )
{
case BULLET_PLAYER_MP5:
case BULLET_MONSTER_MP5:
case BULLET_PLAYER_SNIPER : //modif de Julien
case BULLET_PLAYER_M16 : //modif de Julien
case BULLET_PLAYER_IRGUN: //modif de Julien
case BULLET_MONSTER_9MM:
case BULLET_MONSTER_12MM:
default:
EV_CreateTracer( vecTracerSrc, end );
break;
}
}
return tracer;
}
/*
================
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 flDistance, int iBulletType, int iTracerFreq, int *tracerCount, float flSpreadX, float flSpreadY, int iTraverseMur ) //Original
{
int i;
pmtrace_t tr;
int iShot;
int tracer;
vec3_t vecSpread; //Added for compatibility (this function is sometimes recursive).
for( iShot = 1; iShot <= cShots; iShot++ )
{
vec3_t vecDir, vecEnd;
float x, y, z;
//We randomize for the Shotgun.
if( iBulletType == BULLET_PLAYER_BUCKSHOT )
{
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 * flSpreadX * right[i] + y * flSpreadY * up [i];
vecEnd[i] = vecSrc[i] + flDistance * vecDir[i];
}
}//But other guns already have their spread randomized in the synched spread.
else
{
for( i = 0 ; i < 3; i++ )
{
vecDir[i] = vecDirShooting[i] + flSpreadX * right[i] + flSpreadY * up [i];
vecEnd[i] = vecSrc[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 );
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr );
tracer = EV_HLDM_CheckTracer( idx, vecSrc, tr.endpos, forward, right, iBulletType, iTracerFreq, tracerCount );
// do damage, paint decals
if( tr.fraction != 1.0f )
{
switch( iBulletType )
{
default:
case BULLET_PLAYER_9MM:
EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType );
EV_HLDM_DecalGunshot( &tr, iBulletType );
break;
case BULLET_PLAYER_MP5:
if( !tracer )
{
EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType );
EV_HLDM_DecalGunshot( &tr, iBulletType );
}
break;
case BULLET_PLAYER_SNIPER : //modif de Julien
if ( !tracer )
{
EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType );
EV_HLDM_DecalGunshot( &tr, iBulletType );
}
break;
case BULLET_PLAYER_M16 : //modif de Julien
if ( !tracer )
{
EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType );
EV_HLDM_DecalGunshot( &tr, iBulletType );
}
break;
case BULLET_PLAYER_IRGUN : //modif de Julien
if ( !tracer )
{
EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType );
EV_HLDM_DecalGunshot( &tr, iBulletType );
}
break;
case BULLET_PLAYER_BUCKSHOT_DOUBLE:
case BULLET_PLAYER_BUCKSHOT:
EV_HLDM_DecalGunshot( &tr, iBulletType );
break;
case BULLET_PLAYER_357:
EV_HLDM_PlayTextureSound( idx, &tr, vecSrc, vecEnd, iBulletType );
EV_HLDM_DecalGunshot( &tr, iBulletType );
break;
}
// particules et decals
gEngfuncs.pEventAPI->EV_PopPMStates();
EV_HLDM_BulletImpact ( &tr, vecSrc, vecEnd, iTraverseMur == 0 ? 1 : 0 );
// mettre le tir a travers les murs
if ( iTraverseMur == 0 )
{
float distance;
switch(iBulletType)
{
default:
case BULLET_PLAYER_9MM:
case BULLET_PLAYER_MP5:
case BULLET_PLAYER_SNIPER :
case BULLET_PLAYER_M16 :
case BULLET_PLAYER_BUCKSHOT_DOUBLE:
case BULLET_PLAYER_BUCKSHOT:
case BULLET_PLAYER_357:
distance = 16;
break;
case BULLET_PLAYER_IRGUN :
distance = 32;
break;
}
//
vec3_t vecSource = vecSrc;
vec3_t vecTraceDir = (tr.endpos - vecSource).Normalize();
vecSource = tr.endpos + vecTraceDir * distance;
pmtrace_t trTir;
gEngfuncs.pEventAPI->EV_SetUpPlayerPrediction( false, true );
gEngfuncs.pEventAPI->EV_PushPMStates();
gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( vecSource, vecSource + vecTraceDir, PM_STUDIO_BOX, -1, &trTir );
gEngfuncs.pEventAPI->EV_PopPMStates();
if ( trTir.startsolid != 1 ){
vecSpread[0] = flSpreadX; //modif de modif de Julien, compatibility fix.
vecSpread[1] = flSpreadY;
vecSpread[2] = flSpreadX; //Just in case, won't be read.
EV_HLDM_FireBulletsVect( idx, forward, right, up, 1, vecSource, forward, vecSpread, 8192, iBulletType, 0, &tracerCount[idx-1], 1 );
}
}
}
else
{
gEngfuncs.pEventAPI->EV_PopPMStates();
}
}
}
//======================
// GLOCK START
//======================
// Shared Glock fire implementation for EV_FireGlock1 and EV_FireGlock2.
static void EV_FireGlock_Impl( event_args_t *args )
{
int idx;
vec3_t origin;
vec3_t angles;
vec3_t velocity;
int empty;
vec3_t ShellVelocity;
vec3_t ShellOrigin;
int shell;
vec3_t vecSrc, vecAiming;
vec3_t up, right, forward;
idx = args->entindex;
VectorCopy( args->origin, origin );
VectorCopy( args->angles, angles );
VectorCopy( args->velocity, velocity );
empty = args->bparam1;
AngleVectors( angles, forward, right, up );
shell = gEngfuncs.pEventAPI->EV_FindModelIndex( "models/shell.mdl" );// brass shell
if( EV_IsLocal( idx ) )
{
EV_MuzzleFlash();
if ( empty == 1 )
gEngfuncs.pEventAPI->EV_WeaponAnimation( GLOCK_SHOOT_EMPTY, 2 );
else
gEngfuncs.pEventAPI->EV_WeaponAnimation( GLOCK_SHOOT, 2 );
// gEngfuncs.pEventAPI->EV_WeaponAnimation( empty ? GLOCK_SHOOT_EMPTY : GLOCK_SHOOT, 2 );
V_PunchAxis( 0, -2.0 );
}
EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 );
EV_EjectBrass( ShellOrigin, ShellVelocity, angles[YAW], shell, TE_BOUNCE_SHELL );
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/pl_gun3.wav", gEngfuncs.pfnRandomFloat( 0.92, 1.0 ), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) );
EV_GetGunPosition( args, vecSrc, origin );
VectorCopy( forward, vecAiming );
EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_9MM, 0, &g_tracerCount[idx - 1], args->fparam1, args->fparam2 );
}
void EV_FireGlock1( event_args_t *args )
{
EV_FireGlock_Impl( args );
}
void EV_FireGlock2( event_args_t *args )
{
EV_FireGlock_Impl( args );
}
//======================
// GLOCK END
//======================
//======================
// SHOTGUN START
//======================
void EV_FireShotGunDouble( event_args_t *args )
{
int idx;
vec3_t origin;
vec3_t angles;
vec3_t velocity;
int j;
vec3_t ShellVelocity;
vec3_t ShellOrigin;
int shell;
vec3_t vecSrc, vecAiming;
//vec3_t vecSpread;
vec3_t up, right, forward;
//float flSpread = 0.01;
int empty = args->bparam1; // modif de Julien
idx = args->entindex;
VectorCopy( args->origin, origin );
VectorCopy( args->angles, angles );
VectorCopy( args->velocity, velocity );
AngleVectors( angles, forward, right, up );
shell = gEngfuncs.pEventAPI->EV_FindModelIndex("models/shotgunshell.mdl");// brass shell
if( EV_IsLocal( idx ) )
{
// Add muzzle flash to current weapon model
EV_MuzzleFlash();
gEngfuncs.pEventAPI->EV_WeaponAnimation( SHOTGUN_FIRE2, 2 );
V_PunchAxis( 0, -10.0 );
}
for( j = 0; j < 2; j++ )
{
EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 32, -12, 6 );
EV_EjectBrass( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHOTSHELL );
}
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/dbarrel1.wav", gEngfuncs.pfnRandomFloat( 0.98, 1.0 ), ATTN_NORM, 0, 85 + gEngfuncs.pfnRandomLong( 0, 0x1f ) );
EV_GetGunPosition( args, vecSrc, origin );
VectorCopy( forward, vecAiming );
if( gEngfuncs.GetMaxClients() > 1 )
{
EV_HLDM_FireBullets( idx, forward, right, up, 8, vecSrc, vecAiming, 2048, BULLET_PLAYER_BUCKSHOT_DOUBLE, 0, &g_tracerCount[idx - 1], 0.17365, 0.04362 );
}
else
{
//EV_HLDM_FireBullets( idx, forward, right, up, 12, vecSrc, vecAiming, 2048, BULLET_PLAYER_BUCKSHOT_DOUBLE, 0, &g_tracerCount[idx - 1], 0.08716, 0.08716 );
EV_HLDM_FireBulletsVect( idx, forward, right, up, 12, vecSrc, vecAiming, VECTOR_CONE_10DEGREES, 2048, BULLET_PLAYER_BUCKSHOT_DOUBLE, 0, &g_tracerCount[idx-1] );
}
}
void EV_FireShotGunSingle( event_args_t *args )
{
int idx;
vec3_t origin;
vec3_t angles;
vec3_t velocity;
vec3_t ShellVelocity;
vec3_t ShellOrigin;
int shell;
vec3_t vecSrc, vecAiming;
//vec3_t vecSpread;
vec3_t up, right, forward;
//float flSpread = 0.01;
idx = args->entindex;
VectorCopy( args->origin, origin );
VectorCopy( args->angles, angles );
VectorCopy( args->velocity, velocity );
AngleVectors( angles, forward, right, up );
shell = gEngfuncs.pEventAPI->EV_FindModelIndex("models/shotgunshell.mdl");// brass shell
if( EV_IsLocal( idx ) )
{
// Add muzzle flash to current weapon model
EV_MuzzleFlash();
gEngfuncs.pEventAPI->EV_WeaponAnimation( SHOTGUN_FIRE, 2 );
V_PunchAxis( 0, -5.0 );
}
EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 32, -12, 6 );
EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[YAW], shell, TE_BOUNCE_SHOTSHELL );
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/sbarrel1.wav", gEngfuncs.pfnRandomFloat( 0.95, 1.0 ), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0x1f ) );
EV_GetGunPosition( args, vecSrc, origin );
VectorCopy( forward, vecAiming );
if( gEngfuncs.GetMaxClients() > 1 )
{
EV_HLDM_FireBullets( idx, forward, right, up, 4, vecSrc, vecAiming, 2048, BULLET_PLAYER_BUCKSHOT, 0, &g_tracerCount[idx - 1], 0.08716, 0.04362 );
}
else
{
EV_HLDM_FireBullets( idx, forward, right, up, 6, vecSrc, vecAiming, 2048, BULLET_PLAYER_BUCKSHOT, 0, &g_tracerCount[idx - 1], 0.08716, 0.08716 );
}
}
//======================
// SHOTGUN END
//======================
//======================
// MP5 START
//======================
void EV_FireMP5( event_args_t *args )
{
int idx;
vec3_t origin;
vec3_t angles;
vec3_t velocity;
vec3_t ShellVelocity;
vec3_t ShellOrigin;
int shell;
vec3_t vecSrc, vecAiming;
vec3_t up, right, forward;
//float flSpread = 0.01;
idx = args->entindex;
VectorCopy( args->origin, origin );
VectorCopy( args->angles, angles );
VectorCopy( args->velocity, velocity );
AngleVectors( angles, forward, right, up );
shell = gEngfuncs.pEventAPI->EV_FindModelIndex("models/shell.mdl");// brass shell
if( EV_IsLocal( idx ) )
{
// Add muzzle flash to current weapon model
EV_MuzzleFlash();
gEngfuncs.pEventAPI->EV_WeaponAnimation( MP5_FIRE1 + gEngfuncs.pfnRandomLong( 0, 2 ), 2 );
V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -2, 2 ) );
}
EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 );
EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[YAW], shell, TE_BOUNCE_SHELL );
switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
{
case 0:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/hks1.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
break;
case 1:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/hks2.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
break;
}
EV_GetGunPosition( args, vecSrc, origin );
VectorCopy( forward, vecAiming );
//HLINVASION Julien
//EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_MP5, 2, &g_tracerCount[idx - 1], args->fparam1, args->fparam2 );
//Julien's code uses old Vector for vecSpread which is vec3_t, needs conversion.
if ( gEngfuncs.GetMaxClients() > 1 )
{
EV_HLDM_FireBulletsVect( idx, forward, right, up, 1, vecSrc, vecAiming, VECTOR_CONE_7DEGREES, 8192, BULLET_PLAYER_MP5, 2, &g_tracerCount[idx-1] );
}
else
{
EV_HLDM_FireBulletsVect( idx, forward, right, up, 1, vecSrc, vecAiming, VECTOR_CONE_7DEGREES, 8192, BULLET_PLAYER_MP5, 2, &g_tracerCount[idx-1] );
}
}
// We only predict the animation and sound
// The grenade is still launched from the server.
void EV_FireMP52( event_args_t *args )
{
int idx;
vec3_t origin;
vec3_t angles;
vec3_t velocity;
vec3_t vecSrc, vecAiming;
vec3_t up, right, forward;
idx = args->entindex;
VectorCopy( args->origin, origin );
VectorCopy( args->angles, angles );
VectorCopy( args->velocity, velocity );
AngleVectors( angles, forward, right, up );
//int idx;
//vec3_t origin;
//idx = args->entindex;
//VectorCopy( args->origin, origin );
if( EV_IsLocal( idx ) )
{
gEngfuncs.pEventAPI->EV_WeaponAnimation( MP5_LAUNCH, 2 );
V_PunchAxis( 0, -10 );
}
switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
{
case 0:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/glauncher.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
break;
case 1:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/glauncher2.wav", 1, ATTN_NORM, 0, 94 + gEngfuncs.pfnRandomLong( 0, 0xf ) );
break;
}
//modif de Julien - ejection de la cartouche
vec3_t ShellVelocity;
vec3_t ShellOrigin;
int shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/beretta_shell.mdl");// brass shell
EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 35, -12, 14 );
EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL );
}
//======================
// MP5 END
//======================
//======================
// JULIEN START
//======================
//modif de Julien
void EV_FireSG( event_args_t *args )
{
int idx;
idx = args->entindex;
if ( args->iparam2 == 1 )
{
// tir
if ( EV_IsLocal( idx ) )
{
V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( 8,10 ) );
}
}
cl_entity_t *pViewmodel = GetViewEntity();
pViewmodel->curstate.skin = args->iparam1;
}
void EV_FireM16( event_args_t *args )
{
int idx;
vec3_t origin;
vec3_t angles;
vec3_t velocity;
vec3_t ShellVelocity;
vec3_t ShellOrigin;
int shell;
vec3_t vecSrc, vecAiming;
vec3_t up, right, forward;
float flSpread = 0.01;
idx = args->entindex;
VectorCopy( args->origin, origin );
VectorCopy( args->angles, angles );
VectorCopy( args->velocity, velocity );
AngleVectors( angles, forward, right, up );
shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/m16_shell.mdl");// brass shell
if ( EV_IsLocal( idx ) )
{
// Add muzzle flash to current weapon model
EV_MuzzleFlash();
gEngfuncs.pEventAPI->EV_WeaponAnimation( M16_FIRE1, 2 );
}
EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 20, -12, 4 );
EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL );
switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
{
case 0:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/m16_shoot_1.wav", 1, 95, ATTN_NORM, 1 );
break;
case 1:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/m16_shoot_2.wav", 1, 95, ATTN_NORM, 1 );
break;
}
EV_GetGunPosition( args, vecSrc, origin );
VectorCopy( forward, vecAiming );
EV_HLDM_FireBulletsVect( idx, forward, right, up, 1, vecSrc, vecAiming, VECTOR_CONE_4DEGREES, 8192, BULLET_PLAYER_M16, 2, &g_tracerCount[idx-1] );
if ( EV_IsLocal( idx ) )
{
V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -4, 4 ) );
}
}
//modif de Julien
void EV_FireFSniper( event_args_t *args )
{
int idx;
vec3_t origin;
vec3_t angles;
vec3_t velocity;
vec3_t ShellVelocity;
vec3_t ShellOrigin;
int shell;
vec3_t vecSrc, vecAiming;
vec3_t up, right, forward;
float flSpread = 0.01;
idx = args->entindex;
VectorCopy( args->origin, origin );
VectorCopy( args->angles, angles );
VectorCopy( args->velocity, velocity );
AngleVectors( angles, forward, right, up );
if ( args->bparam1 )
{
shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/sniper_shell.mdl");
cl_entity_t *ent = GetViewEntity ();
float fR = gEngfuncs.pfnRandomFloat( 50, 70 );
float fU = gEngfuncs.pfnRandomFloat( 60, 100 );
for ( int i = 0; i < 3; i++ )
{
ShellVelocity[i] = velocity[i] + right[i] * -fR + up[i] * fU /*+ forward[i] * 25*/;
}
ShellOrigin = ent->attachment[1];
EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL );
return;
}
if ( EV_IsLocal( idx ) )
{
// Add muzzle flash to current weapon model
EV_MuzzleFlash();
gEngfuncs.pEventAPI->EV_WeaponAnimation( FSNIPER_FIRE1, 2 );
}
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/fsniper_shoot1.wav", 1, 95, ATTN_NORM, 1 );
EV_GetGunPosition( args, vecSrc, origin );
VectorCopy( forward, vecAiming );
EV_HLDM_FireBulletsVect( idx, forward, right, up, 1, vecSrc, vecAiming, Vector(0,0,0)/*VECTOR_CONE_1DEGREES*/, 8192, BULLET_PLAYER_SNIPER, 1, &g_tracerCount[idx-1] );
if ( EV_IsLocal( idx ) )
{
V_PunchAxis( 0, gEngfuncs.pfnRandomFloat( -0.5, 0.5 ) );
}
}
// modif de Julien
void EV_FireIRgun( event_args_t *args )
{
int idx;
vec3_t origin;
vec3_t angles;
vec3_t velocity;
vec3_t vecSrc, vecAiming;
vec3_t up, right, forward;
float flSpread = 0.01;
idx = args->entindex;
VectorCopy( args->origin, origin );
VectorCopy( args->angles, angles );
VectorCopy( args->velocity, velocity );
AngleVectors( angles, forward, right, up );
if ( EV_IsLocal( idx ) )
{
// Add muzzle flash to current weapon model
EV_MuzzleFlash();
int empty = args->bparam1; // modif de Julien
if ( empty == 1 )
gEngfuncs.pEventAPI->EV_WeaponAnimation( IRGUN_FIRE_EMPTY, 2 );
else
gEngfuncs.pEventAPI->EV_WeaponAnimation( IRGUN_FIRE1, 2 );
}
/*
switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
{
case 0:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/357_shot1.wav", gEngfuncs.pfnRandomFloat(0.8, 0.9), ATTN_NORM, 0, PITCH_NORM );
break;
case 1:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/357_shot2.wav", gEngfuncs.pfnRandomFloat(0.8, 0.9), ATTN_NORM, 0, PITCH_NORM );
break;
}*/
switch( gEngfuncs.pfnRandomLong( 0, 2 ) )
{
case 0:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "hassault/hw_shoot1.wav", gEngfuncs.pfnRandomFloat(0.8, 0.9), ATTN_NORM, 0, PITCH_NORM );
break;
case 1:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "hassault/hw_shoot2.wav", gEngfuncs.pfnRandomFloat(0.8, 0.9), ATTN_NORM, 0, PITCH_NORM );
break;
case 2:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "hassault/hw_shoot3.wav", gEngfuncs.pfnRandomFloat(0.8, 0.9), ATTN_NORM, 0, PITCH_NORM );
break;
}
EV_GetGunPosition( args, vecSrc, origin );
VectorCopy( forward, vecAiming );
EV_HLDM_FireBulletsVect( idx, forward, right, up, 1, vecSrc, vecAiming, VECTOR_CONE_1DEGREES, 8192, BULLET_PLAYER_IRGUN, 0, &g_tracerCount[idx-1] );
if ( EV_IsLocal( idx ) )
{
V_PunchAxis( 0, -10.0 );
}
//modif de Julien - ejection de la cartouche
vec3_t ShellVelocity;
vec3_t ShellOrigin;
int shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/beretta_shell.mdl");// brass shell
EV_GetDefaultShellInfo( args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 35, -12, 14 );
EV_EjectBrass ( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL );
}
//======================
// JULIEN END
//======================
//======================
// PHYTON START
// ( .357 )
//======================
void EV_FirePython( event_args_t *args )
{
int idx;
vec3_t origin;
vec3_t angles;
vec3_t velocity;
vec3_t vecSrc, vecAiming;
vec3_t up, right, forward;
//float flSpread = 0.01;
idx = args->entindex;
VectorCopy( args->origin, origin );
VectorCopy( args->angles, angles );
VectorCopy( args->velocity, velocity );
AngleVectors( angles, forward, right, up );
if( EV_IsLocal( idx ) )
{
// Python uses different body in multiplayer versus single player
int multiplayer = gEngfuncs.GetMaxClients() == 1 ? 0 : 1;
// Add muzzle flash to current weapon model
EV_MuzzleFlash();
int empty = args->bparam1; // modif de Julien
if ( empty == 1 )
gEngfuncs.pEventAPI->EV_WeaponAnimation( PYTHON_FIRE_EMPTY, 2 );
else
gEngfuncs.pEventAPI->EV_WeaponAnimation( PYTHON_FIRE1, 2 );
// gEngfuncs.pEventAPI->EV_WeaponAnimation( PYTHON_FIRE1, multiplayer ? 1 : 0 );
V_PunchAxis( 0, -10.0 );
}
switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
{
case 0:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/357_shot1.wav", gEngfuncs.pfnRandomFloat( 0.8, 0.9 ), ATTN_NORM, 0, PITCH_NORM );
break;
case 1:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/357_shot2.wav", gEngfuncs.pfnRandomFloat( 0.8, 0.9 ), ATTN_NORM, 0, PITCH_NORM );
break;
}
EV_GetGunPosition( args, vecSrc, origin );
VectorCopy( forward, vecAiming );
EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, BULLET_PLAYER_357, 0, &g_tracerCount[idx - 1], args->fparam1, args->fparam2 );
}
//======================
// PHYTON END
// ( .357 )
//======================
//======================
// GAUSS START
//======================
#define SND_STOP (1 << 5)
#define SND_CHANGE_PITCH (1 << 7) // duplicated in protocol.h change sound pitch
void EV_SpinGauss( event_args_t *args )
{
int idx;
vec3_t origin;
vec3_t angles;
vec3_t velocity;
int iSoundState = 0;
int pitch;
idx = args->entindex;
VectorCopy( args->origin, origin );
VectorCopy( args->angles, angles );
VectorCopy( args->velocity, velocity );
pitch = args->iparam1;
iSoundState = args->bparam1 ? SND_CHANGE_PITCH : 0;
iSoundState = args->bparam2 ? SND_STOP : iSoundState;
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "ambience/pulsemachine.wav", 1.0, ATTN_NORM, iSoundState, pitch );
}
/*
==============================
EV_StopPreviousGauss
==============================
*/
void EV_StopPreviousGauss( int idx )
{
// Make sure we don't have a gauss spin event in the queue for this guy
gEngfuncs.pEventAPI->EV_KillEvents( idx, "events/gaussspin.sc" );
gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_WEAPON, "ambience/pulsemachine.wav" );
}
extern float g_flApplyVel;
void EV_FireGauss( event_args_t *args )
{
int idx;
vec3_t origin;
vec3_t angles;
vec3_t velocity;
float flDamage = args->fparam1;
//int primaryfire = args->bparam1;
int m_fPrimaryFire = args->bparam1;
//int m_iWeaponVolume = GAUSS_PRIMARY_FIRE_VOLUME;
vec3_t vecSrc;
vec3_t vecDest;
//edict_t *pentIgnore;
pmtrace_t tr, beam_tr;
float flMaxFrac = 1.0;
//int nTotal = 0;
int fHasPunched = 0;
int fFirstBeam = 1;
int nMaxHits = 10;
physent_t *pEntity;
int m_iBeam, m_iGlow, m_iBalls;
vec3_t up, right, forward;
idx = args->entindex;
VectorCopy( args->origin, origin );
VectorCopy( args->angles, angles );
VectorCopy( args->velocity, velocity );
if( args->bparam2 )
{
EV_StopPreviousGauss( idx );
return;
}
//Con_Printf( "Firing gauss with %f\n", flDamage );
EV_GetGunPosition( args, vecSrc, origin );
m_iBeam = gEngfuncs.pEventAPI->EV_FindModelIndex( "sprites/smoke.spr" );
m_iBalls = m_iGlow = gEngfuncs.pEventAPI->EV_FindModelIndex( "sprites/hotglow.spr" );
AngleVectors( angles, forward, right, up );
VectorMA( vecSrc, 8192, forward, vecDest );
if( EV_IsLocal( idx ) )
{
V_PunchAxis( 0.0f, -2.0f );
gEngfuncs.pEventAPI->EV_WeaponAnimation( GAUSS_FIRE2, 2 );
if( m_fPrimaryFire == false )
g_flApplyVel = flDamage;
}
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/gauss2.wav", 0.5f + flDamage * ( 1.0f / 400.0f ), ATTN_NORM, 0, 85 + gEngfuncs.pfnRandomLong( 0, 0x1f ) );
while( flDamage > 10 && nMaxHits > 0 )
{
nMaxHits--;
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 );
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecDest, PM_STUDIO_BOX, -1, &tr );
gEngfuncs.pEventAPI->EV_PopPMStates();
if( tr.allsolid )
break;
if( fFirstBeam )
{
if( EV_IsLocal( idx ) )
{
// Add muzzle flash to current weapon model
EV_MuzzleFlash();
}
fFirstBeam = 0;
gEngfuncs.pEfxAPI->R_BeamEntPoint(
idx | 0x1000,
tr.endpos,
m_iBeam,
0.1f,
m_fPrimaryFire ? 1.0f : 2.5f,
0.0f,
(m_fPrimaryFire ? 128.0f : flDamage) / 255.0f,
0,
0,
0,
(m_fPrimaryFire ? 255 : 255) / 255.0f,
(m_fPrimaryFire ? 128 : 255) / 255.0f,
(m_fPrimaryFire ? 0 : 255) / 255.0f
);
}
else
{
gEngfuncs.pEfxAPI->R_BeamPoints( vecSrc,
tr.endpos,
m_iBeam,
0.1f,
m_fPrimaryFire ? 1.0f : 2.5f,
0.0f,
(m_fPrimaryFire ? 128.0f : flDamage) / 255.0f,
0,
0,
0,
(m_fPrimaryFire ? 255 : 255) / 255.0f,
(m_fPrimaryFire ? 128 : 255) / 255.0f,
(m_fPrimaryFire ? 0 : 255) / 255.0f
);
}
pEntity = gEngfuncs.pEventAPI->EV_GetPhysent( tr.ent );
if( pEntity == NULL )
break;
if( pEntity->solid == SOLID_BSP )
{
float n;
//pentIgnore = NULL;
n = -DotProduct( tr.plane.normal, forward );
if( n < 0.5f ) // 60 degrees
{
vec3_t r;
VectorMA( forward, 2.0f * n, tr.plane.normal, r );
flMaxFrac = flMaxFrac - tr.fraction;
VectorCopy( r, forward );
VectorMA( tr.endpos, 8.0, forward, vecSrc );
VectorMA( vecSrc, 8192.0, forward, vecDest );
gEngfuncs.pEfxAPI->R_TempSprite( tr.endpos, vec3_origin, 0.2, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage * n / 255.0f, flDamage * n * 0.5f * 0.1f, FTENT_FADEOUT );
vec3_t fwd;
VectorAdd( tr.endpos, tr.plane.normal, fwd );
gEngfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, tr.endpos, fwd, m_iBalls, 3, 0.1, gEngfuncs.pfnRandomFloat( 10.0f, 20.0f ) / 100.0f, 100,
255, 100 );
// lose energy
if( n == 0.0f )
{
n = 0.1f;
}
flDamage = flDamage * ( 1 - n );
}
else
{
// tunnel
EV_HLDM_DecalGunshot( &tr, BULLET_MONSTER_12MM );
gEngfuncs.pEfxAPI->R_TempSprite( tr.endpos, vec3_origin, 1.0, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage / 255.0f, 6.0f, FTENT_FADEOUT );
// limit it to one hole punch
if( fHasPunched )
{
break;
}
fHasPunched = 1;
// try punching through wall if secondary attack (primary is incapable of breaking through)
if( !m_fPrimaryFire )
{
vec3_t start;
VectorMA( tr.endpos, 8.0, forward, start );
// Store off the old count
gEngfuncs.pEventAPI->EV_PushPMStates();
// Now add in all of the players.
gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( start, vecDest, PM_STUDIO_BOX, -1, &beam_tr );
if( !beam_tr.allsolid )
{
vec3_t delta;
// trace backwards to find exit point
gEngfuncs.pEventAPI->EV_PlayerTrace( beam_tr.endpos, tr.endpos, PM_STUDIO_BOX, -1, &beam_tr );
VectorSubtract( beam_tr.endpos, tr.endpos, delta );
n = Length( delta );
if( n < flDamage )
{
if( n == 0 )
n = 1;
flDamage -= n;
// absorption balls
{
vec3_t fwd;
VectorSubtract( tr.endpos, forward, fwd );
gEngfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, tr.endpos, fwd, m_iBalls, 3, 0.1, gEngfuncs.pfnRandomFloat( 10.0f, 20.0f ) / 100.0f, 100,
255, 100 );
}
//////////////////////////////////// WHAT TO DO HERE
// CSoundEnt::InsertSound( bits_SOUND_COMBAT, pev->origin, NORMAL_EXPLOSION_VOLUME, 3.0 );
EV_HLDM_DecalGunshot( &beam_tr, BULLET_MONSTER_12MM );
gEngfuncs.pEfxAPI->R_TempSprite( beam_tr.endpos, vec3_origin, 0.1, m_iGlow, kRenderGlow, kRenderFxNoDissipation, flDamage / 255.0f, 6.0f, FTENT_FADEOUT );
// balls
{
vec3_t fwd;
VectorSubtract( beam_tr.endpos, forward, fwd );
gEngfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, beam_tr.endpos, fwd, m_iBalls, (int)( flDamage * 0.3f ), 0.1, gEngfuncs.pfnRandomFloat( 10.0f, 20.0f ) / 100.0f, 200,
255, 40 );
}
VectorAdd( beam_tr.endpos, forward, vecSrc );
}
}
else
{
flDamage = 0;
}
gEngfuncs.pEventAPI->EV_PopPMStates();
}
else
{
if( m_fPrimaryFire )
{
// slug doesn't punch through ever with primary
// fire, so leave a little glowy bit and make some balls
gEngfuncs.pEfxAPI->R_TempSprite( tr.endpos, vec3_origin, 0.2, m_iGlow, kRenderGlow, kRenderFxNoDissipation, 200.0f / 255.0f, 0.3, FTENT_FADEOUT );
{
vec3_t fwd;
VectorAdd( tr.endpos, tr.plane.normal, fwd );
gEngfuncs.pEfxAPI->R_Sprite_Trail( TE_SPRITETRAIL, tr.endpos, fwd, m_iBalls, 8, 0.6, gEngfuncs.pfnRandomFloat( 10.0f, 20.0f ) / 100.0f, 100,
255, 200 );
}
}
flDamage = 0;
}
}
}
else
{
VectorAdd( tr.endpos, forward, vecSrc );
}
}
}
//======================
// GAUSS END
//======================
//======================
// CROWBAR START
//======================
enum crowbar_e //This needs to be copied to crowbar.cpp //A quirk from times long past, reuired to get the animations to play on Client. modif de Roy
{
/*CROWBAR_IDLE = 0,
CROWBAR_DRAW,
CROWBAR_HOLSTER,
CROWBAR_ATTACK1HIT,
CROWBAR_ATTACK1MISS,
CROWBAR_ATTACK2MISS,
CROWBAR_ATTACK2HIT,
CROWBAR_ATTACK3MISS,
#if !CROWBAR_IDLE_ANIM
CROWBAR_ATTACK3HIT
#else
CROWBAR_ATTACK3HIT,
#endif
CROWBAR_IDLE2,
CROWBAR_IDLE3*/
//modif de Julien : nouveau crowbar
CROWBAR_IDLE = 0,
CROWBAR_DRAW,
CROWBAR_ATTACK1HIT,
CROWBAR_ATTACK1MISS,
CROWBAR_ATTACK2HIT,
CROWBAR_ATTACK2MISS,
};
int g_iSwing;
//Only predict the miss sounds, hit sounds are still played
//server side, so players don't get the wrong idea.
void EV_Crowbar( event_args_t *args )
{
int idx;
vec3_t origin;
//vec3_t angles;
//vec3_t velocity;
idx = args->entindex;
VectorCopy( args->origin, origin );
//Play Swing sound
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/cbar_miss1.wav", 1, ATTN_NORM, 0, PITCH_NORM );
if( EV_IsLocal( idx ) )
{
switch( (g_iSwing++) % 2/*3*/ ) //modif de Roy para Julien
{
case 0:
gEngfuncs.pEventAPI->EV_WeaponAnimation( CROWBAR_ATTACK1MISS, 1 );
break;
case 1:
gEngfuncs.pEventAPI->EV_WeaponAnimation( CROWBAR_ATTACK2MISS, 1 );
break;
/*case 2:
gEngfuncs.pEventAPI->EV_WeaponAnimation( CROWBAR_ATTACK3MISS, 1 );
break;*/
}
}
}
//======================
// CROWBAR END
//======================
//======================
// CROSSBOW START
//======================
enum crossbow_e
{
CROSSBOW_IDLE1 = 0, // full
CROSSBOW_IDLE2, // empty
CROSSBOW_FIDGET1, // full
CROSSBOW_FIDGET2, // empty
CROSSBOW_FIRE1, // full
CROSSBOW_FIRE2, // reload
CROSSBOW_FIRE3, // empty
CROSSBOW_RELOAD, // from empty
CROSSBOW_DRAW1, // full
CROSSBOW_DRAW2, // empty
CROSSBOW_HOLSTER1, // full
CROSSBOW_HOLSTER2 // empty
};
//=====================
// EV_BoltCallback
// This function is used to correct the origin and angles
// of the bolt, so it looks like it's stuck on the wall.
//=====================
void EV_BoltCallback( struct tempent_s *ent, float frametime, float currenttime )
{
ent->entity.origin = ent->entity.baseline.vuser1;
ent->entity.angles = ent->entity.baseline.vuser2;
}
void EV_FireCrossbow2( event_args_t *args )
{
vec3_t vecSrc, vecEnd;
vec3_t up, right, forward;
pmtrace_t tr;
int idx;
vec3_t origin;
vec3_t angles;
vec3_t velocity;
idx = args->entindex;
VectorCopy( args->origin, origin );
VectorCopy( args->angles, angles );
VectorCopy( args->velocity, velocity );
AngleVectors( angles, forward, right, up );
EV_GetGunPosition( args, vecSrc, origin );
VectorMA( vecSrc, 8192, forward, vecEnd );
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/xbow_fire1.wav", 1, ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0xF ) );
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_ITEM, "weapons/xbow_reload1.wav", gEngfuncs.pfnRandomFloat( 0.95f, 1.0f ), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0xF ) );
if( EV_IsLocal( idx ) )
{
if( args->iparam1 )
gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE1, 1 );
else
gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE3, 1 );
}
// Store off the old count
gEngfuncs.pEventAPI->EV_PushPMStates();
// Now add in all of the players.
gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr );
//We hit something
if( tr.fraction < 1.0f )
{
physent_t *pe = gEngfuncs.pEventAPI->EV_GetPhysent( tr.ent );
//Not the world, let's assume we hit something organic ( dog, cat, uncle joe, etc ).
if( pe->solid != SOLID_BSP )
{
switch( gEngfuncs.pfnRandomLong( 0, 1 ) )
{
case 0:
gEngfuncs.pEventAPI->EV_PlaySound( idx, tr.endpos, CHAN_BODY, "weapons/xbow_hitbod1.wav", 1, ATTN_NORM, 0, PITCH_NORM );
break;
case 1:
gEngfuncs.pEventAPI->EV_PlaySound( idx, tr.endpos, CHAN_BODY, "weapons/xbow_hitbod2.wav", 1, ATTN_NORM, 0, PITCH_NORM );
break;
}
}
//Stick to world but don't stick to glass, it might break and leave the bolt floating. It can still stick to other non-transparent breakables though.
else if( pe->rendermode == kRenderNormal )
{
gEngfuncs.pEventAPI->EV_PlaySound( 0, tr.endpos, CHAN_BODY, "weapons/xbow_hit1.wav", gEngfuncs.pfnRandomFloat( 0.95f, 1.0f ), ATTN_NORM, 0, PITCH_NORM );
//Not underwater, do some sparks...
if( gEngfuncs.PM_PointContents( tr.endpos, NULL ) != CONTENTS_WATER )
gEngfuncs.pEfxAPI->R_SparkShower( tr.endpos );
vec3_t vBoltAngles;
int iModelIndex = gEngfuncs.pEventAPI->EV_FindModelIndex( "models/crossbow_bolt.mdl" );
VectorAngles( forward, vBoltAngles );
TEMPENTITY *bolt = gEngfuncs.pEfxAPI->R_TempModel( tr.endpos - forward * 10, Vector( 0, 0, 0 ), vBoltAngles , 5, iModelIndex, TE_BOUNCE_NULL );
if( bolt )
{
bolt->flags |= ( FTENT_CLIENTCUSTOM ); //So it calls the callback function.
bolt->entity.baseline.vuser1 = tr.endpos - forward * 10; // Pull out a little bit
bolt->entity.baseline.vuser2 = vBoltAngles; //Look forward!
bolt->callback = EV_BoltCallback; //So we can set the angles and origin back. (Stick the bolt to the wall)
}
}
}
gEngfuncs.pEventAPI->EV_PopPMStates();
}
//TODO: Fully predict the fliying bolt.
void EV_FireCrossbow( event_args_t *args )
{
int idx;
vec3_t origin;
idx = args->entindex;
VectorCopy( args->origin, origin );
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/xbow_fire1.wav", 1, ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0xF ) );
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_ITEM, "weapons/xbow_reload1.wav", gEngfuncs.pfnRandomFloat( 0.95f, 1.0f ), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0xF ) );
//Only play the weapon anims if I shot it.
if( EV_IsLocal( idx ) )
{
if( args->iparam1 )
gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE1, 1 );
else
gEngfuncs.pEventAPI->EV_WeaponAnimation( CROSSBOW_FIRE3, 1 );
V_PunchAxis( 0.0f, -2.0f );
}
}
//======================
// CROSSBOW END
//======================
//======================
// RPG START
//======================
enum rpg_e
{
RPG_IDLE = 0,
RPG_FIDGET,
RPG_RELOAD, // to reload
RPG_FIRE2, // to empty
RPG_HOLSTER1, // loaded
RPG_DRAW1, // loaded
RPG_HOLSTER2, // unloaded
RPG_DRAW_UL, // unloaded
RPG_IDLE_UL, // unloaded idle
RPG_FIDGET_UL // unloaded fidget
};
void EV_FireRpg( event_args_t *args )
{
int idx;
vec3_t origin;
idx = args->entindex;
VectorCopy( args->origin, origin );
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "weapons/rocketfire1.wav", 0.9, ATTN_NORM, 0, PITCH_NORM );
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_ITEM, "weapons/glauncher.wav", 0.7, ATTN_NORM, 0, PITCH_NORM );
//Only play the weapon anims if I shot it.
if( EV_IsLocal( idx ) )
{
gEngfuncs.pEventAPI->EV_WeaponAnimation( RPG_FIRE2, 1 );
V_PunchAxis( 0, -5.0 );
}
}
//======================
// RPG END
//======================
//======================
// EGON START
//======================
enum egon_e
{
EGON_IDLE1 = 0,
EGON_FIDGET1,
EGON_ALTFIREON,
EGON_ALTFIRECYCLE,
EGON_ALTFIREOFF,
EGON_FIRE1,
EGON_FIRE2,
EGON_FIRE3,
EGON_FIRE4,
EGON_DRAW,
EGON_HOLSTER
};
int g_fireAnims1[] = { EGON_FIRE1, EGON_FIRE2, EGON_FIRE3, EGON_FIRE4 };
int g_fireAnims2[] = { EGON_ALTFIRECYCLE };
enum EGON_FIRESTATE
{
FIRE_OFF,
FIRE_CHARGE
};
enum EGON_FIREMODE
{
FIRE_NARROW,
FIRE_WIDE
};
#define EGON_PRIMARY_VOLUME 450
#define EGON_BEAM_SPRITE "sprites/xbeam1.spr"
#define EGON_FLARE_SPRITE "sprites/XSpark1.spr"
#define EGON_SOUND_OFF "weapons/egon_off1.wav"
#define EGON_SOUND_RUN "weapons/egon_run3.wav"
#define EGON_SOUND_STARTUP "weapons/egon_windup2.wav"
#if !defined(ARRAYSIZE)
#define ARRAYSIZE(p) ( sizeof(p) /sizeof(p[0]) )
#endif
BEAM *pBeam;
BEAM *pBeam2;
TEMPENTITY *pFlare; // Vit_amiN: egon's beam flare
void EV_EgonFlareCallback( struct tempent_s *ent, float frametime, float currenttime )
{
float delta = currenttime - ent->tentOffset.z; // time past since the last scale
if( delta >= ent->tentOffset.y )
{
ent->entity.curstate.scale += ent->tentOffset.x * delta;
ent->tentOffset.z = currenttime;
}
}
void EV_EgonFire( event_args_t *args )
{
int idx, /*iFireState,*/ iFireMode;
vec3_t origin;
idx = args->entindex;
VectorCopy( args->origin, origin );
//iFireState = args->iparam1;
iFireMode = args->iparam2;
int iStartup = args->bparam1;
if( iStartup )
{
if( iFireMode == FIRE_WIDE )
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, EGON_SOUND_STARTUP, 0.98, ATTN_NORM, 0, 125 );
else
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, EGON_SOUND_STARTUP, 0.9, ATTN_NORM, 0, 100 );
}
else
{
// If there is any sound playing already, kill it. - Solokiller
// This is necessary because multiple sounds can play on the same channel at the same time.
// In some cases, more than 1 run sound plays when the egon stops firing, in which case only the earliest entry in the list is stopped.
// This ensures no more than 1 of those is ever active at the same time.
gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_STATIC, EGON_SOUND_RUN );
if( iFireMode == FIRE_WIDE )
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, EGON_SOUND_RUN, 0.98, ATTN_NORM, 0, 125 );
else
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, EGON_SOUND_RUN, 0.9, ATTN_NORM, 0, 100 );
}
//Only play the weapon anims if I shot it.
if( EV_IsLocal( idx ) )
gEngfuncs.pEventAPI->EV_WeaponAnimation( g_fireAnims1[gEngfuncs.pfnRandomLong( 0, 3 )], 1 );
if( iStartup == 1 && EV_IsLocal( idx ) && !( pBeam || pBeam2 || pFlare ) && cl_lw->value ) //Adrian: Added the cl_lw check for those lital people that hate weapon prediction.
{
vec3_t vecSrc, vecEnd, angles, forward, right, up;
pmtrace_t tr;
cl_entity_t *pl = gEngfuncs.GetEntityByIndex( idx );
if( pl )
{
VectorCopy( gHUD.m_vecAngles, angles );
AngleVectors( angles, forward, right, up );
EV_GetGunPosition( args, vecSrc, pl->origin );
VectorMA( vecSrc, 2048, forward, vecEnd );
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 );
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecEnd, PM_STUDIO_BOX, -1, &tr );
gEngfuncs.pEventAPI->EV_PopPMStates();
int iBeamModelIndex = gEngfuncs.pEventAPI->EV_FindModelIndex( EGON_BEAM_SPRITE );
float r = 50.0f;
float g = 50.0f;
float b = 125.0f;
// if( IEngineStudio.IsHardware() )
{
r /= 255.0f;
g /= 255.0f;
b /= 255.0f;
}
pBeam = gEngfuncs.pEfxAPI->R_BeamEntPoint( idx | 0x1000, tr.endpos, iBeamModelIndex, 99999, 3.5, 0.2, 0.7, 55, 0, 0, r, g, b );
if( pBeam )
pBeam->flags |= ( FBEAM_SINENOISE );
pBeam2 = gEngfuncs.pEfxAPI->R_BeamEntPoint( idx | 0x1000, tr.endpos, iBeamModelIndex, 99999, 5.0, 0.08, 0.7, 25, 0, 0, r, g, b );
// Vit_amiN: egon beam flare
pFlare = gEngfuncs.pEfxAPI->R_TempSprite( tr.endpos, vec3_origin, 1.0, gEngfuncs.pEventAPI->EV_FindModelIndex( EGON_FLARE_SPRITE ), kRenderGlow, kRenderFxNoDissipation, 1.0, 99999, FTENT_SPRCYCLE | FTENT_PERSIST );
}
}
if( pFlare ) // Vit_amiN: store the last mode for EV_EgonStop()
{
pFlare->tentOffset.x = ( iFireMode == FIRE_WIDE ) ? 1.0f : 0.0f;
}
}
void EV_EgonStop( event_args_t *args )
{
int idx;
vec3_t origin;
idx = args->entindex;
VectorCopy( args->origin, origin );
gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_STATIC, EGON_SOUND_RUN );
if( args->iparam1 )
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, EGON_SOUND_OFF, 0.98, ATTN_NORM, 0, 100 );
if( EV_IsLocal( idx ) )
{
if( pBeam )
{
pBeam->die = 0.0f;
pBeam = NULL;
}
if( pBeam2 )
{
pBeam2->die = 0.0f;
pBeam2 = NULL;
}
if( pFlare ) // Vit_amiN: egon beam flare
{
pFlare->die = gEngfuncs.GetClientTime();
if( gEngfuncs.GetMaxClients() == 1 || !(pFlare->flags & FTENT_NOMODEL) )
{
if( pFlare->tentOffset.x != 0.0f ) // true for iFireMode == FIRE_WIDE
{
pFlare->callback = &EV_EgonFlareCallback;
pFlare->fadeSpeed = 2.0; // fade out will take 0.5 sec
pFlare->tentOffset.x = 10.0; // scaling speed per second
pFlare->tentOffset.y = 0.1; // min time between two scales
pFlare->tentOffset.z = pFlare->die; // the last callback run time
pFlare->flags = FTENT_FADEOUT | FTENT_CLIENTCUSTOM;
}
}
pFlare = NULL;
}
}
}
//======================
// EGON END
//======================
//======================
// HORNET START
//======================
enum hgun_e
{
HGUN_IDLE1 = 0,
HGUN_FIDGETSWAY,
HGUN_FIDGETSHAKE,
HGUN_DOWN,
HGUN_UP,
HGUN_SHOOT
};
void EV_HornetGunFire( event_args_t *args )
{
int idx; //, iFireMode;
vec3_t origin, angles; //, vecSrc, forward, right, up;
idx = args->entindex;
VectorCopy( args->origin, origin );
VectorCopy( args->angles, angles );
//iFireMode = args->iparam1;
//Only play the weapon anims if I shot it.
if( EV_IsLocal( idx ) )
{
V_PunchAxis( 0, gEngfuncs.pfnRandomLong( 0, 2 ) );
gEngfuncs.pEventAPI->EV_WeaponAnimation( HGUN_SHOOT, 1 );
}
switch( gEngfuncs.pfnRandomLong( 0, 2 ) )
{
case 0:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "agrunt/ag_fire1.wav", 1, ATTN_NORM, 0, 100 );
break;
case 1:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "agrunt/ag_fire2.wav", 1, ATTN_NORM, 0, 100 );
break;
case 2:
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, "agrunt/ag_fire3.wav", 1, ATTN_NORM, 0, 100 );
break;
}
}
//======================
// HORNET END
//======================
//======================
// TRIPMINE START
//======================
enum tripmine_e
{
TRIPMINE_IDLE1 = 0,
TRIPMINE_IDLE2,
TRIPMINE_ARM1,
TRIPMINE_ARM2,
TRIPMINE_FIDGET,
TRIPMINE_HOLSTER,
TRIPMINE_DRAW,
TRIPMINE_WORLD,
TRIPMINE_GROUND
};
//We only check if it's possible to put a trip mine
//and if it is, then we play the animation. Server still places it.
void EV_TripmineFire( event_args_t *args )
{
int idx;
vec3_t vecSrc, angles, view_ofs, forward;
pmtrace_t tr;
idx = args->entindex;
VectorCopy( args->origin, vecSrc );
VectorCopy( args->angles, angles );
AngleVectors( angles, forward, NULL, NULL );
if( !EV_IsLocal ( idx ) )
return;
// Grab predicted result for local player
gEngfuncs.pEventAPI->EV_LocalPlayerViewheight( view_ofs );
vecSrc = vecSrc + view_ofs;
// Store off the old count
gEngfuncs.pEventAPI->EV_PushPMStates();
// Now add in all of the players.
gEngfuncs.pEventAPI->EV_SetSolidPlayers ( idx - 1 );
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc, vecSrc + forward * 128.0f, PM_NORMAL, -1, &tr );
//Hit something solid
if( tr.fraction < 1.0f )
gEngfuncs.pEventAPI->EV_WeaponAnimation ( TRIPMINE_DRAW, 0 );
gEngfuncs.pEventAPI->EV_PopPMStates();
}
//======================
// TRIPMINE END
//======================
//======================
// SQUEAK START
//======================
enum squeak_e
{
SQUEAK_IDLE1 = 0,
SQUEAK_FIDGETFIT,
SQUEAK_FIDGETNIP,
SQUEAK_DOWN,
SQUEAK_UP,
SQUEAK_THROW
};
#define VEC_HULL_MIN Vector( -16, -16, -36 )
#define VEC_DUCK_HULL_MIN Vector( -16, -16, -18 )
void EV_SnarkFire( event_args_t *args )
{
int idx;
vec3_t vecSrc, angles, /*view_ofs,*/ forward;
pmtrace_t tr;
idx = args->entindex;
VectorCopy( args->origin, vecSrc );
VectorCopy( args->angles, angles );
AngleVectors( angles, forward, NULL, NULL );
if( !EV_IsLocal ( idx ) )
return;
if( args->ducking )
vecSrc = vecSrc - ( VEC_HULL_MIN - VEC_DUCK_HULL_MIN );
// Store off the old count
gEngfuncs.pEventAPI->EV_PushPMStates();
// Now add in all of the players.
gEngfuncs.pEventAPI->EV_SetSolidPlayers( idx - 1 );
gEngfuncs.pEventAPI->EV_SetTraceHull( 2 );
gEngfuncs.pEventAPI->EV_PlayerTrace( vecSrc + forward * 20, vecSrc + forward * 64, PM_NORMAL, -1, &tr );
//Find space to drop the thing.
if( tr.allsolid == 0 && tr.startsolid == 0 && tr.fraction > 0.25f )
gEngfuncs.pEventAPI->EV_WeaponAnimation( SQUEAK_THROW, 0 );
gEngfuncs.pEventAPI->EV_PopPMStates();
}
//======================
// SQUEAK END
//======================
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;
const char *pszSound;
idx = args->entindex;
VectorCopy( args->origin, origin );
us_params = (unsigned short)args->iparam1;
stop = args->bparam1;
m_flVolume = (float)( us_params & 0x003f ) / 40.0f;
noise = (int)( ( ( us_params ) >> 12 ) & 0x0007 );
pitch = (int)( 10.0f * (float)( ( us_params >> 6 ) & 0x003f ) );
switch( noise )
{
case 1:
pszSound = "plats/ttrain1.wav";
break;
case 2:
pszSound = "plats/ttrain2.wav";
break;
case 3:
pszSound = "plats/ttrain3.wav";
break;
case 4:
pszSound = "plats/ttrain4.wav";
break;
case 5:
pszSound = "plats/ttrain6.wav";
break;
case 6:
pszSound = "plats/ttrain7.wav";
break;
default:
// no sound
return;
}
if( stop )
{
gEngfuncs.pEventAPI->EV_StopSound( idx, CHAN_STATIC, pszSound );
}
else
{
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_STATIC, pszSound, m_flVolume, ATTN_NORM, SND_CHANGE_PITCH, pitch );
}
}
int EV_TFC_IsAllyTeam( int iTeam1, int iTeam2 )
{
return 0;
}