Sync with VM 0-04-00 release
Fixes a ton of stuff, adds some new goodies
This commit is contained in:
Victor Chow 2001-07-16 01:40:33 +00:00
parent 05b8566b24
commit 732f73a910
11 changed files with 517 additions and 271 deletions

View file

@ -1105,10 +1105,10 @@ Check for hard landings that generate sound events
*/ */
static void PM_CrashLand( void ) { static void PM_CrashLand( void ) {
float delta; float delta;
float dist; //float dist;
float vel, acc; //float vel, acc;
float t; //float t;
float a, b, c, den; //float a, b, c, den;
int damage; int damage;
// decide which landing animation to use // decide which landing animation to use
@ -1190,6 +1190,18 @@ static void PM_CrashLand( void ) {
} }
} }
} }
else if (delta > 20)
{
PM_AddEvent( EV_FALL_SHORT );
//Elder: added? useful?
pm->ps->stats[STAT_FALLDAMAGE] = 0;
}
else
{
PM_AddEvent( PM_FootstepForSurface() );
//Elder: added? useful?
pm->ps->stats[STAT_FALLDAMAGE] = 0;
}
// start footstep cycle over // start footstep cycle over
pm->ps->bobCycle = 0; pm->ps->bobCycle = 0;
@ -1738,6 +1750,13 @@ static void PM_FinishWeaponChange( void ) {
weapon = WP_NONE; weapon = WP_NONE;
} }
//Remove grenade if out of ammo
if (weapon == WP_GRENADE && pm->ps->ammo[WP_GRENADE] == 0)
{
pm->ps->stats[STAT_WEAPONS] &= ~(1 << WP_GRENADE);
weapon = WP_PISTOL;
}
pm->ps->weapon = weapon; pm->ps->weapon = weapon;
pm->ps->weaponstate = WEAPON_RAISING; pm->ps->weaponstate = WEAPON_RAISING;
//pm->ps->weaponTime += 250; //pm->ps->weaponTime += 250;
@ -1873,6 +1892,22 @@ static void PM_Weapon( void ) {
} }
} }
//Elder: drop the primed grenade if bandaging
/*
if ( pm->ps->weapon == WP_GRENADE &&
pm->ps->ammo[WP_GRENADE] > 0 &&
//
//pm->ps->weaponstate == WEAPON_DROPPING &&
(pm->cmd.buttons & 1) &&
(pm->ps->stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK)
{
PM_AddEvent( EV_FIRE_WEAPON );
pm->ps->ammo[WP_GRENADE]--;
if (pm->ps->ammo[WP_GRENADE] == 0)
pm->ps->stats[STAT_WEAPONS] &= ~( 1 << WP_GRENADE);
}*/
if ( pm->ps->weaponTime > 0 ) { if ( pm->ps->weaponTime > 0 ) {
return; return;
} }
@ -2263,8 +2298,9 @@ static void PM_LadderMove( void ) {
for (i=0 ; i<3 ; i++) for (i=0 ; i<3 ; i++)
wishvel[i] = scale * pml.forward[i]*pm->cmd.forwardmove + wishvel[i] = scale * pml.forward[i]*pm->cmd.forwardmove +
scale * pml.right[i]*pm->cmd.rightmove; scale * pml.right[i]*pm->cmd.rightmove;
wishvel[0] /= 2; //Elder: changed from a factor of 2 to 10
wishvel[1] /= 2; wishvel[0] /= 10;
wishvel[1] /= 10;
wishvel[2] += scale * pm->cmd.upmove; wishvel[2] += scale * pm->cmd.upmove;
} }

View file

@ -171,7 +171,7 @@
#define RQ3_AKIMBO_KICK 90 #define RQ3_AKIMBO_KICK 90
#define RQ3_KNIFE_KICK 0 #define RQ3_KNIFE_KICK 0
#define RQ3_THROW_KICK 50 #define RQ3_THROW_KICK 50
#define RQ3_GRENADE_KICK 0 // Elder: assumed #define RQ3_GRENADE_KICK 200 // Elder: assumed
//Elder: weaponTime constants (delay in milliseconds) //Elder: weaponTime constants (delay in milliseconds)
@ -200,16 +200,16 @@
#define RQ3_AKIMBO_RELOAD_DELAY 2500 #define RQ3_AKIMBO_RELOAD_DELAY 2500
#define RQ3_M3_RELOAD_DELAY 1100 #define RQ3_M3_RELOAD_DELAY 1100
#define RQ3_M3_ALLOW_FAST_RELOAD_DELAY 700 // Time into reload to enable fast-reloads #define RQ3_M3_ALLOW_FAST_RELOAD_DELAY 200 // 700 Time into reload to enable fast-reloads
#define RQ3_M3_FAST_RELOAD_DELAY 500 // Fast reload time #define RQ3_M3_FAST_RELOAD_DELAY 500 // Fast reload time
//#define RQ3_M3_START_RELOAD_DELAY 300 // Start index point of fast reload //#define RQ3_M3_START_RELOAD_DELAY 300 // Start index point of fast reload
//#define RQ3_M3_FINISH_RELOAD_DELAY 300 // Amount of time after all fast reloads #define RQ3_M3_FINISH_RELOAD_DELAY 300 // Amount of time after all fast reloads
#define RQ3_SSG3000_RELOAD_DELAY 3100 #define RQ3_SSG3000_RELOAD_DELAY 3100
#define RQ3_SSG3000_ALLOW_FAST_RELOAD_DELAY 2200 // Time into reload to enable fast-reloads #define RQ3_SSG3000_ALLOW_FAST_RELOAD_DELAY 1400 //2200 Time into reload to enable fast-reloads
#define RQ3_SSG3000_FAST_RELOAD_DELAY 600 // Fast reload time #define RQ3_SSG3000_FAST_RELOAD_DELAY 600 // Fast reload time
//#define RQ3_SSG3000_START_RELOAD_DELAY 1700 // Start index point of fast reload //#define RQ3_SSG3000_START_RELOAD_DELAY 1700 // Start index point of fast reload
//#define RQ3_SSG3000_FINISH_RELOAD_DELAY 800 // Amount of time after all fast reloads #define RQ3_SSG3000_FINISH_RELOAD_DELAY 800 // Amount of time after all fast reloads
#define RQ3_KNIFE_RELOAD_DELAY 0 // Elder: shouldn't need #define RQ3_KNIFE_RELOAD_DELAY 0 // Elder: shouldn't need
#define RQ3_GRENADE_RELOAD_DELAY 0 // Elder: shouldn't need #define RQ3_GRENADE_RELOAD_DELAY 0 // Elder: shouldn't need
@ -232,7 +232,7 @@
#define RQ3_M4_SWITCH2_DELAY 500 #define RQ3_M4_SWITCH2_DELAY 500
#define RQ3_MP5_SWITCH2_DELAY 400 #define RQ3_MP5_SWITCH2_DELAY 400
#define RQ3_HANDCANNON_SWITCH2_DELAY 400 #define RQ3_HANDCANNON_SWITCH2_DELAY 400
#define RQ3_SSG3000_SWITCH2_DELAY 900 #define RQ3_SSG3000_SWITCH2_DELAY 150 //900 For some reason it's auto-used with WEAPON_RAISING
#define RQ3_AKIMBO_SWITCH2_DELAY 800 #define RQ3_AKIMBO_SWITCH2_DELAY 800
#define RQ3_KNIFE_SWITCH2_DELAY 700 #define RQ3_KNIFE_SWITCH2_DELAY 700
#define RQ3_THROW_SWITCH2_DELAY 700 #define RQ3_THROW_SWITCH2_DELAY 700

View file

@ -3,164 +3,13 @@
#include "g_local.h" #include "g_local.h"
extern float s_quadFactor; //Elder: got rid of these
extern vec3_t forward, right, up; //extern float s_quadFactor;
extern vec3_t muzzle; //extern vec3_t forward, right, up;
extern void Cmd_OpenDoor( gentity_t * ); //extern vec3_t muzzle;
//extern void Cmd_OpenDoor( gentity_t * );
qboolean DoorKick( trace_t *trIn, gentity_t *ent, vec3_t origin, vec3_t forward ) //Elder: moved kick to g_weapon.c where it belongs
{
gentity_t *traceEnt;
trace_t tr;
traceEnt = &g_entities[ trIn->entityNum ];
if ( Q_stricmp (traceEnt->classname, "func_door_rotating") == 0 )
{
vec3_t d_right, d_forward;
float crossProduct;
vec3_t end;
// Find the hit point and the muzzle point with respect
// to the door's origin, then project down to the XY plane
// and take the cross product
VectorSubtract( trIn->endpos, traceEnt->s.origin, d_right );
VectorSubtract( origin, traceEnt->s.origin, d_forward );
crossProduct = d_forward[0]*d_right[1]-d_right[0]*d_forward[1];
// See if we are on the proper side to do it
if ( ((traceEnt->pos2[1] > traceEnt->pos1[1]) && crossProduct > 0) ||
((traceEnt->pos2[1] < traceEnt->pos1[1]) && crossProduct < 0))
{
Cmd_OpenDoor( ent );
VectorMA( trIn->endpos, 25, forward, end );
trap_Trace (&tr, trIn->endpos, NULL, NULL, end, trIn->entityNum, MASK_SHOT);
if ( !(tr.surfaceFlags & SURF_NOIMPACT) )
{
traceEnt = &g_entities[ tr.entityNum ];
if ( traceEnt->client )
{
*trIn = tr;
}
}
}
return qtrue;
}
else
return qfalse;
}
qboolean JumpKick( gentity_t *ent )
{
trace_t tr;
vec3_t end;
gentity_t *tent;
gentity_t *traceEnt;
int damage;
//Elder: for kick sound
qboolean kickSuccess;
// set aiming directions
AngleVectors (ent->client->ps.viewangles, forward, right, up);
CalcMuzzlePoint ( ent, forward, right, up, muzzle );
VectorMA (muzzle, 32, forward, end);
//VectorCopy( ent->s.origin, muzzle );
//muzzle[2] += 32;
// the muzzle really isn't the right point to test the jumpkick from
trap_Trace (&tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT);
//trap_Trace (&tr, ent->s.origin, ent->r.mins, ent->r.maxs, end, ent->s.number, MASK_SHOT);
//trap_Trace (&tr, ent->s.origin, NULL, NULL, end, ent->s.number, MASK_SHOT);
if ( tr.surfaceFlags & SURF_NOIMPACT ) {
return qfalse;
}
kickSuccess = DoorKick( &tr, ent, muzzle, forward );
traceEnt = &g_entities[ tr.entityNum ];
if ( !traceEnt->takedamage) {
return qfalse;
}
if (ent->client->ps.powerups[PW_QUAD] ) {
G_AddEvent( ent, EV_POWERUP_QUAD, 0 );
s_quadFactor = g_quadfactor.value;
} else {
s_quadFactor = 1;
}
damage = 20;
//Elder: can't hit if crouching but can still hit "dead" bodies :)
if (traceEnt->client && traceEnt->health > 0 && traceEnt->r.maxs[2] < 20)
{
return qfalse;
}
else {
G_Damage( traceEnt, ent, ent, forward, tr.endpos,
damage, DAMAGE_NO_LOCATIONAL, MOD_KICK );
}
// send blood impact
if ( traceEnt->takedamage && traceEnt->client ) {
tent = G_TempEntity( tr.endpos, EV_MISSILE_HIT );
tent->s.otherEntityNum = traceEnt->s.number;
tent->s.eventParm = DirToByte( tr.plane.normal );
tent->s.weapon = ent->s.weapon;
kickSuccess = qtrue;
}
if (traceEnt->client && traceEnt->client->ps.stats[STAT_UNIQUEWEAPONS] > 0)
{
//Elder: toss a unique weapon if kicked
//Todo: Need to make sure to cancel any reload attempts
//Todo: need to send a message to attacker and target about weapon kick
ThrowWeapon(traceEnt);
//trap_SendServerCommand( ent-g_entities, va("print \"You kicked %s's %s from his hands!\n\"", traceEnt->client->pers.netname, (traceEnt->client->ps.weapon)->pickup_name);
//trap_SendServerCommand( targ-g_entities, va("print \"Head Damage.\n\""));
}
//Elder: for the kick
// do our special form of knockback here
/*
VectorMA (self->enemy->absmin, 0.5, self->enemy->size, v);
VectorSubtract (v, point, v);
VectorNormalize (v);
VectorMA (self->enemy->velocity, kick, v, self->enemy->velocity);
if (self->enemy->velocity[2] > 0)
self->enemy->groundentity = NULL;
*/
//Elder: kick knockback for AQ2 -- recall variable kick = 400
if (traceEnt->client)
{
//Elder: for kick knockback
vec3_t size, vTemp;
//Make the "size" vector - hopefully this is right
VectorSubtract(traceEnt->r.maxs, traceEnt->r.mins, size);
G_Printf("Size: %s\n", vtos(size));
VectorMA(traceEnt->r.absmin, 0.5, size, vTemp);
VectorSubtract(vTemp, tr.endpos, vTemp);
VectorNormalize(vTemp);
VectorMA(traceEnt->client->ps.velocity, 400, vTemp, traceEnt->client->ps.velocity);
if (traceEnt->client->ps.velocity[2] > 0)
traceEnt->s.groundEntityNum = ENTITYNUM_NONE;
}
//Elder: Our set of locally called sounds
if (kickSuccess)
G_AddEvent ( ent, EV_RQ3_SOUND, RQ3_SOUND_KICK);
return qtrue;
}
/* /*
=============== ===============
@ -176,6 +25,7 @@ void P_DamageFeedback( gentity_t *player ) {
gclient_t *client; gclient_t *client;
float count, side; float count, side;
vec3_t angles, v; vec3_t angles, v;
vec3_t forward, right, up;
client = player->client; client = player->client;
if ( client->ps.pm_type == PM_DEAD ) { if ( client->ps.pm_type == PM_DEAD ) {
@ -183,8 +33,11 @@ void P_DamageFeedback( gentity_t *player ) {
} }
// total points of damage shot at the player this frame // total points of damage shot at the player this frame
if (client->damage_blood > 0) //if (client->damage_blood > 0)
G_Printf("(%i) Damage_blood: %i\n", player->s.clientNum, client->damage_blood); //G_Printf("(%i) Damage_blood: %i\n", player->s.clientNum, client->damage_blood);
//if (client->damage_knockback > 0)
//G_Printf("(%i) Damage_knockback: %i\n", player->s.clientNum, client->damage_knockback);
count = client->damage_blood + client->damage_armor; count = client->damage_blood + client->damage_armor;
if ( count == 0 ) { if ( count == 0 ) {
@ -213,6 +66,10 @@ void P_DamageFeedback( gentity_t *player ) {
// new RQ3 view-kick code, needs more tweaking (the 50 needs to be replaces with that below calcuation // new RQ3 view-kick code, needs more tweaking (the 50 needs to be replaces with that below calcuation
// from the AQ2 code. // from the AQ2 code.
// set aiming directions
AngleVectors (client->ps.viewangles, forward, right, up);
VectorSubtract(client->damage_from, player->s.origin , v); VectorSubtract(client->damage_from, player->s.origin , v);
VectorNormalize(v); VectorNormalize(v);
@ -692,7 +549,7 @@ void ClientTimerActions( gentity_t *ent, int msec ) {
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_BANDAGE_WORK; ent->client->ps.stats[STAT_RQ3] &= ~RQ3_BANDAGE_WORK;
//Elder: moved from somewhere - err, g_cmds.c I think //Elder: moved from somewhere - err, g_cmds.c I think
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_LEGDAMAGE; ent->client->ps.stats[STAT_RQ3] &= ~RQ3_LEGDAMAGE;
// ent->client->ps.weaponTime += 2500; // ent->client->ps.weaponTime += 2500;
// ent->client->ps.weaponstate = WEAPON_RAISING; // ent->client->ps.weaponstate = WEAPON_RAISING;
// ent->client->ps.torsoAnim = ( ( ent->client->ps.torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | TORSO_RAISE; // ent->client->ps.torsoAnim = ( ( ent->client->ps.torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | TORSO_RAISE;
@ -1139,6 +996,7 @@ void ClientThink_real( gentity_t *ent ) {
client->ps.speed *= 1.3; client->ps.speed *= 1.3;
} }
// Let go of the hook if we aren't firing // Let go of the hook if we aren't firing
//Blaze: No Hook in reaction //Blaze: No Hook in reaction
/* /*
@ -1290,7 +1148,26 @@ void ClientThink_real( gentity_t *ent ) {
FireWeapon( ent ); FireWeapon( ent );
} }
break; break;
case WP_M3:
//Elder: try to do a fast reload if it's queued
if ( ent->client->ps.weaponTime < RQ3_M3_FAST_RELOAD_DELAY &&
ent->client->fastReloads &&
ent->client->reloadAttempts > 0)
{
//G_Printf("(%i) ClientThink: attempting fast-reload...\n", ent->s.clientNum);
Cmd_Reload( ent );
}
break;
case WP_SSG3000: case WP_SSG3000:
//Elder: try to do a fast reload if it's queued
if ( ent->client->ps.weaponTime < RQ3_SSG3000_FAST_RELOAD_DELAY &&
ent->client->fastReloads &&
ent->client->reloadAttempts > 0)
{
//G_Printf("(%i) ClientThink: attempting fast-reload...\n", ent->s.clientNum);
Cmd_Reload( ent );
}
/*
if ( ent->client->weaponfireNextTime != 0 && if ( ent->client->weaponfireNextTime != 0 &&
level.time >= ent->client->weaponfireNextTime) { level.time >= ent->client->weaponfireNextTime) {
//Elder: restore last zoom and clear the variable //Elder: restore last zoom and clear the variable
@ -1302,7 +1179,7 @@ void ClientThink_real( gentity_t *ent ) {
//Elder: stay in 1x until bolt is ready //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_LOW;
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_MED; ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_MED;
} }*/
/* else if (level.time - ent->client->lastReloadTime > ent->client->ps.weaponTime) { /* else if (level.time - ent->client->lastReloadTime > ent->client->ps.weaponTime) {
//Elder: Too buggy at the moment //Elder: Too buggy at the moment
if (level.time - ent->client->lastReloadTime > RQ3_SSG3000_RELOAD_DELAY) if (level.time - ent->client->lastReloadTime > RQ3_SSG3000_RELOAD_DELAY)
@ -1329,13 +1206,6 @@ void ClientThink_real( gentity_t *ent ) {
break; 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 // save results of triggers and client events
if (ent->client->ps.eventSequence != oldEventSequence) { if (ent->client->ps.eventSequence != oldEventSequence) {
ent->eventTime = level.time; ent->eventTime = level.time;
@ -1543,7 +1413,6 @@ void ClientEndFrame( gentity_t *ent ) {
ent->client->ps.stats[STAT_HEALTH] = ent->health; // FIXME: get rid of ent->health... ent->client->ps.stats[STAT_HEALTH] = ent->health; // FIXME: get rid of ent->health...
//Elder: bleeding notification //Elder: bleeding notification
//ent->client->ps.stats[STAT_RQ3] &= RQ3_LEGDAMAGE;
if (ent->client->bleeding || if (ent->client->bleeding ||
(ent->client->ps.stats[STAT_RQ3] & RQ3_LEGDAMAGE) == RQ3_LEGDAMAGE) { (ent->client->ps.stats[STAT_RQ3] & RQ3_LEGDAMAGE) == RQ3_LEGDAMAGE) {
ent->client->ps.stats[STAT_RQ3] |= RQ3_BANDAGE_NEED; ent->client->ps.stats[STAT_RQ3] |= RQ3_BANDAGE_NEED;

View file

@ -1638,20 +1638,35 @@ void Cmd_Bandage (gentity_t *ent)
(ent->client->ps.stats[STAT_RQ3] & RQ3_LEGDAMAGE) == RQ3_LEGDAMAGE) (ent->client->ps.stats[STAT_RQ3] & RQ3_LEGDAMAGE) == RQ3_LEGDAMAGE)
{ {
//Elder: remove zoom bits //Elder: remove zoom bits
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_LOW; Cmd_Unzoom(ent);
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_MED;
//Elder: added
ent->client->ps.stats[STAT_RQ3] |= RQ3_BANDAGE_WORK;
//Elder: drop the primed grenade
//Moved weapon switch to bg_pmove.c
if (ent->client->ps.weapon == WP_GRENADE &&
ent->client->ps.weaponstate == WEAPON_COCKED) {
FireWeapon(ent);
ent->client->ps.ammo[WP_GRENADE]--;
//if (ent->client->ps.ammo[WP_GRENADE] == 0)
//{
//ent->client->ps.stats[STAT_WEAPONS] &= ~(1 << WP_GRENADE);
//ent->client->ps.weapon = WP_PISTOL;
//trap_SendServerCommand( ent-g_entities, "selectpistol" );
//}
}
ent->client->ps.weaponstate = WEAPON_DROPPING; ent->client->ps.weaponstate = WEAPON_DROPPING;
ent->client->ps.torsoAnim = ( ( ent->client->ps.torsoAnim & ANIM_TOGGLEBIT ) ent->client->ps.torsoAnim = ( ( ent->client->ps.torsoAnim & ANIM_TOGGLEBIT )
^ ANIM_TOGGLEBIT ) | TORSO_DROP; ^ ANIM_TOGGLEBIT ) | TORSO_DROP;
ent->client->ps.weaponTime += 6000; ent->client->ps.weaponTime += 6000;
ent->client->bleedtick = 4; ent->client->bleedtick = 4;
//Elder: added to track health to bleed off //Elder: added to track health to bleed off
ent->client->bleedBandageCount = BLEED_BANDAGE; ent->client->bleedBandageCount = BLEED_BANDAGE;
//Elder: added
ent->client->ps.stats[STAT_RQ3] |= RQ3_BANDAGE_WORK;
//Elder: moved to g_active where it will be unset after 2 bleedticks //Elder: moved to g_active where it will be unset after 2 bleedticks
//ent->client->ps.stats[STAT_RQ3] &= !RQ3_LEGDAMAGE; //ent->client->ps.stats[STAT_RQ3] &= !RQ3_LEGDAMAGE;
} }
@ -1675,11 +1690,13 @@ void Cmd_Reload( gentity_t *ent ) {
int weapon; int weapon;
int ammotoadd; int ammotoadd;
int delay; int delay = 0;
//Elder: added for redundant check but shouldn't need to come here - handled in cgame //Elder: added for redundant check but shouldn't need to come here - handled in cgame
//if (ent->client->isBandaging == qtrue) { //if (ent->client->isBandaging == qtrue) {
if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK) { if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK) {
ent->client->fastReloads = 0;
ent->client->reloadAttempts = 0;
trap_SendServerCommand( ent-g_entities, va("print \"You are too busy bandaging...\n\"")); trap_SendServerCommand( ent-g_entities, va("print \"You are too busy bandaging...\n\""));
return; return;
} }
@ -1692,7 +1709,6 @@ void Cmd_Reload( gentity_t *ent ) {
//Elder: changed to new function //Elder: changed to new function
ammotoadd = ClipAmountForReload(weapon); ammotoadd = ClipAmountForReload(weapon);
delay = 0;
/*if (ent->client->ps.ammo[weapon] >= ClipAmountForWeapon(weapon)) /*if (ent->client->ps.ammo[weapon] >= ClipAmountForWeapon(weapon))
{ trap_SendServerCommand( ent-g_entities, va("print \"No need to reload.\n\"")); { trap_SendServerCommand( ent-g_entities, va("print \"No need to reload.\n\""));
return; return;
@ -1747,8 +1763,9 @@ void Cmd_Reload( gentity_t *ent ) {
if (ent->client->ps.ammo[weapon] >= RQ3_M3_AMMO) if (ent->client->ps.ammo[weapon] >= RQ3_M3_AMMO)
{ {
//reset fast reloads //reset fast reloads and attempts
ent->client->fastReloads = 0; ent->client->fastReloads = 0;
ent->client->reloadAttempts = 0;
trap_SendServerCommand( ent-g_entities, va("print \"No need to reload.\n\"")); trap_SendServerCommand( ent-g_entities, va("print \"No need to reload.\n\""));
return; return;
} }
@ -1765,38 +1782,37 @@ void Cmd_Reload( gentity_t *ent ) {
RQ3_M3_RELOAD_DELAY); RQ3_M3_RELOAD_DELAY);
*/ */
//Have we fast reloaded before? //Have we fast reloaded before?
if (ent->client->fastReloads) { if (ent->client->fastReloads)
{
if (level.time - ent->client->lastReloadTime < RQ3_M3_FAST_RELOAD_DELAY) if (level.time - ent->client->lastReloadTime < RQ3_M3_FAST_RELOAD_DELAY)
{ {
//not enough time has passed for a fast reload attempt //not enough time has passed for a fast-reload attempt so ignore it
//so discard the attempt
//G_Printf("Too soon: Discarded fast-reload attempt\n"); //G_Printf("Too soon: Discarded fast-reload attempt\n");
return; return;
} }
else if (level.time - ent->client->lastReloadTime >= RQ3_M3_FAST_RELOAD_DELAY && //else if (level.time - ent->client->lastReloadTime >= RQ3_M3_FAST_RELOAD_DELAY &&
level.time - ent->client->lastReloadTime <= RQ3_M3_RELOAD_DELAY) //level.time - ent->client->lastReloadTime <= RQ3_M3_RELOAD_DELAY)*/
else if (level.time - ent->client->lastReloadTime <= RQ3_M3_RELOAD_DELAY)
{ {
//gotcha //Gotcha!
ent->client->fastReloads = 1; ent->client->fastReloads = 1;
} }
else else
{ {
//Missed the window of opportunity! //Missed the window of opportunity! - Reset fastReloads
//Reset fastReloads
//G_Printf("Missed Window: disabling fast reloads\n"); //G_Printf("Missed Window: disabling fast reloads\n");
ent->client->fastReloads = 0; ent->client->fastReloads = 0;
} }
} }
//Fast-reload virgin //Fast-reload virgin
else if (level.time - ent->client->lastReloadTime >= RQ3_M3_ALLOW_FAST_RELOAD_DELAY && else if (level.time - ent->client->lastReloadTime >= RQ3_M3_ALLOW_FAST_RELOAD_DELAY &&
level.time - ent->client->lastReloadTime <= RQ3_M3_RELOAD_DELAY) level.time - ent->client->lastReloadTime <= RQ3_M3_RELOAD_DELAY)
{ {
ent->client->fastReloads = 1; ent->client->fastReloads = 1;
} }
else else
{ {
//not enough time has passed for a fast reload attempt //not enough time has passed for a fast-reload attempt so ignore it
//so discard the attempt
//G_Printf("Too soon: Discarded fast-reload attempt\n"); //G_Printf("Too soon: Discarded fast-reload attempt\n");
return; return;
} }
@ -1817,7 +1833,14 @@ void Cmd_Reload( gentity_t *ent ) {
ent->client->fastReloads = 0; ent->client->fastReloads = 0;
} }
//Elder: finished a full reload cycle - mark the time and discard the attempt
ent->client->lastReloadTime = level.time; ent->client->lastReloadTime = level.time;
ent->client->reloadAttempts--;
//Finish off if no more reload attempts
if (ent->client->reloadAttempts < 1 && ent->client->fastReloads)
delay += RQ3_M3_FINISH_RELOAD_DELAY;
break; break;
case WP_HANDCANNON: case WP_HANDCANNON:
delay = RQ3_HANDCANNON_RELOAD_DELAY; delay = RQ3_HANDCANNON_RELOAD_DELAY;
@ -1835,8 +1858,9 @@ void Cmd_Reload( gentity_t *ent ) {
if (ent->client->ps.ammo[weapon] >= RQ3_SSG3000_AMMO) if (ent->client->ps.ammo[weapon] >= RQ3_SSG3000_AMMO)
{ {
//reset fast reloads //reset fast reloads and attempts
ent->client->fastReloads = 0; ent->client->fastReloads = 0;
ent->client->reloadAttempts = 0;
trap_SendServerCommand( ent-g_entities, va("print \"No need to reload.\n\"")); trap_SendServerCommand( ent-g_entities, va("print \"No need to reload.\n\""));
return; return;
} }
@ -1853,38 +1877,37 @@ void Cmd_Reload( gentity_t *ent ) {
RQ3_SSG3000_RELOAD_DELAY); RQ3_SSG3000_RELOAD_DELAY);
*/ */
//Have we fast reloaded before? //Have we fast reloaded before?
if (ent->client->fastReloads) { if (ent->client->fastReloads)
{
if (level.time - ent->client->lastReloadTime < RQ3_SSG3000_FAST_RELOAD_DELAY) if (level.time - ent->client->lastReloadTime < RQ3_SSG3000_FAST_RELOAD_DELAY)
{ {
//not enough time has passed for a fast reload attempt //not enough time has passed for a fast-reload attempt so ignore it
//so discard the attempt
//G_Printf("Too soon: Discarded fast-reload attempt\n"); //G_Printf("Too soon: Discarded fast-reload attempt\n");
return; return;
} }
else if (level.time - ent->client->lastReloadTime >= RQ3_SSG3000_FAST_RELOAD_DELAY && //else if (level.time - ent->client->lastReloadTime >= RQ3_SSG3000_FAST_RELOAD_DELAY &&
level.time - ent->client->lastReloadTime <= RQ3_SSG3000_RELOAD_DELAY) //level.time - ent->client->lastReloadTime <= RQ3_SSG3000_RELOAD_DELAY)*/
else if (level.time - ent->client->lastReloadTime <= RQ3_SSG3000_RELOAD_DELAY)
{ {
//gotcha //Gotcha!
ent->client->fastReloads = 1; ent->client->fastReloads = 1;
} }
else else
{ {
//Missed the window of opportunity! //Missed the window of opportunity! - Reset fastReloads
//Reset fastReloads
//G_Printf("Missed Window: disabling fast reloads\n"); //G_Printf("Missed Window: disabling fast reloads\n");
ent->client->fastReloads = 0; ent->client->fastReloads = 0;
} }
} }
//Fast-reload virgin //Fast-reload virgin
else if (level.time - ent->client->lastReloadTime >= RQ3_SSG3000_ALLOW_FAST_RELOAD_DELAY && else if (level.time - ent->client->lastReloadTime >= RQ3_SSG3000_ALLOW_FAST_RELOAD_DELAY &&
level.time - ent->client->lastReloadTime <= RQ3_SSG3000_RELOAD_DELAY) level.time - ent->client->lastReloadTime <= RQ3_SSG3000_RELOAD_DELAY)
{ {
ent->client->fastReloads = 1; ent->client->fastReloads = 1;
} }
else else
{ {
//not enough time has passed for a fast reload attempt //not enough time has passed for a fast-reload attempt so ignore it
//so discard the attempt
//G_Printf("Too soon: Discarded fast-reload attempt\n"); //G_Printf("Too soon: Discarded fast-reload attempt\n");
return; return;
} }
@ -1904,7 +1927,14 @@ void Cmd_Reload( gentity_t *ent ) {
ent->client->fastReloads = 0; ent->client->fastReloads = 0;
} }
//Elder: finished a full reload cycle - mark the time and discard the attempt
ent->client->lastReloadTime = level.time; ent->client->lastReloadTime = level.time;
ent->client->reloadAttempts--;
//Finish off if no more reload attempts
if (ent->client->reloadAttempts < 1 && ent->client->fastReloads)
delay += RQ3_SSG3000_FINISH_RELOAD_DELAY;
break; break;
case WP_AKIMBO: case WP_AKIMBO:
delay = RQ3_AKIMBO_RELOAD_DELAY; delay = RQ3_AKIMBO_RELOAD_DELAY;
@ -1935,11 +1965,13 @@ void Cmd_Reload( gentity_t *ent ) {
//Elder: added handcannon and akimbo conditional //Elder: added handcannon and akimbo conditional
if (ent->client->numClips[weapon] == 0) { if (ent->client->numClips[weapon] == 0) {
ent->client->fastReloads = 0;
ent->client->reloadAttempts = 0;
trap_SendServerCommand( ent-g_entities, va("print \"Out of ammo\n\"")); trap_SendServerCommand( ent-g_entities, va("print \"Out of ammo\n\""));
return; return;
} }
else if ( (weapon == WP_HANDCANNON || weapon == WP_AKIMBO) && ent->client->numClips[weapon] < 2 ) { else if ( (weapon == WP_HANDCANNON || weapon == WP_AKIMBO) && ent->client->numClips[weapon] < 2 ) {
trap_SendServerCommand( ent-g_entities, va("print \"Not enough of ammo\n\"")); trap_SendServerCommand( ent-g_entities, va("print \"Not enough ammo\n\""));
return; return;
} }
@ -1948,8 +1980,8 @@ void Cmd_Reload( gentity_t *ent ) {
if (RQ3_isZoomed(ent) && weapon == WP_SSG3000) { if (RQ3_isZoomed(ent) && weapon == WP_SSG3000) {
RQ3_SaveZoomLevel(ent); RQ3_SaveZoomLevel(ent);
//Elder: remove zoom bits //Elder: remove zoom bits
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_LOW; //ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_LOW;
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_MED; //ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_MED;
} }
//ent->client->ps.weaponstate = WEAPON_RELOADING; //ent->client->ps.weaponstate = WEAPON_RELOADING;
@ -2200,20 +2232,19 @@ void Cmd_Weapon(gentity_t *ent)
{//Going into Short {//Going into Short
ent->client->ps.persistant[PERS_WEAPONMODES] |= RQ3_GRENSHORT; //Set the short flag ent->client->ps.persistant[PERS_WEAPONMODES] |= RQ3_GRENSHORT; //Set the short flag
ent->client->ps.persistant[PERS_WEAPONMODES] &= ~RQ3_GRENMED; //unset the med flag ent->client->ps.persistant[PERS_WEAPONMODES] &= ~RQ3_GRENMED; //unset the med flag
trap_SendServerCommand( ent-g_entities, va("print \"Grenade set for short range throw.\n\"")); //trap_SendServerCommand( ent-g_entities, va("print \"Grenade set for short range throw.\n\""));
} }
else if ( (ent->client->ps.persistant[PERS_WEAPONMODES] & RQ3_GRENSHORT) == RQ3_GRENSHORT) else if ( (ent->client->ps.persistant[PERS_WEAPONMODES] & RQ3_GRENSHORT) == RQ3_GRENSHORT)
{//Going into Med {//Going into Med
ent->client->ps.persistant[PERS_WEAPONMODES] &= ~RQ3_GRENSHORT; //unset the short flag ent->client->ps.persistant[PERS_WEAPONMODES] &= ~RQ3_GRENSHORT; //unset the short flag
ent->client->ps.persistant[PERS_WEAPONMODES] |= RQ3_GRENMED; //Set the med flag ent->client->ps.persistant[PERS_WEAPONMODES] |= RQ3_GRENMED; //Set the med flag
trap_SendServerCommand( ent-g_entities, va("print \"Grenade set for medium range throw.\n\"")); //trap_SendServerCommand( ent-g_entities, va("print \"Grenade set for medium range throw.\n\""));
} }
else if ( (ent->client->ps.persistant[PERS_WEAPONMODES] & RQ3_GRENMED) == RQ3_GRENMED) else if ( (ent->client->ps.persistant[PERS_WEAPONMODES] & RQ3_GRENMED) == RQ3_GRENMED)
{//Going into Long {//Going into Long
ent->client->ps.persistant[PERS_WEAPONMODES] |= RQ3_GRENSHORT; //Set the short flag ent->client->ps.persistant[PERS_WEAPONMODES] |= RQ3_GRENSHORT; //Set the short flag
ent->client->ps.persistant[PERS_WEAPONMODES] |= RQ3_GRENMED; //Set the med flag ent->client->ps.persistant[PERS_WEAPONMODES] |= RQ3_GRENMED; //Set the med flag
trap_SendServerCommand( ent-g_entities, va("print \"Grenade set for long range throw.\n\"")); //trap_SendServerCommand( ent-g_entities, va("print \"Grenade set for long range throw.\n\""));
} }
//Elder: added //Elder: added
else { else {
@ -2235,20 +2266,21 @@ void Cmd_Weapon(gentity_t *ent)
// Hawkins make sure spread comes back // Hawkins make sure spread comes back
void Cmd_Unzoom(gentity_t *ent){ void Cmd_Unzoom(gentity_t *ent)
{
//G_Printf("Got to Cmd_Unzoom\n"); //G_Printf("Got to Cmd_Unzoom\n");
//Elder: added //Elder: added
//if (ent->client->isBandaging == qtrue) { //if (ent->client->isBandaging == qtrue) {
if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK) { //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\"")); //trap_SendServerCommand( ent-g_entities, va("print \"You'll get to your weapon when you are finished bandaging!\n\""));
return; //return;
} //}
else { //else {
//Elder: remove zoom bits //Elder: remove zoom bits
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_LOW; ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_LOW;
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_MED; ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_MED;
//ent->client->zoomed = 0; //ent->client->zoomed = 0;
} //}
} }
@ -2267,6 +2299,7 @@ void Cmd_Drop_f( gentity_t *ent ) {
} }
else { else {
//Elder: remove zoom bits //Elder: remove zoom bits
Cmd_Unzoom(ent);
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_LOW; ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_LOW;
ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_MED; ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_MED;
//ent->client->zoomed=0; //ent->client->zoomed=0;
@ -2384,7 +2417,12 @@ void ClientCommand( int clientNum ) {
Cmd_Stats_f( ent ); Cmd_Stats_f( ent );
// Begin Duffman // Begin Duffman
else if (Q_stricmp (cmd, "reload") == 0) else if (Q_stricmp (cmd, "reload") == 0)
{
//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++;
Cmd_Reload( ent ); Cmd_Reload( ent );
}
// End Duffman // End Duffman
//Blaze's Open door command //Blaze's Open door command
else if (Q_stricmp (cmd, "opendoor") == 0) else if (Q_stricmp (cmd, "opendoor") == 0)

View file

@ -530,8 +530,9 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
//ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_MED; //ent->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_MED;
//Elder: remove zoom bits //Elder: remove zoom bits
self->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_LOW; Cmd_Unzoom(self);
self->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_MED; //self->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_LOW;
//self->client->ps.stats[STAT_RQ3] &= ~RQ3_ZOOM_MED;
//self->client->zoomed = 0; //self->client->zoomed = 0;
self->client->bleeding = 0; self->client->bleeding = 0;
//targ->client->bleedcount = 0; //targ->client->bleedcount = 0;
@ -541,6 +542,9 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
self->client->ps.stats[STAT_RQ3] &= ~RQ3_BANDAGE_WORK; self->client->ps.stats[STAT_RQ3] &= ~RQ3_BANDAGE_WORK;
self->client->ps.stats[STAT_RQ3] &= ~RQ3_BANDAGE_NEED; self->client->ps.stats[STAT_RQ3] &= ~RQ3_BANDAGE_NEED;
self->client->ps.stats[STAT_STREAK] = 0; self->client->ps.stats[STAT_STREAK] = 0;
//Elder: stop reload attempts
self->client->reloadAttempts = 0;
} }
if ( self->client->ps.pm_type == PM_DEAD ) { if ( self->client->ps.pm_type == PM_DEAD ) {
return; return;
@ -1252,33 +1256,94 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
} }
//Elder: this is a simplifed knockback calc - Action has a radically different one. //Elder: this is a simplifed knockback calc - Action has a radically different one.
knockback = damage; //knockback = damage;
if ( knockback > 200 ) {
knockback = 200;
}
if ( mod == MOD_KICK ) //if ( knockback > 200 ) {
{ //knockback = 200;
knockback = 200; //}
}
//if ( mod == MOD_KICK )
//{
//knockback = 200;
//}
if ( targ->flags & FL_NO_KNOCKBACK ) { if ( targ->flags & FL_NO_KNOCKBACK ) {
knockback = 0; knockback = 0;
} }
if ( dflags & DAMAGE_NO_KNOCKBACK ) { else if ( dflags & DAMAGE_NO_KNOCKBACK ) {
knockback = 0; knockback = 0;
} }
else
{
//Elder: select knockback
switch (mod)
{
case MOD_HANDCANNON:
knockback = RQ3_HANDCANNON_KICK;
break;
case MOD_M3:
knockback = RQ3_M3_KICK;
break;
case MOD_M4:
knockback = RQ3_M4_KICK;
break;
case MOD_MP5:
knockback = RQ3_MP5_KICK;
break;
case MOD_SNIPER:
knockback = RQ3_SNIPER_KICK;
break;
case MOD_PISTOL:
knockback = RQ3_PISTOL_KICK;
break;
case MOD_AKIMBO:
knockback = RQ3_AKIMBO_KICK;
break;
case MOD_GRENADE_SPLASH:
case MOD_GRENADE:
knockback = (int)(0.75 * damage);
break;
case MOD_KNIFE:
knockback = RQ3_KNIFE_KICK;
break;
case MOD_KNIFE_THROWN:
knockback = RQ3_THROW_KICK;
break;
case MOD_KICK:
//Elder: do some calculation here?
knockback = 400;
break;
default:
//G_Printf("Unknown MOD\n");
G_Printf("G_Damage: Received unknown MOD - using default knockback\n");
knockback = 50;
break;
}
}
// figure momentum add, even if the damage won't be taken // figure momentum add, even if the damage won't be taken
if ( knockback && targ->client ) { if ( knockback && targ->client ) {
vec3_t kvel; vec3_t kvel, flydir;
float mass; float mass;
if ( mod != MOD_FALLING )
{
VectorCopy(dir, flydir);
flydir[2] += 0.4f;
}
mass = 200; mass = 200;
//Elder: Q2 uses a hardcoded value of 500 for non-rocket jumps //Elder: Q2 uses a hardcoded value of 500 for non-rocket jumps
//Q3 uses g_knockback.value ... default 1000 //Q3 uses g_knockback.value ... default 1000
VectorScale (dir, g_knockback.value * (float)knockback / mass, kvel); //AQ2:
//VectorScale (flydir, 500.0 * (float)knockback / mass, kvel);
//RQ3:
//VectorScale (dir, g_knockback.value * (float)knockback / mass, kvel);
if (targ->client && attacker == targ)
VectorScale (flydir, 1600.0 * (float)knockback / mass, kvel);
else
VectorScale (flydir, 500.0 * (float)knockback / mass, kvel);
VectorAdd (targ->client->ps.velocity, kvel, targ->client->ps.velocity); VectorAdd (targ->client->ps.velocity, kvel, targ->client->ps.velocity);
// set the timer so that the other client can't cancel // set the timer so that the other client can't cancel
@ -1688,7 +1753,6 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
} }
if (client) if (client)
{ {
if (!(targ->flags & FL_GODMODE) && (take)) targ->pain (targ, attacker, take); if (!(targ->flags & FL_GODMODE) && (take)) targ->pain (targ, attacker, take);
} }
if (take) if (take)

View file

@ -327,7 +327,9 @@ int Pickup_Weapon (gentity_t *ent, gentity_t *other) {
trap_SendServerCommand( other-g_entities, va("print \"%s^7\n\"", RQ3_AKIMBO_NAME) ); trap_SendServerCommand( other-g_entities, va("print \"%s^7\n\"", RQ3_AKIMBO_NAME) );
other->client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_AKIMBO ); other->client->ps.stats[STAT_WEAPONS] |= ( 1 << WP_AKIMBO );
other->client->ps.ammo[WP_AKIMBO] = other->client->ps.ammo[WP_PISTOL] + RQ3_PISTOL_AMMO; other->client->ps.ammo[WP_AKIMBO] = other->client->ps.ammo[WP_PISTOL] + RQ3_PISTOL_AMMO;
ammotoadd = other->client->ps.ammo[WP_PISTOL]; //Elder: always reset back to full clip like Action if first pistol picked up
ammotoadd = RQ3_PISTOL_AMMO;
//ammotoadd = other->client->ps.ammo[WP_PISTOL];
} }
//Elder: Already have akimbo - technically should have pistol //Elder: Already have akimbo - technically should have pistol
else if (other->client->numClips[ WP_PISTOL ] < 2) { else if (other->client->numClips[ WP_PISTOL ] < 2) {
@ -374,9 +376,9 @@ int Pickup_Weapon (gentity_t *ent, gentity_t *other) {
other->client->ps.stats[STAT_UNIQUEWEAPONS]++; other->client->ps.stats[STAT_UNIQUEWEAPONS]++;
break; break;
case WP_GRENADE: case WP_GRENADE:
if (other->client->ps.ammo[ent->item->giTag] < RQ3_GRENADE_MAXCLIP) if (other->client->ps.ammo[WP_GRENADE] < RQ3_GRENADE_MAXCLIP)
{ {
ammotoadd=other->client->ps.ammo[ent->item->giTag]+1; ammotoadd=other->client->ps.ammo[WP_GRENADE] + 1;
} }
else else
{ {
@ -606,7 +608,7 @@ void Touch_Item (gentity_t *ent, gentity_t *other, trace_t *trace) {
return; return;
break; break;
case WP_GRENADE: case WP_GRENADE:
if ( (other->client->ps.stats[STAT_WEAPONS] & (1 << WP_GRENADE) == (1 << 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) )
return; return;
break; break;
@ -951,7 +953,7 @@ gentity_t *dropWeapon( gentity_t *ent, gitem_t *item, float angle, int xr_flags
vec3_t velocity; vec3_t velocity;
vec3_t angles; vec3_t angles;
vec3_t origin; vec3_t origin;
int throwheight; //int throwheight;
VectorCopy( ent->s.pos.trBase, origin ); VectorCopy( ent->s.pos.trBase, origin );
VectorCopy( ent->s.apos.trBase, angles ); VectorCopy( ent->s.apos.trBase, angles );

View file

@ -367,6 +367,7 @@ struct gclient_s {
int fastReloads; //Elder: for queuing M3/SSG reloads int fastReloads; //Elder: for queuing M3/SSG reloads
int lastReloadTime; //Elder: for queuing M3/SSG reloads int lastReloadTime; //Elder: for queuing M3/SSG reloads
int reloadAttempts; //Elder: for queueing M3/SSG reloads
int consecutiveShots; //Elder: for M4 ride-up/kick int consecutiveShots; //Elder: for M4 ride-up/kick
@ -506,6 +507,8 @@ void StopFollowing( gentity_t *ent );
void BroadcastTeamChange( gclient_t *client, int oldTeam ); void BroadcastTeamChange( gclient_t *client, int oldTeam );
void SetTeam( gentity_t *ent, char *s ); void SetTeam( gentity_t *ent, char *s );
void Cmd_FollowCycle_f( gentity_t *ent, int dir ); void Cmd_FollowCycle_f( gentity_t *ent, int dir );
void Cmd_Unzoom(gentity_t *ent);
void Cmd_OpenDoor(gentity_t *ent);
//Elder: commented out for Homer //Elder: commented out for Homer
//void toggleSemi(gentity_t *ent); //void toggleSemi(gentity_t *ent);
@ -598,7 +601,8 @@ void TossClientCubes( gentity_t *self );
#ifdef MISSIONPACK #ifdef MISSIONPACK
#define DAMAGE_NO_TEAM_PROTECTION 0x00000010 // armor, shields, invulnerability, and godmode have no effect #define DAMAGE_NO_TEAM_PROTECTION 0x00000010 // armor, shields, invulnerability, and godmode have no effect
#endif #endif
#define DAMAGE_NO_LOCATIONAL 0x00000016 // Generic damage (shotguns, grenades, kicks) //Elder: Changed from 0x00000016 to 0x00000020
#define DAMAGE_NO_LOCATIONAL 0x00000020 // Generic damage (shotguns, grenades, kicks)
// //
// g_missile.c // g_missile.c
@ -656,6 +660,8 @@ qboolean CheckGauntletAttack( gentity_t *ent );
//Elder: for shotgun damage reports //Elder: for shotgun damage reports
void RQ3_InitShotgunDamageReport( void ); void RQ3_InitShotgunDamageReport( void );
void RQ3_ProduceShotgunDamageReport(gentity_t *self); void RQ3_ProduceShotgunDamageReport(gentity_t *self);
qboolean JumpKick( gentity_t *ent );
qboolean DoorKick( trace_t *trIn, gentity_t *ent, vec3_t origin, vec3_t forward );
extern int tookShellHit[MAX_CLIENTS]; extern int tookShellHit[MAX_CLIENTS];

View file

@ -1695,9 +1695,9 @@ void G_RunFrame( int levelTime ) {
int i; int i;
gentity_t *ent; gentity_t *ent;
//Blaze: Used for droping knifes //Blaze: Used for droping knifes
gitem_t *xr_item; //gitem_t *xr_item;
gentity_t *xr_drop; //gentity_t *xr_drop;
int temp; //int temp;
int msec; int msec;
int start, end; int start, end;

View file

@ -709,8 +709,9 @@ gentity_t *fire_grenade (gentity_t *self, vec3_t start, vec3_t dir) {
//Elder: grenade toggle distances/speeds //Elder: grenade toggle distances/speeds
if ( self->client) { if ( self->client) {
if (self->client->ps.stats[STAT_HEALTH] <= 0) { if ( self->client->ps.stats[STAT_HEALTH] <= 0 ||
//Always drop close range if dead (self->client->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK) {
//Always drop close range if dead or about to bandage
speed = GRENADE_SHORT_SPEED / 2; speed = GRENADE_SHORT_SPEED / 2;
} }
else if ( (self->client->ps.persistant[PERS_WEAPONMODES] & RQ3_GRENSHORT) == RQ3_GRENSHORT && else if ( (self->client->ps.persistant[PERS_WEAPONMODES] & RQ3_GRENSHORT) == RQ3_GRENSHORT &&

View file

@ -36,6 +36,174 @@ void G_BounceProjectile( vec3_t start, vec3_t impact, vec3_t dir, vec3_t endout
} }
/*
======================================================================
RQ3 Jump Kick
Moved from g_active.c to g_weapon.c
Because it is a weapon!
======================================================================
*/
qboolean JumpKick( gentity_t *ent )
{
trace_t tr;
vec3_t end;
gentity_t *tent;
gentity_t *traceEnt;
int damage;
//Elder: for kick sound
qboolean kickSuccess;
// set aiming directions
AngleVectors (ent->client->ps.viewangles, forward, right, up);
CalcMuzzlePoint ( ent, forward, right, up, muzzle );
VectorMA (muzzle, 32, forward, end);
//VectorCopy( ent->s.origin, muzzle );
//muzzle[2] += 32;
// the muzzle really isn't the right point to test the jumpkick from
trap_Trace (&tr, muzzle, NULL, NULL, end, ent->s.number, MASK_SHOT);
//trap_Trace (&tr, ent->s.origin, ent->r.mins, ent->r.maxs, end, ent->s.number, MASK_SHOT);
//trap_Trace (&tr, ent->s.origin, NULL, NULL, end, ent->s.number, MASK_SHOT);
if ( tr.surfaceFlags & SURF_NOIMPACT ) {
return qfalse;
}
kickSuccess = DoorKick( &tr, ent, muzzle, forward );
traceEnt = &g_entities[ tr.entityNum ];
if ( !traceEnt->takedamage) {
return qfalse;
}
if (ent->client->ps.powerups[PW_QUAD] ) {
G_AddEvent( ent, EV_POWERUP_QUAD, 0 );
s_quadFactor = g_quadfactor.value;
} else {
s_quadFactor = 1;
}
damage = 20;
if ( traceEnt->s.eType == ET_BREAKABLE || traceEnt->client)
kickSuccess = qtrue;
//Elder: can't hit if crouching but can still hit "dead" bodies :)
if (traceEnt->client && traceEnt->health > 0 && traceEnt->r.maxs[2] < 20)
{
return qfalse;
}
else {
G_Damage( traceEnt, ent, ent, forward, tr.endpos,
damage, DAMAGE_NO_LOCATIONAL, MOD_KICK );
}
// send blood impact
if ( traceEnt->takedamage && traceEnt->client ) {
tent = G_TempEntity( tr.endpos, EV_MISSILE_HIT );
tent->s.otherEntityNum = traceEnt->s.number;
tent->s.eventParm = DirToByte( tr.plane.normal );
tent->s.weapon = ent->s.weapon;
}
if (traceEnt->client && traceEnt->client->ps.stats[STAT_UNIQUEWEAPONS] > 0)
{
//Elder: toss a unique weapon if kicked
//Todo: Need to make sure to cancel any reload attempts
//Todo: need to send a message to attacker and target about weapon kick
ThrowWeapon(traceEnt);
//trap_SendServerCommand( ent-g_entities, va("print \"You kicked %s's %s from his hands!\n\"", traceEnt->client->pers.netname, (traceEnt->client->ps.weapon)->pickup_name);
//trap_SendServerCommand( targ-g_entities, va("print \"Head Damage.\n\""));
}
//Elder: for the kick
// do our special form of knockback here
/*
VectorMA (self->enemy->absmin, 0.5, self->enemy->size, v);
VectorSubtract (v, point, v);
VectorNormalize (v);
VectorMA (self->enemy->velocity, kick, v, self->enemy->velocity);
if (self->enemy->velocity[2] > 0)
self->enemy->groundentity = NULL;
*/
//Elder: kick knockback for AQ2 -- recall variable kick = 400
//if (traceEnt->client)
//{
//Elder: for kick knockback
//vec3_t size, vTemp;
//Make the "size" vector - hopefully this is right
//VectorSubtract(traceEnt->r.maxs, traceEnt->r.mins, size);
//G_Printf("Size: %s\n", vtos(size));
//VectorMA(traceEnt->r.absmin, 0.5, size, vTemp);
//VectorSubtract(vTemp, tr.endpos, vTemp);
//VectorNormalize(vTemp);
//VectorMA(traceEnt->client->ps.velocity, 400, vTemp, traceEnt->client->ps.velocity);
//if (traceEnt->client->ps.velocity[2] > 0)
//traceEnt->s.groundEntityNum = ENTITYNUM_NONE;
//}
//Elder: Our set of locally called sounds
if (kickSuccess)
G_AddEvent ( ent, EV_RQ3_SOUND, RQ3_SOUND_KICK);
return qtrue;
}
qboolean DoorKick( trace_t *trIn, gentity_t *ent, vec3_t origin, vec3_t forward )
{
gentity_t *traceEnt;
trace_t tr;
traceEnt = &g_entities[ trIn->entityNum ];
if ( Q_stricmp (traceEnt->classname, "func_door_rotating") == 0 )
{
vec3_t d_right, d_forward;
float crossProduct;
vec3_t end;
// Find the hit point and the muzzle point with respect
// to the door's origin, then project down to the XY plane
// and take the cross product
VectorSubtract( trIn->endpos, traceEnt->s.origin, d_right );
VectorSubtract( origin, traceEnt->s.origin, d_forward );
crossProduct = d_forward[0]*d_right[1]-d_right[0]*d_forward[1];
// See if we are on the proper side to do it
if ( ((traceEnt->pos2[1] > traceEnt->pos1[1]) && crossProduct > 0) ||
((traceEnt->pos2[1] < traceEnt->pos1[1]) && crossProduct < 0))
{
Cmd_OpenDoor( ent );
VectorMA( trIn->endpos, 25, forward, end );
trap_Trace (&tr, trIn->endpos, NULL, NULL, end, trIn->entityNum, MASK_SHOT);
if ( !(tr.surfaceFlags & SURF_NOIMPACT) )
{
traceEnt = &g_entities[ tr.entityNum ];
if ( traceEnt->client )
{
*trIn = tr;
}
}
}
return qtrue;
}
else
return qfalse;
}
/* /*
====================================================================== ======================================================================
@ -907,18 +1075,77 @@ void Knife_Touch (gentity_t *ent, gentity_t *other,trace_t *trace)
//====================================================================== //======================================================================
int RQ3Spread (gentity_t *ent, int spread) //Elder: can probably be static
int RQ3_Spread (gentity_t *ent, int spread)
{ {
int runspeed = 225; int runspeed = 225;
int walkspeed = 10; int walkspeed = 10;
int stage = 0;
float factor[] = {0.7f, 1.0f, 2.0f, 6.0f};
float xyspeed = (ent->client->ps.velocity[0]*ent->client->ps.velocity[0] + ent->client->ps.velocity[1]*ent->client->ps.velocity[1]); float xyspeed = (ent->client->ps.velocity[0]*ent->client->ps.velocity[0] + ent->client->ps.velocity[1]*ent->client->ps.velocity[1]);
if (ent->client->ps.pm_flags & PMF_DUCKED) return (spread * 0.65); //crouching
if (ent->client->ps.pm_flags & PMF_DUCKED)
return (spread * 0.65);
if (xyspeed > runspeed * runspeed) spread *= 3; //running
else if (xyspeed >= walkspeed*walkspeed) spread *= 2; if (xyspeed > runspeed * runspeed)
return (int)spread; stage = 3;
//walking
else if (xyspeed >= walkspeed*walkspeed)
stage = 2;
//standing
else
stage = 1;
//TODO: add laser advantage
return (int)(spread * factor[stage]);
/*
//Elder: original AQ2 code
int running = 225; // minimum speed for running
int walking = 10; // minimum speed for walking
int laser = 0;
float factor[] = {.7, 1, 2, 6};
int stage = 0;
// 225 is running
// < 10 will be standing
float xyspeed = (ent->velocity[0]*ent->velocity[0] + ent->velocity[1]*ent->velocity[1]);
if (ent->client->ps.pmove.pm_flags & PMF_DUCKED) // crouching
return( spread * .65);
if ( (ent->client->pers.inventory[ITEM_INDEX(FindItem(LASER_NAME))])
&& (ent->client->curr_weap == MK23_NUM
|| ent->client->curr_weap == MP5_NUM
|| ent->client->curr_weap == M4_NUM ) )
laser = 1;
// running
if ( xyspeed > running*running )
stage = 3;
// walking
else if ( xyspeed >= walking*walking )
stage = 2;
// standing
else
stage = 1;
// laser advantage
if (laser)
{
if (stage == 1)
stage = 0;
else
stage = 1;
}
return (int)(spread * factor[stage]);
*/
} }
@ -981,7 +1208,7 @@ void Weapon_M4_Fire(gentity_t *ent)
} }
Bullet_Fire( ent, RQ3Spread(ent, M4_SPREAD), M4_DAMAGE, MOD_M4); Bullet_Fire( ent, RQ3_Spread(ent, M4_SPREAD), M4_DAMAGE, MOD_M4);
/* /*
if ( (ent->client->ps.persistant[PERS_WEAPONMODES] & RQ3_M4MODE) == RQ3_M4MODE) { if ( (ent->client->ps.persistant[PERS_WEAPONMODES] & RQ3_M4MODE) == RQ3_M4MODE) {
@ -1014,7 +1241,7 @@ void Weapon_MK23_Fire(gentity_t *ent)
{ {
spread = PISTOL_SPREAD; spread = PISTOL_SPREAD;
} }
Bullet_Fire( ent, RQ3Spread(ent, spread), PISTOL_DAMAGE, MOD_PISTOL); Bullet_Fire( ent, RQ3_Spread(ent, spread), PISTOL_DAMAGE, MOD_PISTOL);
} }
@ -1028,7 +1255,7 @@ void Weapon_SSG3000_FireOld(gentity_t *ent)
float spread; float spread;
//Elder: Don't print - will broadcast to server //Elder: Don't print - will broadcast to server
//G_Printf("Zoom Level: %d\n", ent->client->zoomed); //G_Printf("Zoom Level: %d\n", ent->client->zoomed);
//Elder: changed to use RQ3Spread as well //Elder: changed to use RQ3_Spread as well
//Elder: using new stat //Elder: using new stat
//if ( (ent->client->ps.stats[STAT_RQ3] & RQ3_ZOOM_LOW) == RQ3_ZOOM_LOW || //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) { //(ent->client->ps.stats[STAT_RQ3] & RQ3_ZOOM_MED) == RQ3_ZOOM_MED) {
@ -1036,7 +1263,7 @@ void Weapon_SSG3000_FireOld(gentity_t *ent)
spread = 0; spread = 0;
} }
else { else {
spread = RQ3Spread(ent, SNIPER_SPREAD); spread = RQ3_Spread(ent, SNIPER_SPREAD);
} }
Bullet_Fire( ent, spread, SNIPER_DAMAGE, MOD_SNIPER); Bullet_Fire( ent, spread, SNIPER_DAMAGE, MOD_SNIPER);
@ -1054,7 +1281,7 @@ railgun_fire, old SSG, and bullet_fire code
weapon_ssg3000_fire weapon_ssg3000_fire
================= =================
*/ */
#define MAX_SSG3000_HITS 4 #define MAX_SSG3000_HITS 8
void Weapon_SSG3000_Fire (gentity_t *ent) { void Weapon_SSG3000_Fire (gentity_t *ent) {
vec3_t end; vec3_t end;
trace_t trace; trace_t trace;
@ -1081,7 +1308,7 @@ void Weapon_SSG3000_Fire (gentity_t *ent) {
spread = 0; spread = 0;
} }
else { else {
spread = RQ3Spread(ent, SNIPER_SPREAD); spread = RQ3_Spread(ent, SNIPER_SPREAD);
r = random() * M_PI * 2.0f; r = random() * M_PI * 2.0f;
u = sin(r) * crandom() * spread * 16; u = sin(r) * crandom() * spread * 16;
r = cos(r) * crandom() * spread * 16; r = cos(r) * crandom() * spread * 16;
@ -1226,7 +1453,7 @@ void Weapon_SSG3000_Fire (gentity_t *ent) {
} }
//Elder: bolt action plus save last zoom //Elder: bolt action plus save last zoom
ent->client->weaponfireNextTime = level.time + RQ3_SSG3000_BOLT_DELAY; //ent->client->weaponfireNextTime = level.time + RQ3_SSG3000_BOLT_DELAY;
RQ3_SaveZoomLevel(ent); RQ3_SaveZoomLevel(ent);
} }
@ -1250,7 +1477,7 @@ void Weapon_MP5_Fire(gentity_t *ent)
spread = MP5_SPREAD; spread = MP5_SPREAD;
} }
Bullet_Fire( ent, RQ3Spread(ent, MP5_SPREAD), MP5_DAMAGE, MOD_MP5); Bullet_Fire( ent, RQ3_Spread(ent, MP5_SPREAD), MP5_DAMAGE, MOD_MP5);
} }
/* /*
@ -1385,7 +1612,7 @@ void Weapon_Akimbo_Fire(gentity_t *ent)
float spread; float spread;
//Blaze: Will need 2 of these //Blaze: Will need 2 of these
spread = AKIMBO_SPREAD; spread = AKIMBO_SPREAD;
Bullet_Fire( ent, RQ3Spread(ent, spread), AKIMBO_DAMAGE, MOD_AKIMBO); Bullet_Fire( ent, RQ3_Spread(ent, spread), AKIMBO_DAMAGE, MOD_AKIMBO);
//Elder: reset plus added 1 bullet check //Elder: reset plus added 1 bullet check
if (ent->client->weaponfireNextTime > 0 || ent->client->ps.ammo[WP_AKIMBO] < 2) if (ent->client->weaponfireNextTime > 0 || ent->client->ps.ammo[WP_AKIMBO] < 2)
@ -1393,7 +1620,7 @@ void Weapon_Akimbo_Fire(gentity_t *ent)
else else
ent->client->weaponfireNextTime = level.time + RQ3_AKIMBO_DELAY2; ent->client->weaponfireNextTime = level.time + RQ3_AKIMBO_DELAY2;
//Bullet_Fire( ent, RQ3Spread(ent, spread), AKIMBO_DAMAGE, MOD_AKIMBO); //Bullet_Fire( ent, RQ3_Spread(ent, spread), AKIMBO_DAMAGE, MOD_AKIMBO);
} }
/* /*

View file

@ -19,6 +19,7 @@ void CheckBleeding(gentity_t *targ)
if (targ->client->bleed_remain >= BLEED_TIME) if (targ->client->bleed_remain >= BLEED_TIME)
{ {
//G_Printf("Bleed Remain: %i\n", targ->client->bleed_remain);
if ( (targ->client->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK && if ( (targ->client->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK &&
targ->client->bleedBandageCount < 1) targ->client->bleedBandageCount < 1)
{ {
@ -32,7 +33,9 @@ void CheckBleeding(gentity_t *targ)
//Elder: hack to count off health so we only lose 6 health on a bandage //Elder: hack to count off health so we only lose 6 health on a bandage
if ( (targ->client->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK) if ( (targ->client->ps.stats[STAT_RQ3] & RQ3_BANDAGE_WORK) == RQ3_BANDAGE_WORK)
{ {
targ->client->bleedBandageCount--; //Start hack enforcement once we've ramped down to 1 health/second
if (targ->client->bleed_remain <= 10)
targ->client->bleedBandageCount--;
} }
if (targ->health <= 0) if (targ->health <= 0)