2001-12-31 16:16:59 +00:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// $Id$
|
|
|
|
//
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
2001-12-31 16:28:42 +00:00
|
|
|
// $Log$
|
2002-06-29 04:15:15 +00:00
|
|
|
// Revision 1.86 2002/06/29 04:15:15 jbravo
|
|
|
|
// CTF is now CTB. no weapons while the case is in hand other than pistol or knife
|
|
|
|
//
|
2002-06-23 04:36:27 +00:00
|
|
|
// Revision 1.85 2002/06/23 04:34:54 niceass
|
|
|
|
// change to foglaser
|
|
|
|
//
|
2002-06-21 04:11:34 +00:00
|
|
|
// Revision 1.84 2002/06/21 04:09:44 niceass
|
|
|
|
// fog laser
|
|
|
|
//
|
2002-06-17 03:53:31 +00:00
|
|
|
// Revision 1.83 2002/06/17 03:53:31 niceass
|
|
|
|
// m4 muzzle flash is smaller
|
|
|
|
//
|
2002-06-16 20:06:15 +00:00
|
|
|
// Revision 1.82 2002/06/16 20:06:13 jbravo
|
|
|
|
// Reindented all the source files with "indent -kr -ut -i8 -l120 -lc120 -sob -bad -bap"
|
|
|
|
//
|
2002-06-16 19:12:52 +00:00
|
|
|
// Revision 1.81 2002/06/16 19:12:52 jbravo
|
|
|
|
// Removed the MISSIONPACK ifdefs and missionpack only code.
|
|
|
|
//
|
2002-06-12 17:05:14 +00:00
|
|
|
// Revision 1.80 2002/06/12 17:05:14 slicer
|
|
|
|
// Fixed a couple of problems related to the sniper zooming
|
|
|
|
//
|
2002-06-11 21:50:51 +00:00
|
|
|
// Revision 1.79 2002/06/11 21:50:51 niceass
|
|
|
|
// HC changes
|
|
|
|
//
|
2002-06-06 00:29:14 +00:00
|
|
|
// Revision 1.78 2002/06/06 00:29:14 blaze
|
|
|
|
// got rid of the out of ammo shader
|
|
|
|
//
|
2002-06-05 09:40:10 +00:00
|
|
|
// Revision 1.77 2002/06/05 09:40:10 niceass
|
|
|
|
// tracer fix
|
|
|
|
//
|
2002-06-03 01:09:33 +00:00
|
|
|
// Revision 1.76 2002/06/03 01:09:33 niceass
|
|
|
|
// silencer scale changes
|
|
|
|
//
|
2002-05-29 03:52:21 +00:00
|
|
|
// Revision 1.75 2002/05/29 03:52:21 niceass
|
|
|
|
// LAM code
|
|
|
|
//
|
2002-05-27 17:47:19 +00:00
|
|
|
// Revision 1.74 2002/05/27 17:47:19 jbravo
|
|
|
|
// Fixes and cleanups
|
|
|
|
//
|
2002-05-27 06:58:40 +00:00
|
|
|
// Revision 1.73 2002/05/27 06:58:40 niceass
|
|
|
|
// removed reflection stuff. Silencer stuff added
|
|
|
|
//
|
2002-05-18 03:55:35 +00:00
|
|
|
// Revision 1.72 2002/05/18 03:55:35 niceass
|
|
|
|
// many misc. changes
|
|
|
|
//
|
2002-05-12 14:40:28 +00:00
|
|
|
// Revision 1.71 2002/05/12 14:39:48 makro
|
|
|
|
// Wood, brick & ceramic impact sounds
|
|
|
|
//
|
2002-05-09 06:45:14 +00:00
|
|
|
// Revision 1.70 2002/05/09 06:40:37 niceass
|
|
|
|
// New tracers
|
|
|
|
//
|
2002-05-01 17:46:00 +00:00
|
|
|
// Revision 1.69 2002/05/01 17:46:00 slicer
|
|
|
|
// Only calling "unzoom" when switching from ssg ( less lag )
|
|
|
|
//
|
2002-05-01 03:28:07 +00:00
|
|
|
// Revision 1.68 2002/05/01 03:28:07 niceass
|
|
|
|
// mp5 scale change for silencer
|
|
|
|
//
|
2002-04-29 06:10:09 +00:00
|
|
|
// Revision 1.67 2002/04/29 06:10:09 niceass
|
|
|
|
// visible silencer
|
|
|
|
//
|
2002-04-07 02:10:42 +00:00
|
|
|
// Revision 1.66 2002/04/07 02:10:42 niceass
|
|
|
|
// shell ejection bug fixed
|
|
|
|
//
|
2002-04-06 21:43:59 +00:00
|
|
|
// Revision 1.65 2002/04/06 21:43:59 makro
|
|
|
|
// New surfaceparm system
|
|
|
|
//
|
2002-04-05 18:53:26 +00:00
|
|
|
// Revision 1.64 2002/04/05 18:53:26 jbravo
|
|
|
|
// Warning fixes
|
|
|
|
//
|
2002-04-03 03:13:49 +00:00
|
|
|
// Revision 1.63 2002/04/03 03:13:49 blaze
|
|
|
|
// NEW BREAKABLE CODE - will break all old breakables(wont appear in maps)
|
|
|
|
//
|
2002-04-01 22:23:38 +00:00
|
|
|
// Revision 1.62 2002/04/01 22:23:38 slicer
|
|
|
|
// Added "weapon" command buffering
|
|
|
|
//
|
2002-03-31 13:52:48 +00:00
|
|
|
// Revision 1.61 2002/03/31 13:52:48 jbravo
|
|
|
|
// More cleanups
|
|
|
|
//
|
2002-03-31 03:31:24 +00:00
|
|
|
// Revision 1.60 2002/03/31 03:31:24 jbravo
|
|
|
|
// Compiler warning cleanups
|
|
|
|
//
|
2002-03-31 02:00:42 +00:00
|
|
|
// Revision 1.59 2002/03/31 02:00:42 niceass
|
|
|
|
// shell stuff
|
|
|
|
//
|
2002-03-24 22:46:23 +00:00
|
|
|
// Revision 1.58 2002/03/24 22:46:23 niceass
|
|
|
|
// shell ejection stuff/handcannon fix
|
|
|
|
//
|
2002-03-21 02:17:39 +00:00
|
|
|
// Revision 1.57 2002/03/21 02:17:39 blaze
|
|
|
|
// more func_explosive goodness
|
|
|
|
//
|
2002-03-21 00:26:46 +00:00
|
|
|
// Revision 1.56 2002/03/21 00:26:11 blaze
|
|
|
|
// some fixing of func_explosive
|
|
|
|
//
|
2002-03-18 19:19:08 +00:00
|
|
|
// Revision 1.55 2002/03/18 19:19:08 slicer
|
|
|
|
// Fixed bandage bugs ( i hope )
|
|
|
|
//
|
2002-03-16 21:50:09 +00:00
|
|
|
// Revision 1.54 2002/03/16 21:48:39 niceass
|
|
|
|
// All new shell ejection code
|
|
|
|
//
|
2002-03-13 18:41:18 +00:00
|
|
|
// Revision 1.53 2002/03/13 18:41:18 slicer
|
|
|
|
// Adjusted some of elder's unzoom code for the new sniper system ( server side )
|
|
|
|
//
|
2002-03-11 03:25:41 +00:00
|
|
|
// Revision 1.52 2002/03/11 03:25:41 jbravo
|
|
|
|
// Minor fix for NA
|
|
|
|
//
|
2002-03-11 02:22:45 +00:00
|
|
|
// Revision 1.51 2002/03/11 02:22:45 niceass
|
|
|
|
// tag shell ejections
|
|
|
|
//
|
2002-02-24 20:49:07 +00:00
|
|
|
// Revision 1.50 2002/02/24 20:49:07 slicer
|
|
|
|
// Follow Spect Players- Draws the gun
|
|
|
|
//
|
2002-02-23 18:07:46 +00:00
|
|
|
// Revision 1.49 2002/02/23 18:07:46 slicer
|
|
|
|
// Changed Sniper code and Cam code
|
|
|
|
//
|
2002-02-08 18:00:34 +00:00
|
|
|
// Revision 1.48 2002/02/08 18:00:34 jbravo
|
|
|
|
// Fixing "No newline at end of file" Warnings Linux keeps giving me
|
|
|
|
//
|
2002-01-14 01:19:23 +00:00
|
|
|
// Revision 1.47 2002/01/14 01:19:23 niceass
|
|
|
|
// No more default 800 gravity on items - NiceAss
|
|
|
|
//
|
2002-01-12 15:18:20 +00:00
|
|
|
// Revision 1.46 2002/01/12 15:18:20 jbravo
|
|
|
|
// Added a fix from Niceass. (cg_drawgun affecting other player models)
|
|
|
|
//
|
2002-01-11 19:48:33 +00:00
|
|
|
// Revision 1.45 2002/01/11 19:48:29 jbravo
|
|
|
|
// Formatted the source in non DOS format.
|
|
|
|
//
|
2001-12-31 16:28:42 +00:00
|
|
|
// Revision 1.44 2001/12/31 16:28:41 jbravo
|
|
|
|
// I made a Booboo with the Log tag.
|
|
|
|
//
|
2001-12-31 16:16:59 +00:00
|
|
|
//
|
|
|
|
//-----------------------------------------------------------------------------
|
2001-07-28 12:32:54 +00:00
|
|
|
// Copyright (C) 1999-2000 Id Software, Inc.
|
2001-05-06 20:50:27 +00:00
|
|
|
//
|
|
|
|
// cg_weapons.c -- events and effects dealing with weapons
|
|
|
|
#include "cg_local.h"
|
2001-09-11 00:11:00 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
==========================
|
|
|
|
CG_ParseWeaponSoundFile
|
|
|
|
|
|
|
|
Added by Elder
|
|
|
|
Reads information for frame-sound timing
|
|
|
|
==========================
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
static qboolean CG_ParseWeaponSoundFile(const char *filename, weaponInfo_t * weapon)
|
|
|
|
{
|
|
|
|
char *text_p;
|
|
|
|
int len;
|
|
|
|
int i;
|
|
|
|
char *token;
|
|
|
|
|
|
|
|
// float fps;
|
|
|
|
int skip; // Elder: What's this for?
|
|
|
|
char text[20000];
|
|
|
|
fileHandle_t f;
|
|
|
|
sfxWeapTiming_t *weapTiming;
|
2001-09-11 00:11:00 +00:00
|
|
|
|
2001-10-11 22:50:58 +00:00
|
|
|
weapTiming = weapon->animationSounds;
|
2001-09-11 00:11:00 +00:00
|
|
|
|
|
|
|
// load the file
|
2002-06-16 20:06:15 +00:00
|
|
|
len = trap_FS_FOpenFile(filename, &f, FS_READ);
|
|
|
|
if (len <= 0) {
|
2001-09-11 00:11:00 +00:00
|
|
|
return qfalse;
|
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
if (len >= sizeof(text) - 1) {
|
|
|
|
CG_Printf("File %s too long\n", filename);
|
2001-09-11 00:11:00 +00:00
|
|
|
return qfalse;
|
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
trap_FS_Read(text, len, f);
|
2001-09-11 00:11:00 +00:00
|
|
|
text[len] = 0;
|
2002-06-16 20:06:15 +00:00
|
|
|
trap_FS_FCloseFile(f);
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-09-11 00:11:00 +00:00
|
|
|
// parse the text
|
|
|
|
text_p = text;
|
|
|
|
// Elder: uhh, what was this for?
|
2002-06-16 20:06:15 +00:00
|
|
|
skip = 0; // quite the compiler warning
|
2001-10-11 22:50:58 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
for (i = 0; i < MAX_ANIM_SOUNDS; i++) {
|
2001-10-11 22:50:58 +00:00
|
|
|
// Grab frame number
|
2002-06-16 20:06:15 +00:00
|
|
|
token = COM_Parse(&text_p);
|
|
|
|
if (!token)
|
|
|
|
break;
|
2001-10-11 22:50:58 +00:00
|
|
|
// Add it to the array
|
2002-06-16 20:06:15 +00:00
|
|
|
if (atoi(token)) {
|
2001-11-11 07:23:16 +00:00
|
|
|
//Com_Printf("(%i): %s\n", i, token);
|
2001-10-11 22:50:58 +00:00
|
|
|
weapTiming->sfxInfo[i].frame = atoi(token);
|
2002-06-16 20:06:15 +00:00
|
|
|
} else
|
2001-10-11 22:50:58 +00:00
|
|
|
break;
|
2002-06-16 20:06:15 +00:00
|
|
|
//return qfalse;
|
2001-10-11 22:50:58 +00:00
|
|
|
|
|
|
|
// Grab sound file path
|
2002-06-16 20:06:15 +00:00
|
|
|
token = COM_Parse(&text_p);
|
|
|
|
if (!token)
|
|
|
|
break;
|
|
|
|
//return qfalse;
|
2001-10-11 22:50:58 +00:00
|
|
|
|
2001-11-11 07:23:16 +00:00
|
|
|
//Com_Printf("(%i): %s\n", i, token);
|
2002-06-16 20:06:15 +00:00
|
|
|
weapTiming->sfxInfo[i].sound = trap_S_RegisterSound(token, qfalse);
|
2001-10-11 22:50:58 +00:00
|
|
|
}
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-10-11 22:50:58 +00:00
|
|
|
// Store total number
|
|
|
|
weapTiming->numFrames = i;
|
2001-11-11 07:23:16 +00:00
|
|
|
//Com_Printf("Total Frames: %i\n", weapTiming->numFrames);
|
2001-10-11 22:50:58 +00:00
|
|
|
|
|
|
|
return qtrue;
|
2001-09-11 00:11:00 +00:00
|
|
|
}
|
|
|
|
|
2002-05-18 03:55:35 +00:00
|
|
|
/*
|
|
|
|
======================
|
|
|
|
CG_CalcMuzzlePoint
|
|
|
|
======================
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
static qboolean CG_CalcMuzzlePoint(int entityNum, vec3_t muzzle)
|
|
|
|
{
|
|
|
|
vec3_t forward;
|
|
|
|
centity_t *cent;
|
|
|
|
int anim;
|
2002-05-18 03:55:35 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (entityNum == cg.snap->ps.clientNum) {
|
|
|
|
VectorCopy(cg.snap->ps.origin, muzzle);
|
2002-05-18 03:55:35 +00:00
|
|
|
muzzle[2] += cg.snap->ps.viewheight;
|
2002-06-16 20:06:15 +00:00
|
|
|
AngleVectors(cg.snap->ps.viewangles, forward, NULL, NULL);
|
|
|
|
VectorMA(muzzle, 14, forward, muzzle);
|
2002-05-18 03:55:35 +00:00
|
|
|
return qtrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
cent = &cg_entities[entityNum];
|
2002-06-16 20:06:15 +00:00
|
|
|
if (!cent->currentValid) {
|
2002-05-18 03:55:35 +00:00
|
|
|
return qfalse;
|
|
|
|
}
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorCopy(cent->currentState.pos.trBase, muzzle);
|
2002-05-18 03:55:35 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
AngleVectors(cent->currentState.apos.trBase, forward, NULL, NULL);
|
2002-05-18 03:55:35 +00:00
|
|
|
anim = cent->currentState.legsAnim & ~ANIM_TOGGLEBIT;
|
2002-06-16 20:06:15 +00:00
|
|
|
if (anim == LEGS_WALKCR || anim == LEGS_IDLECR) {
|
2002-05-18 03:55:35 +00:00
|
|
|
muzzle[2] += CROUCH_VIEWHEIGHT;
|
|
|
|
} else {
|
|
|
|
muzzle[2] += DEFAULT_VIEWHEIGHT;
|
|
|
|
}
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorMA(muzzle, 14, forward, muzzle);
|
2002-05-18 03:55:35 +00:00
|
|
|
|
|
|
|
return qtrue;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2001-07-28 02:49:18 +00:00
|
|
|
/* [QUARANTINE] - Weapon Animations - CG_ParseWeaponAnimFile
|
|
|
|
==========================
|
|
|
|
CG_ParseWeaponAnimFile
|
|
|
|
==========================
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
static qboolean CG_ParseWeaponAnimFile(const char *filename, weaponInfo_t * weapon)
|
2001-09-16 04:04:31 +00:00
|
|
|
{
|
2001-07-28 12:32:54 +00:00
|
|
|
char *text_p;
|
|
|
|
int len;
|
|
|
|
int i;
|
2001-09-16 04:04:31 +00:00
|
|
|
int skip;
|
2001-07-28 12:32:54 +00:00
|
|
|
char *token;
|
|
|
|
float fps;
|
|
|
|
char text[20000];
|
|
|
|
fileHandle_t f;
|
|
|
|
animation_t *animations;
|
|
|
|
|
|
|
|
animations = weapon->animations;
|
|
|
|
|
|
|
|
// load the file
|
2002-06-16 20:06:15 +00:00
|
|
|
len = trap_FS_FOpenFile(filename, &f, FS_READ);
|
|
|
|
if (len <= 0) {
|
2001-07-28 12:32:54 +00:00
|
|
|
return qfalse;
|
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
if (len >= sizeof(text) - 1) {
|
|
|
|
CG_Printf("File %s too long\n", filename);
|
2001-07-28 12:32:54 +00:00
|
|
|
return qfalse;
|
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
trap_FS_Read(text, len, f);
|
2001-07-28 12:32:54 +00:00
|
|
|
text[len] = 0;
|
2002-06-16 20:06:15 +00:00
|
|
|
trap_FS_FCloseFile(f);
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-07-28 12:32:54 +00:00
|
|
|
// parse the text
|
|
|
|
text_p = text;
|
2002-06-16 20:06:15 +00:00
|
|
|
skip = 0; // quite the compiler warning
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-07-28 12:32:54 +00:00
|
|
|
// read information for each frame
|
2002-06-16 20:06:15 +00:00
|
|
|
for (i = 0; i < MAX_WEAPON_ANIMATIONS; i++) {
|
|
|
|
token = COM_Parse(&text_p);
|
|
|
|
if (!token)
|
|
|
|
break;
|
|
|
|
animations[i].firstFrame = atoi(token);
|
|
|
|
token = COM_Parse(&text_p);
|
|
|
|
if (!token)
|
|
|
|
break;
|
|
|
|
animations[i].numFrames = atoi(token);
|
|
|
|
token = COM_Parse(&text_p);
|
|
|
|
if (!token)
|
|
|
|
break;
|
|
|
|
animations[i].loopFrames = atoi(token);
|
|
|
|
token = COM_Parse(&text_p);
|
|
|
|
if (!token)
|
|
|
|
break;
|
|
|
|
fps = atof(token);
|
|
|
|
if (fps == 0)
|
|
|
|
fps = 1;
|
2001-07-28 12:32:54 +00:00
|
|
|
animations[i].frameLerp = 1000 / fps;
|
|
|
|
animations[i].initialLerp = 1000 / fps;
|
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
if (i != MAX_WEAPON_ANIMATIONS) {
|
|
|
|
CG_Printf("Error parsing weapon animation file: %s", filename);
|
2001-07-28 12:32:54 +00:00
|
|
|
return qfalse;
|
2001-11-11 20:03:09 +00:00
|
|
|
}
|
2001-07-28 02:49:18 +00:00
|
|
|
|
2001-07-28 12:32:54 +00:00
|
|
|
return qtrue;
|
2001-07-28 02:49:18 +00:00
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
|
2001-07-28 02:49:18 +00:00
|
|
|
// END
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
==========================
|
|
|
|
CG_MachineGunEjectBrass
|
|
|
|
==========================
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
localEntity_t *CG_MachineGunEjectBrass(centity_t * cent)
|
|
|
|
{
|
|
|
|
localEntity_t *le;
|
|
|
|
refEntity_t *re;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
// vec3_t velocity, xvelocity;
|
|
|
|
// vec3_t offset, xoffset;
|
|
|
|
// float waterScale = 1.0f;
|
|
|
|
// vec3_t v[3];
|
|
|
|
|
|
|
|
if (cg_brassTime.integer <= 0) {
|
2002-03-11 02:22:45 +00:00
|
|
|
return NULL;
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
le = CG_AllocLocalEntity();
|
|
|
|
re = &le->refEntity;
|
|
|
|
|
|
|
|
le->leType = LE_FRAGMENT;
|
|
|
|
le->startTime = cg.time;
|
2002-06-16 20:06:15 +00:00
|
|
|
le->endTime = le->startTime + cg_brassTime.integer + (cg_brassTime.integer / 4) * random();
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
le->pos.trType = TR_GRAVITY;
|
2002-06-16 20:06:15 +00:00
|
|
|
le->pos.trTime = cg.time - (rand() & 15);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
AxisCopy(axisDefault, re->axis);
|
2002-03-11 02:22:45 +00:00
|
|
|
|
2002-03-16 21:50:09 +00:00
|
|
|
le->bounceFactor = 0.5;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cent->currentState.weapon == WP_M4 || cent->currentState.weapon == WP_SSG3000) {
|
2002-06-11 21:50:51 +00:00
|
|
|
re->hModel = cgs.media.largeBrassModel;
|
|
|
|
le->bounceFactor *= 0.75;
|
2002-06-16 20:06:15 +00:00
|
|
|
} else
|
2002-06-11 21:50:51 +00:00
|
|
|
re->hModel = cgs.media.machinegunBrassModel;
|
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
le->angles.trType = TR_LINEAR;
|
|
|
|
le->angles.trTime = cg.time;
|
2002-03-11 02:22:45 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
le->angles.trDelta[0] = rand() % 200 - 100;
|
|
|
|
le->angles.trDelta[1] = rand() % 200 - 100;
|
|
|
|
le->angles.trDelta[2] = rand() % 200 - 100;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
le->leFlags = LEF_TUMBLE;
|
|
|
|
le->leBounceSoundType = LEBS_BRASS;
|
|
|
|
le->leMarkType = LEMT_NONE;
|
2002-03-11 02:22:45 +00:00
|
|
|
return le;
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==========================
|
|
|
|
CG_ShotgunEjectBrass
|
|
|
|
==========================
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
localEntity_t *CG_ShotgunEjectBrass(centity_t * cent)
|
|
|
|
{
|
|
|
|
localEntity_t *le;
|
|
|
|
refEntity_t *re;
|
|
|
|
int isHC;
|
|
|
|
|
|
|
|
// vec3_t velocity, xvelocity;
|
|
|
|
// vec3_t offset, xoffset;
|
|
|
|
// vec3_t v[3];
|
|
|
|
// int i;//, isHC;
|
|
|
|
// float waterScale = 1.0f;
|
2002-03-11 02:22:45 +00:00
|
|
|
|
2002-06-11 21:50:51 +00:00
|
|
|
if (cent->currentState.weapon == WP_HANDCANNON)
|
2002-06-16 20:06:15 +00:00
|
|
|
isHC = 1;
|
2002-06-11 21:50:51 +00:00
|
|
|
else
|
2002-06-16 20:06:15 +00:00
|
|
|
isHC = 0;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg_brassTime.integer <= 0) {
|
2002-03-11 02:22:45 +00:00
|
|
|
return NULL;
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
2002-03-24 22:46:23 +00:00
|
|
|
//for ( i = 0; i < isHC + 1; i++ ) {
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
le = CG_AllocLocalEntity();
|
|
|
|
re = &le->refEntity;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
le->leType = LE_FRAGMENT;
|
|
|
|
le->startTime = cg.time;
|
|
|
|
le->endTime = le->startTime + cg_brassTime.integer * 3 + cg_brassTime.integer * random();
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
le->pos.trType = TR_GRAVITY;
|
|
|
|
le->pos.trTime = cg.time;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
AxisCopy(axisDefault, re->axis);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (isHC)
|
|
|
|
re->hModel = cgs.media.HCBrassModel;
|
|
|
|
else
|
|
|
|
re->hModel = cgs.media.shotgunBrassModel;
|
2002-06-11 21:50:51 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
le->bounceFactor = 0.3f;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
le->angles.trType = TR_LINEAR;
|
|
|
|
le->angles.trTime = cg.time;
|
2002-03-16 21:50:09 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
le->angles.trDelta[0] = rand() % 200 - 100;
|
|
|
|
le->angles.trDelta[1] = rand() % 200 - 100;
|
|
|
|
le->angles.trDelta[2] = rand() % 200 - 100;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
le->leFlags = LEF_TUMBLE;
|
|
|
|
le->leBounceSoundType = LEBS_BRASS;
|
|
|
|
le->leMarkType = LEMT_NONE;
|
2002-03-24 22:46:23 +00:00
|
|
|
//}
|
2002-03-11 02:22:45 +00:00
|
|
|
return le;
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==========================
|
|
|
|
CG_RailTrail
|
|
|
|
==========================
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_RailTrail(clientInfo_t * ci, vec3_t start, vec3_t end)
|
|
|
|
{
|
2001-08-01 21:07:48 +00:00
|
|
|
vec3_t axis[36], move, move2, next_move, vec, temp;
|
2002-06-16 20:06:15 +00:00
|
|
|
float len;
|
|
|
|
int i, j, skip;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
localEntity_t *le;
|
|
|
|
refEntity_t *re;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2001-08-01 21:07:48 +00:00
|
|
|
#define RADIUS 4
|
|
|
|
#define ROTATION 1
|
|
|
|
#define SPACING 5
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-08-01 21:07:48 +00:00
|
|
|
start[2] -= 4;
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorCopy(start, move);
|
|
|
|
VectorSubtract(end, start, vec);
|
|
|
|
len = VectorNormalize(vec);
|
2001-08-01 21:07:48 +00:00
|
|
|
PerpendicularVector(temp, vec);
|
2002-06-16 20:06:15 +00:00
|
|
|
for (i = 0; i < 36; i++) {
|
|
|
|
RotatePointAroundVector(axis[i], vec, temp, i * 10); //banshee 2.4 was 10
|
2001-08-01 21:07:48 +00:00
|
|
|
}
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
le = CG_AllocLocalEntity();
|
|
|
|
re = &le->refEntity;
|
|
|
|
|
|
|
|
le->leType = LE_FADE_RGB;
|
|
|
|
le->startTime = cg.time;
|
|
|
|
le->endTime = cg.time + cg_railTrailTime.value;
|
2002-06-16 20:06:15 +00:00
|
|
|
le->lifeRate = 1.0 / (le->endTime - le->startTime);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
re->shaderTime = cg.time / 1000.0f;
|
2001-08-01 21:07:48 +00:00
|
|
|
re->reType = RT_RAIL_CORE;
|
|
|
|
re->customShader = cgs.media.railCoreShader;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorCopy(start, re->origin);
|
|
|
|
VectorCopy(end, re->oldorigin);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2001-08-01 21:07:48 +00:00
|
|
|
re->shaderRGBA[0] = ci->color1[0] * 255;
|
2002-06-16 20:06:15 +00:00
|
|
|
re->shaderRGBA[1] = ci->color1[1] * 255;
|
|
|
|
re->shaderRGBA[2] = ci->color1[2] * 255;
|
|
|
|
re->shaderRGBA[3] = 255;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2001-08-01 21:07:48 +00:00
|
|
|
le->color[0] = ci->color1[0] * 0.75;
|
|
|
|
le->color[1] = ci->color1[1] * 0.75;
|
|
|
|
le->color[2] = ci->color1[2] * 0.75;
|
2001-05-06 20:50:27 +00:00
|
|
|
le->color[3] = 1.0f;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
AxisClear(re->axis);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2001-08-01 21:07:48 +00:00
|
|
|
VectorMA(move, 20, vec, move);
|
|
|
|
VectorCopy(move, next_move);
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorScale(vec, SPACING, vec);
|
2001-08-01 21:07:48 +00:00
|
|
|
|
|
|
|
if (cg_oldRail.integer != 0) {
|
|
|
|
// nudge down a bit so it isn't exactly in center
|
|
|
|
re->origin[2] -= 8;
|
|
|
|
re->oldorigin[2] -= 8;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
skip = -1;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-08-01 21:07:48 +00:00
|
|
|
j = 18;
|
2002-06-16 20:06:15 +00:00
|
|
|
for (i = 0; i < len; i += SPACING) {
|
2001-08-01 21:07:48 +00:00
|
|
|
if (i != skip) {
|
|
|
|
skip = i + SPACING;
|
2002-06-16 20:06:15 +00:00
|
|
|
le = CG_AllocLocalEntity();
|
|
|
|
re = &le->refEntity;
|
|
|
|
le->leFlags = LEF_PUFF_DONT_SCALE;
|
2001-08-01 21:07:48 +00:00
|
|
|
le->leType = LE_MOVE_SCALE_FADE;
|
2002-06-16 20:06:15 +00:00
|
|
|
le->startTime = cg.time;
|
|
|
|
le->endTime = cg.time + (i >> 1) + 600;
|
|
|
|
le->lifeRate = 1.0 / (le->endTime - le->startTime);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
re->shaderTime = cg.time / 1000.0f;
|
|
|
|
re->reType = RT_SPRITE;
|
|
|
|
re->radius = 1.1f;
|
2001-08-01 21:07:48 +00:00
|
|
|
re->customShader = cgs.media.railRingsShader;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
re->shaderRGBA[0] = ci->color2[0] * 255;
|
|
|
|
re->shaderRGBA[1] = ci->color2[1] * 255;
|
|
|
|
re->shaderRGBA[2] = ci->color2[2] * 255;
|
|
|
|
re->shaderRGBA[3] = 255;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
le->color[0] = ci->color2[0] * 0.75;
|
|
|
|
le->color[1] = ci->color2[1] * 0.75;
|
|
|
|
le->color[2] = ci->color2[2] * 0.75;
|
|
|
|
le->color[3] = 1.0f;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
le->pos.trType = TR_LINEAR;
|
|
|
|
le->pos.trTime = cg.time;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorCopy(move, move2);
|
|
|
|
VectorMA(move2, RADIUS, axis[j], move2);
|
|
|
|
VectorCopy(move2, le->pos.trBase);
|
2001-08-01 21:07:48 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
le->pos.trDelta[0] = axis[j][0] * 6;
|
|
|
|
le->pos.trDelta[1] = axis[j][1] * 6;
|
|
|
|
le->pos.trDelta[2] = axis[j][2] * 6;
|
2001-08-01 21:07:48 +00:00
|
|
|
}
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorAdd(move, vec, move);
|
2001-08-01 21:07:48 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
j = j + ROTATION < 36 ? j + ROTATION : (j + ROTATION) % 36;
|
2001-08-01 21:07:48 +00:00
|
|
|
}
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==========================
|
|
|
|
CG_RocketTrail
|
|
|
|
==========================
|
|
|
|
*/
|
2002-03-31 03:31:24 +00:00
|
|
|
// JBravo: not used
|
|
|
|
/*
|
2001-05-06 20:50:27 +00:00
|
|
|
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;
|
|
|
|
|
2001-08-01 21:07:48 +00:00
|
|
|
if ( cg_noProjectileTrail.integer ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
up[0] = 0;
|
|
|
|
up[1] = 0;
|
|
|
|
up[2] = 0;
|
|
|
|
|
|
|
|
step = 50;
|
|
|
|
|
|
|
|
es = &ent->currentState;
|
|
|
|
startTime = ent->trailTime;
|
|
|
|
t = step * ( (startTime + step) / step );
|
|
|
|
|
2002-01-14 01:19:23 +00:00
|
|
|
CG_EvaluateTrajectory( &es->pos, cg.time, origin );
|
2001-05-06 20:50:27 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2002-01-14 01:19:23 +00:00
|
|
|
CG_EvaluateTrajectory( &es->pos, ent->trailTime, lastPos );
|
2001-05-06 20:50:27 +00:00
|
|
|
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 ) {
|
2002-01-14 01:19:23 +00:00
|
|
|
CG_EvaluateTrajectory( &es->pos, t, lastPos );
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2001-11-11 20:03:09 +00:00
|
|
|
smoke = CG_SmokePuff( lastPos, up,
|
|
|
|
wi->trailRadius,
|
2001-05-06 20:50:27 +00:00
|
|
|
1, 1, 1, 0.33f,
|
2001-11-11 20:03:09 +00:00
|
|
|
wi->wiTrailTime,
|
2001-05-06 20:50:27 +00:00
|
|
|
t,
|
|
|
|
0,
|
2001-11-11 20:03:09 +00:00
|
|
|
0,
|
2001-05-06 20:50:27 +00:00
|
|
|
cgs.media.smokePuffShader );
|
|
|
|
// use the optimized local entity add
|
|
|
|
smoke->leType = LE_SCALE_FADE;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2002-03-31 03:31:24 +00:00
|
|
|
*/
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2001-08-01 21:07:48 +00:00
|
|
|
/*
|
|
|
|
==========================
|
|
|
|
CG_NailTrail
|
|
|
|
==========================
|
|
|
|
*/
|
2002-03-31 03:31:24 +00:00
|
|
|
// JBravo: apparently not used.
|
|
|
|
/*
|
2001-08-01 21:07:48 +00:00
|
|
|
static void CG_PlasmaTrail( centity_t *cent, const weaponInfo_t *wi ) {
|
|
|
|
localEntity_t *le;
|
|
|
|
refEntity_t *re;
|
|
|
|
entityState_t *es;
|
|
|
|
vec3_t velocity, xvelocity, origin;
|
|
|
|
vec3_t offset, xoffset;
|
|
|
|
vec3_t v[3];
|
|
|
|
int t, startTime, step;
|
|
|
|
|
|
|
|
float waterScale = 1.0f;
|
|
|
|
|
|
|
|
if ( cg_noProjectileTrail.integer || cg_oldPlasma.integer ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
step = 50;
|
|
|
|
|
|
|
|
es = ¢->currentState;
|
|
|
|
startTime = cent->trailTime;
|
|
|
|
t = step * ( (startTime + step) / step );
|
|
|
|
|
2002-01-14 01:19:23 +00:00
|
|
|
CG_EvaluateTrajectory( &es->pos, cg.time, origin );
|
2001-08-01 21:07:48 +00:00
|
|
|
|
|
|
|
le = CG_AllocLocalEntity();
|
|
|
|
re = &le->refEntity;
|
|
|
|
|
|
|
|
velocity[0] = 60 - 120 * crandom();
|
|
|
|
velocity[1] = 40 - 80 * crandom();
|
|
|
|
velocity[2] = 100 - 200 * crandom();
|
|
|
|
|
|
|
|
le->leType = LE_MOVE_SCALE_FADE;
|
|
|
|
le->leFlags = LEF_TUMBLE;
|
|
|
|
le->leBounceSoundType = LEBS_NONE;
|
|
|
|
le->leMarkType = LEMT_NONE;
|
|
|
|
|
|
|
|
le->startTime = cg.time;
|
|
|
|
le->endTime = le->startTime + 600;
|
|
|
|
|
|
|
|
le->pos.trType = TR_GRAVITY;
|
|
|
|
le->pos.trTime = cg.time;
|
|
|
|
|
|
|
|
AnglesToAxis( cent->lerpAngles, v );
|
|
|
|
|
|
|
|
offset[0] = 2;
|
|
|
|
offset[1] = 2;
|
|
|
|
offset[2] = 2;
|
|
|
|
|
|
|
|
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( origin, 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->shaderTime = cg.time / 1000.0f;
|
|
|
|
re->reType = RT_SPRITE;
|
|
|
|
re->radius = 0.25f;
|
|
|
|
re->customShader = cgs.media.railRingsShader;
|
|
|
|
le->bounceFactor = 0.3f;
|
|
|
|
|
|
|
|
re->shaderRGBA[0] = wi->flashDlightColor[0] * 63;
|
|
|
|
re->shaderRGBA[1] = wi->flashDlightColor[1] * 63;
|
|
|
|
re->shaderRGBA[2] = wi->flashDlightColor[2] * 63;
|
|
|
|
re->shaderRGBA[3] = 63;
|
|
|
|
|
|
|
|
le->color[0] = wi->flashDlightColor[0] * 0.2;
|
|
|
|
le->color[1] = wi->flashDlightColor[1] * 0.2;
|
|
|
|
le->color[2] = wi->flashDlightColor[2] * 0.2;
|
|
|
|
le->color[3] = 0.25f;
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
}
|
2002-03-31 03:31:24 +00:00
|
|
|
*/
|
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
/*
|
|
|
|
==========================
|
|
|
|
CG_GrappleTrail
|
|
|
|
==========================
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_GrappleTrail(centity_t * ent, const weaponInfo_t * wi)
|
|
|
|
{
|
|
|
|
vec3_t origin;
|
|
|
|
entityState_t *es;
|
|
|
|
vec3_t forward, up;
|
|
|
|
refEntity_t beam;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
es = &ent->currentState;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_EvaluateTrajectory(&es->pos, cg.time, origin);
|
2001-05-06 20:50:27 +00:00
|
|
|
ent->trailTime = cg.time;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
memset(&beam, 0, sizeof(beam));
|
2001-05-06 20:50:27 +00:00
|
|
|
//FIXME adjust for muzzle position
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorCopy(cg_entities[ent->currentState.otherEntityNum].lerpOrigin, beam.origin);
|
2001-05-06 20:50:27 +00:00
|
|
|
beam.origin[2] += 26;
|
2002-06-16 20:06:15 +00:00
|
|
|
AngleVectors(cg_entities[ent->currentState.otherEntityNum].lerpAngles, forward, NULL, up);
|
|
|
|
VectorMA(beam.origin, -6, up, beam.origin);
|
|
|
|
VectorCopy(origin, beam.oldorigin);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (Distance(beam.origin, beam.oldorigin) < 64)
|
|
|
|
return; // Don't draw if close
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
beam.reType = RT_LIGHTNING;
|
|
|
|
beam.customShader = cgs.media.lightningShader;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
AxisClear(beam.axis);
|
2001-05-06 20:50:27 +00:00
|
|
|
beam.shaderRGBA[0] = 0xff;
|
|
|
|
beam.shaderRGBA[1] = 0xff;
|
|
|
|
beam.shaderRGBA[2] = 0xff;
|
|
|
|
beam.shaderRGBA[3] = 0xff;
|
2002-06-16 20:06:15 +00:00
|
|
|
trap_R_AddRefEntityToScene(&beam);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==========================
|
|
|
|
CG_GrenadeTrail
|
2002-03-31 03:31:24 +00:00
|
|
|
JBravo: not used
|
2001-05-06 20:50:27 +00:00
|
|
|
==========================
|
|
|
|
*/
|
2002-03-31 03:31:24 +00:00
|
|
|
/*
|
2001-05-06 20:50:27 +00:00
|
|
|
static void CG_GrenadeTrail( centity_t *ent, const weaponInfo_t *wi ) {
|
2001-08-01 21:07:48 +00:00
|
|
|
CG_RocketTrail( ent, wi );
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
2002-03-31 03:31:24 +00:00
|
|
|
*/
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
CG_RegisterWeapon
|
|
|
|
|
|
|
|
The server says this item is used on this level
|
|
|
|
=================
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_RegisterWeapon(int weaponNum)
|
|
|
|
{
|
|
|
|
weaponInfo_t *weaponInfo;
|
|
|
|
gitem_t *item, *ammo;
|
|
|
|
char path[MAX_QPATH];
|
|
|
|
vec3_t mins, maxs;
|
|
|
|
|
2001-07-28 02:49:18 +00:00
|
|
|
// QUARANTINE - Weapon Animations - Added Variable
|
2002-06-16 20:06:15 +00:00
|
|
|
char filename[MAX_QPATH]; //Used to open animation.cfg files
|
|
|
|
|
2001-07-28 02:49:18 +00:00
|
|
|
// END
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
int i;
|
|
|
|
qboolean weapAnimLoad = qtrue;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
weaponInfo = &cg_weapons[weaponNum];
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (weaponNum == 0) {
|
2001-05-06 20:50:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (weaponInfo->registered) {
|
2001-05-06 20:50:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
memset(weaponInfo, 0, sizeof(*weaponInfo));
|
2001-05-06 20:50:27 +00:00
|
|
|
weaponInfo->registered = qtrue;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
for (item = bg_itemlist + 1; item->classname; item++) {
|
|
|
|
if (item->giType == IT_WEAPON && item->giTag == weaponNum) {
|
2001-05-06 20:50:27 +00:00
|
|
|
weaponInfo->item = item;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
if (!item->classname) {
|
|
|
|
CG_Error("Couldn't find weapon %i", weaponNum);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_RegisterItemVisuals(item - bg_itemlist);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
// load cmodel before model so filecache works
|
2002-06-16 20:06:15 +00:00
|
|
|
weaponInfo->weaponModel = trap_R_RegisterModel(item->world_model[0]);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
// calc midpoint for rotation
|
2002-06-16 20:06:15 +00:00
|
|
|
trap_R_ModelBounds(weaponInfo->weaponModel, mins, maxs);
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
weaponInfo->weaponMidpoint[i] = mins[i] + 0.5 * (maxs[i] - mins[i]);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
weaponInfo->weaponIcon = trap_R_RegisterShader(item->icon);
|
|
|
|
weaponInfo->ammoIcon = trap_R_RegisterShader(item->icon);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
for (ammo = bg_itemlist + 1; ammo->classname; ammo++) {
|
|
|
|
if (ammo->giType == IT_AMMO && ammo->giTag == weaponNum) {
|
2001-05-06 20:50:27 +00:00
|
|
|
break;
|
|
|
|
}
|
2001-07-24 01:49:02 +00:00
|
|
|
//Elder: hack for handcannon to use M3 ammo icon
|
2002-06-16 20:06:15 +00:00
|
|
|
else if (weaponNum == WP_HANDCANNON && ammo->giType == IT_AMMO && ammo->giTag == WP_M3) {
|
2001-07-24 01:49:02 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
//Elder: hack for akimbos to use MK23 ammo icon
|
2002-06-16 20:06:15 +00:00
|
|
|
else if (weaponNum == WP_AKIMBO && ammo->giType == IT_AMMO && ammo->giTag == WP_PISTOL) {
|
2001-07-24 01:49:02 +00:00
|
|
|
break;
|
|
|
|
}
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
if (ammo->classname && ammo->world_model[0]) {
|
|
|
|
weaponInfo->ammoModel = trap_R_RegisterModel(ammo->world_model[0]);
|
2001-07-24 01:49:02 +00:00
|
|
|
//Elder: added
|
2002-06-16 20:06:15 +00:00
|
|
|
weaponInfo->ammoIcon = trap_R_RegisterShader(ammo->icon);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
strcpy(path, item->world_model[0]);
|
|
|
|
COM_StripExtension(path, path);
|
|
|
|
strcat(path, "_flash.md3");
|
|
|
|
weaponInfo->flashModel = trap_R_RegisterModel(path);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
strcpy(path, item->world_model[0]);
|
|
|
|
COM_StripExtension(path, path);
|
|
|
|
strcat(path, "_barrel.md3");
|
|
|
|
weaponInfo->barrelModel = trap_R_RegisterModel(path);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
strcpy(path, item->world_model[0]);
|
|
|
|
COM_StripExtension(path, path);
|
|
|
|
strcat(path, "_hand.md3");
|
|
|
|
weaponInfo->handsModel = trap_R_RegisterModel(path);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2001-08-06 19:15:00 +00:00
|
|
|
//Elder: added to cache 1st-person models
|
2002-06-16 20:06:15 +00:00
|
|
|
strcpy(path, item->world_model[0]);
|
|
|
|
COM_StripExtension(path, path);
|
|
|
|
strcat(path, "_1st.md3");
|
|
|
|
weaponInfo->firstModel = trap_R_RegisterModel(path);
|
2001-06-08 04:35:50 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (!weaponInfo->handsModel) {
|
|
|
|
weaponInfo->handsModel = trap_R_RegisterModel("models/weapons2/shotgun/shotgun_hand.md3");
|
2001-06-08 04:35:50 +00:00
|
|
|
}
|
2001-07-09 00:32:10 +00:00
|
|
|
//Elder: if no _1st model, point to the weaponModel... this may get funky :)
|
2002-06-16 20:06:15 +00:00
|
|
|
if (!weaponInfo->firstModel) {
|
2001-08-18 20:01:21 +00:00
|
|
|
// Added warning message
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_Printf(" ^3Warning: %s first-person model not found; using world model^7\n",
|
|
|
|
weaponInfo->item->pickup_name);
|
2001-07-09 00:32:10 +00:00
|
|
|
weaponInfo->firstModel = weaponInfo->weaponModel;
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
weaponInfo->loopFireSound = qfalse;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
switch (weaponNum) {
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
//Blaze: Reaction Pistol
|
2001-05-06 20:50:27 +00:00
|
|
|
case WP_PISTOL:
|
2002-06-16 20:06:15 +00:00
|
|
|
MAKERGB(weaponInfo->flashDlightColor, 1, 1, 0);
|
|
|
|
weaponInfo->flashSound[0] = trap_S_RegisterSound("sound/weapons/mk23/mk23fire.wav", qfalse);
|
|
|
|
weaponInfo->worldReloadSound[0] = trap_S_RegisterSound("sound/weapons/mk23/mk23reload.wav", qfalse);
|
2001-05-06 20:50:27 +00:00
|
|
|
weaponInfo->ejectBrassFunc = CG_MachineGunEjectBrass;
|
2002-06-16 20:06:15 +00:00
|
|
|
cgs.media.bulletExplosionShader = trap_R_RegisterShader("bulletExplosion");
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-09-11 00:11:00 +00:00
|
|
|
// Load the animation information
|
2002-06-16 20:06:15 +00:00
|
|
|
Com_sprintf(filename, sizeof(filename), "models/weapons2/mk23/animation.cfg");
|
|
|
|
if (!CG_ParseWeaponAnimFile(filename, weaponInfo)) {
|
2001-07-28 02:49:18 +00:00
|
|
|
Com_Printf("Failed to load weapon animation file %s\n", filename);
|
2001-09-11 00:11:00 +00:00
|
|
|
weapAnimLoad = qfalse;
|
|
|
|
}
|
|
|
|
// Load sound information -- ALWAYS DO THIS AFTER THE ANIMATION
|
2002-06-16 20:06:15 +00:00
|
|
|
if (weapAnimLoad) {
|
|
|
|
Com_sprintf(filename, sizeof(filename), "models/weapons2/mk23/sound.cfg");
|
|
|
|
if (!CG_ParseWeaponSoundFile(filename, weaponInfo)) {
|
2001-09-11 00:11:00 +00:00
|
|
|
Com_Printf("Failed to load weapon sound file %s\n", filename);
|
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
} else {
|
2001-09-11 00:11:00 +00:00
|
|
|
Com_Printf("Could not load sound.cfg because animation.cfg loading failed\n");
|
2001-07-28 02:49:18 +00:00
|
|
|
}
|
2001-09-11 00:11:00 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
break;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-06-08 04:35:50 +00:00
|
|
|
case WP_KNIFE:
|
2002-06-16 20:06:15 +00:00
|
|
|
MAKERGB(weaponInfo->flashDlightColor, 1, 0.70f, 0);
|
|
|
|
weaponInfo->flashSound[0] = trap_S_RegisterSound("sound/weapons/knife/slash.wav", qfalse);
|
2001-05-06 20:50:27 +00:00
|
|
|
weaponInfo->missileModel = trap_R_RegisterModel("models/weapons2/knife/knife.md3");
|
2001-08-06 19:15:00 +00:00
|
|
|
|
2001-09-11 00:11:00 +00:00
|
|
|
// Load the animation information
|
2002-06-16 20:06:15 +00:00
|
|
|
Com_sprintf(filename, sizeof(filename), "models/weapons2/knife/animation.cfg");
|
|
|
|
if (!CG_ParseWeaponAnimFile(filename, weaponInfo)) {
|
2001-09-11 00:11:00 +00:00
|
|
|
Com_Printf("Failed to load weapon animation file %s\n", filename);
|
|
|
|
weapAnimLoad = qfalse;
|
|
|
|
}
|
2001-05-06 20:50:27 +00:00
|
|
|
//weaponInfo->missileTrailFunc = CG_GrenadeTrail;
|
|
|
|
//cgs.media.grenadeExplosionShader = trap_R_RegisterShader( "grenadeExplosion" );
|
2001-08-06 19:15:00 +00:00
|
|
|
//weaponInfo->wiTrailTime = 700;
|
|
|
|
//weaponInfo->trailRadius = 32;
|
2001-05-06 20:50:27 +00:00
|
|
|
break;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
case WP_M4:
|
2001-06-08 04:35:50 +00:00
|
|
|
//Elder: added
|
2002-06-16 20:06:15 +00:00
|
|
|
MAKERGB(weaponInfo->flashDlightColor, 1, 1, 0);
|
|
|
|
weaponInfo->flashSound[0] = trap_S_RegisterSound("sound/weapons/m4/m4fire.wav", qfalse);
|
|
|
|
weaponInfo->worldReloadSound[0] = trap_S_RegisterSound("sound/weapons/m4/m4reload.wav", qfalse);
|
2001-05-06 20:50:27 +00:00
|
|
|
weaponInfo->ejectBrassFunc = CG_MachineGunEjectBrass;
|
2002-06-16 20:06:15 +00:00
|
|
|
cgs.media.bulletExplosionShader = trap_R_RegisterShader("bulletExplosion");
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
Com_sprintf(filename, sizeof(filename), "models/weapons2/m4/animation.cfg");
|
|
|
|
if (!CG_ParseWeaponAnimFile(filename, weaponInfo)) {
|
2001-08-30 09:42:25 +00:00
|
|
|
Com_Printf("Failed to load weapon animation file %s\n", filename);
|
2001-09-11 00:11:00 +00:00
|
|
|
weapAnimLoad = qfalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (weapAnimLoad) {
|
2002-06-16 20:06:15 +00:00
|
|
|
Com_sprintf(filename, sizeof(filename), "models/weapons2/m4/sound.cfg");
|
|
|
|
if (!CG_ParseWeaponSoundFile(filename, weaponInfo)) {
|
2001-09-11 00:11:00 +00:00
|
|
|
Com_Printf("Failed to load weapon sound file %s\n", filename);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Com_Printf("Could not load sound.cfg because animation.cfg loading failed\n");
|
2001-08-30 09:42:25 +00:00
|
|
|
}
|
2001-10-11 22:50:58 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
break;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
case WP_SSG3000:
|
2001-06-08 04:35:50 +00:00
|
|
|
//Elder: added
|
2002-06-16 20:06:15 +00:00
|
|
|
MAKERGB(weaponInfo->flashDlightColor, 1, 0.5f, 0);
|
|
|
|
weaponInfo->flashSound[0] = trap_S_RegisterSound("sound/weapons/ssg3000/ssgfire.wav", qfalse);
|
|
|
|
weaponInfo->worldReloadSound[0] = trap_S_RegisterSound("sound/weapons/ssg3000/ssgbolt.wav", qfalse);
|
|
|
|
weaponInfo->worldReloadSound[1] = trap_S_RegisterSound("sound/weapons/ssg3000/ssgin.wav", qfalse);
|
|
|
|
weaponInfo->worldReloadSound[2] = trap_S_RegisterSound("sound/weapons/ssg3000/ssgbolt.wav", qfalse);
|
2001-05-06 20:50:27 +00:00
|
|
|
weaponInfo->ejectBrassFunc = CG_MachineGunEjectBrass;
|
2002-06-16 20:06:15 +00:00
|
|
|
cgs.media.bulletExplosionShader = trap_R_RegisterShader("bulletExplosion");
|
|
|
|
Com_sprintf(filename, sizeof(filename), "models/weapons2/ssg3000/animation.cfg");
|
|
|
|
if (!CG_ParseWeaponAnimFile(filename, weaponInfo)) {
|
2001-08-25 00:05:20 +00:00
|
|
|
Com_Printf("Failed to load weapon animation file %s\n", filename);
|
|
|
|
}
|
2001-10-11 22:50:58 +00:00
|
|
|
// Load sound information -- ALWAYS DO THIS AFTER THE ANIMATION
|
|
|
|
if (weapAnimLoad) {
|
2002-06-16 20:06:15 +00:00
|
|
|
Com_sprintf(filename, sizeof(filename), "models/weapons2/ssg3000/sound.cfg");
|
|
|
|
if (!CG_ParseWeaponSoundFile(filename, weaponInfo)) {
|
2001-10-11 22:50:58 +00:00
|
|
|
Com_Printf("Failed to load weapon sound file %s\n", filename);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Com_Printf("Could not load sound.cfg because animation.cfg loading failed\n");
|
|
|
|
}
|
2001-05-06 20:50:27 +00:00
|
|
|
break;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
case WP_MP5:
|
2001-06-08 04:35:50 +00:00
|
|
|
//Elder: added
|
2002-06-16 20:06:15 +00:00
|
|
|
MAKERGB(weaponInfo->flashDlightColor, 1, 0.75f, 0);
|
|
|
|
weaponInfo->flashSound[0] = trap_S_RegisterSound("sound/weapons/mp5/mp5fire.wav", qfalse);
|
|
|
|
weaponInfo->worldReloadSound[0] = trap_S_RegisterSound("sound/weapons/mp5/mp5reload.wav", qfalse);
|
2001-05-06 20:50:27 +00:00
|
|
|
weaponInfo->ejectBrassFunc = CG_MachineGunEjectBrass;
|
2002-06-16 20:06:15 +00:00
|
|
|
cgs.media.bulletExplosionShader = trap_R_RegisterShader("bulletExplosion");
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
Com_sprintf(filename, sizeof(filename), "models/weapons2/mp5/animation.cfg");
|
|
|
|
if (!CG_ParseWeaponAnimFile(filename, weaponInfo)) {
|
2001-10-30 23:23:04 +00:00
|
|
|
Com_Printf("Failed to load weapon animation file %s\n", filename);
|
|
|
|
weapAnimLoad = qfalse;
|
|
|
|
}
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-11-08 02:37:11 +00:00
|
|
|
if (weapAnimLoad) {
|
2002-06-16 20:06:15 +00:00
|
|
|
Com_sprintf(filename, sizeof(filename), "models/weapons2/mp5/sound.cfg");
|
|
|
|
if (!CG_ParseWeaponSoundFile(filename, weaponInfo)) {
|
2001-11-08 02:37:11 +00:00
|
|
|
Com_Printf("Failed to load weapon sound file %s\n", filename);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Com_Printf("Could not load sound.cfg because animation.cfg loading failed\n");
|
|
|
|
}
|
2001-05-06 20:50:27 +00:00
|
|
|
break;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
case WP_HANDCANNON:
|
2001-06-08 04:35:50 +00:00
|
|
|
//Elder: added
|
2002-06-16 20:06:15 +00:00
|
|
|
MAKERGB(weaponInfo->flashDlightColor, 1, 1, 0);
|
2001-06-08 04:35:50 +00:00
|
|
|
//Elder: changed to hcfire from cannon_fire
|
2002-06-16 20:06:15 +00:00
|
|
|
weaponInfo->flashSound[0] = trap_S_RegisterSound("sound/weapons/handcannon/hcfire.wav", qfalse);
|
|
|
|
weaponInfo->worldReloadSound[0] = trap_S_RegisterSound("sound/weapons/handcannon/hcreload.wav", qfalse);
|
2002-03-24 22:46:23 +00:00
|
|
|
weaponInfo->ejectBrassFunc = CG_ShotgunEjectBrass;
|
2002-06-16 20:06:15 +00:00
|
|
|
cgs.media.bulletExplosionShader = trap_R_RegisterShader("bulletExplosion");
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
Com_sprintf(filename, sizeof(filename), "models/weapons2/handcannon/animation.cfg");
|
|
|
|
if (!CG_ParseWeaponAnimFile(filename, weaponInfo)) {
|
2001-08-17 14:28:52 +00:00
|
|
|
Com_Printf("Failed to load weapon animation file %s\n", filename);
|
2001-10-11 22:50:58 +00:00
|
|
|
weapAnimLoad = qfalse;
|
2001-08-17 14:28:52 +00:00
|
|
|
}
|
2001-10-11 22:50:58 +00:00
|
|
|
|
|
|
|
if (weapAnimLoad) {
|
2002-06-16 20:06:15 +00:00
|
|
|
Com_sprintf(filename, sizeof(filename), "models/weapons2/handcannon/sound.cfg");
|
|
|
|
if (!CG_ParseWeaponSoundFile(filename, weaponInfo)) {
|
2001-10-11 22:50:58 +00:00
|
|
|
Com_Printf("Failed to load weapon sound file %s\n", filename);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Com_Printf("Could not load sound.cfg because animation.cfg loading failed\n");
|
|
|
|
}
|
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
break;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
case WP_M3:
|
2002-06-16 20:06:15 +00:00
|
|
|
MAKERGB(weaponInfo->flashDlightColor, 1, 1, 0);
|
|
|
|
weaponInfo->flashSound[0] = trap_S_RegisterSound("sound/weapons/m3/m3fire.wav", qfalse);
|
|
|
|
weaponInfo->worldReloadSound[1] = trap_S_RegisterSound("sound/weapons/m3/m3in.wav", qfalse);
|
2001-05-06 20:50:27 +00:00
|
|
|
weaponInfo->ejectBrassFunc = CG_ShotgunEjectBrass;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
Com_sprintf(filename, sizeof(filename), "models/weapons2/m3/animation.cfg");
|
|
|
|
if (!CG_ParseWeaponAnimFile(filename, weaponInfo)) {
|
2001-08-01 18:28:38 +00:00
|
|
|
Com_Printf("Failed to load weapon animation file %s\n", filename);
|
2001-10-11 22:50:58 +00:00
|
|
|
weapAnimLoad = qfalse;
|
2001-08-01 18:28:38 +00:00
|
|
|
}
|
2001-10-11 22:50:58 +00:00
|
|
|
|
|
|
|
if (weapAnimLoad) {
|
2002-06-16 20:06:15 +00:00
|
|
|
Com_sprintf(filename, sizeof(filename), "models/weapons2/m3/sound.cfg");
|
|
|
|
if (!CG_ParseWeaponSoundFile(filename, weaponInfo)) {
|
2001-10-11 22:50:58 +00:00
|
|
|
Com_Printf("Failed to load weapon sound file %s\n", filename);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Com_Printf("Could not load sound.cfg because animation.cfg loading failed\n");
|
|
|
|
}
|
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
break;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
case WP_AKIMBO:
|
2001-06-08 04:35:50 +00:00
|
|
|
//Elder: added
|
2002-06-16 20:06:15 +00:00
|
|
|
MAKERGB(weaponInfo->flashDlightColor, 1, 1, 0.5f);
|
2001-09-01 16:15:01 +00:00
|
|
|
// Elder: no more pseudo-dual sound needed :)
|
2002-06-16 20:06:15 +00:00
|
|
|
weaponInfo->flashSound[0] = trap_S_RegisterSound("sound/weapons/mk23/mk23fire.wav", qfalse);
|
|
|
|
weaponInfo->worldReloadSound[0] = trap_S_RegisterSound("sound/weapons/akimbo/akimboreload.wav", qfalse);
|
2001-05-06 20:50:27 +00:00
|
|
|
weaponInfo->ejectBrassFunc = CG_MachineGunEjectBrass;
|
2002-06-16 20:06:15 +00:00
|
|
|
cgs.media.bulletExplosionShader = trap_R_RegisterShader("bulletExplosion");
|
|
|
|
Com_sprintf(filename, sizeof(filename), "models/weapons2/akimbo/animation.cfg");
|
|
|
|
if (!CG_ParseWeaponAnimFile(filename, weaponInfo)) {
|
2001-09-01 16:15:01 +00:00
|
|
|
Com_Printf("Failed to load weapon animation file %s\n", filename);
|
2001-09-11 00:11:00 +00:00
|
|
|
weapAnimLoad = qfalse;
|
|
|
|
}
|
|
|
|
// Load sound information -- ALWAYS DO THIS AFTER THE ANIMATION
|
|
|
|
if (weapAnimLoad) {
|
2002-06-16 20:06:15 +00:00
|
|
|
Com_sprintf(filename, sizeof(filename), "models/weapons2/akimbo/sound.cfg");
|
|
|
|
if (!CG_ParseWeaponSoundFile(filename, weaponInfo)) {
|
2001-09-11 00:11:00 +00:00
|
|
|
Com_Printf("Failed to load weapon sound file %s\n", filename);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Com_Printf("Could not load sound.cfg because animation.cfg loading failed\n");
|
2001-09-01 16:15:01 +00:00
|
|
|
}
|
2001-10-11 22:50:58 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
break;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
case WP_GRENADE:
|
2001-09-11 00:11:00 +00:00
|
|
|
//Use the projectile model
|
2002-06-16 20:06:15 +00:00
|
|
|
weaponInfo->missileModel = trap_R_RegisterModel("models/weapons2/grenade/gren_projectile.md3");
|
2001-11-11 07:23:16 +00:00
|
|
|
//Elder: removed smoke for the last time! :)
|
2001-08-06 19:15:00 +00:00
|
|
|
//weaponInfo->missileTrailFunc = CG_GrenadeTrail;
|
2001-05-06 20:50:27 +00:00
|
|
|
weaponInfo->wiTrailTime = 700;
|
|
|
|
weaponInfo->trailRadius = 32;
|
2002-06-16 20:06:15 +00:00
|
|
|
MAKERGB(weaponInfo->flashDlightColor, 1, 0.70f, 0);
|
2001-10-11 22:50:58 +00:00
|
|
|
//weaponInfo->flashSound[0] = trap_S_RegisterSound( "sound/weapons/grenade/gren_throw.wav", qfalse );
|
2002-06-16 20:06:15 +00:00
|
|
|
//Blaze: Make sure we load this as we may have exploding crates
|
2002-03-21 00:26:46 +00:00
|
|
|
//cgs.media.grenadeExplosionShader = trap_R_RegisterShader( "grenadeExplosion" );
|
2001-09-11 00:11:00 +00:00
|
|
|
|
|
|
|
// Load the animation information
|
2002-06-16 20:06:15 +00:00
|
|
|
Com_sprintf(filename, sizeof(filename), "models/weapons2/grenade/animation.cfg");
|
|
|
|
if (!CG_ParseWeaponAnimFile(filename, weaponInfo)) {
|
2001-09-11 00:11:00 +00:00
|
|
|
Com_Printf("Failed to load weapon animation file %s\n", filename);
|
|
|
|
weapAnimLoad = qfalse;
|
|
|
|
}
|
2001-10-11 22:50:58 +00:00
|
|
|
// Load sound information -- ALWAYS DO THIS AFTER THE ANIMATION
|
|
|
|
if (weapAnimLoad) {
|
2002-06-16 20:06:15 +00:00
|
|
|
Com_sprintf(filename, sizeof(filename), "models/weapons2/grenade/sound.cfg");
|
|
|
|
if (!CG_ParseWeaponSoundFile(filename, weaponInfo)) {
|
2001-10-11 22:50:58 +00:00
|
|
|
Com_Printf("Failed to load weapon sound file %s\n", filename);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Com_Printf("Could not load sound.cfg because animation.cfg loading failed\n");
|
|
|
|
}
|
2001-05-06 20:50:27 +00:00
|
|
|
break;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
default:
|
2001-05-06 20:50:27 +00:00
|
|
|
//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
|
|
|
|
=================
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_RegisterItemVisuals(int itemNum)
|
|
|
|
{
|
|
|
|
itemInfo_t *itemInfo;
|
|
|
|
gitem_t *item;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
itemInfo = &cg_items[itemNum];
|
|
|
|
if (itemInfo->registered) {
|
2001-05-06 20:50:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
item = &bg_itemlist[itemNum];
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
memset(itemInfo, 0, sizeof(&itemInfo));
|
2001-05-06 20:50:27 +00:00
|
|
|
itemInfo->registered = qtrue;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
itemInfo->models[0] = trap_R_RegisterModel(item->world_model[0]);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
itemInfo->icon = trap_R_RegisterShader(item->icon);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (item->giType == IT_WEAPON) {
|
|
|
|
CG_RegisterWeapon(item->giTag);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
//
|
|
|
|
// powerups have an accompanying ring or sphere
|
|
|
|
//
|
2002-06-16 20:06:15 +00:00
|
|
|
if (item->giType == IT_POWERUP || item->giType == IT_HEALTH ||
|
|
|
|
item->giType == IT_ARMOR || item->giType == IT_HOLDABLE) {
|
|
|
|
if (item->world_model[1]) {
|
|
|
|
itemInfo->models[1] = trap_R_RegisterModel(item->world_model[1]);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
========================================================================================
|
|
|
|
|
|
|
|
VIEW WEAPON
|
|
|
|
|
|
|
|
========================================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
CG_MapTorsoToWeaponFrame
|
2002-03-31 03:31:24 +00:00
|
|
|
// JBravo: not used.
|
2001-05-06 20:50:27 +00:00
|
|
|
=================
|
|
|
|
*/
|
2002-03-31 03:31:24 +00:00
|
|
|
/*
|
2001-05-06 20:50:27 +00:00
|
|
|
static int CG_MapTorsoToWeaponFrame( clientInfo_t *ci, int frame ) {
|
|
|
|
|
2001-08-06 19:15:00 +00:00
|
|
|
// change weapon
|
2001-11-11 20:03:09 +00:00
|
|
|
if ( frame >= ci->animations[TORSO_DROP].firstFrame
|
2001-08-06 19:15:00 +00:00
|
|
|
&& frame < ci->animations[TORSO_DROP].firstFrame + 9 ) {
|
|
|
|
return frame - ci->animations[TORSO_DROP].firstFrame + 6;
|
|
|
|
}
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-08-06 19:15:00 +00:00
|
|
|
// stand attack
|
2001-11-11 20:03:09 +00:00
|
|
|
if ( frame >= ci->animations[TORSO_ATTACK].firstFrame
|
2001-08-06 19:15:00 +00:00
|
|
|
&& frame < ci->animations[TORSO_ATTACK].firstFrame + 6 ) {
|
|
|
|
return 1 + frame - ci->animations[TORSO_ATTACK].firstFrame;
|
|
|
|
}
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2001-08-06 19:15:00 +00:00
|
|
|
// stand attack 2
|
2001-11-11 20:03:09 +00:00
|
|
|
if ( frame >= ci->animations[TORSO_ATTACK2].firstFrame
|
2001-08-06 19:15:00 +00:00
|
|
|
&& frame < ci->animations[TORSO_ATTACK2].firstFrame + 6 ) {
|
|
|
|
return 1 + frame - ci->animations[TORSO_ATTACK2].firstFrame;
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
2001-08-06 19:15:00 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2002-03-31 03:31:24 +00:00
|
|
|
*/
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
==============
|
|
|
|
CG_CalculateWeaponPosition
|
|
|
|
==============
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
static void CG_CalculateWeaponPosition(vec3_t origin, vec3_t angles)
|
|
|
|
{
|
|
|
|
float scale;
|
|
|
|
int delta;
|
|
|
|
float fracsin;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorCopy(cg.refdef.vieworg, origin);
|
|
|
|
VectorCopy(cg.refdefViewAngles, angles);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
// on odd legs, invert some angles
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.bobcycle & 1) {
|
2001-05-06 20:50:27 +00:00
|
|
|
scale = -cg.xyspeed;
|
|
|
|
} else {
|
|
|
|
scale = cg.xyspeed;
|
|
|
|
}
|
|
|
|
|
|
|
|
// gun angles from bobbing
|
|
|
|
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
|
|
|
|
delta = cg.time - cg.landTime;
|
2002-06-16 20:06:15 +00:00
|
|
|
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;
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
#if 0
|
|
|
|
// drop the weapon when stair climbing
|
|
|
|
delta = cg.time - cg.stepTime;
|
2002-06-16 20:06:15 +00:00
|
|
|
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);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// idle drift
|
|
|
|
scale = cg.xyspeed + 40;
|
2002-06-16 20:06:15 +00:00
|
|
|
fracsin = sin(cg.time * 0.001);
|
2001-05-06 20:50:27 +00:00
|
|
|
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)
|
2001-12-17 15:06:41 +00:00
|
|
|
|
|
|
|
NiceAss; I've torn this function up with testing... ignore it =P
|
2001-05-06 20:50:27 +00:00
|
|
|
===============
|
|
|
|
*/
|
2002-03-31 03:31:24 +00:00
|
|
|
/*
|
2001-05-06 20:50:27 +00:00
|
|
|
static void CG_LightningBolt( centity_t *cent, vec3_t origin ) {
|
|
|
|
trace_t trace;
|
|
|
|
refEntity_t beam;
|
|
|
|
vec3_t forward;
|
|
|
|
vec3_t muzzlePoint, endPoint;
|
2001-12-17 15:06:41 +00:00
|
|
|
centity_t *client;
|
2001-05-06 20:50:27 +00:00
|
|
|
//Blaze: LG No longer exists
|
|
|
|
// if ( cent->currentState.weapon != WP_LIGHTNING ) {
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
|
|
|
|
memset( &beam, 0, sizeof( beam ) );
|
2001-12-17 15:06:41 +00:00
|
|
|
//client = &cg_entities[cg.predictedPlayerState.clientNum];
|
|
|
|
|
|
|
|
//CG_Printf("%d \n", cg.predictedPlayerState.clientNum);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
// find muzzle point for this frame
|
2002-01-14 01:19:23 +00:00
|
|
|
//CG_EvaluateTrajectory( ¢->currentState.apos, cg.time, cent->lerpAngles );
|
2001-05-06 20:50:27 +00:00
|
|
|
AngleVectors( cent->lerpAngles, forward, NULL, NULL );
|
|
|
|
|
|
|
|
// project forward by the lightning range
|
2001-12-17 15:06:41 +00:00
|
|
|
VectorMA( muzzlePoint, 8192, forward, endPoint );
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
// see if it hit a wall
|
2001-11-11 20:03:09 +00:00
|
|
|
CG_Trace( &trace, muzzlePoint, vec3_origin, vec3_origin, endPoint,
|
2001-05-06 20:50:27 +00:00
|
|
|
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 ) {
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
2002-03-31 03:31:24 +00:00
|
|
|
*/
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
CG_SpawnRailTrail
|
|
|
|
|
|
|
|
Origin will be the exact tag point, which is slightly
|
|
|
|
different than the muzzle point used for determining hits.
|
|
|
|
===============
|
|
|
|
*/
|
2002-03-31 03:31:24 +00:00
|
|
|
// JBravo: not used.
|
|
|
|
/*
|
2001-05-06 20:50:27 +00:00
|
|
|
static void CG_SpawnRailTrail( centity_t *cent, vec3_t origin ) {
|
|
|
|
clientInfo_t *ci;
|
|
|
|
|
|
|
|
//Blaze: No more rail gun
|
|
|
|
//if ( cent->currentState.weapon != WP_RAILGUN ) {
|
|
|
|
// return;
|
|
|
|
//}
|
|
|
|
if ( !cent->pe.railgunFlash ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
cent->pe.railgunFlash = qtrue;
|
|
|
|
ci = &cgs.clientinfo[ cent->currentState.clientNum ];
|
|
|
|
//Blaze: No Rail Trail
|
|
|
|
//CG_RailTrail( ci, origin, cent->pe.railgunImpact );
|
|
|
|
}
|
2002-03-31 03:31:24 +00:00
|
|
|
*/
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
======================
|
|
|
|
CG_MachinegunSpinAngle
|
|
|
|
======================
|
|
|
|
*/
|
2002-03-31 03:31:24 +00:00
|
|
|
// JBravo: not used.
|
|
|
|
/*
|
2001-05-06 20:50:27 +00:00
|
|
|
#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;
|
|
|
|
}
|
2002-03-31 03:31:24 +00:00
|
|
|
*/
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
========================
|
|
|
|
CG_AddWeaponWithPowerups
|
|
|
|
========================
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
static void CG_AddWeaponWithPowerups(refEntity_t * gun, int powerups)
|
|
|
|
{
|
2001-05-06 20:50:27 +00:00
|
|
|
// add powerup effects
|
2002-06-16 20:06:15 +00:00
|
|
|
if (powerups & (1 << PW_INVIS)) {
|
2001-05-06 20:50:27 +00:00
|
|
|
gun->customShader = cgs.media.invisShader;
|
2002-06-16 20:06:15 +00:00
|
|
|
trap_R_AddRefEntityToScene(gun);
|
2001-05-06 20:50:27 +00:00
|
|
|
} else {
|
2002-06-16 20:06:15 +00:00
|
|
|
trap_R_AddRefEntityToScene(gun);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (powerups & (1 << PW_BATTLESUIT)) {
|
2001-05-06 20:50:27 +00:00
|
|
|
gun->customShader = cgs.media.battleWeaponShader;
|
2002-06-16 20:06:15 +00:00
|
|
|
trap_R_AddRefEntityToScene(gun);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
if (powerups & (1 << PW_QUAD)) {
|
2001-05-06 20:50:27 +00:00
|
|
|
gun->customShader = cgs.media.quadWeaponShader;
|
2002-06-16 20:06:15 +00:00
|
|
|
trap_R_AddRefEntityToScene(gun);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=============
|
|
|
|
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.
|
|
|
|
=============
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_AddPlayerWeapon(refEntity_t * parent, playerState_t * ps, centity_t * cent, int team)
|
|
|
|
{
|
|
|
|
refEntity_t gun;
|
|
|
|
|
|
|
|
// Blaze: Can remove this because no more spinning barrel
|
|
|
|
// refEntity_t barrel;
|
|
|
|
refEntity_t flash;
|
2002-05-29 03:52:21 +00:00
|
|
|
refEntity_t silencer, laser;
|
2002-06-16 20:06:15 +00:00
|
|
|
vec3_t angles;
|
|
|
|
weapon_t weaponNum;
|
|
|
|
weaponInfo_t *weapon;
|
|
|
|
centity_t *nonPredictedCent;
|
2002-03-16 21:50:09 +00:00
|
|
|
localEntity_t *shell = NULL;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
weaponNum = cent->currentState.weapon;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_RegisterWeapon(weaponNum);
|
2001-05-06 20:50:27 +00:00
|
|
|
weapon = &cg_weapons[weaponNum];
|
|
|
|
|
|
|
|
// add the weapon
|
2002-06-16 20:06:15 +00:00
|
|
|
memset(&gun, 0, sizeof(gun));
|
|
|
|
VectorCopy(parent->lightingOrigin, gun.lightingOrigin);
|
2001-05-06 20:50:27 +00:00
|
|
|
gun.shadowPlane = parent->shadowPlane;
|
|
|
|
gun.renderfx = parent->renderfx;
|
|
|
|
|
|
|
|
// set custom shading for railgun refire rate
|
|
|
|
//if ( ps ) {
|
2002-06-16 20:06:15 +00:00
|
|
|
//Blaze: No Railgun
|
|
|
|
//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;
|
2001-05-06 20:50:27 +00:00
|
|
|
//}
|
2002-06-16 20:06:15 +00:00
|
|
|
//}
|
|
|
|
if (ps == NULL) {
|
2001-07-09 00:32:10 +00:00
|
|
|
//Elder: We are in third person, use the third-person model (DEFAULT)
|
|
|
|
gun.hModel = weapon->weaponModel;
|
2002-06-16 20:06:15 +00:00
|
|
|
} else {
|
2001-07-09 00:32:10 +00:00
|
|
|
//Elder: we are in first-person, use the first-person (NOT default) model
|
|
|
|
gun.hModel = weapon->firstModel;
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
if (!gun.hModel) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (!ps) {
|
2001-05-06 20:50:27 +00:00
|
|
|
// add weapon ready sound
|
|
|
|
cent->pe.lightningFiring = qfalse;
|
2002-06-16 20:06:15 +00:00
|
|
|
if ((cent->currentState.eFlags & EF_FIRING) && weapon->firingSound) {
|
2001-05-06 20:50:27 +00:00
|
|
|
// lightning gun and guantlet make a different sound when fire is held down
|
2002-06-16 20:06:15 +00:00
|
|
|
trap_S_AddLoopingSound(cent->currentState.number, cent->lerpOrigin, vec3_origin,
|
|
|
|
weapon->firingSound);
|
2001-05-06 20:50:27 +00:00
|
|
|
cent->pe.lightningFiring = qtrue;
|
2002-06-16 20:06:15 +00:00
|
|
|
} else if (weapon->readySound) {
|
|
|
|
trap_S_AddLoopingSound(cent->currentState.number, cent->lerpOrigin, vec3_origin,
|
|
|
|
weapon->readySound);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
}
|
2001-07-28 02:49:18 +00:00
|
|
|
//if (ps == NULL)
|
|
|
|
//{
|
2002-06-16 20:06:15 +00:00
|
|
|
/* resizing code
|
|
|
|
msec = cg.time - cent->miscTime;
|
|
|
|
if ( msec >= 0 && msec < ITEM_SCALEUP_TIME ) {
|
|
|
|
frac = (float)msec / ITEM_SCALEUP_TIME;
|
|
|
|
VectorScale( ent.axis[0], frac, ent.axis[0] );
|
|
|
|
VectorScale( ent.axis[1], frac, ent.axis[1] );
|
|
|
|
VectorScale( ent.axis[2], frac, ent.axis[2] );
|
|
|
|
ent.nonNormalizedAxes = qtrue;
|
|
|
|
} else {
|
|
|
|
frac = 1.0;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
//Elder: shouldn't have to do this anymore
|
|
|
|
/*
|
|
|
|
if (weaponNum == 4)//Blaze: Scale the Sniper Rifle down a bit
|
|
|
|
{
|
|
|
|
frac = 0.8f;
|
|
|
|
VectorScale(parent->axis[0], frac, parent->axis[0]);
|
|
|
|
//VectorScale(parent->axis[1], frac, parent->axis[1]);
|
|
|
|
//VectorScale(parent->axis[2], frac, parent->axis[2]);
|
|
|
|
}
|
|
|
|
*/
|
2001-11-11 20:03:09 +00:00
|
|
|
|
|
|
|
//}
|
2002-06-16 20:06:15 +00:00
|
|
|
if (!ps) {
|
|
|
|
CG_PositionEntityOnTag(&gun, parent, parent->hModel, "tag_weapon");
|
|
|
|
} else {
|
|
|
|
CG_WeaponAnimation(cent, &gun.oldframe, &gun.frame, &gun.backlerp);
|
|
|
|
CG_PositionWeaponOnTag(&gun, parent, parent->hModel, "tag_weapon");
|
2001-09-11 00:11:00 +00:00
|
|
|
|
|
|
|
// Elder: Local sound events will sync perfectly here
|
|
|
|
// However, we must remember to ignore the ones pmove will generate
|
|
|
|
// (for other clients to hear) or we'll get some nasty echo
|
|
|
|
|
|
|
|
// Temp hack because it isn't fully implemented
|
2002-06-16 20:06:15 +00:00
|
|
|
if (weapon->item->giTag == WP_PISTOL ||
|
|
|
|
weapon->item->giTag == WP_AKIMBO ||
|
|
|
|
weapon->item->giTag == WP_M4 ||
|
|
|
|
weapon->item->giTag == WP_MP5 ||
|
|
|
|
weapon->item->giTag == WP_M3 ||
|
|
|
|
weapon->item->giTag == WP_HANDCANNON ||
|
|
|
|
weapon->item->giTag == WP_SSG3000 || weapon->item->giTag == WP_GRENADE) {
|
2001-10-11 22:50:58 +00:00
|
|
|
int i = 0;
|
|
|
|
qboolean noSound = qfalse;
|
2001-11-25 23:17:41 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
while (gun.frame != weapon->animationSounds->sfxInfo[i].frame) {
|
|
|
|
if (++i == weapon->animationSounds->numFrames) {
|
2001-10-11 22:50:58 +00:00
|
|
|
noSound = qtrue;
|
|
|
|
break;
|
|
|
|
}
|
2001-09-11 00:11:00 +00:00
|
|
|
}
|
|
|
|
|
2001-10-11 22:50:58 +00:00
|
|
|
// reset the current sound
|
|
|
|
if (cg.curSyncSound.played && cg.curSyncSound.frame != gun.frame)
|
|
|
|
cg.curSyncSound.played = qfalse;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (!noSound) {
|
2001-10-11 22:50:58 +00:00
|
|
|
// copy the struct to reset it
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.curSyncSound.frame != gun.frame)
|
2001-10-11 22:50:58 +00:00
|
|
|
cg.curSyncSound = weapon->animationSounds->sfxInfo[i];
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.curSyncSound.played == qfalse) {
|
2001-10-11 22:50:58 +00:00
|
|
|
cg.curSyncSound.played = qtrue;
|
2001-11-25 23:17:41 +00:00
|
|
|
|
2001-11-11 07:23:16 +00:00
|
|
|
//CG_Printf("Playing a timed sound (%i %i %1.1f)\n", gun.frame, gun.oldframe, gun.backlerp);
|
2002-06-16 20:06:15 +00:00
|
|
|
trap_S_StartLocalSound(cg.curSyncSound.sound, CHAN_WEAPON);
|
2001-09-11 00:11:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2001-11-11 20:03:09 +00:00
|
|
|
}
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2001-08-30 09:42:25 +00:00
|
|
|
// Elder: break off here so we still have weapon animations on bolt out
|
2001-10-11 22:50:58 +00:00
|
|
|
// Elder: added ps so we see SSG in third-person zoomed
|
|
|
|
if (cg.zoomed && ps)
|
2001-08-30 09:42:25 +00:00
|
|
|
return;
|
|
|
|
|
2002-01-12 15:18:20 +00:00
|
|
|
// JBravo: Adding a fix from NiceAss (cg_drawgun affecting other player models)
|
2002-06-16 20:06:15 +00:00
|
|
|
if (!cg_drawGun.integer && ps)
|
|
|
|
return;
|
2001-11-24 23:55:56 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_AddWeaponWithPowerups(&gun, cent->currentState.powerups);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
// add the spinning barrel
|
|
|
|
//Blaze: No Spinning Barrel
|
|
|
|
/*
|
2002-06-16 20:06:15 +00:00
|
|
|
if ( weapon->barrelModel ) {
|
|
|
|
memset( &barrel, 0, sizeof( barrel ) );
|
|
|
|
VectorCopy( parent->lightingOrigin, barrel.lightingOrigin );
|
|
|
|
barrel.shadowPlane = parent->shadowPlane;
|
|
|
|
barrel.renderfx = parent->renderfx;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
barrel.hModel = weapon->barrelModel;
|
|
|
|
angles[YAW] = 0;
|
|
|
|
angles[PITCH] = 0;
|
|
|
|
angles[ROLL] = CG_MachinegunSpinAngle( cent );
|
|
|
|
AnglesToAxis( angles, barrel.axis );
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_PositionRotatedEntityOnTag( &barrel, &gun, weapon->weaponModel, "tag_barrel" );
|
|
|
|
|
|
|
|
CG_AddWeaponWithPowerups( &barrel, cent->currentState.powerups );
|
|
|
|
} */
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
// 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
|
2002-06-16 20:06:15 +00:00
|
|
|
if ((nonPredictedCent - cg_entities) != cent->currentState.clientNum) {
|
2001-05-06 20:50:27 +00:00
|
|
|
nonPredictedCent = cent;
|
|
|
|
}
|
|
|
|
// add the flash
|
|
|
|
//Blaze: no more of these
|
|
|
|
/*
|
2002-06-16 20:06:15 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2001-12-17 15:06:41 +00:00
|
|
|
//CG_LightningBolt( nonPredictedCent, parent->lightingOrigin );
|
2002-06-16 20:06:15 +00:00
|
|
|
if (ps && bg_itemlist[cg.snap->ps.stats[STAT_HOLDABLE_ITEM]].giTag == HI_SILENCER &&
|
|
|
|
(weaponNum == WP_PISTOL || weaponNum == WP_MP5 || weaponNum == WP_SSG3000)) {
|
2002-04-06 21:43:59 +00:00
|
|
|
//Makro - wasn't initialized, caused a warning in MSVC
|
2002-06-16 20:06:15 +00:00
|
|
|
vec3_t silencerEnd;
|
|
|
|
float scale = 0.0f;
|
|
|
|
vec3_t angles;
|
|
|
|
|
|
|
|
if (weaponNum == WP_PISTOL)
|
|
|
|
scale = 1.2f;
|
|
|
|
if (weaponNum == WP_SSG3000)
|
|
|
|
scale = 2.5f;
|
|
|
|
if (weaponNum == WP_MP5)
|
|
|
|
scale = 1.3f;
|
|
|
|
|
|
|
|
memset(&silencer, 0, sizeof(silencer));
|
2002-03-16 21:50:09 +00:00
|
|
|
silencer.hModel = cgs.media.rq3_silencerModel;
|
|
|
|
silencer.shadowPlane = parent->shadowPlane;
|
|
|
|
silencer.renderfx = parent->renderfx;
|
|
|
|
|
|
|
|
angles[YAW] = 90;
|
|
|
|
angles[PITCH] = 0;
|
|
|
|
angles[ROLL] = 0;
|
2002-06-16 20:06:15 +00:00
|
|
|
AnglesToAxis(angles, silencer.axis);
|
2002-03-16 21:50:09 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorScale(silencer.axis[0], scale, silencer.axis[0]);
|
|
|
|
VectorScale(silencer.axis[1], scale, silencer.axis[1]);
|
|
|
|
VectorScale(silencer.axis[2], scale, silencer.axis[2]);
|
2002-03-16 21:50:09 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_PositionRotatedOffsetEntityOnTag(&silencer, &gun, weapon->firstModel, "tag_silencer", vec3_origin);
|
2002-05-01 03:28:07 +00:00
|
|
|
// Offset weapon
|
2002-04-29 06:10:09 +00:00
|
|
|
VectorMA(silencer.origin, -7.2f, silencer.axis[1], silencer.origin);
|
2002-05-18 03:55:35 +00:00
|
|
|
VectorMA(silencer.origin, 10.0f, silencer.axis[1], silencerEnd);
|
2002-05-29 03:52:21 +00:00
|
|
|
silencer.nonNormalizedAxes = qtrue;
|
2002-04-29 06:10:09 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_AddWeaponWithPowerups(&silencer, cent->currentState.powerups);
|
2002-05-18 03:55:35 +00:00
|
|
|
|
|
|
|
/*
|
2002-06-16 20:06:15 +00:00
|
|
|
NiceAss: Add a puff of smoke at the end of the silencer when fired. Not alligned properly and looks bad.
|
|
|
|
if (cent->muzzleFlashTime == -1) {
|
|
|
|
localEntity_t *smoke;
|
|
|
|
vec3_t up;
|
2002-05-18 03:55:35 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
silencerEnd[2] += 5.0f;
|
2002-05-18 03:55:35 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorSet(up, 0.0f, 0.0f, 15.0f);
|
|
|
|
smoke = CG_SmokePuff( silencerEnd, up, 0.75f, 1, 1, 1, 0.75f, 300, cg.time, 0, 0, cgs.media.shotgunSmokePuffShader );
|
|
|
|
smoke->leType = LE_SCALE_FADE;
|
2002-05-18 03:55:35 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
cent->muzzleFlashTime = 0;
|
|
|
|
}
|
|
|
|
*/
|
2002-03-16 21:50:09 +00:00
|
|
|
}
|
2001-12-17 15:06:41 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (ps && bg_itemlist[cg.snap->ps.stats[STAT_HOLDABLE_ITEM]].giTag == HI_LASER &&
|
|
|
|
(weaponNum == WP_PISTOL || weaponNum == WP_MP5 || weaponNum == WP_M4)) {
|
|
|
|
float scale = 0.0f;
|
|
|
|
vec3_t angles;
|
2002-05-29 03:52:21 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (weaponNum == WP_PISTOL)
|
|
|
|
scale = 0.66f;
|
|
|
|
if (weaponNum == WP_MP5)
|
|
|
|
scale = 0.675f;
|
|
|
|
if (weaponNum == WP_M4)
|
|
|
|
scale = 0.79f;
|
2002-05-29 03:52:21 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
memset(&laser, 0, sizeof(laser));
|
2002-05-29 03:52:21 +00:00
|
|
|
laser.hModel = cgs.media.rq3_laserModel;
|
|
|
|
laser.shadowPlane = parent->shadowPlane;
|
|
|
|
laser.renderfx = parent->renderfx;
|
|
|
|
|
|
|
|
angles[YAW] = 90;
|
|
|
|
angles[PITCH] = 0;
|
|
|
|
angles[ROLL] = 0;
|
2002-06-16 20:06:15 +00:00
|
|
|
AnglesToAxis(angles, laser.axis);
|
2002-05-29 03:52:21 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorScale(laser.axis[0], scale, laser.axis[0]);
|
|
|
|
VectorScale(laser.axis[1], scale, laser.axis[1]);
|
|
|
|
VectorScale(laser.axis[2], scale, laser.axis[2]);
|
2002-05-29 03:52:21 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_PositionRotatedOffsetEntityOnTag(&laser, &gun, weapon->firstModel, "tag_laser", vec3_origin);
|
2002-05-29 03:52:21 +00:00
|
|
|
|
|
|
|
laser.nonNormalizedAxes = qtrue;
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_AddWeaponWithPowerups(&laser, cent->currentState.powerups);
|
2002-05-29 03:52:21 +00:00
|
|
|
}
|
|
|
|
|
2002-03-11 02:22:45 +00:00
|
|
|
// NiceAss: Tag locations used for shell ejection
|
2002-03-24 22:46:23 +00:00
|
|
|
// The handcannon hacks have ruined my beautiful code =(
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.time > cent->ejectBrassTime && cent->ejectBrassTime && weapon->ejectBrassFunc &&
|
|
|
|
(ps || cg.renderingThirdPerson || cent->currentState.number != cg.predictedPlayerState.clientNum)) {
|
2002-03-16 21:50:09 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
shell = weapon->ejectBrassFunc(cent);
|
2002-03-16 21:50:09 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (shell != NULL) {
|
|
|
|
float speed = 1.0f;
|
|
|
|
int axis1 = 0, axis2 = 0;
|
2002-04-07 02:10:42 +00:00
|
|
|
|
2002-03-16 21:50:09 +00:00
|
|
|
if (ps) {
|
2002-06-16 20:06:15 +00:00
|
|
|
if (weapon->item->giTag == WP_AKIMBO && !ps->stats[STAT_BURST])
|
|
|
|
CG_PositionRotatedEntityOnTag(&shell->refEntity, &gun, gun.hModel,
|
|
|
|
"tag_shell2");
|
2002-03-16 21:50:09 +00:00
|
|
|
else
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_PositionRotatedEntityOnTag(&shell->refEntity, &gun, gun.hModel, "tag_shell");
|
|
|
|
} else {
|
|
|
|
if (weapon->item->giTag == WP_AKIMBO && cg.akimboFlash)
|
|
|
|
CG_PositionRotatedEntityOnTag(&shell->refEntity, &gun, gun.hModel,
|
|
|
|
"tag_shell2");
|
2002-03-16 21:50:09 +00:00
|
|
|
else
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_PositionRotatedEntityOnTag(&shell->refEntity, &gun, gun.hModel, "tag_shell");
|
|
|
|
|
2002-03-16 21:50:09 +00:00
|
|
|
}
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorCopy(shell->refEntity.origin, shell->pos.trBase);
|
|
|
|
|
|
|
|
if (trap_CM_PointContents(shell->pos.trBase, 0) == CONTENTS_WATER)
|
|
|
|
speed = 0.5f;
|
2002-03-16 21:50:09 +00:00
|
|
|
|
2002-05-18 03:55:35 +00:00
|
|
|
if (weaponNum == WP_HANDCANNON) {
|
2002-06-16 20:06:15 +00:00
|
|
|
speed = -speed; // horrible hacks
|
2002-06-11 21:50:51 +00:00
|
|
|
axis1 = 1;
|
2002-03-24 22:46:23 +00:00
|
|
|
}
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
vectoangles(shell->refEntity.axis[axis1], shell->angles.trBase);
|
|
|
|
VectorScale(shell->refEntity.axis[axis2], 160 * speed, shell->pos.trDelta);
|
|
|
|
VectorAdd(shell->pos.trDelta, cent->currentState.pos.trDelta, shell->pos.trDelta);
|
2002-03-16 21:50:09 +00:00
|
|
|
}
|
2002-03-24 22:46:23 +00:00
|
|
|
// All this code for a SECOND shell on the HC
|
2002-06-16 20:06:15 +00:00
|
|
|
if (weaponNum == WP_HANDCANNON) {
|
|
|
|
float speed = -1.0f;
|
|
|
|
|
|
|
|
shell = weapon->ejectBrassFunc(cent);
|
2002-03-24 22:46:23 +00:00
|
|
|
if (shell != NULL) {
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_PositionRotatedEntityOnTag(&shell->refEntity, &gun, gun.hModel, "tag_shell2");
|
|
|
|
|
|
|
|
VectorCopy(shell->refEntity.origin, shell->pos.trBase);
|
2002-03-24 22:46:23 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (trap_CM_PointContents(shell->pos.trBase, 0) == CONTENTS_WATER)
|
|
|
|
speed = -0.5f;
|
2002-03-24 22:46:23 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
vectoangles(shell->refEntity.axis[1], shell->angles.trBase);
|
|
|
|
VectorScale(shell->refEntity.axis[0], 160 * speed, shell->pos.trDelta);
|
|
|
|
VectorAdd(shell->pos.trDelta, cent->currentState.pos.trDelta, shell->pos.trDelta);
|
2002-03-24 22:46:23 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-03-16 21:50:09 +00:00
|
|
|
cent->ejectBrassTime = 0;
|
2002-03-11 02:22:45 +00:00
|
|
|
}
|
2002-06-21 04:11:34 +00:00
|
|
|
|
|
|
|
if ( cent->currentState.number != cg.predictedPlayerState.clientNum ) {
|
|
|
|
refEntity_t muzzle;
|
|
|
|
memset(&muzzle, 0, sizeof(muzzle));
|
|
|
|
CG_PositionEntityOnTag(&muzzle, &gun, weapon->weaponModel, "tag_flash");
|
2002-06-23 04:36:27 +00:00
|
|
|
|
|
|
|
CG_DrawVisibleLaser(muzzle.origin, cent->currentState.clientNum, muzzle.axis[0]);
|
2002-06-21 04:11:34 +00:00
|
|
|
}
|
|
|
|
|
2001-06-08 04:35:50 +00:00
|
|
|
//Elder: re-added to fix loss of muzzle flashes!
|
|
|
|
// impulse flash
|
2002-03-11 02:22:45 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.time - cent->muzzleFlashTime > MUZZLE_FLASH_TIME && !cent->pe.railgunFlash) {
|
2001-06-08 04:35:50 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
memset(&flash, 0, sizeof(flash));
|
2002-03-11 02:22:45 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorCopy(parent->lightingOrigin, flash.lightingOrigin);
|
2001-05-06 20:50:27 +00:00
|
|
|
flash.shadowPlane = parent->shadowPlane;
|
|
|
|
flash.renderfx = parent->renderfx;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
flash.hModel = weapon->flashModel;
|
|
|
|
if (!flash.hModel) {
|
|
|
|
return;
|
|
|
|
}
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
angles[YAW] = 0;
|
|
|
|
angles[PITCH] = 0;
|
|
|
|
angles[ROLL] = crandom() * 10;
|
2002-06-16 20:06:15 +00:00
|
|
|
AnglesToAxis(angles, flash.axis);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
// colorize the railgun blast
|
|
|
|
//Blaze: No more railgun
|
|
|
|
/*
|
2002-06-16 20:06:15 +00:00
|
|
|
if ( weaponNum == WP_RAILGUN ) {
|
|
|
|
clientInfo_t *ci;
|
|
|
|
|
|
|
|
ci = &cgs.clientinfo[ cent->currentState.clientNum ];
|
|
|
|
flash.shaderRGBA[0] = 255 * ci->color1[0];
|
|
|
|
flash.shaderRGBA[1] = 255 * ci->color1[1];
|
|
|
|
flash.shaderRGBA[2] = 255 * ci->color1[2];
|
|
|
|
}
|
|
|
|
*/
|
2001-05-06 20:50:27 +00:00
|
|
|
//Blaze: No flash
|
2001-06-08 04:35:50 +00:00
|
|
|
//Elder: Yes flash - try this
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-07-16 01:41:36 +00:00
|
|
|
//Elder: add conditional here so the dlight is still drawn when cg_RQ3_flash is 0
|
2002-03-11 02:22:45 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg_RQ3_flash.integer) {
|
2001-06-08 04:35:50 +00:00
|
|
|
if (ps) {
|
2002-06-17 03:53:31 +00:00
|
|
|
float scale = 2.0f;
|
|
|
|
|
|
|
|
if (ps->weapon == WP_M4) scale = 1.5f;
|
|
|
|
|
2001-08-30 09:42:25 +00:00
|
|
|
// Elder: draw flash based on first-person view
|
2002-06-16 20:06:15 +00:00
|
|
|
if (ps->weapon == WP_AKIMBO) {
|
2001-09-11 00:11:00 +00:00
|
|
|
// choose tag for akimbos
|
|
|
|
if (ps->stats[STAT_BURST])
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_PositionRotatedEntityOnTag(&flash, &gun, weapon->firstModel, "tag_flash");
|
2001-09-11 00:11:00 +00:00
|
|
|
else
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_PositionRotatedEntityOnTag(&flash, &gun, weapon->firstModel, "tag_flash2");
|
|
|
|
} else
|
|
|
|
CG_PositionRotatedEntityOnTag(&flash, &gun, weapon->firstModel, "tag_flash");
|
2001-09-11 00:11:00 +00:00
|
|
|
|
2001-08-30 09:42:25 +00:00
|
|
|
// Make flash larger to compensate for depth hack
|
2002-06-17 03:53:31 +00:00
|
|
|
VectorScale(flash.axis[0], scale, flash.axis[0]);
|
|
|
|
VectorScale(flash.axis[1], scale, flash.axis[1]);
|
|
|
|
VectorScale(flash.axis[2], scale, flash.axis[2]);
|
2001-08-30 09:42:25 +00:00
|
|
|
flash.nonNormalizedAxes = qtrue;
|
2002-06-16 20:06:15 +00:00
|
|
|
} else {
|
2001-06-08 04:35:50 +00:00
|
|
|
//Elder: draw flash based on 3rd-person view
|
2002-06-16 20:06:15 +00:00
|
|
|
if (weapon->item->giTag == WP_AKIMBO) {
|
2001-09-11 00:11:00 +00:00
|
|
|
// choose tag for akimbos
|
|
|
|
if (cg.akimboFlash)
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_PositionRotatedEntityOnTag(&flash, &gun, weapon->weaponModel, "tag_flash");
|
2001-09-11 00:11:00 +00:00
|
|
|
else
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_PositionRotatedEntityOnTag(&flash, &gun, weapon->weaponModel, "tag_flash2");
|
|
|
|
} else
|
|
|
|
CG_PositionRotatedEntityOnTag(&flash, &gun, weapon->weaponModel, "tag_flash");
|
2001-06-08 04:35:50 +00:00
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
trap_R_AddRefEntityToScene(&flash);
|
|
|
|
} else {
|
2001-06-08 04:35:50 +00:00
|
|
|
//Elder: crappy way to get the dlight working w/o the flash model
|
2002-06-16 20:06:15 +00:00
|
|
|
if (ps || cg.renderingThirdPerson || cent->currentState.number != cg.predictedPlayerState.clientNum) {
|
|
|
|
if (weapon->flashDlightColor[0] || weapon->flashDlightColor[1] || weapon->flashDlightColor[2]) {
|
|
|
|
if (!cg_drawGun.value)
|
|
|
|
trap_R_AddLightToScene(gun.origin, 300 + (rand() & 31),
|
|
|
|
weapon->flashDlightColor[0], weapon->flashDlightColor[1],
|
|
|
|
weapon->flashDlightColor[2]);
|
2001-06-08 04:35:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (ps || cg.renderingThirdPerson || cent->currentState.number != cg.predictedPlayerState.clientNum) {
|
2001-05-06 20:50:27 +00:00
|
|
|
// add lightning bolt
|
|
|
|
//Blaze: No need for this
|
|
|
|
|
|
|
|
// add rail trail
|
|
|
|
//Blaze: no need for this
|
|
|
|
//CG_SpawnRailTrail( cent, flash.origin );
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
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]);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==============
|
|
|
|
CG_AddViewWeapon
|
|
|
|
|
|
|
|
Add the weapon, and flash for the player's view
|
|
|
|
==============
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_AddViewWeapon(playerState_t * ps)
|
|
|
|
{
|
|
|
|
refEntity_t hand;
|
|
|
|
centity_t *cent;
|
|
|
|
|
|
|
|
//clientInfo_t *ci;
|
|
|
|
float fovOffset;
|
|
|
|
vec3_t angles;
|
|
|
|
weaponInfo_t *weapon;
|
|
|
|
|
2001-12-17 15:06:41 +00:00
|
|
|
// remove this:
|
2002-06-16 20:06:15 +00:00
|
|
|
//vec3_t origin;
|
2001-12-17 15:06:41 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
//Blaze: Reaction vars for gun positions
|
2002-01-14 01:19:23 +00:00
|
|
|
//float rxn_gunx, rxn_guny, rxn_gunz;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-02-24 20:49:07 +00:00
|
|
|
//Slicer - Spect code for follow
|
2002-06-16 20:06:15 +00:00
|
|
|
if (ps->persistant[PERS_TEAM] == TEAM_SPECTATOR && !(ps->pm_flags & PMF_FOLLOW)) {
|
2001-05-06 20:50:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (ps->pm_type == PM_INTERMISSION) {
|
2001-05-06 20:50:27 +00:00
|
|
|
return;
|
|
|
|
}
|
2001-08-01 21:07:48 +00:00
|
|
|
// no gun if in third person view or a camera is active
|
|
|
|
//if ( cg.renderingThirdPerson || cg.cameraMode) {
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.renderingThirdPerson) {
|
2001-05-06 20:50:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// allow the gun to be completely removed
|
2001-08-17 20:38:54 +00:00
|
|
|
// Elder: don't draw if throwing
|
2002-06-16 20:06:15 +00:00
|
|
|
// if ( !cg_drawGun.integer || (cg.snap->ps.stats[STAT_RQ3] & RQ3_THROWWEAPON) == RQ3_THROWWEAPON) {
|
2001-11-24 23:55:56 +00:00
|
|
|
//Blaze: removed cg_drawGun checks and moved into other code.
|
2002-06-16 20:06:15 +00:00
|
|
|
if ((cg.snap->ps.stats[STAT_RQ3] & RQ3_THROWWEAPON) == RQ3_THROWWEAPON) {
|
2001-05-06 20:50:27 +00:00
|
|
|
//Blaze: Removed these
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.predictedPlayerState.eFlags & EF_FIRING) {
|
2001-05-06 20:50:27 +00:00
|
|
|
// special hack for lightning gun...
|
2001-12-17 15:06:41 +00:00
|
|
|
//VectorCopy( cg.refdef.vieworg, origin );
|
|
|
|
//VectorMA( origin, -8, cg.refdef.viewaxis[2], origin );
|
|
|
|
//CG_LightningBolt( &cg_entities[ps->clientNum], origin );
|
|
|
|
}
|
2001-05-06 20:50:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Hawkins- don't draw gun if zoomed
|
2001-08-30 09:42:25 +00:00
|
|
|
// Elder: we'll break it off later because we still need to perform animation operations
|
|
|
|
/*
|
2002-06-16 20:06:15 +00:00
|
|
|
if(cg.zoomed)
|
|
|
|
return;
|
|
|
|
*/
|
2001-05-06 20:50:27 +00:00
|
|
|
// don't draw if testing a gun model
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.testGun) {
|
2001-05-06 20:50:27 +00:00
|
|
|
return;
|
2001-11-11 20:03:09 +00:00
|
|
|
}
|
2001-11-13 05:32:07 +00:00
|
|
|
// Elder: temporarily removed because we never used it anyways
|
|
|
|
/*
|
2002-06-16 20:06:15 +00:00
|
|
|
//Blaze start: Reaction gun positioning
|
|
|
|
rxn_gunx = cg_gun_x.value;
|
|
|
|
rxn_guny = cg_gun_y.value;
|
|
|
|
rxn_gunz = cg_gun_z.value;
|
|
|
|
//Blaze: Gun xyz coords changes
|
|
|
|
switch(ps->weapon)
|
|
|
|
{
|
|
|
|
case WP_PISTOL:
|
|
|
|
rxn_gunx += 10;
|
|
|
|
break;
|
|
|
|
case WP_M4:
|
|
|
|
rxn_gunx += 10;
|
|
|
|
break;
|
|
|
|
case WP_SSG3000:
|
|
|
|
rxn_gunx += 10;
|
|
|
|
break;
|
|
|
|
case WP_AKIMBO:
|
|
|
|
rxn_gunx += 10;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((cg_RQ3_drawWeapon.integer > 1 ) && (cg_RQ3_drawWeapon.integer < 4 ))
|
|
|
|
{
|
|
|
|
rxn_guny = cg_gun_y.value + 4*(cg_RQ3_drawWeapon.integer-1);
|
|
|
|
}
|
|
|
|
*/
|
2001-11-13 05:32:07 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
//Blaze end:
|
|
|
|
|
|
|
|
// drop gun lower at higher fov
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg_fov.integer > 90) {
|
|
|
|
fovOffset = -0.2 * (cg_fov.integer - 90);
|
2001-05-06 20:50:27 +00:00
|
|
|
} else {
|
|
|
|
fovOffset = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
cent = &cg.predictedPlayerEntity; // &cg_entities[cg.snap->ps.clientNum];
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_RegisterWeapon(ps->weapon);
|
|
|
|
weapon = &cg_weapons[ps->weapon];
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
memset(&hand, 0, sizeof(hand));
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
// set up gun position
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_CalculateWeaponPosition(hand.origin, angles);
|
2001-05-06 20:50:27 +00:00
|
|
|
//Blaze start: reaction gun positioning
|
2002-06-16 20:06:15 +00:00
|
|
|
// VectorMA( hand.origin, rxn_gunx, cg.refdef.viewaxis[0], hand.origin );
|
|
|
|
// VectorMA( hand.origin, rxn_guny, cg.refdef.viewaxis[1], hand.origin );
|
|
|
|
// VectorMA( hand.origin, (rxn_gunz + fovOffset), cg.refdef.viewaxis[2], hand.origin );
|
2001-05-06 20:50:27 +00:00
|
|
|
//Blaze end:
|
|
|
|
|
|
|
|
//Blaze: Use above code instead
|
2001-06-08 04:35:50 +00:00
|
|
|
//Elder: reused so Cloud can adjust the models manually
|
2002-06-16 20:06:15 +00:00
|
|
|
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);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
AnglesToAxis(angles, hand.axis);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2001-08-06 19:15:00 +00:00
|
|
|
//Elder: temp hack
|
2001-10-30 23:23:04 +00:00
|
|
|
// map torso animations to weapon animations
|
|
|
|
/*
|
2002-06-16 20:06:15 +00:00
|
|
|
if ( cg_gun_frame.integer ||
|
|
|
|
ps->weapon == WP_PISTOL ||
|
|
|
|
ps->weapon == WP_M3 ||
|
|
|
|
ps->weapon == WP_HANDCANNON ||
|
|
|
|
ps->weapon == WP_SSG3000 ||
|
|
|
|
ps->weapon == WP_M4 ||
|
|
|
|
ps->weapon == WP_MP5 ||
|
|
|
|
ps->weapon == WP_AKIMBO ||
|
|
|
|
ps->weapon == WP_GRENADE ||
|
|
|
|
ps->weapon == WP_KNIFE ) {
|
|
|
|
*/
|
|
|
|
// development tool
|
|
|
|
hand.frame = hand.oldframe = cg_gun_frame.integer;
|
|
|
|
hand.backlerp = 0;
|
2001-10-30 23:23:04 +00:00
|
|
|
/*
|
2002-06-16 20:06:15 +00:00
|
|
|
} 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;
|
|
|
|
}
|
|
|
|
*/
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2001-07-28 12:32:54 +00:00
|
|
|
hand.hModel = weapon->handsModel;
|
2001-05-06 20:50:27 +00:00
|
|
|
hand.renderfx = RF_DEPTHHACK | RF_FIRST_PERSON | RF_MINLIGHT;
|
|
|
|
|
|
|
|
// add everything onto the hand
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_AddPlayerWeapon(&hand, ps, &cg.predictedPlayerEntity, ps->persistant[PERS_TEAM]);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==============================================================================
|
|
|
|
|
|
|
|
WEAPON SELECTION
|
|
|
|
|
|
|
|
==============================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
===================
|
|
|
|
CG_DrawWeaponSelect
|
|
|
|
===================
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_DrawWeaponSelect(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int bits;
|
|
|
|
int count;
|
|
|
|
int x, y, w;
|
|
|
|
char *name;
|
|
|
|
float *color;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
// don't display if dead
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.predictedPlayerState.stats[STAT_HEALTH] <= 0) {
|
2001-05-06 20:50:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
color = CG_FadeColor(cg.weaponSelectTime, WEAPON_SELECT_TIME);
|
|
|
|
if (!color) {
|
2001-05-06 20:50:27 +00:00
|
|
|
return;
|
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
trap_R_SetColor(color);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
// showing weapon select clears pickup item display, but not the blend blob
|
|
|
|
cg.itemPickupTime = 0;
|
|
|
|
|
|
|
|
// count the number of weapons owned
|
2002-06-16 20:06:15 +00:00
|
|
|
bits = cg.snap->ps.stats[STAT_WEAPONS];
|
2001-05-06 20:50:27 +00:00
|
|
|
count = 0;
|
2002-06-16 20:06:15 +00:00
|
|
|
for (i = 1; i < 16; i++) {
|
|
|
|
if (bits & (1 << i)) {
|
2001-05-06 20:50:27 +00:00
|
|
|
count++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
x = 320 - count * 20;
|
|
|
|
y = 380;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
for (i = 1; i < 16; i++) {
|
|
|
|
if (!(bits & (1 << i))) {
|
2001-05-06 20:50:27 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_RegisterWeapon(i);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
// draw weapon icon
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_DrawPic(x, y, 32, 32, cg_weapons[i].weaponIcon);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
// draw selection marker
|
2002-06-16 20:06:15 +00:00
|
|
|
if (i == cg.weaponSelect) {
|
|
|
|
CG_DrawPic(x - 4, y - 4, 40, 40, cgs.media.selectShader);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
// no ammo cross on top
|
2002-06-16 20:06:15 +00:00
|
|
|
// if ( !cg.snap->ps.ammo[ i ] ) {
|
|
|
|
// CG_DrawPic( x, y, 32, 32, cgs.media.noammoShader );
|
|
|
|
// }
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
x += 40;
|
|
|
|
}
|
|
|
|
|
|
|
|
// draw the selected name
|
2002-06-16 20:06:15 +00:00
|
|
|
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;
|
2001-05-06 20:50:27 +00:00
|
|
|
CG_DrawBigStringColor(x, y - 22, name, color);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
trap_R_SetColor(NULL);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
CG_WeaponSelectable
|
|
|
|
===============
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
static qboolean CG_WeaponSelectable(int i)
|
|
|
|
{
|
2001-07-01 05:11:12 +00:00
|
|
|
//Elder: never switch to empty grenades/knives
|
2002-06-16 20:06:15 +00:00
|
|
|
if (!cg.snap->ps.ammo[i] && (i == WP_GRENADE || i == WP_KNIFE)) {
|
2001-05-06 20:50:27 +00:00
|
|
|
return qfalse;
|
|
|
|
}
|
2001-07-01 05:11:12 +00:00
|
|
|
//Blaze: Check the amount of clips too for the weapon rotate code
|
|
|
|
//Elder: this won't work plus AQ2 lets you select empty weapons
|
|
|
|
//if ( !cg.snap->ps.ammo[i] && !cg.snap->ps.stats[STAT_CLIPS] ) {
|
2002-06-16 20:06:15 +00:00
|
|
|
//return qfalse;
|
2001-07-01 05:11:12 +00:00
|
|
|
//}
|
2002-06-29 04:15:15 +00:00
|
|
|
// JBravo: lets not allow switching to weapons other than pistol or knife if the player has a case
|
|
|
|
if (cg.snap->ps.powerups[PW_BLUEFLAG] || cg.snap->ps.powerups[PW_REDFLAG]) {
|
|
|
|
if (i != WP_PISTOL && i != WP_KNIFE)
|
|
|
|
return qfalse;
|
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
if (!(cg.snap->ps.stats[STAT_WEAPONS] & (1 << i))) {
|
2001-05-06 20:50:27 +00:00
|
|
|
return qfalse;
|
|
|
|
}
|
|
|
|
|
|
|
|
return qtrue;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
CG_NextWeapon_f
|
|
|
|
===============
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_NextWeapon_f(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int original;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (!cg.snap) {
|
2001-05-06 20:50:27 +00:00
|
|
|
return;
|
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.snap->ps.pm_flags & PMF_FOLLOW) {
|
2001-05-06 20:50:27 +00:00
|
|
|
return;
|
|
|
|
}
|
2001-07-01 05:11:12 +00:00
|
|
|
// if we are going into the intermission, don't do anything
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.intermissionStarted) {
|
2001-07-01 05:11:12 +00:00
|
|
|
return;
|
|
|
|
}
|
2001-06-08 04:35:50 +00:00
|
|
|
//Elder: added
|
2002-06-16 20:06:15 +00:00
|
|
|
// if ( (cg.snap->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK) {
|
|
|
|
if (cg.snap->ps.weaponstate == WEAPON_BANDAGING) {
|
2001-06-18 00:40:38 +00:00
|
|
|
CG_Printf("You are too busy bandaging...\n");
|
|
|
|
return;
|
|
|
|
}
|
2001-07-24 01:49:02 +00:00
|
|
|
//Elder: don't allow weapon switching when in the middle of bursts
|
|
|
|
if (cg.snap->ps.stats[STAT_BURST] > 0)
|
|
|
|
return;
|
|
|
|
|
2001-06-24 02:07:17 +00:00
|
|
|
//Elder: in the middle of firing, reloading or weapon-switching
|
2001-08-30 09:42:25 +00:00
|
|
|
/*
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.snap->ps.weaponstate == WEAPON_RELOADING && cg.snap->ps.weaponTime > 0) {
|
|
|
|
return;
|
|
|
|
} */
|
2001-06-24 02:07:17 +00:00
|
|
|
|
2001-06-18 00:40:38 +00:00
|
|
|
//Elder: added
|
|
|
|
//cg.zoomed = qfalse;
|
|
|
|
//cg.zoomLevel = 0;
|
2001-06-08 04:35:50 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
cg.weaponSelectTime = cg.time;
|
|
|
|
original = cg.weaponSelect;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
for (i = 0; i < 16; i++) {
|
2001-05-06 20:50:27 +00:00
|
|
|
cg.weaponSelect++;
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.weaponSelect == 16) {
|
2001-05-06 20:50:27 +00:00
|
|
|
cg.weaponSelect = 0;
|
|
|
|
}
|
|
|
|
//Blaze: Allow full Cycle
|
|
|
|
//if ( cg.weaponSelect == WP_GAUNTLET ) {
|
2002-06-16 20:06:15 +00:00
|
|
|
// continue; // never cycle to gauntlet
|
2001-05-06 20:50:27 +00:00
|
|
|
//}
|
2002-06-16 20:06:15 +00:00
|
|
|
if (CG_WeaponSelectable(cg.weaponSelect)) {
|
2001-05-06 20:50:27 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
if (i == 16) {
|
2001-05-06 20:50:27 +00:00
|
|
|
cg.weaponSelect = original;
|
|
|
|
}
|
2002-03-13 18:41:18 +00:00
|
|
|
//Slicer: Done Server Side
|
2001-07-01 05:11:12 +00:00
|
|
|
else {
|
2002-06-16 20:06:15 +00:00
|
|
|
// CG_RQ3_Zoom1x();
|
2002-05-01 17:46:00 +00:00
|
|
|
//Slicer lets call unzoom for SSG only
|
2002-06-16 20:06:15 +00:00
|
|
|
if (original == WP_SSG3000)
|
2002-05-01 17:46:00 +00:00
|
|
|
trap_SendClientCommand("unzoom");
|
2001-07-01 05:11:12 +00:00
|
|
|
}
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
CG_PrevWeapon_f
|
|
|
|
===============
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_PrevWeapon_f(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int original;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (!cg.snap) {
|
2001-05-06 20:50:27 +00:00
|
|
|
return;
|
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.snap->ps.pm_flags & PMF_FOLLOW) {
|
2001-05-06 20:50:27 +00:00
|
|
|
return;
|
|
|
|
}
|
2001-07-01 05:11:12 +00:00
|
|
|
// if we are going into the intermission, don't do anything
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.intermissionStarted) {
|
2001-07-01 05:11:12 +00:00
|
|
|
return;
|
|
|
|
}
|
2001-06-08 04:35:50 +00:00
|
|
|
//Elder: added
|
2002-03-18 19:19:08 +00:00
|
|
|
// if ( (cg.snap->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK) {
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.snap->ps.weaponstate == WEAPON_BANDAGING) {
|
2001-06-18 00:40:38 +00:00
|
|
|
CG_Printf("You are too busy bandaging...\n");
|
|
|
|
return;
|
|
|
|
}
|
2001-07-24 01:49:02 +00:00
|
|
|
//Elder: don't allow weapon switching when in the middle of bursts
|
|
|
|
if (cg.snap->ps.stats[STAT_BURST] > 0)
|
|
|
|
return;
|
|
|
|
|
2001-06-24 02:07:17 +00:00
|
|
|
//Elder: in the middle of firing, reloading or weapon-switching
|
2001-07-01 05:11:12 +00:00
|
|
|
//cg.snap->ps.weaponstate == WEAPON_RELOADING when it's in
|
2001-10-11 22:50:58 +00:00
|
|
|
/*
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.snap->ps.weaponstate == WEAPON_RELOADING && cg.snap->ps.weaponTime > 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
*/
|
2001-06-24 02:07:17 +00:00
|
|
|
|
2001-06-18 00:40:38 +00:00
|
|
|
//Elder: added
|
|
|
|
//cg.zoomed = qfalse;
|
|
|
|
//cg.zoomLevel = 0;
|
2001-06-08 04:35:50 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
cg.weaponSelectTime = cg.time;
|
|
|
|
original = cg.weaponSelect;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
for (i = 0; i < 16; i++) {
|
2001-05-06 20:50:27 +00:00
|
|
|
cg.weaponSelect--;
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.weaponSelect == -1) {
|
2001-05-06 20:50:27 +00:00
|
|
|
cg.weaponSelect = 15;
|
|
|
|
}
|
|
|
|
//Blaze: Allow full Cycle
|
|
|
|
//if ( cg.weaponSelect == WP_GAUNTLET ) {
|
2002-06-16 20:06:15 +00:00
|
|
|
// continue; // never cycle to gauntlet
|
2001-05-06 20:50:27 +00:00
|
|
|
//}
|
2002-06-16 20:06:15 +00:00
|
|
|
if (CG_WeaponSelectable(cg.weaponSelect)) {
|
2001-05-06 20:50:27 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
if (i == 16) {
|
2001-05-06 20:50:27 +00:00
|
|
|
cg.weaponSelect = original;
|
2002-06-16 20:06:15 +00:00
|
|
|
} else {
|
2002-03-13 18:41:18 +00:00
|
|
|
//Slicer: Done Server Side
|
|
|
|
//CG_RQ3_Zoom1x();
|
2002-05-01 17:46:00 +00:00
|
|
|
//Slicer lets call unzoom for SSG only
|
2002-06-16 20:06:15 +00:00
|
|
|
if (original == WP_SSG3000)
|
2002-05-01 17:46:00 +00:00
|
|
|
trap_SendClientCommand("unzoom");
|
2001-07-01 05:11:12 +00:00
|
|
|
}
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
2001-07-01 05:11:12 +00:00
|
|
|
/*
|
|
|
|
===============
|
|
|
|
Added by Elder
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-07-01 05:11:12 +00:00
|
|
|
CG_SpecialWeapon_f
|
|
|
|
===============
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_SpecialWeapon_f(void)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
int original;
|
2001-07-01 05:11:12 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (!cg.snap) {
|
2001-07-24 01:49:02 +00:00
|
|
|
//CG_Printf("No snapshot: normally exiting\n");
|
2001-07-01 05:11:12 +00:00
|
|
|
return;
|
|
|
|
}
|
2001-07-24 01:49:02 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.snap->ps.pm_flags & PMF_FOLLOW) {
|
2001-07-01 05:11:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// if we are going into the intermission, don't do anything
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.intermissionStarted) {
|
2001-07-01 05:11:12 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
//Elder: added
|
2002-06-16 20:06:15 +00:00
|
|
|
// if ( (cg.snap->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK) {
|
|
|
|
if (cg.snap->ps.weaponstate == WEAPON_BANDAGING) {
|
2001-07-01 05:11:12 +00:00
|
|
|
CG_Printf("You are too busy bandaging...\n");
|
|
|
|
return;
|
|
|
|
}
|
2001-07-24 01:49:02 +00:00
|
|
|
//Elder: don't allow weapon switching when in the middle of bursts
|
|
|
|
if (cg.snap->ps.stats[STAT_BURST] > 0)
|
|
|
|
return;
|
2001-07-01 05:11:12 +00:00
|
|
|
|
2002-06-29 04:15:15 +00:00
|
|
|
// JBravo: not in CTF
|
|
|
|
if (cg.snap->ps.powerups[PW_BLUEFLAG] || cg.snap->ps.powerups[PW_REDFLAG])
|
|
|
|
return;
|
|
|
|
|
2001-07-01 05:11:12 +00:00
|
|
|
//Elder: in the middle of firing, reloading or weapon-switching
|
|
|
|
//cg.snap->ps.weaponstate == WEAPON_RELOADING when it's in
|
2001-10-11 22:50:58 +00:00
|
|
|
/*
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.snap->ps.weaponstate == WEAPON_RELOADING && cg.snap->ps.weaponTime > 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
*/
|
2001-07-01 05:11:12 +00:00
|
|
|
|
|
|
|
cg.weaponSelectTime = cg.time;
|
|
|
|
original = cg.weaponSelect;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
for (i = 0; i < 16; i++) {
|
2001-07-01 05:11:12 +00:00
|
|
|
cg.weaponSelect++;
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.weaponSelect == 16) {
|
2001-07-01 05:11:12 +00:00
|
|
|
cg.weaponSelect = 0;
|
|
|
|
}
|
|
|
|
//Skip normal weapons
|
|
|
|
switch (cg.weaponSelect) {
|
2002-06-16 20:06:15 +00:00
|
|
|
case WP_PISTOL:
|
|
|
|
case WP_AKIMBO:
|
|
|
|
case WP_KNIFE:
|
|
|
|
case WP_GRENADE:
|
|
|
|
continue;
|
|
|
|
break;
|
2001-07-01 05:11:12 +00:00
|
|
|
}
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (CG_WeaponSelectable(cg.weaponSelect)) {
|
2001-07-01 05:11:12 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2001-08-30 09:42:25 +00:00
|
|
|
|
|
|
|
// FIXME: 15 because of the stupid continue I used
|
2002-06-16 20:06:15 +00:00
|
|
|
if (i >= 15) {
|
2001-07-01 05:11:12 +00:00
|
|
|
cg.weaponSelect = original;
|
2002-06-16 20:06:15 +00:00
|
|
|
} else {
|
2002-03-13 18:41:18 +00:00
|
|
|
//Slicer: Done Server Side
|
2002-06-16 20:06:15 +00:00
|
|
|
// CG_RQ3_Zoom1x();
|
2002-05-01 17:46:00 +00:00
|
|
|
//Slicer lets call unzoom for SSG only
|
2002-06-16 20:06:15 +00:00
|
|
|
if (original == WP_SSG3000)
|
2002-05-01 17:46:00 +00:00
|
|
|
trap_SendClientCommand("unzoom");
|
2001-07-01 05:11:12 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-06-18 00:40:38 +00:00
|
|
|
//Elder: for returning to the zoom state in ps stats
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_RQ3_SyncZoom(void)
|
|
|
|
{
|
|
|
|
if ((cg.snap->ps.stats[STAT_RQ3] & RQ3_ZOOM_LOW) == RQ3_ZOOM_LOW &&
|
|
|
|
(cg.snap->ps.stats[STAT_RQ3] & RQ3_ZOOM_MED) == RQ3_ZOOM_MED) {
|
2001-07-16 01:41:36 +00:00
|
|
|
//CG_Printf("Zoomed to 6x\n");
|
2002-06-16 20:06:15 +00:00
|
|
|
cg.zoomLevel = RQ3_ZOOM_LOW | RQ3_ZOOM_MED;
|
|
|
|
} else if ((cg.snap->ps.stats[STAT_RQ3] & RQ3_ZOOM_LOW) == RQ3_ZOOM_LOW) {
|
2001-07-16 01:41:36 +00:00
|
|
|
//CG_Printf("Zoomed to 2x\n");
|
|
|
|
cg.zoomLevel = RQ3_ZOOM_LOW;
|
2002-06-16 20:06:15 +00:00
|
|
|
} else if ((cg.snap->ps.stats[STAT_RQ3] & RQ3_ZOOM_MED) == RQ3_ZOOM_MED) {
|
2001-07-16 01:41:36 +00:00
|
|
|
//CG_Printf("Zoomed to 4x\n");
|
|
|
|
cg.zoomLevel = RQ3_ZOOM_MED;
|
2002-06-16 20:06:15 +00:00
|
|
|
} else {
|
2001-07-16 01:41:36 +00:00
|
|
|
//CG_Printf("Zoomed out\n");
|
|
|
|
cg.zoomLevel = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//Elder: save zoom level and do any other necessary housekeeping
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_RQ3_SaveZoomLevel()
|
|
|
|
{
|
2001-07-16 01:41:36 +00:00
|
|
|
cg.lastZoomLevel = cg.zoomLevel;
|
2001-06-18 00:40:38 +00:00
|
|
|
}
|
|
|
|
|
2001-07-16 01:41:36 +00:00
|
|
|
/*
|
|
|
|
void CG_RQ3_SyncZoom2 ( void ) {
|
|
|
|
int statZoom;
|
|
|
|
|
|
|
|
if ( (cg.snap->ps.stats[STAT_RQ3] & RQ3_ZOOM_LOW) == RQ3_ZOOM_LOW &&
|
|
|
|
(cg.snap->ps.stats[STAT_RQ3] & RQ3_ZOOM_MED) == RQ3_ZOOM_MED ) {
|
|
|
|
statZoom = RQ3_ZOOM_LOW|RQ3_ZOOM_MED;
|
|
|
|
}
|
|
|
|
else if ( (cg.snap->ps.stats[STAT_RQ3] & RQ3_ZOOM_LOW) == RQ3_ZOOM_LOW) {
|
|
|
|
statZoom = RQ3_ZOOM_LOW;
|
|
|
|
}
|
|
|
|
else if ( (cg.snap->ps.stats[STAT_RQ3] & RQ3_ZOOM_MED) == RQ3_ZOOM_MED) {
|
|
|
|
statZoom = RQ3_ZOOM_MED;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
statZoom = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (statZoom != cg.zoomLevel)
|
|
|
|
cg.zoomLevel = statZoom;
|
|
|
|
}*/
|
|
|
|
|
|
|
|
//Elder: This should identical to the portion inside
|
|
|
|
//the weapon function in g_cmds.c
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_RQ3_Zoom(void)
|
|
|
|
{
|
2001-06-08 04:35:50 +00:00
|
|
|
//Elder: reworked SSG zoom
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.snap->ps.weapon == WP_SSG3000) {
|
2001-07-16 01:41:36 +00:00
|
|
|
CG_RQ3_SaveZoomLevel();
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if ((cg.zoomLevel & RQ3_ZOOM_LOW) == RQ3_ZOOM_LOW && (cg.zoomLevel & RQ3_ZOOM_MED) == RQ3_ZOOM_MED) {
|
2001-07-16 01:41:36 +00:00
|
|
|
//Elder: zoom 1x
|
|
|
|
cg.zoomLevel &= ~RQ3_ZOOM_LOW;
|
|
|
|
cg.zoomLevel &= ~RQ3_ZOOM_MED;
|
2002-06-16 20:06:15 +00:00
|
|
|
} else if ((cg.zoomLevel & RQ3_ZOOM_MED) == RQ3_ZOOM_MED) {
|
2001-07-16 01:41:36 +00:00
|
|
|
//Elder: zoom 6x
|
|
|
|
cg.zoomLevel |= RQ3_ZOOM_LOW;
|
2002-06-16 20:06:15 +00:00
|
|
|
} else if ((cg.zoomLevel & RQ3_ZOOM_LOW) == RQ3_ZOOM_LOW) {
|
2001-07-16 01:41:36 +00:00
|
|
|
//Elder: zoom 4x
|
|
|
|
cg.zoomLevel |= RQ3_ZOOM_MED;
|
|
|
|
cg.zoomLevel &= ~RQ3_ZOOM_LOW;
|
2002-06-16 20:06:15 +00:00
|
|
|
} else {
|
2001-07-16 01:41:36 +00:00
|
|
|
//Elder: zoom 2x
|
|
|
|
cg.zoomLevel |= RQ3_ZOOM_LOW;
|
|
|
|
}
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-07-16 01:41:36 +00:00
|
|
|
cg.zoomTime = cg.time;
|
|
|
|
}
|
|
|
|
|
2001-06-18 00:40:38 +00:00
|
|
|
/*
|
2002-06-16 20:06:15 +00:00
|
|
|
if(cg.snap->ps.weapon==WP_SSG3000) {
|
|
|
|
cg.zoomLevel++;
|
|
|
|
if (cg.zoomLevel == 4) {
|
|
|
|
cg.zoomed = qfalse;
|
|
|
|
cg.zoomLevel = 0;
|
|
|
|
CG_Printf("Zoomed out\n");
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
cg.zoomed = qtrue;
|
|
|
|
CG_Printf("Zoomed to %dx\n", cg.zoomLevel * 2);
|
|
|
|
}
|
|
|
|
cg.zoomTime = cg.time;
|
|
|
|
}
|
|
|
|
*/
|
2001-07-16 01:41:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
//Elder: reset locally and send server message
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_RQ3_Zoom1x()
|
|
|
|
{
|
|
|
|
if (cg_RQ3_ssgZoomAssist.integer) {
|
2001-07-16 01:41:36 +00:00
|
|
|
cg.lastZoomLevel = cg.zoomLevel;
|
|
|
|
cg.zoomLevel = 0;
|
|
|
|
cg.zoomTime = cg.time;
|
2001-06-18 00:40:38 +00:00
|
|
|
}
|
2001-07-24 01:49:02 +00:00
|
|
|
//trap_SendClientCommand("unzoom");
|
2001-07-16 01:41:36 +00:00
|
|
|
}
|
2001-06-18 00:40:38 +00:00
|
|
|
|
2001-07-16 01:41:36 +00:00
|
|
|
int CG_RQ3_GetGrenadeMode()
|
|
|
|
{
|
|
|
|
int grenMode = 0;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if ((cg.snap->ps.persistant[PERS_WEAPONMODES] & RQ3_GRENSHORT) == RQ3_GRENSHORT)
|
2001-07-16 01:41:36 +00:00
|
|
|
grenMode |= RQ3_GRENSHORT;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if ((cg.snap->ps.persistant[PERS_WEAPONMODES] & RQ3_GRENMED) == RQ3_GRENMED)
|
2001-07-16 01:41:36 +00:00
|
|
|
grenMode |= RQ3_GRENMED;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2001-07-16 01:41:36 +00:00
|
|
|
return grenMode;
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
2001-07-16 01:41:36 +00:00
|
|
|
//Print grenade mode message
|
|
|
|
void CG_RQ3_GrenadeMode()
|
|
|
|
{
|
|
|
|
//Print a message for the next mode in line
|
2002-06-16 20:06:15 +00:00
|
|
|
if ((cg.snap->ps.persistant[PERS_WEAPONMODES] & RQ3_GRENSHORT) == RQ3_GRENSHORT &&
|
|
|
|
(cg.snap->ps.persistant[PERS_WEAPONMODES] & RQ3_GRENMED) == RQ3_GRENMED) {
|
2001-07-16 01:41:36 +00:00
|
|
|
CG_Printf("Prepared to make a short range throw\n");
|
|
|
|
//cg.grenadeMode = RQ3_GRENSHORT|RQ3_GRENMED;
|
2002-06-16 20:06:15 +00:00
|
|
|
} else if ((cg.snap->ps.persistant[PERS_WEAPONMODES] & RQ3_GRENSHORT) == RQ3_GRENSHORT) {
|
2001-07-16 01:41:36 +00:00
|
|
|
CG_Printf("Prepared to make a medium range throw\n");
|
|
|
|
//cg.grenadeMode = RQ3_GRENSHORT;
|
2002-06-16 20:06:15 +00:00
|
|
|
} else if ((cg.snap->ps.persistant[PERS_WEAPONMODES] & RQ3_GRENMED) == RQ3_GRENMED) {
|
2001-07-16 01:41:36 +00:00
|
|
|
CG_Printf("Prepared to make a long range throw\n");
|
|
|
|
//cg.grenadeMode = RQ3_GRENMED;
|
|
|
|
}
|
|
|
|
}
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
CG_Weapon_f
|
2001-06-08 04:35:50 +00:00
|
|
|
|
|
|
|
Elder: does local stuff, then proceeds to server
|
|
|
|
Used with Q3's internal weapon switching "e.g. weapon 10"
|
2001-05-06 20:50:27 +00:00
|
|
|
===============
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_Weapon_f(void)
|
|
|
|
{
|
2001-06-08 04:35:50 +00:00
|
|
|
int num;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (!cg.snap) {
|
2001-07-24 01:49:02 +00:00
|
|
|
//CG_Printf("No snapshot: normally exiting\n");
|
2001-05-06 20:50:27 +00:00
|
|
|
return;
|
|
|
|
}
|
2001-06-26 01:58:02 +00:00
|
|
|
// if we are going into the intermission, don't do anything
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.intermissionStarted) {
|
2001-06-26 01:58:02 +00:00
|
|
|
return;
|
|
|
|
}
|
2001-06-08 04:35:50 +00:00
|
|
|
// Hawkins (give 'weapon' dual meaning)
|
2002-06-16 20:06:15 +00:00
|
|
|
if (trap_Argc() == 1) {
|
2001-10-11 22:50:58 +00:00
|
|
|
//Elder: in the middle of firing, reloading or weapon-switching
|
2002-06-16 20:06:15 +00:00
|
|
|
// if (cg.snap->ps.weaponTime > 0 || cg.snap->ps.stats[STAT_RELOADTIME] > 0) {
|
|
|
|
// return;
|
|
|
|
// }
|
2001-10-11 22:50:58 +00:00
|
|
|
|
2001-06-08 04:35:50 +00:00
|
|
|
if (cg.snap->ps.weapon == WP_SSG3000) {
|
2002-06-16 20:06:15 +00:00
|
|
|
//Slicer : had to comment this, it caused a bug on the zooming, and it really didn't make much sense for lagged players
|
|
|
|
// has it would get out of synch !
|
2002-06-12 17:05:14 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
//Save the time..
|
|
|
|
// cg.zoomTime = cg.time;
|
2002-06-12 17:05:14 +00:00
|
|
|
|
2002-02-23 18:07:46 +00:00
|
|
|
//Slicer- Changing Sniper stuff- some to game.
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
/* trap_S_StartLocalSound( cgs.media.lensSound, CHAN_ITEM);
|
|
|
|
if (cg_RQ3_ssgZoomAssist.integer)
|
|
|
|
CG_RQ3_Zoom();
|
|
|
|
*/
|
2002-02-23 18:07:46 +00:00
|
|
|
//Let's sound it..
|
2002-06-16 20:06:15 +00:00
|
|
|
// trap_S_StartLocalSound( cgs.media.lensSound, CHAN_ITEM);
|
2002-06-12 17:05:14 +00:00
|
|
|
|
2001-06-18 00:40:38 +00:00
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
/* else if (cg.snap->ps.weapon == WP_GRENADE)
|
|
|
|
{
|
|
|
|
CG_RQ3_GrenadeMode();
|
|
|
|
} */
|
2001-10-30 23:23:04 +00:00
|
|
|
// only play "click" sound for M4/MP5/Pistol
|
2002-06-16 20:06:15 +00:00
|
|
|
/* else if (cg.snap->ps.weapon == WP_M4 || cg.snap->ps.weapon == WP_MP5 ||
|
|
|
|
cg.snap->ps.weapon == WP_PISTOL )
|
|
|
|
{
|
|
|
|
trap_S_StartLocalSound( cgs.media.weapToggleSound, CHAN_ITEM);
|
|
|
|
} */
|
2001-06-18 00:40:38 +00:00
|
|
|
trap_SendClientCommand("weapon");
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-07-24 01:49:02 +00:00
|
|
|
//Elder: added to get out of function at this point
|
|
|
|
return;
|
2001-06-08 04:35:50 +00:00
|
|
|
}
|
2002-04-01 22:23:38 +00:00
|
|
|
//Elder: added to prevent weapon switching while bandaging
|
2002-06-16 20:06:15 +00:00
|
|
|
// if ( (cg.snap->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK) {
|
|
|
|
if (cg.snap->ps.weaponstate == WEAPON_BANDAGING) {
|
2002-04-01 22:23:38 +00:00
|
|
|
CG_Printf("You are too busy bandaging...\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
//Elder: don't allow weapon switching when in the middle of bursts
|
|
|
|
if (cg.snap->ps.stats[STAT_BURST] > 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/*
|
2002-06-16 20:06:15 +00:00
|
|
|
//Elder: in the middle of firing, reloading or weapon-switching
|
|
|
|
if (cg.snap->ps.weaponTime > 0 || cg.snap->ps.stats[STAT_RELOADTIME] > 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
*/
|
2002-04-01 22:23:38 +00:00
|
|
|
|
|
|
|
///Elder: spectator?
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.snap->ps.pm_flags & PMF_FOLLOW) {
|
2002-04-01 22:23:38 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
num = atoi(CG_Argv(1));
|
2002-04-01 22:23:38 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (num < 1 || num > 15) {
|
2001-05-06 20:50:27 +00:00
|
|
|
return;
|
|
|
|
}
|
2002-06-29 04:15:15 +00:00
|
|
|
// JBravo: CTB provisions
|
|
|
|
if (cg.snap->ps.powerups[PW_BLUEFLAG] || cg.snap->ps.powerups[PW_REDFLAG]) {
|
|
|
|
if (num != WP_PISTOL && num != WP_KNIFE)
|
|
|
|
return;
|
|
|
|
}
|
2001-06-08 04:35:50 +00:00
|
|
|
//Elder: this point on is the regular Q3 weapon function - weird
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
cg.weaponSelectTime = cg.time;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (!(cg.snap->ps.stats[STAT_WEAPONS] & (1 << num))) {
|
2001-05-06 20:50:27 +00:00
|
|
|
return; // don't have the weapon
|
|
|
|
}
|
2001-06-08 04:35:50 +00:00
|
|
|
//Elder: If re-selecting SSG - leave function
|
2002-06-16 20:06:15 +00:00
|
|
|
if ((1 << num) == (1 << WP_SSG3000) && cg.snap->ps.weapon == WP_SSG3000) {
|
2001-06-08 04:35:50 +00:00
|
|
|
//CG_Printf("Selecting SSG\n");
|
|
|
|
return;
|
|
|
|
}
|
2001-06-18 00:40:38 +00:00
|
|
|
//cg.zoomed = qfalse;
|
|
|
|
//cg.zoomLevel = 0;
|
2002-03-13 18:41:18 +00:00
|
|
|
//Slicer : Done Server Side
|
2002-06-16 20:06:15 +00:00
|
|
|
// CG_RQ3_Zoom1x();
|
2002-05-01 17:46:00 +00:00
|
|
|
//Slicer lets call unzoom for SSG only
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.weaponSelect == WP_SSG3000)
|
2002-05-01 17:46:00 +00:00
|
|
|
trap_SendClientCommand("unzoom");
|
2001-05-06 20:50:27 +00:00
|
|
|
cg.weaponSelect = num;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===================
|
|
|
|
CG_OutOfAmmoChange
|
|
|
|
|
|
|
|
The current weapon has just run out of ammo
|
|
|
|
===================
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_OutOfAmmoChange(void)
|
|
|
|
{
|
|
|
|
//int i;
|
2001-06-26 01:58:02 +00:00
|
|
|
|
|
|
|
if (!cg.snap)
|
|
|
|
return;
|
|
|
|
|
|
|
|
//Select the pistol when we run out of grenades or knives
|
|
|
|
if (cg.snap->ps.weapon == WP_KNIFE || cg.snap->ps.weapon == WP_GRENADE) {
|
|
|
|
cg.weaponSelectTime = cg.time;
|
|
|
|
cg.weaponSelect = WP_PISTOL;
|
|
|
|
}
|
|
|
|
|
2001-06-08 04:35:50 +00:00
|
|
|
/* Elder: disable auto-switch
|
2002-06-16 20:06:15 +00:00
|
|
|
cg.weaponSelectTime = cg.time;
|
|
|
|
|
|
|
|
//Elder: we'll have to change this to
|
|
|
|
//a) show the empty gun animation if gun's ammo = 0
|
|
|
|
//b) NOT auto-switch to another weapon
|
|
|
|
|
|
|
|
for ( i = 15 ; i > 0 ; i-- ) {
|
|
|
|
if ( CG_WeaponSelectable( i ) ) {
|
|
|
|
cg.weaponSelect = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
===================================================================================================
|
|
|
|
|
|
|
|
WEAPON EVENTS
|
|
|
|
|
|
|
|
===================================================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
CG_FireWeapon
|
|
|
|
|
|
|
|
Caused by an EV_FIRE_WEAPON event
|
|
|
|
================
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_FireWeapon(centity_t * cent, int weapModification)
|
|
|
|
{
|
2001-05-06 20:50:27 +00:00
|
|
|
entityState_t *ent;
|
2002-06-16 20:06:15 +00:00
|
|
|
int c, i;
|
|
|
|
weaponInfo_t *weap;
|
2002-05-18 03:55:35 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
ent = ¢->currentState;
|
2002-06-16 20:06:15 +00:00
|
|
|
if (ent->weapon == WP_NONE) {
|
2001-05-06 20:50:27 +00:00
|
|
|
return;
|
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
if (ent->weapon >= WP_NUM_WEAPONS) {
|
|
|
|
CG_Error("CG_FireWeapon: ent->weapon >= WP_NUM_WEAPONS");
|
2001-05-06 20:50:27 +00:00
|
|
|
return;
|
|
|
|
}
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
weap = &cg_weapons[ent->weapon];
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2001-07-24 01:49:02 +00:00
|
|
|
//Elder: added to supress burst mode flashes + sounds when 'predicting'
|
|
|
|
// M4
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.snap->ps.weapon == WP_M4 &&
|
|
|
|
(cg.snap->ps.persistant[PERS_WEAPONMODES] & RQ3_M4MODE) == RQ3_M4MODE &&
|
|
|
|
cg.snap->ps.stats[STAT_BURST] > 2) {
|
2001-07-24 01:49:02 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// MP5
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.snap->ps.weapon == WP_MP5 &&
|
|
|
|
(cg.snap->ps.persistant[PERS_WEAPONMODES] & RQ3_MP5MODE) == RQ3_MP5MODE &&
|
|
|
|
cg.snap->ps.stats[STAT_BURST] > 2) {
|
2001-07-24 01:49:02 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
// MK23
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.snap->ps.weapon == WP_PISTOL &&
|
|
|
|
(cg.snap->ps.persistant[PERS_WEAPONMODES] & RQ3_MK23MODE) == RQ3_MK23MODE &&
|
|
|
|
cg.snap->ps.stats[STAT_BURST] > 0) {
|
2001-07-24 01:49:02 +00:00
|
|
|
return;
|
|
|
|
}
|
2001-12-17 15:06:41 +00:00
|
|
|
// KNIFE
|
2002-03-11 02:22:45 +00:00
|
|
|
// NiceAss: This is if the knife slash is not the first (2,3,4,5)
|
2001-12-17 15:06:41 +00:00
|
|
|
if (weapModification == RQ3_WPMOD_KNIFENOMARK) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
/*if ( cg.snap->ps.weapon == WP_KNIFE ) // { && cg.snap->ps.stats[STAT_BURST] > 0 ) {
|
2002-06-16 20:06:15 +00:00
|
|
|
return;
|
|
|
|
} */
|
2001-07-24 01:49:02 +00:00
|
|
|
|
2002-03-11 02:22:45 +00:00
|
|
|
// NiceAss:
|
2002-03-16 21:50:09 +00:00
|
|
|
if (ent->weapon == WP_M3)
|
2002-06-16 20:06:15 +00:00
|
|
|
cent->ejectBrassTime = cg.time + 500;
|
2002-03-16 21:50:09 +00:00
|
|
|
else if (ent->weapon == WP_SSG3000)
|
2002-06-16 20:06:15 +00:00
|
|
|
cent->ejectBrassTime = cg.time + 650;
|
2002-03-24 22:46:23 +00:00
|
|
|
else if (ent->weapon != WP_KNIFE && ent->weapon != WP_GRENADE && ent->weapon != WP_HANDCANNON)
|
2002-03-16 21:50:09 +00:00
|
|
|
cent->ejectBrassTime = cg.time;
|
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
// mark the entity as muzzle flashing, so when it is added it will
|
|
|
|
// append the flash to the weapon model
|
2001-07-28 14:12:11 +00:00
|
|
|
if (weapModification != RQ3_WPMOD_SILENCER)
|
|
|
|
cent->muzzleFlashTime = cg.time;
|
2002-05-18 03:55:35 +00:00
|
|
|
else
|
|
|
|
cent->muzzleFlashTime = -1;
|
2001-09-01 16:15:01 +00:00
|
|
|
|
|
|
|
// Elder: choose alternate muzzle flashes for 3rd-person views
|
|
|
|
if (ent->weapon == WP_AKIMBO) {
|
|
|
|
if (cg.akimboFlash) {
|
|
|
|
cg.akimboFlash = 0;
|
|
|
|
} else {
|
|
|
|
cg.akimboFlash = 1;
|
|
|
|
}
|
|
|
|
}
|
2001-05-06 20:50:27 +00:00
|
|
|
// lightning gun only does this this on initial press
|
|
|
|
//Blaze: no more Lighting gun
|
|
|
|
/*
|
2002-06-16 20:06:15 +00:00
|
|
|
if ( ent->weapon == WP_LIGHTNING ) {
|
|
|
|
if ( cent->pe.lightningFiring ) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
// play quad sound if needed
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cent->currentState.powerups & (1 << PW_QUAD)) {
|
|
|
|
trap_S_StartSound(NULL, cent->currentState.number, CHAN_ITEM, cgs.media.quadSound);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
2001-07-28 14:12:11 +00:00
|
|
|
//Elder: silencer stuff
|
2002-06-16 20:06:15 +00:00
|
|
|
if (weapModification == RQ3_WPMOD_SILENCER) {
|
|
|
|
trap_S_StartSound(NULL, ent->number, CHAN_WEAPON, cgs.media.silencerSound);
|
|
|
|
} else // if (cg.snap->ps.weapon != WP_KNIFE)
|
2001-07-28 14:12:11 +00:00
|
|
|
{
|
2001-07-27 00:21:23 +00:00
|
|
|
// play a sound
|
2002-06-16 20:06:15 +00:00
|
|
|
for (c = 0; c < 4; c++) {
|
|
|
|
if (!weap->flashSound[c]) {
|
2001-07-27 00:21:23 +00:00
|
|
|
break;
|
|
|
|
}
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
2001-07-27 00:21:23 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (c > 0) {
|
2001-07-27 00:21:23 +00:00
|
|
|
c = rand() % c;
|
2002-06-16 20:06:15 +00:00
|
|
|
if (weap->flashSound[c]) {
|
|
|
|
trap_S_StartSound(NULL, ent->number, CHAN_WEAPON, weap->flashSound[c]);
|
2001-07-27 00:21:23 +00:00
|
|
|
}
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
2001-07-28 14:12:11 +00:00
|
|
|
}
|
2001-09-11 00:11:00 +00:00
|
|
|
|
|
|
|
// View kicks -- note this doesn't affect aim which is handled on the server-side
|
|
|
|
// even though it probably should
|
2002-06-16 20:06:15 +00:00
|
|
|
if (ent->clientNum == cg.snap->ps.clientNum) {
|
2001-09-11 00:11:00 +00:00
|
|
|
vec3_t forward;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
switch (cg.snap->ps.weapon) {
|
|
|
|
case WP_KNIFE:
|
|
|
|
AngleVectors(cg.predictedPlayerState.viewangles, forward, NULL, NULL);
|
|
|
|
VectorScale(forward, -2, cg.kick_origin);
|
|
|
|
cg.kick_angles[0] = -2;
|
|
|
|
cg.kick_time = cg.time;
|
|
|
|
cg.kick_duration = 200;
|
|
|
|
break;
|
|
|
|
case WP_PISTOL:
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
cg.kick_origin[i] = crandom() * 0.35f;
|
|
|
|
cg.kick_angles[i] = crandom() * 0.7f;
|
|
|
|
}
|
|
|
|
cg.kick_origin[0] = crandom() * 0.35f;
|
|
|
|
cg.kick_time = cg.time;
|
|
|
|
break;
|
|
|
|
case WP_M3:
|
|
|
|
AngleVectors(cg.predictedPlayerState.viewangles, forward, NULL, NULL);
|
|
|
|
VectorScale(forward, -2, cg.kick_origin);
|
|
|
|
cg.kick_angles[0] = -2;
|
|
|
|
cg.kick_time = cg.time;
|
|
|
|
break;
|
|
|
|
case WP_M4:
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
cg.kick_origin[i] = crandom() * 0.25f;
|
|
|
|
cg.kick_angles[i] = crandom() * 0.5f;
|
|
|
|
}
|
|
|
|
cg.kick_origin[0] = crandom() * 0.35f;
|
|
|
|
cg.kick_time = cg.time;
|
|
|
|
break;
|
|
|
|
case WP_MP5:
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
cg.kick_origin[i] = crandom() * 0.25f;
|
|
|
|
cg.kick_angles[i] = crandom() * 0.5f;
|
|
|
|
}
|
|
|
|
cg.kick_origin[0] = crandom() * 0.35f;
|
|
|
|
cg.kick_time = cg.time;
|
|
|
|
break;
|
|
|
|
case WP_HANDCANNON:
|
|
|
|
AngleVectors(cg.predictedPlayerState.viewangles, forward, NULL, NULL);
|
|
|
|
VectorScale(forward, -2, cg.kick_origin);
|
|
|
|
cg.kick_angles[0] = -2;
|
|
|
|
cg.kick_time = cg.time;
|
|
|
|
break;
|
|
|
|
case WP_AKIMBO:
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
|
|
cg.kick_origin[i] = crandom() * 0.25f;
|
|
|
|
cg.kick_angles[i] = crandom() * 0.5f;
|
|
|
|
}
|
|
|
|
cg.kick_origin[0] = crandom() * 0.35f;
|
|
|
|
cg.kick_time = cg.time;
|
|
|
|
break;
|
2001-09-11 00:11:00 +00:00
|
|
|
}
|
|
|
|
}
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
CG_MissileHitWall
|
|
|
|
|
|
|
|
Caused by an EV_MISSILE_MISS event, or directly by local bullet tracing
|
|
|
|
=================
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_MissileHitWall(int weapon, int clientNum, vec3_t origin,
|
|
|
|
vec3_t dir, impactSound_t soundType, int weapModification)
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
int angle;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-07-24 01:49:02 +00:00
|
|
|
//Elder: for impact smoke marks
|
2002-06-16 20:06:15 +00:00
|
|
|
localEntity_t *smokePuff;
|
|
|
|
vec3_t puffOrigin;
|
|
|
|
vec3_t puffOffset;
|
|
|
|
vec3_t puffDir;
|
|
|
|
int contentType;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-08-30 09:42:25 +00:00
|
|
|
//Elder: for impact sparks
|
2002-06-16 20:06:15 +00:00
|
|
|
vec3_t velocity;
|
|
|
|
int sparkCount;
|
|
|
|
int i;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
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;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
switch (weapon) {
|
2001-11-12 08:59:46 +00:00
|
|
|
// Elder: bullet weapons all fall under MK23 >:(
|
2002-06-16 20:06:15 +00:00
|
|
|
case WP_M4:
|
|
|
|
case WP_MP5:
|
|
|
|
case WP_PISTOL:
|
|
|
|
case WP_AKIMBO:
|
|
|
|
case WP_SSG3000:
|
|
|
|
duration = 160;
|
|
|
|
mod = cgs.media.hitSparkModel;
|
|
|
|
shader = cgs.media.hitSparkShader;
|
|
|
|
radius = 8;
|
|
|
|
r = rand() & 3;
|
|
|
|
|
|
|
|
if (soundType == IMPACTSOUND_METAL) {
|
|
|
|
mark = cgs.media.metalMarkShader;
|
|
|
|
if (r < 2)
|
|
|
|
sfx = cgs.media.sfx_metalric1;
|
|
|
|
else if (r == 2)
|
|
|
|
sfx = cgs.media.sfx_metalric2;
|
2001-10-30 23:23:04 +00:00
|
|
|
else
|
2002-06-16 20:06:15 +00:00
|
|
|
sfx = cgs.media.sfx_metalric3;
|
|
|
|
} else if (soundType == IMPACTSOUND_GLASS) {
|
|
|
|
mark = cgs.media.glassMarkShader;
|
|
|
|
if (r < 2)
|
|
|
|
sfx = cgs.media.sfx_glassric1;
|
|
|
|
else if (r == 2)
|
|
|
|
sfx = cgs.media.sfx_glassric2;
|
2001-10-30 23:23:04 +00:00
|
|
|
else
|
2002-06-16 20:06:15 +00:00
|
|
|
sfx = cgs.media.sfx_glassric3;
|
|
|
|
}
|
|
|
|
//Makro - added
|
|
|
|
else if (soundType == IMPACTSOUND_BRICK) {
|
|
|
|
mark = cgs.media.bulletMarkShader;
|
|
|
|
if (r < 2)
|
|
|
|
sfx = cgs.media.sfx_brickric1;
|
|
|
|
else if (r == 2)
|
|
|
|
sfx = cgs.media.sfx_brickric2;
|
2001-10-30 23:23:04 +00:00
|
|
|
else
|
2002-06-16 20:06:15 +00:00
|
|
|
sfx = cgs.media.sfx_brickric3;
|
|
|
|
}
|
|
|
|
//Makro - added
|
|
|
|
else if (soundType == IMPACTSOUND_WOOD) {
|
|
|
|
mark = cgs.media.bulletMarkShader;
|
|
|
|
if (r < 2)
|
|
|
|
sfx = cgs.media.sfx_woodric1;
|
|
|
|
else if (r == 2)
|
|
|
|
sfx = cgs.media.sfx_woodric2;
|
2001-10-30 23:23:04 +00:00
|
|
|
else
|
2002-06-16 20:06:15 +00:00
|
|
|
sfx = cgs.media.sfx_woodric3;
|
|
|
|
}
|
|
|
|
//Makro - added
|
|
|
|
else if (soundType == IMPACTSOUND_CERAMIC) {
|
|
|
|
mark = cgs.media.bulletMarkShader;
|
|
|
|
if (r < 2)
|
|
|
|
sfx = cgs.media.sfx_ceramicric1;
|
|
|
|
else if (r == 2)
|
|
|
|
sfx = cgs.media.sfx_ceramicric2;
|
2001-10-30 23:23:04 +00:00
|
|
|
else
|
2002-06-16 20:06:15 +00:00
|
|
|
sfx = cgs.media.sfx_ceramicric3;
|
|
|
|
} else {
|
|
|
|
mark = cgs.media.bulletMarkShader;
|
|
|
|
if (r == 0)
|
|
|
|
sfx = cgs.media.sfx_ric1;
|
|
|
|
else if (r == 1)
|
|
|
|
sfx = cgs.media.sfx_ric2;
|
2001-10-30 23:23:04 +00:00
|
|
|
else
|
2002-06-16 20:06:15 +00:00
|
|
|
sfx = cgs.media.sfx_ric3;
|
|
|
|
}
|
|
|
|
break;
|
2001-08-30 09:42:25 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
/*
|
|
|
|
//Blaze: Reaction M4
|
|
|
|
case WP_M4:
|
|
|
|
mod = cgs.media.bulletFlashModel;
|
|
|
|
shader = cgs.media.bulletExplosionShader;
|
|
|
|
if (soundType == IMPACTSOUND_GLASS)
|
|
|
|
mark = cgs.media.glassMarkShader;
|
|
|
|
else
|
|
|
|
mark = cgs.media.bulletMarkShader;
|
|
|
|
|
|
|
|
r = rand() & 3;
|
|
|
|
if (soundType == IMPACTSOUND_METAL)
|
|
|
|
{
|
|
|
|
if ( r < 2 ) {
|
|
|
|
sfx = cgs.media.sfx_metalric1;
|
|
|
|
} else if ( r == 2 ) {
|
|
|
|
sfx = cgs.media.sfx_metalric2;
|
|
|
|
} else {
|
|
|
|
sfx = cgs.media.sfx_metalric3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (soundType == IMPACTSOUND_GLASS)
|
|
|
|
{
|
|
|
|
if ( r < 2 ) {
|
|
|
|
sfx = cgs.media.sfx_glassric1;
|
|
|
|
} else if ( r == 2 ) {
|
|
|
|
sfx = cgs.media.sfx_glassric2;
|
|
|
|
} else {
|
|
|
|
sfx = cgs.media.sfx_glassric3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
//Blaze: Reaction Pistol
|
|
|
|
case WP_PISTOL:
|
|
|
|
mod = cgs.media.bulletFlashModel;
|
|
|
|
shader = cgs.media.bulletExplosionShader;
|
|
|
|
if (soundType == IMPACTSOUND_GLASS)
|
|
|
|
mark = cgs.media.glassMarkShader;
|
|
|
|
else
|
|
|
|
mark = cgs.media.bulletMarkShader;
|
|
|
|
|
|
|
|
r = rand() & 3;
|
|
|
|
if (soundType == IMPACTSOUND_METAL)
|
|
|
|
{
|
|
|
|
if ( r < 2 ) {
|
|
|
|
sfx = cgs.media.sfx_metalric1;
|
|
|
|
} else if ( r == 2 ) {
|
|
|
|
sfx = cgs.media.sfx_metalric2;
|
|
|
|
} else {
|
|
|
|
sfx = cgs.media.sfx_metalric3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (soundType == IMPACTSOUND_GLASS)
|
|
|
|
{
|
|
|
|
if ( r < 2 ) {
|
|
|
|
sfx = cgs.media.sfx_glassric1;
|
|
|
|
} else if ( r == 2 ) {
|
|
|
|
sfx = cgs.media.sfx_glassric2;
|
|
|
|
} else {
|
|
|
|
sfx = cgs.media.sfx_glassric3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
case WP_SSG3000:
|
|
|
|
mod = cgs.media.bulletFlashModel;
|
|
|
|
shader = cgs.media.bulletExplosionShader;
|
|
|
|
if (soundType == IMPACTSOUND_GLASS)
|
|
|
|
mark = cgs.media.glassMarkShader;
|
|
|
|
else
|
|
|
|
mark = cgs.media.bulletMarkShader;
|
|
|
|
|
|
|
|
r = rand() & 3;
|
|
|
|
if (soundType == IMPACTSOUND_METAL)
|
|
|
|
{
|
|
|
|
if ( r < 2 ) {
|
|
|
|
sfx = cgs.media.sfx_metalric1;
|
|
|
|
} else if ( r == 2 ) {
|
|
|
|
sfx = cgs.media.sfx_metalric2;
|
|
|
|
} else {
|
|
|
|
sfx = cgs.media.sfx_metalric3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (soundType == IMPACTSOUND_GLASS)
|
|
|
|
{
|
|
|
|
if ( r < 2 ) {
|
|
|
|
sfx = cgs.media.sfx_glassric1;
|
|
|
|
} else if ( r == 2 ) {
|
|
|
|
sfx = cgs.media.sfx_glassric2;
|
|
|
|
} else {
|
|
|
|
sfx = cgs.media.sfx_glassric3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
case WP_AKIMBO:
|
|
|
|
mod = cgs.media.bulletFlashModel;
|
|
|
|
shader = cgs.media.bulletExplosionShader;
|
|
|
|
if (soundType == IMPACTSOUND_GLASS)
|
|
|
|
mark = cgs.media.glassMarkShader;
|
|
|
|
else
|
|
|
|
mark = cgs.media.bulletMarkShader;
|
|
|
|
|
|
|
|
r = rand() & 3;
|
|
|
|
if (soundType == IMPACTSOUND_METAL)
|
|
|
|
{
|
|
|
|
if ( r < 2 ) {
|
|
|
|
sfx = cgs.media.sfx_metalric1;
|
|
|
|
} else if ( r == 2 ) {
|
|
|
|
sfx = cgs.media.sfx_metalric2;
|
|
|
|
} else {
|
|
|
|
sfx = cgs.media.sfx_metalric3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (soundType == IMPACTSOUND_GLASS)
|
|
|
|
{
|
|
|
|
if ( r < 2 ) {
|
|
|
|
sfx = cgs.media.sfx_glassric1;
|
|
|
|
} else if ( r == 2 ) {
|
|
|
|
sfx = cgs.media.sfx_glassric2;
|
|
|
|
} else {
|
|
|
|
sfx = cgs.media.sfx_glassric3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
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;
|
|
|
|
|
|
|
|
//Blaze: Reaction MP5
|
|
|
|
case WP_MP5:
|
|
|
|
mod = cgs.media.bulletFlashModel;
|
|
|
|
shader = cgs.media.bulletExplosionShader;
|
|
|
|
if (soundType == IMPACTSOUND_GLASS)
|
|
|
|
mark = cgs.media.glassMarkShader;
|
|
|
|
else
|
|
|
|
mark = cgs.media.bulletMarkShader;
|
|
|
|
|
|
|
|
r = rand() & 3;
|
|
|
|
if (soundType == IMPACTSOUND_METAL)
|
|
|
|
{
|
|
|
|
if ( r < 2 ) {
|
|
|
|
sfx = cgs.media.sfx_metalric1;
|
|
|
|
} else if ( r == 2 ) {
|
|
|
|
sfx = cgs.media.sfx_metalric2;
|
|
|
|
} else {
|
|
|
|
sfx = cgs.media.sfx_metalric3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (soundType == IMPACTSOUND_GLASS)
|
|
|
|
{
|
|
|
|
if ( r < 2 ) {
|
|
|
|
sfx = cgs.media.sfx_glassric1;
|
|
|
|
} else if ( r == 2 ) {
|
|
|
|
sfx = cgs.media.sfx_glassric2;
|
|
|
|
} else {
|
|
|
|
sfx = cgs.media.sfx_glassric3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( r == 0 ) {
|
|
|
|
sfx = cgs.media.sfx_ric1;
|
|
|
|
} else if ( r == 1 ) {
|
|
|
|
sfx = cgs.media.sfx_ric2;
|
|
|
|
} else {
|
|
|
|
sfx = cgs.media.sfx_ric3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
radius = 8;
|
|
|
|
break;
|
|
|
|
*/
|
2001-10-30 23:23:04 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
case WP_M3:
|
|
|
|
case WP_HANDCANNON:
|
|
|
|
duration = 200;
|
|
|
|
mod = cgs.media.hitSparkModel;
|
|
|
|
shader = cgs.media.hitSparkShader;
|
|
|
|
//mod = cgs.media.bulletFlashModel;
|
|
|
|
//shader = cgs.media.bulletExplosionShader;
|
|
|
|
if (soundType == IMPACTSOUND_GLASS)
|
|
|
|
mark = cgs.media.glassMarkShader;
|
|
|
|
else if (soundType == IMPACTSOUND_METAL)
|
|
|
|
mark = cgs.media.metalMarkShader;
|
|
|
|
else
|
|
|
|
mark = cgs.media.bulletMarkShader;
|
|
|
|
sfx = 0;
|
|
|
|
radius = 4;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WP_GRENADE:
|
|
|
|
mod = cgs.media.dishFlashModel;
|
|
|
|
shader = cgs.media.grenadeExplosionShader;
|
|
|
|
sfx = cgs.media.sfx_rockexp;
|
|
|
|
mark = cgs.media.burnMarkShader;
|
|
|
|
radius = 96; //64
|
|
|
|
light = 350; //300
|
|
|
|
isSprite = qtrue;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case WP_KNIFE:
|
|
|
|
/*
|
|
|
|
mod = cgs.media.dishFlashModel;
|
|
|
|
//shader = cgs.media.grenadeExplosionShader;
|
|
|
|
sfx = cgs.media.sfx_rockexp;
|
|
|
|
mark = cgs.media.burnMarkShader;
|
|
|
|
radius = 64;
|
|
|
|
light = 300;
|
|
|
|
isSprite = qtrue;
|
|
|
|
break;
|
|
|
|
*/
|
|
|
|
if (weapModification == RQ3_WPMOD_KNIFESLASH) {
|
|
|
|
duration = 100;
|
2001-11-12 08:59:46 +00:00
|
|
|
mod = cgs.media.hitSparkModel;
|
|
|
|
shader = cgs.media.hitSparkShader;
|
|
|
|
//mod = cgs.media.bulletFlashModel;
|
|
|
|
//shader = cgs.media.bulletExplosionShader;
|
2002-06-16 20:06:15 +00:00
|
|
|
mark = cgs.media.slashMarkShader;
|
|
|
|
sfx = cgs.media.knifeClankSound;
|
|
|
|
radius = rand() % 4 + 6;
|
|
|
|
} else {
|
|
|
|
duration = 180;
|
|
|
|
mod = cgs.media.hitSparkModel;
|
|
|
|
shader = cgs.media.hitSparkShader;
|
|
|
|
//mod = cgs.media.bulletFlashModel;
|
|
|
|
//shader = cgs.media.bulletExplosionShader;
|
|
|
|
sfx = cgs.media.knifeClankSound;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
2001-10-30 23:23:04 +00:00
|
|
|
//
|
|
|
|
// ricochet sound
|
|
|
|
//
|
2002-06-16 20:06:15 +00:00
|
|
|
if (weapon == WP_KNIFE || weapon == WP_SSG3000 || weapon == WP_GRENADE || soundType == IMPACTSOUND_METAL)
|
2001-08-13 17:25:06 +00:00
|
|
|
i = 1;
|
|
|
|
else
|
2001-08-30 09:42:25 +00:00
|
|
|
//Elder: 90% of the time render a bullet ricochet sound
|
|
|
|
i = rand() % 10;
|
2001-08-13 17:25:06 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (sfx && i < 9) {
|
|
|
|
trap_S_StartSound(origin, ENTITYNUM_WORLD, CHAN_AUTO, sfx);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
//
|
|
|
|
// create the explosion
|
|
|
|
//
|
2002-06-16 20:06:15 +00:00
|
|
|
if (mod) {
|
|
|
|
if (weapon == WP_GRENADE) {
|
|
|
|
le = CG_MakeExplosion(origin, dir, mod, shader, duration, isSprite);
|
2001-11-12 08:59:46 +00:00
|
|
|
le->light = light;
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorCopy(lightColor, le->lightColor);
|
2002-04-03 03:13:49 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
} else if (cg_RQ3_impactEffects.integer) {
|
2001-11-12 08:59:46 +00:00
|
|
|
vec3_t temp, offsetDir;
|
|
|
|
byte color[4];
|
|
|
|
int flashCount;
|
|
|
|
float scale;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
switch (weapon) {
|
|
|
|
case WP_MP5:
|
|
|
|
case WP_PISTOL:
|
|
|
|
case WP_AKIMBO:
|
|
|
|
flashCount = 3 + rand() % 3;
|
|
|
|
color[0] = 224;
|
|
|
|
color[1] = 180;
|
|
|
|
color[2] = 128;
|
|
|
|
color[3] = 192;
|
|
|
|
break;
|
|
|
|
case WP_M4:
|
|
|
|
case WP_KNIFE:
|
|
|
|
flashCount = 3 + rand() % 3;
|
|
|
|
color[0] = 192;
|
|
|
|
color[1] = 96;
|
|
|
|
color[2] = 64;
|
|
|
|
color[3] = 192;
|
|
|
|
break;
|
|
|
|
case WP_M3:
|
|
|
|
case WP_HANDCANNON:
|
|
|
|
flashCount = 2 + rand() % 3;
|
|
|
|
color[0] = 192;
|
|
|
|
color[1] = 96;
|
|
|
|
color[2] = 64;
|
|
|
|
color[3] = 192;
|
|
|
|
break;
|
|
|
|
case WP_SSG3000:
|
|
|
|
default:
|
|
|
|
flashCount = 4 + rand() % 3;
|
|
|
|
color[0] = 255;
|
|
|
|
color[1] = 224;
|
|
|
|
color[2] = 128;
|
|
|
|
color[3] = 192;
|
|
|
|
break;
|
2001-11-12 08:59:46 +00:00
|
|
|
}
|
2001-11-25 23:04:08 +00:00
|
|
|
|
2001-11-12 08:59:46 +00:00
|
|
|
// Elder: should probably dump this into another function
|
2002-06-16 20:06:15 +00:00
|
|
|
for (i = 0; i < flashCount; i++) {
|
2001-11-12 08:59:46 +00:00
|
|
|
// introduce variance
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorCopy(dir, temp);
|
2001-11-12 08:59:46 +00:00
|
|
|
scale = crandom() + 1.8f;
|
|
|
|
temp[0] += (crandom() * 0.4f) - 0.2f;
|
|
|
|
temp[1] += (crandom() * 0.4f) - 0.2f;
|
|
|
|
temp[2] += (crandom() * 0.4f) - 0.2f;
|
|
|
|
// save result
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorCopy(temp, offsetDir);
|
|
|
|
VectorScale(temp, scale, temp);
|
2001-11-12 08:59:46 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
le = CG_MakeExplosion(origin, dir, mod, shader, duration, isSprite);
|
2001-11-12 08:59:46 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorMA(origin, scale + 0.5f, temp, le->refEntity.origin);
|
2001-11-12 08:59:46 +00:00
|
|
|
VectorCopy(temp, le->refEntity.axis[0]);
|
2001-11-25 23:04:08 +00:00
|
|
|
|
2001-11-12 08:59:46 +00:00
|
|
|
// set spark colour
|
|
|
|
le->refEntity.shaderRGBA[0] = color[0];
|
|
|
|
le->refEntity.shaderRGBA[1] = color[1];
|
|
|
|
le->refEntity.shaderRGBA[2] = color[2];
|
|
|
|
le->refEntity.shaderRGBA[3] = color[3];
|
2001-11-25 23:04:08 +00:00
|
|
|
|
2001-11-12 08:59:46 +00:00
|
|
|
// readjust behaviour
|
|
|
|
le->leType = LE_MOVE_SCALE_FADE;
|
|
|
|
le->pos.trType = TR_LINEAR;
|
|
|
|
le->pos.trTime = cg.time;
|
|
|
|
VectorCopy(le->refEntity.origin, le->pos.trBase);
|
|
|
|
VectorScale(offsetDir, 30, le->pos.trDelta);
|
2001-11-25 23:04:08 +00:00
|
|
|
|
2001-11-12 08:59:46 +00:00
|
|
|
le->light = light;
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorCopy(lightColor, le->lightColor);
|
2001-11-12 08:59:46 +00:00
|
|
|
}
|
|
|
|
}
|
2001-05-06 20:50:27 +00:00
|
|
|
//Blaze: No railgun
|
|
|
|
/*
|
2002-06-16 20:06:15 +00:00
|
|
|
if ( weapon == WP_RAILGUN ) {
|
|
|
|
// colorize with client color
|
|
|
|
VectorCopy( cgs.clientinfo[clientNum].color1, le->color );
|
|
|
|
}
|
|
|
|
*/
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
//
|
|
|
|
// impact mark
|
|
|
|
//
|
|
|
|
alphaFade = (mark == cgs.media.energyMarkShader); // plasma fades alpha, all others fade color
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
//Blaze: No more railgun
|
2001-10-30 23:23:04 +00:00
|
|
|
/*
|
2002-06-16 20:06:15 +00:00
|
|
|
if ( weapon == WP_RAILGUN ) {
|
|
|
|
float *color;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
// 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 {
|
|
|
|
*/
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-10-30 23:23:04 +00:00
|
|
|
// Elder: Our knife slashes are vertical
|
2001-08-18 20:01:21 +00:00
|
|
|
if (weapon == WP_KNIFE)
|
2001-10-30 23:23:04 +00:00
|
|
|
angle = random() * 90;
|
2001-08-18 20:01:21 +00:00
|
|
|
else
|
|
|
|
angle = random() * 360;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (mark)
|
|
|
|
CG_ImpactMark(mark, origin, dir, angle, 1, 1, 1, 1, alphaFade, radius, qfalse);
|
2001-05-06 20:50:27 +00:00
|
|
|
//}
|
2001-07-24 01:49:02 +00:00
|
|
|
|
2001-10-30 23:23:04 +00:00
|
|
|
//
|
|
|
|
// impact visual effects
|
|
|
|
//
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-07-24 01:49:02 +00:00
|
|
|
//Elder: 75% of the time render a smoke puff
|
2001-08-30 09:42:25 +00:00
|
|
|
i = rand() % 4;
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg_RQ3_impactEffects.integer && i < 3) {
|
|
|
|
contentType = trap_CM_PointContents(origin, 0);
|
2001-09-01 16:15:01 +00:00
|
|
|
// no puff in water
|
2002-06-16 20:06:15 +00:00
|
|
|
if (!(contentType & CONTENTS_WATER)) {
|
|
|
|
switch (weapon) {
|
|
|
|
case WP_MP5:
|
|
|
|
case WP_M4:
|
|
|
|
case WP_PISTOL:
|
|
|
|
case WP_AKIMBO:
|
|
|
|
case WP_SSG3000:
|
|
|
|
puffDir[0] = 0;
|
|
|
|
puffDir[1] = 0;
|
|
|
|
puffDir[2] = 16;
|
|
|
|
|
|
|
|
VectorCopy(dir, puffOffset);
|
|
|
|
VectorNormalize(puffOffset);
|
|
|
|
VectorNegate(puffOffset, puffOffset);
|
|
|
|
VectorScale(puffOffset, 13, puffOffset);
|
|
|
|
VectorSubtract(origin, puffOffset, puffOrigin);
|
|
|
|
smokePuff = CG_SmokePuff(puffOrigin, puffDir,
|
|
|
|
(int) (random() * 100) % 4 + 13,
|
|
|
|
1, 1, 1, 0.25f,
|
|
|
|
650,
|
|
|
|
cg.time, 0,
|
|
|
|
LEF_PUFF_DONT_SCALE, cgs.media.smokePuffAnimShader);
|
|
|
|
break;
|
2001-09-01 16:15:01 +00:00
|
|
|
}
|
2001-07-24 01:49:02 +00:00
|
|
|
}
|
|
|
|
}
|
2001-08-30 09:42:25 +00:00
|
|
|
// Elder: Spark effect for metal surfaces
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg_RQ3_impactEffects.integer && soundType == IMPACTSOUND_METAL) {
|
|
|
|
if (weapon != WP_GRENADE) {
|
2001-08-30 09:42:25 +00:00
|
|
|
if (weapon == WP_M3 || weapon == WP_HANDCANNON)
|
|
|
|
sparkCount = 5 + rand() % 5;
|
|
|
|
else if (weapon == WP_KNIFE)
|
|
|
|
sparkCount = 10 + rand() % 10;
|
|
|
|
else if (weapon == WP_SSG3000)
|
|
|
|
sparkCount = 25 + rand() % 20;
|
|
|
|
else
|
|
|
|
sparkCount = 15 + rand() % 15;
|
|
|
|
|
|
|
|
// Generate the particles
|
2002-06-16 20:06:15 +00:00
|
|
|
for (i = 0; i < sparkCount; i++) {
|
2001-08-30 09:42:25 +00:00
|
|
|
if (weapon == WP_KNIFE)
|
2002-05-27 06:58:40 +00:00
|
|
|
VectorScale(dir, 50 + rand() % 10, velocity);
|
2001-08-30 09:42:25 +00:00
|
|
|
else
|
2002-05-27 06:58:40 +00:00
|
|
|
VectorScale(dir, 150 + rand() % 30, velocity);
|
2001-08-30 09:42:25 +00:00
|
|
|
//random upwards sparks
|
2002-06-16 20:06:15 +00:00
|
|
|
if (rand() % 5 < 1)
|
2001-08-30 09:42:25 +00:00
|
|
|
velocity[2] += 120 + rand() % 30;
|
|
|
|
|
|
|
|
velocity[0] += rand() % 50 - 25;
|
|
|
|
velocity[1] += rand() % 50 - 25;
|
2002-06-16 20:06:15 +00:00
|
|
|
// CG_ParticleSparks(origin, velocity, 100 + rand() % 120, 2, 2, -4, 1);
|
2001-12-17 15:06:41 +00:00
|
|
|
// NiceAss: Longer life, faster sparks == more eye candy! =)
|
|
|
|
CG_ParticleSparks(origin, velocity, 150 + rand() % 120, 2, 2, -5, 1);
|
2001-08-30 09:42:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Elder: grenade explosion
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg_RQ3_impactEffects.integer && weapon == WP_GRENADE) {
|
2002-04-03 03:13:49 +00:00
|
|
|
|
2001-09-01 16:15:01 +00:00
|
|
|
vec3_t shrapnelDest;
|
|
|
|
|
|
|
|
sparkCount = 60 + rand() % 10;
|
2001-08-30 09:42:25 +00:00
|
|
|
origin[2] += 32;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
for (i = 0; i < sparkCount; i++) {
|
|
|
|
VectorScale(dir, rand() % 200, velocity);
|
2001-08-30 09:42:25 +00:00
|
|
|
velocity[0] += rand() % 200 - 100;
|
|
|
|
velocity[1] += rand() % 200 - 100;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (i % 8 == 7) {
|
2001-09-01 16:15:01 +00:00
|
|
|
// Add shrapnel trace effect
|
|
|
|
VectorMA(origin, 0.7f, velocity, shrapnelDest);
|
|
|
|
CG_ShrapnelSpark(origin, shrapnelDest, 10, 280);
|
|
|
|
}
|
|
|
|
// Add sparks
|
2001-08-30 09:42:25 +00:00
|
|
|
CG_ParticleSparks(origin, velocity, 900 + rand() % 200, 5, 5, -2.5f, 3.5f);
|
|
|
|
}
|
2001-09-01 16:15:01 +00:00
|
|
|
|
|
|
|
// Add smoke puff
|
|
|
|
puffDir[0] = 0;
|
|
|
|
puffDir[1] = 0;
|
|
|
|
puffDir[2] = 20;
|
|
|
|
origin[2] -= 16;
|
2002-06-16 20:06:15 +00:00
|
|
|
smokePuff = CG_SmokePuff(origin, puffDir,
|
|
|
|
rand() % 12 + 48,
|
|
|
|
1, 1, 1, 0.4f, 1750, cg.time, 0, 0, cgs.media.smokePuffShader);
|
2001-08-30 09:42:25 +00:00
|
|
|
}
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
=================
|
|
|
|
CG_MissileHitPlayer
|
|
|
|
=================
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_MissileHitPlayer(int weapon, vec3_t origin, vec3_t dir, int entityNum)
|
|
|
|
{
|
|
|
|
CG_Bleed(origin, entityNum);
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
// some weapons will make an explosion with the blood, while
|
|
|
|
// others will just make the blood
|
|
|
|
//Blaze: None of these are valid
|
|
|
|
/*
|
2002-06-16 20:06:15 +00:00
|
|
|
switch ( weapon ) {
|
|
|
|
case WP_GRENADE_LAUNCHER:
|
|
|
|
case WP_ROCKET_LAUNCHER:
|
|
|
|
CG_MissileHitWall( weapon, 0, origin, dir, IMPACTSOUND_FLESH, 0 );
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
*/
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
============================================================================
|
|
|
|
|
|
|
|
SHOTGUN TRACING
|
|
|
|
|
|
|
|
============================================================================
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
CG_ShotgunPellet
|
2001-06-26 01:58:02 +00:00
|
|
|
|
|
|
|
Elder: added shellWeapon param
|
|
|
|
We are not going to show every HC impact
|
2001-05-06 20:50:27 +00:00
|
|
|
================
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
static void CG_ShotgunPellet(vec3_t start, vec3_t end, int skipNum, int shellWeapon)
|
|
|
|
{
|
|
|
|
trace_t tr;
|
2001-05-06 20:50:27 +00:00
|
|
|
int sourceContentType, destContentType;
|
2002-06-16 20:06:15 +00:00
|
|
|
|
2002-04-06 21:43:59 +00:00
|
|
|
//Makro
|
2002-06-16 20:06:15 +00:00
|
|
|
int Material;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_Trace(&tr, start, NULL, NULL, end, skipNum, MASK_SHOT);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
sourceContentType = trap_CM_PointContents(start, 0);
|
|
|
|
destContentType = trap_CM_PointContents(tr.endpos, 0);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
// FIXME: should probably move this cruft into CG_BubbleTrail
|
2002-06-16 20:06:15 +00:00
|
|
|
if (sourceContentType == destContentType) {
|
|
|
|
if (sourceContentType & CONTENTS_WATER) {
|
|
|
|
CG_BubbleTrail(start, tr.endpos, 32);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
} else if (sourceContentType & CONTENTS_WATER) {
|
2001-05-06 20:50:27 +00:00
|
|
|
trace_t trace;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
trap_CM_BoxTrace(&trace, end, start, NULL, NULL, 0, CONTENTS_WATER);
|
|
|
|
CG_BubbleTrail(start, trace.endpos, 32);
|
|
|
|
} else if (destContentType & CONTENTS_WATER) {
|
2001-05-06 20:50:27 +00:00
|
|
|
trace_t trace;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
trap_CM_BoxTrace(&trace, start, end, NULL, NULL, 0, CONTENTS_WATER);
|
|
|
|
CG_BubbleTrail(tr.endpos, trace.endpos, 32);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (tr.surfaceFlags & SURF_NOIMPACT) {
|
2001-05-06 20:50:27 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg_entities[tr.entityNum].currentState.eType == ET_PLAYER) {
|
2001-05-06 20:50:27 +00:00
|
|
|
//Blaze: Changed WP_SHOTGUN to WP_M3
|
2001-07-28 14:12:11 +00:00
|
|
|
//Elder: don't display so many blood stains - so we can reduce slow down
|
|
|
|
cg.shellHits++;
|
|
|
|
if (cg.shellHits < MAX_SHELL_HITS)
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_MissileHitPlayer(WP_M3, tr.endpos, tr.plane.normal, tr.entityNum);
|
|
|
|
} else {
|
|
|
|
if (tr.surfaceFlags & SURF_NOIMPACT) {
|
2001-05-06 20:50:27 +00:00
|
|
|
// SURF_NOIMPACT will not make a flame puff or a mark
|
|
|
|
return;
|
|
|
|
}
|
2002-04-06 21:43:59 +00:00
|
|
|
//Makro - new surfaceparm system
|
|
|
|
Material = GetMaterialFromFlag(tr.surfaceFlags);
|
|
|
|
//if ( (tr.surfaceFlags & SURF_METALSTEPS) || (tr.surfaceFlags & SURF_METAL2) )
|
2002-06-16 20:06:15 +00:00
|
|
|
if (IsMetalMat(Material)) {
|
2001-05-06 20:50:27 +00:00
|
|
|
//Blaze: Changed WP_SHOTGUN to WP_M3
|
2001-06-26 01:58:02 +00:00
|
|
|
if (shellWeapon == WP_M3)
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_MissileHitWall(WP_M3, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_METAL, 0);
|
|
|
|
else if (shellWeapon == WP_HANDCANNON && crandom() > 0.5) {
|
2001-06-26 01:58:02 +00:00
|
|
|
//Elder: show only approximately every other impact mark
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_MissileHitWall(WP_HANDCANNON, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_METAL, 0);
|
2001-11-11 20:03:09 +00:00
|
|
|
}
|
2001-07-28 14:12:11 +00:00
|
|
|
}
|
2002-04-06 21:43:59 +00:00
|
|
|
//else if ( tr.surfaceFlags & SURF_GLASS )
|
2002-06-16 20:06:15 +00:00
|
|
|
else if (Material == MAT_GLASS) {
|
2001-10-11 22:50:58 +00:00
|
|
|
//Blaze: Changed WP_SHOTGUN to WP_M3
|
|
|
|
if (shellWeapon == WP_M3)
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_MissileHitWall(WP_M3, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_GLASS, 0);
|
|
|
|
else if (shellWeapon == WP_HANDCANNON && crandom() > 0.5) {
|
2001-10-11 22:50:58 +00:00
|
|
|
//Elder: show only approximately every other impact mark
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_MissileHitWall(WP_HANDCANNON, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_GLASS, 0);
|
2001-10-11 22:50:58 +00:00
|
|
|
}
|
|
|
|
}
|
2002-05-12 14:40:28 +00:00
|
|
|
//Makro - added
|
2002-06-16 20:06:15 +00:00
|
|
|
else if (IsWoodMat(Material)) {
|
2002-05-12 14:40:28 +00:00
|
|
|
//Blaze: Changed WP_SHOTGUN to WP_M3
|
|
|
|
if (shellWeapon == WP_M3)
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_MissileHitWall(WP_M3, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_WOOD, 0);
|
|
|
|
else if (shellWeapon == WP_HANDCANNON && crandom() > 0.5) {
|
2002-05-12 14:40:28 +00:00
|
|
|
//Elder: show only approximately every other impact mark
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_MissileHitWall(WP_HANDCANNON, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_WOOD, 0);
|
2002-05-12 14:40:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
//Makro - added
|
2002-06-16 20:06:15 +00:00
|
|
|
else if (Material == MAT_BRICK) {
|
2002-05-12 14:40:28 +00:00
|
|
|
//Blaze: Changed WP_SHOTGUN to WP_M3
|
|
|
|
if (shellWeapon == WP_M3)
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_MissileHitWall(WP_M3, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_BRICK, 0);
|
|
|
|
else if (shellWeapon == WP_HANDCANNON && crandom() > 0.5) {
|
2002-05-12 14:40:28 +00:00
|
|
|
//Elder: show only approximately every other impact mark
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_MissileHitWall(WP_HANDCANNON, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_BRICK, 0);
|
2002-05-12 14:40:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
//Makro - added
|
2002-06-16 20:06:15 +00:00
|
|
|
else if (Material == MAT_CERAMIC) {
|
2002-05-12 14:40:28 +00:00
|
|
|
//Blaze: Changed WP_SHOTGUN to WP_M3
|
|
|
|
if (shellWeapon == WP_M3)
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_MissileHitWall(WP_M3, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_CERAMIC, 0);
|
|
|
|
else if (shellWeapon == WP_HANDCANNON && crandom() > 0.5) {
|
2002-05-12 14:40:28 +00:00
|
|
|
//Elder: show only approximately every other impact mark
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_MissileHitWall(WP_HANDCANNON, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_CERAMIC, 0);
|
2002-05-12 14:40:28 +00:00
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
} else {
|
2001-10-30 23:23:04 +00:00
|
|
|
// Elder: By default, the M3 and HC will spark on all surfaces
|
|
|
|
// Blaze: Changed WP_SHOTGUN to WP_M3
|
2001-06-26 01:58:02 +00:00
|
|
|
if (shellWeapon == WP_M3)
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_MissileHitWall(WP_M3, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_METAL, 0);
|
|
|
|
else if (shellWeapon == WP_HANDCANNON && crandom() > 0.5) {
|
2001-06-26 01:58:02 +00:00
|
|
|
//Elder: show only approximately every other impact mark
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_MissileHitWall(WP_HANDCANNON, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_METAL, 0);
|
2001-06-26 01:58:02 +00:00
|
|
|
}
|
2001-08-18 20:01:21 +00:00
|
|
|
//CG_MissileHitWall( WP_M3, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_DEFAULT, 0 );
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
================
|
|
|
|
CG_ShotgunPattern
|
|
|
|
|
|
|
|
Perform the same traces the server did to locate the
|
2001-08-01 21:07:48 +00:00
|
|
|
hit splashes
|
2001-05-06 20:50:27 +00:00
|
|
|
================
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
static void CG_ShotgunPattern(vec3_t origin, vec3_t origin2, int otherEntNum, int shotType, int seed)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
float r, u;
|
|
|
|
vec3_t end;
|
|
|
|
vec3_t forward, right, up;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
int count;
|
|
|
|
int hc_multipler = 0;
|
2001-06-24 02:07:17 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
// derive the right and up vectors from the forward vector, because
|
|
|
|
// the client won't have any other information
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorNormalize2(origin2, forward);
|
|
|
|
PerpendicularVector(right, forward);
|
|
|
|
CrossProduct(forward, right, up);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
// generate the "random" spread pattern
|
2001-06-24 02:07:17 +00:00
|
|
|
|
|
|
|
//Elder: added
|
|
|
|
if (shotType == WP_M3)
|
|
|
|
count = DEFAULT_M3_COUNT;
|
|
|
|
else if (shotType == WP_HANDCANNON) {
|
|
|
|
count = DEFAULT_HANDCANNON_COUNT;
|
|
|
|
hc_multipler = 4;
|
2002-06-16 20:06:15 +00:00
|
|
|
} else {
|
2001-06-24 02:07:17 +00:00
|
|
|
count = DEFAULT_HANDCANNON_COUNT;
|
|
|
|
hc_multipler = 5;
|
|
|
|
}
|
|
|
|
|
2001-07-28 14:12:11 +00:00
|
|
|
cg.shellHits = 0;
|
2002-06-16 20:06:15 +00:00
|
|
|
for (i = 0; i < count; i++) {
|
|
|
|
if (shotType == WP_M3) {
|
2001-07-24 01:49:02 +00:00
|
|
|
r = Q_crandom(&seed) * DEFAULT_M3_HSPREAD * 16;
|
|
|
|
u = Q_crandom(&seed) * DEFAULT_M3_VSPREAD * 16;
|
|
|
|
//r = crandom() * DEFAULT_M3_HSPREAD * 16;
|
|
|
|
//u = crandom() * DEFAULT_M3_VSPREAD * 16;
|
2001-06-24 02:07:17 +00:00
|
|
|
//r = crandom() * DEFAULT_SHOTGUN_SPREAD * 16;
|
|
|
|
//u = crandom() * DEFAULT_SHOTGUN_SPREAD * 16;
|
2002-06-16 20:06:15 +00:00
|
|
|
} else {
|
2001-06-26 01:58:02 +00:00
|
|
|
//Elder: fill in shotType
|
|
|
|
shotType = WP_HANDCANNON;
|
2001-07-24 01:49:02 +00:00
|
|
|
r = Q_crandom(&seed) * DEFAULT_SHOTGUN_HSPREAD * 16 * 4;
|
|
|
|
u = Q_crandom(&seed) * DEFAULT_SHOTGUN_VSPREAD * 16 * hc_multipler;
|
2002-06-16 20:06:15 +00:00
|
|
|
// r = crandom() * DEFAULT_HANDCANNON_SPREAD * 16 * 4;
|
|
|
|
// u = crandom() * DEFAULT_HANDCANNON_SPREAD * 16 * 4;
|
2001-07-24 01:49:02 +00:00
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorMA(origin, 8192 * 16, forward, end);
|
|
|
|
VectorMA(end, r, right, end);
|
|
|
|
VectorMA(end, u, up, end);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_ShotgunPellet(origin, end, otherEntNum, shotType);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
2001-07-28 14:12:11 +00:00
|
|
|
//Reset shellHits once we're finished with it
|
|
|
|
cg.shellHits = 0;
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==============
|
|
|
|
CG_ShotgunFire
|
|
|
|
==============
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_ShotgunFire(entityState_t * es, qboolean ism3)
|
|
|
|
{
|
|
|
|
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) {
|
2001-05-06 20:50:27 +00:00
|
|
|
// ragepro can't alpha fade, so don't even bother with smoke
|
2002-06-16 20:06:15 +00:00
|
|
|
vec3_t up;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
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);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
}
|
2001-06-24 02:07:17 +00:00
|
|
|
//Elder: note param changes
|
2002-06-16 20:06:15 +00:00
|
|
|
if (ism3) {
|
|
|
|
CG_ShotgunPattern(es->pos.trBase, es->origin2, es->otherEntityNum, WP_M3, es->eventParm);
|
|
|
|
} else {
|
|
|
|
CG_ShotgunPattern(es->pos.trBase, es->origin2, es->otherEntityNum, WP_HANDCANNON, es->eventParm);
|
2001-07-24 01:49:02 +00:00
|
|
|
es->angles2[1] += 20;
|
|
|
|
//es->origin2[1] += 5;
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_ShotgunPattern(es->pos.trBase, es->origin2, es->otherEntityNum, -1, es->eventParm);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
============================================================================
|
|
|
|
|
|
|
|
BULLETS
|
|
|
|
|
|
|
|
============================================================================
|
|
|
|
*/
|
|
|
|
|
2002-05-09 06:45:14 +00:00
|
|
|
/*
|
|
|
|
===============
|
2002-05-18 03:55:35 +00:00
|
|
|
CG_CreateTracer
|
2002-05-09 06:45:14 +00:00
|
|
|
- NiceAss
|
|
|
|
===============
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_CreateTracer(int entity, vec3_t start, vec3_t end)
|
|
|
|
{
|
|
|
|
localEntity_t *le;
|
|
|
|
float dist;
|
2002-06-05 09:40:10 +00:00
|
|
|
vec3_t dir, end2;
|
2002-05-18 03:55:35 +00:00
|
|
|
vec3_t temp, midpoint;
|
2002-06-16 20:06:15 +00:00
|
|
|
float tracerSpeed = 4200;
|
2002-05-09 06:45:14 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorSubtract(end, start, dir);
|
|
|
|
dist = VectorNormalize(dir);
|
2002-05-09 06:45:14 +00:00
|
|
|
|
2002-05-18 03:55:35 +00:00
|
|
|
if (dist < 1.5 * cg_tracerLength.value)
|
|
|
|
return;
|
2002-05-09 06:45:14 +00:00
|
|
|
|
2002-05-18 03:55:35 +00:00
|
|
|
// Stop right before the end
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorMA(end, -cg_tracerLength.value, dir, end2);
|
2002-05-09 06:45:14 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorSubtract(end2, start, temp);
|
|
|
|
dist = VectorLength(temp);
|
2002-05-09 06:45:14 +00:00
|
|
|
|
|
|
|
le = CG_AllocLocalEntity();
|
2002-05-18 03:55:35 +00:00
|
|
|
le->leType = LE_TRACER;
|
|
|
|
le->startTime = cg.time;
|
|
|
|
le->endTime = le->startTime + 1000.0 * (dist / tracerSpeed);
|
2002-05-09 06:45:14 +00:00
|
|
|
|
|
|
|
le->pos.trType = TR_LINEAR;
|
|
|
|
le->pos.trTime = le->startTime;
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorCopy(start, le->pos.trBase);
|
|
|
|
VectorScale(dir, tracerSpeed, le->pos.trDelta);
|
2002-05-09 06:45:14 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
midpoint[0] = (start[0] + end2[0]) * 0.5;
|
|
|
|
midpoint[1] = (start[1] + end2[1]) * 0.5;
|
|
|
|
midpoint[2] = (start[2] + end2[2]) * 0.5;
|
|
|
|
trap_S_StartSound(midpoint, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.tracerSound);
|
2002-05-09 06:45:14 +00:00
|
|
|
}
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
===============
|
|
|
|
CG_Tracer
|
|
|
|
===============
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
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;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
// tracer
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorSubtract(dest, source, forward);
|
|
|
|
len = VectorNormalize(forward);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
// start at least a little ways from the muzzle
|
2002-06-16 20:06:15 +00:00
|
|
|
if (len < 100) {
|
2001-05-06 20:50:27 +00:00
|
|
|
return;
|
|
|
|
}
|
2002-05-09 06:45:14 +00:00
|
|
|
|
2001-05-06 20:50:27 +00:00
|
|
|
begin = 50 + random() * (len - 60);
|
|
|
|
end = begin + cg_tracerLength.value;
|
2002-06-16 20:06:15 +00:00
|
|
|
if (end > len) {
|
2001-05-06 20:50:27 +00:00
|
|
|
end = len;
|
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorMA(source, begin, forward, start);
|
|
|
|
VectorMA(source, end, forward, finish);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
line[0] = DotProduct(forward, cg.refdef.viewaxis[1]);
|
|
|
|
line[1] = DotProduct(forward, cg.refdef.viewaxis[2]);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorScale(cg.refdef.viewaxis[1], line[1], right);
|
|
|
|
VectorMA(right, -line[0], cg.refdef.viewaxis[2], right);
|
|
|
|
VectorNormalize(right);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorMA(finish, cg_tracerWidth.value, right, verts[0].xyz);
|
2001-05-06 20:50:27 +00:00
|
|
|
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;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorMA(finish, -cg_tracerWidth.value, right, verts[1].xyz);
|
2001-05-06 20:50:27 +00:00
|
|
|
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;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorMA(start, -cg_tracerWidth.value, right, verts[2].xyz);
|
2001-05-06 20:50:27 +00:00
|
|
|
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;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorMA(start, cg_tracerWidth.value, right, verts[3].xyz);
|
2001-05-06 20:50:27 +00:00
|
|
|
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;
|
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
trap_R_AddPolyToScene(cgs.media.tracerShader, 4, verts);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
2002-05-09 06:45:14 +00:00
|
|
|
//midpoint[0] = ( start[0] + finish[0] ) * 0.5;
|
|
|
|
//midpoint[1] = ( start[1] + finish[1] ) * 0.5;
|
|
|
|
//midpoint[2] = ( start[2] + finish[2] ) * 0.5;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
// add the tracer sound
|
2002-05-09 06:45:14 +00:00
|
|
|
// trap_S_StartSound( midpoint, ENTITYNUM_WORLD, CHAN_AUTO, cgs.media.tracerSound );
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
======================
|
|
|
|
CG_Bullet
|
|
|
|
|
|
|
|
Renders bullet effects.
|
2001-08-30 09:42:25 +00:00
|
|
|
Elder: added soundType conditional
|
2001-05-06 20:50:27 +00:00
|
|
|
======================
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_Bullet(vec3_t end, int sourceEntityNum, vec3_t normal,
|
|
|
|
qboolean flesh, int fleshEntityNum, impactSound_t soundType)
|
|
|
|
{
|
2001-05-06 20:50:27 +00:00
|
|
|
trace_t trace;
|
|
|
|
int sourceContentType, destContentType;
|
2002-06-16 20:06:15 +00:00
|
|
|
vec3_t start;
|
|
|
|
centity_t *cent;
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
// if the shooter is currently valid, calc a source point and possibly
|
|
|
|
// do trail effects
|
2002-06-16 20:06:15 +00:00
|
|
|
if (sourceEntityNum >= 0 && cg_tracerChance.value > 0) {
|
|
|
|
if (CG_CalcMuzzlePoint(sourceEntityNum, start)) {
|
|
|
|
sourceContentType = trap_CM_PointContents(start, 0);
|
|
|
|
destContentType = trap_CM_PointContents(end, 0);
|
2001-05-06 20:50:27 +00:00
|
|
|
|
|
|
|
// do a complete bubble trail if necessary
|
2002-06-16 20:06:15 +00:00
|
|
|
if ((sourceContentType == destContentType) && (sourceContentType & CONTENTS_WATER)) {
|
|
|
|
CG_BubbleTrail(start, end, 32);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
// bubble trail from water into air
|
2002-06-16 20:06:15 +00:00
|
|
|
else if ((sourceContentType & CONTENTS_WATER)) {
|
|
|
|
trap_CM_BoxTrace(&trace, end, start, NULL, NULL, 0, CONTENTS_WATER);
|
|
|
|
CG_BubbleTrail(start, trace.endpos, 32);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
// bubble trail from air into water
|
2002-06-16 20:06:15 +00:00
|
|
|
else if ((destContentType & CONTENTS_WATER)) {
|
|
|
|
trap_CM_BoxTrace(&trace, start, end, NULL, NULL, 0, CONTENTS_WATER);
|
|
|
|
CG_BubbleTrail(trace.endpos, end, 32);
|
2001-09-01 16:15:01 +00:00
|
|
|
// TODO: water splash mark
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
// draw a tracer
|
2001-08-13 17:25:06 +00:00
|
|
|
// Elder: only if not using SSG, check if this client is the source
|
2002-06-16 20:06:15 +00:00
|
|
|
if (sourceEntityNum == cg.snap->ps.clientNum) {
|
2002-05-27 06:58:40 +00:00
|
|
|
if (cg.snap->ps.weapon != WP_SSG3000 &&
|
2002-06-16 20:06:15 +00:00
|
|
|
bg_itemlist[cg.snap->ps.stats[STAT_HOLDABLE_ITEM]].giTag != HI_SILENCER) {
|
|
|
|
if (random() < cg_tracerChance.value)
|
|
|
|
CG_CreateTracer(sourceEntityNum, start, end);
|
2001-08-13 17:25:06 +00:00
|
|
|
}
|
2002-06-16 20:06:15 +00:00
|
|
|
} else {
|
2001-08-13 17:25:06 +00:00
|
|
|
cent = &cg_entities[sourceEntityNum];
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cent->currentValid && cent->currentState.weapon != WP_SSG3000) {
|
|
|
|
if (random() < cg_tracerChance.value && cent->muzzleFlashTime != -1) {
|
|
|
|
CG_CreateTracer(sourceEntityNum, start, end);
|
2001-08-13 17:25:06 +00:00
|
|
|
}
|
|
|
|
}
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// impact splash and mark
|
2002-06-16 20:06:15 +00:00
|
|
|
if (flesh) {
|
|
|
|
CG_Bleed(end, fleshEntityNum);
|
2001-05-06 20:50:27 +00:00
|
|
|
} else {
|
|
|
|
//Blaze: Changed WP_MACHINEGUN to WP_PISTOL
|
2002-06-16 20:06:15 +00:00
|
|
|
CG_MissileHitWall(WP_PISTOL, 0, end, normal, soundType, 0);
|
2001-05-06 20:50:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2001-07-28 14:12:11 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
==================
|
|
|
|
CG_LocalLaser
|
|
|
|
|
|
|
|
Elder:
|
|
|
|
Local laser dot if it is the client's own laser
|
|
|
|
==================
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
static void CG_LocalLaser()
|
2001-07-28 14:12:11 +00:00
|
|
|
{
|
2002-06-16 20:06:15 +00:00
|
|
|
vec3_t muzzle;
|
|
|
|
vec3_t forward;
|
|
|
|
vec3_t end;
|
|
|
|
refEntity_t *re;
|
|
|
|
trace_t tr;
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-07-28 14:12:11 +00:00
|
|
|
//Create the laser entity if it's not there
|
2002-06-16 20:06:15 +00:00
|
|
|
if (cg.laserSight == qfalse) {
|
2001-11-15 07:04:46 +00:00
|
|
|
//CG_Printf("Initializing Local Laser...\n");
|
2001-07-28 14:12:11 +00:00
|
|
|
|
|
|
|
cg.laserSight = qtrue;
|
|
|
|
cg.laserEnt = CG_AllocLocalEntity();
|
|
|
|
cg.laserEnt->startTime = cg.time;
|
|
|
|
cg.laserEnt->color[3] = 1.0;
|
|
|
|
//cg.laserEnt->pos.trType = TR_INTERPOLATE;
|
|
|
|
}
|
|
|
|
//Setup refEntity stuff
|
|
|
|
re = &cg.laserEnt->refEntity;
|
|
|
|
re->radius = 6;
|
|
|
|
re->reType = RT_SPRITE;
|
|
|
|
re->rotation = 0;
|
|
|
|
re->customShader = cgs.media.laserShader;
|
|
|
|
|
|
|
|
//Calculate muzzle and endpoint
|
2002-06-16 20:06:15 +00:00
|
|
|
if (CG_CalcMuzzlePoint(cg.snap->ps.clientNum, muzzle)) {
|
|
|
|
AngleVectors(cg.snap->ps.viewangles, forward, NULL, NULL);
|
|
|
|
VectorMA(muzzle, 8192 * 16, forward, end);
|
|
|
|
} else {
|
2001-07-28 14:12:11 +00:00
|
|
|
CG_Error("CG_LocalLaser: Could not calculate own muzzle point\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
CG_Trace(&tr, muzzle, NULL, NULL, end, cg.predictedPlayerState.clientNum, CONTENTS_SOLID);
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-07-28 14:12:11 +00:00
|
|
|
//Set position of laser dot
|
|
|
|
if (tr.fraction != 1)
|
2002-06-16 20:06:15 +00:00
|
|
|
VectorMA(tr.endpos, -4, forward, tr.endpos);
|
2001-07-28 14:12:11 +00:00
|
|
|
|
2001-08-17 20:38:54 +00:00
|
|
|
VectorCopy(re->origin, re->oldorigin);
|
2001-07-28 14:12:11 +00:00
|
|
|
VectorCopy(tr.endpos, re->origin);
|
|
|
|
//VectorCopy(tr.endpos, cg.laserEnt->pos.trBase);
|
2002-01-14 01:19:23 +00:00
|
|
|
//CG_EvaluateTrajectory(&cg.laserEnt->pos, cg.time, re->origin);
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2001-07-28 14:12:11 +00:00
|
|
|
//Boost the endTime
|
|
|
|
cg.laserEnt->endTime += 10000;
|
|
|
|
|
|
|
|
//if (tr.surfaceFlags & SURF_NOIMPACT || tr.surfaceFlags & SURF_SKY)
|
|
|
|
//Don't render if it hits the sky
|
|
|
|
//if (!(tr.surfaceFlags & SURF_SKY))
|
2002-06-16 20:06:15 +00:00
|
|
|
trap_R_AddRefEntityToScene(re);
|
2001-07-28 14:12:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
==================
|
|
|
|
CG_CheckLaser
|
|
|
|
|
|
|
|
Elder:
|
|
|
|
Whether or not to use the local laser
|
|
|
|
Broken until I find a way to lerp an entity without a cent
|
|
|
|
==================
|
|
|
|
*/
|
|
|
|
void CG_CheckLaser()
|
|
|
|
{
|
|
|
|
//Elder: check for local laser
|
|
|
|
if (bg_itemlist[cg.snap->ps.stats[STAT_HOLDABLE_ITEM]].giTag == HI_LASER &&
|
2002-06-16 20:06:15 +00:00
|
|
|
cg_RQ3_laserAssist.integer &&
|
|
|
|
(cg.snap->ps.weapon == WP_PISTOL || cg.snap->ps.weapon == WP_MP5 || cg.snap->ps.weapon == WP_M4)) {
|
2001-07-28 14:12:11 +00:00
|
|
|
CG_LocalLaser();
|
|
|
|
}
|
|
|
|
//Disable laser
|
2002-06-16 20:06:15 +00:00
|
|
|
else if (cg.laserSight == qtrue) {
|
2001-11-15 07:04:46 +00:00
|
|
|
//CG_Printf("Destroying Local Laser...\n");
|
2001-07-28 14:12:11 +00:00
|
|
|
CG_FreeLocalEntity(cg.laserEnt);
|
|
|
|
cg.laserSight = qfalse;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-08-06 19:15:00 +00:00
|
|
|
/*
|
|
|
|
==================
|
|
|
|
CG_ReloadWeapon
|
|
|
|
|
|
|
|
Elder: Does local reload effects like
|
|
|
|
reload shell drops, sounds, etc.
|
|
|
|
==================
|
|
|
|
*/
|
2002-06-16 20:06:15 +00:00
|
|
|
void CG_ReloadWeapon(centity_t * cent, int reloadStage)
|
2001-08-06 19:15:00 +00:00
|
|
|
{
|
|
|
|
entityState_t *ent;
|
2002-06-16 20:06:15 +00:00
|
|
|
weaponInfo_t *weap;
|
2001-08-06 19:15:00 +00:00
|
|
|
|
|
|
|
ent = ¢->currentState;
|
2002-06-16 20:06:15 +00:00
|
|
|
if (ent->weapon == WP_NONE)
|
2001-08-06 19:15:00 +00:00
|
|
|
return;
|
2001-11-11 07:23:16 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (ent->weapon >= WP_NUM_WEAPONS) {
|
|
|
|
CG_Error("CG_ReloadWeapon: ent->weapon >= WP_NUM_WEAPONS");
|
2001-08-06 19:15:00 +00:00
|
|
|
return;
|
|
|
|
}
|
2001-11-11 07:23:16 +00:00
|
|
|
weap = &cg_weapons[ent->weapon];
|
2002-06-16 20:06:15 +00:00
|
|
|
switch (reloadStage) {
|
2001-11-11 07:23:16 +00:00
|
|
|
case 0:
|
2002-06-16 20:06:15 +00:00
|
|
|
if (weap->worldReloadSound[0] && ent->clientNum != cg.snap->ps.clientNum) {
|
2001-11-11 07:23:16 +00:00
|
|
|
trap_S_StartSound(cent->lerpOrigin, ent->number, CHAN_AUTO, weap->worldReloadSound[0]);
|
2001-11-24 23:55:56 +00:00
|
|
|
}
|
2001-11-11 07:23:16 +00:00
|
|
|
break;
|
|
|
|
case 1:
|
2002-06-16 20:06:15 +00:00
|
|
|
if (weap->worldReloadSound[1] && ent->clientNum != cg.snap->ps.clientNum) {
|
2001-11-11 07:23:16 +00:00
|
|
|
trap_S_StartSound(cent->lerpOrigin, ent->number, CHAN_AUTO, weap->worldReloadSound[1]);
|
2001-11-24 23:55:56 +00:00
|
|
|
}
|
2001-11-11 20:03:09 +00:00
|
|
|
|
2002-06-16 20:06:15 +00:00
|
|
|
if (ent->weapon == WP_HANDCANNON)
|
2002-03-24 22:46:23 +00:00
|
|
|
cent->ejectBrassTime = cg.time;
|
2002-06-16 20:06:15 +00:00
|
|
|
// CG_ShotgunEjectBrass( cent );
|
2001-11-11 07:23:16 +00:00
|
|
|
break;
|
|
|
|
case 2:
|
2002-06-16 20:06:15 +00:00
|
|
|
if (weap->worldReloadSound[2] && ent->clientNum != cg.snap->ps.clientNum) {
|
2001-11-11 07:23:16 +00:00
|
|
|
trap_S_StartSound(cent->lerpOrigin, ent->number, CHAN_AUTO, weap->worldReloadSound[2]);
|
2001-11-24 23:55:56 +00:00
|
|
|
}
|
2001-11-25 23:17:41 +00:00
|
|
|
|
2001-11-11 07:23:16 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
CG_Error("CG_ReloadWeapon: Reload stage > 2\n");
|
|
|
|
break;
|
2001-08-06 19:15:00 +00:00
|
|
|
}
|
2002-05-27 17:47:19 +00:00
|
|
|
}
|