/*** * * 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 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 , char *fire_sound,int iBulletType, char *loshell, 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, char *sound, char *loshell, 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 ); }