forked from vera/halflife-thewastes-sdk
2252 lines
63 KiB
C++
2252 lines
63 KiB
C++
/***
|
|
*
|
|
* Copyright (c) 1996-2001, 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_thewastes.h"
|
|
|
|
#include "r_efx.h"
|
|
#include "event_api.h"
|
|
#include "event_args.h"
|
|
#include "in_defs.h"
|
|
#include "tw_common.h"
|
|
|
|
#include <string.h>
|
|
|
|
static int tracerCount[ 32 ];
|
|
|
|
#define DISABLE_PENETRATION 0 // Disables client side wall penetration
|
|
|
|
#ifndef M_PI
|
|
#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h
|
|
#endif
|
|
|
|
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;
|
|
|
|
// Used for gun recoil
|
|
extern cl_enginefunc_t gEngfuncs;
|
|
|
|
// Thermal vision on the client
|
|
extern int ev_thermal;
|
|
|
|
extern "C"
|
|
{
|
|
// Events
|
|
void EV_BerettaShoot (struct event_args_s *args);
|
|
void EV_ColtShoot (struct event_args_s *args);
|
|
void EV_DeagleShoot (struct event_args_s *args);
|
|
void EV_RugerShoot (struct event_args_s *args);
|
|
void EV_HandcannonShoot(struct event_args_s *args);
|
|
void EV_SawedOffShoot (struct event_args_s *args);
|
|
void EV_MossbergShoot (struct event_args_s *args);
|
|
void EV_WinchesterShoot(struct event_args_s *args);
|
|
void EV_Smg9Shoot (struct event_args_s *args);
|
|
void EV_FnFalShoot (struct event_args_s *args);
|
|
void EV_TommyGunShoot (struct event_args_s *args);
|
|
void EV_JackHammerShoot(struct event_args_s *args);
|
|
void EV_G11Shoot (struct event_args_s *args);
|
|
void EV_BoltRifleShoot (struct event_args_s *args);
|
|
void EV_StenShoot (struct event_args_s *args);
|
|
void EV_MolotovCocktail(struct event_args_s *args);
|
|
void EV_FragGrenade (struct event_args_s *args);
|
|
void EV_Pipebomb (struct event_args_s *args);
|
|
void EV_CombatKnife (struct event_args_s *args);
|
|
void EV_BaseballBat (struct event_args_s *args);
|
|
void EV_SledgeHammer (struct event_args_s *args);
|
|
void EV_Katana (struct event_args_s *args);
|
|
void EV_Spear (struct event_args_s *args);
|
|
void EV_CattleProd (struct event_args_s *args);
|
|
void EV_AkimboBerettas (struct event_args_s *args);
|
|
void EV_AkimboColts (struct event_args_s *args);
|
|
void EV_AkimboDeagles (struct event_args_s *args);
|
|
void EV_AkimboSawedOffs(struct event_args_s *args);
|
|
}
|
|
|
|
#define VECTOR_CONE_1DEGREES Vector( 0.00873, 0.00873, 0.00873 )
|
|
#define VECTOR_CONE_2DEGREES Vector( 0.01745, 0.01745, 0.01745 )
|
|
#define VECTOR_CONE_3DEGREES Vector( 0.02618, 0.02618, 0.02618 )
|
|
#define VECTOR_CONE_4DEGREES Vector( 0.03490, 0.03490, 0.03490 )
|
|
#define VECTOR_CONE_5DEGREES Vector( 0.04362, 0.04362, 0.04362 )
|
|
#define VECTOR_CONE_6DEGREES Vector( 0.05234, 0.05234, 0.05234 )
|
|
#define VECTOR_CONE_7DEGREES Vector( 0.06105, 0.06105, 0.06105 )
|
|
#define VECTOR_CONE_8DEGREES Vector( 0.06976, 0.06976, 0.06976 )
|
|
#define VECTOR_CONE_9DEGREES Vector( 0.07846, 0.07846, 0.07846 )
|
|
#define VECTOR_CONE_10DEGREES Vector( 0.08716, 0.08716, 0.08716 )
|
|
#define VECTOR_CONE_15DEGREES Vector( 0.13053, 0.13053, 0.13053 )
|
|
#define VECTOR_CONE_20DEGREES Vector( 0.17365, 0.17365, 0.17365 )
|
|
|
|
// 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 VectorAngles2( const float *forward, float *angles )
|
|
{
|
|
float tmp, yaw, pitch;
|
|
|
|
if (forward[1] == 0 && forward[0] == 0)
|
|
{
|
|
yaw = 0;
|
|
if (forward[2] > 0)
|
|
pitch = 90;
|
|
else
|
|
pitch = 270;
|
|
}
|
|
else
|
|
{
|
|
yaw = (atan2(forward[1], forward[0]) * 180 / M_PI);
|
|
if (yaw < 0)
|
|
yaw += 360;
|
|
|
|
tmp = sqrt (forward[0]*forward[0] + forward[1]*forward[1]);
|
|
pitch = (atan2(forward[2], tmp) * 180 / M_PI);
|
|
if (pitch < 0)
|
|
pitch += 360;
|
|
}
|
|
|
|
angles[0] = pitch;
|
|
angles[1] = yaw;
|
|
angles[2] = 0;
|
|
}
|
|
|
|
int EV_HLDM_SpawnSmoke(int iBulletType)
|
|
{
|
|
// we use cl_efx_frequency to decide
|
|
// if we want to spawn a tent
|
|
switch(iBulletType)
|
|
{
|
|
case BULLET_9MMP:
|
|
case BULLET_10MM:
|
|
case BULLET_50AE:
|
|
case BULLET_454CASULL:
|
|
case BULLET_SLUG:
|
|
case BULLET_556MM:
|
|
if(gEngfuncs.pfnRandomFloat(0,1) > CVAR_GET_FLOAT("cl_efx_frequency")*2)
|
|
return 0;
|
|
case BULLET_9MM:
|
|
case BULLET_45ACP:
|
|
case BULLET_762MM:
|
|
case BULLET_47MM:
|
|
if(gEngfuncs.pfnRandomFloat(0,1) > CVAR_GET_FLOAT("cl_efx_frequency"))
|
|
return 0;
|
|
case BULLET_20GAUGE:
|
|
case BULLET_12GAUGE:
|
|
case BULLET_10GAUGE:
|
|
if(gEngfuncs.pfnRandomFloat(0,1) > CVAR_GET_FLOAT("cl_efx_frequency")/2)
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
TEMPENTITY *EV_HLDM_GunshotSmoke(pmtrace_t *pTrace,float *vecSrc,int iBulletType,color24 Color)
|
|
{
|
|
int iSpriteIdx;
|
|
vec3_t vecDir;
|
|
float scale;
|
|
|
|
// Game told us not to make smoke
|
|
if(!EV_HLDM_SpawnSmoke(iBulletType))
|
|
return NULL;
|
|
|
|
iSpriteIdx = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/smoke1.spr");
|
|
|
|
// TODO: Find a way to prevent bullets from going
|
|
// Into the wall if you hit the wall directly?
|
|
VectorSubtract(pTrace->endpos,vecSrc,vecDir);
|
|
VectorNormalize(vecDir); // Set actual sprite speed below
|
|
|
|
switch(iBulletType)
|
|
{
|
|
// small caliber
|
|
case BULLET_9MMP:
|
|
case BULLET_10MM:
|
|
case BULLET_9MM:
|
|
VectorScale(vecDir,2,vecDir);
|
|
scale = 0.25f;
|
|
break;
|
|
// medium caliber
|
|
case BULLET_50AE:
|
|
case BULLET_454CASULL:
|
|
case BULLET_45ACP:
|
|
VectorScale(vecDir,3,vecDir);
|
|
scale = 0.5f;
|
|
break;
|
|
// large caliber
|
|
case BULLET_SLUG:
|
|
case BULLET_556MM:
|
|
case BULLET_762MM:
|
|
case BULLET_47MM:
|
|
VectorScale(vecDir,4,vecDir);
|
|
scale = 1.0f;
|
|
break;
|
|
// buckshot
|
|
case BULLET_20GAUGE:
|
|
case BULLET_12GAUGE:
|
|
case BULLET_10GAUGE:
|
|
VectorScale(vecDir,1,vecDir);
|
|
scale = 1.25f;
|
|
break;
|
|
// insane values so we know we need
|
|
// to assign a bullet type to the list!
|
|
default:
|
|
VectorScale(vecDir,-5,vecDir);
|
|
scale = 20;
|
|
break;
|
|
}
|
|
|
|
// create the puff
|
|
TEMPENTITY *pTent = gEngfuncs.pEfxAPI->R_TempSprite(pTrace->endpos + pTrace->plane.normal*4,
|
|
vecDir,
|
|
scale,
|
|
iSpriteIdx,
|
|
kRenderTransAlpha,
|
|
0,
|
|
25,
|
|
5,
|
|
FTENT_SPRANIMATE);
|
|
|
|
// state settings
|
|
if(pTent != NULL)
|
|
{
|
|
pTent->entity.curstate.rendercolor = Color;
|
|
pTent->entity.curstate.framerate = 10;
|
|
pTent->entity.curstate.renderamt = 128;
|
|
|
|
return pTent;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
void EV_HLDM_SetColor(color24 &color,byte r,byte g,byte b)
|
|
{
|
|
color.r = r;
|
|
color.g = g;
|
|
color.b = b;
|
|
}
|
|
|
|
void EV_HLDM_GunshotLight( float *origin, float radius, byte r, byte g, byte b, float lifetime )
|
|
{
|
|
// TODO: IMPLEMENT AT LATER STAGE
|
|
/* dlight_t *dl;
|
|
|
|
dl = gEngfuncs.pEfxAPI->CL_AllocDlight( 0 );
|
|
if( dl == NULL )
|
|
return;
|
|
|
|
VectorCopy( origin, dl->origin );
|
|
dl->radius = radius;
|
|
dl->color.r = r;
|
|
dl->color.g = g;
|
|
dl->color.b = b;
|
|
|
|
dl->die = gHUD.m_flTime + lifetime;
|
|
lifetime -= 0.05f;
|
|
dl->decay = 1/(lifetime/dl->radius);*/
|
|
}
|
|
|
|
void EV_HLDM_GunshotEfx( pmtrace_t *pTrace, int iBulletType, float *vecSrc, float *vecEnd)
|
|
{
|
|
int iRand = gEngfuncs.pfnRandomLong(0,0x7FFF);
|
|
int bRicochet = (iRand < (0x7fff/2));
|
|
int bGenericDecal = 0;
|
|
physent_t *pe;
|
|
static char decalname[32];
|
|
|
|
// we create texture based smoke instead of just cute little sparks
|
|
color24 SmokeColor;
|
|
const char *szTextureName = gEngfuncs.pEventAPI->EV_TraceTexture(pTrace->ent,vecSrc,vecEnd); // get texture info
|
|
char cTextureType = 0;
|
|
int iRenderSmoke = 1; // Do we want to show a smokepuff ?
|
|
int bShowLight = 1;
|
|
static unsigned int lightcount;
|
|
|
|
EV_HLDM_SetColor(SmokeColor,255,255,255); // default color
|
|
|
|
if( szTextureName != NULL )
|
|
cTextureType = PM_FindTextureType((char*)szTextureName);
|
|
|
|
switch(cTextureType)
|
|
{
|
|
case CHAR_TEX_COMPUTER:
|
|
case CHAR_TEX_GLASS:
|
|
if(bRicochet)
|
|
{
|
|
switch(iRand % 3)
|
|
{
|
|
case 0: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_glass1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
case 1: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_glass2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
case 2: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_glass3.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
}
|
|
}
|
|
iRenderSmoke = 0; // No smoke puff
|
|
bShowLight = 0;
|
|
bGenericDecal = 1;
|
|
break;
|
|
case CHAR_TEX_WOOD:
|
|
if(bRicochet)
|
|
{
|
|
switch(iRand % 5)
|
|
{
|
|
case 0: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_wood1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
case 1: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_wood2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
case 2: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_wood3.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
case 3: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_wood4.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
case 4: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_wood5.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
}
|
|
}
|
|
strcpy(decalname, "{holewood");
|
|
EV_HLDM_SetColor(SmokeColor,187,141,43);
|
|
break;
|
|
case CHAR_TEX_CONCRETE:
|
|
if(bRicochet)
|
|
{
|
|
switch(iRand % 3)
|
|
{
|
|
case 0: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_con1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
case 1: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_con2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
case 2: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_con3.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
}
|
|
}
|
|
strcpy(decalname, "{holeconcrete");
|
|
break;
|
|
case CHAR_TEX_RUST:
|
|
if(bRicochet)
|
|
{
|
|
switch(iRand % 2)
|
|
{
|
|
case 0: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_metalwall1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
case 1: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_metalwall2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
}
|
|
}
|
|
strcpy(decalname, "{holerust");
|
|
break;
|
|
case CHAR_TEX_VENT:
|
|
case CHAR_TEX_METAL:
|
|
if(bRicochet)
|
|
{
|
|
switch(iRand % 2)
|
|
{
|
|
case 0: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_metalwall1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
case 1: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_metalwall2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
}
|
|
}
|
|
strcpy(decalname, "{holemetal");
|
|
break;
|
|
case CHAR_TEX_GRATE:
|
|
case CHAR_TEX_BARREL:
|
|
if(bRicochet)
|
|
{
|
|
switch(iRand % 4)
|
|
{
|
|
case 0: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_barrel1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
case 1: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_barrel2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
case 2: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_barrel3.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
case 3: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_barrel4.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
}
|
|
}
|
|
sprintf(decalname, "{dent%i", gEngfuncs.pfnRandomLong( 0, 5 ) + 1 );
|
|
break;
|
|
case CHAR_TEX_TIN:
|
|
if(bRicochet)
|
|
{
|
|
switch(iRand % 3)
|
|
{
|
|
case 0: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_tinroof1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
case 1: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_tinroof2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
case 2: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_tinroof3.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
}
|
|
}
|
|
sprintf(decalname, "{dent%i", gEngfuncs.pfnRandomLong( 0, 5 ) + 1 );
|
|
break;
|
|
case CHAR_TEX_TILE:
|
|
if(bRicochet)
|
|
{
|
|
switch(iRand % 2)
|
|
{
|
|
case 0: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_drywall1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
case 1: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_drywall2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
}
|
|
}
|
|
strcpy(decalname, "{holetile");
|
|
break;
|
|
case CHAR_TEX_DRYWALL:
|
|
if(bRicochet)
|
|
{
|
|
switch(iRand % 2)
|
|
{
|
|
case 0: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_drywall1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
case 1: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric_drywall2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
}
|
|
}
|
|
strcpy(decalname, "{holedry");
|
|
EV_HLDM_SetColor(SmokeColor,255,255,200);
|
|
break;
|
|
case CHAR_TEX_SAND:
|
|
strcpy(decalname, "{holesand");
|
|
EV_HLDM_SetColor(SmokeColor,255,255,192);
|
|
break;
|
|
case CHAR_TEX_FLESH:
|
|
EV_HLDM_SetColor(SmokeColor,200,25,25);
|
|
bGenericDecal = 1;
|
|
break;
|
|
case CHAR_TEX_DIRT:
|
|
EV_HLDM_SetColor(SmokeColor,115,53,25);
|
|
bGenericDecal = 1;
|
|
break;
|
|
case CHAR_TEX_SNOW:
|
|
EV_HLDM_SetColor(SmokeColor,255,255,255);
|
|
bGenericDecal = 1;
|
|
break;
|
|
case CHAR_TEX_SLOSH:
|
|
iRenderSmoke = 0;
|
|
default:
|
|
if(bRicochet)
|
|
{
|
|
switch( iRand % 5)
|
|
{
|
|
case 0: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric1.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
case 1: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric2.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
case 2: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric3.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
case 3: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric4.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
case 4: gEngfuncs.pEventAPI->EV_PlaySound( -1, pTrace->endpos, 0, "debris/ric5.wav", 1.0, ATTN_NORM, 0, PITCH_NORM ); break;
|
|
}
|
|
}
|
|
bGenericDecal = 1;
|
|
break;
|
|
}
|
|
|
|
pe = gEngfuncs.pEventAPI->EV_GetPhysent( pTrace->ent );
|
|
|
|
// Override some object decals
|
|
if ( pe->classnumber == 1 )
|
|
sprintf( decalname, "{break%i", gEngfuncs.pfnRandomLong( 0, 2 ) + 1 );
|
|
else if ( pe->rendermode != kRenderNormal )
|
|
{
|
|
sprintf( decalname, "{bproof1" );
|
|
}
|
|
else if(iBulletType >= BULLET_20GAUGE && iBulletType <= BULLET_12GAUGE)
|
|
{
|
|
// Buckshot
|
|
sprintf(decalname,"{bigshot%i",gEngfuncs.pfnRandomLong( 0, 4 )+ 1 );
|
|
bShowLight = 0;
|
|
}
|
|
else if(bGenericDecal)
|
|
sprintf( decalname, "{shot%i", gEngfuncs.pfnRandomLong( 0, 7 ) + 1 );
|
|
|
|
if( bShowLight && CVAR_GET_FLOAT( "cl_efx_frequency" ) > 0 )
|
|
{
|
|
// Only do every 3 bullets
|
|
if( lightcount++ % 3 == 1 )
|
|
EV_HLDM_GunshotLight( pTrace->endpos, gEngfuncs.pfnRandomFloat( 30.0f, 40.0f ), 255, 255, 255, 0.75f );
|
|
}
|
|
|
|
if(iRenderSmoke)
|
|
EV_HLDM_GunshotSmoke(pTrace,vecSrc,iBulletType,SmokeColor);
|
|
|
|
// 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 );
|
|
}
|
|
}
|
|
}
|
|
|
|
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 )
|
|
// {
|
|
// default:
|
|
EV_CreateTracer( vecTracerSrc, end );
|
|
// break;
|
|
// }
|
|
}
|
|
|
|
return tracer;
|
|
}
|
|
|
|
void EV_HLDM_BulletDecal(int iBulletType,pmtrace_t *pTr,float *vecSrc,float *vecEnd)
|
|
{
|
|
// do damage, paint decals
|
|
physent_t *pe;
|
|
|
|
pe = gEngfuncs.pEventAPI->EV_GetPhysent( pTr->ent );
|
|
|
|
if ( pe && pe->solid == SOLID_BSP )
|
|
{
|
|
// smoke and decal
|
|
EV_HLDM_GunshotEfx( pTr, iBulletType, vecSrc, vecEnd );
|
|
}
|
|
}
|
|
|
|
/*
|
|
================
|
|
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 penetration_type )
|
|
{
|
|
int i;
|
|
pmtrace_t tr;
|
|
int tracer;
|
|
int iShot;
|
|
|
|
#if !(DISABLE_PENETRATION)
|
|
// penetration values
|
|
int wall_thickness = 0;
|
|
float falloff_rate = 0;
|
|
int wall_limit = MAX_WALLCOUNT;
|
|
|
|
switch(penetration_type)
|
|
{
|
|
case P_BERETTA:
|
|
wall_thickness = MAX_THICKNESS_BERETTA;
|
|
falloff_rate = FALLOFF_BERETTA;
|
|
break;
|
|
case P_COLT:
|
|
wall_thickness = MAX_THICKNESS_COLT;
|
|
falloff_rate = FALLOFF_COLT;
|
|
break;
|
|
case P_RUGER:
|
|
wall_thickness = MAX_THICKNESS_RUGER;
|
|
falloff_rate = FALLOFF_RUGER;
|
|
break;
|
|
case P_DEAGLE:
|
|
wall_thickness = MAX_THICKNESS_DEAGLE;
|
|
falloff_rate = FALLOFF_DEAGLE;
|
|
break;
|
|
case P_HANDCANNON:
|
|
wall_thickness = MAX_THICKNESS_HANDCANNON;
|
|
falloff_rate = FALLOFF_HANDCANNON;
|
|
break;
|
|
case P_WINCHESTER:
|
|
wall_thickness = MAX_THICKNESS_WINCHESTER;
|
|
falloff_rate = FALLOFF_WINCHESTER;
|
|
break;
|
|
case P_SMG9:
|
|
wall_thickness = MAX_THICKNESS_SMG9;
|
|
falloff_rate = FALLOFF_SMG9;
|
|
break;
|
|
case P_FNFAL:
|
|
wall_thickness = MAX_THICKNESS_FNFAL;
|
|
falloff_rate = FALLOFF_FNFAL;
|
|
break;
|
|
case P_TOMMYGUN:
|
|
wall_thickness = MAX_THICKNESS_TOMMYGUN;
|
|
falloff_rate = FALLOFF_TOMMYGUN;
|
|
break;
|
|
case P_G11:
|
|
wall_thickness = MAX_THICKNESS_G11;
|
|
falloff_rate = FALLOFF_G11;
|
|
break;
|
|
case P_BOLTRIFLE:
|
|
wall_thickness = MAX_THICKNESS_BOLTRIFLE;
|
|
falloff_rate = FALLOFF_BOLTRIFLE;
|
|
break;
|
|
case P_STEN:
|
|
wall_thickness = MAX_THICKNESS_STEN;
|
|
falloff_rate = FALLOFF_STEN;
|
|
break;
|
|
}
|
|
#endif
|
|
|
|
|
|
#if !(DISABLE_PENETRATION)
|
|
do
|
|
{
|
|
#endif
|
|
for ( iShot = 1; iShot <= cShots; iShot++ )
|
|
{
|
|
vec3_t vecDir, vecEnd;
|
|
|
|
float x, y, z;
|
|
//We randomize for the Shotguns
|
|
if(iBulletType >= BULLET_20GAUGE && iBulletType <= BULLET_12GAUGE)
|
|
{
|
|
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 );
|
|
|
|
if( tr.fraction != 1.0 )
|
|
{
|
|
EV_HLDM_BulletDecal(iBulletType,&tr,vecSrc,(float*)&vecEnd);
|
|
|
|
#if !(DISABLE_PENETRATION)
|
|
// If we want an exit hole, show it.
|
|
if(wall_thickness)
|
|
{
|
|
// wall thickness
|
|
vec3_t wall_begin = tr.endpos;
|
|
vec3_t wall_end;
|
|
pmtrace_t new_tr;
|
|
|
|
gEngfuncs.pEventAPI->EV_PlayerTrace(tr.endpos+vecDir*wall_thickness,vecEnd,PM_STUDIO_BOX,-1,&new_tr);
|
|
|
|
// We cannot continue
|
|
if(new_tr.allsolid)
|
|
wall_thickness = 0;
|
|
else
|
|
{
|
|
// Get exit hole
|
|
gEngfuncs.pEventAPI->EV_PlayerTrace(new_tr.endpos,tr.endpos,PM_STUDIO_BOX,-1,&tr);
|
|
|
|
if(!tr.allsolid)
|
|
{
|
|
// get length of wall, and detract from overall bullet effectiveness
|
|
// only subtract for hard targets, not players.
|
|
if(tr.ent != NULL && !EV_IsPlayer(tr.ent))
|
|
{
|
|
VectorSubtract(tr.endpos,wall_begin,wall_end);
|
|
wall_thickness -= (int)(Length(wall_end) * falloff_rate);
|
|
}
|
|
|
|
if(wall_thickness <= 0)
|
|
wall_thickness = 0;
|
|
else
|
|
EV_HLDM_BulletDecal(iBulletType,&tr,vecSrc,(float*)&vecEnd);
|
|
|
|
// Trace ahead to get next wall.
|
|
vecSrc = tr.endpos;
|
|
}
|
|
else
|
|
wall_thickness = 0; // cant go any further.
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_PopPMStates();
|
|
}
|
|
#if !(DISABLE_PENETRATION)
|
|
}while(wall_thickness && wall_limit--);
|
|
#endif
|
|
}
|
|
|
|
// globals used by most Pistol events
|
|
// Some Ruger specific code is here too.
|
|
int EV_PistolShoot( event_args_t *args , const char *fire_sound,int iBulletType, const char *loshell, const char *hishell)
|
|
{
|
|
int idx = args->entindex;
|
|
int empty = args->bparam1;
|
|
int aimmode = args->bparam2;
|
|
|
|
vec3_t up, right, forward;
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
VectorCopy( args->origin, origin );
|
|
VectorCopy( args->angles, angles );
|
|
VectorCopy( args->velocity, velocity );
|
|
AngleVectors( angles, forward, right, up );
|
|
vec3_t vecSrc, vecAiming;
|
|
|
|
if ( EV_IsLocal( idx ) )
|
|
{
|
|
EV_MuzzleFlash();
|
|
|
|
if(iBulletType == BULLET_454CASULL)
|
|
{
|
|
if(!aimmode)
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation( RUGER_SHOOT, 2 );
|
|
else
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation( RUGER_AIM_SHOOT, 2 );
|
|
}
|
|
else
|
|
{
|
|
if(!aimmode)
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation( empty ? SPISTOL_SHOOT_LAST : SPISTOL_SHOOT, 2 );
|
|
else
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation( empty ? SPISTOL_AIM_SHOOT_LAST : SPISTOL_AIM_SHOOT , 2 );
|
|
}
|
|
|
|
V_PunchAxis( 0, -2.0 );
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON,fire_sound, gEngfuncs.pfnRandomFloat(0.92, 1.0), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) );
|
|
|
|
EV_GetGunPosition( args, vecSrc, origin );
|
|
VectorCopy( forward, vecAiming );
|
|
|
|
int penetration_type;
|
|
|
|
switch(iBulletType)
|
|
{
|
|
case BULLET_9MMP:
|
|
penetration_type = P_BERETTA;
|
|
break;
|
|
case BULLET_10MM:
|
|
penetration_type = P_COLT;
|
|
break;
|
|
case BULLET_454CASULL:
|
|
penetration_type = P_RUGER;
|
|
break;
|
|
case BULLET_50AE:
|
|
penetration_type = P_DEAGLE;
|
|
break;
|
|
default:
|
|
penetration_type = 0;
|
|
break;
|
|
}
|
|
|
|
vec3_t ShellVelocity;
|
|
vec3_t ShellOrigin;
|
|
int shell;
|
|
|
|
if( iBulletType != BULLET_454CASULL )
|
|
{
|
|
if(!CVAR_GET_FLOAT("cl_shellcase_quality"))
|
|
shell = gEngfuncs.pEventAPI->EV_FindModelIndex( loshell );
|
|
else
|
|
shell = gEngfuncs.pEventAPI->EV_FindModelIndex( hishell );
|
|
|
|
EV_GetDefaultShellInfo( 0, args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 10, -4, 5 );
|
|
|
|
EV_EjectBrass( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL );
|
|
}
|
|
|
|
EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, iBulletType, (ev_thermal) ? 1 : 0, (ev_thermal) ? &tracerCount[idx-1] : 0, args->fparam1, args->fparam2, penetration_type );
|
|
|
|
return 1;
|
|
}
|
|
|
|
void EV_PistolWhip(event_args_t *args)
|
|
{
|
|
int idx = args->entindex;
|
|
int clip_empty = args->iparam1;
|
|
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
|
|
VectorCopy( args->origin, origin );
|
|
|
|
//Play Swing sound
|
|
switch(gEngfuncs.pfnRandomLong(0,2))
|
|
{
|
|
case 0:
|
|
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_AUTO, "weapons/whip.wav", 1, ATTN_NORM, 0, PITCH_NORM); break;
|
|
case 1:
|
|
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_AUTO, "weapons/whip3.wav", 1, ATTN_NORM, 0, PITCH_NORM); break;
|
|
case 2:
|
|
default:
|
|
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_AUTO, "weapons/whip2.wav", 1, ATTN_NORM, 0, PITCH_NORM); break;
|
|
}
|
|
|
|
if ( EV_IsLocal( idx ) )
|
|
{
|
|
switch( gEngfuncs.pfnRandomLong(0,1) )
|
|
{
|
|
case 0:
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation ( clip_empty ? SPISTOL_WHIP1_EMPTY : SPISTOL_WHIP1, 1 ); break;
|
|
case 1:
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation ( clip_empty ? SPISTOL_WHIP2_EMPTY : SPISTOL_WHIP2, 1 ); break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*************
|
|
Beretta
|
|
*************/
|
|
void EV_BerettaShoot(event_args_t *args)
|
|
{
|
|
if(args->iparam2)
|
|
EV_PistolShoot(args,"weapons/beretta_fire.wav",BULLET_9MMP,"models/shells/shell_9x18mm_lo.mdl","models/shells/shell_9x18mm_hi.mdl");
|
|
else
|
|
EV_PistolWhip(args);
|
|
}
|
|
|
|
/*************
|
|
Enforcer
|
|
*************/
|
|
void EV_ColtShoot(event_args_t *args)
|
|
{
|
|
if(args->iparam2)
|
|
EV_PistolShoot(args,"weapons/colt_fire.wav",BULLET_10MM,"models/shells/shell_10mm_lo.mdl","models/shells/shell_10mm_hi.mdl");
|
|
else
|
|
EV_PistolWhip(args);
|
|
}
|
|
|
|
/*************
|
|
Desert Eagle
|
|
*************/
|
|
void EV_DeagleShoot(event_args_t *args)
|
|
{
|
|
if(args->iparam2)
|
|
{
|
|
EV_PistolShoot(args,"weapons/deagle_fire.wav",BULLET_50AE,"models/shells/shell_50AE_lo.mdl","models/shells/shell_50AE_hi.mdl");
|
|
|
|
// Pop up the view angle - (dont pop up if aiming)
|
|
if(EV_IsPlayer(args->entindex) && EV_IsLocal(args->entindex) && !args->bparam2)
|
|
RECOIL_VIEW(5.5,0);
|
|
}
|
|
else
|
|
EV_PistolWhip(args);
|
|
}
|
|
|
|
/*************
|
|
Ruger
|
|
*************/
|
|
void EV_RugerShoot(event_args_t *args)
|
|
{
|
|
if(EV_PistolShoot(args,"weapons/ruger_fire.wav",BULLET_454CASULL,"models/shells/shell_454_lo.mdl","models/shells/shell_454_hi.mdl"))
|
|
{
|
|
// Not as extreme as Desert Eagle, but still there :D
|
|
if(EV_IsPlayer(args->entindex) && EV_IsLocal(args->entindex) && !args->bparam2 && !args->iparam2)
|
|
RECOIL_VIEW(5,0);
|
|
}
|
|
}
|
|
|
|
/*************
|
|
5.56mm Handcannon
|
|
*************/
|
|
void EV_HandcannonShoot(event_args_t *args)
|
|
{
|
|
int idx;
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
int empty;
|
|
|
|
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 );
|
|
|
|
// Play sound only
|
|
if(args->iparam1)
|
|
{
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx,origin,CHAN_AUTO,args->bparam2 ? "weapons/handcannon_laser_on.wav" : "weapons/handcannon_laser_off.wav", gEngfuncs.pfnRandomFloat(0.92, 1.0), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) );
|
|
return;
|
|
}
|
|
|
|
if ( EV_IsLocal( idx ) )
|
|
{
|
|
EV_MuzzleFlash();
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation( empty ? HC_SHOOT_LAST : HC_SHOOT, 2 );
|
|
|
|
if(!args->bparam2)
|
|
{
|
|
RECOIL_VIEW(13.5,0);
|
|
}
|
|
else
|
|
// Huge kickback noticed if your using a laser
|
|
V_PunchAxis( 0, -10.0 );
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON,"weapons/handcannon_fire.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_556MM, (ev_thermal) ? 1 : 0, (ev_thermal) ? &tracerCount[idx-1] : 0, args->fparam1, args->fparam2,P_HANDCANNON );
|
|
}
|
|
|
|
/*************
|
|
Sawed Off
|
|
*************/
|
|
void EV_SawedOffShoot(event_args_t *args)
|
|
{
|
|
int idx = args->entindex;
|
|
int barrels = args->iparam1;
|
|
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
vec3_t up, right, forward;
|
|
VectorCopy( args->origin, origin );
|
|
VectorCopy( args->angles, angles );
|
|
VectorCopy( args->velocity, velocity );
|
|
AngleVectors( angles, forward, right, up );
|
|
|
|
vec3_t vecSrc, vecAiming;
|
|
vec3_t vecSpread;
|
|
|
|
if( EV_IsLocal( idx ) )
|
|
{
|
|
// Add muzzle flash to current weapon model
|
|
EV_MuzzleFlash();
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation( (barrels == 2) ? SAWED_SHOOT_L : SAWED_SHOOT_R, 2 );
|
|
|
|
if(barrels == 1)
|
|
V_PunchAxis( 0, -5.0 );
|
|
else
|
|
V_PunchAxis( 0, -11.5 );
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, (barrels == 1) ? "weapons/sawedoff_fire1.wav" : "weapons/sawedoff_fire2.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0x1f ) );
|
|
|
|
EV_GetGunPosition( args, vecSrc, origin );
|
|
VectorCopy( forward, vecAiming );
|
|
|
|
int shotCount = (barrels == 1) ? 14 : 26;
|
|
|
|
// Remember to change the randomization code at the bottom :)
|
|
EV_HLDM_FireBullets( idx, forward, right, up, shotCount, vecSrc, vecAiming, 2048, BULLET_20GAUGE, (ev_thermal) ? 1 : 0, (ev_thermal) ? &tracerCount[idx-1] : 0, args->fparam1, args->fparam2,0 );
|
|
}
|
|
|
|
/*************
|
|
Mossberg
|
|
*************/
|
|
void EV_MossbergBlast(event_args_t *args)
|
|
{
|
|
int idx = args->entindex;
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
vec3_t up, right, forward;
|
|
|
|
VectorCopy ( args->origin, origin );
|
|
VectorCopy ( args->angles, angles );
|
|
VectorCopy ( args->velocity, velocity );
|
|
AngleVectors( angles, forward, right, up );
|
|
|
|
// Shoot gun as normal
|
|
vec3_t vecSrc, vecAiming;
|
|
vec3_t vecSpread;
|
|
|
|
if(EV_IsLocal(idx))
|
|
{
|
|
// Add muzzle flash to current weapon model
|
|
EV_MuzzleFlash();
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation( args->bparam2 ? MOSSBERG_SHOOT : MOSSBERG_SHOOT2, 2 );
|
|
V_PunchAxis( 0, -4.5 );
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, args->bparam2 ? "weapons/mossberg_fire1.wav" : "weapons/mossberg_fire2.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0x1f ) );
|
|
|
|
EV_GetGunPosition( args, vecSrc, origin );
|
|
VectorCopy( forward, vecAiming );
|
|
|
|
int shotCount = args->iparam1;
|
|
|
|
// Remember to change the randomization code at the bottom :)
|
|
EV_HLDM_FireBullets( idx, forward, right, up, shotCount, vecSrc, vecAiming, 2048, BULLET_12GAUGE, (ev_thermal) ? 1 : 0, (ev_thermal) ? &tracerCount[idx-1] : 0, args->fparam1, args->fparam2,0 );
|
|
}
|
|
|
|
void EV_MossbergWhip(event_args_t *args)
|
|
{
|
|
int idx = args->entindex;
|
|
int clip_empty = args->iparam1;
|
|
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
|
|
VectorCopy( args->origin, origin );
|
|
|
|
//Play Swing sound
|
|
switch(gEngfuncs.pfnRandomLong(0,2))
|
|
{
|
|
case 0:
|
|
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_AUTO, "weapons/whip.wav", 1, ATTN_NORM, 0, PITCH_NORM); break;
|
|
case 1:
|
|
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_AUTO, "weapons/whip3.wav", 1, ATTN_NORM, 0, PITCH_NORM); break;
|
|
case 2:
|
|
default:
|
|
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_AUTO, "weapons/whip2.wav", 1, ATTN_NORM, 0, PITCH_NORM); break;
|
|
}
|
|
|
|
if ( EV_IsLocal( idx ) )
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation ( MOSSBERG_WHIP, 1 );
|
|
}
|
|
|
|
void EV_MossbergShoot(event_args_t *args)
|
|
{
|
|
if(args->iparam2)
|
|
EV_MossbergBlast(args);
|
|
else
|
|
EV_MossbergWhip(args);
|
|
}
|
|
|
|
/*************
|
|
Winchester
|
|
*************/
|
|
void EV_WinchesterShoot(event_args_t *args)
|
|
{
|
|
int idx = args->entindex;
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
vec3_t up, right, forward;
|
|
VectorCopy( args->origin, origin );
|
|
VectorCopy( args->angles, angles );
|
|
VectorCopy( args->velocity, velocity );
|
|
AngleVectors( angles, forward, right, up );
|
|
|
|
int animation = args->iparam1;
|
|
|
|
vec3_t vecSrc, vecAiming;
|
|
|
|
if(EV_IsLocal(idx))
|
|
{
|
|
EV_MuzzleFlash();
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation( animation ? WINNY_SHOOT : WINNY_SHOOT2, 2 );
|
|
V_PunchAxis( 0, -2.0 );
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON,animation ? "weapons/winchester_fire1.wav" : "weapons/winchester_fire2.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_SLUG, ev_thermal ? 1 : 0, ev_thermal ? &tracerCount[idx-1] : 0, args->fparam1, args->fparam2, P_WINCHESTER);
|
|
}
|
|
|
|
/*************
|
|
Smg9
|
|
*************/
|
|
void EV_Smg9Shoot(struct event_args_s *args)
|
|
{
|
|
float dirx = args->fparam1;
|
|
float diry = args->fparam2;
|
|
float accuracy = args->angles[0];
|
|
float recoil;
|
|
int idx = args->entindex;
|
|
int empty = args->iparam2;
|
|
int secondary = args->iparam1;
|
|
int lowrecoil = args->bparam1;
|
|
int burstpredict = args->bparam2;
|
|
|
|
if(secondary)
|
|
{
|
|
if(lowrecoil)
|
|
recoil = gEngfuncs.pfnRandomFloat(1.4,2.4);
|
|
else
|
|
recoil = gEngfuncs.pfnRandomFloat(3.4,4.4);
|
|
}
|
|
else
|
|
{
|
|
if(lowrecoil)
|
|
recoil = gEngfuncs.pfnRandomFloat(0.4,1.4);
|
|
else
|
|
recoil = gEngfuncs.pfnRandomFloat(1.4,2.0);
|
|
}
|
|
|
|
// muck up bullet locations a bit in burst fire
|
|
if(burstpredict)
|
|
{
|
|
dirx *= gEngfuncs.pfnRandomFloat(-accuracy,accuracy);
|
|
diry *= gEngfuncs.pfnRandomFloat(accuracy/4,accuracy);
|
|
}
|
|
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
vec3_t vecSrc;
|
|
vec3_t up, right, forward;
|
|
|
|
VectorCopy(args->origin,origin);
|
|
VectorCopy(args->angles,angles);
|
|
VectorCopy(args->velocity,velocity);
|
|
AngleVectors(angles,forward,right,up);
|
|
|
|
// Shell ejection
|
|
vec3_t ShellVelocity;
|
|
vec3_t ShellOrigin;
|
|
int shell;
|
|
|
|
if(!CVAR_GET_FLOAT("cl_shellcase_quality"))
|
|
shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shells/shell_9x22mm_lo.mdl");
|
|
else
|
|
shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shells/shell_9x22mm_hi.mdl");
|
|
|
|
if(!secondary)
|
|
EV_GetDefaultShellInfo( 2, args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 10, -4, 5 );
|
|
else
|
|
// Eject upwards as normal
|
|
EV_GetDefaultShellInfo( 0, args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 10, -4, 0 );
|
|
|
|
EV_EjectBrass(ShellOrigin,ShellVelocity,angles[ YAW ],shell,TE_BOUNCE_SHELL);
|
|
|
|
if(EV_IsLocal(idx))
|
|
{
|
|
EV_MuzzleFlash();
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(secondary ? SMG9_SECONDARY_SHOOT : SMG9_SHOOT,2);
|
|
|
|
RECOIL_VIEW(recoil,0);
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx,origin,CHAN_WEAPON,(gEngfuncs.pfnRandomFloat(0,1) == 0) ? "weapons/smg9_fire1.wav" : "weapons/smg9_fire2.wav", gEngfuncs.pfnRandomFloat(0.92, 1.0), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) );
|
|
|
|
EV_GetGunPosition( args, vecSrc, origin );
|
|
EV_HLDM_FireBullets(idx,forward,right,up,1,vecSrc,forward,8192,BULLET_9MM,ev_thermal ? 1 : 0,ev_thermal ? &tracerCount[idx-1] : 0,dirx,diry,P_SMG9);
|
|
}
|
|
|
|
/*************
|
|
FN FAL
|
|
*************/
|
|
void EV_FnFalShoot(event_args_t *args)
|
|
{
|
|
int idx = args->entindex;
|
|
int aimfire = args->bparam2;
|
|
int lowrecoil = args->bparam1;
|
|
int semiauto = args->iparam2;
|
|
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
vec3_t vecSrc;
|
|
vec3_t up, right, forward;
|
|
|
|
VectorCopy(args->origin,origin);
|
|
VectorCopy(args->angles,angles);
|
|
VectorCopy(args->velocity,velocity);
|
|
AngleVectors(angles,forward,right,up);
|
|
|
|
// Shell ejection
|
|
vec3_t ShellVelocity;
|
|
vec3_t ShellOrigin;
|
|
int shell;
|
|
|
|
if(!CVAR_GET_FLOAT("cl_shellcase_quality"))
|
|
shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shells/shell_762mm_lo.mdl");
|
|
else
|
|
shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shells/shell_762mm_hi.mdl");
|
|
|
|
if(!aimfire)
|
|
EV_GetDefaultShellInfo( 2, args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 10, -4, 5 );
|
|
else
|
|
EV_GetDefaultShellInfo( 2, args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 10, -4, 0 );
|
|
|
|
EV_EjectBrass(ShellOrigin,ShellVelocity,angles[ YAW ],shell,TE_BOUNCE_SHELL);
|
|
|
|
if(EV_IsLocal(idx))
|
|
{
|
|
EV_MuzzleFlash();
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(aimfire ? FNFAL_AIM_SHOOT : FNFAL_SHOOT,2);
|
|
|
|
if(aimfire)
|
|
{
|
|
if( semiauto )
|
|
V_PunchAxis(0,-3.4);
|
|
else
|
|
{
|
|
if( lowrecoil )
|
|
{
|
|
RECOIL_VIEW( gEngfuncs.pfnRandomFloat( 0.50, 1.50 ), 0 );
|
|
}
|
|
else
|
|
{
|
|
RECOIL_VIEW( gEngfuncs.pfnRandomFloat( 1.25, 2.25 ), 0 );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(lowrecoil)
|
|
{
|
|
RECOIL_VIEW(gEngfuncs.pfnRandomFloat(1.25,2.25),0);
|
|
}
|
|
else
|
|
{
|
|
RECOIL_VIEW(gEngfuncs.pfnRandomFloat(2.75,4.5),0);
|
|
}
|
|
}
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx,origin,CHAN_WEAPON,(gEngfuncs.pfnRandomLong(0,1) == 0) ? "weapons/fnfal_fire1.wav" : "weapons/fnfal_fire2.wav", gEngfuncs.pfnRandomFloat(0.92, 1.0), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) );
|
|
|
|
EV_GetGunPosition( args, vecSrc, origin );
|
|
EV_HLDM_FireBullets(idx,forward,right,up,1,vecSrc,forward,8192,BULLET_762MM,ev_thermal ? 1 : 2,&tracerCount[idx-1],args->fparam1,args->fparam2,P_FNFAL);
|
|
}
|
|
|
|
/*************
|
|
Tommy Gun
|
|
*************/
|
|
void EV_TommyGunShoot(event_args_t *args)
|
|
{
|
|
int idx = args->entindex;
|
|
int lessrecoil = args->bparam1;
|
|
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
vec3_t vecSrc;
|
|
vec3_t up, right, forward;
|
|
|
|
VectorCopy(args->origin,origin);
|
|
VectorCopy(args->angles,angles);
|
|
VectorCopy(args->velocity,velocity);
|
|
AngleVectors(angles,forward,right,up);
|
|
|
|
// Shell ejection
|
|
vec3_t ShellVelocity;
|
|
vec3_t ShellOrigin;
|
|
int shell;
|
|
|
|
if(!CVAR_GET_FLOAT("cl_shellcase_quality"))
|
|
shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shells/shell_45cal_lo.mdl");
|
|
else
|
|
shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shells/shell_45cal_hi.mdl");
|
|
|
|
EV_GetDefaultShellInfo( 2, args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 10, -4, 5 );
|
|
EV_EjectBrass(ShellOrigin,ShellVelocity,angles[ YAW ],shell,TE_BOUNCE_SHELL);
|
|
|
|
if(EV_IsLocal(idx))
|
|
{
|
|
EV_MuzzleFlash();
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(TOMMYGUN_SHOOT,2);
|
|
|
|
if(lessrecoil)
|
|
{
|
|
RECOIL_VIEW(gEngfuncs.pfnRandomFloat(1.25,2.0),0);
|
|
}
|
|
else
|
|
{
|
|
RECOIL_VIEW(gEngfuncs.pfnRandomFloat(2.0,3.5),0);
|
|
}
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx,origin,CHAN_WEAPON,(gEngfuncs.pfnRandomLong(0,1) == 0) ? "weapons/tommygun_fire1.wav" : "weapons/tommygun_fire2.wav", gEngfuncs.pfnRandomFloat(0.92, 1.0), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) );
|
|
|
|
EV_GetGunPosition( args, vecSrc, origin );
|
|
EV_HLDM_FireBullets(idx,forward,right,up,1,vecSrc,forward,8192,BULLET_45ACP,ev_thermal ? 1 : 3,&tracerCount[idx-1],args->fparam1,args->fparam2,P_TOMMYGUN);
|
|
}
|
|
|
|
/*************
|
|
Jackhammer
|
|
*************/
|
|
void EV_JackHammerShoot(event_args_t *args)
|
|
{
|
|
int idx = args->entindex;
|
|
int ducking = args->iparam2;
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
vec3_t up, right, forward;
|
|
|
|
VectorCopy ( args->origin, origin );
|
|
VectorCopy ( args->angles, angles );
|
|
VectorCopy ( args->velocity, velocity );
|
|
AngleVectors( angles, forward, right, up );
|
|
|
|
vec3_t vecSrc, vecAiming;
|
|
vec3_t vecSpread;
|
|
|
|
if(EV_IsLocal(idx))
|
|
{
|
|
// Add muzzle flash to current weapon model
|
|
EV_MuzzleFlash();
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation( JACKHAMMER_SHOOT, 2 );
|
|
|
|
if(ducking)
|
|
{
|
|
RECOIL_VIEW(gEngfuncs.pfnRandomFloat(3.0,4.0),0);
|
|
}
|
|
else
|
|
{
|
|
RECOIL_VIEW(gEngfuncs.pfnRandomFloat(5.0,6.5),0);
|
|
}
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, gEngfuncs.pfnRandomLong(0,1) ? "weapons/jackhammer_fire1.wav" : "weapons/jackhammer_fire2.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0x1f ) );
|
|
|
|
EV_GetGunPosition( args, vecSrc, origin );
|
|
VectorCopy( forward, vecAiming );
|
|
|
|
int shotCount = args->iparam1;
|
|
|
|
// Remember to change the randomization code at the bottom :)
|
|
EV_HLDM_FireBullets( idx, forward, right, up, shotCount, vecSrc, vecAiming, 2048, BULLET_10GAUGE, ev_thermal ? 1 : 0, ev_thermal ? &tracerCount[idx-1] : 0, args->fparam1, args->fparam2,0 );
|
|
}
|
|
|
|
/*************
|
|
H&K G11
|
|
*************/
|
|
void EV_G11Shoot(event_args_t *args)
|
|
{
|
|
int idx = args->entindex;
|
|
int burstfire = args->iparam1;
|
|
float bursthop = args->fparam2;
|
|
int burstcount = args->iparam2; // How many bullets to fire
|
|
int zoom_sound = args->bparam1; // just do a cute zoom sound ?
|
|
int lessrecoil = args->bparam2;
|
|
|
|
// We do this as an event so other people can hear it
|
|
if(zoom_sound)
|
|
{
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx,args->origin,CHAN_AUTO,args->bparam2 ? "weapons/g11_zoom2.wav" : "weapons/g11_zoom1.wav", gEngfuncs.pfnRandomFloat(0.7,0.8), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) );
|
|
return;
|
|
}
|
|
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
vec3_t vecSrc;
|
|
vec3_t up, right, forward;
|
|
|
|
VectorCopy(args->origin,origin);
|
|
VectorCopy(args->angles,angles);
|
|
VectorCopy(args->velocity,velocity);
|
|
AngleVectors(angles,forward,right,up);
|
|
|
|
if(EV_IsLocal(idx))
|
|
{
|
|
EV_MuzzleFlash();
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(burstfire ? G11_BURST : G11_SHOOT,2);
|
|
|
|
if(burstfire)
|
|
{
|
|
if(lessrecoil)
|
|
{
|
|
RECOIL_VIEW(gEngfuncs.pfnRandomFloat(2.0,3.0),0);
|
|
}
|
|
else
|
|
{
|
|
RECOIL_VIEW(gEngfuncs.pfnRandomFloat(3.0,4.5),0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(lessrecoil)
|
|
{
|
|
RECOIL_VIEW(gEngfuncs.pfnRandomFloat(0.5,1.0),0);
|
|
}
|
|
else
|
|
{
|
|
RECOIL_VIEW(gEngfuncs.pfnRandomFloat(1.0,1.5),0);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(burstfire)
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx,origin,CHAN_WEAPON, "weapons/g11_burst.wav", gEngfuncs.pfnRandomFloat(0.92, 1.0), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) );
|
|
else
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx,origin,CHAN_WEAPON,(gEngfuncs.pfnRandomLong(0,1) == 0) ? "weapons/g11_ffire1.wav" : "weapons/g11_ffire2.wav", gEngfuncs.pfnRandomFloat(0.92, 1.0), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) );
|
|
|
|
EV_GetGunPosition( args, vecSrc, origin );
|
|
|
|
if(burstfire)
|
|
{
|
|
float spreadX = args->fparam1;
|
|
float spreadY = args->fparam2;
|
|
|
|
for(int i = 0;i < burstcount;i++)
|
|
{
|
|
spreadX += gEngfuncs.pfnRandomFloat(-0.015,0.015);
|
|
|
|
EV_HLDM_FireBullets(idx,forward,right,up,1,vecSrc,forward,8192,BULLET_47MM,ev_thermal ? 1 : 3,&tracerCount[idx-1],spreadX,spreadY,P_G11);
|
|
|
|
spreadY += bursthop;
|
|
spreadX = args->fparam1;
|
|
}
|
|
}
|
|
else
|
|
EV_HLDM_FireBullets(idx,forward,right,up,1,vecSrc,forward,8192,BULLET_47MM,ev_thermal ? 1 : 10,&tracerCount[idx-1],args->fparam1,args->fparam2,P_G11);
|
|
}
|
|
|
|
/*************
|
|
Bolt Rifle
|
|
*************/
|
|
void EV_BoltRifleShoot(event_args_t *args)
|
|
{
|
|
int idx = args->entindex;
|
|
int whip_only = args->bparam1;
|
|
int empty = args->iparam1;
|
|
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
vec3_t vecSrc;
|
|
vec3_t up, right, forward;
|
|
|
|
VectorCopy(args->origin,origin);
|
|
VectorCopy(args->angles,angles);
|
|
VectorCopy(args->velocity,velocity);
|
|
AngleVectors(angles,forward,right,up);
|
|
|
|
// BoltRifle whip
|
|
if(whip_only)
|
|
{
|
|
//Play Swing sound
|
|
switch(gEngfuncs.pfnRandomLong(0,2))
|
|
{
|
|
case 0:
|
|
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_AUTO, "weapons/whip.wav", 1, ATTN_NORM, 0, PITCH_NORM); break;
|
|
case 1:
|
|
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_AUTO, "weapons/whip3.wav", 1, ATTN_NORM, 0, PITCH_NORM); break;
|
|
case 2:
|
|
default:
|
|
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_AUTO, "weapons/whip2.wav", 1, ATTN_NORM, 0, PITCH_NORM); break;
|
|
}
|
|
|
|
if ( EV_IsLocal( idx ) )
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation ( BOLTRIFLE_STRIKE, 1 );
|
|
|
|
return;
|
|
}
|
|
|
|
if(EV_IsLocal(idx))
|
|
{
|
|
EV_MuzzleFlash();
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(empty ? BOLTRIFLE_SHOOT_LAST : BOLTRIFLE_SHOOT,2);
|
|
|
|
RECOIL_VIEW(5.0,gEngfuncs.pfnRandomFloat(-1.5,1.5));
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx,origin,CHAN_WEAPON,"weapons/boltrifle_fire1.wav", gEngfuncs.pfnRandomFloat(0.92, 1.0), ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong( 0, 3 ) );
|
|
|
|
EV_GetGunPosition( args, vecSrc, origin );
|
|
EV_HLDM_FireBullets(idx,forward,right,up,1,vecSrc,forward,8192,BULLET_762MM,ev_thermal ? 1 : 0,ev_thermal ? &tracerCount[idx-1] : 0,args->fparam1,args->fparam2,P_BOLTRIFLE);
|
|
}
|
|
|
|
/*************
|
|
Sten
|
|
*************/
|
|
void EV_StenShoot(event_args_t *args)
|
|
{
|
|
int idx = args->entindex;
|
|
int silenced = args->bparam1;
|
|
int overheat = args->bparam2;
|
|
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
vec3_t vecSrc;
|
|
vec3_t up, right, forward;
|
|
|
|
VectorCopy(args->origin,origin);
|
|
VectorCopy(args->angles,angles);
|
|
VectorCopy(args->velocity,velocity);
|
|
AngleVectors(angles,forward,right,up);
|
|
|
|
if(overheat)
|
|
{
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx,origin,CHAN_WEAPON,"weapons/sten_overheat.wav",1.0,ATTN_NORM,0,98 + gEngfuncs.pfnRandomLong( 0, 3 ) );
|
|
return;
|
|
}
|
|
|
|
// Shell ejection
|
|
vec3_t ShellVelocity;
|
|
vec3_t ShellOrigin;
|
|
int shell;
|
|
|
|
if(!CVAR_GET_FLOAT("cl_shellcase_quality"))
|
|
shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shells/shell_9x22mm_lo.mdl");
|
|
else
|
|
shell = gEngfuncs.pEventAPI->EV_FindModelIndex ("models/shells/shell_9x22mm_hi.mdl");
|
|
|
|
EV_GetDefaultShellInfo( 2, args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 10, -4, 5 );
|
|
EV_EjectBrass(ShellOrigin,ShellVelocity,angles[ YAW ],shell,TE_BOUNCE_SHELL);
|
|
|
|
if(EV_IsLocal(idx))
|
|
{
|
|
if(!silenced)
|
|
EV_MuzzleFlash();
|
|
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(silenced ? STEN_SHOOT_SILENCED : STEN_SHOOT,2);
|
|
|
|
if(!silenced)
|
|
{
|
|
RECOIL_VIEW(gEngfuncs.pfnRandomFloat(1.4,2.4),0);
|
|
}
|
|
else
|
|
{
|
|
V_PunchAxis( 0, -1.0 );
|
|
}
|
|
}
|
|
|
|
if(silenced)
|
|
{
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx,origin,CHAN_WEAPON,(gEngfuncs.pfnRandomFloat(0,1) == 0) ? "weapons/sten_sfire1.wav" : "weapons/sten_sfire2.wav",gEngfuncs.pfnRandomFloat(0.6, 0.75),ATTN_NORM,0,98 + gEngfuncs.pfnRandomLong( 0, 3 ) );
|
|
}
|
|
else
|
|
{
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx,origin,CHAN_WEAPON,(gEngfuncs.pfnRandomFloat(0,1) == 0) ? "weapons/sten_nfire1.wav" : "weapons/sten_nfire2.wav",gEngfuncs.pfnRandomFloat(0.6, 0.75),ATTN_NORM,0,98 + gEngfuncs.pfnRandomLong( 0, 3 ) );
|
|
}
|
|
|
|
EV_GetGunPosition( args, vecSrc, origin );
|
|
EV_HLDM_FireBullets(idx,forward,right,up,1,vecSrc,forward,8192,BULLET_9MMP,ev_thermal ? 1 : 0,ev_thermal ? &tracerCount[idx-1] : 0,args->fparam1,args->fparam2,P_STEN);
|
|
}
|
|
|
|
/*************
|
|
Molotov Cocktail
|
|
*************/
|
|
void EV_MolotovCocktail(event_args_t *args)
|
|
{
|
|
int flameidx = gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/fire.spr");
|
|
int idx = args->entindex;
|
|
int i;
|
|
float lifetime = args->fparam1;
|
|
float radius = args->fparam2;
|
|
vec3_t origin,origin_down,normal,flame_origin,dl_normal;
|
|
dlight_t *dl;
|
|
pmtrace_t tr;
|
|
physent_t *pe;
|
|
TEMPENTITY *pExplosion;
|
|
|
|
VectorCopy(args->origin,origin);
|
|
VectorCopy(args->angles,normal);
|
|
|
|
// If we're underwater, dont bother running the event
|
|
if(gEngfuncs.PM_PointContents(origin,NULL) == CONTENTS_WATER)
|
|
return;
|
|
|
|
VectorScale(normal,-1024,origin_down);
|
|
VectorAdd(origin,origin_down,origin_down);
|
|
|
|
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(origin,origin_down,PM_WORLD_ONLY,-1,&tr);
|
|
|
|
pe = gEngfuncs.pEventAPI->EV_GetPhysent(tr.ent);
|
|
|
|
// Add scorch mark
|
|
if(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("{scorch1")),
|
|
gEngfuncs.pEventAPI->EV_IndexFromTrace(&tr),0,tr.endpos,0);
|
|
}
|
|
|
|
pExplosion = gEngfuncs.pEfxAPI->R_TempSprite(origin + normal * 8,
|
|
Vector(0,0,8),
|
|
4,
|
|
gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/explode1.spr"),
|
|
kRenderTransAdd,
|
|
0,
|
|
25,
|
|
2,
|
|
FTENT_SPRANIMATE);
|
|
|
|
// Create dynamiclight
|
|
dl = gEngfuncs.pEfxAPI->CL_AllocDlight(0);
|
|
if(dl != NULL)
|
|
{
|
|
VectorCopy(args->origin,dl->origin);
|
|
|
|
// Pull out of the wall so the light shows up
|
|
VectorScale(normal,6,dl_normal);
|
|
VectorAdd(dl_normal,dl->origin,dl->origin);
|
|
|
|
dl->radius = radius;
|
|
|
|
// Color
|
|
dl->color.r = 255;
|
|
dl->color.g = 220;
|
|
dl->color.b = 0;
|
|
|
|
dl->die = gHUD.m_flTime + lifetime;
|
|
dl->decay = 1/(lifetime/dl->radius); // Make it so it completely decays
|
|
}
|
|
|
|
switch(gEngfuncs.pfnRandomLong(0,2))
|
|
{
|
|
case 0:
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx,origin,CHAN_AUTO,"debris/glass1.wav",1.0,ATTN_NORM,0,98 + gEngfuncs.pfnRandomLong(0,3)); break;
|
|
case 1:
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx,origin,CHAN_AUTO,"debris/glass2.wav",1.0,ATTN_NORM,0,98 + gEngfuncs.pfnRandomLong(0,3)); break;
|
|
case 2:
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx,origin,CHAN_AUTO,"debris/glass3.wav",1.0,ATTN_NORM,0,98 + gEngfuncs.pfnRandomLong(0,3)); break;
|
|
}
|
|
|
|
// Main flame
|
|
VectorCopy(origin,flame_origin);
|
|
|
|
gEngfuncs.pEventAPI->EV_PopPMStates();
|
|
|
|
// Cinders
|
|
for(i = 0;i <= CVAR_GET_FLOAT("cl_efx_frequency");i++)
|
|
{
|
|
vec3_t cinder_origin = flame_origin + normal*10;
|
|
|
|
// randomize cinder_origin a bit
|
|
cinder_origin[0] += gEngfuncs.pfnRandomFloat(-9.0f,9.0f);
|
|
cinder_origin[1] += gEngfuncs.pfnRandomFloat(-9.0f,9.0f);
|
|
cinder_origin[2] += gEngfuncs.pfnRandomFloat(-9.0f,9.0f);
|
|
TEMPENTITY *pTent = gEngfuncs.pEfxAPI->CL_TempEntAllocNoModel(cinder_origin);
|
|
|
|
if(pTent != NULL)
|
|
{
|
|
pTent->flags |= FTENT_NOMODEL|FTENT_GRAVITY|FTENT_COLLIDEWORLD|FTENT_COLLIDEKILL|FTENT_PERSIST|FTENT_CLIENTCUSTOM;
|
|
pTent->die += lifetime;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*************
|
|
Frag Grenade
|
|
*************/
|
|
|
|
// copied from util.cpp to here
|
|
float EV_WaterLevel(float *position, float minz, float maxz )
|
|
{
|
|
vec3_t midUp = position;
|
|
midUp.z = minz;
|
|
|
|
if (gEngfuncs.PM_PointContents(midUp,NULL) != CONTENTS_WATER)
|
|
return minz;
|
|
|
|
midUp.z = maxz;
|
|
if (gEngfuncs.PM_PointContents(midUp,NULL) == CONTENTS_WATER)
|
|
return maxz;
|
|
|
|
float diff = maxz - minz;
|
|
while (diff > 1.0)
|
|
{
|
|
midUp.z = minz + diff/2.0;
|
|
if (gEngfuncs.PM_PointContents(midUp,NULL) == CONTENTS_WATER)
|
|
{
|
|
minz = midUp.z;
|
|
}
|
|
else
|
|
{
|
|
maxz = midUp.z;
|
|
}
|
|
diff = maxz - minz;
|
|
}
|
|
|
|
return midUp.z;
|
|
}
|
|
|
|
void EV_FragGrenade_ShrapnelCallback(struct tempent_s *ent,float frametime,float currenttime)
|
|
{
|
|
if(gHUD.m_flTime >= ent->entity.baseline.fuser1)
|
|
{
|
|
ent->entity.baseline.fuser1 = gHUD.m_flTime + 0.25f;
|
|
|
|
// Emit a smoke tent
|
|
TEMPENTITY *pTent = gEngfuncs.pEfxAPI->R_TempSprite(ent->entity.origin,
|
|
Vector(0,0,5),
|
|
1,
|
|
gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/smoke1.spr"),
|
|
kRenderTransAlpha,
|
|
0,
|
|
25,
|
|
5,
|
|
FTENT_SPRANIMATE);
|
|
|
|
// state settings
|
|
if(pTent != NULL)
|
|
{
|
|
pTent->entity.curstate.framerate = 30;
|
|
pTent->entity.curstate.renderamt = 128;
|
|
}
|
|
}
|
|
}
|
|
|
|
void EV_FragGrenade(event_args_t *args)
|
|
{
|
|
int idx = args->entindex;
|
|
int inwater = args->iparam1;
|
|
vec3_t origin,normal;
|
|
vec3_t origin_down;
|
|
vec3_t sh_forward,sh_right,sh_up,sh_velocity;
|
|
pmtrace_t tr;
|
|
physent_t *pe;
|
|
TEMPENTITY *pExplosion;
|
|
TEMPENTITY *pShrapnel;
|
|
|
|
VectorCopy(args->origin,origin);
|
|
VectorCopy(args->angles,normal);
|
|
|
|
VectorScale(normal,-32,origin_down);
|
|
VectorAdd(origin,origin_down,origin_down);
|
|
|
|
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(origin + normal*16,origin_down,PM_WORLD_ONLY,-1,&tr);
|
|
|
|
gEngfuncs.pEventAPI->EV_PopPMStates();
|
|
|
|
pe = gEngfuncs.pEventAPI->EV_GetPhysent(tr.ent);
|
|
|
|
// Add scorch mark
|
|
if(!inwater && 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("{scorch1")),
|
|
gEngfuncs.pEventAPI->EV_IndexFromTrace(&tr),0,tr.endpos,0);
|
|
}
|
|
|
|
// create the explosion sprite
|
|
if(!inwater)
|
|
{
|
|
pExplosion = gEngfuncs.pEfxAPI->R_TempSprite(origin + normal * 8,
|
|
Vector(0,0,8),
|
|
4,
|
|
gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/explode1.spr"),
|
|
kRenderTransAdd,
|
|
0,
|
|
25,
|
|
2,
|
|
FTENT_SPRANIMATE);
|
|
}
|
|
else
|
|
{
|
|
vec3_t mins = origin - Vector(64,64,64);
|
|
vec3_t maxs = origin + Vector(64,64,64);
|
|
vec3_t mid = (mins + maxs) * 0.5f;
|
|
|
|
float flHeight = EV_WaterLevel(mid,mid.z,mid.z + 1024);
|
|
|
|
flHeight = flHeight - mins.z;
|
|
|
|
// Water bubbles!
|
|
gEngfuncs.pEfxAPI->R_Bubbles(mins,
|
|
maxs,
|
|
flHeight,
|
|
gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/bubble.spr"),
|
|
CVAR_GET_FLOAT("cl_efx_frequency") * 75,
|
|
8);
|
|
}
|
|
|
|
// Explosion
|
|
switch(gEngfuncs.pfnRandomLong(0,2))
|
|
{
|
|
case 0: gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_AUTO, "weapons/explode3.wav", 1.0, ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong(0,3)); break;
|
|
case 1: gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_AUTO, "weapons/explode4.wav", 1.0, ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong(0,3)); break;
|
|
case 2: gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_AUTO, "weapons/explode5.wav", 1.0, ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong(0,3)); break;
|
|
}
|
|
|
|
// Debris sound
|
|
if(!inwater)
|
|
{
|
|
if(gEngfuncs.pfnRandomLong(0,1))
|
|
{
|
|
switch(gEngfuncs.pfnRandomLong(0,2))
|
|
{
|
|
case 0: gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_AUTO, "weapons/debris1.wav", 1.0, ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong(0,3)); break;
|
|
case 1: gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_AUTO, "weapons/debris2.wav", 1.0, ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong(0,3)); break;
|
|
case 2: gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_AUTO, "weapons/debris3.wav", 1.0, ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong(0,3)); break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Shrapnel !
|
|
if(!inwater)
|
|
{
|
|
AngleVectors(normal,sh_forward,sh_right,sh_up);
|
|
|
|
for(int i = 0;i < CVAR_GET_FLOAT("cl_efx_frequency") * 4;i++)
|
|
{
|
|
// Randomize velocity
|
|
sh_velocity = sh_forward * gEngfuncs.pfnRandomFloat(-800.0f,800.0f) + sh_right * gEngfuncs.pfnRandomFloat(-800.0f,800.0f) + sh_up * gEngfuncs.pfnRandomFloat(200.0f,400.0f);
|
|
|
|
pShrapnel = gEngfuncs.pEfxAPI->R_TempModel(origin + normal * 10,
|
|
sh_velocity,
|
|
normal,
|
|
5,
|
|
gEngfuncs.pEventAPI->EV_FindModelIndex("models/shrapnel.mdl"),
|
|
0);
|
|
|
|
if(pShrapnel != NULL)
|
|
{
|
|
pShrapnel->flags |= FTENT_CLIENTCUSTOM;
|
|
pShrapnel->callback = EV_FragGrenade_ShrapnelCallback;
|
|
|
|
// Next smoke emit
|
|
pShrapnel->entity.baseline.fuser1 = gHUD.m_flTime + 0.25f;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*************
|
|
Pipebomb
|
|
*************/
|
|
void EV_Pipebomb(event_args_t *args)
|
|
{
|
|
int idx = args->entindex;
|
|
int inwater = args->iparam1;
|
|
vec3_t origin,normal;
|
|
vec3_t origin_down;
|
|
pmtrace_t tr;
|
|
physent_t *pe;
|
|
TEMPENTITY *pExplosion;
|
|
|
|
VectorCopy(args->origin,origin);
|
|
VectorCopy(args->angles,normal);
|
|
|
|
VectorScale(normal,-32,origin_down);
|
|
VectorAdd(origin,origin_down,origin_down);
|
|
|
|
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(origin + normal*16,origin_down,PM_WORLD_ONLY,-1,&tr);
|
|
|
|
gEngfuncs.pEventAPI->EV_PopPMStates();
|
|
|
|
pe = gEngfuncs.pEventAPI->EV_GetPhysent(tr.ent);
|
|
|
|
// Add scorch mark
|
|
if(!inwater && 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("{scorch1")),
|
|
gEngfuncs.pEventAPI->EV_IndexFromTrace(&tr),0,tr.endpos,0);
|
|
}
|
|
|
|
// Explosion
|
|
switch(gEngfuncs.pfnRandomLong(0,2))
|
|
{
|
|
case 0: gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_AUTO, "weapons/explode3.wav", 1.0, ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong(0,3)); break;
|
|
case 1: gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_AUTO, "weapons/explode4.wav", 1.0, ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong(0,3)); break;
|
|
case 2: gEngfuncs.pEventAPI->EV_PlaySound(idx, origin, CHAN_AUTO, "weapons/explode5.wav", 1.0, ATTN_NORM, 0, 98 + gEngfuncs.pfnRandomLong(0,3)); break;
|
|
}
|
|
|
|
// create the explosion sprite
|
|
if(!inwater)
|
|
{
|
|
pExplosion = gEngfuncs.pEfxAPI->R_TempSprite(origin + normal * 8,
|
|
Vector(0,0,8),
|
|
4.75f,
|
|
gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/explode1.spr"),
|
|
kRenderTransAdd,
|
|
0,
|
|
25,
|
|
2,
|
|
FTENT_SPRANIMATE);
|
|
}
|
|
else
|
|
{
|
|
vec3_t mins = origin - Vector(64,64,64);
|
|
vec3_t maxs = origin + Vector(64,64,64);
|
|
vec3_t mid = (mins + maxs) * 0.5f;
|
|
|
|
float flHeight = EV_WaterLevel(mid,mid.z,mid.z + 1024);
|
|
|
|
flHeight = flHeight - mins.z;
|
|
|
|
// Water bubbles!
|
|
gEngfuncs.pEfxAPI->R_Bubbles(mins,
|
|
maxs,
|
|
flHeight,
|
|
gEngfuncs.pEventAPI->EV_FindModelIndex("sprites/bubble.spr"),
|
|
CVAR_GET_FLOAT("cl_efx_frequency") * 75,
|
|
8);
|
|
}
|
|
}
|
|
|
|
/*************
|
|
Combat Knife
|
|
*************/
|
|
void EV_CombatKnife(event_args_t *args)
|
|
{
|
|
int idx,primary_attack;
|
|
vec3_t origin;
|
|
vec3_t vecSrc,vecDest;
|
|
|
|
idx = args->entindex;
|
|
primary_attack = args->iparam1;
|
|
|
|
VectorCopy( args->origin, origin );
|
|
|
|
//Play Swing sound
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx,origin,CHAN_WEAPON,"weapons/combatknife_slash1.wav",1,ATTN_NORM,0,PITCH_NORM);
|
|
|
|
if(EV_IsLocal(idx))
|
|
{
|
|
if(primary_attack)
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(COMBATKNIFE_ATTACK1MISS,1);
|
|
else
|
|
{
|
|
switch(gEngfuncs.pfnRandomLong(0,1))
|
|
{
|
|
case 0:
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(COMBATKNIFE_ATTACK2,1); break;
|
|
case 1:
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(COMBATKNIFE_ATTACK3,1); break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*************
|
|
Baseball Bat
|
|
*************/
|
|
void EV_BaseballBat(event_args_t *args)
|
|
{
|
|
int idx;
|
|
vec3_t origin;
|
|
vec3_t vecSrc,vecDest;
|
|
|
|
idx = args->entindex;
|
|
|
|
VectorCopy( args->origin, origin );
|
|
|
|
//Play Swing sound
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx,origin,CHAN_WEAPON,"weapons/baseballbat_slash1.wav",1,ATTN_NORM,0,PITCH_NORM);
|
|
|
|
if(EV_IsLocal(idx))
|
|
{
|
|
switch(gEngfuncs.pfnRandomLong(0,2))
|
|
{
|
|
case 0: gEngfuncs.pEventAPI->EV_WeaponAnimation(BAT_ATTACK1,1); break;
|
|
case 1: gEngfuncs.pEventAPI->EV_WeaponAnimation(BAT_ATTACK2,1); break;
|
|
case 2: gEngfuncs.pEventAPI->EV_WeaponAnimation(BAT_ATTACK3,1); break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*************
|
|
Sledge Hammer
|
|
*************/
|
|
void EV_SledgeHammer(event_args_t *args)
|
|
{
|
|
int idx;
|
|
vec3_t origin;
|
|
|
|
idx = args->entindex;
|
|
|
|
VectorCopy( args->origin, origin );
|
|
|
|
//Play Swing sound
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx,origin,CHAN_WEAPON,"weapons/sledgehammer_slash1.wav",1,ATTN_NORM,0,PITCH_NORM);
|
|
|
|
if(EV_IsLocal(idx))
|
|
{
|
|
switch(gEngfuncs.pfnRandomLong(0,1))
|
|
{
|
|
case 0: gEngfuncs.pEventAPI->EV_WeaponAnimation(SLEDGE_ATTACK1,1); break;
|
|
case 1: gEngfuncs.pEventAPI->EV_WeaponAnimation(SLEDGE_ATTACK2,1); break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*************
|
|
Katana
|
|
*************/
|
|
void EV_Katana(event_args_t *args)
|
|
{
|
|
int idx,primary_attack;
|
|
vec3_t origin;
|
|
|
|
idx = args->entindex;
|
|
primary_attack = args->iparam1;
|
|
|
|
VectorCopy( args->origin, origin );
|
|
|
|
//Play Swing sound
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx,origin,CHAN_WEAPON,"weapons/katana_slash1.wav",1,ATTN_NORM,0,PITCH_NORM);
|
|
|
|
if(EV_IsLocal(idx))
|
|
{
|
|
if(primary_attack)
|
|
{
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation(KATANA_ST1_ATTACK1,1);
|
|
}
|
|
else
|
|
{
|
|
switch(gEngfuncs.pfnRandomLong(0,1))
|
|
{
|
|
case 0: gEngfuncs.pEventAPI->EV_WeaponAnimation(KATANA_ST2_ATTACK1,1); break;
|
|
case 1: gEngfuncs.pEventAPI->EV_WeaponAnimation(KATANA_ST2_ATTACK2,1); break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/*************
|
|
Spear
|
|
*************/
|
|
void EV_Spear(event_args_t *args)
|
|
{
|
|
int idx;
|
|
vec3_t origin;
|
|
|
|
idx = args->entindex;
|
|
|
|
VectorCopy( args->origin, origin );
|
|
|
|
//Play Swing sound
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx,origin,CHAN_WEAPON,"weapons/spear_slash1.wav",1,ATTN_NORM,0,PITCH_NORM);
|
|
|
|
if(EV_IsLocal(idx))
|
|
{
|
|
switch(gEngfuncs.pfnRandomLong(0,1))
|
|
{
|
|
case 0: gEngfuncs.pEventAPI->EV_WeaponAnimation(SPEAR_ATTACK1,1); break;
|
|
case 1: gEngfuncs.pEventAPI->EV_WeaponAnimation(SPEAR_ATTACK2,1); break;
|
|
}
|
|
}
|
|
}
|
|
|
|
extern cvar_t *sensitivity;
|
|
|
|
/*************
|
|
Cattle Prod
|
|
*************/
|
|
void EV_CattleProd(event_args_t *args)
|
|
{
|
|
int idx;
|
|
vec3_t origin;
|
|
|
|
idx = args->entindex;
|
|
|
|
VectorCopy( args->origin, origin );
|
|
|
|
//Play Swing sound
|
|
gEngfuncs.pEventAPI->EV_PlaySound(idx,origin,CHAN_WEAPON,"weapons/prod_hit.wav",1,ATTN_NORM,0,PITCH_NORM);
|
|
|
|
if(EV_IsLocal(idx))
|
|
{
|
|
switch(gEngfuncs.pfnRandomLong(0,1))
|
|
{
|
|
case 0: gEngfuncs.pEventAPI->EV_WeaponAnimation(PROD_ATTACK1,1); break;
|
|
case 1: gEngfuncs.pEventAPI->EV_WeaponAnimation(PROD_ATTACK2,1); break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*************
|
|
Akimbo Weapons
|
|
*************/
|
|
void EV_AkimboWeapon(event_args_t *args, const char *sound, const char *loshell, const char *hishell, int bullettype, int ptype )
|
|
{
|
|
int idx;
|
|
vec3_t origin, angles, up, right, forward, velocity;
|
|
vec3_t vecSrc, vecAiming;
|
|
int curhand;
|
|
int ammo_left;
|
|
|
|
VectorCopy( args->origin, origin );
|
|
VectorCopy( args->angles, angles );
|
|
VectorCopy( args->velocity, velocity );
|
|
AngleVectors( angles, forward, right, up );
|
|
EV_GetGunPosition( args, vecSrc, origin );
|
|
VectorCopy( forward, vecAiming );
|
|
|
|
idx = args->entindex;
|
|
curhand = args->iparam1;
|
|
ammo_left = args->iparam2;
|
|
|
|
// Play firing sound
|
|
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, sound, 1, ATTN_NORM, 0, PITCH_NORM );
|
|
|
|
// Shell ejection
|
|
vec3_t ShellVelocity;
|
|
vec3_t ShellOrigin;
|
|
int shell;
|
|
|
|
if(!CVAR_GET_FLOAT("cl_shellcase_quality"))
|
|
shell = gEngfuncs.pEventAPI->EV_FindModelIndex ( loshell );
|
|
else
|
|
shell = gEngfuncs.pEventAPI->EV_FindModelIndex ( hishell );
|
|
|
|
if( curhand == AH_RIGHT )
|
|
EV_GetDefaultShellInfo( 0, args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 10, -4, 5 );
|
|
else
|
|
EV_GetDefaultShellInfo( 0, args, origin, velocity, ShellVelocity, ShellOrigin, forward, right, up, 10, -4, -5 );
|
|
|
|
EV_EjectBrass( ShellOrigin, ShellVelocity, angles[ YAW ], shell, TE_BOUNCE_SHELL );
|
|
|
|
if( EV_IsLocal( idx ) )
|
|
{
|
|
EV_MuzzleFlash();
|
|
|
|
if( curhand == AH_LEFT )
|
|
{
|
|
if( ammo_left <= 1 )
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation( AKIMBO_LSHOOTLAST, 1 );
|
|
else
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation( AKIMBO_LSHOOT, 1 );
|
|
}
|
|
else
|
|
{
|
|
if( ammo_left <= 1 )
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation( AKIMBO_RSHOOTLAST_LEMPTY, 1 );
|
|
else
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation( AKIMBO_RSHOOT, 1 );
|
|
}
|
|
}
|
|
|
|
// TODO: change penetration type and bullet type to match different guns!
|
|
EV_HLDM_FireBullets( idx, forward, right, up, 1, vecSrc, vecAiming, 8192, bullettype, (ev_thermal) ? 1 : 0, (ev_thermal) ? &tracerCount[idx-1] : 0, args->fparam1, args->fparam2, ptype );
|
|
}
|
|
|
|
void EV_AkimboBerettas( event_args_t *args )
|
|
{
|
|
int idx = args->entindex;
|
|
|
|
EV_AkimboWeapon( args,
|
|
"weapons/beretta_fire.wav",
|
|
"models/shells/shell_9x18mm_lo.mdl",
|
|
"models/shells/shell_9x18mm_hi.mdl",
|
|
BULLET_9MMP,
|
|
P_BERETTA );
|
|
|
|
if( EV_IsLocal( idx ) )
|
|
V_PunchAxis( 0, -2.0 );
|
|
}
|
|
|
|
void EV_AkimboColts( event_args_t *args )
|
|
{
|
|
int idx = args->entindex;
|
|
|
|
EV_AkimboWeapon( args,
|
|
"weapons/colt_fire.wav",
|
|
"models/shells/shell_10mm_lo.mdl",
|
|
"models/shells/shell_10mm_hi.mdl",
|
|
BULLET_10MM,
|
|
P_COLT );
|
|
|
|
if( EV_IsLocal( idx ) )
|
|
V_PunchAxis( 0, -2.0 );
|
|
}
|
|
|
|
void EV_AkimboDeagles( event_args_t *args )
|
|
{
|
|
int idx = args->entindex;
|
|
|
|
EV_AkimboWeapon( args,
|
|
"weapons/deagle_fire.wav",
|
|
"models/shells/shell_50AE_lo.mdl",
|
|
"models/shells/shell_50AE_hi.mdl",
|
|
BULLET_50AE,
|
|
P_DEAGLE );
|
|
|
|
if( EV_IsLocal( idx ) )
|
|
{
|
|
V_PunchAxis( 0, -2.0 );
|
|
|
|
RECOIL_VIEW(5.5,0);
|
|
}
|
|
}
|
|
|
|
void EV_AkimboSawedOffs( event_args_t *args )
|
|
{
|
|
int idx = args->entindex;
|
|
int curhand = args->iparam1;
|
|
int bothshoot = args->bparam1; // Both guns were fired :O
|
|
|
|
vec3_t origin;
|
|
vec3_t angles;
|
|
vec3_t velocity;
|
|
vec3_t up, right, forward;
|
|
VectorCopy( args->origin, origin );
|
|
VectorCopy( args->angles, angles );
|
|
VectorCopy( args->velocity, velocity );
|
|
AngleVectors( angles, forward, right, up );
|
|
|
|
vec3_t vecSrc, vecAiming;
|
|
vec3_t vecSpread;
|
|
|
|
if( EV_IsLocal( idx ) )
|
|
{
|
|
// Add muzzle flash to current weapon model
|
|
EV_MuzzleFlash();
|
|
|
|
if( bothshoot )
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation( AKIMBOSS_BSHOOT, 2 );
|
|
else
|
|
gEngfuncs.pEventAPI->EV_WeaponAnimation( (curhand == AH_LEFT) ? AKIMBOSS_LSHOOT : AKIMBOSS_RSHOOT, 2 );
|
|
|
|
if( bothshoot )
|
|
V_PunchAxis( 0, -11.5 );
|
|
else
|
|
V_PunchAxis( 0, -5.0 );
|
|
}
|
|
|
|
gEngfuncs.pEventAPI->EV_PlaySound( idx, origin, CHAN_WEAPON, ( !bothshoot ) ? "weapons/sawedoff_fire1.wav" : "weapons/sawedoff_fire2.wav", gEngfuncs.pfnRandomFloat(0.95, 1.0), ATTN_NORM, 0, 93 + gEngfuncs.pfnRandomLong( 0, 0x1f ) );
|
|
|
|
EV_GetGunPosition( args, vecSrc, origin );
|
|
VectorCopy( forward, vecAiming );
|
|
|
|
int shotCount = (bothshoot) ? 26 : 14;
|
|
|
|
// Remember to change the randomization code at the bottom :)
|
|
EV_HLDM_FireBullets( idx, forward, right, up, shotCount, vecSrc, vecAiming, 2048, BULLET_20GAUGE, (ev_thermal) ? 1 : 0, (ev_thermal) ? &tracerCount[idx-1] : 0, args->fparam1, args->fparam2, 0 );
|
|
}
|