For the coming 0-06-xx VMs
Lots of item stuff + more
This commit is contained in:
Victor Chow 2001-07-28 14:12:11 +00:00
parent 21b2fc4497
commit 058281a050
23 changed files with 978 additions and 154 deletions

View file

@ -55,6 +55,36 @@ static void CG_DropWeapon_f (void) {
trap_SendClientCommand("dropweapon");
}
/*
=================
CG_DropItem_f
Elder: Do any client pre-processing here for drop item
=================
*/
static void CG_DropItem_f (void) {
if ( !cg.snap ) {
//CG_Printf("No snapshot: normally exiting\n");
return;
}
// if we are going into the intermission, don't do anything
if ( cg.intermissionStarted ) {
return;
}
///Elder: spectator?
if ( cg.snap->ps.pm_flags & PMF_FOLLOW ) {
return;
}
//Elder: don't allow item dropping when in the middle of bursts
if (cg.snap->ps.stats[STAT_BURST] > 0)
return;
trap_SendClientCommand("dropitem");
}
/*
=================
CG_Bandage_f
@ -668,6 +698,7 @@ static consoleCommand_t commands[] = {
{ "weapnext", CG_NextWeapon_f },
{ "weapprev", CG_PrevWeapon_f },
{ "weapon", CG_Weapon_f }, // Elder: it's for RQ3 and Q3A
{ "dropitem", CG_DropItem_f },
{ "dropweapon", CG_DropWeapon_f }, // Elder: added to reset zoom then goto server
{ "bandage", CG_Bandage_f }, // Elder: added to reset zoom then goto server
{ "+reload", CG_Reload_f }, // Elder: added to reset zoom then goto server
@ -790,6 +821,7 @@ void CG_InitConsoleCommands( void ) {
//trap_AddCommand ("drop"); // XRAY FMJ weap drop cmd - Elder: not used
//Elder: added to give drop weapon auto-complete
trap_AddCommand ("dropweapon");
trap_AddCommand ("dropitem");
//Elder: try this
trap_AddCommand ("weapon");
trap_AddCommand ("specialweapon");

View file

@ -599,9 +599,9 @@ static void CG_DrawStatusBar( void ) {
UI_DrawProportionalString(580, 364, va("%d", cg.snap->ps.ammo[WP_GRENADE]), style, colors[0]);
}
//Elder: draw special weapons, if any, on the side
if (cg.snap->ps.stats[STAT_UNIQUEWEAPONS])
{
//Elder: draw a special weapon, if any, on the side
//if (cg.snap->ps.stats[STAT_UNIQUEWEAPONS])
//{
for (i = 1; i < MAX_WEAPONS; i++)
{
if (i == WP_KNIFE ||
@ -620,7 +620,7 @@ static void CG_DrawStatusBar( void ) {
if (icon)
CG_DrawPic(640-SMICON_SIZE, 400, SMICON_SIZE, SMICON_SIZE, icon);
}
}
//}
}

View file

@ -462,7 +462,80 @@ localEntity_t *CG_MakeExplosion( vec3_t origin, vec3_t dir,
}
//Elder: we need one that sprays blood
/*
=================
CG_BleedSpray
Elder: This is a super blood spray for SSG hits
Based on bubble trail code + other stuff
=================
*/
#define MAX_SPRAY_BURSTS 16
void CG_BleedSpray ( vec3_t start, vec3_t end, int entityNum )
{
//vec3_t dir;
vec3_t trueEnd;
vec3_t move;
vec3_t vec;
vec3_t velocity;
localEntity_t *blood;
float len;
int i;
int spacing = 30;
int bloodCount = 0;
if ( !cg_blood.integer ) {
return;
}
VectorCopy (end, move);
VectorSubtract (end, start, vec);
//Calculate true length via start/end points
VectorCopy (vec, trueEnd);
VectorNormalize (trueEnd);
//VectorScale (trueEnd, 300 + rand() % 100, trueEnd);
//VectorAdd (end, trueEnd, trueEnd);
VectorMA(end, 300 + rand() % 100, trueEnd, trueEnd);
VectorSubtract (trueEnd, start, vec);
len = VectorNormalize (vec);
//Set velocity
VectorScale(vec, 10, velocity);
velocity[2] += 30;
// advance a random amount first
i = rand() % (int)spacing;
VectorMA( move, i, vec, move );
VectorScale (vec, spacing, vec);
for ( ; i < len; i += spacing )
{
//restrict amount of spurts
if (bloodCount++ > MAX_SPRAY_BURSTS)
break;
blood = CG_SmokePuff(move, velocity, 8,
1, 1, 1, 1,
1500 + rand() % 250,
cg.time, 0,
LEF_TUMBLE|LEF_PUFF_DONT_SCALE,
cgs.media.bloodTrailShader);
blood->refEntity.rotation = rand() % 360;
blood->leMarkType = LEMT_BLOOD;
blood->leType = LE_FRAGMENT;
blood->pos.trType = TR_GRAVITY;
blood->bounceFactor = 0.4f;
VectorAdd (move, vec, move);
}
}
/*
=================
CG_Bleed
@ -701,7 +774,8 @@ CG_LaunchGlass
==================
*/
void CG_LaunchGlass( vec3_t origin, vec3_t velocity, vec3_t rotation,
float bounce, qhandle_t hModel ) {
float bounce, qhandle_t hModel )//, qhandle_t altSkin )
{
localEntity_t *le;
refEntity_t *re;
@ -716,6 +790,11 @@ void CG_LaunchGlass( vec3_t origin, vec3_t velocity, vec3_t rotation,
AxisCopy( axisDefault, re->axis );
re->hModel = hModel;
//Elder: custom shaders for debris?
//if (altSkin)
//re->customSkin = altSkin;
le->pos.trType = TR_GRAVITY;
VectorCopy( origin, le->pos.trBase );
VectorCopy( velocity, le->pos.trDelta );
@ -733,7 +812,7 @@ void CG_LaunchGlass( vec3_t origin, vec3_t velocity, vec3_t rotation,
le->leFlags = LEF_TUMBLE;
le->leBounceSoundType = LEBS_BRASS;
le->leMarkType = LEMT_NONE;
}
}
/*
===================
@ -762,22 +841,22 @@ void CG_BreakGlass( vec3_t playerOrigin, int glassParm, int type ) {
(glassParm & RQ3_DEBRIS_HIGH) == RQ3_DEBRIS_HIGH)
{
//Tons
count = 65 + rand() % 25;
count = 65 + rand() % 16;
}
else if ( (glassParm & RQ3_DEBRIS_HIGH) == RQ3_DEBRIS_HIGH)
{
//Large
count = 40 + rand() % 15;
count = 40 + rand() % 11;
}
else if ( (glassParm & RQ3_DEBRIS_MEDIUM) == RQ3_DEBRIS_MEDIUM)
{
//Medium
count = 22 + rand() % 7;
count = 20 + rand() % 6;
}
else
{
//Small
count = 8 + rand() % 5;
count = 8 + rand() % 6;
}
/*

View file

@ -4,6 +4,7 @@
#include "cg_local.h"
static void CG_LaserSight( centity_t *cent );
/*
======================
@ -308,6 +309,12 @@ static void CG_Item( centity_t *cent ) {
VectorNegate(ent.axis[2], ent.axis[1]);
VectorCopy(myvec, ent.axis[2]);
}
else if (item->giType == IT_HOLDABLE &&
(es->pos.trDelta[0] != 0 || es->pos.trDelta[1] != 0 || es->pos.trDelta[2] != 0))
{
VectorCopy( cg.autoAnglesFast, cent->lerpAngles );
AxisCopy( cg.autoAxisFast, ent.axis );
}
wi = NULL;
// the weapons have their origin where they attatch to player
@ -350,9 +357,11 @@ static void CG_Item( centity_t *cent ) {
}
}
//Elder: what the heck is this?
//Elder: ammo offset?
if (item->giType == IT_AMMO)
cent->lerpOrigin[2]-=12;
else if (item->giType == IT_HOLDABLE)
cent->lerpOrigin[2] -= 12;
ent.hModel = cg_items[es->modelindex].models[0];
@ -781,7 +790,7 @@ static void CG_InterpolateEntityPosition( centity_t *cent ) {
// it would be an internal error to find an entity that interpolates without
// a snapshot ahead of the current one
if ( cg.nextSnap == NULL ) {
CG_Error( "CG_InterpoateEntityPosition: cg.nextSnap == NULL" );
CG_Error( "CG_InterpolateEntityPosition: cg.nextSnap == NULL" );
}
f = cg.frameInterpolation;
@ -1058,6 +1067,12 @@ static void CG_AddCEntity( centity_t *cent ) {
case ET_TEAM:
CG_TeamBase( cent );
break;
case ET_LASER:
//Elder: the local laser call is checked in playerstate unless it is disabled
//if (!cg_RQ3_laserAssist.integer || cent->currentState.clientNum != cg.snap->ps.clientNum)
CG_LaserSight( cent );
break;
}
}
@ -1115,3 +1130,34 @@ void CG_AddPacketEntities( void ) {
}
}
/*
==================
CG_LaserSight
Creates the laser dot
Elder's Note: Client does not use this if the dot is his/her own -- see CG_LocalLaser
==================
*/
static void CG_LaserSight( centity_t *cent ) {
refEntity_t ent;
// create the reference entity
memset (&ent, 0, sizeof(ent));
VectorCopy( cent->lerpOrigin, ent.origin);
VectorCopy( cent->lerpOrigin, ent.oldorigin);
if (cent->currentState.eventParm == 1)
{
ent.reType = RT_SPRITE;
ent.radius = 3;
ent.rotation = 0;
ent.customShader = cgs.media.laserShader;
trap_R_AddRefEntityToScene( &ent );
}
else {
trap_R_AddLightToScene(ent.origin, 200, 1, 1, 1);
}
}

View file

@ -1700,7 +1700,8 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) {
break;
case EV_FIRE_WEAPON:
DEBUGNAME("EV_FIRE_WEAPON");
CG_FireWeapon( cent );
//Elder: modified
CG_FireWeapon( cent, es->eventParm );
break;
// Reaction Zoom
@ -1892,14 +1893,23 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) {
case EV_BULLET_HIT_WALL:
DEBUGNAME("EV_BULLET_HIT_WALL");
ByteToDir( es->eventParm, dir );
CG_Bullet( es->pos.trBase, es->otherEntityNum, dir, qfalse, ENTITYNUM_WORLD );
//Elder: added additional param
CG_Bullet( es->pos.trBase, es->otherEntityNum, dir, qfalse, ENTITYNUM_WORLD, qfalse );
break;
case EV_BULLET_HIT_FLESH:
DEBUGNAME("EV_BULLET_HIT_FLESH");
CG_Bullet( es->pos.trBase, es->otherEntityNum, dir, qtrue, es->eventParm );
//Elder: added additional param
CG_Bullet( es->pos.trBase, es->otherEntityNum, dir, qtrue, es->eventParm, qfalse );
break;
case EV_SSG3000_HIT_FLESH:
DEBUGNAME("EV_SSG3000_HIT_FLESH");
//Elder: added additional param
CG_Bullet( es->pos.trBase, es->otherEntityNum, dir, qtrue, es->eventParm, qtrue );
break;
case EV_SHOTGUN:
DEBUGNAME("EV_SHOTGUN");
CG_ShotgunFire( es ,qtrue);
@ -1950,6 +1960,10 @@ void CG_EntityEvent( centity_t *cent, vec3_t position ) {
//Global sound
trap_S_StartSound( NULL, cg.snap->ps.clientNum, CHAN_AUTO, cgs.media.lcaSound);
break;
case RQ3_SOUND_KEVLARHIT:
//TODO: make sparks from hit position
trap_S_StartSound( NULL, es->number, CHAN_AUTO, cgs.media.kevlarHitSound);
break;
default:
break;
}

View file

@ -81,6 +81,9 @@
#define ZOOM_LEVELS 3
#define ZOOM_PREPTIME 10 //milliseconds
//Elder: max number of "blood" marks when hitting a player w/ shell weapons
#define MAX_SHELL_HITS 6
typedef enum {
FOOTSTEP_NORMAL,
FOOTSTEP_BOOT,
@ -641,6 +644,10 @@ typedef struct {
int sayTime;
int sayCount;
int shellHits; //Count number of successful shell hits
qboolean laserSight; //Whether to draw local laser sight
localEntity_t *laserEnt; //Local model -- NULL if not in-use
} cg_t;
@ -759,6 +766,9 @@ typedef struct {
qhandle_t backTileShader;
qhandle_t noammoShader;
//Elder: C3A Laser tutorial
qhandle_t laserShader;
//Elder: sniper crosshairs
qhandle_t ssgCrosshair[ZOOM_LEVELS];
@ -865,6 +875,9 @@ typedef struct {
sfxHandle_t headshotSound; //Elder: splat
sfxHandle_t lcaSound; //Elder: lights, camera, action!
sfxHandle_t lensSound; //Elder: sniper lens zoom
sfxHandle_t silencerSound;
sfxHandle_t kevlarHitSound;
sfxHandle_t quadSound;
sfxHandle_t tracerSound;
sfxHandle_t selectSound;
@ -1209,6 +1222,8 @@ extern vmCvar_t cg_RQ3_ssgColorB;
extern vmCvar_t cg_RQ3_ssgColorA;
//Elder: smoke puffs, sparks, etc.
extern vmCvar_t cg_RQ3_impactEffects;
//Elder: toggle client-side laser drawing
extern vmCvar_t cg_RQ3_laserAssist;
//Blaze: anouncer sounds
extern vmCvar_t cg_RQ3_anouncer;
@ -1422,11 +1437,11 @@ void CG_RQ3_GrenadeMode();
void CG_RegisterWeapon( int weaponNum );
void CG_RegisterItemVisuals( int itemNum );
void CG_FireWeapon( centity_t *cent );
void CG_FireWeapon( centity_t *cent, int weapModification );
void CG_MissileHitWall( int weapon, int clientNum, vec3_t origin, vec3_t dir, impactSound_t soundType );
void CG_MissileHitPlayer( int weapon, vec3_t origin, vec3_t dir, int entityNum );
void CG_ShotgunFire( entityState_t *es, qboolean ism3 );
void CG_Bullet( vec3_t origin, int sourceEntityNum, vec3_t normal, qboolean flesh, int fleshEntityNum );
void CG_Bullet( vec3_t origin, int sourceEntityNum, vec3_t normal, qboolean flesh, int fleshEntityNum, qboolean armorPiercing );
void CG_RailTrail( clientInfo_t *ci, vec3_t start, vec3_t end );
void CG_GrappleTrail( centity_t *ent, const weaponInfo_t *wi );
@ -1435,6 +1450,8 @@ void CG_AddPlayerWeapon( refEntity_t *parent, playerState_t *ps, centity_t *cent
void CG_DrawWeaponSelect( void );
void CG_OutOfAmmoChange( void ); // should this be in pmove?
void CG_CheckLaser (); //Elder: check laser to see if it's our own
//
// cg_marks.c
@ -1484,6 +1501,8 @@ void CG_BigExplode( vec3_t playerOrigin );
// Blaze: Breakable glass Elder: modified
void CG_BreakGlass( vec3_t playerOrigin, int glassParm, int type );
void CG_Bleed( vec3_t origin, int entityNum );
//Elder: for SSG shots
void CG_BleedSpray ( vec3_t origin, vec3_t dir, int entityNum );
localEntity_t *CG_MakeExplosion( vec3_t origin, vec3_t dir,
qhandle_t hModel, qhandle_t shader, int msec,

View file

@ -153,9 +153,10 @@ vmCvar_t cg_RQ3_ssgColorB;
vmCvar_t cg_RQ3_ssgColorA;
//Elder: smoke puffs, sparks, etc.
vmCvar_t cg_RQ3_impactEffects;
//Elder: toggle client-side laser drawing
vmCvar_t cg_RQ3_laserAssist;
//Blaze: anouncer sounds
vmCvar_t cg_RQ3_anouncer;
vmCvar_t cg_drawFriend;
vmCvar_t cg_teamChatsOnly;
vmCvar_t cg_noVoiceChats;
@ -318,8 +319,14 @@ cvarTable_t cvarTable[] = {
{ &cg_RQ3_ssgColorG, "cg_RQ3_ssgColorG", "1.0", CVAR_ARCHIVE },
{ &cg_RQ3_ssgColorB, "cg_RQ3_ssgColorB", "0.0", CVAR_ARCHIVE },
{ &cg_RQ3_ssgColorA, "cg_RQ3_ssgColorA", "0.75", CVAR_ARCHIVE },
<<<<<<< cg_main.c
{ &cg_RQ3_impactEffects, "cg_RQ3_impactEffects", "1", CVAR_ARCHIVE },
//Elder: toggle client-side laser drawing
{ &cg_RQ3_laserAssist, "cg_RQ3_laserAssist", "0", CVAR_ARCHIVE }
=======
{ &cg_RQ3_impactEffects, "cg_RQ3_impactEffects", "1", CVAR_ARCHIVE },
{ &cg_RQ3_anouncer, "cg_RQ3_anouncer", "1", CVAR_ARCHIVE },
>>>>>>> 1.9
// { &cg_pmove_fixed, "cg_pmove_fixed", "0", CVAR_USERINFO | CVAR_ARCHIVE }
};
@ -640,6 +647,8 @@ static void CG_RegisterSounds( void ) {
cgs.media.lensSound = trap_S_RegisterSound( "sound/misc/lens.wav", qfalse);
cgs.media.headshotSound = trap_S_RegisterSound( "sound/misc/headshot.wav", qfalse);
cgs.media.lcaSound = trap_S_RegisterSound( "sound/misc/lca.wav", qfalse);
cgs.media.silencerSound = trap_S_RegisterSound( "sound/misc/silencer.wav", qfalse);
cgs.media.kevlarHitSound = trap_S_RegisterSound( "sound/misc/vest.wav", qfalse);
#ifdef MISSIONPACK
@ -1049,6 +1058,9 @@ static void CG_RegisterGraphics( void ) {
cgs.media.medalAssist = trap_R_RegisterShaderNoMip( "medal_assist" );
cgs.media.medalCapture = trap_R_RegisterShaderNoMip( "medal_capture" );
//Elder: C3A laser tutorial
cgs.media.laserShader = trap_R_RegisterShader( "sprites/laser" );
//Elder: added for sniper crosshairs
cgs.media.ssgCrosshair[0] = trap_R_RegisterShaderNoMip( "gfx/rq3_hud/ssg2x" );
cgs.media.ssgCrosshair[1] = trap_R_RegisterShaderNoMip( "gfx/rq3_hud/ssg4x" );

View file

@ -587,6 +587,5 @@ void CG_TransitionPlayerState( playerState_t *ps, playerState_t *ops ) {
break;
}
}
}

View file

@ -942,6 +942,9 @@ void CG_DrawActiveFrame( int serverTime, stereoFrame_t stereoView, qboolean demo
}
CG_AddViewWeapon( &cg.predictedPlayerState );
//Elder: check local laser status
//CG_CheckLaser();
// add buffered sounds
CG_PlayBufferedSounds();

View file

@ -2015,7 +2015,7 @@ CG_FireWeapon
Caused by an EV_FIRE_WEAPON event
================
*/
void CG_FireWeapon( centity_t *cent ) {
void CG_FireWeapon( centity_t *cent, int weapModification ) {
entityState_t *ent;
int c;
weaponInfo_t *weap;
@ -2054,7 +2054,10 @@ void CG_FireWeapon( centity_t *cent ) {
// mark the entity as muzzle flashing, so when it is added it will
// append the flash to the weapon model
cent->muzzleFlashTime = cg.time;
if (weapModification != RQ3_WPMOD_SILENCER)
{
cent->muzzleFlashTime = cg.time;
}
// lightning gun only does this this on initial press
//Blaze: no more Lighting gun
@ -2071,7 +2074,13 @@ void CG_FireWeapon( centity_t *cent ) {
trap_S_StartSound (NULL, cent->currentState.number, CHAN_ITEM, cgs.media.quadSound );
}
//Elder: silencer stuff
if (weapModification == RQ3_WPMOD_SILENCER)
{
trap_S_StartSound( NULL, ent->number, CHAN_WEAPON, cgs.media.silencerSound );
}
else
{
// play a sound
for ( c = 0 ; c < 4 ; c++ ) {
if ( !weap->flashSound[c] ) {
@ -2086,7 +2095,7 @@ void CG_FireWeapon( centity_t *cent ) {
trap_S_StartSound( NULL, ent->number, CHAN_WEAPON, weap->flashSound[c] );
}
}
}
// do brass ejection
if ( weap->ejectBrassFunc && cg_brassTime.integer > 0 ) {
weap->ejectBrassFunc( cent );
@ -2523,27 +2532,39 @@ static void CG_ShotgunPellet( vec3_t start, vec3_t end, int skipNum, int shellWe
return;
}
if ( cg_entities[tr.entityNum].currentState.eType == ET_PLAYER ) {
if ( cg_entities[tr.entityNum].currentState.eType == ET_PLAYER )
{
//Blaze: Changed WP_SHOTGUN to WP_M3
CG_MissileHitPlayer( WP_M3, tr.endpos, tr.plane.normal, tr.entityNum );
} else {
if ( tr.surfaceFlags & SURF_NOIMPACT ) {
//Elder: don't display so many blood stains - so we can reduce slow down
cg.shellHits++;
if (cg.shellHits < MAX_SHELL_HITS)
CG_MissileHitPlayer( WP_M3, tr.endpos, tr.plane.normal, tr.entityNum );
}
else
{
if ( tr.surfaceFlags & SURF_NOIMPACT )
{
// SURF_NOIMPACT will not make a flame puff or a mark
return;
}
if ( tr.surfaceFlags & SURF_METALSTEPS ) {
if ( tr.surfaceFlags & SURF_METALSTEPS )
{
//Blaze: Changed WP_SHOTGUN to WP_M3
if (shellWeapon == WP_M3)
CG_MissileHitWall( WP_M3, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_METAL );
else if (shellWeapon == WP_HANDCANNON && crandom() > 0.5) {
else if (shellWeapon == WP_HANDCANNON && crandom() > 0.5)
{
//Elder: show only approximately every other impact mark
CG_MissileHitWall( WP_HANDCANNON, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_METAL );
}
} else {
}
else
{
//Blaze: Changed WP_SHOTGUN to WP_M3
if (shellWeapon == WP_M3)
CG_MissileHitWall( WP_M3, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_DEFAULT );
else if (shellWeapon == WP_HANDCANNON && crandom() > 0.5) {
else if (shellWeapon == WP_HANDCANNON && crandom() > 0.5)
{
//Elder: show only approximately every other impact mark
CG_MissileHitWall( WP_HANDCANNON, 0, tr.endpos, tr.plane.normal, IMPACTSOUND_DEFAULT );
}
@ -2590,7 +2611,7 @@ static void CG_ShotgunPattern( vec3_t origin, vec3_t origin2, int otherEntNum, i
hc_multipler = 5;
}
cg.shellHits = 0;
for ( i = 0 ; i < count ; i++ ) {
if (shotType == WP_M3)
{
@ -2616,6 +2637,8 @@ static void CG_ShotgunPattern( vec3_t origin, vec3_t origin2, int otherEntNum, i
CG_ShotgunPellet( origin, end, otherEntNum, shotType );
}
//Reset shellHits once we're finished with it
cg.shellHits = 0;
}
/*
@ -2788,9 +2811,11 @@ static qboolean CG_CalcMuzzlePoint( int entityNum, vec3_t muzzle ) {
CG_Bullet
Renders bullet effects.
Elder: added armorPiercing conditional
======================
*/
void CG_Bullet( vec3_t end, int sourceEntityNum, vec3_t normal, qboolean flesh, int fleshEntityNum ) {
void CG_Bullet( vec3_t end, int sourceEntityNum, vec3_t normal,
qboolean flesh, int fleshEntityNum, qboolean armorPiercing ) {
trace_t trace;
int sourceContentType, destContentType;
vec3_t start;
@ -2826,10 +2851,110 @@ void CG_Bullet( vec3_t end, int sourceEntityNum, vec3_t normal, qboolean flesh,
// impact splash and mark
if ( flesh ) {
CG_Bleed( end, fleshEntityNum );
//Elder: added
if ( armorPiercing && CG_CalcMuzzlePoint( sourceEntityNum, start))
CG_BleedSpray(start, end, fleshEntityNum);
else
CG_Bleed( end, fleshEntityNum );
} else {
//Blaze: Changed WP_MACHINEGUN to WP_PISTOL
CG_MissileHitWall( WP_PISTOL, 0, end, normal, IMPACTSOUND_DEFAULT );
}
}
/*
==================
CG_LocalLaser
Elder:
Local laser dot if it is the client's own laser
==================
*/
static void CG_LocalLaser ()
{
vec3_t muzzle;
vec3_t forward;
vec3_t end;
refEntity_t *re;
trace_t tr;
//Create the laser entity if it's not there
if (cg.laserSight == qfalse)
{
CG_Printf("Initializing Local Laser...\n");
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
if (CG_CalcMuzzlePoint(cg.snap->ps.clientNum, muzzle))
{
AngleVectors( cg.snap->ps.viewangles, forward, NULL, NULL );
VectorMA( muzzle, 8192 * 16, forward, end );
}
else
{
CG_Error("CG_LocalLaser: Could not calculate own muzzle point\n");
}
CG_Trace(&tr, muzzle, NULL, NULL, end, cg.predictedPlayerState.clientNum, CONTENTS_SOLID);
//Set position of laser dot
if (tr.fraction != 1)
VectorMA(tr.endpos,-4, forward, tr.endpos);
VectorCopy(tr.endpos, re->origin);
//VectorCopy(tr.endpos, cg.laserEnt->pos.trBase);
//BG_EvaluateTrajectory(&cg.laserEnt->pos, cg.time, re->origin);
//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))
trap_R_AddRefEntityToScene( re );
}
/*
==================
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 &&
cg_RQ3_laserAssist.integer &&
(cg.snap->ps.weapon == WP_PISTOL ||
cg.snap->ps.weapon == WP_MP5 ||
cg.snap->ps.weapon == WP_M4))
{
CG_LocalLaser();
}
//Disable laser
else if (cg.laserSight == qtrue)
{
CG_Printf("Destroying Local Laser...\n");
CG_FreeLocalEntity(cg.laserEnt);
cg.laserSight = qfalse;
}
}

View file

@ -58,6 +58,8 @@ extern int c_pmove;
void PM_ClipVelocity( vec3_t in, vec3_t normal, vec3_t out, float overbounce );
void PM_AddTouchEnt( int entityNum );
void PM_AddEvent( int newEvent );
//Elder: added
void PM_AddEvent2( int newEvent, int eventParm );
qboolean PM_SlideMove( qboolean gravity );
void PM_StepSlideMove( qboolean gravity );

View file

@ -329,10 +329,10 @@ gitem_t bg_itemlist[] =
//
// AMMO ITEMS
//
/*QUAKED ammo_bullets (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
/*QUAKED ammo_mk23 (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
*/
{
"ammo_bullets",
"ammo_mk23",
"sound/misc/am_pkup.wav",
{ "models/ammo/mk23.md3",
0, 0, 0},
@ -351,28 +351,28 @@ gitem_t bg_itemlist[] =
{
"ammo_shells",
"sound/misc/am_pkup.wav",
{ "models/ammo/m4.md3",
{ "models/ammo/m3.md3",
0, 0, 0},
/* icon */ "icons/icona_m4clip",
/* pickup */ "M4 Clip",
1,
/* icon */ "icons/icona_shells",
/* pickup */ "Shotgun Shells",
7,
IT_AMMO,
//Blaze: changed from WP_SHOTGUN to WP_M4
WP_M4,
//Blaze: Changed from WP_ROCKET_LAUNCHER to WP_SHOTGUN
WP_M3,
/* precache */ "",
/* sounds */ ""
},
/*QUAKED ammo_slugs (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
/*QUAKED ammo_ssg3000 (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
*/
{
"ammo_slugs",
"ammo_ssg3000",
"sound/misc/am_pkup.wav",
{ "models/ammo/ssg3000.md3",
0, 0, 0},
/* icon */ "icons/icona_ssgammo",
/* pickup */ "Sniper Ammo",
/* pickup */ "AP Sniper Ammo",
10,
IT_AMMO,
//Blaze: Changed from WP_RAILGUN to WP_GRENADE
@ -381,10 +381,10 @@ gitem_t bg_itemlist[] =
/* sounds */ ""
},
/*QUAKED ammo_cells (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
/*QUAKED ammo_mp5 (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
*/
{
"ammo_cells",
"ammo_mp5",
"sound/misc/am_pkup.wav",
{ "models/ammo/mp5.md3",
0, 0, 0},
@ -416,6 +416,7 @@ gitem_t bg_itemlist[] =
/* sounds */ //""
// },
//Elder: just leaving this in for now
/*QUAKED ammo_rockets (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
*/
{
@ -433,6 +434,23 @@ gitem_t bg_itemlist[] =
/* sounds */ ""
},
/*QUAKED ammo_m4 (.3 .3 1) (-16 -16 -16) (16 16 16) suspended
*/
{
"ammo_m4",
"sound/misc/am_pkup.wav",
{ "models/ammo/m4.md3",
0, 0, 0},
/* icon */ "icons/icona_m4clip",
/* pickup */ "M4 Clip",
1,
IT_AMMO,
//Blaze: changed from WP_SHOTGUN to WP_M4
WP_M4,
/* precache */ "",
/* sounds */ ""
},
/*QUAKED team_CTF_redflag (1 0 0) (-16 -16 -16) (16 16 16)
Only in CTF games
@ -1318,6 +1336,7 @@ char *eventnames[] = {
"EV_BULLET_HIT_FLESH",
"EV_BULLET_HIT_WALL",
"EV_SSG3000_HIT_FLESH", //Elder: SSG3000 blood spray
"EV_MISSILE_HIT",
"EV_MISSILE_MISS",

View file

@ -104,6 +104,17 @@ void PM_AddEvent( int newEvent ) {
BG_AddPredictableEventToPlayerstate( newEvent, 0, pm->ps );
}
/*
===============
PM_AddEvent
Elder: stuffs event parameters
===============
*/
void PM_AddEvent2( int newEvent, int eventParm ) {
BG_AddPredictableEventToPlayerstate( newEvent, eventParm, pm->ps );
}
/*
===============
PM_AddTouchEnt
@ -1907,14 +1918,16 @@ static void PM_Weapon( void ) {
}
// check for item using
// Elder: removed
/*
if ( pm->cmd.buttons & BUTTON_USE_HOLDABLE ) {
if ( ! ( pm->ps->pm_flags & PMF_USE_ITEM_HELD ) ) {
/* Blaze: No more medkit
if ( bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag == HI_MEDKIT
&& pm->ps->stats[STAT_HEALTH] >= (125) ) { //medikit check pm->ps->stats[STAT_MAX_HEALTH] + 25) ) {
// Blaze: No more medkit
//if ( bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag == HI_MEDKIT
//&& pm->ps->stats[STAT_HEALTH] >= (125) ) { //medikit check pm->ps->stats[STAT_MAX_HEALTH] + 25) ) {
// don't use medkit if at max health
} else {*/
//} else {
pm->ps->pm_flags |= PMF_USE_ITEM_HELD;
PM_AddEvent( EV_USE_ITEM0 + bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag );
pm->ps->stats[STAT_HOLDABLE_ITEM] = 0;
@ -1924,6 +1937,7 @@ static void PM_Weapon( void ) {
} else {
pm->ps->pm_flags &= ~PMF_USE_ITEM_HELD;
}
*/
// make weapon function
@ -2144,7 +2158,16 @@ static void PM_Weapon( void ) {
// fire weapon
PM_AddEvent( EV_FIRE_WEAPON );
//Elder: check for silencer
if (bg_itemlist[pm->ps->stats[STAT_HOLDABLE_ITEM]].giTag == HI_SILENCER &&
(pm->ps->weapon == WP_PISTOL ||
pm->ps->weapon == WP_MP5 ||
pm->ps->weapon == WP_SSG3000))
{
PM_AddEvent2( EV_FIRE_WEAPON, RQ3_WPMOD_SILENCER );
}
else
PM_AddEvent( EV_FIRE_WEAPON );
switch( pm->ps->weapon ) {
default:

View file

@ -42,10 +42,13 @@
#define MINS_Z -24
#define DEFAULT_VIEWHEIGHT 26
#define CROUCH_VIEWHEIGHT 12
//Elder: changed to 8 like AQ2 source BUT is it sync-ed?
#define CROUCH_VIEWHEIGHT 8
//#define CROUCH_VIEWHEIGHT 12
#define DEAD_VIEWHEIGHT -16
//Elder: New breakable bit definitions
//Enum materials?
//No amount bits = Low ... both amount bits = Tons
#define RQ3_DEBRIS_MEDIUM 0x00000001
#define RQ3_DEBRIS_HIGH 0x00000002
@ -154,10 +157,20 @@
#define RQ3_LASER_NAME "Lasersight"
//Elder: sound events for EV_RQ3_SOUND
#define RQ3_SOUND_KICK 0
#define RQ3_SOUND_HEADSHOT 1
#define RQ3_SOUND_KNIFEDEATH 2
#define RQ3_SOUND_LCA 3 //lights, camera, action!
typedef enum {
RQ3_SOUND_KICK,
RQ3_SOUND_HEADSHOT,
RQ3_SOUND_KNIFEDEATH,
RQ3_SOUND_LCA, //lights, camera, action!
RQ3_SOUND_KEVLARHIT,
RQ3_SOUND_TOTAL
} rq3_sounds_t;
//#define RQ3_SOUND_KICK 0
//#define RQ3_SOUND_HEADSHOT 1
//#define RQ3_SOUND_KNIFEDEATH 2
//#define RQ3_SOUND_LCA 3 //lights, camera, action!
//Elder: Weapon damage and spread stats
#define PISTOL_DAMAGE 90
@ -270,6 +283,8 @@
//Elder: special flag needed in both games
#define FL_THROWN_KNIFE 0x00040000 // Elder: thrown knife special case
//Elder: weapon modifications -- right now only silencer
#define RQ3_WPMOD_SILENCER 1
//
// config strings are a general means of communicating variable length strings
@ -430,25 +445,26 @@ void Pmove (pmove_t *pmove);
// NOTE: may not have more than 16
typedef enum {
STAT_HEALTH,
STAT_HOLDABLE_ITEM,
STAT_HOLDABLE_ITEM, // Elder: Used to hold unique items in Reaction
#ifdef MISSIONPACK
STAT_PERSISTANT_POWERUP,
#endif
STAT_WEAPONS, // 16 bit fields
STAT_ARMOR, // Elder: technically we don't need this anymore - maybe for vest
STAT_DEAD_YAW, // look this direction when dead (FIXME: get rid of?)
// Begin Duffman
STAT_CLIENTS_READY, // bit mask of clients wishing to exit the intermission (FIXME: configstring?)
// STAT_MAX_HEALTH, // health / armor limit, changable by handicap
//These are RQ3-related specific stats
STAT_CLIPS, // Num Clips player currently has
STAT_STREAK,
// End Duffman
// Homer: for bursting
STAT_BURST, // number of shots in burst
STAT_CLIENTS_READY, // bit mask of clients wishing to exit the intermission (FIXME: configstring?)
// STAT_MAX_HEALTH, // health / armor limit, changable by handicap
STAT_JUMPTIME, //Blaze RE: Double jump
STAT_UNIQUEWEAPONS,
STAT_BURST, // number of shots in burst
STAT_JUMPTIME, // Blaze RE: Double jump
//STAT_UNIQUEWEAPONS, // Elder - wasteful stat - moved to gclient_s
STAT_FALLDAMAGE,
STAT_RQ3, //Blaze: Will hold a few flags for bandage, etc info
STAT_RQ3, // Blaze: Will hold a few flags for bandage, etc info
} statIndex_t;
//STAT_RQ3 stat info
@ -547,6 +563,7 @@ typedef enum {
typedef enum {
HI_NONE,
//TODO: remove the baseQ3 ones
HI_TELEPORTER,
HI_MEDKIT,
HI_KAMIKAZE,
@ -681,6 +698,7 @@ typedef enum {
EV_BULLET_HIT_FLESH,
EV_BULLET_HIT_WALL,
EV_SSG3000_HIT_FLESH,
EV_MISSILE_HIT,
EV_MISSILE_MISS,
@ -1008,6 +1026,7 @@ typedef enum {
ET_INVISIBLE,
ET_GRAPPLE, // grapple hooked on wall
ET_TEAM,
ET_LASER, // lasersight entity type
ET_EVENTS // any of the EV_* events can be added freestanding
// by setting eType to ET_EVENTS + eventNum

View file

@ -22,6 +22,7 @@ global pain sound events for all clients.
===============
*/
void P_DamageFeedback( gentity_t *player ) {
gentity_t *tent;
gclient_t *client;
float count, side;
vec3_t angles, v;
@ -127,10 +128,21 @@ void P_DamageFeedback( gentity_t *player ) {
//Elder: headshot sound
case LOCATION_HEAD:
case LOCATION_FACE:
tent = G_TempEntity2(client->ps.origin, EV_RQ3_SOUND, RQ3_SOUND_HEADSHOT);
//Elder: takes more bandwidth but guarantees a headshot sound
G_Sound(player, CHAN_AUTO, G_SoundIndex("sound/misc/headshot.wav"));
//G_Sound(player, CHAN_AUTO, G_SoundIndex("sound/misc/headshot.wav"));
//G_AddEvent ( player, EV_RQ3_SOUND, RQ3_SOUND_HEADSHOT);
break;
case LOCATION_CHEST:
//Play metal impact if vest was hit
if (client->damage_vest == qtrue)
{
tent = G_TempEntity2(client->ps.origin, EV_RQ3_SOUND, RQ3_SOUND_KEVLARHIT);
client->damage_vest = qfalse;
}
else
G_AddEvent( player, EV_PAIN, player->health );
break;
default:
G_AddEvent( player, EV_PAIN, player->health );
break;
@ -828,6 +840,7 @@ static int StuckInOtherClient(gentity_t *ent) {
}
return qfalse;
}
/*
=============
ThrowWeapon
@ -867,7 +880,7 @@ void ThrowWeapon( gentity_t *ent )
weap = 0;
if (client->ps.stats[STAT_UNIQUEWEAPONS] > 0)
if (client->uniqueWeapons > 0)
{
weap = client->ps.stats[STAT_WEAPONS];
if ((client->ps.stats[STAT_WEAPONS] & (1 << WP_M4) ) == (1 << WP_M4))
@ -893,10 +906,58 @@ void ThrowWeapon( gentity_t *ent )
client->ps.stats[STAT_WEAPONS] &= ~( 1 << weap);
xr_drop= dropWeapon( ent, xr_item, 0, FL_DROPPED_ITEM | FL_THROWN_ITEM );
xr_drop->count= -1; // XRAY FMJ 0 is already taken, -1 means no ammo
client->ps.stats[STAT_UNIQUEWEAPONS]--;
client->uniqueWeapons--;
}
}
/*
=============
ThrowItem
Used to toss an item much like weapons except a bit leaner
=============
*/
void ThrowItem( gentity_t *ent )
{
gclient_t *client;
usercmd_t *ucmd;
gitem_t *xr_item;
gentity_t *xr_drop;
int item;
client = ent->client;
ucmd = &ent->client->pers.cmd;
//Elder: TODO: have to add a reloading case:
//itemonTime > 0 or itemonState == itemon_dropping? Or both?
//Still firing
if ( (ucmd->buttons & BUTTON_ATTACK) == BUTTON_ATTACK || client->ps.weaponTime > 0) {
return;
}
//Elder: Bandaging case
if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK) {
trap_SendServerCommand( ent-g_entities, va("print \"You are too busy bandaging...\n\""));
return;
}
//item = 0;
if (client->uniqueItems > 0)
{
item = bg_itemlist[client->ps.stats[STAT_HOLDABLE_ITEM]].giTag;
xr_item = BG_FindItemForHoldable( item );
client->ps.stats[STAT_HOLDABLE_ITEM] = 0;
//Elder: Just going to re-use the dropWeapon function
xr_drop= dropWeapon( ent, xr_item, 0, FL_DROPPED_ITEM | FL_THROWN_ITEM );
xr_drop->count= -1; // XRAY FMJ 0 is already taken, -1 means no ammo
client->uniqueItems--;
}
}
//Elder: wtf?
void BotTestSolid(vec3_t origin);
/*
@ -1396,9 +1457,9 @@ while a slow client may have multiple ClientEndFrame between ClientThink.
void ClientEndFrame( gentity_t *ent ) {
int i;
clientPersistant_t *pers;
gitem_t *rq3_item;
gentity_t *rq3_temp;
vec3_t spawn_origin, spawn_angles;
// gitem_t *rq3_item;
// gentity_t *rq3_temp;
//vec3_t spawn_origin, spawn_angles;
if ( ent->client->sess.sessionTeam == TEAM_SPECTATOR ) {
SpectatorClientEndFrame( ent );
return;
@ -1466,14 +1527,9 @@ void ClientEndFrame( gentity_t *ent ) {
// Blaze: Do Bleed
// if(ent->client->bleeding)
// CheckBleeding(ent); // perform once-a-second actions
if (level.time % 30000 < 1)
{
G_Printf("Spawn an Item\n");
//rq3_item = BG_FindItem( "Kevlar Vest" );
rq3_item = BG_FindItemForHoldable( HI_SLIPPERS );
rq3_temp = SelectSpawnPoint(ent->client->ps.origin,spawn_origin, spawn_angles);
Drop_Item (rq3_temp, rq3_item, 0);
}
//Elder: moved unique item spawning to new function called RQ3_CheckUniqueItems
// Begin Duffman
//Update the clips Amount in weapon for the client
ent->client->ps.stats[STAT_CLIPS] = ent->client->numClips[ent->client->ps.weapon];
@ -1511,6 +1567,31 @@ void ClientEndFrame( gentity_t *ent ) {
ent->client->consecutiveShots = 0;
}
if ( bg_itemlist[ent->client->ps.stats[STAT_HOLDABLE_ITEM]].giTag == HI_LASER )
{
//Disable laser if switching weapons, bandaging, etc.
if (ent->client->lasersight && ent->client->ps.weaponstate == WEAPON_DROPPING)
{
Laser_Gen(ent, qfalse);
}
//Using M4/MP5/MK23 but not on yet so turn it on
else if (ent->client->lasersight == NULL &&
(ent->client->ps.weapon == WP_M4 ||
ent->client->ps.weapon == WP_MP5 ||
ent->client->ps.weapon == WP_PISTOL))
{
Laser_Gen(ent, qtrue);
}
//Not using M4/MP5/MK23 -- turn it off
else if (ent->client->lasersight &&
!( ent->client->ps.weapon == WP_M4 ||
ent->client->ps.weapon == WP_MP5 ||
ent->client->ps.weapon == WP_PISTOL))
{
Laser_Gen(ent, qfalse);
}
}
G_SetClientSound (ent);

View file

@ -1692,7 +1692,7 @@ void Cmd_Reload( gentity_t *ent ) {
int ammotoadd;
int delay = 0;
G_Printf("(%i) Cmd_Reload: Attempting reload\n", ent->s.clientNum);
//G_Printf("(%i) Cmd_Reload: Attempting reload\n", ent->s.clientNum);
//Elder: added for redundant check but shouldn't need to come here - handled in cgame
//if (ent->client->isBandaging == qtrue) {
@ -2292,10 +2292,10 @@ void Cmd_Unzoom(gentity_t *ent)
/*
=================
Cmd_Drop_f XRAY FMJ
Cmd_DropWeapon_f XRAY FMJ
=================
*/
void Cmd_Drop_f( gentity_t *ent ) {
void Cmd_DropWeapon_f( gentity_t *ent ) {
//Elder: added
//if (ent->client->isBandaging == qtrue) {
@ -2314,6 +2314,49 @@ void Cmd_Drop_f( gentity_t *ent ) {
}
}
/*
=================
Cmd_DropItem_f
=================
*/
void Cmd_DropItem_f( gentity_t *ent )
{
if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK)
{
trap_SendServerCommand( ent-g_entities, va("print \"You are too busy bandaging!\n\""));
return;
}
else
{
//Elder: reset item totals if using bandolier
if (bg_itemlist[ent->client->ps.stats[STAT_HOLDABLE_ITEM]].giTag == HI_BANDOLIER)
{
if (ent->client->numClips[WP_PISTOL] > RQ3_PISTOL_MAXCLIP)
{
ent->client->numClips[WP_PISTOL] = RQ3_PISTOL_MAXCLIP;
ent->client->numClips[WP_AKIMBO] = RQ3_PISTOL_MAXCLIP;
}
if (ent->client->numClips[WP_M3] > RQ3_M3_MAXCLIP)
{
ent->client->numClips[WP_M3] = RQ3_M3_MAXCLIP;
ent->client->numClips[WP_HANDCANNON] = RQ3_M3_MAXCLIP;
}
if (ent->client->numClips[WP_M4] > RQ3_M4_MAXCLIP)
ent->client->numClips[WP_M4] = RQ3_M4_MAXCLIP;
if (ent->client->numClips[WP_MP5] > RQ3_MP5_MAXCLIP)
ent->client->numClips[WP_MP5] = RQ3_MP5_MAXCLIP;
if (ent->client->numClips[WP_KNIFE] > RQ3_KNIFE_MAXCLIP)
ent->client->numClips[WP_KNIFE] = RQ3_KNIFE_MAXCLIP;
if (ent->client->numClips[WP_GRENADE] > RQ3_GRENADE_MAXCLIP)
ent->client->numClips[WP_GRENADE] = RQ3_GRENADE_MAXCLIP;
}
else if (bg_itemlist[ent->client->ps.stats[STAT_HOLDABLE_ITEM]].giTag == HI_LASER)
Laser_Gen(ent, qfalse);
ThrowItem( ent );
}
}
/*
=================
@ -2427,7 +2470,7 @@ void ClientCommand( int clientNum ) {
//Elder: add to reload queue if using fast-reloadable weapons
if (ent->client->ps.weapon == WP_M3 || ent->client->ps.weapon == WP_SSG3000)
ent->client->reloadAttempts++;
G_Printf("Trying a reload...\n");
//G_Printf("Trying a reload...\n");
Cmd_Reload( ent );
}
// End Duffman
@ -2445,7 +2488,10 @@ void ClientCommand( int clientNum ) {
Cmd_Unzoom (ent);
// end hawkins
else if (Q_stricmp (cmd, "dropweapon") == 0) // XRAY FMJ
Cmd_Drop_f( ent );
Cmd_DropWeapon_f( ent );
//Elder: stuff for dropping items
else if (Q_stricmp (cmd, "dropitem") == 0)
Cmd_DropItem_f( ent );
else
trap_SendServerCommand( clientNum, va("print \"unknown cmd %s\n\"", cmd ) );
}

View file

@ -113,7 +113,7 @@ void TossClientItems( gentity_t *self ) {
item = BG_FindItemForWeapon( WP_M3 );
Drop_Item( self, item, angle);
self->client->pers.hadUniqueWeapon[ WP_M3 ] = qfalse;
self->client->ps.stats[STAT_UNIQUEWEAPONS]--;
self->client->uniqueWeapons--;
angle += 30;
}
@ -121,7 +121,7 @@ void TossClientItems( gentity_t *self ) {
item = BG_FindItemForWeapon( WP_M4 );
Drop_Item( self, item, angle);
self->client->pers.hadUniqueWeapon[ WP_M4 ] = qfalse;
self->client->ps.stats[STAT_UNIQUEWEAPONS]--;
self->client->uniqueWeapons--;
angle += 30;
}
@ -129,7 +129,7 @@ void TossClientItems( gentity_t *self ) {
item = BG_FindItemForWeapon( WP_MP5 );
Drop_Item( self, item, angle);
self->client->pers.hadUniqueWeapon[ WP_MP5 ] = qfalse;
self->client->ps.stats[STAT_UNIQUEWEAPONS]--;
self->client->uniqueWeapons--;
angle += 30;
}
@ -137,7 +137,7 @@ void TossClientItems( gentity_t *self ) {
item = BG_FindItemForWeapon( WP_HANDCANNON );
Drop_Item( self, item, angle);
self->client->pers.hadUniqueWeapon[ WP_HANDCANNON ] = qfalse;
self->client->ps.stats[STAT_UNIQUEWEAPONS]--;
self->client->uniqueWeapons--;
angle += 30;
}
@ -145,7 +145,7 @@ void TossClientItems( gentity_t *self ) {
item = BG_FindItemForWeapon( WP_SSG3000 );
Drop_Item( self, item, angle);
self->client->pers.hadUniqueWeapon[ WP_SSG3000 ] = qfalse;
self->client->ps.stats[STAT_UNIQUEWEAPONS]--;
self->client->uniqueWeapons--;
angle += 30;
}
@ -158,6 +158,13 @@ void TossClientItems( gentity_t *self ) {
if ( self->client->ps.ammo[ WP_KNIFE ] > 0) {
item = BG_FindItemForWeapon( WP_KNIFE );
Drop_Item (self, item, angle);
angle += 30;
}
if ( self->client->ps.stats[STAT_HOLDABLE_ITEM] )
{
Drop_Item(self, &bg_itemlist[self->client->ps.stats[STAT_HOLDABLE_ITEM]], angle);
angle += 30;
}
// drop all the powerups if not in teamplay
@ -1652,14 +1659,15 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
}
case (LOCATION_CHEST):
{
//Vest stuff
if (bg_itemlist[targ->client->ps.stats[STAT_HOLDABLE_ITEM]].giTag == HI_KEVLAR)
{
if ((attacker->client->ps.stats[STAT_WEAPONS] & (1 << WP_SSG3000)) == (1 << WP_SSG3000))
//if ((attacker->client->ps.stats[STAT_WEAPONS] & (1 << WP_SSG3000)) == (1 << WP_SSG3000))
if (attacker->client->ps.weapon == WP_SSG3000)
{ trap_SendServerCommand(attacker-g_entities, va("print \"%s has a Kevlar Vest, too bad you have AP rounds...\n\"",targ->client->pers.netname));
trap_SendServerCommand(targ-g_entities, va("print \"Kevlar Vest absorbed some of %s's AP sniper round\n\"",attacker->client->pers.netname));
take = take * .325;
take = take * 0.325;
}
else
@ -1668,6 +1676,8 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
take = take/10;
bleeding = 0;
}
//Elder: flag for sound in feedback
targ->client->damage_vest = qtrue;
break;
}
else

View file

@ -176,57 +176,71 @@ int Pickup_PersistantPowerup( gentity_t *ent, gentity_t *other ) {
int Pickup_Holdable( gentity_t *ent, gentity_t *other ) {
//Elder: why it's implemented like this I have no idea
other->client->ps.stats[STAT_HOLDABLE_ITEM] = ent->item - bg_itemlist;
//other->client->ps.stats[STAT_HOLDABLE_ITEM] = ent->item->giTag;
other->client->uniqueItems++;
//Fire up the laser if it's picked up
if (ent->item->giTag == HI_LASER)
{
Laser_Gen(other, qtrue);
}
/* Blaze: No Kamikazie
if( ent->item->giTag == HI_KAMIKAZE ) {
other->client->ps.eFlags |= EF_KAMIKAZE;
}*/
return RESPAWN_HOLDABLE;
//Elder: our unique items don't respawn
return -1;
//return RESPAWN_HOLDABLE;
}
//======================================================================
void Add_Ammo (gentity_t *ent, int weapon, int count)
void Add_Ammo (gentity_t *ent, int weapon, int count, int bandolierFactor)
{
//Blaze: Reaction stuff, add to clip when picking up ammo packs
//Elder: Modified to use constants def'd in bg_public.h
ent->client->numClips[weapon] += count;
switch (weapon)
{
case WP_KNIFE:
//Blaze: you get more knifes by picking up the "gun" as opposed to ammo
break;
case WP_PISTOL:
if (ent->client->numClips[weapon] > RQ3_PISTOL_MAXCLIP)
ent->client->numClips[weapon] = RQ3_PISTOL_MAXCLIP;
if (ent->client->numClips[weapon] > RQ3_PISTOL_MAXCLIP * bandolierFactor)
ent->client->numClips[weapon] = RQ3_PISTOL_MAXCLIP * bandolierFactor;
break;
case WP_AKIMBO:
if (ent->client->numClips[weapon] > RQ3_AKIMBO_MAXCLIP)
ent->client->numClips[weapon] = RQ3_AKIMBO_MAXCLIP;
if (ent->client->numClips[weapon] > RQ3_AKIMBO_MAXCLIP * bandolierFactor)
ent->client->numClips[weapon] = RQ3_AKIMBO_MAXCLIP * bandolierFactor;
break;
case WP_MP5:
if (ent->client->numClips[weapon] > RQ3_MP5_MAXCLIP)
ent->client->numClips[weapon] = RQ3_MP5_MAXCLIP;
if (ent->client->numClips[weapon] > RQ3_MP5_MAXCLIP * bandolierFactor)
ent->client->numClips[weapon] = RQ3_MP5_MAXCLIP * bandolierFactor;
break;
case WP_M4:
if (ent->client->numClips[weapon] > RQ3_M4_MAXCLIP)
ent->client->numClips[weapon] = RQ3_M4_MAXCLIP;
if (ent->client->numClips[weapon] > RQ3_M4_MAXCLIP * bandolierFactor)
ent->client->numClips[weapon] = RQ3_M4_MAXCLIP * bandolierFactor;
break;
case WP_M3:
if (ent->client->numClips[weapon] > RQ3_M3_MAXCLIP)
ent->client->numClips[weapon] = RQ3_M3_MAXCLIP;
if (ent->client->numClips[weapon] > RQ3_M3_MAXCLIP * bandolierFactor)
ent->client->numClips[weapon] = RQ3_M3_MAXCLIP * bandolierFactor;
break;
case WP_HANDCANNON:
if (ent->client->numClips[weapon] > RQ3_HANDCANNON_MAXCLIP)
ent->client->numClips[weapon] = RQ3_HANDCANNON_MAXCLIP;
if (ent->client->numClips[weapon] > RQ3_HANDCANNON_MAXCLIP * bandolierFactor)
ent->client->numClips[weapon] = RQ3_HANDCANNON_MAXCLIP * bandolierFactor;
break;
case WP_SSG3000:
if (ent->client->numClips[weapon] > RQ3_SSG3000_MAXCLIP)
ent->client->numClips[weapon] = RQ3_SSG3000_MAXCLIP;
if (ent->client->numClips[weapon] > RQ3_SSG3000_MAXCLIP * bandolierFactor)
ent->client->numClips[weapon] = RQ3_SSG3000_MAXCLIP * bandolierFactor;
break;
case WP_GRENADE:
//Blaze: you get more knifes by picking up the "gun" as opposed to ammo
@ -258,7 +272,7 @@ void Add_Ammo (gentity_t *ent, int weapon, int count)
//}
}
int Pickup_Ammo (gentity_t *ent, gentity_t *other)
int Pickup_Ammo (gentity_t *ent, gentity_t *other, int bandolierFactor)
{
int quantity;
@ -267,7 +281,7 @@ int Pickup_Ammo (gentity_t *ent, gentity_t *other)
} else {
quantity = ent->item->quantity;
}
Add_Ammo (other, ent->item->giTag, quantity);
Add_Ammo (other, ent->item->giTag, quantity, bandolierFactor);
return RESPAWN_AMMO;
}
@ -275,7 +289,7 @@ int Pickup_Ammo (gentity_t *ent, gentity_t *other)
//======================================================================
int Pickup_Weapon (gentity_t *ent, gentity_t *other) {
int Pickup_Weapon (gentity_t *ent, gentity_t *other, int bandolierFactor) {
int quantity,ammotoadd;
if ( ent->count < 0 ) {
@ -351,15 +365,15 @@ int Pickup_Weapon (gentity_t *ent, gentity_t *other) {
break;
case WP_MP5:
ammotoadd= RQ3_MP5_AMMO;
other->client->ps.stats[STAT_UNIQUEWEAPONS]++;
other->client->uniqueWeapons++;
break;
case WP_M4:
ammotoadd= RQ3_M4_AMMO;
other->client->ps.stats[STAT_UNIQUEWEAPONS]++;
other->client->uniqueWeapons++;
break;
case WP_M3:
ammotoadd= RQ3_M3_AMMO;
other->client->ps.stats[STAT_UNIQUEWEAPONS]++;
other->client->uniqueWeapons++;
break;
case WP_HANDCANNON:
ammotoadd= RQ3_HANDCANNON_AMMO;
@ -369,20 +383,20 @@ int Pickup_Weapon (gentity_t *ent, gentity_t *other) {
//When it's dropped
//other->client->numClips[ WP_HANDCANNON ] += 5;
//other->client->numClips[ WP_M3 ] += 5;
other->client->ps.stats[STAT_UNIQUEWEAPONS]++;
other->client->uniqueWeapons++;
break;
case WP_SSG3000:
ammotoadd= RQ3_SSG3000_AMMO;
other->client->ps.stats[STAT_UNIQUEWEAPONS]++;
other->client->uniqueWeapons++;
break;
case WP_GRENADE:
if (other->client->ps.ammo[WP_GRENADE] < RQ3_GRENADE_MAXCLIP)
if (other->client->ps.ammo[WP_GRENADE] < RQ3_GRENADE_MAXCLIP * bandolierFactor)
{
ammotoadd=other->client->ps.ammo[WP_GRENADE] + 1;
}
else
{
ammotoadd= RQ3_GRENADE_MAXCLIP;
ammotoadd= RQ3_GRENADE_MAXCLIP * bandolierFactor;
}
break;
default:
@ -573,6 +587,8 @@ void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) {
int respawn;
qboolean predict;
int bandolierFactor;
if (!other->client)
return;
@ -585,6 +601,12 @@ void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) {
predict = other->client->pers.predictItemPickup;
if (bg_itemlist[other->client->ps.stats[STAT_HOLDABLE_ITEM]].giTag == HI_BANDOLIER)
bandolierFactor = 2;
else
bandolierFactor = 1;
//Elder: should check if the item was recently thrown ... if it was, then
//don't allow it to be picked up ... or something like that
@ -602,18 +624,18 @@ void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) {
//Specials: if you have more than/equal to limit (remember bando later), leave
case WP_KNIFE:
if ( ( (other->client->ps.stats[STAT_WEAPONS] & (1 << WP_KNIFE) ) == (1 << WP_KNIFE) ) &&
(other->client->ps.ammo[ent->item->giTag] >= RQ3_KNIFE_MAXCLIP) )
(other->client->ps.ammo[ent->item->giTag] >= RQ3_KNIFE_MAXCLIP * bandolierFactor))
return;
break;
case WP_GRENADE:
if ( ( (other->client->ps.stats[STAT_WEAPONS] & (1 << WP_GRENADE) )== (1 << WP_GRENADE) ) &&
(other->client->ps.ammo[ent->item->giTag] >= RQ3_GRENADE_MAXCLIP) )
(other->client->ps.ammo[ent->item->giTag] >= RQ3_GRENADE_MAXCLIP * bandolierFactor) )
return;
break;
case WP_PISTOL:
//Elder: always have pistol - but extra ones give akimbo or clips
if ( ( (other->client->ps.stats[STAT_WEAPONS] & (1 << WP_AKIMBO) ) == (1 << WP_AKIMBO) ) &&
other->client->numClips[WP_PISTOL] >= RQ3_PISTOL_MAXCLIP ) {
other->client->numClips[WP_PISTOL] >= RQ3_PISTOL_MAXCLIP * bandolierFactor) {
//leave if we have max clips and akimbos
return;
}
@ -624,7 +646,7 @@ void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) {
case WP_M4:
case WP_SSG3000:
//Elder: check to see if it's in mid-air
if (other->client->ps.stats[STAT_UNIQUEWEAPONS] >= g_RQ3_maxWeapons.integer ||
if (other->client->uniqueWeapons >= g_RQ3_maxWeapons.integer ||
ent->s.pos.trDelta[2] != 0)
return;
break;
@ -696,11 +718,8 @@ void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) {
}
*/
//Elder: Moved after checks so we don't print a billion log messages
G_LogPrintf( "Item: %i %s\n", other->s.number, ent->item->classname );
respawn = Pickup_Weapon(ent, other);
respawn = Pickup_Weapon(ent, other, bandolierFactor);
//Elder: added pistol and knife condition
@ -724,31 +743,31 @@ void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) {
if (other->client->numClips[ent->item->giTag] >= 0) return;//No clips for knifes
break;
case WP_PISTOL:
if (other->client->numClips[ent->item->giTag] >= RQ3_PISTOL_MAXCLIP ) return;
if (other->client->numClips[ent->item->giTag] >= RQ3_PISTOL_MAXCLIP * bandolierFactor) return;
break;
case WP_M3:
if (other->client->numClips[ent->item->giTag] >= RQ3_M3_MAXCLIP) return;
if (other->client->numClips[ent->item->giTag] >= RQ3_M3_MAXCLIP * bandolierFactor) return;
break;
case WP_HANDCANNON:
if (other->client->numClips[ent->item->giTag] >= RQ3_HANDCANNON_MAXCLIP) return;
if (other->client->numClips[ent->item->giTag] >= RQ3_HANDCANNON_MAXCLIP * bandolierFactor) return;
break;
case WP_MP5:
if (other->client->numClips[ent->item->giTag] >= RQ3_MP5_MAXCLIP ) return;
if (other->client->numClips[ent->item->giTag] >= RQ3_MP5_MAXCLIP * bandolierFactor) return;
break;
case WP_M4:
if (other->client->numClips[ent->item->giTag] >= RQ3_M4_MAXCLIP ) return;
if (other->client->numClips[ent->item->giTag] >= RQ3_M4_MAXCLIP * bandolierFactor) return;
break;
case WP_SSG3000:
if (other->client->numClips[ent->item->giTag] >= RQ3_SSG3000_MAXCLIP ) return;
if (other->client->numClips[ent->item->giTag] >= RQ3_SSG3000_MAXCLIP * bandolierFactor) return;
break;
case WP_AKIMBO:
if (other->client->numClips[ent->item->giTag] >= RQ3_AKIMBO_MAXCLIP ) return;
if (other->client->numClips[ent->item->giTag] >= RQ3_AKIMBO_MAXCLIP * bandolierFactor) return;
break;
case WP_GRENADE:
if (other->client->numClips[ent->item->giTag] >= 0 ) return;//no clips for grenades
break;
}
respawn = Pickup_Ammo(ent, other);
respawn = Pickup_Ammo(ent, other, bandolierFactor);
// predict = qfalse;
break;
case IT_ARMOR:
@ -770,6 +789,10 @@ void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) {
respawn = Pickup_Team(ent, other);
break;
case IT_HOLDABLE:
//Elder: check to see if it's in mid-air
if (other->client->uniqueItems >= 1 || //g_RQ3_maxWeapons.integer ||
ent->s.pos.trDelta[2] != 0)
return;
respawn = Pickup_Holdable(ent, other);
break;
default:
@ -780,6 +803,9 @@ void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) {
return;
}
//Elder: Moved after checks so we don't print a billion log messages
G_LogPrintf( "Item: %i %s\n", other->s.number, ent->item->classname );
// play the normal pickup sound
if (predict) {
G_AddPredictableEvent( other, EV_ITEM_PICKUP, ent->s.modelindex );
@ -919,10 +945,17 @@ gentity_t *LaunchItem( gitem_t *item, vec3_t origin, vec3_t velocity, int xr_fla
//Don't forget to condition it when we get teamplay in
else if ( item->giType == IT_WEAPON &&
item->giTag != WP_GRENADE && item->giTag != WP_PISTOL &&
item->giTag != WP_AKIMBO && item->giTag != WP_KNIFE ) {
item->giTag != WP_AKIMBO && item->giTag != WP_KNIFE )
{
dropped->think = RQ3_DroppedWeaponThink;
dropped->nextthink = level.time + RQ3_RESPAWNTIME_DEFAULT;
}
//Elder: for unique items in deathmatch ... remember to condition for teamplay
else if ( item->giType == IT_HOLDABLE)
{
dropped->think = RQ3_DroppedItemThink;
dropped->nextthink = level.time + RQ3_RESPAWNTIME_DEFAULT;
}
else { // auto-remove after 30 seconds
dropped->think = G_FreeEntity;
@ -951,7 +984,8 @@ Modified by Elder
dropWeapon XRAY FMJ
================
*/
gentity_t *dropWeapon( gentity_t *ent, gitem_t *item, float angle, int xr_flags ) { // XRAY FMJ
gentity_t *dropWeapon( gentity_t *ent, gitem_t *item, float angle, int xr_flags )
{
vec3_t velocity;
vec3_t angles;
vec3_t origin;
@ -1182,6 +1216,13 @@ void ClearRegisteredItems( void ) {
//Blaze: Changed WP_MACHINEGUN to WP_PISTOL and WP_GAUNTLET to WP_KNIFE
RegisterItem( BG_FindItemForWeapon( WP_PISTOL ) );
RegisterItem( BG_FindItemForWeapon( WP_KNIFE ) );
//Elder: add unique items here
RegisterItem( BG_FindItemForHoldable( HI_KEVLAR ) );
RegisterItem( BG_FindItemForHoldable( HI_SLIPPERS ) );
RegisterItem( BG_FindItemForHoldable( HI_SILENCER ) );
RegisterItem( BG_FindItemForHoldable( HI_BANDOLIER ) );
RegisterItem( BG_FindItemForHoldable( HI_LASER ) );
#ifdef MISSIONPACK
if( g_gametype.integer == GT_HARVESTER ) {
RegisterItem( BG_FindItem( "Red Cube" ) );
@ -1513,3 +1554,41 @@ void RQ3_ResetWeapon( int weapon ) {
//return rent;
}
/*
==============
Added by Elder
RQ3_DroppedItemThink
Items respawn themselves after a period of time
Based on the AQ2 item code which was based off Q2 CTF techs
==============
*/
void RQ3_DroppedItemThink(gentity_t *ent) {
gitem_t *rq3_item;
gentity_t *rq3_temp;
float angle = rand() % 360;
switch (ent->item->giTag)
{
case HI_KEVLAR:
case HI_LASER:
case HI_SILENCER:
case HI_BANDOLIER:
case HI_SLIPPERS:
//Free entity and reset position in unique item array
//level.uniqueItemsUsed &= ~(1 << ent->item->giTag);
rq3_item = BG_FindItemForHoldable( ent->item->giTag );
rq3_temp = (gentity_t*)SelectRandomDeathmatchSpawnPoint();
G_FreeEntity(ent);
Drop_Item (rq3_temp, rq3_item, angle);
G_Printf("RQ3_DroppedItemThink: Freeing item entity + respawning\n");
break;
default:
//Elder: shouldn't have to come here
G_Printf("RQ3_DroppedItemThink: Out of range or invalid item %d\n", ent->item->giTag);
G_FreeEntity(ent);
break;
}
}

View file

@ -296,6 +296,7 @@ struct gclient_s {
int damage_knockback; // impact damage
vec3_t damage_from; // origin for vector calculation
qboolean damage_fromWorld; // if true, don't use the damage_from vector
qboolean damage_vest; // Elder: if true, play the vest-hit sound
int accurateCount; // for "impressive" reward sound
@ -332,8 +333,12 @@ struct gclient_s {
qboolean openDoor;//Blaze: used to hold if someone has hit opendoor key
// timeResidual is used to handle events that happen every second
// like health / armor countdowns and regeneration
int timeResidual;
//Elder: C3A laser tutorial
gentity_t *lasersight; // lasersight OR flashlight if in use
int bleeding; //Blaze: remaining points to bleed away
int bleed_remain; //Blaze: How much left to bleed
int bleedloc; //Blaze: Where are we bleeding
@ -361,15 +366,16 @@ struct gclient_s {
//qboolean isBandaging; //Elder: player in the process of bandaging
// end Homer
//Elder: added for 3rb and akimbos
int weaponfireNextTime; //for akimbos and burst modes
int weaponfireNextTime; // for akimbos
int lastzoom; // Elder: save last zoom state when firing
int fastReloads; //Elder: for queuing M3/SSG reloads
int lastReloadTime; //Elder: for queuing M3/SSG reloads
int reloadAttempts; //Elder: for queueing M3/SSG reloads
int fastReloads; // Elder: for queuing M3/SSG reloads
int lastReloadTime; // Elder: for queuing M3/SSG reloads
int reloadAttempts; // Elder: for queuing M3/SSG reloads
int consecutiveShots; //Elder: for M4 ride-up/kick
int consecutiveShots; // Elder: for M4 ride-up/kick
int uniqueWeapons; // Elder: formerly a stat, now just a server var
int uniqueItems;
#ifdef MISSIONPACK
gentity_t *persistantPowerup;
@ -475,6 +481,7 @@ typedef struct {
#ifdef MISSIONPACK
int portalSequence;
#endif
} level_locals_t;
//
// rxn_game.c
@ -484,6 +491,7 @@ void CheckBleeding(gentity_t *targ);
void StartBandage(gentity_t *ent);
void ThrowWeapon( gentity_t *ent );
void ThrowItem( gentity_t *ent );
gentity_t *dropWeapon( gentity_t *ent, gitem_t *item, float angle, int xr_flags ); // XRAY FMJ
//Blaze Reaction knife stuff
//Elder: commented out - unused?
@ -509,6 +517,10 @@ void SetTeam( gentity_t *ent, char *s );
void Cmd_FollowCycle_f( gentity_t *ent, int dir );
void Cmd_Unzoom(gentity_t *ent);
void Cmd_OpenDoor(gentity_t *ent);
//Elder: C3A laser tutorial
void Laser_Gen (gentity_t *ent, qboolean enabled);
void Laser_Think( gentity_t *self );
//Elder: commented out for Homer
//void toggleSemi(gentity_t *ent);
@ -528,7 +540,8 @@ void G_SpawnItem (gentity_t *ent, gitem_t *item);
void FinishSpawningItem( gentity_t *ent );
void Think_Weapon (gentity_t *ent);
int ArmorIndex (gentity_t *ent);
void Add_Ammo (gentity_t *ent, int weapon, int count);
//Elder: added bandolier factor
void Add_Ammo (gentity_t *ent, int weapon, int count, int bandolierfactor);
void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace);
void ClearRegisteredItems( void );
@ -536,6 +549,7 @@ void RegisterItem( gitem_t *item );
void SaveRegisteredItems( void );
//Elder: added
void RQ3_DroppedItemThink(gentity_t *ent);
void RQ3_DroppedWeaponThink(gentity_t *ent);
void RQ3_ResetWeapon( int weapon );
@ -673,6 +687,8 @@ int TeamLeader( int team );
team_t PickTeam( int ignoreClientNum );
void SetClientViewAngle( gentity_t *ent, vec3_t angle );
gentity_t *SelectSpawnPoint ( vec3_t avoidPoint, vec3_t origin, vec3_t angles );
//Elder: added because I use it in g_main.c and g_items.c for item spawning
gentity_t *SelectRandomDeathmatchSpawnPoint( void );
void CopyToBodyQue( gentity_t *ent );
void respawn (gentity_t *ent);
void BeginIntermission (void);
@ -727,6 +743,8 @@ void QDECL G_LogPrintf( const char *fmt, ... );
void SendScoreboardMessageToAllClients( void );
void QDECL G_Printf( const char *fmt, ... );
void QDECL G_Error( const char *fmt, ... );
//Elder: added
void RQ3_StartUniqueItems ( void );
//
// g_client.c

View file

@ -471,6 +471,9 @@ void G_InitGame( int levelTime, int randomSeed, int restart ) {
G_CheckTeamItems();
}
//Elder: spawn unique items.
RQ3_StartUniqueItems();
SaveRegisteredItems();
G_Printf ("-----------------------------------\n");
@ -1805,6 +1808,14 @@ start = trap_Milliseconds();
}
end = trap_Milliseconds();
// Elder: added for unique items
//if (level.time - level.uniqueItemsTime >= 30000)
//if (level.time % 30000 < 1)
//{
//level.uniqueItemsTime = level.time;
//RQ3_CheckUniqueItems();
//}
// see if it is time to do a tournement restart
CheckTournament();
@ -1831,3 +1842,52 @@ end = trap_Milliseconds();
trap_Cvar_Set("g_listEntity", "0");
}
}
/*
==============
Added by Elder
RQ3_StartUniqueItems
Spawns items at the beginning of a level
==============
*/
void RQ3_StartUniqueItems ( void )
{
gitem_t *rq3_item;
gentity_t *rq3_temp;
float angle = 0;
G_Printf("RQ3_StartUniqueItems: Starting unique item spawn code...\n");
rq3_item = BG_FindItemForHoldable( HI_SLIPPERS );
rq3_temp = (gentity_t*)SelectRandomDeathmatchSpawnPoint();
Drop_Item (rq3_temp, rq3_item, angle);
angle += 30;
rq3_item = BG_FindItemForHoldable( HI_KEVLAR );
rq3_temp = (gentity_t*)SelectRandomDeathmatchSpawnPoint();
Drop_Item (rq3_temp, rq3_item, angle);
angle += 30;
rq3_item = BG_FindItemForHoldable( HI_SILENCER );
rq3_temp = (gentity_t*)SelectRandomDeathmatchSpawnPoint();
Drop_Item (rq3_temp, rq3_item, angle);
angle += 30;
rq3_item = BG_FindItemForHoldable( HI_BANDOLIER );
rq3_temp = (gentity_t*)SelectRandomDeathmatchSpawnPoint();
Drop_Item (rq3_temp, rq3_item, angle);
angle += 30;
rq3_item = BG_FindItemForHoldable( HI_LASER );
rq3_temp = (gentity_t*)SelectRandomDeathmatchSpawnPoint();
Drop_Item (rq3_temp, rq3_item, angle);
angle += 30;
//rq3_item = BG_FindItem( "Kevlar Vest" );
//rq3_item = BG_FindItemForHoldable( HI_SLIPPERS );
//rq3_temp = SelectSpawnPoint(ent->client->ps.origin,spawn_origin, spawn_angles);
//Drop_Item (rq3_temp, rq3_item, 0);
}

View file

@ -271,6 +271,38 @@ qboolean G_CallSpawn( gentity_t *ent ) {
return qfalse;
}
//Blaze: allow for Reaction specific spawns to be used
//Elder: map Q3DM weapons -> RQ3 weapons
if (!strcmp(ent->classname,"weapon_gauntlet"))
ent->classname = "weapon_knife";
else if (!strcmp(ent->classname,"weapon_machinegun"))
ent->classname = "weapon_pistol";
else if (!strcmp(ent->classname,"weapon_shotgun"))
ent->classname = "weapon_m3";
else if (!strcmp(ent->classname,"weapon_plasmagun"))
ent->classname = "weapon_mp5";
else if (!strcmp(ent->classname,"weapon_rocketlauncher"))
ent->classname = "weapon_handcannon";
else if (!strcmp(ent->classname,"weapon_railgun"))
ent->classname = "weapon_ssg3000";
else if (!strcmp(ent->classname,"weapon_bfg"))
ent->classname = "weapon_m4";
else if (!strcmp(ent->classname,"ammo_grenades"))
ent->classname = "weapon_grenade";
//Elder: map Q3DM ammo -> RQ3 ammo
if (!strcmp(ent->classname,"ammo_bullets"))
ent->classname = "ammo_mk23";
else if (!strcmp(ent->classname, "ammo_slugs"))
ent->classname = "ammo_ssg3000";
else if (!strcmp(ent->classname, "ammo_cells"))
ent->classname = "ammo_mp5";
else if (!strcmp(ent->classname, "ammo_bfg"))
ent->classname = "ammo_m4";
else if (!strcmp(ent->classname, "ammo_rockets"))
ent->classname = "ammo_shells";
/*
//Elder: old stuff
if (!strcmp(ent->classname,"weapon_gauntlet")) ent->classname = "weapon_knife";
else if (!strcmp(ent->classname,"weapon_railgun")) ent->classname = "weapon_ssg3000";
else if (!strcmp(ent->classname,"weapon_shotgun")) ent->classname = "weapon_m3";
@ -279,6 +311,7 @@ qboolean G_CallSpawn( gentity_t *ent ) {
else if (!strcmp(ent->classname,"weapon_bfg")) ent->classname = "weapon_m4";
else if (!strcmp(ent->classname,"weapon_grenadelauncher")) ent->classname = "weapon_pistol";
else if (!strcmp(ent->classname,"ammo_grenades")) ent->classname = "weapon_grenade";
*/
// check item spawn functions
for ( item=bg_itemlist+1 ; item->classname ; item++ ) {
if ( !strcmp(item->classname, ent->classname) ) {

View file

@ -111,7 +111,7 @@ qboolean JumpKick( gentity_t *ent )
tent->s.weapon = ent->s.weapon;
}
if (traceEnt->client && traceEnt->client->ps.stats[STAT_UNIQUEWEAPONS] > 0)
if (traceEnt->client && traceEnt->client->uniqueWeapons > 0)
{
//Elder: toss a unique weapon if kicked
//Todo: Need to make sure to cancel any reload attempts
@ -1127,7 +1127,18 @@ int RQ3_Spread (gentity_t *ent, int spread)
else
stage = 1;
//TODO: add laser advantage
//added laser advantage
if (bg_itemlist[ent->client->ps.stats[STAT_HOLDABLE_ITEM]].giTag == HI_LASER &&
(ent->client->ps.weapon == WP_PISTOL ||
ent->client->ps.weapon == WP_MP5 ||
ent->client->ps.weapon == WP_M4))
{
//G_Printf("Using laser advantage\n");
if (stage == 1)
stage = 0;
else
stage = 1;
}
return (int)(spread * factor[stage]);
@ -1381,7 +1392,8 @@ void Weapon_SSG3000_Fire (gentity_t *ent) {
// send impacts
if ( traceEnt->client )
{
tent[unlinked] = G_TempEntity( trace.endpos, EV_BULLET_HIT_FLESH );
tent[unlinked] = G_TempEntity( trace.endpos, EV_SSG3000_HIT_FLESH );
//tent[unlinked]->s.eventParm = DirToByte( trace.plane.normal );
tent[unlinked]->s.eventParm = traceEnt->s.number;
}
else
@ -2073,3 +2085,94 @@ void G_StartKamikaze( gentity_t *ent ) {
te->s.eventParm = GTS_KAMIKAZE;
}
#endif
/*
============
Laser Sight Stuff
Laser Sight / Flash Light Functions
============
*/
void Laser_Gen( gentity_t *ent, qboolean enabled ) {
gentity_t *las;
//Elder: force it to laser
int type = 1;
//Get rid of you?
if ( ent->client->lasersight && !enabled)
{
G_FreeEntity( ent->client->lasersight );
ent->client->lasersight = NULL;
return;
}
las = G_Spawn();
las->nextthink = level.time + 10;
las->think = Laser_Think;
las->s.clientNum = ent->s.number;
las->r.ownerNum = ent->s.number;
las->parent = ent;
las->s.eType = ET_LASER;
//Elder: added to enable lerping in cgame
las->s.pos.trType = TR_INTERPOLATE;
//Lets tell it if flashlight or laser
if (type == 2) {
las->s.eventParm = 2; //tells CG that it is a flashlight
las->classname = "flashlight";
}
else {
las->s.eventParm = 1; //tells CG that it is a laser sight
las->classname = "lasersight";
}
ent->client->lasersight = las;
}
void Laser_Think( gentity_t *self )
{
vec3_t end, start, forward, up;
trace_t tr;
//If Player Dies, You Die -> now thanks to Camouflage!
if (self->parent->client->ps.pm_type == PM_DEAD) {
G_FreeEntity(self);
return;
}
//Set Aiming Directions
AngleVectors(self->parent->client->ps.viewangles, forward, right, up);
CalcMuzzlePoint(self->parent, forward, right, up, start);
VectorMA (start, 8192 * 16, forward, end);
//Trace Position
trap_Trace (&tr, start, NULL, NULL, end, self->parent->s.number, MASK_SHOT );
//Did you not hit anything?
if (tr.surfaceFlags & SURF_NOIMPACT || tr.surfaceFlags & SURF_SKY) {
self->nextthink = level.time + 10;
trap_UnlinkEntity(self);
return;
}
//Move you forward to keep you visible
if (tr.fraction != 1)
VectorMA(tr.endpos,-4,forward,tr.endpos);
//Set Your position
VectorCopy( tr.endpos, self->r.currentOrigin );
VectorCopy( tr.endpos, self->s.pos.trBase );
vectoangles(tr.plane.normal, self->s.angles);
trap_LinkEntity(self);
//Prep next move
self->nextthink = level.time + 10;
}

View file

@ -24,6 +24,8 @@ void CheckBleeding(gentity_t *targ)
targ->client->bleedBandageCount < 1)
{
//Elder: skip damage being dealt
//TODO: check bleed_remain again -- if it's > 11, then reset bleedBandageCount?
//That would probably remove the long-time AQ2 headshot bandage bug
}
else
{