mirror of
https://github.com/ReactionQuake3/reaction.git
synced 2024-11-23 04:32:28 +00:00
Elder:
Code for the 0-10-0x VM releases Server-side
This commit is contained in:
parent
8ea88d097b
commit
9e2222ecf1
12 changed files with 688 additions and 106 deletions
|
@ -1312,7 +1312,9 @@ char *eventnames[] = {
|
|||
"EV_NOAMMO",
|
||||
"EV_CHANGE_WEAPON",
|
||||
"EV_FIRE_WEAPON",
|
||||
"EV_RELOAD_WEAPON," // Elder: reload weapon sounds
|
||||
"EV_RELOAD_WEAPON0", // Elder: reload weapon sounds
|
||||
"EV_RELOAD_WEAPON1", // Elder: reload weapon sounds
|
||||
"EV_RELOAD_WEAPON2", // Elder: reload weapon sounds
|
||||
|
||||
"EV_USE_ITEM0",
|
||||
"EV_USE_ITEM1",
|
||||
|
@ -1347,8 +1349,10 @@ char *eventnames[] = {
|
|||
|
||||
"EV_BULLET_HIT_FLESH",
|
||||
"EV_BULLET_HIT_WALL",
|
||||
"EV_SSG3000_HIT_FLESH", //Elder: SSG3000 blood spray
|
||||
"EV_JUMPKICK", //Elder: sound + jumpkick message
|
||||
"EV_BULLET_HIT_METAL", // Elder: sparks
|
||||
"EV_BULLET_HIT_KEVLAR", // Elder: sparks
|
||||
"EV_SSG3000_HIT_FLESH", // Elder: SSG3000 blood spray
|
||||
"EV_JUMPKICK", // Elder: sound + jumpkick message
|
||||
|
||||
"EV_MISSILE_HIT",
|
||||
"EV_MISSILE_MISS",
|
||||
|
|
|
@ -109,6 +109,7 @@ void PM_AddEvent( int newEvent ) {
|
|||
PM_AddEvent
|
||||
|
||||
Elder: stuffs event parameters
|
||||
Be careful because you are stuffing the player
|
||||
===============
|
||||
*/
|
||||
void PM_AddEvent2( int newEvent, int eventParm ) {
|
||||
|
@ -1831,16 +1832,25 @@ static void PM_BeginWeaponChange( int weapon ) {
|
|||
if (pm->ps->weapon == WP_PISTOL ||
|
||||
pm->ps->weapon == WP_M3 ||
|
||||
pm->ps->weapon == WP_HANDCANNON ||
|
||||
pm->ps->weapon == WP_SSG3000)
|
||||
pm->ps->weapon == WP_SSG3000 ||
|
||||
pm->ps->weapon == WP_M4)
|
||||
PM_StartWeaponAnim(WP_ANIM_DISARM);
|
||||
}
|
||||
|
||||
|
||||
// Elder: cancel reload stuff here
|
||||
pm->ps->stats[STAT_RELOADTIME] = 0;
|
||||
pm->ps->stats[STAT_RELOADATTEMPTS] = 0;
|
||||
pm->ps->stats[STAT_RQ3] &= ~RQ3_FASTRELOADS;
|
||||
pm->ps->stats[STAT_RQ3] &= ~RQ3_LOCKRELOADS;
|
||||
|
||||
pm->ps->weaponstate = WEAPON_DROPPING;
|
||||
|
||||
//Elder: temp hack
|
||||
if (pm->ps->weapon == WP_PISTOL ||
|
||||
pm->ps->weapon == WP_M3 ||
|
||||
pm->ps->weapon == WP_HANDCANNON ||
|
||||
pm->ps->weapon == WP_SSG3000)
|
||||
pm->ps->weapon == WP_SSG3000 ||
|
||||
pm->ps->weapon == WP_M4)
|
||||
PM_StartWeaponAnim(WP_ANIM_DISARM);
|
||||
|
||||
PM_StartTorsoAnim( TORSO_DROP );
|
||||
|
@ -1915,7 +1925,8 @@ static void PM_FinishWeaponChange( void ) {
|
|||
if (pm->ps->weapon == WP_PISTOL ||
|
||||
pm->ps->weapon == WP_M3 ||
|
||||
pm->ps->weapon == WP_HANDCANNON ||
|
||||
pm->ps->weapon == WP_SSG3000)
|
||||
pm->ps->weapon == WP_SSG3000 ||
|
||||
pm->ps->weapon == WP_M4)
|
||||
PM_StartWeaponAnim(WP_ANIM_ACTIVATE);
|
||||
|
||||
PM_StartTorsoAnim( TORSO_RAISE );
|
||||
|
@ -1942,7 +1953,8 @@ static void PM_TorsoAnimation( void ) {
|
|||
if (pm->ps->weapon == WP_PISTOL ||
|
||||
pm->ps->weapon == WP_M3 ||
|
||||
pm->ps->weapon == WP_HANDCANNON ||
|
||||
pm->ps->weapon == WP_SSG3000)
|
||||
pm->ps->weapon == WP_SSG3000 ||
|
||||
pm->ps->weapon == WP_M4)
|
||||
PM_ContinueWeaponAnim( WP_ANIM_IDLE );
|
||||
// PM_ContinueWeaponAnim( WP_ANIM_READY );
|
||||
|
||||
|
@ -1970,6 +1982,298 @@ static void PM_WeaponAnimation( void ) {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
PM_Reload
|
||||
|
||||
Added by Elder
|
||||
What a mess this is :/
|
||||
FIXME: This is poorly implemented
|
||||
|
||||
Does reload stuff like fast-reloads, sound events,
|
||||
some ammo synchronization, etc.
|
||||
Clip management is handled on the server (ReloadWeapon)
|
||||
because we can't store all the clips in a playerstate (nor should we)
|
||||
It is triggered by BUTTON_AFFIRMATIVE (bind +button5)
|
||||
==============
|
||||
*/
|
||||
static void PM_Reload( void )
|
||||
{
|
||||
// int weapon = pm->ps->weapon;
|
||||
|
||||
// only normal/noclip players can reload
|
||||
if (pm->ps->pm_type > PM_NOCLIP)
|
||||
{
|
||||
pm->ps->pm_flags &= ~PMF_RELOAD_HELD;
|
||||
pm->ps->stats[STAT_RELOADTIME] = 0;
|
||||
pm->ps->stats[STAT_RELOADATTEMPTS] = 0;
|
||||
pm->ps->stats[STAT_RQ3] &= ~RQ3_FASTRELOADS;
|
||||
pm->ps->stats[STAT_RQ3] &= ~RQ3_LOCKRELOADS;
|
||||
return;
|
||||
}
|
||||
|
||||
if ( pm->cmd.buttons & BUTTON_AFFIRMATIVE ) {
|
||||
if ( !(pm->ps->pm_flags & PMF_RELOAD_HELD) )
|
||||
{
|
||||
// prevent throttling
|
||||
pm->ps->pm_flags |= PMF_RELOAD_HELD;
|
||||
|
||||
// check for bursting or weapon delay
|
||||
if (pm->ps->stats[STAT_BURST] > 0 || pm->ps->weaponTime > 0)
|
||||
return;
|
||||
|
||||
// check for bandaging
|
||||
if (pm->ps->stats[STAT_RQ3] & RQ3_BANDAGE_WORK)
|
||||
return;
|
||||
|
||||
// check for full clip or non-reloadable weapons
|
||||
if (pm->ps->ammo[pm->ps->weapon] == ClipAmountForAmmo(pm->ps->weapon) ||
|
||||
pm->ps->weapon == WP_KNIFE ||
|
||||
pm->ps->weapon == WP_GRENADE)
|
||||
{
|
||||
//Com_Printf("No need to reload.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// check for insufficient ammo
|
||||
if (pm->ps->stats[STAT_CLIPS] <= 0)
|
||||
{
|
||||
//Com_Printf("Out of ammo.\n");
|
||||
return;
|
||||
}
|
||||
else if (pm->ps->weapon == WP_HANDCANNON ||
|
||||
pm->ps->weapon == WP_AKIMBO)
|
||||
{
|
||||
if (pm->ps->stats[STAT_CLIPS] < 2)
|
||||
{
|
||||
//Com_Printf("Not enough ammo.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// check for fast-reload interrupt
|
||||
if (pm->ps->weapon == WP_M3 || pm->ps->weapon == WP_SSG3000)
|
||||
{
|
||||
if (pm->ps->stats[STAT_RELOADTIME] > 0) {
|
||||
if ( pm->ps->stats[STAT_RQ3] & RQ3_LOCKRELOADS )
|
||||
{
|
||||
Com_Printf("============= Locked out in fast-reload interrupt\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
//if (pm->ps->ammo[pm->ps->weapon] + pm->ps->stats[STAT_RELOADATTEMPTS] < ClipAmountForAmmo(pm->ps->weapon) &&
|
||||
//pm->ps->stats[STAT_RELOADATTEMPTS] < pm->ps->stats[STAT_CLIPS])
|
||||
if (pm->ps->stats[STAT_RELOADATTEMPTS] < ClipAmountForAmmo(pm->ps->weapon))
|
||||
{
|
||||
//Com_Printf("Hit fast-reload entrance\n");
|
||||
// add to reload queue and enable fast-reloads flag
|
||||
pm->ps->stats[STAT_RQ3] |= RQ3_FASTRELOADS;
|
||||
pm->ps->stats[STAT_RELOADATTEMPTS]++;
|
||||
Com_Printf("======== Reload attempts: %i ========\n", pm->ps->stats[STAT_RELOADATTEMPTS]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// fresh reload
|
||||
if (pm->ps->stats[STAT_RELOADTIME] == 0)
|
||||
{
|
||||
// set reload time according to weapon
|
||||
switch (pm->ps->weapon)
|
||||
{
|
||||
case WP_PISTOL:
|
||||
pm->ps->stats[STAT_RELOADTIME] = RQ3_PISTOL_RELOAD_DELAY;
|
||||
break;
|
||||
case WP_AKIMBO:
|
||||
pm->ps->stats[STAT_RELOADTIME] = RQ3_AKIMBO_RELOAD_DELAY;
|
||||
break;
|
||||
case WP_M3:
|
||||
pm->ps->stats[STAT_RELOADTIME] = RQ3_M3_RELOAD_DELAY;
|
||||
pm->ps->stats[STAT_RELOADATTEMPTS]++;
|
||||
break;
|
||||
case WP_M4:
|
||||
pm->ps->stats[STAT_RELOADTIME] = RQ3_M4_RELOAD_DELAY;
|
||||
break;
|
||||
case WP_MP5:
|
||||
pm->ps->stats[STAT_RELOADTIME] = RQ3_MP5_RELOAD_DELAY;
|
||||
break;
|
||||
case WP_HANDCANNON:
|
||||
pm->ps->stats[STAT_RELOADTIME] = RQ3_HANDCANNON_RELOAD_DELAY;
|
||||
break;
|
||||
case WP_SSG3000:
|
||||
pm->ps->stats[STAT_RELOADTIME] = RQ3_SSG3000_RELOAD_DELAY;
|
||||
pm->ps->stats[STAT_RELOADATTEMPTS]++;
|
||||
break;
|
||||
}
|
||||
|
||||
pm->ps->weaponstate = WEAPON_RELOADING;
|
||||
PM_AddEvent(EV_RELOAD_WEAPON0);
|
||||
//Com_Printf("Starting reload\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
pm->ps->pm_flags &= ~PMF_RELOAD_HELD;
|
||||
}
|
||||
|
||||
// in-progress reload
|
||||
if (pm->ps->stats[STAT_RELOADTIME] > 0)
|
||||
{
|
||||
pm->ps->stats[STAT_RELOADTIME] -= pml.msec;
|
||||
|
||||
// process any fast-reload stuff here
|
||||
if (pm->ps->weapon == WP_M3 || pm->ps->weapon == WP_SSG3000) {
|
||||
if ((pm->ps->stats[STAT_RQ3] & RQ3_FASTRELOADS) && pm->ps->stats[STAT_RELOADATTEMPTS] > 0)
|
||||
{
|
||||
if (pm->ps->weapon == WP_M3)
|
||||
{
|
||||
// knock down reload time if doing fast-reloads
|
||||
if (pm->ps->stats[STAT_RELOADTIME] > RQ3_M3_FAST_RELOAD_DELAY)
|
||||
{
|
||||
//Com_Printf("Reducing reload time\n");
|
||||
pm->ps->stats[STAT_RELOADTIME] = RQ3_M3_FAST_RELOAD_DELAY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// knock down reload time if doing fast-reloads
|
||||
if (pm->ps->stats[STAT_RELOADTIME] > RQ3_SSG3000_FAST_RELOAD_DELAY)
|
||||
{
|
||||
//Com_Printf("Reducing reload time\n");
|
||||
pm->ps->stats[STAT_RELOADTIME] = RQ3_SSG3000_FAST_RELOAD_DELAY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// insert stage 1 sound events here; check against the reload time
|
||||
|
||||
// finished reload
|
||||
if (pm->ps->stats[STAT_RELOADTIME] <= 0)
|
||||
{
|
||||
int ammotoadd;
|
||||
|
||||
ammotoadd = ClipAmountForReload(pm->ps->weapon);
|
||||
if (pm->ps->weapon == WP_M3 || pm->ps->weapon == WP_SSG3000)
|
||||
{
|
||||
// need to also check here because of fast-reloads
|
||||
if (ammotoadd + pm->ps->ammo[pm->ps->weapon] > ClipAmountForAmmo(pm->ps->weapon) ||
|
||||
pm->ps->stats[STAT_CLIPS] <= 0)
|
||||
{
|
||||
ammotoadd = pm->ps->ammo[pm->ps->weapon];
|
||||
pm->ps->stats[STAT_RELOADATTEMPTS] = 0;
|
||||
}
|
||||
else
|
||||
ammotoadd += pm->ps->ammo[pm->ps->weapon];
|
||||
}
|
||||
|
||||
// akimbo and MK23 synchronization
|
||||
if (pm->ps->weapon == WP_AKIMBO)
|
||||
{
|
||||
pm->ps->ammo[WP_PISTOL] = RQ3_PISTOL_AMMO;
|
||||
}
|
||||
else if (pm->ps->weapon == WP_PISTOL &&
|
||||
(pm->ps->stats[STAT_WEAPONS] & (1 << WP_AKIMBO)))
|
||||
{
|
||||
// weird? That's because we gave one pistol a full clip
|
||||
pm->ps->ammo[WP_AKIMBO] = pm->ps->ammo[WP_AKIMBO] - pm->ps->ammo[WP_PISTOL] + ammotoadd;
|
||||
if (pm->ps->ammo[WP_AKIMBO] > RQ3_AKIMBO_AMMO)
|
||||
pm->ps->ammo[WP_AKIMBO] = RQ3_AKIMBO_AMMO;
|
||||
}
|
||||
|
||||
if ( !(pm->ps->stats[STAT_RQ3] & RQ3_LOCKRELOADS) )
|
||||
pm->ps->ammo[pm->ps->weapon] = ammotoadd;
|
||||
|
||||
// handle continuous fast-reloads
|
||||
if ((pm->ps->weapon == WP_M3 || pm->ps->weapon == WP_SSG3000) &&
|
||||
(pm->ps->stats[STAT_RQ3] & RQ3_FASTRELOADS) )//&&
|
||||
//pm->ps->stats[STAT_RELOADATTEMPTS] > 0)
|
||||
{
|
||||
if ( !(pm->ps->stats[STAT_RQ3] & RQ3_LOCKRELOADS) &&
|
||||
pm->ps->stats[STAT_RELOADATTEMPTS] > 0)
|
||||
{
|
||||
//Com_Printf("Fast-reload cycle repeating\n");
|
||||
if (pm->ps->weapon == WP_M3)
|
||||
pm->ps->stats[STAT_RELOADTIME] += RQ3_M3_FAST_RELOAD_DELAY;
|
||||
else
|
||||
pm->ps->stats[STAT_RELOADTIME] += RQ3_SSG3000_FAST_RELOAD_DELAY;
|
||||
|
||||
pm->ps->stats[STAT_RELOADATTEMPTS]--;
|
||||
|
||||
|
||||
if (pm->ps->stats[STAT_RELOADATTEMPTS] > 0)
|
||||
PM_StartWeaponAnim(WP_ANIM_RELOAD);
|
||||
//PM_StartWeaponAnim(WP_ANIM_EXTRA1);
|
||||
|
||||
if (pm->ps->stats[STAT_CLIPS] > 0)
|
||||
{
|
||||
Com_Printf("Sending event from continuous fast-reloads\n");
|
||||
PM_AddEvent(EV_RELOAD_WEAPON2);
|
||||
}
|
||||
else
|
||||
{
|
||||
Com_Printf("Negative event prevented\n");
|
||||
pm->ps->stats[STAT_RELOADATTEMPTS] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Com_Printf("============= Locked out in continuous fast-reloads\n");
|
||||
}
|
||||
|
||||
// finishing up fast reloads
|
||||
if ((pm->ps->stats[STAT_RQ3] & RQ3_FASTRELOADS) &&
|
||||
pm->ps->stats[STAT_RELOADATTEMPTS] == 0)
|
||||
{
|
||||
//Com_Printf("Fast-reload cycle ending\n");
|
||||
if (pm->ps->weapon == WP_M3)
|
||||
pm->ps->stats[STAT_RELOADTIME] += RQ3_M3_FINISH_RELOAD_DELAY;
|
||||
else
|
||||
pm->ps->stats[STAT_RELOADTIME] += RQ3_SSG3000_FINISH_RELOAD_DELAY;
|
||||
|
||||
pm->ps->stats[STAT_RQ3] &= ~RQ3_FASTRELOADS;
|
||||
// lock fast-reloads during finish delay
|
||||
pm->ps->stats[STAT_RQ3] |= RQ3_LOCKRELOADS;
|
||||
Com_Printf("<<<<<<<<<<<<< Locking\n");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// normal reload case
|
||||
//else
|
||||
//{
|
||||
// unlock
|
||||
if (pm->ps->stats[STAT_RQ3] & RQ3_LOCKRELOADS)
|
||||
{
|
||||
Com_Printf(">>>>>>>>>>>>> Unlocking\n");
|
||||
pm->ps->stats[STAT_RQ3] &= ~RQ3_LOCKRELOADS;
|
||||
}
|
||||
else
|
||||
{
|
||||
Com_Printf("Sending event from normal reload\n");
|
||||
PM_AddEvent(EV_RELOAD_WEAPON2);
|
||||
}
|
||||
|
||||
//Com_Printf("Finished reload\n");
|
||||
pm->ps->stats[STAT_RELOADTIME] = 0;
|
||||
pm->ps->stats[STAT_RELOADATTEMPTS] = 0;
|
||||
pm->ps->weaponstate = WEAPON_READY;
|
||||
//}
|
||||
|
||||
} // end finish reload
|
||||
|
||||
} // end in-progress reload
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
==============
|
||||
PM_Weapon
|
||||
|
@ -2102,7 +2406,8 @@ static void PM_Weapon( void ) {
|
|||
(pm->ps->weapon == WP_PISTOL ||
|
||||
pm->ps->weapon == WP_M3 ||
|
||||
pm->ps->weapon == WP_HANDCANNON ||
|
||||
pm->ps->weapon == WP_SSG3000))
|
||||
pm->ps->weapon == WP_SSG3000 ||
|
||||
pm->ps->weapon == WP_M4))
|
||||
PM_ContinueWeaponAnim(WP_ANIM_IDLE);
|
||||
}
|
||||
}
|
||||
|
@ -2122,11 +2427,11 @@ static void PM_Weapon( void ) {
|
|||
pm->ps->stats[STAT_WEAPONS] &= ~( 1 << WP_GRENADE);
|
||||
}*/
|
||||
|
||||
|
||||
if ( pm->ps->weaponTime > 0 ) {
|
||||
// Elder: added STAT_RELOADTIME check
|
||||
if ( pm->ps->weaponTime > 0 || pm->ps->stats[STAT_RELOADTIME] > 0) {
|
||||
return;
|
||||
}
|
||||
//Com_Printf("Weaponstate (%d)\n", pm->ps->weaponstate);
|
||||
|
||||
|
||||
// change weapon if time
|
||||
if ( pm->ps->weaponstate == WEAPON_DROPPING ) {
|
||||
|
@ -2148,7 +2453,8 @@ static void PM_Weapon( void ) {
|
|||
if (pm->ps->weapon == WP_PISTOL ||
|
||||
pm->ps->weapon == WP_M3 ||
|
||||
pm->ps->weapon == WP_HANDCANNON ||
|
||||
pm->ps->weapon == WP_SSG3000)
|
||||
pm->ps->weapon == WP_SSG3000 ||
|
||||
pm->ps->weapon == WP_M4)
|
||||
PM_StartWeaponAnim( WP_ANIM_IDLE );
|
||||
return;
|
||||
}
|
||||
|
@ -2233,10 +2539,12 @@ static void PM_Weapon( void ) {
|
|||
// QUARANTINE - Weapon animations
|
||||
// This should change pm->ps->generic1 so we can animate
|
||||
// Elder: don't repeat if on semi-auto
|
||||
// temp hack
|
||||
if (pm->ps->weapon == WP_PISTOL ||
|
||||
pm->ps->weapon == WP_M3 ||
|
||||
pm->ps->weapon == WP_HANDCANNON ||
|
||||
pm->ps->weapon == WP_SSG3000)
|
||||
pm->ps->weapon == WP_SSG3000 ||
|
||||
pm->ps->weapon == WP_M4)
|
||||
PM_StartWeaponAnim( WP_ANIM_FIRE );
|
||||
}
|
||||
}
|
||||
|
@ -2293,7 +2601,7 @@ static void PM_Weapon( void ) {
|
|||
//Elder: remove one more bullet/shell if handcannon/akimbo
|
||||
else if (pm->ps->weapon == WP_HANDCANNON)
|
||||
{
|
||||
pm->ps->ammo[ pm->ps->weapon ]--;
|
||||
pm->ps->ammo[ WP_HANDCANNON ]--;
|
||||
}
|
||||
//Elder: take away an extra bullet if available - handled in g_weapon.c as well
|
||||
else if (pm->ps->weapon == WP_AKIMBO && pm->ps->ammo[ WP_AKIMBO ] > 0) {
|
||||
|
@ -2301,7 +2609,7 @@ static void PM_Weapon( void ) {
|
|||
}
|
||||
|
||||
//Elder: sync bullets a la AQ2 style
|
||||
if (pm->ps->weapon == WP_AKIMBO && pm->ps->ammo[pm->ps->weapon] < 12) {
|
||||
if (pm->ps->weapon == WP_AKIMBO && pm->ps->ammo[WP_AKIMBO] < 12) {
|
||||
pm->ps->ammo[WP_PISTOL] = pm->ps->ammo[WP_AKIMBO];
|
||||
}
|
||||
else if (pm->ps->weapon == WP_PISTOL && pm->ps->ammo[WP_AKIMBO] > 0) {
|
||||
|
@ -2538,8 +2846,42 @@ static void PM_LadderMove( void ) {
|
|||
vec3_t lookAhead;
|
||||
vec3_t trEndTest;
|
||||
|
||||
// New experimental jump code -- not too good
|
||||
#if 0
|
||||
// Elder: ladder jump crap
|
||||
lookAhead[0] = pml.forward[0];
|
||||
lookAhead[1] = pml.forward[1];
|
||||
lookAhead[2] = 0;
|
||||
VectorNormalize (lookAhead);
|
||||
// Calculate end point
|
||||
VectorMA (pm->ps->origin, 1, lookAhead, trEndTest);
|
||||
//trEndTest[2] += 20;
|
||||
trEndTest[2] += 6;
|
||||
// Calculate start point
|
||||
VectorCopy(pm->ps->origin, lookAhead);
|
||||
//lookAhead[2] += 16;
|
||||
lookAhead[2] += 2;
|
||||
|
||||
pm->trace (&tr, lookAhead, pm->mins, pm->maxs, trEndTest,
|
||||
pm->ps->clientNum, MASK_PLAYERSOLID);
|
||||
|
||||
if (tr.fraction == 1 || !(tr.surfaceFlags & SURF_LADDER))
|
||||
{
|
||||
// good conditions -- now we can set up a double jump on the ladder
|
||||
if (pm->debugLevel)
|
||||
Com_Printf("Ladder jump conditions met...\n");
|
||||
if (pm->ps->stats[STAT_JUMPTIME] > 0 && PM_CheckJump())
|
||||
{
|
||||
if (pm->debugLevel)
|
||||
Com_Printf("Trying ladder jump...\n");
|
||||
pml.ladder = qfalse;
|
||||
}
|
||||
}
|
||||
// End ladder jump crap
|
||||
#endif
|
||||
|
||||
PM_Friction ();
|
||||
//pml.ladder = qtrue;
|
||||
|
||||
scale = PM_CmdScale( &pm->cmd );
|
||||
|
||||
|
@ -2566,6 +2908,8 @@ static void PM_LadderMove( void ) {
|
|||
wishspeed = pm->ps->speed * pm_ladderScale;
|
||||
}
|
||||
|
||||
// Old ladder jump code -- right now it works better
|
||||
#if 1
|
||||
// Elder: ladder jump crap
|
||||
lookAhead[0] = pml.forward[0];
|
||||
lookAhead[1] = pml.forward[1];
|
||||
|
@ -2589,11 +2933,12 @@ static void PM_LadderMove( void ) {
|
|||
if (PM_CheckJump())
|
||||
{
|
||||
if (pm->debugLevel)
|
||||
Com_Printf("Trying airmove ladder jump...\n");
|
||||
Com_Printf("Trying ladder jump...\n");
|
||||
}
|
||||
}
|
||||
// End ladder jump crap
|
||||
|
||||
#endif
|
||||
|
||||
PM_Accelerate (wishdir, wishspeed, pm_ladderAccelerate);
|
||||
|
||||
// This SHOULD help us with sloped ladders, but it remains untested.
|
||||
|
@ -2610,7 +2955,7 @@ static void PM_LadderMove( void ) {
|
|||
|
||||
PM_SlideMove( qfalse ); // move without gravity
|
||||
// Elder: stop legs from animating
|
||||
PM_ForceLegsAnim( LEGS_IDLE );
|
||||
PM_ForceLegsAnim( LEGS_JUMP );
|
||||
}
|
||||
|
||||
|
||||
|
@ -2648,8 +2993,12 @@ void CheckLadder( void )
|
|||
pml.ladder = qtrue;
|
||||
|
||||
// Elder: does this work?
|
||||
if (pml.ladder && pml.previous_ladder)
|
||||
if (pml.ladder && pml.previous_ladder == qfalse)
|
||||
{
|
||||
if (pm->debugLevel)
|
||||
Com_Printf("Hit ladder hard\n");
|
||||
PM_CrashLand();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -2847,6 +3196,7 @@ void PmoveSingle (pmove_t *pmove) {
|
|||
PM_SetWaterLevel();
|
||||
|
||||
// weapons
|
||||
PM_Reload();
|
||||
PM_Weapon();
|
||||
|
||||
//weapon animations(rq3 specific)
|
||||
|
@ -2854,7 +3204,8 @@ void PmoveSingle (pmove_t *pmove) {
|
|||
if (pm->ps->weapon == WP_PISTOL ||
|
||||
pm->ps->weapon == WP_M3 ||
|
||||
pm->ps->weapon == WP_HANDCANNON ||
|
||||
pm->ps->weapon == WP_SSG3000)
|
||||
pm->ps->weapon == WP_SSG3000 ||
|
||||
pm->ps->weapon == WP_M4)
|
||||
PM_WeaponAnimation();
|
||||
|
||||
// torso animation
|
||||
|
|
|
@ -388,6 +388,8 @@ typedef enum {
|
|||
WP_ANIM_DISARM,
|
||||
WP_ANIM_ACTIVATE,
|
||||
//WP_ANIM_EMPTY,
|
||||
//WP_ANIM_EXTRA1,
|
||||
//WP_ANIM_EXTRA2,
|
||||
MAX_WEAPON_ANIMATIONS
|
||||
} wpAnimNumber_t;
|
||||
|
||||
|
@ -405,6 +407,7 @@ typedef enum {
|
|||
#define PMF_FOLLOW 4096 // spectate following another player
|
||||
#define PMF_SCOREBOARD 8192 // spectate as a scoreboard
|
||||
#define PMF_INVULEXPAND 16384 // invulnerability sphere set to full size
|
||||
#define PMF_RELOAD_HELD 32768 // Elder: new reload code
|
||||
|
||||
#define PMF_ALL_TIMES (PMF_TIME_WATERJUMP|PMF_TIME_LAND|PMF_TIME_KNOCKBACK)
|
||||
|
||||
|
@ -460,7 +463,7 @@ typedef enum {
|
|||
STAT_PERSISTANT_POWERUP,
|
||||
#endif
|
||||
STAT_WEAPONS, // 16 bit fields
|
||||
STAT_ARMOR, // Elder: technically we don't need this anymore - maybe for vest
|
||||
STAT_ARMOR, // Elder: technically we don't need this anymore
|
||||
STAT_DEAD_YAW, // look this direction when dead (FIXME: get rid of?)
|
||||
|
||||
|
||||
|
@ -469,22 +472,28 @@ typedef enum {
|
|||
|
||||
//These are RQ3-related specific stats
|
||||
STAT_CLIPS, // Num Clips player currently has
|
||||
STAT_STREAK,
|
||||
STAT_BURST, // number of shots in burst
|
||||
STAT_JUMPTIME, // Blaze RE: Double jump
|
||||
//STAT_UNIQUEWEAPONS, // Elder - wasteful stat - moved to gclient_s
|
||||
STAT_JUMPTIME, // Blaze: Double jump
|
||||
STAT_RELOADTIME, // Elder: Reload sound triggering and weapon switch override
|
||||
STAT_RELOADATTEMPTS, // Elder: For fast-reload queuing
|
||||
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
|
||||
//STAT_STREAK, // Elder: wasteful stat -- only used on server-side ATM
|
||||
} statIndex_t;
|
||||
|
||||
//STAT_RQ3 stat info
|
||||
#define RQ3_LEGDAMAGE 1 //If this bit is set, the player has leg damage
|
||||
#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
|
||||
// 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
|
||||
#define RQ3_THROWWEAPON 32 //Present if dropping weapon via cmd or kicked away
|
||||
#define RQ3_THROWWEAPON 32 // Present if dropping weapon via cmd or kicked away
|
||||
#define RQ3_FASTRELOADS 64 // Fast-reloads flag
|
||||
#define RQ3_LOCKRELOADS 128 // Lock-reloads at end of fast-reload cycle
|
||||
// Elder: reload status; 0 + 1 = stage 2
|
||||
//#define RQ3_RELOADSTAGE0 256
|
||||
//#define RQ3_RELOADSTAGE1 512
|
||||
|
||||
|
||||
// player_state->persistant[] indexes
|
||||
|
@ -525,6 +534,7 @@ typedef enum {
|
|||
#ifdef MISSIONPACK
|
||||
#define EF_TICKING 0x00000002 // used to make players play the prox mine ticking sound
|
||||
#endif
|
||||
#define EF_HANDCANNON_SMOKED 0x00000002 // Elder: HC Smoke
|
||||
#define EF_TELEPORT_BIT 0x00000004 // toggled every time the origin abruptly changes
|
||||
#define EF_AWARD_EXCELLENT 0x00000008 // draw an excellent sprite
|
||||
#define EF_PLAYER_EVENT 0x00000010
|
||||
|
@ -560,6 +570,7 @@ typedef enum {
|
|||
PW_BLUEFLAG,
|
||||
PW_NEUTRALFLAG,
|
||||
|
||||
|
||||
PW_SCOUT,
|
||||
PW_GUARD,
|
||||
PW_DOUBLER,
|
||||
|
@ -612,20 +623,78 @@ typedef enum {
|
|||
WP_NUM_WEAPONS
|
||||
} weapon_t;
|
||||
|
||||
|
||||
// Elder: for our end-level awards later on
|
||||
// I was just brainstorming a whole bunch of necessary records
|
||||
// This should probably be defined in g_local.h because it
|
||||
// will almost be exclusively for the server to utilize
|
||||
// We can send config strings to the individual players
|
||||
// for their own review and the global config string would
|
||||
// contain the global ones with rewards
|
||||
typedef enum {
|
||||
RECORD_HEADSHOTS,
|
||||
RECORD_CHESTSHOTS,
|
||||
RECORD_STOMACHSHOTS,
|
||||
RECORD_LEGSHOTS,
|
||||
RECORD_FALLINGDEATHS,
|
||||
RECORD_CAMPCOUNT,
|
||||
RECORD_JUMPCOUNT, // e.g. rabbit or monkey award
|
||||
RECORD_SUICIDES, // e.g. for MPELP award
|
||||
RECORD_STEALTHKILLS,
|
||||
RECORD_FRAGSTEALS,
|
||||
|
||||
RECORD_TOTAL
|
||||
// Location-hit tally - Where this player shot at
|
||||
REC_HEADSHOTS,
|
||||
REC_CHESTSHOTS,
|
||||
REC_STOMACHSHOTS,
|
||||
REC_LEGSHOTS,
|
||||
REC_FRONTSHOTS,
|
||||
REC_BACKSHOTS,
|
||||
REC_LEFTSHOTS,
|
||||
REC_RIGHTSHOTS,
|
||||
REC_CORPSESHOTS, // sickos - takes precedence over above records on carcasses
|
||||
REC_GIBSHOTS, // sickos - takes precedence over above records on carcasses
|
||||
// Weapon usage tally
|
||||
REC_MP5SHOTS,
|
||||
REC_M4SHOTS,
|
||||
REC_MK23SHOTS,
|
||||
REC_SSG3000SHOTS,
|
||||
REC_HANDCANNONSHOTS,
|
||||
REC_M3SHOTS,
|
||||
REC_AKIMBOSHOTS,
|
||||
REC_GRENADESHOTS,
|
||||
REC_KNIFETHROWSHOTS,
|
||||
REC_KNIFESLASHSHOTS,
|
||||
REC_MK23HITS,
|
||||
REC_M3HITS,
|
||||
REC_MP5HITS,
|
||||
REC_M4HITS,
|
||||
REC_SSG3000HITS,
|
||||
REC_HANDCANNONHITS,
|
||||
REC_AKIMBOHITS,
|
||||
REC_GRENADEHITS,
|
||||
REC_KNIFETHROWHITS,
|
||||
REC_KNIFESLASHHITS,
|
||||
REC_KICKHITS,
|
||||
// Death tally
|
||||
REC_HEADDEATHS,
|
||||
REC_CHESTDEATHS,
|
||||
REC_STOMACHDEATHS,
|
||||
REC_LEGDEATHS,
|
||||
REC_MK23DEATHS,
|
||||
REC_M3DEATHS,
|
||||
REC_MP5DEATHS,
|
||||
REC_M4DEATHS,
|
||||
REC_SSG3000DEATHS,
|
||||
REC_HANDCANNONDEATHS,
|
||||
REC_AKIMBODEATHS,
|
||||
REC_GRENADEDEATHS,
|
||||
REC_KNIFETHROWDEATHS,
|
||||
REC_KNIFESLASHDEATHS,
|
||||
REC_BLEEDDEATHS,
|
||||
REC_FALLINGDEATHS,
|
||||
REC_SUICIDES, // e.g. for MPELP award, those loonies :)
|
||||
REC_WORLDDEATHS, // crushers, doors, etc.
|
||||
REC_STEALTHKILLS, // this is a derived record -- remove?
|
||||
// Movement tally - dunno about these ones since they are related to pmove
|
||||
REC_CAMPCOUNT,
|
||||
REC_CROUCHCOUNT,
|
||||
REC_JUMPCOUNT, // e.g. rabbit or monkey award
|
||||
// Player interaction tally
|
||||
REC_FRAGSTEALS, // this is a derived record -- remove?
|
||||
REC_CHATCOUNT,
|
||||
REC_GESTURECOUNT,
|
||||
|
||||
REC_NUM_RECORDS
|
||||
} rq3record_t;
|
||||
|
||||
|
||||
|
@ -696,7 +765,9 @@ typedef enum {
|
|||
EV_NOAMMO,
|
||||
EV_CHANGE_WEAPON,
|
||||
EV_FIRE_WEAPON,
|
||||
EV_RELOAD_WEAPON, // Elder: reload weapon sounds
|
||||
EV_RELOAD_WEAPON0, // Elder: reload weapon sounds
|
||||
EV_RELOAD_WEAPON1, // Elder: reload weapon sounds
|
||||
EV_RELOAD_WEAPON2, // Elder: reload weapon sounds
|
||||
|
||||
EV_USE_ITEM0,
|
||||
EV_USE_ITEM1,
|
||||
|
@ -731,6 +802,8 @@ typedef enum {
|
|||
|
||||
EV_BULLET_HIT_FLESH,
|
||||
EV_BULLET_HIT_WALL,
|
||||
EV_BULLET_HIT_METAL, // Elder: sparks
|
||||
EV_BULLET_HIT_KEVLAR, // Elder: sparks
|
||||
EV_SSG3000_HIT_FLESH,
|
||||
EV_JUMPKICK, // Elder: sound + jumpkick message
|
||||
|
||||
|
|
|
@ -152,6 +152,21 @@ void P_DamageFeedback( gentity_t *player ) {
|
|||
|
||||
client->ps.damageCount = count;
|
||||
|
||||
// Elder: HC Smoke
|
||||
/*
|
||||
if (client->lasthurt_mod == MOD_HANDCANNON)
|
||||
{
|
||||
G_Printf("Feedback: damage_blood: %i, damage_knockback: %i\n",
|
||||
client->damage_blood, client->damage_knockback);
|
||||
}
|
||||
*/
|
||||
if (client->lasthurt_mod == MOD_HANDCANNON &&
|
||||
client->damage_blood >= 120 &&
|
||||
client->damage_knockback >= RQ3_HANDCANNON_KICK * 6)
|
||||
{
|
||||
client->ps.eFlags |= EF_HANDCANNON_SMOKED;
|
||||
}
|
||||
|
||||
//
|
||||
// clear totals
|
||||
//
|
||||
|
@ -698,7 +713,18 @@ void ClientEvents( gentity_t *ent, int oldEventSequence ) {
|
|||
case EV_FIRE_WEAPON:
|
||||
FireWeapon( ent );
|
||||
break;
|
||||
|
||||
/*
|
||||
case EV_RELOAD_WEAPON0:
|
||||
ReloadWeapon ( ent, 0 );
|
||||
break;
|
||||
case EV_RELOAD_WEAPON1:
|
||||
ReloadWeapon ( ent, 1 );
|
||||
break;
|
||||
*/
|
||||
case EV_RELOAD_WEAPON2:
|
||||
ReloadWeapon ( ent, 2 );
|
||||
break;
|
||||
|
||||
case EV_CHANGE_WEAPON:
|
||||
//Elder: not a good place to put stuff
|
||||
//ent->client->zoomed=0;
|
||||
|
@ -1613,15 +1639,13 @@ void ClientEndFrame( gentity_t *ent ) {
|
|||
} else {
|
||||
ent->s.eFlags &= ~EF_CONNECTION;
|
||||
}
|
||||
// Blaze: Do Bleed
|
||||
// if(ent->client->bleeding)
|
||||
// CheckBleeding(ent); // perform once-a-second actions
|
||||
|
||||
//Elder: moved unique item spawning to new function called RQ3_CheckUniqueItems
|
||||
|
||||
|
||||
|
||||
// Begin Duffman
|
||||
//Update the clips Amount in weapon for the client
|
||||
// Update the clips Amount in weapon for the client
|
||||
// Elder: the STAT takes precedence over the server-side only listing
|
||||
ent->client->ps.stats[STAT_CLIPS] = ent->client->numClips[ent->client->ps.weapon];
|
||||
|
||||
// End Duffman
|
||||
ent->client->ps.stats[STAT_HEALTH] = ent->health; // FIXME: get rid of ent->health...
|
||||
|
||||
|
|
|
@ -1228,7 +1228,7 @@ void ClientSpawn(gentity_t *ent) {
|
|||
// health will count down towards max_health
|
||||
ent->health = client->ps.stats[STAT_HEALTH] = 100;// max health of 100 client->ps.stats[STAT_MAX_HEALTH];//Blaze: removed * 1.25 becase we wanna start at 100 health
|
||||
// reset streak count
|
||||
client->ps.stats[STAT_STREAK] = 0;
|
||||
client->killStreak = 0;
|
||||
G_SetOrigin( ent, spawn_origin );
|
||||
VectorCopy( spawn_origin, client->ps.origin );
|
||||
|
||||
|
|
|
@ -1680,7 +1680,8 @@ void Cmd_Bandage (gentity_t *ent)
|
|||
if (ent->client->ps.weapon == WP_PISTOL ||
|
||||
ent->client->ps.weapon == WP_M3 ||
|
||||
ent->client->ps.weapon == WP_HANDCANNON ||
|
||||
ent->client->ps.weapon == WP_SSG3000)
|
||||
ent->client->ps.weapon == WP_SSG3000 ||
|
||||
ent->client->ps.weapon == WP_M4)
|
||||
{
|
||||
ent->client->ps.generic1 = ( ( ent->client->ps.generic1 & ANIM_TOGGLEBIT )
|
||||
^ ANIM_TOGGLEBIT ) | WP_ANIM_DISARM;
|
||||
|
@ -2021,7 +2022,9 @@ void Cmd_Reload( gentity_t *ent )
|
|||
^ ANIM_TOGGLEBIT ) | TORSO_DROP;
|
||||
//}
|
||||
|
||||
ent->client->ps.weaponTime += delay;
|
||||
// Elder: handled in pmove now
|
||||
// ent->client->ps.weaponTime += delay;
|
||||
|
||||
|
||||
//Elder: at this point there should be sufficient ammo requirements to reload
|
||||
if (ent->client->numClips[weapon] > 0) {
|
||||
|
@ -2150,8 +2153,8 @@ void Cmd_Weapon(gentity_t *ent)
|
|||
return;
|
||||
}
|
||||
|
||||
//Can't reload while firing
|
||||
if ( ent->client->ps.weaponTime > 0)
|
||||
//Can't use weapon while firing
|
||||
if ( ent->client->ps.weaponTime > 0 || ent->client->ps.stats[STAT_RELOADTIME] > 0)
|
||||
return;
|
||||
|
||||
//Elder: added brackets, and-ops and not-ops instead of logical ops
|
||||
|
@ -2513,10 +2516,10 @@ void ClientCommand( int clientNum ) {
|
|||
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++;
|
||||
//if (ent->client->ps.weapon == WP_M3 || ent->client->ps.weapon == WP_SSG3000)
|
||||
//ent->client->reloadAttempts++;
|
||||
//G_Printf("Trying a reload...\n");
|
||||
Cmd_Reload( ent );
|
||||
//Cmd_Reload( ent );
|
||||
}
|
||||
// End Duffman
|
||||
//Blaze's Open door command
|
||||
|
|
|
@ -541,7 +541,7 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
|
|||
//Elder: added;
|
||||
self->client->ps.stats[STAT_RQ3] &= ~RQ3_BANDAGE_WORK;
|
||||
self->client->ps.stats[STAT_RQ3] &= ~RQ3_BANDAGE_NEED;
|
||||
self->client->ps.stats[STAT_STREAK] = 0;
|
||||
self->client->killStreak = 0;
|
||||
|
||||
//Elder: stop reload attempts
|
||||
self->client->reloadAttempts = 0;
|
||||
|
@ -631,37 +631,37 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
|
|||
AddScore( attacker, self->r.currentOrigin, -1 );
|
||||
} else {
|
||||
// Increase number of kills this life for attacker
|
||||
attacker->client->ps.stats[STAT_STREAK]++;
|
||||
attacker->client->killStreak++;
|
||||
// DM reward scoring, should add an if statement to get around this when
|
||||
// we add teamplay.
|
||||
if (attacker->client->ps.stats[STAT_STREAK] < 4)
|
||||
if (attacker->client->killStreak < 4)
|
||||
AddScore( attacker, self->r.currentOrigin, 1 );
|
||||
else if (attacker->client->ps.stats[STAT_STREAK] < 8)
|
||||
else if (attacker->client->killStreak < 8)
|
||||
{ AddScore( attacker, self->r.currentOrigin, 2 );
|
||||
DMReward = G_TempEntity(self->r.currentOrigin ,EV_DMREWARD);
|
||||
DMReward->s.otherEntityNum2 = killer;
|
||||
DMReward->s.eventParm = attacker->client->ps.stats[STAT_STREAK];
|
||||
DMReward->s.eventParm = attacker->client->killStreak;
|
||||
DMReward->r.svFlags = SVF_BROADCAST;
|
||||
}
|
||||
else if (attacker->client->ps.stats[STAT_STREAK] < 16)
|
||||
else if (attacker->client->killStreak < 16)
|
||||
{ AddScore( attacker, self->r.currentOrigin, 4 );
|
||||
DMReward = G_TempEntity(self->r.currentOrigin ,EV_DMREWARD);
|
||||
DMReward->s.otherEntityNum2 = killer;
|
||||
DMReward->s.eventParm = attacker->client->ps.stats[STAT_STREAK];
|
||||
DMReward->s.eventParm = attacker->client->killStreak;
|
||||
DMReward->r.svFlags = SVF_BROADCAST;
|
||||
}
|
||||
else if (attacker->client->ps.stats[STAT_STREAK] < 32)
|
||||
else if (attacker->client->killStreak < 32)
|
||||
{ AddScore( attacker, self->r.currentOrigin, 8 );
|
||||
DMReward = G_TempEntity(self->r.currentOrigin ,EV_DMREWARD);
|
||||
DMReward->s.otherEntityNum2 = killer;
|
||||
DMReward->s.eventParm = attacker->client->ps.stats[STAT_STREAK];
|
||||
DMReward->s.eventParm = attacker->client->killStreak;
|
||||
DMReward->r.svFlags = SVF_BROADCAST;
|
||||
}
|
||||
else
|
||||
{ AddScore( attacker, self->r.currentOrigin, 16 );
|
||||
DMReward = G_TempEntity(self->r.currentOrigin ,EV_DMREWARD);
|
||||
DMReward->s.otherEntityNum2 = killer;
|
||||
DMReward->s.eventParm = attacker->client->ps.stats[STAT_STREAK];
|
||||
DMReward->s.eventParm = attacker->client->killStreak;
|
||||
DMReward->r.svFlags = SVF_BROADCAST;
|
||||
}
|
||||
|
||||
|
@ -681,7 +681,7 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
|
|||
|
||||
self->client->ps.persistant[PERS_PLAYEREVENTS] ^= PLAYEREVENT_GAUNTLETREWARD;
|
||||
}
|
||||
|
||||
|
||||
// check for two kills in a short amount of time
|
||||
// if this is close enough to the last kill, give a reward sound
|
||||
if ( level.time - attacker->client->lastKillTime < CARNAGE_REWARD_TIME ) {
|
||||
|
@ -801,6 +801,17 @@ void player_die( gentity_t *self, gentity_t *inflictor, gentity_t *attacker, int
|
|||
|
||||
self->s.weapon = WP_NONE;
|
||||
self->s.powerups = 0;
|
||||
|
||||
|
||||
// Elder: HC smoke
|
||||
//G_Printf("player_die: damage_knockback: %i\n", self->client->damage_knockback);
|
||||
if (meansOfDeath == MOD_HANDCANNON && self->client->damage_knockback > RQ3_HANDCANNON_KICK * 4) //self->client->ps.stats[STAT_HEALTH] < -50)
|
||||
{
|
||||
//G_Printf("Smoked\n");
|
||||
self->client->ps.eFlags |= EF_HANDCANNON_SMOKED;
|
||||
}
|
||||
|
||||
|
||||
self->r.contents = CONTENTS_CORPSE;
|
||||
|
||||
self->s.angles[0] = 0;
|
||||
|
@ -1697,6 +1708,7 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
|
|||
//Vest stuff - is the knife supposed to be affected?
|
||||
if (bg_itemlist[targ->client->ps.stats[STAT_HOLDABLE_ITEM]].giTag == HI_KEVLAR)
|
||||
{
|
||||
targ->client->kevlarHit = qtrue;
|
||||
//if ((attacker->client->ps.stats[STAT_WEAPONS] & (1 << WP_SSG3000)) == (1 << WP_SSG3000))
|
||||
if (attacker->client->ps.weapon == WP_SSG3000)
|
||||
{
|
||||
|
@ -1717,7 +1729,11 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
|
|||
}
|
||||
//Kevlar sound
|
||||
if (mod != MOD_KNIFE && mod != MOD_KNIFE_THROWN)
|
||||
tent = G_TempEntity2(targ->s.pos.trBase, EV_RQ3_SOUND, RQ3_SOUND_KEVLARHIT);
|
||||
{
|
||||
tent = G_TempEntity(targ->s.pos.trBase, EV_BULLET_HIT_KEVLAR);
|
||||
tent->s.eventParm = DirToByte(dir);
|
||||
//tent = G_TempEntity2(targ->s.pos.trBase, EV_RQ3_SOUND, RQ3_SOUND_KEVLARHIT);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1792,6 +1808,7 @@ void G_Damage( gentity_t *targ, gentity_t *inflictor, gentity_t *attacker,
|
|||
//if ( client ) {
|
||||
//targ->flags |= FL_NO_KNOCKBACK;
|
||||
//}
|
||||
|
||||
if (targ->health < -999) {
|
||||
targ->health = -999;
|
||||
}
|
||||
|
|
|
@ -202,12 +202,9 @@ int Pickup_Holdable( gentity_t *ent, gentity_t *other ) {
|
|||
|
||||
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)
|
||||
{
|
||||
|
@ -1301,6 +1298,8 @@ void G_SpawnItem (gentity_t *ent, gitem_t *item) {
|
|||
G_SpawnFloat( "random", "0", &ent->random );
|
||||
G_SpawnFloat( "wait", "0", &ent->wait );
|
||||
|
||||
//TODO: check spawn angles; client-side should make use of them too
|
||||
|
||||
RegisterItem( item );
|
||||
if ( G_ItemDisabled(item) )
|
||||
return;
|
||||
|
|
|
@ -335,6 +335,7 @@ struct gclient_s {
|
|||
int accuracy_hits; // total number of hits
|
||||
//Blaze: For weapon stats
|
||||
//Will need to pass these along in g_client to the new client after spawn
|
||||
// Elder: to be merged into rq3Record_t for more comprehensive tracking
|
||||
int knifeShots;
|
||||
int knifeHits;
|
||||
int mk23Shots;
|
||||
|
@ -410,6 +411,7 @@ struct gclient_s {
|
|||
int weaponfireNextTime; // for akimbos
|
||||
int lastzoom; // Elder: save last zoom state when firing
|
||||
|
||||
// These are now obsolete with the new reload code
|
||||
int fastReloads; // Elder: for queuing M3/SSG reloads
|
||||
int lastReloadTime; // Elder: for queuing M3/SSG reloads
|
||||
int reloadAttempts; // Elder: for queuing M3/SSG reloads
|
||||
|
@ -418,6 +420,8 @@ struct gclient_s {
|
|||
int consecutiveShots; // Elder: for M4 ride-up/kick
|
||||
int uniqueWeapons; // Elder: formerly a stat, now just a server var
|
||||
int uniqueItems;
|
||||
int killStreak; // Elder: replaces the old STAT_STREAK
|
||||
qboolean kevlarHit; // Elder: kevlar hit -- FIXME: poor implementation
|
||||
//int records[RECORD_TOTAL]; // Elder: for our awards when we implement it
|
||||
|
||||
|
||||
|
@ -758,6 +762,7 @@ qboolean G_FilterPacket (char *from);
|
|||
// g_weapon.c
|
||||
//
|
||||
void FireWeapon( gentity_t *ent );
|
||||
void ReloadWeapon ( gentity_t *ent, int stage ); // Elder: added
|
||||
#ifdef MISSIONPACK
|
||||
void G_StartKamikaze( gentity_t *ent );
|
||||
#endif
|
||||
|
|
|
@ -427,6 +427,9 @@ void G_MissileImpact( gentity_t *ent, trace_t *trace ) {
|
|||
//Elder: knife handling routines go HERE, not in g_main.c !!!
|
||||
if (ent->s.weapon == WP_KNIFE) {
|
||||
if ( other->takedamage && other->client) {
|
||||
// Elder: must add it in here if we remove it from above
|
||||
|
||||
G_Damage (other, ent, &g_entities[ent->r.ownerNum], velocity, ent->s.origin, THROW_DAMAGE, 0, MOD_KNIFE_THROWN);
|
||||
//hit a player - send the gurgle or embedding sound event
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -999,29 +999,45 @@ void Blocked_Door( gentity_t *ent, gentity_t *other ) {
|
|||
// remove anything other than a client
|
||||
if ( !other->client ) {
|
||||
// except CTF flags!!!!
|
||||
if( other->s.eType == ET_ITEM && other->item->giType == IT_TEAM ) {
|
||||
if ( other->s.eType == ET_ITEM && other->item->giType == IT_TEAM ) {
|
||||
Team_DroppedFlagThink( other );
|
||||
return;
|
||||
}
|
||||
// Elder: added to handle weapons in door paths -
|
||||
// later we'll need to handle items here too
|
||||
if( other->s.eType == ET_ITEM && other->item->giType == IT_WEAPON ) {
|
||||
switch ( other->item->giTag ) {
|
||||
case WP_MP5:
|
||||
case WP_M4:
|
||||
case WP_M3:
|
||||
case WP_HANDCANNON:
|
||||
case WP_SSG3000:
|
||||
RQ3_DroppedWeaponThink( other );
|
||||
return;
|
||||
case WP_GRENADE:
|
||||
case WP_PISTOL:
|
||||
case WP_KNIFE:
|
||||
case WP_AKIMBO:
|
||||
default:
|
||||
break;
|
||||
// Elder: added to handle items and weapons in door paths
|
||||
if ( other->s.eType == ET_ITEM && other->item->giType == IT_WEAPON)
|
||||
{
|
||||
switch ( other->item->giTag )
|
||||
{
|
||||
case WP_MP5:
|
||||
case WP_M4:
|
||||
case WP_M3:
|
||||
case WP_HANDCANNON:
|
||||
case WP_SSG3000:
|
||||
RQ3_DroppedWeaponThink( other );
|
||||
return;
|
||||
break;
|
||||
case WP_GRENADE:
|
||||
case WP_PISTOL:
|
||||
case WP_KNIFE:
|
||||
case WP_AKIMBO:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( other->s.eType == ET_ITEM && other->item->giType == IT_HOLDABLE) {
|
||||
switch ( other->item->giTag )
|
||||
{
|
||||
case HI_LASER:
|
||||
case HI_BANDOLIER:
|
||||
case HI_KEVLAR:
|
||||
case HI_SILENCER:
|
||||
case HI_SLIPPERS:
|
||||
RQ3_DroppedItemThink( other );
|
||||
return;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
G_TempEntity( other->s.origin, EV_ITEM_POP );
|
||||
G_FreeEntity( other );
|
||||
|
|
|
@ -326,7 +326,6 @@ void SnapVectorTowards( vec3_t v, vec3_t to ) {
|
|||
#define MACHINEGUN_DAMAGE 7
|
||||
#define MACHINEGUN_TEAM_DAMAGE 5 // wimpier MG in teamplay
|
||||
|
||||
|
||||
void Bullet_Fire (gentity_t *ent, float spread, int damage, int MOD ) {
|
||||
trace_t tr;
|
||||
vec3_t end;
|
||||
|
@ -392,8 +391,13 @@ void Bullet_Fire (gentity_t *ent, float spread, int damage, int MOD ) {
|
|||
|
||||
// send bullet impact
|
||||
if ( traceEnt->takedamage && traceEnt->client ) {
|
||||
tent = G_TempEntity( tr.endpos, EV_BULLET_HIT_FLESH );
|
||||
tent->s.eventParm = traceEnt->s.number;
|
||||
if (bg_itemlist[traceEnt->client->ps.stats[STAT_HOLDABLE_ITEM]].giTag != HI_KEVLAR)
|
||||
{
|
||||
tent = G_TempEntity( tr.endpos, EV_BULLET_HIT_FLESH );
|
||||
//tent->s.eventParm = traceEnt->s.number;
|
||||
tent->s.eventParm = DirToByte(forward);
|
||||
tent->s.otherEntityNum2 = traceEnt->s.number;
|
||||
}
|
||||
if( LogAccuracyHit( traceEnt, ent ) ) {
|
||||
ent->client->accuracy_hits++;
|
||||
switch (MOD)
|
||||
|
@ -418,6 +422,10 @@ void Bullet_Fire (gentity_t *ent, float spread, int damage, int MOD ) {
|
|||
//} else if ( tr.surfaceFlags & SURF_GRASS ) {
|
||||
//tent = G_TempEntity( tr.endpos, EV_BULLET_HIT_FLESH);
|
||||
//tent->s.eventParm = DirToByte( tr.plane.normal );
|
||||
} else if ( (tr.surfaceFlags & SURF_METALSTEPS) ||
|
||||
(tr.surfaceFlags & SURF_METAL2) ) {
|
||||
tent = G_TempEntity( tr.endpos, EV_BULLET_HIT_METAL );
|
||||
tent->s.eventParm = DirToByte( tr.plane.normal );
|
||||
} else {
|
||||
tent = G_TempEntity( tr.endpos, EV_BULLET_HIT_WALL );
|
||||
tent->s.eventParm = DirToByte( tr.plane.normal );
|
||||
|
@ -444,6 +452,19 @@ void Bullet_Fire (gentity_t *ent, float spread, int damage, int MOD ) {
|
|||
#endif
|
||||
G_Damage( traceEnt, ent, ent, forward, tr.endpos,
|
||||
damage, 0, MOD);
|
||||
|
||||
// FIXME: poor implementation
|
||||
if (traceEnt->client && bg_itemlist[traceEnt->client->ps.stats[STAT_HOLDABLE_ITEM]].giTag == HI_KEVLAR) {
|
||||
if (traceEnt->client->kevlarHit == qfalse) {
|
||||
tent = G_TempEntity( tr.endpos, EV_BULLET_HIT_FLESH );
|
||||
//tent->s.eventParm = traceEnt->s.number;
|
||||
tent->s.eventParm = DirToByte(forward);
|
||||
tent->s.otherEntityNum2 = traceEnt->s.number;
|
||||
}
|
||||
else
|
||||
traceEnt->client->kevlarHit = qfalse;
|
||||
}
|
||||
|
||||
#ifdef MISSIONPACK
|
||||
}
|
||||
#endif
|
||||
|
@ -1431,13 +1452,15 @@ void Weapon_SSG3000_Fire (gentity_t *ent) {
|
|||
|
||||
traceEnt = &g_entities[ trace.entityNum ];
|
||||
|
||||
if ( traceEnt->takedamage ) {
|
||||
if ( traceEnt->takedamage )
|
||||
{
|
||||
//G_Printf("(%d) SSG: hit damagable entity\n", level.time);
|
||||
|
||||
//flag hitBreakable - bullets go through even
|
||||
//if it doesn't "shatter" - but that's usually
|
||||
//not the case
|
||||
if ( traceEnt->s.eType == ET_BREAKABLE ) {
|
||||
if ( traceEnt->s.eType == ET_BREAKABLE )
|
||||
{
|
||||
//G_Printf("(%d) SSG: Hit a breakable\n", level.time);
|
||||
hitBreakable = qtrue;
|
||||
}
|
||||
|
@ -1445,29 +1468,51 @@ void Weapon_SSG3000_Fire (gentity_t *ent) {
|
|||
// send impacts
|
||||
if ( traceEnt->client )
|
||||
{
|
||||
//if (bg_itemlist[traceEnt->client->ps.stats[STAT_HOLDABLE_ITEM]].giTag != HI_KEVLAR)
|
||||
//{
|
||||
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;
|
||||
//Check to see if we've hit kevlar
|
||||
tent[unlinked]->s.eventParm = DirToByte( forward );
|
||||
tent[unlinked]->s.otherEntityNum2 = traceEnt->s.number;
|
||||
tent[unlinked]->s.otherEntityNum = ent->s.number;
|
||||
//}
|
||||
//tent[unlinked]->s.eventParm = traceEnt->s.number;
|
||||
//Check to see if we've hit kevlar -- FIXME: wrong way to do it
|
||||
if (bg_itemlist[traceEnt->client->ps.stats[STAT_HOLDABLE_ITEM]].giTag == HI_KEVLAR)
|
||||
hitKevlar = qtrue;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
tent[unlinked] = G_TempEntity( trace.endpos, EV_BULLET_HIT_WALL );
|
||||
tent[unlinked]->s.eventParm = DirToByte( trace.plane.normal );
|
||||
}
|
||||
tent[unlinked]->s.otherEntityNum = ent->s.number;
|
||||
// impact type
|
||||
if ( (trace.surfaceFlags & SURF_METALSTEPS) ||
|
||||
(trace.surfaceFlags & SURF_METAL2) )
|
||||
tent[unlinked] = G_TempEntity( trace.endpos, EV_BULLET_HIT_METAL );
|
||||
else
|
||||
tent[unlinked] = G_TempEntity( trace.endpos, EV_BULLET_HIT_WALL );
|
||||
|
||||
if( LogAccuracyHit( traceEnt, ent ) ) {
|
||||
tent[unlinked]->s.eventParm = DirToByte( trace.plane.normal );
|
||||
tent[unlinked]->s.otherEntityNum = ent->s.number;
|
||||
}
|
||||
|
||||
if( LogAccuracyHit( traceEnt, ent ) )
|
||||
{
|
||||
hits++;
|
||||
}
|
||||
|
||||
//G_Printf("(%d) SSG: Doing damage to target\n", level.time);
|
||||
G_Damage (traceEnt, ent, ent, forward, trace.endpos, damage, 0, MOD_SNIPER);
|
||||
// FIXME: poor implementation
|
||||
/*
|
||||
if (traceEnt->client && bg_itemlist[traceEnt->client->ps.stats[STAT_HOLDABLE_ITEM]].giTag == HI_KEVLAR)
|
||||
{
|
||||
// reset kevlar flag
|
||||
traceEnt->client->kevlarHit = qfalse;
|
||||
// set SSG kevlar flag so we stop piercing
|
||||
hitKevlar = qtrue;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
//Elder: go through non-solids and breakables
|
||||
//If we ever wanted to "shoot through walls" we'd do stuff here
|
||||
if ( hitKevlar || (hitBreakable == qfalse && (trace.contents & CONTENTS_SOLID))) {
|
||||
|
@ -1500,7 +1545,13 @@ void Weapon_SSG3000_Fire (gentity_t *ent) {
|
|||
// no explosion at end if SURF_NOIMPACT
|
||||
if ( !(trace.surfaceFlags & SURF_NOIMPACT) )
|
||||
{
|
||||
tentWall = G_TempEntity( trace.endpos, EV_BULLET_HIT_WALL );
|
||||
if ( (trace.surfaceFlags & SURF_METALSTEPS) ||
|
||||
(trace.surfaceFlags & SURF_METAL2) )
|
||||
tentWall = G_TempEntity( trace.endpos, EV_BULLET_HIT_METAL );
|
||||
else
|
||||
{
|
||||
tentWall = G_TempEntity( trace.endpos, EV_BULLET_HIT_WALL );
|
||||
}
|
||||
tentWall->s.eventParm = DirToByte( trace.plane.normal );
|
||||
tentWall->s.otherEntityNum = ent->s.number;
|
||||
}
|
||||
|
@ -2273,3 +2324,39 @@ void Laser_Think( gentity_t *self )
|
|||
self->nextthink = level.time + 10;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
ReloadWeapon
|
||||
|
||||
Added by Elder
|
||||
Handles server-side management of numclips
|
||||
=================
|
||||
*/
|
||||
void ReloadWeapon ( gentity_t *ent, int stage )
|
||||
{
|
||||
|
||||
if (stage == 2)
|
||||
{
|
||||
G_Printf("Hit server-side reload\n");
|
||||
ent->client->numClips[ent->client->ps.weapon]--;
|
||||
// remove an extra clip if using HC or Akimbos
|
||||
if (ent->client->ps.weapon == WP_HANDCANNON ||
|
||||
ent->client->ps.weapon == WP_AKIMBO)
|
||||
ent->client->numClips[ent->client->ps.weapon]--;
|
||||
|
||||
//Elder: sync hc and m3 ammo + mk23 and akimbo ammo - a switch might look nicer
|
||||
if (ent->client->ps.weapon == WP_M3) {
|
||||
ent->client->numClips[WP_HANDCANNON] = ent->client->numClips[WP_M3];
|
||||
}
|
||||
else if (ent->client->ps.weapon == WP_HANDCANNON) {
|
||||
ent->client->numClips[WP_M3] = ent->client->numClips[WP_HANDCANNON];
|
||||
}
|
||||
else if(ent->client->ps.weapon == WP_PISTOL) {
|
||||
ent->client->numClips[WP_AKIMBO] = ent->client->numClips[WP_PISTOL];
|
||||
}
|
||||
else if (ent->client->ps.weapon == WP_AKIMBO) {
|
||||
ent->client->numClips[WP_PISTOL] = ent->client->numClips[WP_AKIMBO];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue