summaryrefslogtreecommitdiff
path: root/src/cgame/cg_weapons.c
diff options
context:
space:
mode:
authorTim Angus <tim@ngus.net>2001-01-03 21:54:12 +0000
committerTim Angus <tim@ngus.net>2001-01-03 21:54:12 +0000
commit76a5aa612381ba1ba7567ca408197c235f5869e5 (patch)
treeda7b8bc475dd18e48f87138a218c276aa9f599a7 /src/cgame/cg_weapons.c
parent6d22a7d4231f0cf301a576a072f142a01d830216 (diff)
im making a right mess of this
Diffstat (limited to 'src/cgame/cg_weapons.c')
-rw-r--r--src/cgame/cg_weapons.c1994
1 files changed, 0 insertions, 1994 deletions
diff --git a/src/cgame/cg_weapons.c b/src/cgame/cg_weapons.c
deleted file mode 100644
index a5535586..00000000
--- a/src/cgame/cg_weapons.c
+++ /dev/null
@@ -1,1994 +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 GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
- *
- * 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. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-/* To assertain which portions are licensed under the GPL and which are
- * licensed by Id Software, Inc. please run a diff between the equivalent
- * versions of the "Tremulous" modification and the unmodified "Quake3"
- * game source code.
- */
-
-#include "cg_local.h"
-
-/*
-==========================
-CG_MachineGunEjectBrass
-==========================
-*/
-static void CG_MachineGunEjectBrass( centity_t *cent ) {
- localEntity_t *le;
- refEntity_t *re;
- vec3_t velocity, xvelocity;
- vec3_t offset, xoffset;
- float waterScale = 1.0f;
- vec3_t v[3];
-
- if ( cg_brassTime.integer <= 0 ) {
- return;
- }
-
- le = CG_AllocLocalEntity();
- re = &le->refEntity;
-
- velocity[0] = 0;
- velocity[1] = -50 + 40 * crandom();
- velocity[2] = 100 + 50 * crandom();
-
- le->leType = LE_FRAGMENT;
- le->startTime = cg.time;
- le->endTime = le->startTime + cg_brassTime.integer + ( cg_brassTime.integer / 4 ) * random();
-
- le->pos.trType = TR_GRAVITY;
- le->pos.trTime = cg.time - (rand()&15);
-
- AnglesToAxis( cent->lerpAngles, v );
-
- offset[0] = 8;
- offset[1] = -4;
- offset[2] = 24;
-
- xoffset[0] = offset[0] * v[0][0] + offset[1] * v[1][0] + offset[2] * v[2][0];
- xoffset[1] = offset[0] * v[0][1] + offset[1] * v[1][1] + offset[2] * v[2][1];
- xoffset[2] = offset[0] * v[0][2] + offset[1] * v[1][2] + offset[2] * v[2][2];
- VectorAdd( cent->lerpOrigin, xoffset, re->origin );
-
- VectorCopy( re->origin, le->pos.trBase );
-
- if ( CG_PointContents( re->origin, -1 ) & CONTENTS_WATER ) {
- waterScale = 0.10f;
- }
-
- xvelocity[0] = velocity[0] * v[0][0] + velocity[1] * v[1][0] + velocity[2] * v[2][0];
- xvelocity[1] = velocity[0] * v[0][1] + velocity[1] * v[1][1] + velocity[2] * v[2][1];
- xvelocity[2] = velocity[0] * v[0][2] + velocity[1] * v[1][2] + velocity[2] * v[2][2];
- VectorScale( xvelocity, waterScale, le->pos.trDelta );
-
- AxisCopy( axisDefault, re->axis );
- re->hModel = cgs.media.machinegunBrassModel;
-
- le->bounceFactor = 0.4 * waterScale;
-
- le->angles.trType = TR_LINEAR;
- le->angles.trTime = cg.time;
- le->angles.trBase[0] = rand()&31;
- le->angles.trBase[1] = rand()&31;
- le->angles.trBase[2] = rand()&31;
- le->angles.trDelta[0] = 2;
- le->angles.trDelta[1] = 1;
- le->angles.trDelta[2] = 0;
-
- le->leFlags = LEF_TUMBLE;
- le->leBounceSoundType = LEBS_BRASS;
- le->leMarkType = LEMT_NONE;
-}
-
-/*
-==========================
-CG_ShotgunEjectBrass
-==========================
-*/
-static void CG_ShotgunEjectBrass( centity_t *cent ) {
- localEntity_t *le;
- refEntity_t *re;
- vec3_t velocity, xvelocity;
- vec3_t offset, xoffset;
- vec3_t v[3];
- int i;
-
- if ( cg_brassTime.integer <= 0 ) {
- return;
- }
-
- for ( i = 0; i < 2; i++ ) {
- float waterScale = 1.0f;
-
- le = CG_AllocLocalEntity();
- re = &le->refEntity;
-
- velocity[0] = 60 + 60 * crandom();
- if ( i == 0 ) {
- velocity[1] = 40 + 10 * crandom();
- } else {
- velocity[1] = -40 + 10 * crandom();
- }
- velocity[2] = 100 + 50 * crandom();
-
- le->leType = LE_FRAGMENT;
- le->startTime = cg.time;
- le->endTime = le->startTime + cg_brassTime.integer*3 + cg_brassTime.integer * random();
-
- le->pos.trType = TR_GRAVITY;
- le->pos.trTime = cg.time;
-
- AnglesToAxis( cent->lerpAngles, v );
-
- offset[0] = 8;
- offset[1] = 0;
- offset[2] = 24;
-
- xoffset[0] = offset[0] * v[0][0] + offset[1] * v[1][0] + offset[2] * v[2][0];
- xoffset[1] = offset[0] * v[0][1] + offset[1] * v[1][1] + offset[2] * v[2][1];
- xoffset[2] = offset[0] * v[0][2] + offset[1] * v[1][2] + offset[2] * v[2][2];
- VectorAdd( cent->lerpOrigin, xoffset, re->origin );
- VectorCopy( re->origin, le->pos.trBase );
- if ( CG_PointContents( re->origin, -1 ) & CONTENTS_WATER ) {
- waterScale = 0.10f;
- }
-
- xvelocity[0] = velocity[0] * v[0][0] + velocity[1] * v[1][0] + velocity[2] * v[2][0];
- xvelocity[1] = velocity[0] * v[0][1] + velocity[1] * v[1][1] + velocity[2] * v[2][1];
- xvelocity[2] = velocity[0] * v[0][2] + velocity[1] * v[1][2] + velocity[2] * v[2][2];
- VectorScale( xvelocity, waterScale, le->pos.trDelta );
-
- AxisCopy( axisDefault, re->axis );
- re->hModel = cgs.media.shotgunBrassModel;
- le->bounceFactor = 0.3f;
-
- le->angles.trType = TR_LINEAR;
- le->angles.trTime = cg.time;
- le->angles.trBase[0] = rand()&31;
- le->angles.trBase[1] = rand()&31;
- le->angles.trBase[2] = rand()&31;
- le->angles.trDelta[0] = 1;
- le->angles.trDelta[1] = 0.5;
- le->angles.trDelta[2] = 0;
-
- le->leFlags = LEF_TUMBLE;
- le->leBounceSoundType = LEBS_BRASS;
- le->leMarkType = LEMT_NONE;
- }
-}
-
-
-/*
-==========================
-CG_RailTrail
-==========================
-*/
-void CG_RailTrail( clientInfo_t *ci, vec3_t start, vec3_t end ) {
- localEntity_t *le;
- refEntity_t *re;
-
- //
- // rings
- //
- le = CG_AllocLocalEntity();
- re = &le->refEntity;
-
- le->leType = LE_FADE_RGB;
- le->startTime = cg.time;
- le->endTime = cg.time + cg_railTrailTime.value;
- le->lifeRate = 1.0 / ( le->endTime - le->startTime );
-
- re->shaderTime = cg.time / 1000.0f;
- re->reType = RT_RAIL_RINGS;
- re->customShader = cgs.media.railRingsShader;
-
- VectorCopy( start, re->origin );
- VectorCopy( end, re->oldorigin );
-
- // nudge down a bit so it isn't exactly in center
- re->origin[2] -= 8;
- re->oldorigin[2] -= 8;
-
- le->color[0] = ci->color[0] * 0.75;
- le->color[1] = ci->color[1] * 0.75;
- le->color[2] = ci->color[2] * 0.75;
- le->color[3] = 1.0f;
-
- AxisClear( re->axis );
-
- //
- // core
- //
- le = CG_AllocLocalEntity();
- re = &le->refEntity;
-
- le->leType = LE_FADE_RGB;
- le->startTime = cg.time;
- le->endTime = cg.time + cg_railTrailTime.value;
- le->lifeRate = 1.0 / ( le->endTime - le->startTime );
-
- re->shaderTime = cg.time / 1000.0f;
- re->reType = RT_RAIL_CORE;
- re->customShader = cgs.media.railCoreShader;
-
- VectorCopy( start, re->origin );
- VectorCopy( end, re->oldorigin );
-
- // nudge down a bit so it isn't exactly in center
- re->origin[2] -= 8;
- re->oldorigin[2] -= 8;
-
- le->color[0] = ci->color[0] * 0.75;
- le->color[1] = ci->color[1] * 0.75;
- le->color[2] = ci->color[2] * 0.75;
- le->color[3] = 1.0f;
-
- AxisClear( re->axis );
-}
-
-/*
-==========================
-CG_RocketTrail
-==========================
-*/
-static void CG_RocketTrail( centity_t *ent, const weaponInfo_t *wi ) {
- int step;
- vec3_t origin, lastPos;
- int t;
- int startTime, contents;
- int lastContents;
- entityState_t *es;
- vec3_t up;
- localEntity_t *smoke;
-
- up[0] = 0;
- up[1] = 0;
- up[2] = 0;
-
- step = 50;
-
- es = &ent->currentState;
- startTime = ent->trailTime;
- t = step * ( (startTime + step) / step );
-
- BG_EvaluateTrajectory( &es->pos, cg.time, origin );
- contents = CG_PointContents( origin, -1 );
-
- // if object (e.g. grenade) is stationary, don't toss up smoke
- if ( es->pos.trType == TR_STATIONARY ) {
- ent->trailTime = cg.time;
- return;
- }
-
- BG_EvaluateTrajectory( &es->pos, ent->trailTime, lastPos );
- lastContents = CG_PointContents( lastPos, -1 );
-
- ent->trailTime = cg.time;
-
- if ( contents & ( CONTENTS_WATER | CONTENTS_SLIME | CONTENTS_LAVA ) ) {
- if ( contents & lastContents & CONTENTS_WATER ) {
- CG_BubbleTrail( lastPos, origin, 8 );
- }
- return;
- }
-
- for ( ; t <= ent->trailTime ; t += step ) {
- BG_EvaluateTrajectory( &es->pos, t, lastPos );
-
- smoke = CG_SmokePuff( lastPos, up,
- wi->trailRadius,
- 1, 1, 1, 0.33f,
- wi->wiTrailTime,
- t,
- 0,
- 0,
- cgs.media.smokePuffShader );
- // use the optimized local entity add
- smoke->leType = LE_SCALE_FADE;
- }
-
-}
-
-/*
-==========================
-CG_GrappleTrail
-==========================
-*/
-void CG_GrappleTrail( centity_t *ent, const weaponInfo_t *wi ) {
- vec3_t origin;
- entityState_t *es;
- vec3_t forward, up;
- refEntity_t beam;
-
- es = &ent->currentState;
-
- BG_EvaluateTrajectory( &es->pos, cg.time, origin );
- ent->trailTime = cg.time;
-
- memset( &beam, 0, sizeof( beam ) );
- //FIXME adjust for muzzle position
- VectorCopy ( cg_entities[ ent->currentState.otherEntityNum ].lerpOrigin, beam.origin );
- beam.origin[2] += 26;
- AngleVectors( cg_entities[ ent->currentState.otherEntityNum ].lerpAngles, forward, NULL, up );
- VectorMA( beam.origin, -6, up, beam.origin );
- VectorCopy( origin, beam.oldorigin );
-
- if (Distance( beam.origin, beam.oldorigin ) < 64 )
- return; // Don't draw if close
-
- beam.reType = RT_LIGHTNING;
- beam.customShader = cgs.media.lightningShader;
-
- AxisClear( beam.axis );
- beam.shaderRGBA[0] = 0xff;
- beam.shaderRGBA[1] = 0xff;
- beam.shaderRGBA[2] = 0xff;
- beam.shaderRGBA[3] = 0xff;
- trap_R_AddRefEntityToScene( &beam );
-}
-
-/*
-==========================
-CG_GrenadeTrail
-==========================
-*/
-static void CG_GrenadeTrail( centity_t *ent, const weaponInfo_t *wi ) {
- CG_RocketTrail( ent, wi );
-}
-
-/*
-=================
-CG_RegisterUpgrade
-
-The server says this item is used on this level
-=================
-*/
-void CG_RegisterUpgrade( int upgradeNum ) {
- upgradeInfo_t *upgradeInfo;
- gitem_t *item;
- char path[MAX_QPATH];
- int i;
-
- upgradeInfo = &cg_upgrades[ upgradeNum ];
-
- if ( upgradeNum == 0 ) {
- return;
- }
-
- if ( upgradeInfo->registered ) {
- return;
- }
-
- memset( upgradeInfo, 0, sizeof( *upgradeInfo ) );
- upgradeInfo->registered = qtrue;
-
- for ( item = bg_itemlist + 1 ; item->classname ; item++ ) {
- if ( item->giType == IT_UPGRADE && item->giTag == upgradeNum ) {
- upgradeInfo->item = item;
- break;
- }
- }
- if ( !item->classname ) {
- CG_Error( "Couldn't find upgrade %i", upgradeNum );
- }
- CG_RegisterItemVisuals( item - bg_itemlist );
-
- upgradeInfo->upgradeIcon = trap_R_RegisterShader( item->icon );
-}
-
-/*
-=================
-CG_RegisterWeapon
-
-The server says this item is used on this level
-=================
-*/
-void CG_RegisterWeapon( int weaponNum ) {
- weaponInfo_t *weaponInfo;
- gitem_t *item, *ammo;
- 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;
-
- for ( item = bg_itemlist + 1 ; item->classname ; item++ ) {
- if ( item->giType == IT_WEAPON && item->giTag == weaponNum ) {
- weaponInfo->item = item;
- break;
- }
- }
- if ( !item->classname ) {
- CG_Error( "Couldn't find weapon %i", weaponNum );
- }
- CG_RegisterItemVisuals( item - bg_itemlist );
-
- // load cmodel before model so filecache works
- weaponInfo->weaponModel = trap_R_RegisterModel( item->world_model[0] );
-
- // 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] );
- }
-
- weaponInfo->weaponIcon = trap_R_RegisterShader( item->icon );
- weaponInfo->ammoIcon = trap_R_RegisterShader( item->icon );
-
- for ( ammo = bg_itemlist + 1 ; ammo->classname ; ammo++ ) {
- if ( ammo->giType == IT_AMMO && ammo->giTag == weaponNum ) {
- break;
- }
- }
- if ( ammo->classname && ammo->world_model[0] ) {
- weaponInfo->ammoModel = trap_R_RegisterModel( ammo->world_model[0] );
- }
-
- strcpy( path, item->world_model[0] );
- COM_StripExtension( path, path );
- strcat( path, "_flash.md3" );
- weaponInfo->flashModel = trap_R_RegisterModel( path );
-
- strcpy( path, item->world_model[0] );
- COM_StripExtension( path, path );
- strcat( path, "_barrel.md3" );
- weaponInfo->barrelModel = trap_R_RegisterModel( path );
-
- strcpy( path, item->world_model[0] );
- COM_StripExtension( path, path );
- strcat( path, "_hand.md3" );
- weaponInfo->handsModel = trap_R_RegisterModel( path );
-
- if ( !weaponInfo->handsModel ) {
- weaponInfo->handsModel = trap_R_RegisterModel( "models/weapons2/shotgun/shotgun_hand.md3" );
- }
-
- weaponInfo->loopFireSound = qfalse;
-
- switch ( weaponNum ) {
- case WP_GAUNTLET:
- MAKERGB( weaponInfo->flashDlightColor, 0.6f, 0.6f, 1.0f );
- weaponInfo->firingSound = trap_S_RegisterSound( "sound/weapons/melee/fstrun.wav", qfalse );
- weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/melee/fstatck.wav", qfalse );
- break;
-
- case WP_LIGHTNING:
- MAKERGB( weaponInfo->flashDlightColor, 0.6f, 0.6f, 1.0f );
- weaponInfo->readySound = trap_S_RegisterSound( "sound/weapons/melee/fsthum.wav", qfalse );
- weaponInfo->firingSound = trap_S_RegisterSound( "sound/weapons/lightning/lg_hum.wav", qfalse );
-
- weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/lightning/lg_fire.wav", qfalse );
- cgs.media.lightningShader = trap_R_RegisterShader( "lightningBolt");
- cgs.media.lightningExplosionModel = trap_R_RegisterModel( "models/weaphits/crackle.md3" );
- cgs.media.sfx_lghit1 = trap_S_RegisterSound( "sound/weapons/lightning/lg_hit.wav", qfalse );
- cgs.media.sfx_lghit2 = trap_S_RegisterSound( "sound/weapons/lightning/lg_hit2.wav", qfalse );
- cgs.media.sfx_lghit3 = trap_S_RegisterSound( "sound/weapons/lightning/lg_hit3.wav", qfalse );
-
- break;
-
- case WP_GRAPPLING_HOOK:
- MAKERGB( weaponInfo->flashDlightColor, 0.6f, 0.6f, 1.0f );
- weaponInfo->missileModel = trap_R_RegisterModel( "models/ammo/rocket/rocket.md3" );
- weaponInfo->missileTrailFunc = CG_GrappleTrail;
- weaponInfo->missileDlight = 200;
- weaponInfo->wiTrailTime = 2000;
- weaponInfo->trailRadius = 64;
- MAKERGB( weaponInfo->missileDlightColor, 1, 0.75f, 0 );
- weaponInfo->readySound = trap_S_RegisterSound( "sound/weapons/melee/fsthum.wav", qfalse );
- weaponInfo->firingSound = trap_S_RegisterSound( "sound/weapons/melee/fstrun.wav", qfalse );
- break;
-
- case WP_MACHINEGUN:
- MAKERGB( weaponInfo->flashDlightColor, 1, 1, 0 );
- weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/machinegun/machgf1b.wav", qfalse );
- weaponInfo->flashSound[1] = trap_S_RegisterSound( "sound/weapons/machinegun/machgf2b.wav", qfalse );
- weaponInfo->flashSound[2] = trap_S_RegisterSound( "sound/weapons/machinegun/machgf3b.wav", qfalse );
- weaponInfo->flashSound[3] = trap_S_RegisterSound( "sound/weapons/machinegun/machgf4b.wav", qfalse );
- weaponInfo->ejectBrassFunc = CG_MachineGunEjectBrass;
- cgs.media.bulletExplosionShader = trap_R_RegisterShader( "bulletExplosion" );
- break;
-
- case WP_CHAINGUN:
- MAKERGB( weaponInfo->flashDlightColor, 1, 1, 0 );
- weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/machinegun/machgf1b.wav", qfalse );
- weaponInfo->flashSound[1] = trap_S_RegisterSound( "sound/weapons/machinegun/machgf2b.wav", qfalse );
- weaponInfo->flashSound[2] = trap_S_RegisterSound( "sound/weapons/machinegun/machgf3b.wav", qfalse );
- weaponInfo->flashSound[3] = trap_S_RegisterSound( "sound/weapons/machinegun/machgf4b.wav", qfalse );
- weaponInfo->ejectBrassFunc = CG_MachineGunEjectBrass;
- cgs.media.bulletExplosionShader = trap_R_RegisterShader( "bulletExplosion" );
- break;
-
- case WP_SHOTGUN:
- MAKERGB( weaponInfo->flashDlightColor, 1, 1, 0 );
- weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/shotgun/sshotf1b.wav", qfalse );
- weaponInfo->ejectBrassFunc = CG_ShotgunEjectBrass;
- break;
-
- case WP_ROCKET_LAUNCHER:
- weaponInfo->missileModel = trap_R_RegisterModel( "models/ammo/rocket/rocket.md3" );
- weaponInfo->missileSound = trap_S_RegisterSound( "sound/weapons/rocket/rockfly.wav", qfalse );
- weaponInfo->missileTrailFunc = CG_RocketTrail;
- weaponInfo->missileDlight = 200;
- weaponInfo->wiTrailTime = 2000;
- weaponInfo->trailRadius = 64;
- MAKERGB( weaponInfo->missileDlightColor, 1, 0.75f, 0 );
- MAKERGB( weaponInfo->flashDlightColor, 1, 0.75f, 0 );
- weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/rocket/rocklf1a.wav", qfalse );
- cgs.media.rocketExplosionShader = trap_R_RegisterShader( "rocketExplosion" );
- break;
-
- case WP_GRENADE_LAUNCHER:
- weaponInfo->missileModel = trap_R_RegisterModel( "models/ammo/grenade1.md3" );
- weaponInfo->missileTrailFunc = CG_GrenadeTrail;
- weaponInfo->wiTrailTime = 700;
- weaponInfo->trailRadius = 32;
- MAKERGB( weaponInfo->flashDlightColor, 1, 0.70f, 0 );
- weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/grenade/grenlf1a.wav", qfalse );
- cgs.media.grenadeExplosionShader = trap_R_RegisterShader( "grenadeExplosion" );
- break;
-
- case WP_FLAMER:
- weaponInfo->missileSound = trap_S_RegisterSound( "sound/weapons/plasma/lasfly.wav", qfalse );
- MAKERGB( weaponInfo->flashDlightColor, 0.25, 0.1, 0 );
- weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/plasma/rg_hum.wav", qfalse );
- cgs.media.flameExplShader = trap_R_RegisterShader( "rocketExplosion" );
- break;
-
- case WP_PLASMAGUN:
- weaponInfo->missileSound = trap_S_RegisterSound( "sound/weapons/plasma/lasfly.wav", qfalse );
- MAKERGB( weaponInfo->flashDlightColor, 0.6f, 0.6f, 1.0f );
- weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/plasma/hyprbf1a.wav", qfalse );
- cgs.media.plasmaExplosionShader = trap_R_RegisterShader( "plasmaExplosion" );
- break;
-
- case WP_RAILGUN:
- weaponInfo->readySound = trap_S_RegisterSound( "sound/weapons/railgun/rg_hum.wav", qfalse );
- MAKERGB( weaponInfo->flashDlightColor, 1, 0.5f, 0 );
- weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/railgun/railgf1a.wav", qfalse );
- cgs.media.railExplosionShader = trap_R_RegisterShader( "railExplosion" );
- cgs.media.railRingsShader = trap_R_RegisterShader( "railDisc" );
- cgs.media.railCoreShader = trap_R_RegisterShader( "railCore" );
- break;
-
- case WP_BFG:
- weaponInfo->readySound = trap_S_RegisterSound( "sound/weapons/bfg/bfg_hum.wav", qfalse );
- MAKERGB( weaponInfo->flashDlightColor, 1, 0.7f, 1 );
- weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/bfg/bfg_fire.wav", qfalse );
- cgs.media.bfgExplosionShader = trap_R_RegisterShader( "bfgExplosion" );
- weaponInfo->missileModel = trap_R_RegisterModel( "models/weaphits/bfg.md3" );
- weaponInfo->missileSound = trap_S_RegisterSound( "sound/weapons/rocket/rockfly.wav", qfalse );
- break;
-
- case WP_VENOM:
- MAKERGB( weaponInfo->flashDlightColor, 0, 0, 0 );
- weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/melee/fstatck.wav", qfalse );
- break;
-
- case WP_ABUILD:
- case WP_HBUILD:
- case WP_SCANNER:
- //nowt
- break;
-
- default:
- MAKERGB( weaponInfo->flashDlightColor, 1, 1, 1 );
- weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/rocket/rocklf1a.wav", qfalse );
- break;
- }
-}
-
-/*
-=================
-CG_RegisterItemVisuals
-
-The server says this item is used on this level
-=================
-*/
-void CG_RegisterItemVisuals( int itemNum ) {
- itemInfo_t *itemInfo;
- gitem_t *item;
- int i;
-
- itemInfo = &cg_items[ itemNum ];
- if ( itemInfo->registered ) {
- return;
- }
-
- item = &bg_itemlist[ itemNum ];
-
- memset( itemInfo, 0, sizeof( &itemInfo ) );
- itemInfo->registered = qtrue;
-
- itemInfo->icon = trap_R_RegisterShader( item->icon );
-
- if ( item->giType == IT_WEAPON ) {
- CG_RegisterWeapon( item->giTag );
- }
-
- for( i = 0; i < 4; i++ )
- {
- if( item->world_model[ i ] )
- itemInfo->models[i] = trap_R_RegisterModel( item->world_model[i] );
- }
-
-}
-
-
-/*
-========================================================================================
-
-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_ATTACK].firstFrame;
- }
-
- return 0;
-}
-
-
-/*
-==============
-CG_CalculateWeaponPosition
-==============
-*/
-static void CG_CalculateWeaponPosition( vec3_t origin, vec3_t angles ) {
- float scale;
- int delta;
- float fracsin;
- int 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
- BG_unpackAttributes( NULL, &bob, NULL, cg.predictedPlayerState.stats );
- 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( !( cg.predictedPlayerState.stats[ STAT_ABILITIES ] & 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;
- }
-
- //TA: huh? why drop the weapon when stair climbing... just as well this isn't actually used :)
-#if 0
- // drop the weapon when stair climbing
- delta = cg.time - cg.stepTime;
- if ( delta < STEP_TIME/2 ) {
- origin[2] -= cg.stepChange*0.25 * delta / (STEP_TIME/2);
- } else if ( delta < STEP_TIME ) {
- origin[2] -= cg.stepChange*0.25 * (STEP_TIME - delta) / (STEP_TIME/2);
- }
-#endif
-
- // 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_LightningBolt
-
-Origin will be the exact tag point, which is slightly
-different than the muzzle point used for determining hits.
-The cent should be the non-predicted cent if it is from the player,
-so the endpoint will reflect the simulated strike (lagging the predicted
-angle)
-===============
-*/
-static void CG_LightningBolt( centity_t *cent, vec3_t origin ) {
- trace_t trace;
- refEntity_t beam;
- vec3_t forward;
- vec3_t muzzlePoint, endPoint;
-
- if ( cent->currentState.weapon != WP_LIGHTNING ) {
- return;
- }
-
- memset( &beam, 0, sizeof( beam ) );
-
- // find muzzle point for this frame
- VectorCopy( cent->lerpOrigin, muzzlePoint );
- AngleVectors( cent->lerpAngles, forward, NULL, NULL );
-
- // FIXME: crouch
- muzzlePoint[2] += DEFAULT_VIEWHEIGHT;
-
- VectorMA( muzzlePoint, 14, forward, muzzlePoint );
-
- // project forward by the lightning range
- VectorMA( muzzlePoint, LIGHTNING_RANGE, forward, endPoint );
-
- // see if it hit a wall
- CG_Trace( &trace, muzzlePoint, vec3_origin, vec3_origin, endPoint,
- cent->currentState.number, MASK_SHOT );
-
- // this is the endpoint
- VectorCopy( trace.endpos, beam.oldorigin );
-
- // use the provided origin, even though it may be slightly
- // different than the muzzle origin
- VectorCopy( origin, beam.origin );
-
- beam.reType = RT_LIGHTNING;
- beam.customShader = cgs.media.lightningShader;
- trap_R_AddRefEntityToScene( &beam );
-
- // add the impact flare if it hit something
- if ( trace.fraction < 1.0 ) {
- vec3_t angles;
- vec3_t dir;
-
- VectorSubtract( beam.oldorigin, beam.origin, dir );
- VectorNormalize( dir );
-
- memset( &beam, 0, sizeof( beam ) );
- beam.hModel = cgs.media.lightningExplosionModel;
-
- VectorMA( trace.endpos, -16, dir, beam.origin );
-
- // make a random orientation
- angles[0] = rand() % 360;
- angles[1] = rand() % 360;
- angles[2] = rand() % 360;
- AnglesToAxis( angles, beam.axis );
- trap_R_AddRefEntityToScene( &beam );
- }
-}
-
-
-/*
-===============
-CG_SpawnRailTrail
-
-Origin will be the exact tag point, which is slightly
-different than the muzzle point used for determining hits.
-===============
-*/
-static void CG_SpawnRailTrail( centity_t *cent, vec3_t origin ) {
- clientInfo_t *ci;
-
- if ( cent->currentState.weapon != WP_RAILGUN ) {
- return;
- }
- if ( !cent->pe.railgunFlash ) {
- return;
- }
- cent->pe.railgunFlash = qtrue;
- ci = &cgs.clientinfo[ cent->currentState.clientNum ];
- CG_RailTrail( ci, origin, cent->pe.railgunImpact );
-}
-
-
-/*
-======================
-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);
- }
-
- return angle;
-}
-
-
-/*
-========================
-CG_AddWeaponWithPowerups
-========================
-*/
-static void CG_AddWeaponWithPowerups( refEntity_t *gun, int powerups ) {
- // add powerup effects
- /*if ( powerups & ( 1 << PW_INVIS ) ) {
- gun->customShader = cgs.media.invisShader;
- trap_R_AddRefEntityToScene( gun );
- } else*/ {
- trap_R_AddRefEntityToScene( gun );
-
- /*if ( powerups & ( 1 << PW_BATTLESUIT ) ) {
- gun->customShader = cgs.media.battleWeaponShader;
- trap_R_AddRefEntityToScene( gun );
- }
- if ( powerups & ( 1 << PW_QUAD ) ) {
- gun->customShader = cgs.media.quadWeaponShader;
- trap_R_AddRefEntityToScene( gun );
- }*/
- }
-}
-
-
-/*
-=============
-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;
- weaponInfo_t *weapon;
- centity_t *nonPredictedCent;
-
- weaponNum = cent->currentState.weapon;
-
- 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 ) {
- if ( cg.predictedPlayerState.weapon == WP_RAILGUN
- && cg.predictedPlayerState.weaponstate == WEAPON_FIRING ) {
- float f;
-
- f = (float)cg.predictedPlayerState.weaponTime / 1500;
- gun.shaderRGBA[1] = 0;
- gun.shaderRGBA[0] =
- gun.shaderRGBA[2] = 255 * ( 1.0 - f );
- } else {
- gun.shaderRGBA[0] = 255;
- gun.shaderRGBA[1] = 255;
- gun.shaderRGBA[2] = 255;
- gun.shaderRGBA[3] = 255;
- }
- }
-
- gun.hModel = weapon->weaponModel;
- if (!gun.hModel) {
- return;
- }
-
- if ( !ps ) {
- // add weapon ready sound
- cent->pe.lightningFiring = qfalse;
- if ( ( cent->currentState.eFlags & EF_FIRING ) && weapon->firingSound ) {
- // lightning gun and guantlet make a different sound when fire is held down
- trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, weapon->firingSound );
- cent->pe.lightningFiring = qtrue;
- } else if ( weapon->readySound ) {
- trap_S_AddLoopingSound( cent->currentState.number, cent->lerpOrigin, vec3_origin, weapon->readySound );
- }
- }
-
- CG_PositionEntityOnTag( &gun, parent, parent->hModel, "tag_weapon");
-
- CG_AddWeaponWithPowerups( &gun, cent->currentState.powerups );
-
- // 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" );
-
- CG_AddWeaponWithPowerups( &barrel, cent->currentState.powerups );
- }
-
- // make sure we aren't looking at cg.predictedPlayerEntity for LG
- nonPredictedCent = &cg_entities[cent->currentState.clientNum];
-
- // if the index of the nonPredictedCent is not the same as the clientNum
- // then this is a fake player (like on teh single player podiums), so
- // go ahead and use the cent
- if( ( nonPredictedCent - cg_entities ) != cent->currentState.clientNum ) {
- nonPredictedCent = cent;
- }
-
- // add the flash
- if ( ( weaponNum == WP_LIGHTNING || weaponNum == WP_GAUNTLET || weaponNum == WP_GRAPPLING_HOOK )
- && ( nonPredictedCent->currentState.eFlags & EF_FIRING ) )
- {
- // continuous flash
- } else {
- // impulse flash
- if ( cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME && !cent->pe.railgunFlash ) {
- 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) {
- return;
- }
- angles[YAW] = 0;
- angles[PITCH] = 0;
- angles[ROLL] = crandom() * 10;
- AnglesToAxis( angles, flash.axis );
-
- // colorize the railgun blast
- if ( weaponNum == WP_RAILGUN ) {
- clientInfo_t *ci;
-
- ci = &cgs.clientinfo[ cent->currentState.clientNum ];
- flash.shaderRGBA[0] = 255 * ci->color[0];
- flash.shaderRGBA[1] = 255 * ci->color[1];
- flash.shaderRGBA[2] = 255 * ci->color[2];
- }
-
- CG_PositionRotatedEntityOnTag( &flash, &gun, weapon->weaponModel, "tag_flash");
- trap_R_AddRefEntityToScene( &flash );
-
- if ( ps || cg.renderingThirdPerson ||
- cent->currentState.number != cg.predictedPlayerState.clientNum ) {
- // add lightning bolt
- CG_LightningBolt( nonPredictedCent, flash.origin );
-
- // add rail trail
- CG_SpawnRailTrail( cent, flash.origin );
-
- // make a dlight for the flash
- if ( weapon->flashDlightColor[0] || weapon->flashDlightColor[1] || weapon->flashDlightColor[2] ) {
- trap_R_AddLightToScene( flash.origin, 300 + (rand()&31), weapon->flashDlightColor[0],
- weapon->flashDlightColor[1], weapon->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 *weapon;
-
- if ( ps->persistant[PERS_TEAM] == TEAM_SPECTATOR ) {
- return;
- }
-
- if ( ps->pm_type == PM_INTERMISSION ) {
- return;
- }
-
- // 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;
-
- if ( cg.predictedPlayerState.eFlags & EF_FIRING ) {
- // special hack for lightning gun...
- VectorCopy( cg.refdef.vieworg, origin );
- VectorMA( origin, -8, cg.refdef.viewaxis[2], origin );
- CG_LightningBolt( &cg_entities[ps->clientNum], origin );
- }
- 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.2 * ( cg.refdef.fov_y - 90 );
- else
- fovOffset = 0;
-
- cent = &cg.predictedPlayerEntity; // &cg_entities[cg.snap->ps.clientNum];
- CG_RegisterWeapon( ps->weapon );
- weapon = &cg_weapons[ ps->weapon ];
-
- 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 );
-
- 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 = weapon->handsModel;
- hand.renderfx = RF_DEPTHHACK | RF_FIRST_PERSON | RF_MINLIGHT;
-
- // add everything onto the hand
- CG_AddPlayerWeapon( &hand, ps, &cg.predictedPlayerEntity );
-}
-
-/*
-==============================================================================
-
-WEAPON SELECTION
-
-==============================================================================
-*/
-
-/*
-===================
-CG_DrawWeaponSelect
-
-===================
-*/
-void CG_DrawWeaponSelect( void ) {
- int i;
- //int count;
- int x, y, w;
- char *name;
- float *color;
- int ammo, clips, maxclips;
-
- // don't display if dead
- if ( cg.predictedPlayerState.stats[STAT_HEALTH] <= 0 ) {
- return;
- }
-
- color = CG_FadeColor( cg.weaponSelectTime, WEAPON_SELECT_TIME );
- if ( !color ) {
- return;
- }
- trap_R_SetColor( color );
-
- // showing weapon select clears pickup item display, but not the blend blob
- cg.itemPickupTime = 0;
-
- /*// count the number of weapons owned
- count = 0;
- for ( i = WP_GAUNTLET; i < WP_NUM_WEAPONS; i++ ) {
- if ( BG_gotWeapon( i, cg.snap->ps.stats ) ) {
- count++;
- }
- }*/
-
- //x = 320 - count * 20;
- //y = 380;
-
- x = 10;
- y = 10;
-
- for ( i = WP_GAUNTLET; i < WP_NUM_WEAPONS; i++ ) {
- if( !BG_gotWeapon( i, cg.snap->ps.stats ) )
- continue;
-
- CG_RegisterWeapon( i );
-
- // draw weapon icon
- CG_DrawPic( x, y, 16, 16, cg_weapons[i].weaponIcon );
-
- // draw selection marker
- if ( i == cg.weaponSelect ) {
- CG_DrawPic( x-2, y-2, 20, 20, cgs.media.selectShader );
- }
-
- BG_unpackAmmoArray( i, cg.snap->ps.ammo, cg.snap->ps.powerups, &ammo, &clips, &maxclips );
-
- // no ammo cross on top
- if ( !ammo && !clips && !BG_infiniteAmmo( i ) ) {
- CG_DrawPic( x, y, 16, 16, cgs.media.noammoShader );
- }
-
- y += 20;
- }
-
- for ( i = UP_TORCH; i < UP_NUM_UPGRADES; i++ ) {
- if( !BG_gotItem( i, cg.snap->ps.stats ) )
- continue;
-
- CG_RegisterUpgrade( i );
-
- // draw weapon icon
- CG_DrawPic( x, y, 16, 16, cg_upgrades[i].upgradeIcon );
-
- // draw selection marker
- if ( i == ( cg.weaponSelect - 32 ) ) {
- CG_DrawPic( x-2, y-2, 20, 20, cgs.media.selectShader );
- }
-
- y += 20;
- }
-
- // draw the selected name
- if( cg.weaponSelect <= 32 )
- {
- if ( cg_weapons[ cg.weaponSelect ].item ) {
- name = cg_weapons[ cg.weaponSelect ].item->pickup_name;
- if ( name ) {
- w = CG_DrawStrlen( name ) * BIGCHAR_WIDTH;
- x = ( SCREEN_WIDTH - w ) / 2;
- CG_DrawBigStringColor(x, y - 22, name, color);
- }
- }
- }
- else if( cg.weaponSelect > 32 )
- {
- if ( cg_upgrades[ cg.weaponSelect - 32 ].item ) {
- name = cg_upgrades[ cg.weaponSelect - 32 ].item->pickup_name;
- if ( name ) {
- w = CG_DrawStrlen( name ) * BIGCHAR_WIDTH;
- x = ( SCREEN_WIDTH - w ) / 2;
- CG_DrawBigStringColor(x, y - 22, name, color);
- }
- }
- }
-
- trap_R_SetColor( NULL );
-}
-
-
-/*
-===============
-CG_WeaponSelectable
-===============
-*/
-static qboolean CG_WeaponSelectable( int i )
-{
- int ammo, clips, maxclips;
-
- BG_unpackAmmoArray( i, cg.snap->ps.ammo, cg.snap->ps.powerups, &ammo, &clips, &maxclips );
-
- if ( !ammo && !clips && !BG_infiniteAmmo( i ) ) {
- return qfalse;
- }
- if ( !BG_gotWeapon( i, cg.snap->ps.stats ) ) {
- return qfalse;
- }
-
- return qtrue;
-}
-
-
-/*
-===============
-CG_ItemSelectable
-===============
-*/
-static qboolean CG_ItemSelectable( int i )
-{
- if( !BG_gotItem( i, cg.snap->ps.stats ) ) {
- return qfalse;
- }
-
- return qtrue;
-}
-
-
-/*
-===============
-CG_NextWeapon_f
-===============
-*/
-void CG_NextWeapon_f( void ) {
- int i;
- int original;
-
- if ( !cg.snap ) {
- return;
- }
- if ( cg.snap->ps.pm_flags & PMF_FOLLOW ) {
- 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 == WP_GAUNTLET ) {
- continue; // never cycle to gauntlet
- }*/
-
- if( cg.weaponSelect <= 32 )
- {
- if ( CG_WeaponSelectable( cg.weaponSelect ) ) {
- break;
- }
- }
- else if( cg.weaponSelect > 32 )
- {
- if ( CG_ItemSelectable( 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 ) {
- 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 == WP_GAUNTLET ) {
- continue; // never cycle to gauntlet
- }*/
- if( cg.weaponSelect <= 32 )
- {
- if ( CG_WeaponSelectable( cg.weaponSelect ) ) {
- break;
- }
- }
- else if( cg.weaponSelect > 32 )
- {
- if ( CG_ItemSelectable( 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_gotWeapon( num, cg.snap->ps.stats ) ) {
- return; // don't have the weapon
- }
-
- cg.weaponSelect = num;
-}
-
-/*
-===================
-CG_OutOfAmmoChange
-
-The current weapon has just run out of ammo
-===================
-*/
-void CG_OutOfAmmoChange( void ) {
- int i;
-
- //TA: mwhaha, must manually change weapons
- /*cg.weaponSelectTime = cg.time;
-
- for ( i = 31 ; i > 0 ; i-- ) {
- if ( CG_WeaponSelectable( i ) ) {
- cg.weaponSelect = i;
- break;
- }
- }*/
-}
-
-
-
-/*
-===================================================================================================
-
-WEAPON EVENTS
-
-===================================================================================================
-*/
-
-/*
-================
-CG_FireWeapon
-
-Caused by an EV_FIRE_WEAPON event
-================
-*/
-void CG_FireWeapon( centity_t *cent ) {
- entityState_t *ent;
- int c;
- weaponInfo_t *weap;
-
- ent = &cent->currentState;
- if ( ent->weapon == WP_NONE ) {
- return;
- }
- if ( ent->weapon >= WP_NUM_WEAPONS ) {
- CG_Error( "CG_FireWeapon: ent->weapon >= WP_NUM_WEAPONS" );
- return;
- }
- weap = &cg_weapons[ ent->weapon ];
-
- // mark the entity as muzzle flashing, so when it is added it will
- // append the flash to the weapon model
- cent->muzzleFlashTime = cg.time;
-
- // lightning gun only does this this on initial press
- if ( ent->weapon == WP_LIGHTNING ) {
- if ( cent->pe.lightningFiring ) {
- return;
- }
- }
-
- // play quad sound if needed
- /*if ( cent->currentState.powerups & ( 1 << PW_QUAD ) ) {
- trap_S_StartSound (NULL, cent->currentState.number, CHAN_ITEM, cgs.media.quadSound );
- }*/
-
- // play a sound
- for ( c = 0 ; c < 4 ; c++ ) {
- if ( !weap->flashSound[c] ) {
- break;
- }
- }
- if ( c > 0 ) {
- c = rand() % c;
- if ( weap->flashSound[c] )
- {
- trap_S_StartSound( NULL, ent->number, CHAN_WEAPON, weap->flashSound[c] );
- }
- }
-
- // do brass ejection
- if ( weap->ejectBrassFunc && cg_brassTime.integer > 0 ) {
- weap->ejectBrassFunc( cent );
- }
-}
-
-
-/*
-=================
-CG_MissileHitWall
-
-Caused by an EV_MISSILE_MISS event, or directly by local bullet tracing
-=================
-*/
-void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, impactSound_t soundType ) {
- qhandle_t mod;
- qhandle_t mark;
- qhandle_t shader;
- sfxHandle_t sfx;
- float radius;
- float light;
- vec3_t lightColor;
- localEntity_t *le;
- int r;
- qboolean alphaFade;
- qboolean isSprite;
- int duration;
-
- mark = 0;
- radius = 32;
- sfx = 0;
- mod = 0;
- shader = 0;
- light = 0;
- lightColor[0] = 1;
- lightColor[1] = 1;
- lightColor[2] = 0;
-
- // set defaults
- isSprite = qfalse;
- duration = 600;
-
- switch ( weapon ) {
- default:
- case WP_LIGHTNING:
- // no explosion at LG impact, it is added with the beam
- r = rand() & 3;
- if ( r < 2 ) {
- sfx = cgs.media.sfx_lghit2;
- } else if ( r == 2 ) {
- sfx = cgs.media.sfx_lghit1;
- } else {
- sfx = cgs.media.sfx_lghit3;
- }
- mark = cgs.media.holeMarkShader;
- radius = 12;
- break;
- case WP_GRENADE_LAUNCHER:
- mod = cgs.media.dishFlashModel;
- shader = cgs.media.grenadeExplosionShader;
- sfx = cgs.media.sfx_rockexp;
- mark = cgs.media.burnMarkShader;
- radius = 64;
- light = 300;
- isSprite = qtrue;
- break;
- case WP_ROCKET_LAUNCHER:
- mod = cgs.media.dishFlashModel;
- shader = cgs.media.rocketExplosionShader;
- sfx = cgs.media.sfx_rockexp;
- mark = cgs.media.burnMarkShader;
- radius = 64;
- light = 300;
- isSprite = qtrue;
- duration = 1000;
- lightColor[0] = 1;
- lightColor[1] = 0.75;
- lightColor[2] = 0.0;
- break;
- case WP_RAILGUN:
- mod = cgs.media.ringFlashModel;
- shader = cgs.media.railExplosionShader;
- sfx = cgs.media.sfx_plasmaexp;
- mark = cgs.media.energyMarkShader;
- radius = 24;
- break;
- case WP_FLAMER:
- mod = cgs.media.dishFlashModel;
- shader = cgs.media.flameExplShader;
- sfx = cgs.media.sfx_lghit2;
- mark = cgs.media.burnMarkShader;
- radius = 48;
- isSprite = qtrue;
- break;
- case WP_PLASMAGUN:
- mod = cgs.media.ringFlashModel;
- shader = cgs.media.plasmaExplosionShader;
- sfx = cgs.media.sfx_plasmaexp;
- mark = cgs.media.energyMarkShader;
- radius = 16;
- break;
- case WP_BFG:
- mod = cgs.media.dishFlashModel;
- shader = cgs.media.bfgExplosionShader;
- sfx = cgs.media.sfx_rockexp;
- mark = cgs.media.burnMarkShader;
- radius = 32;
- isSprite = qtrue;
- break;
- case WP_SHOTGUN:
- mod = cgs.media.bulletFlashModel;
- shader = cgs.media.bulletExplosionShader;
- mark = cgs.media.bulletMarkShader;
- sfx = 0;
- radius = 4;
- break;
- case WP_MACHINEGUN:
- mod = cgs.media.bulletFlashModel;
- shader = cgs.media.bulletExplosionShader;
- mark = cgs.media.bulletMarkShader;
- case WP_CHAINGUN:
- mod = cgs.media.bulletFlashModel;
- shader = cgs.media.bulletExplosionShader;
- mark = cgs.media.bulletMarkShader;
-
- r = rand() & 3;
- if ( r < 2 ) {
- sfx = cgs.media.sfx_ric1;
- } else if ( r == 2 ) {
- sfx = cgs.media.sfx_ric2;
- } else {
- sfx = cgs.media.sfx_ric3;
- }
-
- radius = 8;
- break;
- }
-
- if ( sfx ) {
- trap_S_StartSound( origin, ENTITYNUM_WORLD, CHAN_AUTO, sfx );
- }
-
- //
- // create the explosion
- //
- if ( mod ) {
- le = CG_MakeExplosion( origin, dir,
- mod, shader,
- duration, isSprite );
- le->light = light;
- VectorCopy( lightColor, le->lightColor );
- if ( weapon == WP_RAILGUN ) {
- // colorize with client color
- VectorCopy( cgs.clientinfo[clientNum].color, le->color );
- }
- }
-
- //
- // impact mark
- //
- alphaFade = (mark == cgs.media.energyMarkShader); // plasma fades alpha, all others fade color
- if ( weapon == WP_RAILGUN ) {
- float *color;
-
- // colorize with client color
- color = cgs.clientinfo[clientNum].color;
- CG_ImpactMark( mark, origin, dir, random()*360, color[0],color[1], color[2],1, alphaFade, radius, qfalse );
- } else {
- CG_ImpactMark( mark, origin, dir, random()*360, 1,1,1,1, alphaFade, radius, qfalse );
- }
-}
-
-
-/*
-=================
-CG_MissileHitPlayer
-=================
-*/
-void CG_MissileHitPlayer( int weapon, vec3_t origin, vec3_t dir, int entityNum ) {
- CG_Bleed( origin, entityNum );
-
- // some weapons will make an explosion with the blood, while
- // others will just make the blood
- switch ( weapon ) {
- case WP_GRENADE_LAUNCHER:
- case WP_ROCKET_LAUNCHER:
- CG_MissileHitWall( weapon, 0, origin, dir, IMPACTSOUND_FLESH );
- break;
- default:
- break;
- }
-}
-
-
-
-/*
-============================================================================
-
-SHOTGUN TRACING
-
-============================================================================
-*/
-
-/*
-================
-CG_ShotgunPellet
-================
-*/
-static void CG_ShotgunPellet( vec3_t start, vec3_t end, int skipNum ) {
- trace_t tr;
- int sourceContentType, destContentType;
-
- CG_Trace( &tr, start, NULL, NULL, end, skipNum, MASK_SHOT );
-
- sourceContentType = trap_CM_PointContents( start, 0 );
- destContentType = trap_CM_PointContents( tr.endpos, 0 );
-
- // FIXME: should probably move this cruft into CG_BubbleTrail
- if ( sourceContentType == destContentType ) {
- if ( sourceContentType & CONTENTS_WATER ) {
- CG_BubbleTrail( start, tr.endpos, 32 );
- }
- } else if ( sourceContentType & CONTENTS_WATER ) {
- trace_t trace;
-
- trap_CM_BoxTrace( &trace, end, start, NULL, NULL, 0, CONTENTS_WATER );
- CG_BubbleTrail( start, trace.endpos, 32 );
- } else if ( destContentType & CONTENTS_WATER ) {
- trace_t trace;
-
- trap_CM_BoxTrace( &trace, start, end, NULL, NULL, 0, CONTENTS_WATER );
- CG_BubbleTrail( tr.endpos, trace.endpos, 32 );
- }
-
- if ( tr.surfaceFlags & SURF_NOIMPACT ) {
- return;
- }
-
- if ( cg_entities[tr.entityNum].currentState.eType == ET_PLAYER ) {
- CG_MissileHitPlayer( WP_SHOTGUN, tr.endpos, tr.plane.normal, tr.entityNum );
- } else {
- if ( tr.surfaceFlags & SURF_NOIMPACT ) {
- // SURF_NOIMPACT will not make a flame puff or a mark
- return;
- }
- if ( tr.surfaceFlags & SURF_METALSTEPS ) {
- CG_MissileHitWall( WP_SHOTGUN, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_METAL );
- } else {
- CG_MissileHitWall( WP_SHOTGUN, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_DEFAULT );
- }
- }
-}
-
-/*
-================
-CG_ShotgunPattern
-
-Perform the same traces the server did to locate the
-hit splashes (FIXME: ranom seed isn't synce anymore)
-================
-*/
-static void CG_ShotgunPattern( vec3_t origin, vec3_t origin2, int otherEntNum ) {
- int i;
- float r, u;
- vec3_t end;
- vec3_t forward, right, up;
-
- // 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 < DEFAULT_SHOTGUN_COUNT ; i++ ) {
- r = crandom() * DEFAULT_SHOTGUN_SPREAD * 16;
- u = crandom() * DEFAULT_SHOTGUN_SPREAD * 16;
- VectorMA( origin, 8192 * 16, forward, end);
- VectorMA (end, r, right, end);
- VectorMA (end, u, up, end);
-
- CG_ShotgunPellet( origin, end, otherEntNum );
- }
-}
-
-/*
-==============
-CG_ShotgunFire
-==============
-*/
-void CG_ShotgunFire( entityState_t *es ) {
- vec3_t v;
- int contents;
-
- VectorSubtract( es->origin2, es->pos.trBase, v );
- VectorNormalize( v );
- VectorScale( v, 32, v );
- VectorAdd( es->pos.trBase, v, v );
- if ( cgs.glconfig.hardwareType != GLHW_RAGEPRO ) {
- // ragepro can't alpha fade, so don't even bother with smoke
- vec3_t up;
-
- contents = trap_CM_PointContents( es->pos.trBase, 0 );
- if ( !( contents & CONTENTS_WATER ) ) {
- VectorSet( up, 0, 0, 8 );
- CG_SmokePuff( v, up, 32, 1, 1, 1, 0.33f, 900, cg.time, 0, LEF_PUFF_DONT_SCALE, cgs.media.shotgunSmokePuffShader );
- }
- }
- CG_ShotgunPattern( es->pos.trBase, es->origin2, es->otherEntityNum );
-}
-
-/*
-============================================================================
-
-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 ) {
- trace_t trace;
- int sourceContentType, destContentType;
- 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 ) ) {
- sourceContentType = trap_CM_PointContents( start, 0 );
- destContentType = trap_CM_PointContents( end, 0 );
-
- // do a complete bubble trail if necessary
- if ( ( sourceContentType == destContentType ) && ( sourceContentType & CONTENTS_WATER ) ) {
- CG_BubbleTrail( start, end, 32 );
- }
- // bubble trail from water into air
- else if ( ( sourceContentType & CONTENTS_WATER ) ) {
- trap_CM_BoxTrace( &trace, end, start, NULL, NULL, 0, CONTENTS_WATER );
- CG_BubbleTrail( start, trace.endpos, 32 );
- }
- // bubble trail from air into water
- else if ( ( destContentType & CONTENTS_WATER ) ) {
- trap_CM_BoxTrace( &trace, start, end, NULL, NULL, 0, CONTENTS_WATER );
- CG_BubbleTrail( trace.endpos, end, 32 );
- }
-
- // draw a tracer
- if ( random() < cg_tracerChance.value ) {
- CG_Tracer( start, end );
- }
- }
- }
-
- // impact splash and mark
- if ( flesh ) {
- CG_Bleed( end, fleshEntityNum );
- } else {
- CG_MissileHitWall( WP_MACHINEGUN, 0, end, normal, IMPACTSOUND_DEFAULT );
- }
-
-}