Reworking the sniper zoom and bandage required extensive server changes
to fit the new model.  Also made various fixes.
This commit is contained in:
Victor Chow 2001-06-18 01:59:58 +00:00
parent 3fe61cd477
commit b37c00c9d0
12 changed files with 411 additions and 115 deletions

View File

@ -939,6 +939,10 @@ qboolean BG_CanItemBeGrabbed( int gametype, const entityState_t *ent, const play
switch( item->giType ) {
case IT_WEAPON:
//Elder: gotta check before we can pick it up
//if (item->giTag == WP_KNIFE && ps->ammo[WP_KNIFE] >= RQ3_KNIFE_MAXCLIP)
//return qfalse;
//else
return qtrue; // weapons are always picked up
case IT_AMMO:

View File

@ -1810,7 +1810,14 @@ static void PM_Weapon( void ) {
pm->ps->weaponTime = 0;
pm->ps->weaponstate = WEAPON_READY;
// Homer: not firing, reset burst value (cheaper than a non-zero check)
//Elder: reset only if the max amount has been shot
//if ( pm->ps->weapon == WP_PISTOL) {
pm->ps->stats[STAT_BURST] = 0;
//}
//else if ( ( pm->ps->weapon == WP_M4 && pm->ps->stats[STAT_BURST] > 2 ) ||
//( pm->ps->weapon == WP_MP5 && pm->ps->stats[STAT_BURST] > 2 ) ) {
//pm->ps->stats[STAT_BURST] = 0;
//}
return;
}
@ -1880,41 +1887,40 @@ static void PM_Weapon( void ) {
switch( pm->ps->weapon ) {
default:
//Blaze: Reaction Sniper Rifle delay
//Elder: weapon delay times using constants
case WP_SSG3000:
addTime = 1500;
addTime = RQ3_SSG3000_DELAY;
break;
//Blaze: Reaction Pistol delay
case WP_PISTOL:
addTime = 500;
addTime = RQ3_PISTOL_DELAY;
break;
//Blaze: Reaction M4 fire delay
case WP_M4:
addTime = 80;//refire time
addTime = RQ3_M4_DELAY;
break;
//Blaze: Reaction MP5 fire delay
case WP_MP5:
addTime = 100;//refire time
addTime = RQ3_MP5_DELAY;
break;
//Blaze: Reaction Knife fire delay
case WP_KNIFE:
addTime = 1000;//refire time
if ( (pm->ps->persistant[PERS_WEAPONMODES] & RQ3_KNIFEMODE) == RQ3_KNIFEMODE) {
//knife slash
addTime = RQ3_KNIFE_DELAY;
}
else {
//knife throw
addTime = RQ3_THROW_DELAY;
}
break;
//Blaze: Reaction HandCannon fire delay
case WP_HANDCANNON:
addTime = 1500;//refire time
addTime = RQ3_HANDCANNON_DELAY;
break;
//Blaze: Reaction Shotgun fire delay
case WP_M3:
addTime = 1000;//refire time
addTime = RQ3_M3_DELAY;
break;
//Blaze: Reaction Akimbo fire delay
case WP_AKIMBO:
addTime = 1000;//refire time
addTime = RQ3_AKIMBO_DELAY;
break;
//Blaze: Reaction Grenade fire delay
case WP_GRENADE:
addTime = 1000;//refire time
addTime = RQ3_GRENADE_DELAY;
break;
#ifdef MISSIONPACK
case WP_NAILGUN:

View File

@ -16,10 +16,12 @@
#define RANK_TIED_FLAG 0x4000
//Elder: this are uncertified
#define DEFAULT_SHOTGUN_SPREAD 700
#define DEFAULT_HANDCANNON_SPREAD 1400
#define DEFAULT_SHOTGUN_COUNT 11
//Elder: changed this will affect the cgame entity placement
#define ITEM_RADIUS 15 // item sizes are needed for client side pickup detection
#define LIGHTNING_RANGE 768
@ -96,7 +98,7 @@
//Elder: confused?
//Elder: used for STAT_KNIFE ...
//Elder: used for STAT_KNIFE ... obsolete now
#define RQ3_KNIFE_SLASH 0
#define RQ3_KNIFE_THROW 1
@ -135,6 +137,9 @@
#define AKIMBO_DAMAGE 90
#define SLASH_DAMAGE 200 //Shashing knife damage
#define THROW_DAMAGE 250 //Throwing Knife damage
#define GRENADE_DAMAGE 170
#define GRENADE_SPLASH_DAMAGE 170
#define GRENADE_SPLASH_RADIUS 340 //Splash damage * 2
#define PISTOL_SPREAD 140
#define MP5_SPREAD 250
@ -142,6 +147,44 @@
#define SNIPER_SPREAD 425
#define AKIMBO_SPREAD 300
//Elder: weapon kicks - I think this is against whoever got hit?
#define RQ3_PISTOL_KICK 150
#define RQ3_M3_KICK 20
#define RQ3_M4_KICK 90
#define RQ3_MP5_KICK 90
#define RQ3_HANDCANNON_KICK 40
#define RQ3_SNIPER_KICK 200 // but it seems to get multiplied by zero in the source
#define RQ3_AKIMBO_KICK 90
#define RQ3_KNIFE_KICK 0
#define RQ3_THROW_KICK 50
#define RQ3_GRENADE_KICK 0 // Elder: assumed
//Elder: weaponTime constants (delay in milliseconds)
//Kinda "derived" from the AQ2 source
//Recall that Q2 animations run at 10Hz and the fire
//rate is derived from the number of animation frames
#define RQ3_PISTOL_DELAY 400
#define RQ3_M3_DELAY 900
#define RQ3_M4_DELAY 100
#define RQ3_MP5_DELAY 100
#define RQ3_HANDCANNON_DELAY 1200
#define RQ3_SSG3000_DELAY 1400
#define RQ3_SSG3000_BOLT_DELAY 1300// Elder: delay before zooming back in
#define RQ3_AKIMBO_DELAY 500 // Elder: two delays: one for the total delay
#define RQ3_AKIMBO_DELAY2 200 // one for the time to start the second shot
#define RQ3_KNIFE_DELAY 800
#define RQ3_THROW_DELAY 800
#define RQ3_GRENADE_DELAY 750 // Elder: I made this up
//Elder: special for grenade: speeds depending on distance select
#define GRENADE_SHORT_SPEED 400
#define GRENADE_MEDIUM_SPEED 720
#define GRENADE_LONG_SPEED 920
//Elder: knife throw speed - from the AQ2 source
#define THROW_SPEED 1200
//Elder: special flag needed in both games
#define FL_THROWN_KNIFE 0x00040000 // Elder: thrown knife special case
@ -314,13 +357,22 @@ typedef enum {
STAT_JUMPTIME, //Blaze RE: Double jump
STAT_UNIQUEWEAPONS,
STAT_FALLDAMAGE,
STAT_BANDAGE, //Elder: holds bandage need
// STAT_BANDAGE, //Elder: holds bandage need - moved to STAT_RQ3
STAT_RQ3, //Blaze: Will hold a few flags for bandage, etc info
// STAT_KNIFE, //Elder: knife throwing -- wasteful? then later rename STAT_RQ3 or something and use bits
} statIndex_t;
//STAT_RQ3 stat info
#define RQ3_LEGDAMAGE 1 //If this bit is set, the player has leg damage
//Elder: bandage states to pass to cgame - should remove STAT_BANDAGE
//and integrate with STAT_RQ3
#define RQ3_BANDAGE_NEED 2
#define RQ3_BANDAGE_WORK 4
//Elder: zoom stat - 1x = 0, 2x = zoom low, 4x = zoom_med, 6x = zoom_low + zoom_med
#define RQ3_ZOOM_LOW 8
#define RQ3_ZOOM_MED 16
// player_state->persistant[] indexes
// these fields are the only part of player_state that isn't

View File

@ -590,7 +590,9 @@ void ClientTimerActions( gentity_t *ent, int msec ) {
ent->client->bleeding = 0;
ent->client->bleedtick = 0;
//Elder: added
ent->client->isBandaging = qfalse;
//ent->client->isBandaging = qfalse;
//Elder: remove bandage work
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_BANDAGE_WORK;
//Elder: moved from somewhere - err, g_cmds.c I think
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_LEGDAMAGE;
@ -883,7 +885,8 @@ void ThrowWeapon( gentity_t *ent )
return;
}
//Elder: Bandaging case
else if (client->isBandaging) {
//else if (client->isBandaging) {
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;
}
@ -1177,8 +1180,52 @@ void ClientThink_real( gentity_t *ent ) {
// touch other objects
ClientImpacts( ent, &pm );
//Elder: someone added
if ( bJumping ) JumpKick( ent );
//Elder: added for akimbos and 3rb and sniper zoom
switch( ent->client->ps.weapon ) {
case WP_AKIMBO:
if ( ent->client->weaponfireNextTime != 0 &&
level.time >= ent->client->weaponfireNextTime) {
FireWeapon( ent );
}
break;
case WP_SSG3000:
if ( ent->client->weaponfireNextTime != 0 &&
level.time >= ent->client->weaponfireNextTime) {
//Elder: restore last zoom and clear the variable
ent->client->ps.stats[STAT_RQ3] |= ent->client->lastzoom;
ent->client->lastzoom = 0;
ent->client->weaponfireNextTime = 0;
}
else if (level.time < ent->client->weaponfireNextTime) {
//Elder: stay in 1x until bolt is ready
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_LOW;
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_MED;
}
break;
//case WP_MP5:
case WP_M4:
/*
if (ent->client->weaponfireNextTime != 0 &&
level.time >= ent->client->weaponfireNextTime) {
//Burst three shots and subtract ammo accordingly
FireWeapon(ent);
ent->client->ps.ammo[WP_M4]--;
}*/
break;
default:
break;
}
//if ( ent->client->ps.weapon == WP_AKIMBO &&
//ent->client->weaponfireNextTime != 0 &&
//level.time >= ent->client->weaponfireNextTime) {
//FireWeapon( ent );
//}
// save results of triggers and client events
if (ent->client->ps.eventSequence != oldEventSequence) {
ent->eventTime = level.time;
@ -1376,15 +1423,15 @@ void ClientEndFrame( gentity_t *ent ) {
// End Duffman
ent->client->ps.stats[STAT_HEALTH] = ent->health; // FIXME: get rid of ent->health...
//Elder: bleeding
//TODO: add in when you get leg damage
//Elder: bleeding notification
//ent->client->ps.stats[STAT_RQ3] &= RQ3_LEGDAMAGE;
if (ent->client->bleeding ||
(ent->client->ps.stats[STAT_RQ3] & RQ3_LEGDAMAGE) == RQ3_LEGDAMAGE) {
ent->client->ps.stats[STAT_BANDAGE] = 1;
ent->client->ps.stats[STAT_RQ3] |= RQ3_BANDAGE_NEED;
}
else {
ent->client->ps.stats[STAT_BANDAGE] = 0;
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_BANDAGE_NEED;
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_BANDAGE_WORK;
}
G_SetClientSound (ent);

View File

@ -1240,14 +1240,21 @@ void ClientSpawn(gentity_t *ent) {
client->latched_buttons = 0;
// Hawkins reset zoomed flag
client->zoomed=0;
//Elder: using new stat - it's cleared anyways below
//client->zoomed=0;
//Elder: knife reset/initialize
//Elder: removed - set in ClientBegin
//client->ps.persistant[PERS_WEAPONMODES] &= !RQ3_KNIFEMODE;
//Elder: reset isBandaging flag
client->isBandaging = qfalse;
//client->isBandaging = qfalse;
//Elder: reset all RQ3 non-persistent stats
ent->client->ps.stats[STAT_RQ3] = 0;
//Elder: set weaponfireNextTime amount
client->weaponfireNextTime = 0;
// set default animations
client->ps.torsoAnim = TORSO_STAND;

View File

@ -1595,21 +1595,29 @@ void Cmd_Stats_f( gentity_t *ent ) {
void Cmd_Bandage (gentity_t *ent)
{
// Zoom out when bandaging.
if( ent->client->zoomed ){
ent->client->zoomed = 0;
}
//if( ent->client->zoomed ){
//ent->client->zoomed = 0;
//}
//Elder: can't use events
//G_AddEvent(ent,EV_ZOOM,0);
//}
//Elder: added so you can't "rebandage"
if (ent->client->isBandaging == qtrue) {
if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK) {
//if (ent->client->isBandaging == qtrue) {
trap_SendServerCommand( ent-g_entities, va("print \"You are already bandaging!\n\""));
return;
}
if (ent->client->bleeding || (ent->client->ps.stats[STAT_RQ3] & RQ3_LEGDAMAGE) == RQ3_LEGDAMAGE)
//if (ent->client->bleeding || (ent->client->ps.stats[STAT_RQ3] & RQ3_LEGDAMAGE) == RQ3_LEGDAMAGE)
if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_BANDAGE_NEED) == RQ3_BANDAGE_NEED ||
(ent->client->ps.stats[STAT_RQ3] & RQ3_LEGDAMAGE) == RQ3_LEGDAMAGE)
{
//Elder: remove zoom bits
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_LOW;
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_MED;
ent->client->ps.weaponstate = WEAPON_DROPPING;
ent->client->ps.torsoAnim = ( ( ent->client->ps.torsoAnim & ANIM_TOGGLEBIT )
^ ANIM_TOGGLEBIT ) | TORSO_DROP;
@ -1617,7 +1625,8 @@ void Cmd_Bandage (gentity_t *ent)
ent->client->ps.weaponTime += 6000;
ent->client->bleedtick = 4;
//Elder: added
ent->client->isBandaging = qtrue;
//ent->client->isBandaging = qtrue;
ent->client->ps.stats[STAT_RQ3] |= RQ3_BANDAGE_WORK;
//Elder: moved to g_active where it will be unset after 2 bleedticks
//ent->client->ps.stats[STAT_RQ3] &= !RQ3_LEGDAMAGE;
}
@ -1643,8 +1652,9 @@ void Cmd_Reload( gentity_t *ent ) {
int ammotoadd;
int delay;
//Elder: added
if (ent->client->isBandaging) {
//Elder: added for redundant check but shouldn't need to come here - handled in cgame
//if (ent->client->isBandaging == qtrue) {
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;
}
@ -1662,9 +1672,12 @@ void Cmd_Reload( gentity_t *ent ) {
// Hawkins: Zoom out when reloading.
//Elder: shouldn't need to know about it
// To Do: Must remember to zoom back in
if( ent->client->zoomed ){
ent->client->zoomed=0;
}
//if( ent->client->zoomed ){
//ent->client->zoomed=0;
//}
//Elder: remove zoom bits
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_LOW;
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_MED;
//Elder: can't use events
//G_AddEvent(ent,EV_ZOOM,0);
@ -1689,7 +1702,7 @@ void Cmd_Reload( gentity_t *ent ) {
break;
//Elder: was missing?
case WP_M4:
delay = 2500;
delay = 2000;
if (ent->client->ps.ammo[weapon] >= RQ3_M4_AMMO)
{
trap_SendServerCommand( ent-g_entities, va("print \"No need to reload.\n\""));
@ -1876,17 +1889,50 @@ void Cmd_Weapon(gentity_t *ent)
//Elder: debug code
//G_Printf("PERS_WEAPONMODES: %d\n", ent->client->ps.persistant[PERS_WEAPONMODES]);
//Elder: added since cgame doesn't actually know if its bandaging
//if (ent->client->isBandaging == qtrue) {
if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK) {
trap_SendServerCommand( ent-g_entities, va("print \"You'll get to your weapon when you are finished bandaging!\n\""));
return;
}
//Elder: added brackets, and-ops and not-ops instead of logical ops
switch(ent->s.weapon){
case WP_SSG3000:
// zoom is done by client. zoom 3 levels, then zoom out
//Elder: This is just for the server to track when calcing the spread
/*
if (ent->client->zoomed == 3) {
ent->client->zoomed = 0;
}
else {
ent->client->zoomed++;
}
*/
if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_ZOOM_LOW) == RQ3_ZOOM_LOW &&
(ent->client->ps.stats[STAT_RQ3] & RQ3_ZOOM_MED) == RQ3_ZOOM_MED ) {
//Elder: zoom 1x
//G_Printf("Server: 1x\n");
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_LOW;
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_MED;
}
else if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_ZOOM_MED) == RQ3_ZOOM_MED) {
//Elder: zoom 6x
//G_Printf("Server: 6x\n");
ent->client->ps.stats[STAT_RQ3] |= RQ3_ZOOM_LOW;
}
else if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_ZOOM_LOW) == RQ3_ZOOM_LOW) {
//Elder: zoom 4x
//G_Printf("Server: 4x\n");
ent->client->ps.stats[STAT_RQ3] |= RQ3_ZOOM_MED;
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_LOW;
}
else {
//Elder: zoom 2x
//G_Printf("Server: 2x\n");
ent->client->ps.stats[STAT_RQ3] |= RQ3_ZOOM_LOW;
}
//Elder: don't print - will broadcast to server
//G_Printf("zoomlevel = %d\n",ent->client->zoomed);
@ -2000,7 +2046,18 @@ void Cmd_Weapon(gentity_t *ent)
// Hawkins make sure spread comes back
void Cmd_Unzoom(gentity_t *ent){
//G_Printf("Got to Cmd_Unzoom\n");
ent->client->zoomed = 0;
//Elder: added
//if (ent->client->isBandaging == qtrue) {
if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK) {
trap_SendServerCommand( ent-g_entities, va("print \"You'll get to your weapon when you are finished bandaging!\n\""));
return;
}
else {
//Elder: remove zoom bits
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_LOW;
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_MED;
//ent->client->zoomed = 0;
}
}
@ -2010,10 +2067,22 @@ Cmd_Drop_f XRAY FMJ
=================
*/
void Cmd_Drop_f( gentity_t *ent ) {
ent->client->zoomed=0;
//Elder: added
//if (ent->client->isBandaging == qtrue) {
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: remove zoom bits
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_LOW;
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_MED;
//ent->client->zoomed=0;
//G_AddEvent(ent,EV_ZOOM,0);
ThrowWeapon( ent );
}
}
/*

View File

@ -101,45 +101,57 @@ void TossClientItems( gentity_t *self ) {
//BTW, that means no cheating to get all weapons or it'll spawn mad!!
weaponInventory = self->client->ps.stats[STAT_WEAPONS];
//Elder: throw items in a "circle" starting at a random angle
i = level.time;
angle = Q_random(&i) * 30;
//Elder: added hadUniqueWeapons check - returns to qfalse if died with the gun
//as opposed to dropping it, then died
if ( (weaponInventory & (1 << WP_M3) ) == (1 << WP_M3) ) {
item = BG_FindItemForWeapon( WP_M3 );
Drop_Item( self, item, 0);
Drop_Item( self, item, angle);
self->client->hadUniqueWeapon[ WP_M3 ] = qfalse;
angle += 30;
}
if ( (weaponInventory & (1 << WP_M4) ) == (1 << WP_M4) ) {
item = BG_FindItemForWeapon( WP_M4 );
Drop_Item( self, item, 0);
Drop_Item( self, item, angle);
self->client->hadUniqueWeapon[ WP_M4 ] = qfalse;
angle += 30;
}
if ( (weaponInventory & (1 << WP_MP5) ) == (1 << WP_MP5) ) {
item = BG_FindItemForWeapon( WP_MP5 );
Drop_Item( self, item, 0);
Drop_Item( self, item, angle);
self->client->hadUniqueWeapon[ WP_MP5 ] = qfalse;
angle += 30;
}
if ( (weaponInventory & (1 << WP_HANDCANNON) ) == (1 << WP_HANDCANNON) ) {
item = BG_FindItemForWeapon( WP_HANDCANNON );
Drop_Item( self, item, 0);
Drop_Item( self, item, angle);
self->client->hadUniqueWeapon[ WP_HANDCANNON ] = qfalse;
angle += 30;
}
if ( (weaponInventory & (1 << WP_SSG3000) ) == (1 << WP_SSG3000) ) {
item = BG_FindItemForWeapon( WP_SSG3000 );
Drop_Item( self, item, 0);
Drop_Item( self, item, angle);
self->client->hadUniqueWeapon[ WP_SSG3000 ] = qfalse;
angle += 30;
}
//Elder: Always drop the pistol
item = BG_FindItemForWeapon( WP_PISTOL );
Drop_Item (self, item, 0);
Drop_Item (self, item, angle);
angle += 30;
//Elder: drop a knife if player has at least one
if ( self->client->ps.ammo[ WP_KNIFE ] > 0) {
item = BG_FindItemForWeapon( WP_KNIFE );
Drop_Item (self, item, 0);
Drop_Item (self, item, angle);
}
// drop all the powerups if not in teamplay
@ -500,12 +512,17 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
if ( self->client )
{
// Hawkins put spread back and zoom out
self->client->zoomed = 0;
//Elder: remove zoom bits
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_LOW;
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_MED;
//self->client->zoomed = 0;
self->client->bleeding = 0;
//targ->client->bleedcount = 0;
self->client->bleed_remain = 0;
//Elder: added;
self->client->isBandaging = qfalse;
//self->client->isBandaging = qfalse;
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_BANDAGE_WORK;
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_BANDAGE_NEED;
}
if ( self->client->ps.pm_type == PM_DEAD ) {
return;

View File

@ -281,7 +281,6 @@ int Pickup_Weapon (gentity_t *ent, gentity_t *other) {
quantity = 0; // None for you, sir!
} else {
if ( ent->count ) {
//Elder: place to put gun's chamber ammo?
quantity = ent->count;
} else {
quantity = ent->item->quantity;
@ -299,7 +298,8 @@ int Pickup_Weapon (gentity_t *ent, gentity_t *other) {
} */
}
// add the weapon
// add the weapon if not knife or pistol
if (ent->item->giTag != WP_KNIFE || ent->item->giTag != WP_PISTOL)
other->client->ps.stats[STAT_WEAPONS] |= ( 1 << ent->item->giTag );
// Begin Duffman - Adds a clip for each weapon picked up, will want to edit this later
@ -307,10 +307,10 @@ int Pickup_Weapon (gentity_t *ent, gentity_t *other) {
switch (ent->item->giTag)
{
case WP_KNIFE:
if (other->client->ps.ammo[ent->item->giTag] < RQ3_KNIFE_MAXCLIP)
if (other->client->ps.ammo[WP_KNIFE] < RQ3_KNIFE_MAXCLIP)
{
//G_Printf("(%d)\n",other->client->ps.ammo[ent->item->giTag]);
ammotoadd=other->client->ps.ammo[ent->item->giTag]+1;
ammotoadd = other->client->ps.ammo[WP_KNIFE] + 1;
}
else
{
@ -384,14 +384,19 @@ int Pickup_Weapon (gentity_t *ent, gentity_t *other) {
break;
default:
//Blaze: Should never hit here
G_Printf("Pickup_Weapon given bad giTag: %d\n", ent->item->giTag);
ammotoadd=30;
G_Printf("Pickup_Weapon: Given bad giTag: %d\n", ent->item->giTag);
ammotoadd=0;
break;
}
//Elder: conditional added to "restore" weapons
if ( other->client->hadUniqueWeapon[ent->item->giTag] == qfalse ||
!((ent->flags & FL_THROWN_ITEM) == FL_THROWN_ITEM) ) {
other->client->ps.ammo[ent->item->giTag]= ammotoadd;
//Elder: add extra handcannon clips if it's "fresh"
if (ent->item->giTag == WP_HANDCANNON) {
other->client->numClips[ WP_HANDCANNON ] += 5;
other->client->numClips[ WP_M3 ] += 5;
}
}
// End Duffman
@ -589,7 +594,7 @@ void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) {
//Akimbos: shouldn't pick them up b/c they shouldn't be dropped
//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) ) &&
if ( ( (other->client->ps.stats[STAT_WEAPONS] & (1 << WP_KNIFE) ) == (1 << WP_KNIFE) ) &&
(other->client->ps.ammo[ent->item->giTag] >= RQ3_KNIFE_MAXCLIP) )
return;
break;
@ -600,10 +605,11 @@ void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) {
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->ps.stats[ent->item->giTag] >= RQ3_PISTOL_MAXCLIP)
if ( ( (other->client->ps.stats[STAT_WEAPONS] & (1 << WP_AKIMBO) ) == (1 << WP_AKIMBO) ) &&
other->client->numClips[WP_PISTOL] >= RQ3_PISTOL_MAXCLIP ) {
//leave if we have max clips and akimbos
return;
}
break;
case WP_M3:
case WP_HANDCANNON:
@ -682,14 +688,18 @@ void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) {
*/
respawn = Pickup_Weapon(ent, other);
respawn = -1; //Dont respawn weapons
//Elder: added pistol condition
if (ent->item->giTag == WP_GRENADE || ent->item->giTag == WP_PISTOL)
{
//Elder: added pistol and knife condition
if (ent->item->giTag == WP_GRENADE || ent->item->giTag == WP_PISTOL ||
ent->item->giTag == WP_KNIFE) {
// G_Printf("Grenade Picked up (%d)\n",respawn);
respawn = 30;
}
else {
//Elder: moved here
respawn = -1; //Dont respawn weapons
}
// predict = qfalse;
break;
@ -912,7 +922,7 @@ gentity_t *LaunchItem( gitem_t *item, vec3_t origin, vec3_t velocity, int xr_fla
if( xr_flags & FL_THROWN_ITEM) {
dropped->clipmask = MASK_SHOT; // XRAY FMJ
dropped->s.pos.trTime = level.time - 50; // move a bit on the very first frame
VectorScale( velocity, 400, dropped->s.pos.trDelta ); // 700 500
VectorScale( velocity, 200, dropped->s.pos.trDelta ); // 700 500 400
SnapVector( dropped->s.pos.trDelta ); // save net bandwidth
dropped->physicsBounce= 0;
}
@ -929,22 +939,33 @@ dropWeapon XRAY FMJ
*/
gentity_t *dropWeapon( gentity_t *ent, gitem_t *item, float angle, int xr_flags ) { // XRAY FMJ
vec3_t velocity;
vec3_t angles;
vec3_t origin;
VectorCopy( ent->s.pos.trBase, origin );
VectorCopy( ent->s.apos.trBase, angles );
angles[YAW] += angle;
angles[PITCH] = 0; // always forward
AngleVectors( angles, velocity, NULL, NULL);
//VectorScale( velocity, 150, velocity);
// set aiming directions
AngleVectors (ent->client->ps.viewangles, velocity, NULL, NULL);
//AngleVectors (ent->client->ps.viewangles, velocity, NULL, NULL);
origin[2] += ent->client->ps.viewheight;
VectorMA( origin, 34, velocity, origin ); // 14
VectorMA( origin, 10, velocity, origin ); // 14 34
// snap to integer coordinates for more efficient network bandwidth usage
SnapVector( origin);
// less vertical velocity
velocity[2] += 0.2f;
//velocity[2] += 0.2f;
//velocity[2] = 20;
//G_Printf("Velocity: %s\n", vtos(velocity));
VectorNormalize( velocity );
VectorScale( velocity, 5, velocity);
return LaunchItem( item, origin, velocity, xr_flags );
//return LaunchItem( item, ent->s.pos.trBase, velocity, xr_flags );
}
/*

View File

@ -65,7 +65,7 @@ typedef enum {
#define RQ3_RESPAWNTIME_DEFAULT 60000 // Elder: time for weapons to respawn - up to 60s
#define SP_AUTOOPEN 128 // Elder: revert to Q3 behaviour
#define SP_NODOORTOGGLE 256 // Elder: added to disable mover toggling
#define SP_DOORTOGGLE 256 // Elder: added to enable mover toggling
//============================================================================
@ -181,6 +181,7 @@ struct gentity_s {
gitem_t *item; // for bonus items
float distance; // VALKYRIE: for rotating door
};
@ -339,7 +340,7 @@ struct gclient_s {
int bleedtick; //Blaze: Holds # of seconds till bleeding stops.
//Elder: server only needs to know for sniper spread - ARGH
int zoomed; // Hawkins (SSG zoom)
// int zoomed; // Hawkins (SSG zoom)
//qboolean semi; // hawkins (semiauto mode for m4, mp5, pistol)
int shots; //Blaze: Number of shots fired so far with this weapon
@ -352,13 +353,17 @@ struct gclient_s {
int grenRange; // range to throw grenade (short/medium/long)
int throwKnife; // knife to throwing
*/
qboolean isBandaging; //Elder: player in the process of bandaging
//qboolean isBandaging; //Elder: player in the process of bandaging
// end Homer
//Elder: prep for "ammo" in last gun
//Only the server needs to know this
qboolean hadUniqueWeapon[MAX_WEAPONS];
//Elder: added for 3rb and akimbos
int weaponfireNextTime; //for akimbos and burst modes
int lastzoom; // Elder: save last zoom state when firing
#ifdef MISSIONPACK
gentity_t *persistantPowerup;
int portalID;

View File

@ -662,6 +662,7 @@ fire_grenade
*/
gentity_t *fire_grenade (gentity_t *self, vec3_t start, vec3_t dir) {
gentity_t *bolt;
int speed;
VectorNormalize (dir);
@ -675,9 +676,9 @@ gentity_t *fire_grenade (gentity_t *self, vec3_t start, vec3_t dir) {
bolt->s.eFlags = EF_BOUNCE_HALF;
bolt->r.ownerNum = self->s.number;
bolt->parent = self;
bolt->damage = 100;
bolt->splashDamage = 340;//Blaze: Reaction Grenade Damage
bolt->splashRadius = 200;//Blaze: changed from 150 was 170, but I uped it some more
bolt->damage = GRENADE_DAMAGE; //probably only used on a direct hit
bolt->splashDamage = GRENADE_SPLASH_DAMAGE; //Blaze: Reaction Grenade Damage
bolt->splashRadius = GRENADE_SPLASH_RADIUS; //Blaze: changed from 150 was 170, but I uped it some more
bolt->methodOfDeath = MOD_GRENADE;
bolt->splashMethodOfDeath = MOD_GRENADE_SPLASH;
bolt->clipmask = MASK_SHOT;
@ -686,7 +687,30 @@ gentity_t *fire_grenade (gentity_t *self, vec3_t start, vec3_t dir) {
bolt->s.pos.trType = TR_GRAVITY;
bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit on the very first frame
VectorCopy( start, bolt->s.pos.trBase );
VectorScale( dir, 700, bolt->s.pos.trDelta );
//Elder: grenade toggle distances/speeds
if ( self->client) {
if ( (self->client->ps.persistant[PERS_WEAPONMODES] & RQ3_GRENSHORT) == RQ3_GRENSHORT &&
(self->client->ps.persistant[PERS_WEAPONMODES] & RQ3_GRENMED) == RQ3_GRENMED) {
//Long range throw
speed = GRENADE_LONG_SPEED;
}
else if ( (self->client->ps.persistant[PERS_WEAPONMODES] & RQ3_GRENSHORT) == RQ3_GRENSHORT) {
//Short range throw
speed = GRENADE_SHORT_SPEED;
}
else if ( (self->client->ps.persistant[PERS_WEAPONMODES] & RQ3_GRENMED) == RQ3_GRENMED) {
//Medium range throw
speed = GRENADE_MEDIUM_SPEED;
}
else {
//Elder: shouldn't be here
G_Printf("fire_grenade: Did not receive a grenade parm\n");
speed = GRENADE_MEDIUM_SPEED;
}
}
VectorScale( dir, speed, bolt->s.pos.trDelta );
SnapVector( bolt->s.pos.trDelta ); // save net bandwidth
VectorCopy (start, bolt->r.currentOrigin);
@ -720,7 +744,7 @@ gentity_t *fire_knife (gentity_t *self, vec3_t start, vec3_t dir)
bolt->s.pos.trType = TR_GRAVITY;
bolt->s.pos.trTime = level.time - MISSILE_PRESTEP_TIME; // move a bit on the very first frame
VectorCopy( start, bolt->s.pos.trBase );
VectorScale( dir, 1100, bolt->s.pos.trDelta );
VectorScale( dir, THROW_SPEED, bolt->s.pos.trDelta );
SnapVector( bolt->s.pos.trDelta ); // save net bandwidth
VectorCopy (start, bolt->r.currentOrigin);

View File

@ -602,13 +602,16 @@ void Reached_BinaryMover( gentity_t *ent ) {
}
//Elder: added toggle bit
if ( (ent->spawnflags & SP_NODOORTOGGLE) == SP_NODOORTOGGLE ) {
//Also added "touch" and "takedamage" check so we are only abusing doors
if ( (ent->spawnflags & SP_DOORTOGGLE) == SP_DOORTOGGLE ) { //||
//ent->touch || (ent->takedamage == qtrue) ) {
G_Printf("Sliding Toggle Door used\n");
}
else {
// return to pos1 after a delay
ent->think = ReturnToPos1;
ent->nextthink = level.time + ent->wait;
}
else {
//G_Printf("Sliding Toggle Door used\n");
;
}
// fire targets
@ -641,14 +644,17 @@ void Reached_BinaryMover( gentity_t *ent ) {
}
//Elder: added toggle bit
if ( (ent->spawnflags & SP_NODOORTOGGLE) == SP_NODOORTOGGLE ) {
//Also added "touch" and "takedamage" check so we are only abusing doors
//if ( ( (ent->spawnflags & SP_NODOORTOGGLE) == SP_NODOORTOGGLE ) ||
if ( (ent->spawnflags & SP_DOORTOGGLE) == SP_DOORTOGGLE ) { //||
//ent->touch || (ent->takedamage == qtrue) ) {
G_Printf("Rotating Toggle Door used\n");
}
else {
// return to apos1 after a delay
ent->think = ReturnToApos1;
ent->nextthink = level.time + ent->wait;
}
else {
//G_Printf("Rotating Toggle Door used\n");
}
// fire targets
if ( !ent->activator ) {
@ -713,17 +719,20 @@ void Use_BinaryMover( gentity_t *ent, gentity_t *other, gentity_t *activator ) {
// if all the way up, just delay before coming down
if ( ent->moverState == MOVER_POS2 ) {
if ( (ent->spawnflags & SP_NODOORTOGGLE) == SP_NODOORTOGGLE) {
//Elder: normal Q3 door
ent->nextthink = level.time + ent->wait;
}
else {
//Elder: added two additional checks
if ( (ent->spawnflags & SP_DOORTOGGLE) == SP_DOORTOGGLE ) {
//if ( ( (ent->spawnflags & SP_NODOORTOGGLE) == SP_NODOORTOGGLE ) ||
//ent->touch || ent->takedamage) {
//Elder: Move back "immediately"
MatchTeam( ent, MOVER_2TO1, level.time + 50);
if ( ent->sound1to2 ) {
G_AddEvent( ent, EV_GENERAL_SOUND, ent->sound1to2 );
}
}
else {
//Elder: normal Q3 door
ent->nextthink = level.time + ent->wait;
}
return;
}
@ -791,17 +800,19 @@ void Use_BinaryMover( gentity_t *ent, gentity_t *other, gentity_t *activator ) {
// if all the way up, just delay before coming down
if ( ent->moverState == ROTATOR_POS2 ) {
if ( (ent->spawnflags & SP_NODOORTOGGLE) == SP_NODOORTOGGLE) {
//Elder: normal rotating door
ent->nextthink = level.time + ent->wait;
}
else {
//if ( ( (ent->spawnflags & SP_NODOORTOGGLE) == SP_NODOORTOGGLE ) ||
//ent->touch || ent->takedamage) {
if ( (ent->spawnflags & SP_DOORTOGGLE) == SP_DOORTOGGLE ) {
//Elder: Move back "immediately"
MatchTeam( ent, ROTATOR_2TO1, level.time + 50);
if ( ent->sound1to2 ) {
G_AddEvent( ent, EV_GENERAL_SOUND, ent->sound1to2 );
}
}
else {
//Elder: normal rotating door
ent->nextthink = level.time + ent->wait;
}
return;
}
@ -1126,7 +1137,7 @@ NOMONSTER monsters will not trigger this door
//Elder: new one from GTKRadiant's entity.def plus Reaction stuff
/*QUAKED func_door (0 .5 .8) ? START_OPEN x CRUSHER x x x x AUTOOPEN NOTOGGLE
/*QUAKED func_door (0 .5 .8) ? START_OPEN x CRUSHER x x x x AUTOOPEN TOGGLE
Normal sliding door entity. By default, the door will activate when player walks close to it or when damage is inflicted to it.
-------- KEYS --------
angle : determines the opening direction of door (up = -1, down = -2).
@ -1149,9 +1160,9 @@ soundmove : path to sound file to play when door is moving
-------- SPAWNFLAGS --------
START_OPEN : the door will spawn in the open state and operate in reverse.
CRUSHER : door will not reverse direction when blocked and will keep damaging player until he dies or gets out of the way.
NOTOGGLE : door will close like traditional Q3 doors using the wait period
TOGGLE : door requires an opendoor toggle to work
AUTOOPEN : door will open like traditional Q3 doors (like a motion sensor)
Setting NOTOGGLE and AUTOOPEN will make the doors act like traditional Q3A doors
Setting AUTOOPEN will make the doors act like traditional Q3A doors
-------- NOTES --------
Unlike in Quake 2, doors that touch are NOT automatically teamed. If you want doors to operate together, you have to team them manually by assigning the same team name to all of them. Setting the origin key is simply an alternate method to using an origin brush. When using the model2 key, the origin point of the model will correspond to the origin point defined by either the origin brush or the origin coordinate value.*/
void SP_func_door (gentity_t *ent) {
@ -1176,7 +1187,7 @@ void SP_func_door (gentity_t *ent) {
G_Printf("func_door Starting Open\n");
if ( (ent->spawnflags & 4) == 4)
G_Printf("func_door CRUSHER\n");
if ( (ent->spawnflags & SP_NODOORTOGGLE) == SP_NODOORTOGGLE)
if ( (ent->spawnflags & SP_DOORTOGGLE) == SP_DOORTOGGLE)
G_Printf("func_door is a Toggle\n");
// default speed of 400

View File

@ -947,6 +947,17 @@ void Weapon_M4_Fire(gentity_t *ent)
}
Bullet_Fire( ent, RQ3Spread(ent, M4_SPREAD), M4_DAMAGE, MOD_M4);
/*
if ( (ent->client->ps.persistant[PERS_WEAPONMODES] & RQ3_M4MODE) == RQ3_M4MODE) {
//Elder: burst three shots
if (ent->client->weaponfireNextTime > 0 && ent->client->ps.stats[STAT_BURST] > 2) {
ent->client->weaponfireNextTime = 0;
}
else {
ent->client->weaponfireNextTime = level.time + RQ3_M4_DELAY;
}
}*/
}
/*
@ -978,10 +989,26 @@ SSG3000 Attack
*/
void Weapon_SSG3000_Fire(gentity_t *ent)
{
float spread;
//Elder: Don't print - will broadcast to server
//G_Printf("Zoom Level: %d\n", ent->client->zoomed);
//Elder: changed to use RQ3Spread as well
Bullet_Fire( ent, ( ent->client->zoomed? 0:RQ3Spread(ent, SNIPER_SPREAD)), SNIPER_DAMAGE, MOD_SNIPER);
//Elder: using new stat
if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_ZOOM_LOW) == RQ3_ZOOM_LOW ||
(ent->client->ps.stats[STAT_RQ3] & RQ3_ZOOM_MED) == RQ3_ZOOM_MED) {
spread = 0;
}
else {
spread = RQ3Spread(ent, SNIPER_SPREAD);
}
Bullet_Fire( ent, spread, SNIPER_DAMAGE, MOD_SNIPER);
//Elder: bolt action plus save last zoom
ent->client->weaponfireNextTime = level.time + RQ3_SSG3000_BOLT_DELAY;
if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_ZOOM_LOW) == RQ3_ZOOM_LOW)
ent->client->lastzoom |= RQ3_ZOOM_LOW;
if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_ZOOM_MED) == RQ3_ZOOM_MED)
ent->client->lastzoom |= RQ3_ZOOM_MED;
}
@ -1065,8 +1092,14 @@ void Weapon_Akimbo_Fire(gentity_t *ent)
//Blaze: Will need 2 of these
spread = AKIMBO_SPREAD;
Bullet_Fire( ent, RQ3Spread(ent, spread), AKIMBO_DAMAGE, MOD_AKIMBO);
//Elder: should there be a small delay or is that just the sound effect in AQ2?
Bullet_Fire( ent, RQ3Spread(ent, spread), AKIMBO_DAMAGE, MOD_AKIMBO);
//Elder: reset
if (ent->client->weaponfireNextTime > 0)
ent->client->weaponfireNextTime = 0;
else
ent->client->weaponfireNextTime = level.time + RQ3_AKIMBO_DELAY2;
//Bullet_Fire( ent, RQ3Spread(ent, spread), AKIMBO_DAMAGE, MOD_AKIMBO);
}
/*