summaryrefslogtreecommitdiff
path: root/src/cgame/cg_weapons.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cgame/cg_weapons.c')
-rw-r--r--src/cgame/cg_weapons.c1810
1 files changed, 0 insertions, 1810 deletions
diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c
deleted file mode 100644
index 7297c518..00000000
--- a/src/cgame/cg_weapons.c
+++ /dev/null
@@ -1,1810 +0,0 @@
-// Copyright (C) 1999-2000 Id Software, Inc.
-//
-// cg_weapons.c -- events and effects dealing with weapons
-
-/*
- * Portions Copyright (C) 2000-2001 Tim Angus
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the OSML - Open Source Modification License v1.0 as
- * described in the file COPYING which is distributed with this source
- * code.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- */
-
-#include "cg_local.h"
-
-/*
-=================
-CG_RegisterUpgrade
-
-The server says this item is used on this level
-=================
-*/
-void CG_RegisterUpgrade( int upgradeNum )
-{
- upgradeInfo_t *upgradeInfo;
- char *icon;
-
- upgradeInfo = &cg_upgrades[ upgradeNum ];
-
- if( upgradeNum == 0 )
- return;
-
- if( upgradeInfo->registered )
- return;
-
- memset( upgradeInfo, 0, sizeof( *upgradeInfo ) );
- upgradeInfo->registered = qtrue;
-
- if( !BG_FindNameForUpgrade( upgradeNum ) )
- CG_Error( "Couldn't find upgrade %i", upgradeNum );
-
- upgradeInfo->humanName = BG_FindHumanNameForUpgrade( upgradeNum );
-
- //la la la la la, i'm not listening!
- if( upgradeNum == UP_GRENADE )
- upgradeInfo->upgradeIcon = cg_weapons[ WP_GRENADE ].weaponIcon;
- else if( ( icon = BG_FindIconForUpgrade( upgradeNum ) ) )
- upgradeInfo->upgradeIcon = trap_R_RegisterShader( icon );
-}
-
-/*
-===============
-CG_InitUpgrades
-
-Precaches upgrades
-===============
-*/
-void CG_InitUpgrades( void )
-{
- int i;
-
- memset( cg_upgrades, 0, sizeof( cg_upgrades ) );
-
- for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ )
- CG_RegisterUpgrade( i );
-}
-
-
-/*
-===============
-CG_ParseWeaponModeSection
-
-Parse a weapon mode section
-===============
-*/
-static qboolean CG_ParseWeaponModeSection( weaponInfoMode_t *wim, char **text_p )
-{
- char *token;
- int i;
-
- // read optional parameters
- while( 1 )
- {
- token = COM_Parse( text_p );
-
- if( !token )
- break;
-
- if( !Q_stricmp( token, "" ) )
- return qfalse;
-
- if( !Q_stricmp( token, "missileModel" ) )
- {
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- wim->missileModel = trap_R_RegisterModel( token );
-
- if( !wim->missileModel )
- CG_Printf( S_COLOR_RED "ERROR: missile model not found %s\n", token );
-
- continue;
- }
- else if( !Q_stricmp( token, "missileSprite" ) )
- {
- int size = 0;
-
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- size = atoi( token );
-
- if( size < 0 )
- size = 0;
-
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- wim->missileSprite = trap_R_RegisterShader( token );
- wim->missileSpriteSize = size;
- wim->usesSpriteMissle = qtrue;
-
- if( !wim->missileSprite )
- CG_Printf( S_COLOR_RED "ERROR: missile sprite not found %s\n", token );
-
- continue;
- }
- else if( !Q_stricmp( token, "missileRotates" ) )
- {
- wim->missileRotates = qtrue;
-
- continue;
- }
- else if( !Q_stricmp( token, "missileAnimates" ) )
- {
- wim->missileAnimates = qtrue;
-
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- wim->missileAnimStartFrame = atoi( token );
-
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- wim->missileAnimNumFrames = atoi( token );
-
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- wim->missileAnimFrameRate = atoi( token );
-
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- wim->missileAnimLooping = atoi( token );
-
- continue;
- }
- else if( !Q_stricmp( token, "missileParticleSystem" ) )
- {
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- wim->missileParticleSystem = CG_RegisterParticleSystem( token );
-
- if( !wim->missileParticleSystem )
- CG_Printf( S_COLOR_RED "ERROR: missile particle system not found %s\n", token );
-
- continue;
- }
- else if( !Q_stricmp( token, "missileTrailSystem" ) )
- {
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- wim->missileTrailSystem = CG_RegisterTrailSystem( token );
-
- if( !wim->missileTrailSystem )
- CG_Printf( S_COLOR_RED "ERROR: missile trail system not found %s\n", token );
-
- continue;
- }
- else if( !Q_stricmp( token, "muzzleParticleSystem" ) )
- {
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- wim->muzzleParticleSystem = CG_RegisterParticleSystem( token );
-
- if( !wim->muzzleParticleSystem )
- CG_Printf( S_COLOR_RED "ERROR: muzzle particle system not found %s\n", token );
-
- continue;
- }
- else if( !Q_stricmp( token, "impactParticleSystem" ) )
- {
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- wim->impactParticleSystem = CG_RegisterParticleSystem( token );
-
- if( !wim->impactParticleSystem )
- CG_Printf( S_COLOR_RED "ERROR: impact particle system not found %s\n", token );
-
- continue;
- }
- else if( !Q_stricmp( token, "impactMark" ) )
- {
- int size = 0;
-
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- size = atoi( token );
-
- if( size < 0 )
- size = 0;
-
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- wim->impactMark = trap_R_RegisterShader( token );
- wim->impactMarkSize = size;
-
- if( !wim->impactMark )
- CG_Printf( S_COLOR_RED "ERROR: impact mark shader not found %s\n", token );
-
- continue;
- }
- else if( !Q_stricmp( token, "impactSound" ) )
- {
- int index = 0;
-
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- index = atoi( token );
-
- if( index < 0 )
- index = 0;
- else if( index > 3 )
- index = 3;
-
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- wim->impactSound[ index ] = trap_S_RegisterSound( token, qfalse );
-
- continue;
- }
- else if( !Q_stricmp( token, "impactFleshSound" ) )
- {
- int index = 0;
-
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- index = atoi( token );
-
- if( index < 0 )
- index = 0;
- else if( index > 3 )
- index = 3;
-
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- wim->impactFleshSound[ index ] = trap_S_RegisterSound( token, qfalse );
-
- continue;
- }
- else if( !Q_stricmp( token, "alwaysImpact" ) )
- {
- wim->alwaysImpact = qtrue;
-
- continue;
- }
- else if( !Q_stricmp( token, "flashDLightColor" ) )
- {
- for( i = 0 ; i < 3 ; i++ )
- {
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- wim->flashDlightColor[ i ] = atof( token );
- }
-
- continue;
- }
- else if( !Q_stricmp( token, "continuousFlash" ) )
- {
- wim->continuousFlash = qtrue;
-
- continue;
- }
- else if( !Q_stricmp( token, "missileDlightColor" ) )
- {
- for( i = 0 ; i < 3 ; i++ )
- {
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- wim->missileDlightColor[ i ] = atof( token );
- }
-
- continue;
- }
- else if( !Q_stricmp( token, "missileDlight" ) )
- {
- int size = 0;
-
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- size = atoi( token );
-
- if( size < 0 )
- size = 0;
-
- wim->missileDlight = size;
-
- continue;
- }
- else if( !Q_stricmp( token, "firingSound" ) )
- {
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- wim->firingSound = trap_S_RegisterSound( token, qfalse );
-
- continue;
- }
- else if( !Q_stricmp( token, "missileSound" ) )
- {
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- wim->missileSound = trap_S_RegisterSound( token, qfalse );
-
- continue;
- }
- else if( !Q_stricmp( token, "flashSound" ) )
- {
- int index = 0;
-
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- index = atoi( token );
-
- if( index < 0 )
- index = 0;
- else if( index > 3 )
- index = 3;
-
- token = COM_Parse( text_p );
- if( !token )
- break;
-
- wim->flashSound[ index ] = trap_S_RegisterSound( token, qfalse );
-
- continue;
- }
- else if( !Q_stricmp( token, "}" ) )
- return qtrue; //reached the end of this weapon section
- else
- {
- CG_Printf( S_COLOR_RED "ERROR: unknown token '%s' in weapon section\n", token );
- return qfalse;
- }
- }
-
- return qfalse;
-}
-
-
-/*
-======================
-CG_ParseWeaponFile
-
-Parses a configuration file describing a weapon
-======================
-*/
-static qboolean CG_ParseWeaponFile( const char *filename, weaponInfo_t *wi )
-{
- char *text_p;
- int len;
- char *token;
- char text[ 20000 ];
- fileHandle_t f;
- weaponMode_t weaponMode = WPM_NONE;
-
- // load the file
- len = trap_FS_FOpenFile( filename, &f, FS_READ );
- if( len <= 0 )
- return qfalse;
-
- if( len >= sizeof( text ) - 1 )
- {
- CG_Printf( "File %s too long\n", filename );
- return qfalse;
- }
-
- trap_FS_Read( text, len, f );
- text[ len ] = 0;
- trap_FS_FCloseFile( f );
-
- // parse the text
- text_p = text;
-
- // read optional parameters
- while( 1 )
- {
- token = COM_Parse( &text_p );
-
- if( !token )
- break;
-
- if( !Q_stricmp( token, "" ) )
- break;
-
- if( !Q_stricmp( token, "{" ) )
- {
- if( weaponMode == WPM_NONE )
- {
- CG_Printf( S_COLOR_RED "ERROR: weapon mode section started without a declaration\n" );
- return qfalse;
- }
- else if( !CG_ParseWeaponModeSection( &wi->wim[ weaponMode ], &text_p ) )
- {
- CG_Printf( S_COLOR_RED "ERROR: failed to parse weapon mode section\n" );
- return qfalse;
- }
-
- //start parsing ejectors again
- weaponMode = WPM_NONE;
-
- continue;
- }
- else if( !Q_stricmp( token, "primary" ) )
- {
- weaponMode = WPM_PRIMARY;
- continue;
- }
- else if( !Q_stricmp( token, "secondary" ) )
- {
- weaponMode = WPM_SECONDARY;
- continue;
- }
- else if( !Q_stricmp( token, "tertiary" ) )
- {
- weaponMode = WPM_TERTIARY;
- continue;
- }
- else if( !Q_stricmp( token, "weaponModel" ) )
- {
- char path[ MAX_QPATH ];
-
- token = COM_Parse( &text_p );
- if( !token )
- break;
-
- wi->weaponModel = trap_R_RegisterModel( token );
-
- if( !wi->weaponModel )
- CG_Printf( S_COLOR_RED "ERROR: weapon model not found %s\n", token );
-
- strcpy( path, token );
- COM_StripExtension( path, path );
- strcat( path, "_flash.md3" );
- wi->flashModel = trap_R_RegisterModel( path );
-
- strcpy( path, token );
- COM_StripExtension( path, path );
- strcat( path, "_barrel.md3" );
- wi->barrelModel = trap_R_RegisterModel( path );
-
- strcpy( path, token );
- COM_StripExtension( path, path );
- strcat( path, "_hand.md3" );
- wi->handsModel = trap_R_RegisterModel( path );
-
- if( !wi->handsModel )
- wi->handsModel = trap_R_RegisterModel( "models/weapons2/shotgun/shotgun_hand.md3" );
-
- continue;
- }
- else if( !Q_stricmp( token, "idleSound" ) )
- {
- token = COM_Parse( &text_p );
- if( !token )
- break;
-
- wi->readySound = trap_S_RegisterSound( token, qfalse );
-
- continue;
- }
- else if( !Q_stricmp( token, "icon" ) )
- {
- token = COM_Parse( &text_p );
- if( !token )
- break;
-
- wi->weaponIcon = wi->ammoIcon = trap_R_RegisterShader( token );
-
- if( !wi->weaponIcon )
- CG_Printf( S_COLOR_RED "ERROR: weapon icon not found %s\n", token );
-
- continue;
- }
- else if( !Q_stricmp( token, "crosshair" ) )
- {
- int size = 0;
-
- token = COM_Parse( &text_p );
- if( !token )
- break;
-
- size = atoi( token );
-
- if( size < 0 )
- size = 0;
-
- token = COM_Parse( &text_p );
- if( !token )
- break;
-
- wi->crossHair = trap_R_RegisterShader( token );
- wi->crossHairSize = size;
-
- if( !wi->crossHair )
- CG_Printf( S_COLOR_RED "ERROR: weapon crosshair not found %s\n", token );
-
- continue;
- }
- else if( !Q_stricmp( token, "disableIn3rdPerson" ) )
- {
- wi->disableIn3rdPerson = qtrue;
-
- continue;
- }
-
- Com_Printf( S_COLOR_RED "ERROR: unknown token '%s'\n", token );
- return qfalse;
- }
-
- return qtrue;
-}
-
-/*
-=================
-CG_RegisterWeapon
-=================
-*/
-void CG_RegisterWeapon( int weaponNum )
-{
- weaponInfo_t *weaponInfo;
- char path[ MAX_QPATH ];
- vec3_t mins, maxs;
- int i;
-
- weaponInfo = &cg_weapons[ weaponNum ];
-
- if( weaponNum == 0 )
- return;
-
- if( weaponInfo->registered )
- return;
-
- memset( weaponInfo, 0, sizeof( *weaponInfo ) );
- weaponInfo->registered = qtrue;
-
- if( !BG_FindNameForWeapon( weaponNum ) )
- CG_Error( "Couldn't find weapon %i", weaponNum );
-
- Com_sprintf( path, MAX_QPATH, "models/weapons/%s/weapon.cfg", BG_FindNameForWeapon( weaponNum ) );
-
- weaponInfo->humanName = BG_FindHumanNameForWeapon( weaponNum );
-
- if( !CG_ParseWeaponFile( path, weaponInfo ) )
- Com_Printf( S_COLOR_RED "ERROR: failed to parse %s\n", path );
-
- // calc midpoint for rotation
- trap_R_ModelBounds( weaponInfo->weaponModel, mins, maxs );
- for( i = 0 ; i < 3 ; i++ )
- weaponInfo->weaponMidpoint[ i ] = mins[ i ] + 0.5 * ( maxs[ i ] - mins[ i ] );
-
- //FIXME:
- for( i = WPM_NONE + 1; i < WPM_NUM_WEAPONMODES; i++ )
- weaponInfo->wim[ i ].loopFireSound = qfalse;
-}
-
-/*
-===============
-CG_InitWeapons
-
-Precaches weapons
-===============
-*/
-void CG_InitWeapons( void )
-{
- int i;
-
- memset( cg_weapons, 0, sizeof( cg_weapons ) );
-
- for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ )
- CG_RegisterWeapon( i );
-
- cgs.media.level2ZapTS = CG_RegisterTrailSystem( "models/weapons/lev2zap/lightning" );
-}
-
-
-/*
-========================================================================================
-
-VIEW WEAPON
-
-========================================================================================
-*/
-
-/*
-=================
-CG_MapTorsoToWeaponFrame
-
-=================
-*/
-static int CG_MapTorsoToWeaponFrame( clientInfo_t *ci, int frame )
-{
-
- // change weapon
- if( frame >= ci->animations[ TORSO_DROP ].firstFrame &&
- frame < ci->animations[ TORSO_DROP ].firstFrame + 9 )
- return frame - ci->animations[ TORSO_DROP ].firstFrame + 6;
-
- // stand attack
- if( frame >= ci->animations[ TORSO_ATTACK ].firstFrame &&
- frame < ci->animations[ TORSO_ATTACK ].firstFrame + 6 )
- return 1 + frame - ci->animations[ TORSO_ATTACK ].firstFrame;
-
- // stand attack 2
- if( frame >= ci->animations[ TORSO_ATTACK2 ].firstFrame &&
- frame < ci->animations[ TORSO_ATTACK2 ].firstFrame + 6 )
- return 1 + frame - ci->animations[ TORSO_ATTACK2 ].firstFrame;
-
- return 0;
-}
-
-
-/*
-==============
-CG_CalculateWeaponPosition
-==============
-*/
-static void CG_CalculateWeaponPosition( vec3_t origin, vec3_t angles )
-{
- float scale;
- int delta;
- float fracsin;
- float bob;
-
- VectorCopy( cg.refdef.vieworg, origin );
- VectorCopy( cg.refdefViewAngles, angles );
-
- // on odd legs, invert some angles
- if( cg.bobcycle & 1 )
- scale = -cg.xyspeed;
- else
- scale = cg.xyspeed;
-
- // gun angles from bobbing
- //TA: bob amount is class dependant
- bob = BG_FindBobForClass( cg.predictedPlayerState.stats[ STAT_PCLASS ] );
-
- if( bob != 0 )
- {
- angles[ ROLL ] += scale * cg.bobfracsin * 0.005;
- angles[ YAW ] += scale * cg.bobfracsin * 0.01;
- angles[ PITCH ] += cg.xyspeed * cg.bobfracsin * 0.005;
- }
-
- // drop the weapon when landing
- if( !BG_ClassHasAbility( cg.predictedPlayerState.stats[ STAT_PCLASS ], SCA_NOWEAPONDRIFT ) )
- {
- delta = cg.time - cg.landTime;
- if( delta < LAND_DEFLECT_TIME )
- origin[ 2 ] += cg.landChange*0.25 * delta / LAND_DEFLECT_TIME;
- else if( delta < LAND_DEFLECT_TIME + LAND_RETURN_TIME )
- origin[ 2 ] += cg.landChange*0.25 *
- ( LAND_DEFLECT_TIME + LAND_RETURN_TIME - delta ) / LAND_RETURN_TIME;
-
- // idle drift
- scale = cg.xyspeed + 40;
- fracsin = sin( cg.time * 0.001 );
- angles[ ROLL ] += scale * fracsin * 0.01;
- angles[ YAW ] += scale * fracsin * 0.01;
- angles[ PITCH ] += scale * fracsin * 0.01;
- }
-}
-
-
-/*
-======================
-CG_MachinegunSpinAngle
-======================
-*/
-#define SPIN_SPEED 0.9
-#define COAST_TIME 1000
-static float CG_MachinegunSpinAngle( centity_t *cent )
-{
- int delta;
- float angle;
- float speed;
-
- delta = cg.time - cent->pe.barrelTime;
- if( cent->pe.barrelSpinning )
- angle = cent->pe.barrelAngle + delta * SPIN_SPEED;
- else
- {
- if( delta > COAST_TIME )
- delta = COAST_TIME;
-
- speed = 0.5 * ( SPIN_SPEED + (float)( COAST_TIME - delta ) / COAST_TIME );
- angle = cent->pe.barrelAngle + delta * speed;
- }
-
- if( cent->pe.barrelSpinning == !( cent->currentState.eFlags & EF_FIRING ) )
- {
- cent->pe.barrelTime = cg.time;
- cent->pe.barrelAngle = AngleMod( angle );
- cent->pe.barrelSpinning = !!( cent->currentState.eFlags & EF_FIRING );
- //TA: um?
- }
-
- return angle;
-}
-
-
-/*
-=============
-CG_AddPlayerWeapon
-
-Used for both the view weapon (ps is valid) and the world modelother character models (ps is NULL)
-The main player will have this called for BOTH cases, so effects like light and
-sound should only be done on the world model case.
-=============
-*/
-void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent )
-{
- refEntity_t gun;
- refEntity_t barrel;
- refEntity_t flash;
- vec3_t angles;
- weapon_t weaponNum;
- weaponMode_t weaponMode;
- weaponInfo_t *weapon;
- qboolean noGunModel;
- qboolean firing;
-
- weaponNum = cent->currentState.weapon;
- weaponMode = cent->currentState.generic1;
-
- if( weaponMode <= WPM_NONE || weaponMode >= WPM_NUM_WEAPONMODES )
- weaponMode = WPM_PRIMARY;
-
- if( ( ( cent->currentState.eFlags & EF_FIRING ) && weaponMode == WPM_PRIMARY ) ||
- ( ( cent->currentState.eFlags & EF_FIRING2 ) && weaponMode == WPM_SECONDARY ) ||
- ( ( cent->currentState.eFlags & EF_FIRING3 ) && weaponMode == WPM_TERTIARY ) )
- firing = qtrue;
- else
- firing = qfalse;
-
- CG_RegisterWeapon( weaponNum );
- weapon = &cg_weapons[ weaponNum ];
-
- // add the weapon
- memset( &gun, 0, sizeof( gun ) );
- VectorCopy( parent->lightingOrigin, gun.lightingOrigin );
- gun.shadowPlane = parent->shadowPlane;
- gun.renderfx = parent->renderfx;
-
- // set custom shading for railgun refire rate
- if( ps )
- {
- gun.shaderRGBA[ 0 ] = 255;
- gun.shaderRGBA[ 1 ] = 255;
- gun.shaderRGBA[ 2 ] = 255;
- gun.shaderRGBA[ 3 ] = 255;
-
- //set weapon[1/2]Time when respective buttons change state
- if( cg.weapon1Firing != ( cg.predictedPlayerState.eFlags & EF_FIRING ) )
- {
- cg.weapon1Time = cg.time;
- cg.weapon1Firing = ( cg.predictedPlayerState.eFlags & EF_FIRING );
- }
-
- if( cg.weapon2Firing != ( cg.predictedPlayerState.eFlags & EF_FIRING2 ) )
- {
- cg.weapon2Time = cg.time;
- cg.weapon2Firing = ( cg.predictedPlayerState.eFlags & EF_FIRING2 );
- }
-
- if( cg.weapon3Firing != ( cg.predictedPlayerState.eFlags & EF_FIRING3 ) )
- {
- cg.weapon3Time = cg.time;
- cg.weapon3Firing = ( cg.predictedPlayerState.eFlags & EF_FIRING3 );
- }
- }
-
- gun.hModel = weapon->weaponModel;
-
- noGunModel = ( ( !ps || cg.renderingThirdPerson ) && weapon->disableIn3rdPerson ) || !gun.hModel;
-
- if( !ps )
- {
- // add weapon ready sound
- if( firing && weapon->wim[ weaponMode ].firingSound )
- {
- trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin,
- weapon->wim[ weaponMode ].firingSound );
- }
- else if( weapon->readySound )
- trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, weapon->readySound );
- }
-
- if( !noGunModel )
- {
- CG_PositionEntityOnTag( &gun, parent, parent->hModel, "tag_weapon" );
-
- trap_R_AddRefEntityToScene( &gun );
-
- // add the spinning barrel
- if( weapon->barrelModel )
- {
- memset( &barrel, 0, sizeof( barrel ) );
- VectorCopy( parent->lightingOrigin, barrel.lightingOrigin );
- barrel.shadowPlane = parent->shadowPlane;
- barrel.renderfx = parent->renderfx;
-
- barrel.hModel = weapon->barrelModel;
- angles[ YAW ] = 0;
- angles[ PITCH ] = 0;
- angles[ ROLL ] = CG_MachinegunSpinAngle( cent );
- AnglesToAxis( angles, barrel.axis );
-
- CG_PositionRotatedEntityOnTag( &barrel, &gun, weapon->weaponModel, "tag_barrel" );
-
- trap_R_AddRefEntityToScene( &barrel );
- }
- }
-
- if( CG_IsParticleSystemValid( &cent->muzzlePS ) )
- {
- if( ps || cg.renderingThirdPerson ||
- cent->currentState.number != cg.predictedPlayerState.clientNum )
- {
- if( noGunModel )
- CG_SetAttachmentTag( &cent->muzzlePS->attachment, *parent, parent->hModel, "tag_weapon" );
- else
- CG_SetAttachmentTag( &cent->muzzlePS->attachment, gun, weapon->weaponModel, "tag_flash" );
- }
-
- //if the PS is infinite disable it when not firing
- if( !firing && CG_IsParticleSystemInfinite( cent->muzzlePS ) )
- CG_DestroyParticleSystem( &cent->muzzlePS );
- }
-
- // add the flash
- if( !weapon->wim[ weaponMode ].continuousFlash || !firing )
- {
- // impulse flash
- if( cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME )
- return;
- }
-
- memset( &flash, 0, sizeof( flash ) );
- VectorCopy( parent->lightingOrigin, flash.lightingOrigin );
- flash.shadowPlane = parent->shadowPlane;
- flash.renderfx = parent->renderfx;
-
- flash.hModel = weapon->flashModel;
- if( flash.hModel )
- {
- angles[ YAW ] = 0;
- angles[ PITCH ] = 0;
- angles[ ROLL ] = crandom( ) * 10;
- AnglesToAxis( angles, flash.axis );
-
- if( noGunModel )
- CG_PositionRotatedEntityOnTag( &flash, parent, parent->hModel, "tag_weapon" );
- else
- CG_PositionRotatedEntityOnTag( &flash, &gun, weapon->weaponModel, "tag_flash" );
-
- trap_R_AddRefEntityToScene( &flash );
- }
-
- if( ps || cg.renderingThirdPerson ||
- cent->currentState.number != cg.predictedPlayerState.clientNum )
- {
- if( weapon->wim[ weaponMode ].muzzleParticleSystem && cent->muzzlePsTrigger )
- {
- cent->muzzlePS = CG_SpawnNewParticleSystem( weapon->wim[ weaponMode ].muzzleParticleSystem );
-
- if( CG_IsParticleSystemValid( &cent->muzzlePS ) )
- {
- if( noGunModel )
- CG_SetAttachmentTag( &cent->muzzlePS->attachment, *parent, parent->hModel, "tag_weapon" );
- else
- CG_SetAttachmentTag( &cent->muzzlePS->attachment, gun, weapon->weaponModel, "tag_flash" );
-
- CG_SetAttachmentCent( &cent->muzzlePS->attachment, cent );
- CG_AttachToTag( &cent->muzzlePS->attachment );
- }
-
- cent->muzzlePsTrigger = qfalse;
- }
-
- // make a dlight for the flash
- if( weapon->wim[ weaponMode ].flashDlightColor[ 0 ] ||
- weapon->wim[ weaponMode ].flashDlightColor[ 1 ] ||
- weapon->wim[ weaponMode ].flashDlightColor[ 2 ] )
- {
- trap_R_AddLightToScene( flash.origin, 300 + ( rand( ) & 31 ),
- weapon->wim[ weaponMode ].flashDlightColor[ 0 ],
- weapon->wim[ weaponMode ].flashDlightColor[ 1 ],
- weapon->wim[ weaponMode ].flashDlightColor[ 2 ] );
- }
- }
-}
-
-/*
-==============
-CG_AddViewWeapon
-
-Add the weapon, and flash for the player's view
-==============
-*/
-void CG_AddViewWeapon( playerState_t *ps )
-{
- refEntity_t hand;
- centity_t *cent;
- clientInfo_t *ci;
- float fovOffset;
- vec3_t angles;
- weaponInfo_t *wi;
- weapon_t weapon = ps->weapon;
- weaponMode_t weaponMode = ps->generic1;
-
- if( weaponMode <= WPM_NONE || weaponMode >= WPM_NUM_WEAPONMODES )
- weaponMode = WPM_PRIMARY;
-
- CG_RegisterWeapon( weapon );
- wi = &cg_weapons[ weapon ];
- cent = &cg.predictedPlayerEntity; // &cg_entities[cg.snap->ps.clientNum];
-
- if( ( ps->persistant[PERS_TEAM] == TEAM_SPECTATOR ) ||
- ( ps->stats[ STAT_STATE ] & SS_INFESTING ) ||
- ( ps->stats[ STAT_STATE ] & SS_HOVELING ) )
- return;
-
- //TA: no weapon carried - can't draw it
- if( weapon == WP_NONE )
- return;
-
- if( ps->pm_type == PM_INTERMISSION )
- return;
-
- //TA: draw a prospective buildable infront of the player
- if( ( ps->stats[ STAT_BUILDABLE ] & ~SB_VALID_TOGGLEBIT ) > BA_NONE )
- CG_GhostBuildable( ps->stats[ STAT_BUILDABLE ] & ~SB_VALID_TOGGLEBIT );
-
- if( weapon == WP_LUCIFER_CANNON && ps->stats[ STAT_MISC ] > 0 )
- {
- if( ps->stats[ STAT_MISC ] > ( LCANNON_TOTAL_CHARGE - ( LCANNON_TOTAL_CHARGE / 3 ) ) )
- trap_S_AddLoopingSound( ps->clientNum, ps->origin, vec3_origin, cgs.media.lCannonWarningSound );
- }
-
- // no gun if in third person view
- if( cg.renderingThirdPerson )
- return;
-
- // allow the gun to be completely removed
- if( !cg_drawGun.integer )
- {
- vec3_t origin;
-
- VectorCopy( cg.refdef.vieworg, origin );
- VectorMA( origin, -8, cg.refdef.viewaxis[ 2 ], origin );
-
- if( cent->muzzlePS )
- CG_SetAttachmentPoint( &cent->muzzlePS->attachment, origin );
-
- //check for particle systems
- if( wi->wim[ weaponMode ].muzzleParticleSystem && cent->muzzlePsTrigger )
- {
- cent->muzzlePS = CG_SpawnNewParticleSystem( wi->wim[ weaponMode ].muzzleParticleSystem );
-
- if( CG_IsParticleSystemValid( &cent->muzzlePS ) )
- {
- CG_SetAttachmentPoint( &cent->muzzlePS->attachment, origin );
- CG_SetAttachmentCent( &cent->muzzlePS->attachment, cent );
- CG_AttachToPoint( &cent->muzzlePS->attachment );
- }
- cent->muzzlePsTrigger = qfalse;
- }
-
- return;
- }
-
- // don't draw if testing a gun model
- if( cg.testGun )
- return;
-
- // drop gun lower at higher fov
- //if ( cg_fov.integer > 90 ) {
- //TA: the client side variable isn't used ( shouldn't iD have done this anyway? )
- if( cg.refdef.fov_y > 90 )
- fovOffset = -0.4 * ( cg.refdef.fov_y - 90 );
- else
- fovOffset = 0;
-
- memset( &hand, 0, sizeof( hand ) );
-
- // set up gun position
- CG_CalculateWeaponPosition( hand.origin, angles );
-
- VectorMA( hand.origin, cg_gun_x.value, cg.refdef.viewaxis[ 0 ], hand.origin );
- VectorMA( hand.origin, cg_gun_y.value, cg.refdef.viewaxis[ 1 ], hand.origin );
- VectorMA( hand.origin, ( cg_gun_z.value + fovOffset ), cg.refdef.viewaxis[ 2 ], hand.origin );
-
- if( weapon == WP_LUCIFER_CANNON && ps->stats[ STAT_MISC ] > 0 )
- {
- float fraction = (float)ps->stats[ STAT_MISC ] / (float)LCANNON_TOTAL_CHARGE;
-
- VectorMA( hand.origin, random( ) * fraction, cg.refdef.viewaxis[ 0 ], hand.origin );
- VectorMA( hand.origin, random( ) * fraction, cg.refdef.viewaxis[ 1 ], hand.origin );
- }
-
- AnglesToAxis( angles, hand.axis );
-
- // map torso animations to weapon animations
- if( cg_gun_frame.integer )
- {
- // development tool
- hand.frame = hand.oldframe = cg_gun_frame.integer;
- hand.backlerp = 0;
- }
- else
- {
- // get clientinfo for animation map
- ci = &cgs.clientinfo[ cent->currentState.clientNum ];
- hand.frame = CG_MapTorsoToWeaponFrame( ci, cent->pe.torso.frame );
- hand.oldframe = CG_MapTorsoToWeaponFrame( ci, cent->pe.torso.oldFrame );
- hand.backlerp = cent->pe.torso.backlerp;
- }
-
- hand.hModel = wi->handsModel;
- hand.renderfx = RF_DEPTHHACK | RF_FIRST_PERSON | RF_MINLIGHT;
-
- // add everything onto the hand
- CG_AddPlayerWeapon( &hand, ps, &cg.predictedPlayerEntity );
-}
-
-/*
-==============================================================================
-
-WEAPON SELECTION
-
-==============================================================================
-*/
-
-/*
-===============
-CG_WeaponSelectable
-===============
-*/
-static qboolean CG_WeaponSelectable( weapon_t weapon )
-{
- //int ammo, clips;
- //
- //BG_UnpackAmmoArray( i, cg.snap->ps.ammo, cg.snap->ps.powerups, &ammo, &clips );
- //
- //TA: this is a pain in the ass
- //if( !ammo && !clips && !BG_FindInfinteAmmoForWeapon( i ) )
- // return qfalse;
-
- if( !BG_InventoryContainsWeapon( weapon, cg.snap->ps.stats ) )
- return qfalse;
-
- return qtrue;
-}
-
-
-/*
-===============
-CG_UpgradeSelectable
-===============
-*/
-static qboolean CG_UpgradeSelectable( upgrade_t upgrade )
-{
- if( !BG_InventoryContainsUpgrade( upgrade, cg.snap->ps.stats ) )
- return qfalse;
-
- return qtrue;
-}
-
-
-#define ICON_BORDER 4
-
-/*
-===================
-CG_DrawItemSelect
-===================
-*/
-void CG_DrawItemSelect( rectDef_t *rect, vec4_t color )
-{
- int i;
- int x = rect->x;
- int y = rect->y;
- int width = rect->w;
- int height = rect->h;
- int iconsize;
- int items[ 64 ];
- int numItems = 0, selectedItem = 0;
- int length;
- int selectWindow;
- qboolean vertical;
- centity_t *cent;
- playerState_t *ps;
-
- cent = &cg_entities[ cg.snap->ps.clientNum ];
- ps = &cg.snap->ps;
-
- // don't display if dead
- if( cg.predictedPlayerState.stats[ STAT_HEALTH ] <= 0 )
- return;
-
- if( !( cg.snap->ps.pm_flags & PMF_FOLLOW ) )
- {
- // first make sure that whatever it selected is actually selectable
- if( cg.weaponSelect <= 32 && !CG_WeaponSelectable( cg.weaponSelect ) )
- CG_NextWeapon_f( );
- else if( cg.weaponSelect > 32 && !CG_UpgradeSelectable( cg.weaponSelect ) )
- CG_NextWeapon_f( );
- }
-
- // showing weapon select clears pickup item display, but not the blend blob
- cg.itemPickupTime = 0;
-
- if( height > width )
- {
- vertical = qtrue;
- iconsize = width;
- length = height / width;
- }
- else if( height <= width )
- {
- vertical = qfalse;
- iconsize = height;
- length = width / height;
- }
-
- selectWindow = length / 2;
-
- for( i = WP_NONE + 1; i < WP_NUM_WEAPONS; i++ )
- {
- if( !BG_InventoryContainsWeapon( i, cg.snap->ps.stats ) )
- continue;
-
- if( i == cg.weaponSelect )
- selectedItem = numItems;
-
- CG_RegisterWeapon( i );
- items[ numItems ] = i;
- numItems++;
- }
-
- for( i = UP_NONE + 1; i < UP_NUM_UPGRADES; i++ )
- {
- if( !BG_InventoryContainsUpgrade( i, cg.snap->ps.stats ) )
- continue;
-
- if( i == cg.weaponSelect - 32 )
- selectedItem = numItems;
-
- CG_RegisterUpgrade( i );
- items[ numItems ] = i + 32;
- numItems++;
- }
-
- for( i = 0; i < length; i++ )
- {
- int displacement = i - selectWindow;
- int item = displacement + selectedItem;
-
- if( ( item >= 0 ) && ( item < numItems ) )
- {
- trap_R_SetColor( color );
-
- if( items[ item ] <= 32 )
- CG_DrawPic( x, y, iconsize, iconsize, cg_weapons[ items[ item ] ].weaponIcon );
- else if( items[ item ] > 32 )
- CG_DrawPic( x, y, iconsize, iconsize, cg_upgrades[ items[ item ] - 32 ].upgradeIcon );
-
- trap_R_SetColor( NULL );
-
-/* if( displacement == 0 )
- CG_DrawPic( x, y, iconsize, iconsize, cgs.media.selectShader );*/
- }
-
- if( vertical )
- y += iconsize;
- else
- x += iconsize;
- }
-}
-
-
-/*
-===================
-CG_DrawItemSelectText
-===================
-*/
-void CG_DrawItemSelectText( rectDef_t *rect, float scale, int textStyle )
-{
- int x, w;
- char *name;
- float *color;
-
- color = CG_FadeColor( cg.weaponSelectTime, WEAPON_SELECT_TIME );
- if( !color )
- return;
-
- trap_R_SetColor( color );
-
- // draw the selected name
- if( cg.weaponSelect <= 32 )
- {
- if( cg_weapons[ cg.weaponSelect ].registered &&
- BG_InventoryContainsWeapon( cg.weaponSelect, cg.snap->ps.stats ) )
- {
- if( ( name = cg_weapons[ cg.weaponSelect ].humanName ) )
- {
- w = CG_Text_Width( name, scale, 0 );
- x = rect->x + rect->w / 2;
- CG_Text_Paint( x - w / 2, rect->y + rect->h, scale, color, name, 0, 0, textStyle );
- }
- }
- }
- else if( cg.weaponSelect > 32 )
- {
- if( cg_upgrades[ cg.weaponSelect - 32 ].registered &&
- BG_InventoryContainsUpgrade( cg.weaponSelect - 32, cg.snap->ps.stats ) )
- {
- if( ( name = cg_upgrades[ cg.weaponSelect - 32 ].humanName ) )
- {
- w = CG_Text_Width( name, scale, 0 );
- x = rect->x + rect->w / 2;
- CG_Text_Paint( x - w / 2, rect->y + rect->h, scale, color, name, 0, 0, textStyle );
- }
- }
- }
-
- trap_R_SetColor( NULL );
-}
-
-
-/*
-===============
-CG_NextWeapon_f
-===============
-*/
-void CG_NextWeapon_f( void )
-{
- int i;
- int original;
-
- if( !cg.snap )
- return;
-
- if( cg.snap->ps.pm_flags & PMF_FOLLOW )
- {
- trap_SendClientCommand( "followprev\n" );
- return;
- }
-
- cg.weaponSelectTime = cg.time;
- original = cg.weaponSelect;
-
- for( i = 0; i < 64; i++ )
- {
- cg.weaponSelect++;
- if( cg.weaponSelect == 64 )
- cg.weaponSelect = 0;
-
- if( cg.weaponSelect <= 32 )
- {
- if( CG_WeaponSelectable( cg.weaponSelect ) )
- break;
- }
- else if( cg.weaponSelect > 32 )
- {
- if( CG_UpgradeSelectable( cg.weaponSelect - 32 ) )
- break;
- }
- }
-
- if( i == 64 )
- cg.weaponSelect = original;
-}
-
-/*
-===============
-CG_PrevWeapon_f
-===============
-*/
-void CG_PrevWeapon_f( void )
-{
- int i;
- int original;
-
- if( !cg.snap )
- return;
-
- if( cg.snap->ps.pm_flags & PMF_FOLLOW )
- {
- trap_SendClientCommand( "follownext\n" );
- return;
- }
-
- cg.weaponSelectTime = cg.time;
- original = cg.weaponSelect;
-
- for( i = 0; i < 64; i++ )
- {
- cg.weaponSelect--;
- if( cg.weaponSelect == -1 )
- cg.weaponSelect = 63;
-
- if( cg.weaponSelect <= 32 )
- {
- if( CG_WeaponSelectable( cg.weaponSelect ) )
- break;
- }
- else if( cg.weaponSelect > 32 )
- {
- if( CG_UpgradeSelectable( cg.weaponSelect - 32 ) )
- break;
- }
- }
-
- if( i == 64 )
- cg.weaponSelect = original;
-}
-
-/*
-===============
-CG_Weapon_f
-===============
-*/
-void CG_Weapon_f( void )
-{
- int num;
-
- if( !cg.snap )
- return;
-
- if( cg.snap->ps.pm_flags & PMF_FOLLOW )
- return;
-
- num = atoi( CG_Argv( 1 ) );
-
- if( num < 1 || num > 31 )
- return;
-
- cg.weaponSelectTime = cg.time;
-
- if( !BG_InventoryContainsWeapon( num, cg.snap->ps.stats ) )
- return; // don't have the weapon
-
- cg.weaponSelect = num;
-}
-
-
-/*
-===================================================================================================
-
-WEAPON EVENTS
-
-===================================================================================================
-*/
-
-/*
-================
-CG_FireWeapon
-
-Caused by an EV_FIRE_WEAPON event
-================
-*/
-void CG_FireWeapon( centity_t *cent, weaponMode_t weaponMode )
-{
- entityState_t *es;
- int c;
- weaponInfo_t *wi;
- weapon_t weaponNum;
-
- es = &cent->currentState;
-
- weaponNum = es->weapon;
-
- if( weaponNum == WP_NONE )
- return;
-
- if( weaponMode <= WPM_NONE || weaponMode >= WPM_NUM_WEAPONMODES )
- weaponMode = WPM_PRIMARY;
-
- if( weaponNum >= WP_NUM_WEAPONS )
- {
- CG_Error( "CG_FireWeapon: ent->weapon >= WP_NUM_WEAPONS" );
- return;
- }
-
- wi = &cg_weapons[ weaponNum ];
-
- // mark the entity as muzzle flashing, so when it is added it will
- // append the flash to the weapon model
- cent->muzzleFlashTime = cg.time;
-
- if( wi->wim[ weaponMode ].muzzleParticleSystem )
- {
- if( !CG_IsParticleSystemValid( &cent->muzzlePS ) ||
- !CG_IsParticleSystemInfinite( cent->muzzlePS ) )
- cent->muzzlePsTrigger = qtrue;
- }
-
- // play a sound
- for( c = 0; c < 4; c++ )
- {
- if( !wi->wim[ weaponMode ].flashSound[ c ] )
- break;
- }
-
- if( c > 0 )
- {
- c = rand( ) % c;
- if( wi->wim[ weaponMode ].flashSound[ c ] )
- trap_S_StartSound( NULL, es->number, CHAN_WEAPON, wi->wim[ weaponMode ].flashSound[ c ] );
- }
-}
-
-
-/*
-=================
-CG_MissileHitWall
-
-Caused by an EV_MISSILE_MISS event, or directly by local bullet tracing
-=================
-*/
-void CG_MissileHitWall( weapon_t weaponNum, weaponMode_t weaponMode, int clientNum,
- vec3_t origin, vec3_t dir, impactSound_t soundType )
-{
- qhandle_t mark = 0;
- qhandle_t ps = 0;
- int c;
- float radius = 1.0f;
- weaponInfo_t *weapon = &cg_weapons[ weaponNum ];
-
- if( weaponMode <= WPM_NONE || weaponMode >= WPM_NUM_WEAPONMODES )
- weaponMode = WPM_PRIMARY;
-
- mark = weapon->wim[ weaponMode ].impactMark;
- radius = weapon->wim[ weaponMode ].impactMarkSize;
- ps = weapon->wim[ weaponMode ].impactParticleSystem;
-
- if( soundType == IMPACTSOUND_FLESH )
- {
- //flesh sound
- for( c = 0; c < 4; c++ )
- {
- if( !weapon->wim[ weaponMode ].impactFleshSound[ c ] )
- break;
- }
-
- if( c > 0 )
- {
- c = rand( ) % c;
- if( weapon->wim[ weaponMode ].impactFleshSound[ c ] )
- trap_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, weapon->wim[ weaponMode ].impactFleshSound[ c ] );
- }
- }
- else
- {
- //normal sound
- for( c = 0; c < 4; c++ )
- {
- if( !weapon->wim[ weaponMode ].impactSound[ c ] )
- break;
- }
-
- if( c > 0 )
- {
- c = rand( ) % c;
- if( weapon->wim[ weaponMode ].impactSound[ c ] )
- trap_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, weapon->wim[ weaponMode ].impactSound[ c ] );
- }
- }
-
- //create impact particle system
- if( ps )
- {
- particleSystem_t *partSystem = CG_SpawnNewParticleSystem( ps );
-
- if( CG_IsParticleSystemValid( &partSystem ) )
- {
- CG_SetAttachmentPoint( &partSystem->attachment, origin );
- CG_SetParticleSystemNormal( partSystem, dir );
- CG_AttachToPoint( &partSystem->attachment );
- }
- }
-
- //
- // impact mark
- //
- if( radius > 0.0f )
- CG_ImpactMark( mark, origin, dir, random( ) * 360, 1, 1, 1, 1, qfalse, radius, qfalse );
-}
-
-
-/*
-=================
-CG_MissileHitPlayer
-=================
-*/
-void CG_MissileHitPlayer( weapon_t weaponNum, weaponMode_t weaponMode,
- vec3_t origin, vec3_t dir, int entityNum )
-{
- vec3_t normal;
- weaponInfo_t *weapon = &cg_weapons[ weaponNum ];
-
- VectorCopy( dir, normal );
- VectorInverse( normal );
-
- CG_Bleed( origin, normal, entityNum );
-
- if( weaponMode <= WPM_NONE || weaponMode >= WPM_NUM_WEAPONMODES )
- weaponMode = WPM_PRIMARY;
-
- if( weapon->wim[ weaponMode ].alwaysImpact )
- CG_MissileHitWall( weaponNum, weaponMode, 0, origin, dir, IMPACTSOUND_FLESH );
-}
-
-
-/*
-============================================================================
-
-BULLETS
-
-============================================================================
-*/
-
-
-/*
-===============
-CG_Tracer
-===============
-*/
-void CG_Tracer( vec3_t source, vec3_t dest )
-{
- vec3_t forward, right;
- polyVert_t verts[ 4 ];
- vec3_t line;
- float len, begin, end;
- vec3_t start, finish;
- vec3_t midpoint;
-
- // tracer
- VectorSubtract( dest, source, forward );
- len = VectorNormalize( forward );
-
- // start at least a little ways from the muzzle
- if( len < 100 )
- return;
-
- begin = 50 + random( ) * ( len - 60 );
- end = begin + cg_tracerLength.value;
- if( end > len )
- end = len;
-
- VectorMA( source, begin, forward, start );
- VectorMA( source, end, forward, finish );
-
- line[ 0 ] = DotProduct( forward, cg.refdef.viewaxis[ 1 ] );
- line[ 1 ] = DotProduct( forward, cg.refdef.viewaxis[ 2 ] );
-
- VectorScale( cg.refdef.viewaxis[ 1 ], line[ 1 ], right );
- VectorMA( right, -line[ 0 ], cg.refdef.viewaxis[ 2 ], right );
- VectorNormalize( right );
-
- VectorMA( finish, cg_tracerWidth.value, right, verts[ 0 ].xyz );
- verts[ 0 ].st[ 0 ] = 0;
- verts[ 0 ].st[ 1 ] = 1;
- verts[ 0 ].modulate[ 0 ] = 255;
- verts[ 0 ].modulate[ 1 ] = 255;
- verts[ 0 ].modulate[ 2 ] = 255;
- verts[ 0 ].modulate[ 3 ] = 255;
-
- VectorMA( finish, -cg_tracerWidth.value, right, verts[ 1 ].xyz );
- verts[ 1 ].st[ 0 ] = 1;
- verts[ 1 ].st[ 1 ] = 0;
- verts[ 1 ].modulate[ 0 ] = 255;
- verts[ 1 ].modulate[ 1 ] = 255;
- verts[ 1 ].modulate[ 2 ] = 255;
- verts[ 1 ].modulate[ 3 ] = 255;
-
- VectorMA( start, -cg_tracerWidth.value, right, verts[ 2 ].xyz );
- verts[ 2 ].st[ 0 ] = 1;
- verts[ 2 ].st[ 1 ] = 1;
- verts[ 2 ].modulate[ 0 ] = 255;
- verts[ 2 ].modulate[ 1 ] = 255;
- verts[ 2 ].modulate[ 2 ] = 255;
- verts[ 2 ].modulate[ 3 ] = 255;
-
- VectorMA( start, cg_tracerWidth.value, right, verts[ 3 ].xyz );
- verts[ 3 ].st[ 0 ] = 0;
- verts[ 3 ].st[ 1 ] = 0;
- verts[ 3 ].modulate[ 0 ] = 255;
- verts[ 3 ].modulate[ 1 ] = 255;
- verts[ 3 ].modulate[ 2 ] = 255;
- verts[ 3 ].modulate[ 3 ] = 255;
-
- trap_R_AddPolyToScene( cgs.media.tracerShader, 4, verts );
-
- midpoint[ 0 ] = ( start[ 0 ] + finish[ 0 ] ) * 0.5;
- midpoint[ 1 ] = ( start[ 1 ] + finish[ 1 ] ) * 0.5;
- midpoint[ 2 ] = ( start[ 2 ] + finish[ 2 ] ) * 0.5;
-
- // add the tracer sound
- trap_S_StartSound( midpoint, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.tracerSound );
-}
-
-
-/*
-======================
-CG_CalcMuzzlePoint
-======================
-*/
-static qboolean CG_CalcMuzzlePoint( int entityNum, vec3_t muzzle )
-{
- vec3_t forward;
- centity_t *cent;
- int anim;
-
- if( entityNum == cg.snap->ps.clientNum )
- {
- VectorCopy( cg.snap->ps.origin, muzzle );
- muzzle[ 2 ] += cg.snap->ps.viewheight;
- AngleVectors( cg.snap->ps.viewangles, forward, NULL, NULL );
- VectorMA( muzzle, 14, forward, muzzle );
- return qtrue;
- }
-
- cent = &cg_entities[entityNum];
-
- if( !cent->currentValid )
- return qfalse;
-
- VectorCopy( cent->currentState.pos.trBase, muzzle );
-
- AngleVectors( cent->currentState.apos.trBase, forward, NULL, NULL );
- anim = cent->currentState.legsAnim & ~ANIM_TOGGLEBIT;
-
- if( anim == LEGS_WALKCR || anim == LEGS_IDLECR )
- muzzle[ 2 ] += CROUCH_VIEWHEIGHT;
- else
- muzzle[ 2 ] += DEFAULT_VIEWHEIGHT;
-
- VectorMA( muzzle, 14, forward, muzzle );
-
- return qtrue;
-
-}
-
-
-/*
-======================
-CG_Bullet
-
-Renders bullet effects.
-======================
-*/
-void CG_Bullet( vec3_t end, int sourceEntityNum, vec3_t normal, qboolean flesh, int fleshEntityNum )
-{
- vec3_t start;
-
- // if the shooter is currently valid, calc a source point and possibly
- // do trail effects
- if( sourceEntityNum >= 0 && cg_tracerChance.value > 0 )
- {
- if( CG_CalcMuzzlePoint( sourceEntityNum, start ) )
- {
- // draw a tracer
- if( random( ) < cg_tracerChance.value )
- CG_Tracer( start, end );
- }
- }
-
- // impact splash and mark
- if( flesh )
- CG_Bleed( end, normal, fleshEntityNum );
- else
- CG_MissileHitWall( WP_MACHINEGUN, WPM_PRIMARY, 0, end, normal, IMPACTSOUND_DEFAULT );
-}
-
-/*
-============================================================================
-
-SHOTGUN TRACING
-
-============================================================================
-*/
-
-/*
-================
-CG_ShotgunPattern
-
-Perform the same traces the server did to locate the
-hit splashes
-================
-*/
-static void CG_ShotgunPattern( vec3_t origin, vec3_t origin2, int seed, int otherEntNum )
-{
- int i;
- float r, u;
- vec3_t end;
- vec3_t forward, right, up;
- trace_t tr;
-
- // derive the right and up vectors from the forward vector, because
- // the client won't have any other information
- VectorNormalize2( origin2, forward );
- PerpendicularVector( right, forward );
- CrossProduct( forward, right, up );
-
- // generate the "random" spread pattern
- for( i = 0; i < SHOTGUN_PELLETS; i++ )
- {
- r = Q_crandom( &seed ) * SHOTGUN_SPREAD * 16;
- u = Q_crandom( &seed ) * SHOTGUN_SPREAD * 16;
- VectorMA( origin, 8192 * 16, forward, end );
- VectorMA( end, r, right, end );
- VectorMA( end, u, up, end );
-
- CG_Trace( &tr, origin, NULL, NULL, end, otherEntNum, MASK_SHOT );
-
- if( !( tr.surfaceFlags & SURF_NOIMPACT ) )
- {
- if( cg_entities[ tr.entityNum ].currentState.eType == ET_PLAYER )
- CG_MissileHitPlayer( WP_SHOTGUN, WPM_PRIMARY, tr.endpos, tr.plane.normal, tr.entityNum );
- else if( tr.surfaceFlags & SURF_METALSTEPS )
- CG_MissileHitWall( WP_SHOTGUN, WPM_PRIMARY, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_METAL );
- else
- CG_MissileHitWall( WP_SHOTGUN, WPM_PRIMARY, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_DEFAULT );
- }
- }
-}
-
-/*
-==============
-CG_ShotgunFire
-==============
-*/
-void CG_ShotgunFire( entityState_t *es )
-{
- vec3_t v;
-
- VectorSubtract( es->origin2, es->pos.trBase, v );
- VectorNormalize( v );
- VectorScale( v, 32, v );
- VectorAdd( es->pos.trBase, v, v );
-
- CG_ShotgunPattern( es->pos.trBase, es->origin2, es->eventParm, es->otherEntityNum );
-}
-