2001-12-31 16:16:59 +00:00
//-----------------------------------------------------------------------------
//
// $Id$
//
//-----------------------------------------------------------------------------
//
2001-12-31 16:28:42 +00:00
// $Log$
2007-07-31 20:02:56 +00:00
// Revision 1.96 2007/07/31 20:02:56 makro
// Quick hack disabling footstep sounds for ladder surfaces
//
2005-09-07 20:27:42 +00:00
// Revision 1.95 2005/09/07 20:27:41 makro
// Entity attachment trees
//
2005-02-15 16:33:39 +00:00
// Revision 1.94 2005/02/15 16:33:39 makro
// Tons of updates (entity tree attachment system, UI vectors)
//
2003-03-09 19:47:48 +00:00
// Revision 1.93 2003/03/09 19:47:48 niceass
// Support for torso pistol animations
//
2003-02-05 04:29:14 +00:00
// Revision 1.92 2003/02/05 04:29:14 niceass
// added support for akimbo animations
//
2002-10-26 00:37:18 +00:00
// Revision 1.91 2002/10/26 00:37:18 jbravo
// New multiple item code and added PB support to the UI
//
2002-09-08 23:25:09 +00:00
// Revision 1.90 2002/09/08 23:25:09 niceass
// made cg_rq3_predictweapons even more like quake 2, and it's simpler
//
2002-09-04 00:16:17 +00:00
// Revision 1.89 2002/09/04 00:16:17 makro
// Fixed 'unselectable grenade shown in the inventory if you switch weapons
// after pulling the pin' bug
//
2002-08-03 07:04:18 +00:00
// Revision 1.88 2002/08/03 07:04:18 jbravo
// Fixed constant gasping sound when you die in shallow water
//
2002-07-22 06:35:03 +00:00
// Revision 1.87 2002/07/22 06:33:58 niceass
// cleaned up the powerup code
//
2002-07-21 18:52:39 +00:00
// Revision 1.86 2002/07/21 18:52:39 niceass
// weapon prediction stuff
//
2002-07-16 04:27:19 +00:00
// Revision 1.85 2002/07/16 04:27:19 niceass
// physics back to 2.0
//
2002-07-08 04:34:41 +00:00
// Revision 1.84 2002/07/08 04:34:41 niceass
// oops, small mistake
//
2002-07-08 04:34:15 +00:00
// Revision 1.83 2002/07/08 04:34:15 niceass
// changes to gravity and stuff
//
2002-06-29 02:50:58 +00:00
// Revision 1.82 2002/06/29 02:50:58 niceass
// m4 kick fix and removed ladder stuff
//
2002-06-18 06:15:30 +00:00
// Revision 1.81 2002/06/18 06:15:30 niceass
// m4 kick now smooth
//
2002-06-18 05:18:55 +00:00
// Revision 1.80 2002/06/18 05:18:55 niceass
// adjustment to leg damage
//
2002-06-16 20:06:15 +00:00
// Revision 1.79 2002/06/16 20:06:14 jbravo
// Reindented all the source files with "indent -kr -ut -i8 -l120 -lc120 -sob -bad -bap"
//
2002-06-16 17:38:00 +00:00
// Revision 1.78 2002/06/16 17:37:59 jbravo
// Removed the MISSIONPACK ifdefs and missionpack only code.
//
2002-06-11 03:09:28 +00:00
// Revision 1.77 2002/06/11 03:09:28 niceass
// +attack cancels reloads
//
2002-06-07 19:42:44 +00:00
// Revision 1.76 2002/06/07 19:42:44 niceass
// leg damage much closer to AQ2
//
2002-05-27 06:48:02 +00:00
// Revision 1.75 2002/05/27 06:48:02 niceass
// new leg damage
//
2002-05-21 04:58:28 +00:00
// Revision 1.74 2002/05/21 04:58:27 blaze
// kicked the reload bugs ass!
//
2002-05-11 19:18:20 +00:00
// Revision 1.73 2002/05/11 19:18:20 makro
// Sand surfaceparm
//
2002-05-11 18:47:09 +00:00
// Revision 1.72 2002/05/11 18:47:09 niceass
// last fire animation fixed
//
2002-05-08 07:24:33 +00:00
// Revision 1.71 2002/05/08 07:24:33 niceass
// Double jumping added. Everything feels very good.
//
2002-05-07 05:07:32 +00:00
// Revision 1.70 2002/05/07 05:07:32 niceass
// several physics fixes
//
2002-05-01 21:14:59 +00:00
// Revision 1.69 2002/05/01 21:14:59 jbravo
// Misc fixes
//
2002-04-26 05:29:38 +00:00
// Revision 1.68 2002/04/26 05:29:38 niceass
// PHYSICS, Take 2
//
2002-04-20 15:05:08 +00:00
// Revision 1.67 2002/04/20 15:03:47 makro
// More footstep sounds, a few other things
//
2002-04-06 21:42:20 +00:00
// Revision 1.66 2002/04/06 21:42:20 makro
// Changes to bot code. New surfaceparm system.
//
2002-03-31 03:31:24 +00:00
// Revision 1.65 2002/03/31 03:31:24 jbravo
// Compiler warning cleanups
//
2002-03-27 17:20:38 +00:00
// Revision 1.64 2002/03/27 17:20:38 jbravo
// Workaround to the bandage bug :)
//
2002-03-23 05:17:43 +00:00
// Revision 1.63 2002/03/23 05:17:42 jbravo
// Major cleanup of game -> cgame communication with LCA vars.
//
2002-03-18 19:19:08 +00:00
// Revision 1.62 2002/03/18 19:18:39 slicer
// Fixed bandage bugs ( i hope )
//
2002-03-11 01:45:46 +00:00
// Revision 1.61 2002/03/11 01:45:46 jbravo
// Bye bye backflips! :)
//
2002-03-11 01:29:54 +00:00
// Revision 1.60 2002/03/11 01:29:54 slicer
// Fixed Sniper zooming during LCA
//
2002-03-02 22:02:09 +00:00
// Revision 1.59 2002/03/02 22:02:09 niceass
// mk23 and akimbo last fire animation fixed
//
2002-03-02 08:03:14 +00:00
// Revision 1.58 2002/03/02 08:03:14 niceass
// look down movement bug fixed
//
2002-02-27 01:54:29 +00:00
// Revision 1.57 2002/02/27 01:54:28 jbravo
// More spectatorfixes and finally stopped all fallingdamage anims and
// sounds during LCA.
//
2002-02-04 00:30:35 +00:00
// Revision 1.56 2002/02/04 00:30:35 niceass
// New physics
//
2002-01-24 14:20:53 +00:00
// Revision 1.55 2002/01/24 14:20:53 jbravo
// Adding func_explosive and a few new surfaceparms
//
2002-01-11 20:20:58 +00:00
// Revision 1.54 2002/01/11 20:20:58 jbravo
// Adding TP to main branch
//
2002-01-11 19:48:33 +00:00
// Revision 1.53 2002/01/11 19:48:29 jbravo
// Formatted the source in non DOS format.
//
2001-12-31 16:28:42 +00:00
// Revision 1.52 2001/12/31 16:28:42 jbravo
// I made a Booboo with the Log tag.
//
2001-12-31 16:16:59 +00:00
//
//-----------------------------------------------------------------------------
2001-05-06 20:50:27 +00:00
// Copyright (C) 1999-2000 Id Software, Inc.
//
// bg_pmove.c -- both games player movement code
// takes a playerstate and a usercmd as input and returns a modifed playerstate
2001-11-12 07:59:19 +00:00
2009-07-04 02:29:42 +00:00
# include "../qcommon/q_shared.h"
2001-05-06 20:50:27 +00:00
# include "bg_public.h"
# include "bg_local.h"
2002-06-16 20:06:15 +00:00
pmove_t * pm ;
pml_t pml ;
2001-05-06 20:50:27 +00:00
2001-07-24 01:50:01 +00:00
//Elder: reduce x-y speed on ladders by this factor so it 'feels' more like Q2
# define PM_LADDER_MOVE_REDUCTION 10
2001-05-06 20:50:27 +00:00
// movement parameters
2002-06-16 20:06:15 +00:00
float pm_stopspeed = 100.0f ;
float pm_duckScale = 0.25f ;
float pm_swimScale = 0.50f ;
float pm_wadeScale = 0.70f ;
float pm_ladderScale = 0.75f ; // more c3a ladders
float pm_maxspeed = 300 ;
float pm_accelerate = 10.0f ;
float pm_airaccelerate = 1.0f ;
float pm_wateraccelerate = 4.0f ;
float pm_flyaccelerate = 8.0f ;
float pm_ladderAccelerate = 3000 ; // same as ladder friction.
float pm_friction = 6.0f ;
float pm_waterfriction = 1.0f ;
float pm_flightfriction = 3.0f ;
float pm_spectatorfriction = 5.0f ;
float pm_ladderfriction = 3000 ;
int c_pmove = 0 ;
2001-05-06 20:50:27 +00:00
2001-07-28 02:24:11 +00:00
/* [QUARANTINE] - Weapon Animations
= = = = = = = = = = = = = = = = = = =
PM_StartWeaponAnim , PM_ContinueWeaponAnim
= = = = = = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_StartWeaponAnim ( int anim )
{
if ( pm - > ps - > pm_type > = PM_DEAD ) {
2001-07-28 02:24:11 +00:00
return ;
}
2002-07-21 18:52:39 +00:00
// NiceAss: Don't do client prediction of weapon animations
2002-09-08 23:25:09 +00:00
/*if ( !pm->predict && (anim == WP_ANIM_FIRE || anim == WP_ANIM_IDLE ||
2002-07-21 18:52:39 +00:00
anim = = WP_ANIM_EXTRA1 | | anim = = WP_ANIM_THROWFIRE ) )
2002-09-08 23:25:09 +00:00
return ; */
2002-07-21 18:52:39 +00:00
2002-06-16 20:06:15 +00:00
pm - > ps - > generic1 = ( ( pm - > ps - > generic1 & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT ) | anim ;
2001-07-28 02:24:11 +00:00
}
2002-06-16 20:06:15 +00:00
static void PM_ContinueWeaponAnim ( int anim )
{
if ( ( pm - > ps - > generic1 & ~ ANIM_TOGGLEBIT ) = = anim ) {
2001-07-28 02:24:11 +00:00
return ;
}
2002-07-21 18:52:39 +00:00
// NiceAss: Don't do client prediction of weapon animations
2002-09-08 23:25:09 +00:00
/*
2002-07-21 18:52:39 +00:00
if ( ! pm - > predict & & ( anim = = WP_ANIM_FIRE | | anim = = WP_ANIM_IDLE | |
anim = = WP_ANIM_EXTRA1 | | anim = = WP_ANIM_THROWFIRE ) )
2002-09-08 23:25:09 +00:00
return ; */
2002-07-21 18:52:39 +00:00
2002-06-16 20:06:15 +00:00
PM_StartWeaponAnim ( anim ) ;
2001-07-28 02:24:11 +00:00
}
2002-06-16 20:06:15 +00:00
2001-07-28 02:24:11 +00:00
// END
2001-05-06 20:50:27 +00:00
/*
= = = = = = = = = = = = = = =
PM_AddEvent
= = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
void PM_AddEvent ( int newEvent )
{
BG_AddPredictableEventToPlayerstate ( newEvent , 0 , pm - > ps ) ;
2001-05-06 20:50:27 +00:00
}
2001-07-28 14:12:11 +00:00
/*
= = = = = = = = = = = = = = =
PM_AddEvent
Elder : stuffs event parameters
2001-08-30 09:47:39 +00:00
Be careful because you are stuffing the player
2001-07-28 14:12:11 +00:00
= = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
void PM_AddEvent2 ( int newEvent , int eventParm )
{
BG_AddPredictableEventToPlayerstate ( newEvent , eventParm , pm - > ps ) ;
2001-07-28 14:12:11 +00:00
}
2001-05-06 20:50:27 +00:00
/*
= = = = = = = = = = = = = = =
PM_AddTouchEnt
= = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
void PM_AddTouchEnt ( int entityNum )
{
int i ;
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
if ( entityNum = = ENTITYNUM_WORLD ) {
2001-05-06 20:50:27 +00:00
return ;
}
2002-06-16 20:06:15 +00:00
if ( pm - > numtouch = = MAXTOUCH ) {
2001-05-06 20:50:27 +00:00
return ;
}
// see if it is already added
2002-06-16 20:06:15 +00:00
for ( i = 0 ; i < pm - > numtouch ; i + + ) {
if ( pm - > touchents [ i ] = = entityNum ) {
2001-05-06 20:50:27 +00:00
return ;
}
}
// add it
pm - > touchents [ pm - > numtouch ] = entityNum ;
pm - > numtouch + + ;
}
/*
= = = = = = = = = = = = = = = = = = =
PM_StartTorsoAnim
= = = = = = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_StartTorsoAnim ( int anim )
{
if ( pm - > ps - > pm_type > = PM_DEAD ) {
2001-05-06 20:50:27 +00:00
return ;
}
2002-06-16 20:06:15 +00:00
pm - > ps - > torsoAnim = ( ( pm - > ps - > torsoAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT )
| anim ;
2001-05-06 20:50:27 +00:00
}
2002-06-16 20:06:15 +00:00
static void PM_StartLegsAnim ( int anim )
{
if ( pm - > ps - > pm_type > = PM_DEAD ) {
2001-05-06 20:50:27 +00:00
return ;
}
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > legsTimer > 0 ) {
2001-05-06 20:50:27 +00:00
return ; // a high priority animation is running
}
2002-06-16 20:06:15 +00:00
pm - > ps - > legsAnim = ( ( pm - > ps - > legsAnim & ANIM_TOGGLEBIT ) ^ ANIM_TOGGLEBIT )
| anim ;
2001-05-06 20:50:27 +00:00
}
2002-06-16 20:06:15 +00:00
static void PM_ContinueLegsAnim ( int anim )
{
if ( ( pm - > ps - > legsAnim & ~ ANIM_TOGGLEBIT ) = = anim ) {
2001-05-06 20:50:27 +00:00
return ;
}
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > legsTimer > 0 ) {
2001-05-06 20:50:27 +00:00
return ; // a high priority animation is running
}
2002-06-16 20:06:15 +00:00
PM_StartLegsAnim ( anim ) ;
2001-05-06 20:50:27 +00:00
}
2002-06-16 20:06:15 +00:00
static void PM_ContinueTorsoAnim ( int anim )
{
if ( ( pm - > ps - > torsoAnim & ~ ANIM_TOGGLEBIT ) = = anim ) {
2001-05-06 20:50:27 +00:00
return ;
}
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > torsoTimer > 0 ) {
2001-05-06 20:50:27 +00:00
return ; // a high priority animation is running
}
2002-06-16 20:06:15 +00:00
PM_StartTorsoAnim ( anim ) ;
2001-05-06 20:50:27 +00:00
}
2002-06-16 20:06:15 +00:00
static void PM_ForceLegsAnim ( int anim )
{
2001-05-06 20:50:27 +00:00
pm - > ps - > legsTimer = 0 ;
2002-06-16 20:06:15 +00:00
PM_StartLegsAnim ( anim ) ;
2001-05-06 20:50:27 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
PM_ClipVelocity
Slide off of the impacting surface
= = = = = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
void PM_ClipVelocity ( vec3_t in , vec3_t normal , vec3_t out , float overbounce )
{
float backoff ;
float change ;
int i ;
2001-08-01 19:52:17 +00:00
2002-06-16 20:06:15 +00:00
backoff = DotProduct ( in , normal ) ;
2001-11-12 07:59:19 +00:00
2002-06-16 20:06:15 +00:00
if ( backoff < 0 ) {
2001-05-06 20:50:27 +00:00
backoff * = overbounce ;
} else {
backoff / = overbounce ;
}
2002-06-16 20:06:15 +00:00
for ( i = 0 ; i < 3 ; i + + ) {
change = normal [ i ] * backoff ;
2001-05-06 20:50:27 +00:00
out [ i ] = in [ i ] - change ;
}
}
/*
= = = = = = = = = = = = = = = = = =
PM_Friction
Handles both ground friction and water friction
= = = = = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_Friction ( void )
{
vec3_t vec ;
float * vel ;
float speed , newspeed , control ;
float drop ;
2001-11-12 07:59:19 +00:00
2001-05-06 20:50:27 +00:00
vel = pm - > ps - > velocity ;
2001-11-12 07:59:19 +00:00
2002-06-16 20:06:15 +00:00
VectorCopy ( vel , vec ) ;
2002-05-08 07:24:33 +00:00
/*if ( pml.walking ) {
2002-06-16 20:06:15 +00:00
vec [ 2 ] = 0 ; // ignore slope movement
} */
2001-05-06 20:50:27 +00:00
speed = VectorLength ( vec ) ;
if ( speed < 1 ) {
vel [ 0 ] = 0 ;
2002-06-16 20:06:15 +00:00
vel [ 1 ] = 0 ; // allow sinking underwater
2001-05-06 20:50:27 +00:00
// FIXME: still have z friction underwater?
return ;
}
drop = 0 ;
// apply ground friction
2002-06-16 20:06:15 +00:00
if ( pm - > waterlevel < = 1 ) {
if ( pml . walking & & ! ( pml . groundTrace . surfaceFlags & SURF_SLICK ) & & pm - > ps - > groundEntityNum ) {
2001-05-06 20:50:27 +00:00
// if getting knocked back, no friction
2002-06-16 20:06:15 +00:00
if ( ! ( pm - > ps - > pm_flags & PMF_TIME_KNOCKBACK ) ) {
2001-05-06 20:50:27 +00:00
control = speed < pm_stopspeed ? pm_stopspeed : speed ;
2002-06-16 20:06:15 +00:00
drop + = control * pm_friction * pml . frametime ;
2001-05-06 20:50:27 +00:00
}
}
}
// apply water friction even if just wading
2002-06-16 20:06:15 +00:00
if ( pm - > waterlevel ) {
drop + = speed * pm_waterfriction * pm - > waterlevel * pml . frametime ;
2001-05-06 20:50:27 +00:00
}
2002-06-16 20:06:15 +00:00
if ( pml . ladder ) // If they're on a ladder...
2001-05-06 20:50:27 +00:00
{
2002-06-16 20:06:15 +00:00
drop + = speed * pm_ladderfriction * pml . frametime ; // Add ladder friction!
2001-05-06 20:50:27 +00:00
}
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > pm_type = = PM_SPECTATOR ) {
drop + = speed * pm_spectatorfriction * pml . frametime ;
2001-05-06 20:50:27 +00:00
}
// scale the velocity
newspeed = speed - drop ;
if ( newspeed < 0 ) {
newspeed = 0 ;
}
newspeed / = speed ;
vel [ 0 ] = vel [ 0 ] * newspeed ;
vel [ 1 ] = vel [ 1 ] * newspeed ;
vel [ 2 ] = vel [ 2 ] * newspeed ;
}
/*
= = = = = = = = = = = = = =
PM_Accelerate
Handles user intended acceleration
= = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_Accelerate ( vec3_t wishdir , float wishspeed , float accel )
{
int i ;
float addspeed , accelspeed , currentspeed ;
2002-02-04 00:30:35 +00:00
2002-06-16 20:06:15 +00:00
currentspeed = DotProduct ( pm - > ps - > velocity , wishdir ) ;
2001-05-06 20:50:27 +00:00
addspeed = wishspeed - currentspeed ;
if ( addspeed < = 0 ) {
return ;
}
2002-06-16 20:06:15 +00:00
accelspeed = accel * pml . frametime * wishspeed ;
2001-05-06 20:50:27 +00:00
if ( accelspeed > addspeed ) {
accelspeed = addspeed ;
}
2001-11-12 07:59:19 +00:00
2002-06-16 20:06:15 +00:00
for ( i = 0 ; i < 3 ; i + + ) {
pm - > ps - > velocity [ i ] + = accelspeed * wishdir [ i ] ;
2001-05-06 20:50:27 +00:00
}
}
/*
= = = = = = = = = = = =
PM_CmdScale
Returns the scale factor to apply to cmd movements
This allows the clients to use axial - 127 to 127 values for all directions
without getting a sqrt ( 2 ) distortion in speed .
= = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static float PM_CmdScale ( usercmd_t * cmd )
{
int max ;
float total ;
float scale ;
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
max = abs ( cmd - > forwardmove ) ;
if ( abs ( cmd - > rightmove ) > max ) {
max = abs ( cmd - > rightmove ) ;
2001-05-06 20:50:27 +00:00
}
2002-06-16 20:06:15 +00:00
if ( abs ( cmd - > upmove ) > max ) {
max = abs ( cmd - > upmove ) ;
2001-05-06 20:50:27 +00:00
}
2002-06-16 20:06:15 +00:00
if ( ! max ) {
2001-05-06 20:50:27 +00:00
return 0 ;
}
2002-06-16 20:06:15 +00:00
total = sqrt ( cmd - > forwardmove * cmd - > forwardmove + cmd - > rightmove * cmd - > rightmove + cmd - > upmove * cmd - > upmove ) ;
scale = ( float ) pm - > ps - > speed * max / ( 127.0 * total ) ;
2001-05-06 20:50:27 +00:00
return scale ;
}
/*
= = = = = = = = = = = = = = = =
PM_SetMovementDir
Determine the rotation of the legs reletive
to the facing dir
= = = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_SetMovementDir ( void )
{
if ( pm - > cmd . forwardmove | | pm - > cmd . rightmove ) {
if ( pm - > cmd . rightmove = = 0 & & pm - > cmd . forwardmove > 0 ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > movementDir = 0 ;
2002-06-16 20:06:15 +00:00
} else if ( pm - > cmd . rightmove < 0 & & pm - > cmd . forwardmove > 0 ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > movementDir = 1 ;
2002-06-16 20:06:15 +00:00
} else if ( pm - > cmd . rightmove < 0 & & pm - > cmd . forwardmove = = 0 ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > movementDir = 2 ;
2002-06-16 20:06:15 +00:00
} else if ( pm - > cmd . rightmove < 0 & & pm - > cmd . forwardmove < 0 ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > movementDir = 3 ;
2002-06-16 20:06:15 +00:00
} else if ( pm - > cmd . rightmove = = 0 & & pm - > cmd . forwardmove < 0 ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > movementDir = 4 ;
2002-06-16 20:06:15 +00:00
} else if ( pm - > cmd . rightmove > 0 & & pm - > cmd . forwardmove < 0 ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > movementDir = 5 ;
2002-06-16 20:06:15 +00:00
} else if ( pm - > cmd . rightmove > 0 & & pm - > cmd . forwardmove = = 0 ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > movementDir = 6 ;
2002-06-16 20:06:15 +00:00
} else if ( pm - > cmd . rightmove > 0 & & pm - > cmd . forwardmove > 0 ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > movementDir = 7 ;
}
} else {
// if they aren't actively going directly sideways,
// change the animation to the diagonal so they
// don't stop too crooked
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > movementDir = = 2 ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > movementDir = 1 ;
2002-06-16 20:06:15 +00:00
} else if ( pm - > ps - > movementDir = = 6 ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > movementDir = 7 ;
2001-11-12 07:59:19 +00:00
}
2001-05-06 20:50:27 +00:00
}
}
/*
= = = = = = = = = = = = =
PM_CheckJump
= = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static qboolean PM_CheckJump ( void )
{
if ( pm - > ps - > pm_flags & PMF_RESPAWNED ) {
return qfalse ; // don't allow jump until all buttons are up
2001-05-06 20:50:27 +00:00
}
2002-06-16 20:06:15 +00:00
if ( pm - > cmd . upmove < 10 ) {
2001-05-06 20:50:27 +00:00
// not holding jump
return qfalse ;
}
// must wait for jump to be released
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > pm_flags & PMF_JUMP_HELD ) {
2001-05-06 20:50:27 +00:00
// clear upmove so cmdscale doesn't lower running speed
pm - > cmd . upmove = 0 ;
return qfalse ;
}
2002-06-16 20:06:15 +00:00
if ( ! pml . groundPlane & & ! pml . walking )
return qfalse ;
2002-05-08 07:24:33 +00:00
2002-06-16 20:06:15 +00:00
if ( pm - > debugLevel ) {
2002-05-08 07:24:33 +00:00
Com_Printf ( " %i:jump \n " , c_pmove ) ;
}
2002-04-26 05:29:38 +00:00
2002-06-16 20:06:15 +00:00
pml . groundPlane = qfalse ; // jumping away
2001-05-06 20:50:27 +00:00
pml . walking = qfalse ;
pm - > ps - > pm_flags | = PMF_JUMP_HELD ;
pm - > ps - > groundEntityNum = ENTITYNUM_NONE ;
2002-04-26 05:29:38 +00:00
pm - > ps - > velocity [ 2 ] + = JUMP_VELOCITY ;
2001-11-12 07:59:19 +00:00
2002-04-26 05:29:38 +00:00
if ( pm - > ps - > velocity [ 2 ] < JUMP_VELOCITY )
pm - > ps - > velocity [ 2 ] = JUMP_VELOCITY ;
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
PM_AddEvent ( EV_JUMP ) ;
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
PM_ForceLegsAnim ( LEGS_JUMP ) ;
2002-03-11 01:45:46 +00:00
pm - > ps - > pm_flags & = ~ PMF_BACKWARDS_JUMP ;
2001-05-06 20:50:27 +00:00
return qtrue ;
}
/*
= = = = = = = = = = = = =
PM_CheckWaterJump
= = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static qboolean PM_CheckWaterJump ( void )
{
vec3_t spot ;
int cont ;
vec3_t flatforward ;
2001-05-06 20:50:27 +00:00
if ( pm - > ps - > pm_time ) {
return qfalse ;
}
// check for water jump
2002-06-16 20:06:15 +00:00
if ( pm - > waterlevel ! = 2 ) {
2001-05-06 20:50:27 +00:00
return qfalse ;
}
flatforward [ 0 ] = pml . forward [ 0 ] ;
flatforward [ 1 ] = pml . forward [ 1 ] ;
flatforward [ 2 ] = 0 ;
2002-06-16 20:06:15 +00:00
VectorNormalize ( flatforward ) ;
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
VectorMA ( pm - > ps - > origin , 30 , flatforward , spot ) ;
2001-05-06 20:50:27 +00:00
spot [ 2 ] + = 4 ;
2002-06-16 20:06:15 +00:00
cont = pm - > pointcontents ( spot , pm - > ps - > clientNum ) ;
if ( ! ( cont & CONTENTS_SOLID ) ) {
2001-05-06 20:50:27 +00:00
return qfalse ;
}
spot [ 2 ] + = 16 ;
2002-06-16 20:06:15 +00:00
cont = pm - > pointcontents ( spot , pm - > ps - > clientNum ) ;
if ( cont ) {
2001-05-06 20:50:27 +00:00
return qfalse ;
}
// jump out of water
2002-06-16 20:06:15 +00:00
VectorScale ( pml . forward , 200 , pm - > ps - > velocity ) ;
2001-05-06 20:50:27 +00:00
pm - > ps - > velocity [ 2 ] = 350 ;
pm - > ps - > pm_flags | = PMF_TIME_WATERJUMP ;
pm - > ps - > pm_time = 2000 ;
return qtrue ;
}
//============================================================================
/*
= = = = = = = = = = = = = = = = = = =
PM_WaterJumpMove
Flying out of the water
= = = = = = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_WaterJumpMove ( void )
{
2001-05-06 20:50:27 +00:00
// waterjump has no control, but falls
2002-06-16 20:06:15 +00:00
PM_StepSlideMove ( qtrue ) ;
2001-05-06 20:50:27 +00:00
pm - > ps - > velocity [ 2 ] - = pm - > ps - > gravity * pml . frametime ;
if ( pm - > ps - > velocity [ 2 ] < 0 ) {
// cancel as soon as we are falling down again
pm - > ps - > pm_flags & = ~ PMF_ALL_TIMES ;
pm - > ps - > pm_time = 0 ;
}
}
/*
= = = = = = = = = = = = = = = = = = =
PM_WaterMove
= = = = = = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_WaterMove ( void )
{
int i ;
vec3_t wishvel ;
float wishspeed ;
vec3_t wishdir ;
float scale ;
float vel ;
if ( PM_CheckWaterJump ( ) ) {
2001-05-06 20:50:27 +00:00
PM_WaterJumpMove ( ) ;
return ;
}
2002-04-26 05:29:38 +00:00
2002-06-16 20:06:15 +00:00
PM_Friction ( ) ;
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
scale = PM_CmdScale ( & pm - > cmd ) ;
2001-05-06 20:50:27 +00:00
//
// user intentions
//
2002-06-16 20:06:15 +00:00
if ( ! scale ) {
2001-05-06 20:50:27 +00:00
wishvel [ 0 ] = 0 ;
wishvel [ 1 ] = 0 ;
2002-06-16 20:06:15 +00:00
wishvel [ 2 ] = - 60 ; // sink towards bottom
2001-05-06 20:50:27 +00:00
} else {
2002-06-16 20:06:15 +00:00
for ( i = 0 ; i < 3 ; i + + )
wishvel [ i ] =
scale * pml . forward [ i ] * pm - > cmd . forwardmove + scale * pml . right [ i ] * pm - > cmd . rightmove ;
2001-05-06 20:50:27 +00:00
wishvel [ 2 ] + = scale * pm - > cmd . upmove ;
}
2002-06-16 20:06:15 +00:00
VectorCopy ( wishvel , wishdir ) ;
2001-05-06 20:50:27 +00:00
wishspeed = VectorNormalize ( wishdir ) ;
2002-06-16 20:06:15 +00:00
if ( wishspeed > pm - > ps - > speed * pm_swimScale ) {
2001-05-06 20:50:27 +00:00
wishspeed = pm - > ps - > speed * pm_swimScale ;
}
2002-06-16 20:06:15 +00:00
PM_Accelerate ( wishdir , wishspeed , pm_wateraccelerate ) ;
2001-05-06 20:50:27 +00:00
// make sure we can go up slopes easily under water
2002-06-16 20:06:15 +00:00
if ( pml . groundPlane & & DotProduct ( pm - > ps - > velocity , pml . groundTrace . plane . normal ) < 0 ) {
2001-05-06 20:50:27 +00:00
vel = VectorLength ( pm - > ps - > velocity ) ;
// slide along the ground plane
2002-06-16 20:06:15 +00:00
PM_ClipVelocity ( pm - > ps - > velocity , pml . groundTrace . plane . normal , pm - > ps - > velocity , OVERCLIP ) ;
2001-05-06 20:50:27 +00:00
VectorNormalize ( pm - > ps - > velocity ) ;
VectorScale ( pm - > ps - > velocity , vel , pm - > ps - > velocity ) ;
}
2002-06-16 20:06:15 +00:00
PM_StepSlideMove ( qfalse ) ;
2001-05-06 20:50:27 +00:00
}
/*
= = = = = = = = = = = = = = = = = = =
PM_FlyMove
Only with the flight powerup
= = = = = = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_FlyMove ( void )
{
int i ;
vec3_t wishvel ;
float wishspeed ;
vec3_t wishdir ;
float scale ;
2001-05-06 20:50:27 +00:00
// normal slowdown
2002-06-16 20:06:15 +00:00
PM_Friction ( ) ;
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
scale = PM_CmdScale ( & pm - > cmd ) ;
2001-05-06 20:50:27 +00:00
//
// user intentions
//
2002-06-16 20:06:15 +00:00
if ( ! scale ) {
2001-05-06 20:50:27 +00:00
wishvel [ 0 ] = 0 ;
wishvel [ 1 ] = 0 ;
wishvel [ 2 ] = 0 ;
} else {
2002-06-16 20:06:15 +00:00
for ( i = 0 ; i < 3 ; i + + ) {
wishvel [ i ] =
scale * pml . forward [ i ] * pm - > cmd . forwardmove + scale * pml . right [ i ] * pm - > cmd . rightmove ;
2001-05-06 20:50:27 +00:00
}
wishvel [ 2 ] + = scale * pm - > cmd . upmove ;
}
2002-06-16 20:06:15 +00:00
VectorCopy ( wishvel , wishdir ) ;
2001-05-06 20:50:27 +00:00
wishspeed = VectorNormalize ( wishdir ) ;
2002-06-16 20:06:15 +00:00
PM_Accelerate ( wishdir , wishspeed , pm_flyaccelerate ) ;
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
PM_StepSlideMove ( qfalse ) ;
2001-05-06 20:50:27 +00:00
}
/*
= = = = = = = = = = = = = = = = = = =
PM_AirMove
= = = = = = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_AirMove ( void )
{
int i ;
vec3_t wishvel ;
float fmove , smove ;
vec3_t wishdir ;
float wishspeed ;
float scale ;
usercmd_t cmd ;
2001-05-06 20:50:27 +00:00
2002-04-26 05:29:38 +00:00
PM_CheckJump ( ) ;
2001-05-06 20:50:27 +00:00
PM_Friction ( ) ;
fmove = pm - > cmd . forwardmove ;
smove = pm - > cmd . rightmove ;
2002-04-26 05:29:38 +00:00
cmd = pm - > cmd ;
2002-06-16 20:06:15 +00:00
scale = PM_CmdScale ( & cmd ) ;
2001-05-06 20:50:27 +00:00
// set the movementDir so clients can rotate the legs for strafing
PM_SetMovementDir ( ) ;
2002-04-26 05:29:38 +00:00
// project moves down to flat plane
pml . forward [ 2 ] = 0 ;
pml . right [ 2 ] = 0 ;
2002-06-16 20:06:15 +00:00
VectorNormalize ( pml . forward ) ;
VectorNormalize ( pml . right ) ;
2002-04-26 05:29:38 +00:00
2002-06-16 20:06:15 +00:00
for ( i = 0 ; i < 2 ; i + + ) {
wishvel [ i ] = pml . forward [ i ] * fmove * scale + pml . right [ i ] * smove * scale ;
2001-05-06 20:50:27 +00:00
}
wishvel [ 2 ] = 0 ;
2002-06-16 20:06:15 +00:00
VectorCopy ( wishvel , wishdir ) ;
2001-05-06 20:50:27 +00:00
wishspeed = VectorNormalize ( wishdir ) ;
2002-04-26 05:29:38 +00:00
//wishspeed *= scale;
2001-05-06 20:50:27 +00:00
2002-02-04 00:30:35 +00:00
// not on ground, so little effect on velocity
2002-06-16 20:06:15 +00:00
PM_Accelerate ( wishdir , wishspeed , pm_airaccelerate ) ;
2001-05-06 20:50:27 +00:00
2002-04-26 05:29:38 +00:00
// we may have a ground plane that is very steep, even
// though we don't have a groundentity
// slide along the steep plane
/*if ( pml.groundPlane ) {
2002-06-16 20:06:15 +00:00
PM_ClipVelocity ( pm - > ps - > velocity , pml . groundTrace . plane . normal ,
pm - > ps - > velocity , OVERCLIP ) ;
}
*/
2002-07-16 04:27:19 +00:00
2002-06-16 20:06:15 +00:00
PM_StepSlideMove ( qtrue ) ;
2001-05-06 20:50:27 +00:00
}
/*
= = = = = = = = = = = = = = = = = = =
PM_GrappleMove
= = = = = = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_GrappleMove ( void )
{
2001-05-06 20:50:27 +00:00
vec3_t vel , v ;
float vlen ;
VectorScale ( pml . forward , - 16 , v ) ;
VectorAdd ( pm - > ps - > grapplePoint , v , v ) ;
VectorSubtract ( v , pm - > ps - > origin , vel ) ;
vlen = VectorLength ( vel ) ;
2002-06-16 20:06:15 +00:00
VectorNormalize ( vel ) ;
2001-05-06 20:50:27 +00:00
if ( vlen < = 100 )
VectorScale ( vel , 10 * vlen , vel ) ;
else
VectorScale ( vel , 800 , vel ) ;
VectorCopy ( vel , pm - > ps - > velocity ) ;
pml . groundPlane = qfalse ;
}
/*
= = = = = = = = = = = = = = = = = = =
PM_WalkMove
= = = = = = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_WalkMove ( void )
{
int i ;
vec3_t wishvel ;
float fmove , smove ;
vec3_t wishdir ;
float wishspeed ;
float scale ;
usercmd_t cmd ;
float accelerate ;
if ( pm - > waterlevel > 2 & & DotProduct ( pml . forward , pml . groundTrace . plane . normal ) > 0 ) {
2001-05-06 20:50:27 +00:00
// begin swimming
PM_WaterMove ( ) ;
return ;
}
2001-06-18 01:59:58 +00:00
//Blaze: Cant jump while someone has leg damage
2002-06-16 20:06:15 +00:00
if ( ! ( ( pm - > ps - > stats [ STAT_RQ3 ] & RQ3_LEGDAMAGE ) = = RQ3_LEGDAMAGE ) & & PM_CheckJump ( ) ) {
2001-05-06 20:50:27 +00:00
// jumped away
2002-06-16 20:06:15 +00:00
if ( pm - > waterlevel > 1 ) {
2001-05-06 20:50:27 +00:00
PM_WaterMove ( ) ;
} else {
PM_AirMove ( ) ;
}
return ;
}
2001-11-12 07:59:19 +00:00
2002-06-16 20:06:15 +00:00
PM_Friction ( ) ;
2001-05-06 20:50:27 +00:00
fmove = pm - > cmd . forwardmove ;
smove = pm - > cmd . rightmove ;
cmd = pm - > cmd ;
2002-06-16 20:06:15 +00:00
scale = PM_CmdScale ( & cmd ) ;
2001-05-06 20:50:27 +00:00
// set the movementDir so clients can rotate the legs for strafing
PM_SetMovementDir ( ) ;
2002-03-02 08:03:14 +00:00
// project the forward and right directions onto the ground plane
pml . forward [ 2 ] = 0 ;
pml . right [ 2 ] = 0 ;
2002-07-08 04:34:15 +00:00
2002-06-16 20:06:15 +00:00
PM_ClipVelocity ( pml . forward , pml . groundTrace . plane . normal , pml . forward , OVERCLIP ) ;
PM_ClipVelocity ( pml . right , pml . groundTrace . plane . normal , pml . right , OVERCLIP ) ;
2002-07-08 04:34:15 +00:00
2002-06-16 20:06:15 +00:00
VectorNormalize ( pml . forward ) ;
VectorNormalize ( pml . right ) ;
2002-03-02 08:03:14 +00:00
2002-06-16 20:06:15 +00:00
for ( i = 0 ; i < 3 ; i + + ) {
wishvel [ i ] = pml . forward [ i ] * fmove + pml . right [ i ] * smove ;
2001-05-06 20:50:27 +00:00
}
2002-03-02 08:03:14 +00:00
// when going up or down slopes the wish velocity should Not be zero
2002-07-16 04:27:19 +00:00
// wishvel[2] = 0;
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
VectorCopy ( wishvel , wishdir ) ;
2001-05-06 20:50:27 +00:00
wishspeed = VectorNormalize ( wishdir ) ;
2002-03-02 08:03:14 +00:00
wishspeed * = scale ;
2001-07-30 17:09:19 +00:00
2001-05-06 20:50:27 +00:00
// clamp the speed lower if ducking
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > pm_flags & PMF_DUCKED ) {
if ( wishspeed > pm - > ps - > speed * pm_duckScale ) {
2001-05-06 20:50:27 +00:00
wishspeed = pm - > ps - > speed * pm_duckScale ;
}
}
// clamp the speed lower if wading or walking on the bottom
2002-06-16 20:06:15 +00:00
if ( pm - > waterlevel ) {
float waterScale ;
2001-05-06 20:50:27 +00:00
waterScale = pm - > waterlevel / 3.0 ;
2002-06-16 20:06:15 +00:00
waterScale = 1.0 - ( 1.0 - pm_swimScale ) * waterScale ;
if ( wishspeed > pm - > ps - > speed * waterScale ) {
2001-05-06 20:50:27 +00:00
wishspeed = pm - > ps - > speed * waterScale ;
}
}
// when a player gets hit, they temporarily lose
// full control, which allows them to be moved a bit
2002-06-16 20:06:15 +00:00
if ( ( pml . groundTrace . surfaceFlags & SURF_SLICK ) | | pm - > ps - > pm_flags & PMF_TIME_KNOCKBACK ) {
2001-05-06 20:50:27 +00:00
accelerate = pm_airaccelerate ;
} else {
accelerate = pm_accelerate ;
}
2002-06-16 20:06:15 +00:00
PM_Accelerate ( wishdir , wishspeed , accelerate ) ;
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > velocity [ 2 ] < 0 )
pm - > ps - > velocity [ 2 ] = 0 ;
2001-05-06 20:50:27 +00:00
2002-07-08 04:34:15 +00:00
2002-06-16 20:06:15 +00:00
if ( ( pml . groundTrace . surfaceFlags & SURF_SLICK ) | | pm - > ps - > pm_flags & PMF_TIME_KNOCKBACK ) {
2002-05-07 05:07:32 +00:00
pm - > ps - > velocity [ 2 ] - = pm - > ps - > gravity * pml . frametime ;
}
2002-07-08 04:34:15 +00:00
2001-05-06 20:50:27 +00:00
// don't do anything if standing still
if ( ! pm - > ps - > velocity [ 0 ] & & ! pm - > ps - > velocity [ 1 ] ) {
return ;
}
2001-11-12 07:59:19 +00:00
2002-06-16 20:06:15 +00:00
PM_StepSlideMove ( qfalse ) ;
2002-05-07 05:07:32 +00:00
2001-05-06 20:50:27 +00:00
}
/*
= = = = = = = = = = = = = =
PM_DeadMove
= = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_DeadMove ( void )
{
float forward ;
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
if ( ! pml . walking ) {
2001-05-06 20:50:27 +00:00
return ;
}
// extra friction
2002-06-16 20:06:15 +00:00
forward = VectorLength ( pm - > ps - > velocity ) ;
2001-05-06 20:50:27 +00:00
forward - = 20 ;
2002-06-16 20:06:15 +00:00
if ( forward < = 0 ) {
VectorClear ( pm - > ps - > velocity ) ;
2001-05-06 20:50:27 +00:00
} else {
2002-06-16 20:06:15 +00:00
VectorNormalize ( pm - > ps - > velocity ) ;
VectorScale ( pm - > ps - > velocity , forward , pm - > ps - > velocity ) ;
2001-05-06 20:50:27 +00:00
}
}
/*
= = = = = = = = = = = = = = =
PM_NoclipMove
= = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_NoclipMove ( void )
{
float speed , drop , friction , control , newspeed ;
int i ;
vec3_t wishvel ;
float fmove , smove ;
vec3_t wishdir ;
float wishspeed ;
float scale ;
2001-05-06 20:50:27 +00:00
pm - > ps - > viewheight = DEFAULT_VIEWHEIGHT ;
// friction
2002-06-16 20:06:15 +00:00
speed = VectorLength ( pm - > ps - > velocity ) ;
if ( speed < 1 ) {
VectorCopy ( vec3_origin , pm - > ps - > velocity ) ;
} else {
2001-05-06 20:50:27 +00:00
drop = 0 ;
2002-06-16 20:06:15 +00:00
friction = pm_friction * 1.5 ; // extra friction
2001-05-06 20:50:27 +00:00
control = speed < pm_stopspeed ? pm_stopspeed : speed ;
2002-06-16 20:06:15 +00:00
drop + = control * friction * pml . frametime ;
2001-05-06 20:50:27 +00:00
// scale the velocity
newspeed = speed - drop ;
if ( newspeed < 0 )
newspeed = 0 ;
newspeed / = speed ;
2002-06-16 20:06:15 +00:00
VectorScale ( pm - > ps - > velocity , newspeed , pm - > ps - > velocity ) ;
2001-05-06 20:50:27 +00:00
}
// accelerate
2002-06-16 20:06:15 +00:00
scale = PM_CmdScale ( & pm - > cmd ) ;
2001-05-06 20:50:27 +00:00
fmove = pm - > cmd . forwardmove ;
smove = pm - > cmd . rightmove ;
2001-11-12 07:59:19 +00:00
2002-06-16 20:06:15 +00:00
for ( i = 0 ; i < 3 ; i + + )
wishvel [ i ] = pml . forward [ i ] * fmove + pml . right [ i ] * smove ;
2001-05-06 20:50:27 +00:00
wishvel [ 2 ] + = pm - > cmd . upmove ;
2002-06-16 20:06:15 +00:00
VectorCopy ( wishvel , wishdir ) ;
2001-05-06 20:50:27 +00:00
wishspeed = VectorNormalize ( wishdir ) ;
wishspeed * = scale ;
2002-06-16 20:06:15 +00:00
PM_Accelerate ( wishdir , wishspeed , pm_accelerate ) ;
2001-05-06 20:50:27 +00:00
// move
2002-06-16 20:06:15 +00:00
VectorMA ( pm - > ps - > origin , pml . frametime , pm - > ps - > velocity , pm - > ps - > origin ) ;
2001-05-06 20:50:27 +00:00
}
//============================================================================
/*
= = = = = = = = = = = = = = = =
PM_FootstepForSurface
Returns an event number apropriate for the groundsurface
2005-02-15 16:33:39 +00:00
Makro - changed prototype so that we can use it for other surfaces , too
( ladder footsteps )
2001-05-06 20:50:27 +00:00
= = = = = = = = = = = = = = = =
*/
2005-02-15 16:33:39 +00:00
static int PM_FootstepForSurface ( int surfaceFlags )
2002-06-16 20:06:15 +00:00
{
2005-02-15 16:33:39 +00:00
int Material = GetMaterialFromFlag ( surfaceFlags ) ;
2002-06-16 20:06:15 +00:00
2007-07-31 20:02:56 +00:00
//Makro: quick note: surfaceparm nosteps will cause footstep sounds
//NOT to be played, UNLESS surfaceparm ladder is also set.
//Pretty weird, I know, but that how they wanted it...
qboolean bLadder = ( pml . groundTrace . surfaceFlags & SURF_LADDER ) ! = 0 ;
qboolean bNoSteps = ( pml . groundTrace . surfaceFlags & SURF_NOSTEPS ) ! = 0 ;
//2007-07-31: getting rid of ladder footsteps
//if ((bLadder ^ bNoSteps) != 0) {
if ( bNoSteps | | bLadder ) {
2001-05-06 20:50:27 +00:00
return 0 ;
}
2007-07-31 20:02:56 +00:00
2002-04-06 21:42:20 +00:00
//Makro - new surfaceparm system
//if ( pml.groundTrace.surfaceFlags & SURF_METALSTEPS ) {
2002-06-16 20:06:15 +00:00
if ( Material = = MAT_METALSTEPS ) {
2001-05-06 20:50:27 +00:00
return EV_FOOTSTEP_METAL ;
}
2001-08-06 19:15:00 +00:00
//Elder: added for footstep support
2002-04-06 21:42:20 +00:00
//if ( pml.groundTrace.surfaceFlags & SURF_GRASS ) {
2002-06-16 20:06:15 +00:00
if ( Material = = MAT_GRASS ) {
2001-08-06 19:15:00 +00:00
return EV_FOOTSTEP_GRASS ;
}
2002-01-24 14:20:53 +00:00
// JBravo: re-enables Gravel.
2002-04-06 21:42:20 +00:00
//Makro - new surfaceparm system
//if ( pml.groundTrace.surfaceFlags & SURF_GRAVEL ) {
2002-06-16 20:06:15 +00:00
if ( Material = = MAT_GRAVEL ) {
2002-01-24 14:20:53 +00:00
return EV_FOOTSTEP_GRAVEL ;
}
2002-04-06 21:42:20 +00:00
//if ( pml.groundTrace.surfaceFlags & SURF_WOOD ) {
2002-06-16 20:06:15 +00:00
if ( Material = = MAT_WOOD ) {
2001-08-17 20:48:18 +00:00
return EV_FOOTSTEP_WOOD ;
}
2002-04-06 21:42:20 +00:00
//if ( pml.groundTrace.surfaceFlags & SURF_CARPET ) {
2002-06-16 20:06:15 +00:00
if ( Material = = MAT_CARPET ) {
2001-08-17 20:48:18 +00:00
return EV_FOOTSTEP_CARPET ;
}
2002-04-06 21:42:20 +00:00
//if ( pml.groundTrace.surfaceFlags & SURF_METAL2 ) {
2002-06-16 20:06:15 +00:00
if ( Material = = MAT_METAL2 ) {
2001-08-17 20:48:18 +00:00
return EV_FOOTSTEP_METAL2 ;
}
2002-01-24 14:20:53 +00:00
// JBravo: Begin adding new sounds
2002-04-06 21:42:20 +00:00
//Makro - new surfaceparm system
//if ( pml.groundTrace.surfaceFlags & SURF_SNOW ) {
2002-06-16 20:06:15 +00:00
if ( Material = = MAT_SNOW ) {
2002-01-24 14:20:53 +00:00
return EV_FOOTSTEP_SNOW ;
}
2002-04-06 21:42:20 +00:00
//if ( pml.groundTrace.surfaceFlags & SURF_MUD ) {
2002-06-16 20:06:15 +00:00
if ( Material = = MAT_MUD ) {
2002-01-24 14:20:53 +00:00
return EV_FOOTSTEP_MUD ;
}
2002-04-06 21:42:20 +00:00
//if ( pml.groundTrace.surfaceFlags & SURF_WOOD2 ) {
2002-06-16 20:06:15 +00:00
if ( Material = = MAT_WOOD2 ) {
2002-01-24 14:20:53 +00:00
return EV_FOOTSTEP_WOOD2 ;
}
2002-04-06 21:42:20 +00:00
//if ( pml.groundTrace.surfaceFlags & SURF_HARDMETAL ) {
2002-06-16 20:06:15 +00:00
if ( Material = = MAT_HARDMETAL ) {
2002-01-24 14:20:53 +00:00
return EV_FOOTSTEP_HARDMETAL ;
}
// JBravo: end adding new sounds
2002-04-20 15:05:08 +00:00
// Makro - 5 new sounds
2002-06-16 20:06:15 +00:00
if ( Material = = MAT_LEAVES ) {
2002-04-20 15:05:08 +00:00
return EV_FOOTSTEP_LEAVES ;
}
2002-06-16 20:06:15 +00:00
if ( Material = = MAT_CEMENT ) {
2002-04-20 15:05:08 +00:00
return EV_FOOTSTEP_CEMENT ;
}
2002-06-16 20:06:15 +00:00
if ( Material = = MAT_MARBLE ) {
2002-04-20 15:05:08 +00:00
return EV_FOOTSTEP_MARBLE ;
}
2002-06-16 20:06:15 +00:00
if ( Material = = MAT_SNOW2 ) {
2002-04-20 15:05:08 +00:00
return EV_FOOTSTEP_SNOW2 ;
}
2002-06-16 20:06:15 +00:00
if ( Material = = MAT_HARDSTEPS ) {
2002-04-20 15:05:08 +00:00
return EV_FOOTSTEP_HARDSTEPS ;
}
2002-05-11 19:18:20 +00:00
2002-06-16 20:06:15 +00:00
if ( Material = = MAT_SAND ) {
2002-05-11 19:18:20 +00:00
return EV_FOOTSTEP_SAND ;
}
2002-04-20 15:05:08 +00:00
// Makro - end new sounds
2002-01-24 14:20:53 +00:00
2001-05-06 20:50:27 +00:00
return EV_FOOTSTEP ;
}
/*
= = = = = = = = = = = = = = = = =
PM_CrashLand
Check for hard landings that generate sound events
= = = = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_CrashLand ( void )
{
float delta ;
//float dist;
//float vel, acc;
//float t;
//float a, b, c, den;
int damage ;
2001-05-06 20:50:27 +00:00
2002-04-26 05:29:38 +00:00
// JBravo: no falling at all during LCA in Teamplay
2002-03-23 05:17:43 +00:00
if ( pm - > lca ) {
2002-02-27 01:54:29 +00:00
return ;
}
2002-06-16 20:06:15 +00:00
PM_ForceLegsAnim ( LEGS_LAND ) ;
2001-05-06 20:50:27 +00:00
2001-10-11 22:52:43 +00:00
// Elder: 300/320 factor included
delta = 0.9375f * ( pm - > ps - > velocity [ 2 ] - pml . previous_velocity [ 2 ] ) ;
2002-06-16 20:06:15 +00:00
delta = delta * delta * 0.0001 ;
2001-11-12 07:59:19 +00:00
2001-05-06 20:50:27 +00:00
// never take falling damage if completely underwater
2002-06-16 20:06:15 +00:00
if ( pm - > waterlevel = = 3 ) {
2001-05-06 20:50:27 +00:00
return ;
}
// reduce falling damage if there is standing water
2002-06-16 20:06:15 +00:00
if ( pm - > waterlevel = = 2 ) {
2001-05-06 20:50:27 +00:00
delta * = 0.25 ;
}
2002-06-16 20:06:15 +00:00
if ( pm - > waterlevel = = 1 ) {
2001-05-06 20:50:27 +00:00
delta * = 0.5 ;
}
2002-06-16 20:06:15 +00:00
if ( delta < 1 ) {
2001-05-06 20:50:27 +00:00
return ;
}
2002-06-16 20:06:15 +00:00
if ( delta > 30 ) {
damage = ( int ) ( ( ( delta - 30 ) / 2 ) ) ;
if ( damage < 1 )
damage = 1 ;
2001-07-10 01:26:35 +00:00
damage * = 10 ;
2001-11-12 07:59:19 +00:00
2002-06-16 20:06:15 +00:00
if ( ! ( pml . groundTrace . surfaceFlags & SURF_NODAMAGE ) ) {
2002-04-26 05:29:38 +00:00
//Blaze lots of changes to make it more like aq2
// this is a pain grunt, so don't play it if dead
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > stats [ STAT_HEALTH ] > 0 & & damage > 0 ) {
2002-10-26 00:37:18 +00:00
// JBravo: new multiple itemcode
if ( pm - > ps - > stats [ STAT_HOLDABLE_ITEM ] & ( 1 < < HI_SLIPPERS ) )
2002-06-16 20:06:15 +00:00
PM_AddEvent ( EV_FALL_FAR_NOSOUND ) ;
else
PM_AddEvent ( EV_FALL_FAR ) ;
2001-11-12 07:59:19 +00:00
2002-06-16 20:06:15 +00:00
pm - > ps - > stats [ STAT_FALLDAMAGE ] = damage ;
} else {
2005-02-15 16:33:39 +00:00
PM_AddEvent ( PM_FootstepForSurface ( pml . groundTrace . surfaceFlags ) ) ;
2001-11-12 07:59:19 +00:00
//Elder: added? useful?
2001-07-10 01:26:35 +00:00
pm - > ps - > stats [ STAT_FALLDAMAGE ] = 0 ;
2001-05-06 20:50:27 +00:00
}
}
2002-06-16 20:06:15 +00:00
} else if ( delta > 20 ) {
2002-10-26 00:37:18 +00:00
// JBravo: new multiple itemcode
if ( pm - > ps - > stats [ STAT_HOLDABLE_ITEM ] & ( 1 < < HI_SLIPPERS ) ) {
2002-06-16 20:06:15 +00:00
PM_AddEvent ( EV_FALL_SHORT_NOSOUND ) ;
2001-11-12 07:59:19 +00:00
//Elder: added? useful?
2001-07-27 00:21:23 +00:00
pm - > ps - > stats [ STAT_FALLDAMAGE ] = 0 ;
2002-06-16 20:06:15 +00:00
} else {
PM_AddEvent ( EV_FALL_SHORT ) ;
2001-11-12 07:59:19 +00:00
//Elder: added? useful?
2001-07-27 00:21:23 +00:00
pm - > ps - > stats [ STAT_FALLDAMAGE ] = 0 ;
}
2002-10-26 00:37:18 +00:00
// JBravo: new multiple itemcode
} else if ( ! ( pm - > ps - > stats [ STAT_HOLDABLE_ITEM ] & ( 1 < < HI_SLIPPERS ) ) ) {
2001-10-11 22:52:43 +00:00
// Elder: don't spam sound events going up -- more like Q2 ladders as well
2005-02-15 16:33:39 +00:00
//Makro - ladder footsteps are handled in PM_LadderMove, chaging || to &&
if ( ! pml . ladder & & pm - > ps - > velocity [ 2 ] < 0 )
PM_AddEvent ( PM_FootstepForSurface ( pml . groundTrace . surfaceFlags ) ) ;
2001-11-12 07:59:19 +00:00
//Elder: added? useful?
2001-07-16 01:40:33 +00:00
pm - > ps - > stats [ STAT_FALLDAMAGE ] = 0 ;
}
2001-05-06 20:50:27 +00:00
// start footstep cycle over
pm - > ps - > bobCycle = 0 ;
}
/*
= = = = = = = = = = = = =
PM_CorrectAllSolid
= = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static int PM_CorrectAllSolid ( trace_t * trace )
{
int i , j , k ;
vec3_t point ;
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
if ( pm - > debugLevel ) {
2001-05-06 20:50:27 +00:00
Com_Printf ( " %i:allsolid \n " , c_pmove ) ;
}
// jitter around
for ( i = - 1 ; i < = 1 ; i + + ) {
for ( j = - 1 ; j < = 1 ; j + + ) {
for ( k = - 1 ; k < = 1 ; k + + ) {
VectorCopy ( pm - > ps - > origin , point ) ;
point [ 0 ] + = ( float ) i ;
point [ 1 ] + = ( float ) j ;
point [ 2 ] + = ( float ) k ;
2002-06-16 20:06:15 +00:00
pm - > trace ( trace , point , pm - > mins , pm - > maxs , point , pm - > ps - > clientNum , pm - > tracemask ) ;
if ( ! trace - > allsolid ) {
2001-05-06 20:50:27 +00:00
point [ 0 ] = pm - > ps - > origin [ 0 ] ;
point [ 1 ] = pm - > ps - > origin [ 1 ] ;
point [ 2 ] = pm - > ps - > origin [ 2 ] - 0.25 ;
2002-06-16 20:06:15 +00:00
pm - > trace ( trace , pm - > ps - > origin , pm - > mins , pm - > maxs , point , pm - > ps - > clientNum ,
pm - > tracemask ) ;
2001-05-06 20:50:27 +00:00
pml . groundTrace = * trace ;
return qtrue ;
}
}
}
}
pm - > ps - > groundEntityNum = ENTITYNUM_NONE ;
pml . groundPlane = qfalse ;
pml . walking = qfalse ;
return qfalse ;
}
/*
= = = = = = = = = = = = =
PM_GroundTraceMissed
The ground trace didn ' t hit a surface , so we are in freefall
= = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_GroundTraceMissed ( void )
{
trace_t trace ;
vec3_t point ;
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > groundEntityNum ! = ENTITYNUM_NONE ) {
2001-05-06 20:50:27 +00:00
// we just transitioned into freefall
2002-06-16 20:06:15 +00:00
if ( pm - > debugLevel ) {
2001-05-06 20:50:27 +00:00
Com_Printf ( " %i:lift \n " , c_pmove ) ;
}
// if they aren't in a jumping animation and the ground is a ways away, force into it
// if we didn't do the trace, the player would be backflipping down staircases
2002-06-16 20:06:15 +00:00
VectorCopy ( pm - > ps - > origin , point ) ;
2001-05-06 20:50:27 +00:00
point [ 2 ] - = 64 ;
2002-06-16 20:06:15 +00:00
pm - > trace ( & trace , pm - > ps - > origin , pm - > mins , pm - > maxs , point , pm - > ps - > clientNum , pm - > tracemask ) ;
if ( trace . fraction = = 1.0 ) {
PM_ForceLegsAnim ( LEGS_JUMP ) ;
2002-03-11 01:45:46 +00:00
pm - > ps - > pm_flags & = ~ PMF_BACKWARDS_JUMP ;
2001-05-06 20:50:27 +00:00
}
}
pm - > ps - > groundEntityNum = ENTITYNUM_NONE ;
pml . groundPlane = qfalse ;
pml . walking = qfalse ;
}
/*
= = = = = = = = = = = = =
PM_GroundTrace
= = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_GroundTrace ( void )
{
vec3_t point ;
trace_t trace ;
2001-05-06 20:50:27 +00:00
point [ 0 ] = pm - > ps - > origin [ 0 ] ;
point [ 1 ] = pm - > ps - > origin [ 1 ] ;
point [ 2 ] = pm - > ps - > origin [ 2 ] - 0.25 ;
2002-06-16 20:06:15 +00:00
pm - > trace ( & trace , pm - > ps - > origin , pm - > mins , pm - > maxs , point , pm - > ps - > clientNum , pm - > tracemask ) ;
2001-05-06 20:50:27 +00:00
pml . groundTrace = trace ;
// do something corrective if the trace starts in a solid...
2002-06-16 20:06:15 +00:00
if ( trace . allsolid ) {
if ( ! PM_CorrectAllSolid ( & trace ) )
2001-05-06 20:50:27 +00:00
return ;
}
2002-04-26 05:29:38 +00:00
// if the trace didn't hit anything and not on ladder, we are in free fall
2002-06-16 20:06:15 +00:00
if ( trace . fraction = = 1.0 & & ! pml . ladder ) {
2001-05-06 20:50:27 +00:00
PM_GroundTraceMissed ( ) ;
pml . groundPlane = qfalse ;
pml . walking = qfalse ;
return ;
}
2002-07-08 04:34:15 +00:00
2001-05-06 20:50:27 +00:00
// check if getting thrown off the ground
2002-05-08 07:24:33 +00:00
/*
2002-06-16 20:06:15 +00:00
// NiceAss: Comment out and you get double jumping =D
if ( pm - > ps - > velocity [ 2 ] > 0 & & DotProduct ( pm - > ps - > velocity , trace . plane . normal ) > 10 ) {
if ( pm - > debugLevel ) {
Com_Printf ( " %i:kickoff \n " , c_pmove ) ;
}
// go into jump animation
PM_ForceLegsAnim ( LEGS_JUMP ) ;
pm - > ps - > pm_flags & = ~ PMF_BACKWARDS_JUMP ;
pm - > ps - > groundEntityNum = ENTITYNUM_NONE ;
pml . groundPlane = qfalse ;
pml . walking = qfalse ;
return ;
}
*/
2002-07-08 04:34:41 +00:00
if ( pm - > ps - > velocity [ 2 ] > 180 ) { // NiceAss: This is here for slope acceleration!
2002-06-16 20:06:15 +00:00
if ( pm - > debugLevel ) {
2002-05-08 07:24:33 +00:00
Com_Printf ( " %i:slopeslide \n " , c_pmove ) ;
}
pml . groundPlane = qfalse ;
pm - > ps - > groundEntityNum = ENTITYNUM_NONE ;
2002-07-08 04:34:15 +00:00
pml . walking = qfalse ;
2002-05-08 07:24:33 +00:00
return ;
}
2002-07-08 04:34:15 +00:00
2001-05-06 20:50:27 +00:00
// slopes that are too steep will not be considered onground
2001-10-11 22:52:43 +00:00
// Elder: added ladder check
2002-06-16 20:06:15 +00:00
if ( trace . plane . normal [ 2 ] < MIN_WALK_NORMAL & & ! pml . ladder ) {
if ( pm - > debugLevel ) {
2001-05-06 20:50:27 +00:00
Com_Printf ( " %i:steep \n " , c_pmove ) ;
}
// FIXME: if they can't slide down the slope, let them
// walk (sharp crevices)
pm - > ps - > groundEntityNum = ENTITYNUM_NONE ;
2002-06-16 20:06:15 +00:00
pml . groundPlane = qfalse ; //qtrue;
2001-05-06 20:50:27 +00:00
pml . walking = qfalse ;
return ;
}
pml . groundPlane = qtrue ;
pml . walking = qtrue ;
// hitting solid ground will end a waterjump
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > pm_flags & PMF_TIME_WATERJUMP ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > pm_flags & = ~ ( PMF_TIME_WATERJUMP | PMF_TIME_LAND ) ;
pm - > ps - > pm_time = 0 ;
}
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > groundEntityNum = = ENTITYNUM_NONE ) {
2001-05-06 20:50:27 +00:00
// just hit the ground
2002-06-16 20:06:15 +00:00
if ( pm - > debugLevel ) {
2001-05-06 20:50:27 +00:00
Com_Printf ( " %i:Land \n " , c_pmove ) ;
}
2001-11-12 07:59:19 +00:00
2001-05-06 20:50:27 +00:00
PM_CrashLand ( ) ;
2002-06-16 20:06:15 +00:00
if ( pml . ladder ) {
2001-10-11 22:52:43 +00:00
pml . groundPlane = qfalse ;
pml . walking = qfalse ;
return ;
}
2001-05-06 20:50:27 +00:00
// don't do landing time if we were just going down a slope
2002-06-16 20:06:15 +00:00
if ( pml . previous_velocity [ 2 ] < - 200 ) {
2001-05-06 20:50:27 +00:00
// don't allow another jump for a little while
pm - > ps - > pm_flags | = PMF_TIME_LAND ;
pm - > ps - > pm_time = 250 ;
}
}
pm - > ps - > groundEntityNum = trace . entityNum ;
2002-06-16 20:06:15 +00:00
PM_AddTouchEnt ( trace . entityNum ) ;
2001-05-06 20:50:27 +00:00
}
/*
= = = = = = = = = = = = =
PM_SetWaterLevel FIXME : avoid this twice ? certainly if not moving
= = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_SetWaterLevel ( void )
{
vec3_t point ;
int cont ;
int sample1 ;
int sample2 ;
2001-05-06 20:50:27 +00:00
//
// get waterlevel, accounting for ducking
//
pm - > waterlevel = 0 ;
pm - > watertype = 0 ;
point [ 0 ] = pm - > ps - > origin [ 0 ] ;
point [ 1 ] = pm - > ps - > origin [ 1 ] ;
2001-11-12 07:59:19 +00:00
point [ 2 ] = pm - > ps - > origin [ 2 ] + MINS_Z + 1 ;
2002-06-16 20:06:15 +00:00
cont = pm - > pointcontents ( point , pm - > ps - > clientNum ) ;
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
if ( cont & MASK_WATER ) {
2001-05-06 20:50:27 +00:00
sample2 = pm - > ps - > viewheight - MINS_Z ;
sample1 = sample2 / 2 ;
pm - > watertype = cont ;
pm - > waterlevel = 1 ;
point [ 2 ] = pm - > ps - > origin [ 2 ] + MINS_Z + sample1 ;
2002-06-16 20:06:15 +00:00
cont = pm - > pointcontents ( point , pm - > ps - > clientNum ) ;
if ( cont & MASK_WATER ) {
2001-05-06 20:50:27 +00:00
pm - > waterlevel = 2 ;
point [ 2 ] = pm - > ps - > origin [ 2 ] + MINS_Z + sample2 ;
2002-06-16 20:06:15 +00:00
cont = pm - > pointcontents ( point , pm - > ps - > clientNum ) ;
if ( cont & MASK_WATER ) {
2001-05-06 20:50:27 +00:00
pm - > waterlevel = 3 ;
}
}
}
}
/*
= = = = = = = = = = = = = =
PM_CheckDuck
Sets mins , maxs , and pm - > ps - > viewheight
= = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_CheckDuck ( void )
2001-05-06 20:50:27 +00:00
{
2002-06-16 20:06:15 +00:00
trace_t trace ;
vec3_t point ; // NiceAss: Added for FUNKY CODE ALERT section
2001-05-06 20:50:27 +00:00
pm - > mins [ 0 ] = - 15 ;
pm - > mins [ 1 ] = - 15 ;
pm - > maxs [ 0 ] = 15 ;
pm - > maxs [ 1 ] = 15 ;
pm - > mins [ 2 ] = MINS_Z ;
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > pm_type = = PM_DEAD ) {
2001-05-06 20:50:27 +00:00
pm - > maxs [ 2 ] = - 8 ;
pm - > ps - > viewheight = DEAD_VIEWHEIGHT ;
return ;
}
2001-11-12 07:59:19 +00:00
// NiceAss: FUNKY CODE ALERT!
// Check to see if there is ground below. No? then you can't duck...
point [ 0 ] = pm - > ps - > origin [ 0 ] ;
point [ 1 ] = pm - > ps - > origin [ 1 ] ;
point [ 2 ] = pm - > ps - > origin [ 2 ] - 0.25 ;
2002-06-16 20:06:15 +00:00
pm - > trace ( & trace , pm - > ps - > origin , pm - > mins , pm - > maxs , point , pm - > ps - > clientNum , pm - > tracemask ) ;
2001-11-12 07:59:19 +00:00
2002-06-16 20:06:15 +00:00
if ( trace . fraction = = 1.0 & & ! pml . ladder & & ! ( pm - > ps - > pm_flags & PMF_DUCKED ) ) {
2001-11-12 07:59:19 +00:00
pm - > maxs [ 2 ] = 32 ;
pm - > ps - > viewheight = DEFAULT_VIEWHEIGHT ;
return ;
}
// End of funky code alert
2002-06-16 20:06:15 +00:00
if ( pm - > cmd . upmove < 0 ) { // duck
2001-05-06 20:50:27 +00:00
pm - > ps - > pm_flags | = PMF_DUCKED ;
2002-06-16 20:06:15 +00:00
} else { // stand up if possible
if ( pm - > ps - > pm_flags & PMF_DUCKED ) {
2001-05-06 20:50:27 +00:00
// try to stand up
pm - > maxs [ 2 ] = 32 ;
2002-06-16 20:06:15 +00:00
pm - > trace ( & trace , pm - > ps - > origin , pm - > mins , pm - > maxs , pm - > ps - > origin , pm - > ps - > clientNum ,
pm - > tracemask ) ;
2001-05-06 20:50:27 +00:00
if ( ! trace . allsolid )
pm - > ps - > pm_flags & = ~ PMF_DUCKED ;
}
}
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > pm_flags & PMF_DUCKED ) {
2001-05-06 20:50:27 +00:00
pm - > maxs [ 2 ] = 16 ;
pm - > ps - > viewheight = CROUCH_VIEWHEIGHT ;
2002-06-16 20:06:15 +00:00
} else {
2001-05-06 20:50:27 +00:00
pm - > maxs [ 2 ] = 32 ;
pm - > ps - > viewheight = DEFAULT_VIEWHEIGHT ;
}
2001-11-12 07:59:19 +00:00
2001-05-06 20:50:27 +00:00
}
//===================================================================
/*
= = = = = = = = = = = = = = =
PM_Footsteps
= = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_Footsteps ( void )
{
float bobmove ;
int old ;
qboolean footstep ;
2001-05-06 20:50:27 +00:00
//
// calculate speed and cycle to be used for
// all cyclic walking effects
//
2002-06-16 20:06:15 +00:00
pm - > xyspeed = sqrt ( pm - > ps - > velocity [ 0 ] * pm - > ps - > velocity [ 0 ]
+ pm - > ps - > velocity [ 1 ] * pm - > ps - > velocity [ 1 ] ) ;
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > groundEntityNum = = ENTITYNUM_NONE ) {
2001-05-06 20:50:27 +00:00
// airborne leaves position in cycle intact, but doesn't advance
2002-06-16 20:06:15 +00:00
if ( pm - > waterlevel > 1 ) {
PM_ContinueLegsAnim ( LEGS_SWIM ) ;
2001-05-06 20:50:27 +00:00
}
return ;
}
// if not trying to move
2005-09-07 20:27:42 +00:00
//Makro - changed condition a bit
//if (!pm->cmd.forwardmove && !pm->cmd.rightmove) {
// if (pm->xyspeed < 5) {
if ( ( ! pm - > cmd . forwardmove & & ! pm - > cmd . rightmove ) | | pm - > xyspeed < 5 ) {
pm - > ps - > bobCycle = 0 ; // start at beginning of cycle again
if ( pm - > ps - > pm_flags & PMF_DUCKED ) {
PM_ContinueLegsAnim ( LEGS_IDLECR ) ;
} else {
PM_ContinueLegsAnim ( LEGS_IDLE ) ;
2001-05-06 20:50:27 +00:00
}
return ;
}
2001-11-12 07:59:19 +00:00
2005-09-07 20:27:42 +00:00
2001-05-06 20:50:27 +00:00
footstep = qfalse ;
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > pm_flags & PMF_DUCKED ) {
2001-05-06 20:50:27 +00:00
bobmove = 0.5 ; // ducked characters bob much faster
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > pm_flags & PMF_BACKWARDS_RUN ) {
PM_ContinueLegsAnim ( LEGS_BACKCR ) ;
2001-05-06 20:50:27 +00:00
} else {
2002-06-16 20:06:15 +00:00
PM_ContinueLegsAnim ( LEGS_WALKCR ) ;
2001-05-06 20:50:27 +00:00
}
2002-06-16 20:06:15 +00:00
// ducked characters never play footsteps
/*
} else if ( pm - > ps - > pm_flags & PMF_BACKWARDS_RUN ) {
if ( ! ( pm - > cmd . buttons & BUTTON_WALKING ) ) {
bobmove = 0.4 ; // faster speeds bob faster
footstep = qtrue ;
} else {
bobmove = 0.3 ;
}
PM_ContinueLegsAnim ( LEGS_BACK ) ;
*/
2001-05-06 20:50:27 +00:00
} else {
2002-06-16 20:06:15 +00:00
if ( ! ( pm - > cmd . buttons & BUTTON_WALKING ) ) {
2001-05-06 20:50:27 +00:00
bobmove = 0.4f ; // faster speeds bob faster
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > pm_flags & PMF_BACKWARDS_RUN ) {
PM_ContinueLegsAnim ( LEGS_BACK ) ;
} else {
PM_ContinueLegsAnim ( LEGS_RUN ) ;
2001-05-06 20:50:27 +00:00
}
footstep = qtrue ;
} else {
bobmove = 0.3f ; // walking bobs slow
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > pm_flags & PMF_BACKWARDS_RUN ) {
PM_ContinueLegsAnim ( LEGS_BACKWALK ) ;
} else {
PM_ContinueLegsAnim ( LEGS_WALK ) ;
2001-05-06 20:50:27 +00:00
}
}
}
// check for footstep / splash sounds
old = pm - > ps - > bobCycle ;
2002-06-16 20:06:15 +00:00
pm - > ps - > bobCycle = ( int ) ( old + bobmove * pml . msec ) & 255 ;
2001-05-06 20:50:27 +00:00
// if we just crossed a cycle boundary, play an apropriate footstep event
2002-06-16 20:06:15 +00:00
if ( ( ( old + 64 ) ^ ( pm - > ps - > bobCycle + 64 ) ) & 128 ) {
if ( pm - > waterlevel = = 0 ) {
2001-07-01 05:11:12 +00:00
//Elder: we can check for slippers here!
2001-05-06 20:50:27 +00:00
// on ground will only play sounds if running
2002-06-16 20:06:15 +00:00
if ( ( footstep & & ! pm - > noFootsteps )
2002-10-26 00:37:18 +00:00
// JBravo: new multiple itemcode
& & ! ( pm - > ps - > stats [ STAT_HOLDABLE_ITEM ] & ( 1 < < HI_SLIPPERS ) ) ) {
2005-02-15 16:33:39 +00:00
PM_AddEvent ( PM_FootstepForSurface ( pml . groundTrace . surfaceFlags ) ) ;
2001-05-06 20:50:27 +00:00
}
2002-06-16 20:06:15 +00:00
} else if ( pm - > waterlevel = = 1 ) {
2001-05-06 20:50:27 +00:00
// splashing
2002-06-16 20:06:15 +00:00
PM_AddEvent ( EV_FOOTSPLASH ) ;
} else if ( pm - > waterlevel = = 2 ) {
2001-05-06 20:50:27 +00:00
// wading / swimming at surface
2002-06-16 20:06:15 +00:00
PM_AddEvent ( EV_SWIM ) ;
} else if ( pm - > waterlevel = = 3 ) {
2001-05-06 20:50:27 +00:00
// no sound when completely underwater
}
}
}
/*
= = = = = = = = = = = = = =
PM_WaterEvents
Generate sound events for entering and leaving water
= = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_WaterEvents ( void )
{ // FIXME?
2001-05-06 20:50:27 +00:00
//
// if just entered a water volume, play a sound
//
if ( ! pml . previous_waterlevel & & pm - > waterlevel ) {
2002-06-16 20:06:15 +00:00
PM_AddEvent ( EV_WATER_TOUCH ) ;
2001-05-06 20:50:27 +00:00
}
//
// if just completely exited a water volume, play a sound
//
if ( pml . previous_waterlevel & & ! pm - > waterlevel ) {
2002-06-16 20:06:15 +00:00
PM_AddEvent ( EV_WATER_LEAVE ) ;
2001-05-06 20:50:27 +00:00
}
//
// check for head just going under water
//
if ( pml . previous_waterlevel ! = 3 & & pm - > waterlevel = = 3 ) {
2002-06-16 20:06:15 +00:00
PM_AddEvent ( EV_WATER_UNDER ) ;
2001-05-06 20:50:27 +00:00
}
//
// check for head just coming out of water
//
if ( pml . previous_waterlevel = = 3 & & pm - > waterlevel ! = 3 ) {
2002-06-16 20:06:15 +00:00
PM_AddEvent ( EV_WATER_CLEAR ) ;
2001-05-06 20:50:27 +00:00
}
}
/*
= = = = = = = = = = = = = = =
PM_BeginWeaponChange
= = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_BeginWeaponChange ( int weapon )
{
2002-01-11 20:20:58 +00:00
//G_Printf("CHANGING WEAP TO: %i\n", weapon);
2002-07-21 18:52:39 +00:00
2002-06-16 20:06:15 +00:00
if ( weapon < = WP_NONE | | weapon > = WP_NUM_WEAPONS ) {
2001-05-06 20:50:27 +00:00
return ;
}
2002-06-16 20:06:15 +00:00
if ( ! ( pm - > ps - > stats [ STAT_WEAPONS ] & ( 1 < < weapon ) ) ) {
2001-05-06 20:50:27 +00:00
return ;
}
2001-11-12 07:59:19 +00:00
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weaponstate = = WEAPON_DROPPING ) {
2001-05-06 20:50:27 +00:00
return ;
}
2002-06-16 20:06:15 +00:00
PM_AddEvent ( EV_CHANGE_WEAPON ) ;
2001-08-17 20:48:18 +00:00
//Elder: ignore disarm delays when throwing a weapon
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > stats [ STAT_RQ3 ] & RQ3_THROWWEAPON ) {
2001-08-17 20:48:18 +00:00
pm - > ps - > stats [ STAT_RQ3 ] & = ~ RQ3_THROWWEAPON ;
pm - > ps - > weaponTime = 0 ;
2002-06-16 20:06:15 +00:00
} else {
2001-08-17 20:48:18 +00:00
//pm->ps->weaponTime += 200;
//Elder: dependent time for each weapon
switch ( pm - > ps - > weapon ) {
case WP_PISTOL :
pm - > ps - > weaponTime + = RQ3_PISTOL_DISARM_DELAY ;
break ;
case WP_M3 :
pm - > ps - > weaponTime + = RQ3_M3_DISARM_DELAY ;
break ;
case WP_M4 :
pm - > ps - > weaponTime + = RQ3_M4_DISARM_DELAY ;
break ;
case WP_MP5 :
pm - > ps - > weaponTime + = RQ3_MP5_DISARM_DELAY ;
break ;
case WP_HANDCANNON :
pm - > ps - > weaponTime + = RQ3_HANDCANNON_DISARM_DELAY ;
break ;
case WP_SSG3000 :
pm - > ps - > weaponTime + = RQ3_SSG3000_DISARM_DELAY ;
break ;
case WP_AKIMBO :
pm - > ps - > weaponTime + = RQ3_AKIMBO_DISARM_DELAY ;
break ;
case WP_KNIFE :
pm - > ps - > weaponTime + = RQ3_KNIFE_DISARM_DELAY ;
break ;
case WP_GRENADE :
pm - > ps - > weaponTime + = RQ3_GRENADE_DISARM_DELAY ;
break ;
default :
//Elder: shouldn't be here
//G_Printf("PM_BeginWeaponChange: received bad weapon %d\n", pm->ps->weapon);
pm - > ps - > weaponTime + = 600 ;
break ;
}
2001-06-24 02:08:15 +00:00
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weapon = = WP_KNIFE & & ! ( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_KNIFEMODE ) )
2001-09-11 00:12:29 +00:00
PM_StartWeaponAnim ( WP_ANIM_THROWDISARM ) ;
2001-11-25 23:04:08 +00:00
else {
2001-10-30 23:26:03 +00:00
PM_StartWeaponAnim ( WP_ANIM_DISARM ) ;
2001-11-25 23:04:08 +00:00
}
2001-08-17 20:48:18 +00:00
}
2001-08-30 09:47:39 +00:00
// 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 ;
2001-10-11 22:52:43 +00:00
pm - > ps - > stats [ STAT_RQ3 ] & = ~ RQ3_QUEUERELOAD ;
2001-08-30 09:47:39 +00:00
2001-11-11 07:24:27 +00:00
// Elder: cancel burst shots
pm - > ps - > stats [ STAT_BURST ] = 0 ;
2001-12-17 15:08:34 +00:00
// NiceAss: Added this as a fix for knifes and grenades when you throw the last one.
2002-06-16 20:06:15 +00:00
if ( ( ( pm - > ps - > weapon = = WP_GRENADE | | pm - > ps - > weapon = = WP_KNIFE ) & & pm - > ps - > ammo [ pm - > ps - > weapon ] = = 0 ) & &
pm - > ps - > weaponstate ! = WEAPON_FIRING ) {
2001-12-17 15:08:34 +00:00
pm - > ps - > weaponstate = WEAPON_DROPPING ;
2001-11-25 23:04:08 +00:00
pm - > ps - > weaponTime = 0 ;
return ;
}
2001-12-17 15:08:34 +00:00
pm - > ps - > weaponstate = WEAPON_DROPPING ;
2001-10-30 23:26:03 +00:00
if ( pm - > ps - > weapon = = WP_KNIFE & & ! ( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_KNIFEMODE ) )
2001-09-11 00:12:29 +00:00
PM_StartWeaponAnim ( WP_ANIM_THROWDISARM ) ;
2001-11-25 23:04:08 +00:00
else {
2001-10-30 23:26:03 +00:00
PM_StartWeaponAnim ( WP_ANIM_DISARM ) ;
2001-11-25 23:04:08 +00:00
}
2001-06-24 02:08:15 +00:00
2003-02-05 04:29:14 +00:00
if ( pm - > ps - > weapon = = WP_AKIMBO )
PM_StartTorsoAnim ( TORSO_DROP2 ) ;
else
PM_StartTorsoAnim ( TORSO_DROP ) ;
2001-05-06 20:50:27 +00:00
}
/*
= = = = = = = = = = = = = = =
PM_FinishWeaponChange
= = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_FinishWeaponChange ( void )
{
int weapon , savedWeap ;
2001-05-06 20:50:27 +00:00
weapon = pm - > cmd . weapon ;
2001-06-10 06:46:06 +00:00
2002-03-27 17:20:38 +00:00
// JBravo: debug for the bandage bug
savedWeap = pm - > ps - > weapon ;
2002-06-16 20:06:15 +00:00
if ( weapon < WP_NONE | | weapon > = WP_NUM_WEAPONS ) {
// Com_Printf("BANDAGEBUG: (1) weapon is %d and cmd.weapon is %d. Reverting to previous weapon\n", pm->ps->weapon,
// weapon);
2002-03-27 17:20:38 +00:00
weapon = savedWeap ;
2002-06-16 20:06:15 +00:00
// weapon = WP_NONE;
2001-05-06 20:50:27 +00:00
}
2002-06-16 20:06:15 +00:00
if ( ! ( pm - > ps - > stats [ STAT_WEAPONS ] & ( 1 < < weapon ) ) ) {
// Com_Printf("BANDAGEBUG: (2) weapon is %d and cmd.weapon is %d. Reverting to previous weapon\n", pm->ps->weapon,
// weapon);
2002-03-27 17:20:38 +00:00
weapon = savedWeap ;
2002-06-16 20:06:15 +00:00
// weapon = WP_NONE;
2001-05-06 20:50:27 +00:00
}
2001-12-17 15:08:34 +00:00
//Remove grenade/knife if out of ammo
2002-06-16 20:06:15 +00:00
if ( ( weapon = = WP_GRENADE | | weapon = = WP_KNIFE ) & & pm - > ps - > ammo [ weapon ] = = 0 ) {
if ( weapon = = WP_GRENADE )
pm - > ps - > stats [ STAT_WEAPONS ] & = ~ ( 1 < < WP_GRENADE ) ;
if ( weapon = = WP_KNIFE )
pm - > ps - > stats [ STAT_WEAPONS ] & = ~ ( 1 < < WP_KNIFE ) ;
2001-07-16 01:40:33 +00:00
weapon = WP_PISTOL ;
}
2001-05-06 20:50:27 +00:00
pm - > ps - > weapon = weapon ;
pm - > ps - > weaponstate = WEAPON_RAISING ;
2001-06-24 02:08:15 +00:00
//Elder: weapon-dependent timing
2002-06-16 20:06:15 +00:00
switch ( pm - > ps - > weapon ) {
2001-06-24 02:08:15 +00:00
case WP_PISTOL :
2001-08-06 19:15:00 +00:00
pm - > ps - > weaponTime + = RQ3_PISTOL_ACTIVATE_DELAY ;
2001-06-24 02:08:15 +00:00
break ;
case WP_M3 :
2001-08-06 19:15:00 +00:00
pm - > ps - > weaponTime + = RQ3_M3_ACTIVATE_DELAY ;
2001-06-24 02:08:15 +00:00
break ;
case WP_M4 :
2001-08-06 19:15:00 +00:00
pm - > ps - > weaponTime + = RQ3_M4_ACTIVATE_DELAY ;
2001-06-24 02:08:15 +00:00
break ;
case WP_MP5 :
2001-08-06 19:15:00 +00:00
pm - > ps - > weaponTime + = RQ3_MP5_ACTIVATE_DELAY ;
2001-06-24 02:08:15 +00:00
break ;
case WP_HANDCANNON :
2001-08-06 19:15:00 +00:00
pm - > ps - > weaponTime + = RQ3_HANDCANNON_ACTIVATE_DELAY ;
2001-06-24 02:08:15 +00:00
break ;
case WP_SSG3000 :
2001-08-06 19:15:00 +00:00
pm - > ps - > weaponTime + = RQ3_SSG3000_ACTIVATE_DELAY ;
2001-06-24 02:08:15 +00:00
break ;
case WP_AKIMBO :
2001-08-06 19:15:00 +00:00
pm - > ps - > weaponTime + = RQ3_AKIMBO_ACTIVATE_DELAY ;
2001-06-24 02:08:15 +00:00
break ;
case WP_KNIFE :
2001-08-06 19:15:00 +00:00
pm - > ps - > weaponTime + = RQ3_KNIFE_ACTIVATE_DELAY ;
2001-06-24 02:08:15 +00:00
break ;
case WP_GRENADE :
2001-08-06 19:15:00 +00:00
pm - > ps - > weaponTime + = RQ3_GRENADE_ACTIVATE_DELAY ;
2001-06-24 02:08:15 +00:00
break ;
default :
//Elder: shouldn't be here
//G_Printf("PM_FinishWeaponChange: received bad weapon %d\n", pm->ps->weapon);
pm - > ps - > weaponTime + = 750 ;
break ;
}
2001-10-30 23:26:03 +00:00
if ( pm - > ps - > weapon = = WP_KNIFE & & ! ( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_KNIFEMODE ) )
2001-09-11 00:12:29 +00:00
PM_StartWeaponAnim ( WP_ANIM_THROWACTIVATE ) ;
2001-10-30 23:26:03 +00:00
else
PM_StartWeaponAnim ( WP_ANIM_ACTIVATE ) ;
2001-11-12 07:59:19 +00:00
2003-02-05 04:29:14 +00:00
if ( pm - > ps - > weapon = = WP_AKIMBO )
PM_StartTorsoAnim ( TORSO_RAISE2 ) ;
else
PM_StartTorsoAnim ( TORSO_RAISE ) ;
2001-05-06 20:50:27 +00:00
}
/*
= = = = = = = = = = = = = =
PM_TorsoAnimation
= = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_TorsoAnimation ( void )
{
if ( pm - > ps - > weaponstate = = WEAPON_READY ) {
2003-03-09 19:47:48 +00:00
if ( pm - > ps - > weapon = = WP_KNIFE )
2002-06-16 20:06:15 +00:00
PM_ContinueTorsoAnim ( TORSO_STAND2 ) ;
2003-03-09 19:47:48 +00:00
else if ( pm - > ps - > weapon = = WP_AKIMBO )
2003-02-05 04:29:14 +00:00
PM_ContinueTorsoAnim ( TORSO_STAND3 ) ;
2003-03-09 19:47:48 +00:00
else if ( pm - > ps - > weapon = = WP_PISTOL )
PM_ContinueTorsoAnim ( TORSO_STAND4 ) ;
else
2002-06-16 20:06:15 +00:00
PM_ContinueTorsoAnim ( TORSO_STAND ) ;
2003-03-09 19:47:48 +00:00
2001-07-28 02:24:11 +00:00
// QUARANTINE - Weapon Animation
// Should always draw the weapon when it is just ready
2001-09-11 00:12:29 +00:00
if ( pm - > ps - > ammo [ pm - > ps - > weapon ] = = 0 )
2002-06-16 20:06:15 +00:00
PM_ContinueWeaponAnim ( WP_ANIM_EMPTY ) ;
2001-09-11 00:12:29 +00:00
else if ( pm - > ps - > weapon = = WP_KNIFE & & ! ( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_KNIFEMODE ) )
PM_ContinueWeaponAnim ( WP_ANIM_THROWIDLE ) ;
2001-10-30 23:26:03 +00:00
else
PM_ContinueWeaponAnim ( WP_ANIM_IDLE ) ;
2001-09-11 00:12:29 +00:00
2002-06-16 20:06:15 +00:00
// PM_ContinueWeaponAnim( WP_ANIM_READY );
2001-07-28 02:24:11 +00:00
2001-05-06 20:50:27 +00:00
return ;
}
}
2001-08-30 09:47:39 +00:00
/*
= = = = = = = = = = = = = =
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 )
= = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_Reload ( void )
2001-08-30 09:47:39 +00:00
{
// int weapon = pm->ps->weapon;
2001-10-11 22:52:43 +00:00
int truePress = 0 ;
2001-08-30 09:47:39 +00:00
// only normal/noclip players can reload
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > pm_type > PM_NOCLIP ) {
2001-08-30 09:47:39 +00:00
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 ;
2001-10-11 22:52:43 +00:00
pm - > ps - > stats [ STAT_RQ3 ] & = ~ RQ3_QUEUERELOAD ;
2001-08-30 09:47:39 +00:00
return ;
}
2001-10-11 22:52:43 +00:00
// try to reload since it's queued
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > stats [ STAT_RQ3 ] & RQ3_QUEUERELOAD ) {
if ( ( pm - > cmd . buttons & BUTTON_AFFIRMATIVE ) & & ! ( pm - > ps - > pm_flags & PMF_RELOAD_HELD ) )
2001-10-11 22:52:43 +00:00
truePress = 1 ;
pm - > ps - > stats [ STAT_RQ3 ] & = ~ RQ3_QUEUERELOAD ;
pm - > ps - > pm_flags & = ~ PMF_RELOAD_HELD ;
pm - > cmd . buttons | = BUTTON_AFFIRMATIVE ;
}
2002-06-11 03:09:28 +00:00
// NiceAss: +Attack cancels fast reloads
2002-06-16 20:06:15 +00:00
if ( pm - > cmd . buttons & BUTTON_ATTACK & & pm - > ps - > stats [ STAT_RELOADATTEMPTS ] > 1 ) {
2002-06-11 03:09:28 +00:00
pm - > ps - > stats [ STAT_RELOADATTEMPTS ] = 1 ;
}
2002-06-16 20:06:15 +00:00
if ( pm - > cmd . buttons & BUTTON_AFFIRMATIVE ) {
if ( ! ( pm - > ps - > pm_flags & PMF_RELOAD_HELD ) ) {
2001-08-30 09:47:39 +00:00
// prevent throttling
pm - > ps - > pm_flags | = PMF_RELOAD_HELD ;
// check for bursting or weapon delay
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > stats [ STAT_BURST ] > 0 | | pm - > ps - > weaponTime > 0 ) {
if ( truePress & & ( pm - > ps - > weapon = = WP_SSG3000 | | pm - > ps - > weapon = = WP_M3 ) ) {
2001-10-11 22:52:43 +00:00
pm - > ps - > stats [ STAT_RQ3 ] | = RQ3_FASTRELOADS ;
pm - > ps - > stats [ STAT_RELOADATTEMPTS ] + + ;
}
pm - > ps - > stats [ STAT_RQ3 ] | = RQ3_QUEUERELOAD ;
2001-08-30 09:47:39 +00:00
return ;
2001-10-11 22:52:43 +00:00
}
2001-08-30 09:47:39 +00:00
// check for bandaging
2002-03-18 19:19:08 +00:00
/* if (pm->ps->stats[STAT_RQ3] & RQ3_BANDAGE_WORK)
return ;
*/
//Slicer
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weaponstate = = WEAPON_BANDAGING )
2001-08-30 09:47:39 +00:00
return ;
// check for full clip or non-reloadable weapons
if ( pm - > ps - > ammo [ pm - > ps - > weapon ] = = ClipAmountForAmmo ( pm - > ps - > weapon ) | |
2002-06-16 20:06:15 +00:00
pm - > ps - > weapon = = WP_KNIFE | | pm - > ps - > weapon = = WP_GRENADE ) {
2001-08-30 09:47:39 +00:00
//Com_Printf("No need to reload.\n");
return ;
}
// check for insufficient ammo
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > stats [ STAT_CLIPS ] < = 0 ) {
2001-08-30 09:47:39 +00:00
//Com_Printf("Out of ammo.\n");
return ;
2002-06-16 20:06:15 +00:00
} else if ( pm - > ps - > weapon = = WP_HANDCANNON | | pm - > ps - > weapon = = WP_AKIMBO ) {
if ( pm - > ps - > stats [ STAT_CLIPS ] < 2 ) {
2001-08-30 09:47:39 +00:00
//Com_Printf("Not enough ammo.\n");
return ;
}
}
// check for fast-reload interrupt
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weapon = = WP_M3 | | pm - > ps - > weapon = = WP_SSG3000 ) {
if ( pm - > ps - > stats [ STAT_RELOADTIME ] > 0 ) // && (pm->ps->weapon == WP_M3 && pm->ps->stats[STAT_RELOADTIME] < RQ3_M3_RELOAD_DELAY - RQ3_M3_ALLOW_FAST_RELOAD_DELAY || pm->ps->weapon == WP_SSG3000 && pm->ps->stats[STAT_RELOADTIME] < RQ3_SSG3000_RELOAD_DELAY - RQ3_SSG3000_ALLOW_FAST_RELOAD_DELAY))
2002-06-11 03:09:28 +00:00
{
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > stats [ STAT_RQ3 ] & RQ3_LOCKRELOADS ) {
2001-09-11 00:12:29 +00:00
//Com_Printf("============= Locked out in fast-reload interrupt\n");
2002-06-16 20:06:15 +00:00
} else {
2001-08-30 09:47:39 +00:00
//if (pm->ps->ammo[pm->ps->weapon] + pm->ps->stats[STAT_RELOADATTEMPTS] < ClipAmountForAmmo(pm->ps->weapon) &&
2002-06-16 20:06:15 +00:00
//pm->ps->stats[STAT_RELOADATTEMPTS] < pm->ps->stats[STAT_CLIPS])
if ( pm - > ps - > stats [ STAT_RELOADATTEMPTS ] < ( ClipAmountForAmmo ( pm - > ps - > weapon ) - pm - > ps - > ammo [ pm - > ps - > weapon ] ) ) //only let them cue up enough shots to fill the gun
2001-08-30 09:47:39 +00:00
{
//Com_Printf("Hit fast-reload entrance\n");
// add to reload queue and enable fast-reloads flag
2002-06-16 20:06:15 +00:00
2001-08-30 09:47:39 +00:00
pm - > ps - > stats [ STAT_RQ3 ] | = RQ3_FASTRELOADS ;
pm - > ps - > stats [ STAT_RELOADATTEMPTS ] + + ;
2001-09-11 00:12:29 +00:00
//Com_Printf("======== Reload attempts: %i ========\n", pm->ps->stats[STAT_RELOADATTEMPTS]);
2001-08-30 09:47:39 +00:00
}
return ;
}
}
}
// fresh reload
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > stats [ STAT_RELOADTIME ] = = 0 ) {
2001-08-30 09:47:39 +00:00
// set reload time according to weapon
2002-06-16 20:06:15 +00:00
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 ;
2001-08-30 09:47:39 +00:00
}
2001-10-11 22:52:43 +00:00
// start the animation off
if ( pm - > ps - > weaponstate ! = WEAPON_RELOADING )
PM_StartWeaponAnim ( WP_ANIM_RELOAD ) ;
2001-08-30 09:47:39 +00:00
pm - > ps - > weaponstate = WEAPON_RELOADING ;
2001-11-12 07:59:19 +00:00
2001-08-30 09:47:39 +00:00
PM_AddEvent ( EV_RELOAD_WEAPON0 ) ;
//Com_Printf("Starting reload\n");
return ;
}
}
2002-06-16 20:06:15 +00:00
} else {
2001-08-30 09:47:39 +00:00
pm - > ps - > pm_flags & = ~ PMF_RELOAD_HELD ;
}
2001-11-12 07:59:19 +00:00
2001-08-30 09:47:39 +00:00
// in-progress reload
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > stats [ STAT_RELOADTIME ] > 0 ) {
2001-08-30 09:47:39 +00:00
pm - > ps - > stats [ STAT_RELOADTIME ] - = pml . msec ;
2001-11-12 07:59:19 +00:00
2001-08-30 09:47:39 +00:00
// process any fast-reload stuff here
if ( pm - > ps - > weapon = = WP_M3 | | pm - > ps - > weapon = = WP_SSG3000 ) {
2002-06-16 20:06:15 +00:00
if ( ( pm - > ps - > stats [ STAT_RQ3 ] & RQ3_FASTRELOADS ) & & pm - > ps - > stats [ STAT_RELOADATTEMPTS ] > 0 ) {
//Com_Printf("reloadtime (%d)\n",pm->ps->stats[STAT_RELOADTIME]);
if ( pm - > ps - > weapon = = WP_M3 ) {
2001-08-30 09:47:39 +00:00
// knock down reload time if doing fast-reloads
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > stats [ STAT_RELOADTIME ] < RQ3_M3_ALLOW_FAST_RELOAD_DELAY
& & pm - > ps - > stats [ STAT_RELOADTIME ] > RQ3_M3_FAST_RELOAD_DELAY ) {
2001-08-30 09:47:39 +00:00
//Com_Printf("Reducing reload time\n");
pm - > ps - > stats [ STAT_RELOADTIME ] = RQ3_M3_FAST_RELOAD_DELAY ;
}
2002-06-16 20:06:15 +00:00
} else {
2001-08-30 09:47:39 +00:00
// knock down reload time if doing fast-reloads
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > stats [ STAT_RELOADTIME ] < RQ3_SSG3000_ALLOW_FAST_RELOAD_DELAY
& & pm - > ps - > stats [ STAT_RELOADTIME ] > RQ3_SSG3000_FAST_RELOAD_DELAY ) {
2001-08-30 09:47:39 +00:00
//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
2001-11-12 07:59:19 +00:00
2001-11-11 07:24:27 +00:00
// Special handcannon shell ejection hack
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weapon = = WP_HANDCANNON & &
! ( pm - > ps - > stats [ STAT_RQ3 ] & RQ3_RELOADWEAPON1 ) & & pm - > ps - > stats [ STAT_RELOADTIME ] < 1400 ) {
2001-11-11 07:24:27 +00:00
pm - > ps - > stats [ STAT_RQ3 ] | = RQ3_RELOADWEAPON1 ;
PM_AddEvent ( EV_RELOAD_WEAPON1 ) ;
}
2001-08-30 09:47:39 +00:00
// finished reload
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > stats [ STAT_RELOADTIME ] < = 0 ) {
2001-08-30 09:47:39 +00:00
int ammotoadd ;
2001-11-12 07:59:19 +00:00
2001-08-30 09:47:39 +00:00
ammotoadd = ClipAmountForReload ( pm - > ps - > weapon ) ;
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weapon = = WP_M3 | | pm - > ps - > weapon = = WP_SSG3000 ) {
2001-08-30 09:47:39 +00:00
// need to also check here because of fast-reloads
if ( ammotoadd + pm - > ps - > ammo [ pm - > ps - > weapon ] > ClipAmountForAmmo ( pm - > ps - > weapon ) | |
2002-06-16 20:06:15 +00:00
pm - > ps - > stats [ STAT_CLIPS ] < = 0 ) {
2001-08-30 09:47:39 +00:00
ammotoadd = pm - > ps - > ammo [ pm - > ps - > weapon ] ;
pm - > ps - > stats [ STAT_RELOADATTEMPTS ] = 0 ;
2002-06-16 20:06:15 +00:00
} else
2001-08-30 09:47:39 +00:00
ammotoadd + = pm - > ps - > ammo [ pm - > ps - > weapon ] ;
}
// akimbo and MK23 synchronization
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weapon = = WP_AKIMBO ) {
2001-08-30 09:47:39 +00:00
pm - > ps - > ammo [ WP_PISTOL ] = RQ3_PISTOL_AMMO ;
2002-06-16 20:06:15 +00:00
} else if ( pm - > ps - > weapon = = WP_PISTOL & & ( pm - > ps - > stats [ STAT_WEAPONS ] & ( 1 < < WP_AKIMBO ) ) ) {
2001-08-30 09:47:39 +00:00
// 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 ;
}
2001-11-12 07:59:19 +00:00
2002-06-16 20:06:15 +00:00
if ( ! ( pm - > ps - > stats [ STAT_RQ3 ] & RQ3_LOCKRELOADS ) ) {
2001-08-30 09:47:39 +00:00
pm - > ps - > ammo [ pm - > ps - > weapon ] = ammotoadd ;
2001-12-17 15:08:34 +00:00
}
2001-11-12 07:59:19 +00:00
// handle continuous fast-reloads
2002-06-16 20:06:15 +00:00
if ( ( pm - > ps - > weapon = = WP_M3 | | pm - > ps - > weapon = = WP_SSG3000 ) & & ( pm - > ps - > stats [ STAT_RQ3 ] & RQ3_FASTRELOADS ) ) //&&
2001-08-30 09:47:39 +00:00
//pm->ps->stats[STAT_RELOADATTEMPTS] > 0)
{
2002-06-16 20:06:15 +00:00
if ( ! ( pm - > ps - > stats [ STAT_RQ3 ] & RQ3_LOCKRELOADS ) & &
pm - > ps - > stats [ STAT_RELOADATTEMPTS ] > 0 ) {
2001-08-30 09:47:39 +00:00
//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 ] - - ;
2001-11-12 07:59:19 +00:00
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > stats [ STAT_RELOADATTEMPTS ] > 0 ) {
PM_StartWeaponAnim ( WP_ANIM_EXTRA1 ) ;
2001-10-11 22:52:43 +00:00
//PM_StartWeaponAnim(WP_ANIM_RELOAD);
}
2001-11-11 07:24:27 +00:00
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > stats [ STAT_CLIPS ] > 0 ) {
2001-09-11 00:12:29 +00:00
//Com_Printf("Sending event from continuous fast-reloads\n");
2001-11-11 07:24:27 +00:00
PM_AddEvent ( EV_RELOAD_WEAPON1 ) ;
//PM_AddEvent(EV_RELOAD_WEAPON0);
2002-06-16 20:06:15 +00:00
} else {
2001-09-11 00:12:29 +00:00
//Com_Printf("Negative event prevented\n");
2001-08-30 09:47:39 +00:00
pm - > ps - > stats [ STAT_RELOADATTEMPTS ] = 0 ;
}
2002-06-16 20:06:15 +00:00
} else {
2001-09-11 00:12:29 +00:00
//Com_Printf("============= Locked out in continuous fast-reloads\n");
2001-08-30 09:47:39 +00:00
}
// finishing up fast reloads
if ( ( pm - > ps - > stats [ STAT_RQ3 ] & RQ3_FASTRELOADS ) & &
2002-06-16 20:06:15 +00:00
pm - > ps - > stats [ STAT_RELOADATTEMPTS ] = = 0 ) {
2001-08-30 09:47:39 +00:00
//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 ;
2001-09-11 00:12:29 +00:00
//Com_Printf("<<<<<<<<<<<<< Locking\n");
2002-06-16 20:06:15 +00:00
PM_StartWeaponAnim ( WP_ANIM_EXTRA2 ) ;
2001-08-30 09:47:39 +00:00
}
return ;
}
// normal reload case
//else
//{
2002-06-16 20:06:15 +00:00
// 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 ) ;
}
2001-08-30 09:47:39 +00:00
2002-06-16 20:06:15 +00:00
//Com_Printf("Finished reload\n");
pm - > ps - > stats [ STAT_RELOADTIME ] = 0 ;
pm - > ps - > stats [ STAT_RELOADATTEMPTS ] = 0 ;
pm - > ps - > stats [ STAT_RQ3 ] & = ~ RQ3_RELOADWEAPON1 ;
pm - > ps - > weaponstate = WEAPON_READY ;
2001-08-30 09:47:39 +00:00
//}
2001-11-12 07:59:19 +00:00
2002-06-16 20:06:15 +00:00
} // end finish reload
2001-11-12 07:59:19 +00:00
2002-06-16 20:06:15 +00:00
} // end in-progress reload
2001-08-30 09:47:39 +00:00
}
2001-05-06 20:50:27 +00:00
/*
= = = = = = = = = = = = = =
PM_Weapon
Generates weapon events and modifes the weapon counter
= = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_Weapon ( void )
{
int addTime ;
2001-05-06 20:50:27 +00:00
2001-06-08 04:47:30 +00:00
//Elder: PISTOL always gets set to 12 if akimbos have >11 based on AQ2 observation
if ( pm - > ps - > weapon = = WP_AKIMBO & & pm - > ps - > ammo [ WP_AKIMBO ] > 11 ) {
pm - > ps - > ammo [ WP_PISTOL ] = 12 ;
}
2001-05-06 20:50:27 +00:00
// don't allow attack until all buttons are up
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > pm_flags & PMF_RESPAWNED ) {
2001-05-06 20:50:27 +00:00
return ;
}
// ignore if spectator
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > persistant [ PERS_TEAM ] = = TEAM_SPECTATOR ) {
2001-05-06 20:50:27 +00:00
return ;
}
// check for dead player
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > stats [ STAT_HEALTH ] < = 0 ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > weapon = WP_NONE ;
return ;
}
2001-08-13 17:26:53 +00:00
//Elder: New 3rb Code
//force fire button down if STAT_BURST is < proper amount
2001-11-12 07:59:19 +00:00
//Otherwise release the button
2002-06-16 20:06:15 +00:00
if ( ( pm - > ps - > weapon = = WP_M4 & &
( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_M4MODE ) = = RQ3_M4MODE ) | |
( pm - > ps - > weapon = = WP_MP5 & & ( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_MP5MODE ) = = RQ3_MP5MODE ) ) {
2001-08-13 17:26:53 +00:00
int weaponNum = pm - > ps - > weapon ;
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > ammo [ weaponNum ] = = 0 ) {
2001-08-13 17:26:53 +00:00
pm - > ps - > stats [ STAT_BURST ] = 0 ;
2002-06-16 20:06:15 +00:00
} else if ( pm - > cmd . buttons & BUTTON_ATTACK ) // && client->ps.stats[STAT_BURST] > 0)
2001-08-13 17:26:53 +00:00
{
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > stats [ STAT_BURST ] > = 0 & & pm - > ps - > stats [ STAT_BURST ] < 3 )
2001-08-13 17:26:53 +00:00
pm - > cmd . buttons | = BUTTON_ATTACK ;
else
pm - > cmd . buttons & = ~ BUTTON_ATTACK ;
2002-06-16 20:06:15 +00:00
} else if ( pm - > ps - > stats [ STAT_BURST ] > 2 ) {
2001-08-13 17:26:53 +00:00
pm - > ps - > stats [ STAT_BURST ] = 0 ;
pm - > ps - > weaponTime + = 300 ;
}
//Don't need?
else if ( pm - > ps - > stats [ STAT_BURST ] > 0 )
pm - > cmd . buttons | = BUTTON_ATTACK ;
}
2001-12-17 15:08:34 +00:00
//agt: Knife stupidity
//I'll hijack STAT_BURST for this one
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weapon = = WP_KNIFE & & ( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_KNIFEMODE ) ) {
if ( pm - > cmd . buttons & BUTTON_ATTACK & & pm - > ps - > stats [ STAT_BURST ] > = 0 & & pm - > ps - > stats [ STAT_BURST ] < 5 ) {
2001-12-17 15:08:34 +00:00
pm - > cmd . buttons | = BUTTON_ATTACK ;
2002-06-16 20:06:15 +00:00
} else if ( pm - > ps - > stats [ STAT_BURST ] > 4 ) {
2001-12-17 15:08:34 +00:00
pm - > ps - > stats [ STAT_BURST ] = 0 ;
2002-06-16 20:06:15 +00:00
pm - > ps - > weaponTime + = 650 ; // NiceAss note: 30ms * 5 attacks = 150 ms + 650ms = 800ms.
} else if ( pm - > ps - > stats [ STAT_BURST ] > 0 ) {
2001-12-17 15:08:34 +00:00
pm - > cmd . buttons | = BUTTON_ATTACK ;
}
}
2001-08-13 17:26:53 +00:00
//Elder: New semi-auto code
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weapon = = WP_PISTOL & & ( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_MK23MODE ) = = RQ3_MK23MODE ) {
if ( pm - > ps - > ammo [ WP_PISTOL ] = = 0 ) {
2001-08-13 17:26:53 +00:00
pm - > ps - > stats [ STAT_BURST ] = 0 ;
2002-06-16 20:06:15 +00:00
} else if ( ( pm - > cmd . buttons & BUTTON_ATTACK ) & & pm - > ps - > stats [ STAT_BURST ] ) {
2001-08-13 17:26:53 +00:00
pm - > cmd . buttons & = ~ BUTTON_ATTACK ;
2002-06-16 20:06:15 +00:00
} else if ( pm - > ps - > stats [ STAT_BURST ] ) {
pm - > ps - > weaponTime + = 100 ; // lowered again to 100 from 150 from 200
2001-08-13 17:26:53 +00:00
pm - > ps - > stats [ STAT_BURST ] = 0 ;
}
}
2001-09-01 16:14:14 +00:00
// Elder: new akimbo code
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weapon = = WP_AKIMBO ) {
if ( pm - > ps - > ammo [ WP_AKIMBO ] = = 0 & & pm - > ps - > stats [ STAT_BURST ] ) {
2001-09-01 16:14:14 +00:00
pm - > ps - > stats [ STAT_BURST ] = 0 ;
pm - > cmd . buttons & = ~ BUTTON_ATTACK ;
2002-06-16 20:06:15 +00:00
} else if ( pm - > ps - > stats [ STAT_BURST ] ) {
2001-09-01 16:14:14 +00:00
pm - > cmd . buttons | = BUTTON_ATTACK ;
}
}
2002-06-18 06:15:30 +00:00
2002-06-29 02:50:58 +00:00
//NiceAss: I added this for smooth M4 rise
if ( pm - > ps - > weaponstate = = WEAPON_FIRING & & pm - > ps - > ammo [ pm - > ps - > weapon ] & &
pm - > ps - > weapon = = WP_M4 & & ! pm - > ps - > stats [ STAT_BURST ] & &
2002-09-08 23:25:09 +00:00
! ( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_M4MODE ) /*&&
pm - > predict */ ) {
2002-06-29 02:50:58 +00:00
pm - > ps - > delta_angles [ 0 ] - = ANGLE2SHORT ( 0.13 ) ;
2002-06-18 06:15:30 +00:00
}
2001-05-06 20:50:27 +00:00
2002-06-29 02:50:58 +00:00
2001-05-06 20:50:27 +00:00
// make weapon function
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weaponTime > 0 ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > weaponTime - = pml . msec ;
}
2001-11-08 02:37:32 +00:00
// Elder: make stall decrease
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > stats [ STAT_WEAPONSTALLTIME ] > 0 ) {
2001-11-08 02:37:32 +00:00
pm - > ps - > stats [ STAT_WEAPONSTALLTIME ] - = pml . msec ;
}
2001-05-06 20:50:27 +00:00
// check for weapon change
// can't change if weapon is firing, but can change
// again if lowering or raising
2001-11-12 07:59:19 +00:00
2001-11-11 07:24:27 +00:00
// Elder: modified so that a dropweapon command is high precedence
2001-11-08 02:37:32 +00:00
//if ( pm->ps->weaponTime <= 0 || pm->ps->weaponstate != WEAPON_FIRING) {
2002-06-16 20:06:15 +00:00
if ( ( pm - > ps - > stats [ STAT_RQ3 ] & RQ3_THROWWEAPON ) | | ( pm - > ps - > weaponTime < = 0 & &
! ( pm - > ps - > weaponstate = = WEAPON_FIRING
| | pm - > ps - > weaponstate = = WEAPON_STALL ) ) ) {
if ( pm - > ps - > weapon ! = pm - > cmd . weapon ) {
2001-11-11 07:24:27 +00:00
//Elder: if switching weapons, fire off the grenade "instantly"
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weapon = = WP_GRENADE & & pm - > ps - > weaponstate = = WEAPON_COCKED ) {
2001-07-01 05:11:12 +00:00
pm - > ps - > weaponstate = WEAPON_FIRING ;
pm - > cmd . buttons & = ~ BUTTON_ATTACK ;
2002-09-08 23:25:09 +00:00
//if (pm->predict)
2002-07-21 18:52:39 +00:00
PM_AddEvent2 ( EV_FIRE_WEAPON , RQ3_WPMOD_GRENADEDROP ) ;
2001-07-01 05:11:12 +00:00
pm - > ps - > ammo [ WP_GRENADE ] - - ;
2002-09-04 00:16:17 +00:00
//Makro - if this is the last grenade, remove the weapon from the inventory
if ( pm - > ps - > ammo [ WP_GRENADE ] < = 0 ) {
pm - > ps - > stats [ STAT_WEAPONS ] & = ~ ( 1 < < WP_GRENADE ) ;
}
2001-07-01 05:11:12 +00:00
}
2002-06-16 20:06:15 +00:00
PM_BeginWeaponChange ( pm - > cmd . weapon ) ;
} else {
2001-08-17 20:48:18 +00:00
//Elder: temp hack
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weaponstate = = WEAPON_READY ) {
2001-11-25 23:04:08 +00:00
if ( pm - > ps - > ammo [ pm - > ps - > weapon ] = = 0 ) {
2002-06-16 20:06:15 +00:00
PM_ContinueWeaponAnim ( WP_ANIM_EMPTY ) ;
} else if ( pm - > ps - > weapon = = WP_KNIFE & &
! ( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_KNIFEMODE ) ) {
2001-09-11 00:12:29 +00:00
PM_ContinueWeaponAnim ( WP_ANIM_THROWIDLE ) ;
2002-06-16 20:06:15 +00:00
} else
2001-10-30 23:26:03 +00:00
PM_ContinueWeaponAnim ( WP_ANIM_IDLE ) ;
2001-09-11 00:12:29 +00:00
}
2001-08-06 19:15:00 +00:00
}
2001-05-06 20:50:27 +00:00
}
2001-11-08 02:37:32 +00:00
// Elder: added STAT_RELOADTIME and STAT_WEAPONSTALLTIME check
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weaponTime > 0 | | pm - > ps - > stats [ STAT_RELOADTIME ] > 0 | | pm - > ps - > stats [ STAT_WEAPONSTALLTIME ] > 0 ) {
2001-05-06 20:50:27 +00:00
return ;
}
// change weapon if time
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weaponstate = = WEAPON_DROPPING | | pm - > ps - > weaponstate = = WEAPON_BANDAGING ) {
2001-05-06 20:50:27 +00:00
PM_FinishWeaponChange ( ) ;
return ;
}
2001-12-17 15:08:34 +00:00
//NiceAss: Attempt to have the knife/grenade "activate" after a throw if you have another one of them
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weaponstate = = WEAPON_FIRING & & pm - > ps - > ammo [ pm - > ps - > weapon ] > 0 & &
( pm - > ps - > weapon = = WP_KNIFE | | pm - > ps - > weapon = = WP_GRENADE ) ) {
2001-12-17 15:08:34 +00:00
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weapon = = WP_KNIFE & & ! ( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_KNIFEMODE ) ) {
2001-12-17 15:08:34 +00:00
pm - > ps - > weaponTime = RQ3_KNIFE_ACTIVATE_DELAY ;
PM_StartWeaponAnim ( WP_ANIM_THROWACTIVATE ) ;
pm - > ps - > weaponstate = WEAPON_RAISING ;
2002-06-16 20:06:15 +00:00
PM_StartTorsoAnim ( TORSO_RAISE ) ;
2001-12-17 15:08:34 +00:00
return ;
}
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weapon = = WP_GRENADE ) {
2001-12-17 15:08:34 +00:00
pm - > ps - > weaponTime = RQ3_GRENADE_DELAY ;
PM_StartWeaponAnim ( WP_ANIM_ACTIVATE ) ;
pm - > ps - > weaponstate = WEAPON_RAISING ;
2002-06-16 20:06:15 +00:00
PM_StartTorsoAnim ( TORSO_RAISE ) ;
2001-12-17 15:08:34 +00:00
return ;
}
}
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weaponstate = = WEAPON_RAISING & &
! ( ( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_KNIFEMODE ) & & pm - > ps - > stats [ STAT_BURST ] ) ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > weaponstate = WEAPON_READY ;
2003-03-09 19:47:48 +00:00
if ( pm - > ps - > weapon = = WP_KNIFE )
2002-06-16 20:06:15 +00:00
PM_StartTorsoAnim ( TORSO_STAND2 ) ;
2003-03-09 19:47:48 +00:00
else if ( pm - > ps - > weapon = = WP_AKIMBO )
2003-02-05 04:29:14 +00:00
PM_StartTorsoAnim ( TORSO_STAND3 ) ;
2003-03-09 19:47:48 +00:00
else if ( pm - > ps - > weapon = = WP_PISTOL )
PM_StartTorsoAnim ( TORSO_STAND4 ) ;
else
2002-06-16 20:06:15 +00:00
PM_StartTorsoAnim ( TORSO_STAND ) ;
2001-08-17 20:48:18 +00:00
// temp hack
2001-11-25 23:04:08 +00:00
if ( pm - > ps - > ammo [ pm - > ps - > weapon ] = = 0 ) {
2002-06-16 20:06:15 +00:00
PM_ContinueWeaponAnim ( WP_ANIM_EMPTY ) ;
2001-11-25 23:04:08 +00:00
}
2002-04-26 05:29:38 +00:00
2001-09-11 00:12:29 +00:00
else if ( pm - > ps - > weapon = = WP_KNIFE & & ! ( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_KNIFEMODE ) )
2002-06-16 20:06:15 +00:00
PM_StartWeaponAnim ( WP_ANIM_THROWIDLE ) ;
2001-10-30 23:26:03 +00:00
else
2002-06-16 20:06:15 +00:00
PM_StartWeaponAnim ( WP_ANIM_IDLE ) ;
2001-12-17 15:08:34 +00:00
2001-05-06 20:50:27 +00:00
return ;
}
2002-06-18 06:15:30 +00:00
2001-12-17 15:08:34 +00:00
// NiceAss: Added for knife animation switch.
// At the moment, this is only used for changing knife-throw modes.
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weaponstate = = WEAPON_MODECHANGE ) {
if ( pm - > ps - > weapon = = WP_KNIFE )
pm - > ps - > weaponstate = WEAPON_READY ;
2001-12-17 15:08:34 +00:00
}
2002-03-11 01:29:54 +00:00
// JBravo: no shooting during LCA
2002-03-23 05:17:43 +00:00
if ( pm - > lca ) {
2002-03-11 01:29:54 +00:00
return ;
}
2001-07-01 05:11:12 +00:00
// Elder: fire on release - based on code from inolen
2001-05-06 20:50:27 +00:00
// check for fire
2001-07-03 10:26:42 +00:00
// if they are pressing attack and their current weapon is the grenade
2002-06-16 20:06:15 +00:00
if ( pm - > cmd . buttons & 1 ) {
if ( pm - > ps - > weapon = = WP_GRENADE ) {
if ( pm - > ps - > weaponstate = = WEAPON_READY ) {
2001-11-15 04:20:18 +00:00
// NiceAss: Add a delay so the pin-pull animation can complete.
2001-11-14 06:57:40 +00:00
pm - > ps - > weaponTime = 800 ;
2001-11-15 04:20:18 +00:00
// put it in the "cocked" position and play the pin-pull animation
pm - > ps - > weaponstate = WEAPON_COCKED ;
PM_ContinueWeaponAnim ( WP_ANIM_EXTRA1 ) ;
return ;
2002-06-16 20:06:15 +00:00
} else if ( pm - > ps - > weaponstate = = WEAPON_COCKED )
2001-11-15 04:20:18 +00:00
return ;
2001-11-08 02:37:32 +00:00
}
// Elder: stall the thrown knife action
2001-11-15 07:06:33 +00:00
2002-06-16 20:06:15 +00:00
else if ( pm - > ps - > weapon = = WP_KNIFE & & pm - > ps - > weaponstate ! = WEAPON_STALL & &
pm - > ps - > stats [ STAT_WEAPONSTALLTIME ] < = 0 & &
! ( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_KNIFEMODE ) & & pm - > ps - > ammo [ pm - > ps - > weapon ] ) {
2001-11-08 02:37:32 +00:00
pm - > ps - > weaponstate = WEAPON_STALL ;
pm - > ps - > stats [ STAT_WEAPONSTALLTIME ] = 200 ;
2002-06-16 20:06:15 +00:00
PM_StartWeaponAnim ( WP_ANIM_THROWFIRE ) ;
2001-11-08 02:37:32 +00:00
return ;
}
2001-07-01 05:11:12 +00:00
}
2001-11-14 06:57:40 +00:00
// check for fireA release
2001-07-01 05:11:12 +00:00
// if they aren't pressing attack
2002-06-16 20:06:15 +00:00
if ( ! ( pm - > cmd . buttons & 1 ) ) {
2001-07-01 05:11:12 +00:00
// if we had them cocked and then they aren't pressing it then
// that means they released it
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weapon = = WP_GRENADE ) {
if ( pm - > ps - > weaponstate = = WEAPON_COCKED ) {
2001-11-15 04:20:18 +00:00
// Stall for the toss motion
pm - > ps - > weaponstate = WEAPON_STALL ;
pm - > ps - > stats [ STAT_WEAPONSTALLTIME ] = 300 ;
2002-06-16 20:06:15 +00:00
PM_StartWeaponAnim ( WP_ANIM_FIRE ) ;
2001-11-15 04:20:18 +00:00
return ;
2002-06-16 20:06:15 +00:00
} else if ( pm - > ps - > weaponstate = = WEAPON_STALL ) {
2001-11-15 04:20:18 +00:00
// set to be able to fire
pm - > ps - > weaponstate = WEAPON_READY ;
2002-06-16 20:06:15 +00:00
} else {
2001-11-15 04:20:18 +00:00
// else if they arn't pressing attack, then they just are running around
pm - > ps - > weaponTime = 0 ;
pm - > ps - > weaponstate = WEAPON_READY ;
return ;
}
2001-07-01 05:11:12 +00:00
}
2001-11-15 07:06:33 +00:00
2002-06-16 20:06:15 +00:00
else if ( pm - > ps - > weapon = = WP_KNIFE & & ! ( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_KNIFEMODE ) ) {
if ( pm - > ps - > weaponstate = = WEAPON_STALL ) {
2001-11-15 04:20:18 +00:00
pm - > ps - > stats [ STAT_WEAPONSTALLTIME ] = 0 ;
pm - > ps - > weaponstate = WEAPON_READY ;
2002-06-16 20:06:15 +00:00
} else {
2001-11-15 04:20:18 +00:00
// else if they arn't pressing attack, then they just are running around
pm - > ps - > weaponTime = 0 ;
pm - > ps - > weaponstate = WEAPON_READY ;
return ;
}
2001-11-08 02:37:32 +00:00
}
2001-11-15 07:06:33 +00:00
2002-06-16 20:06:15 +00:00
else {
2001-07-01 05:11:12 +00:00
// else if they arn't pressing attack, then they just are running around
pm - > ps - > weaponTime = 0 ;
pm - > ps - > weaponstate = WEAPON_READY ;
return ;
}
}
2001-08-06 19:15:00 +00:00
// check for out of ammo
2002-06-16 20:06:15 +00:00
if ( ! pm - > ps - > ammo [ pm - > ps - > weapon ] ) {
PM_AddEvent ( EV_NOAMMO ) ;
2001-12-17 15:08:34 +00:00
//NiceAss: Dirty hack:
if ( pm - > ps - > weapon = = WP_KNIFE | | pm - > ps - > weapon = = WP_GRENADE )
//PM_FinishWeaponChange();
pm - > ps - > weaponstate = WEAPON_DROPPING ;
else
pm - > ps - > weaponTime + = 500 ;
2001-08-06 19:15:00 +00:00
return ;
}
//Elder: custom player model fire animations go here
// start the animation even if out of ammo -- Elder: NO WAY
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weapon = = WP_KNIFE | | pm - > ps - > weapon = = WP_GRENADE ) {
if ( pm - > ps - > weapon = = WP_KNIFE & & ( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_KNIFEMODE ) )
// Modified by agt for slash "bursting"
if ( ! pm - > ps - > stats [ STAT_BURST ] )
PM_StartWeaponAnim ( WP_ANIM_FIRE ) ;
2001-09-11 00:12:29 +00:00
2002-06-16 20:06:15 +00:00
PM_StartTorsoAnim ( TORSO_ATTACK2 ) ;
2001-05-06 20:50:27 +00:00
} else {
2001-08-06 19:15:00 +00:00
// Elder: don't repeat if semi-auto
2002-03-31 03:31:24 +00:00
if ( ! ( pm - > ps - > weapon = = WP_PISTOL & & pm - > ps - > stats [ STAT_BURST ] ) | |
2002-06-16 20:06:15 +00:00
! ( pm - > ps - > weapon = = WP_M4 & & pm - > ps - > stats [ STAT_BURST ] > 2 ) | |
! ( pm - > ps - > weapon = = WP_MP5 & & pm - > ps - > stats [ STAT_BURST ] > 2 ) ) {
2003-02-05 04:29:14 +00:00
// NiceAss: Support for akimbo torso attack animations
if ( pm - > ps - > weapon = = WP_AKIMBO )
PM_StartTorsoAnim ( TORSO_ATTACK3 ) ;
2003-03-09 19:47:48 +00:00
else if ( pm - > ps - > weapon = = WP_PISTOL )
PM_StartTorsoAnim ( TORSO_ATTACK4 ) ;
2003-02-05 04:29:14 +00:00
else
PM_StartTorsoAnim ( TORSO_ATTACK ) ;
2001-08-06 19:15:00 +00:00
// QUARANTINE - Weapon animations
// This should change pm->ps->generic1 so we can animate
// Elder: don't repeat if on semi-auto
2001-08-30 09:47:39 +00:00
// temp hack
2002-05-11 18:47:09 +00:00
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weapon = = WP_AKIMBO ) {
2001-09-11 00:12:29 +00:00
// don't repeat animation if on second akimbo shot
2002-06-16 20:06:15 +00:00
if ( ! pm - > ps - > stats [ STAT_BURST ] ) {
if ( pm - > ps - > ammo [ pm - > ps - > weapon ] > 2 )
PM_StartWeaponAnim ( WP_ANIM_FIRE ) ;
2002-03-02 22:02:09 +00:00
else
2002-06-16 20:06:15 +00:00
PM_StartWeaponAnim ( WP_ANIM_EXTRA1 ) ;
2002-03-02 22:02:09 +00:00
}
2002-06-16 20:06:15 +00:00
} else {
if ( pm - > ps - > ammo [ pm - > ps - > weapon ] > 1 | | pm - > ps - > weapon ! = WP_PISTOL )
PM_StartWeaponAnim ( WP_ANIM_FIRE ) ;
2002-05-11 18:47:09 +00:00
else
2002-06-16 20:06:15 +00:00
PM_StartWeaponAnim ( WP_ANIM_EXTRA1 ) ; // Fix for last round fired
2002-03-02 22:02:09 +00:00
}
2001-08-06 19:15:00 +00:00
}
2001-05-06 20:50:27 +00:00
}
2001-11-12 07:59:19 +00:00
2001-12-17 15:08:34 +00:00
//NiceAss: Hack of the week!!!!
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weaponstate = = WEAPON_FIRING & & pm - > ps - > weapon = = WP_GRENADE )
return ;
2001-11-25 23:04:08 +00:00
2001-05-06 20:50:27 +00:00
pm - > ps - > weaponstate = WEAPON_FIRING ;
2001-08-13 17:26:53 +00:00
// Elder: increment stat if alt-fire mode --needs to be predicted as well
2002-06-16 20:06:15 +00:00
if ( ( pm - > ps - > weapon = = WP_M4 & &
( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_M4MODE ) = = RQ3_M4MODE ) | |
( pm - > ps - > weapon = = WP_MP5 & &
( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_MP5MODE ) = = RQ3_MP5MODE ) | |
( pm - > ps - > weapon = = WP_PISTOL & &
( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_MK23MODE ) = = RQ3_MK23MODE ) | |
( pm - > ps - > weapon = = WP_KNIFE & & ( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_KNIFEMODE ) = = RQ3_KNIFEMODE ) ) {
2001-08-13 17:26:53 +00:00
pm - > ps - > stats [ STAT_BURST ] + + ;
}
2002-06-18 06:15:30 +00:00
2001-07-03 10:26:42 +00:00
//Elder: M4 kick code
2002-06-18 06:15:30 +00:00
/*
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weapon = = WP_M4 & & ( ( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_M4MODE ) ! = RQ3_M4MODE ) ) {
2001-07-03 10:26:42 +00:00
pm - > ps - > delta_angles [ 0 ] = ANGLE2SHORT ( SHORT2ANGLE ( pm - > ps - > delta_angles [ 0 ] ) - 0.7 ) ;
}
2002-06-18 06:15:30 +00:00
*/
2001-05-06 20:50:27 +00:00
// take an ammo away if not infinite
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > ammo [ pm - > ps - > weapon ] ! = - 1 ) {
2001-06-10 06:46:06 +00:00
//Elder: don't remove ammo if slashing knife
2002-06-16 20:06:15 +00:00
if ( !
( pm - > ps - > weapon = = WP_KNIFE
& & ( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_KNIFEMODE ) = = RQ3_KNIFEMODE ) ) {
pm - > ps - > ammo [ pm - > ps - > weapon ] - - ;
2001-06-10 06:46:06 +00:00
}
2001-07-09 00:32:10 +00:00
//Elder: special weapon case handling
//Elder: remove knives from inventory if out of ammo
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > weapon = = WP_KNIFE & & pm - > ps - > ammo [ WP_KNIFE ] = = 0 ) {
pm - > ps - > stats [ STAT_WEAPONS ] & = ~ ( 1 < < WP_KNIFE ) ;
2001-07-09 00:32:10 +00:00
}
//Elder: remove grenade from inventory if out of ammo
2002-06-16 20:06:15 +00:00
else if ( pm - > ps - > weapon = = WP_GRENADE & & pm - > ps - > ammo [ WP_GRENADE ] = = 0 ) {
pm - > ps - > stats [ STAT_WEAPONS ] & = ~ ( 1 < < WP_GRENADE ) ;
2001-07-09 00:32:10 +00:00
}
2001-09-01 16:14:14 +00:00
//Elder: remove one more bullet/shell if handcannon
2002-06-16 20:06:15 +00:00
else if ( pm - > ps - > weapon = = WP_HANDCANNON ) {
pm - > ps - > ammo [ WP_HANDCANNON ] - - ;
2001-06-08 04:47:30 +00:00
}
2001-06-26 02:06:50 +00:00
2001-06-08 04:47:30 +00:00
//Elder: sync bullets a la AQ2 style
2001-08-30 09:47:39 +00:00
if ( pm - > ps - > weapon = = WP_AKIMBO & & pm - > ps - > ammo [ WP_AKIMBO ] < 12 ) {
2001-06-08 04:47:30 +00:00
pm - > ps - > ammo [ WP_PISTOL ] = pm - > ps - > ammo [ WP_AKIMBO ] ;
2002-06-16 20:06:15 +00:00
} else if ( pm - > ps - > weapon = = WP_PISTOL & & pm - > ps - > ammo [ WP_AKIMBO ] > 0 ) {
2001-06-08 04:47:30 +00:00
pm - > ps - > ammo [ WP_AKIMBO ] - - ;
}
2001-05-06 20:50:27 +00:00
}
2002-06-18 06:15:30 +00:00
2001-05-06 20:50:27 +00:00
// fire weapon
2002-07-21 18:52:39 +00:00
// NiceAss: Check to see if this is game or cgame
2002-09-08 23:25:09 +00:00
//if (pm->predict) {
2002-07-21 18:52:39 +00:00
//Elder: check for silencer
2002-10-26 00:37:18 +00:00
// JBravo: new multiple itemcode
if ( ( pm - > ps - > stats [ STAT_HOLDABLE_ITEM ] & ( 1 < < HI_SILENCER ) ) & &
2002-07-21 18:52:39 +00:00
( pm - > ps - > weapon = = WP_PISTOL | | pm - > ps - > weapon = = WP_MP5 | | pm - > ps - > weapon = = WP_SSG3000 ) ) {
PM_AddEvent2 ( EV_FIRE_WEAPON , RQ3_WPMOD_SILENCER ) ;
} else if ( pm - > ps - > stats [ STAT_BURST ] > 1 & & pm - > ps - > weapon = = WP_KNIFE & &
( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_KNIFEMODE ) = = RQ3_KNIFEMODE ) {
// NiceAss: Prevent the client from doing stuff after the first "slash".
PM_AddEvent2 ( EV_FIRE_WEAPON , RQ3_WPMOD_KNIFENOMARK ) ;
} else
PM_AddEvent ( EV_FIRE_WEAPON ) ;
2002-09-08 23:25:09 +00:00
//}
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
switch ( pm - > ps - > weapon ) {
2001-05-06 20:50:27 +00:00
default :
2002-06-16 20:06:15 +00:00
//Elder: weapon delay times using constants
2001-05-06 20:50:27 +00:00
case WP_SSG3000 :
2001-06-18 01:59:58 +00:00
addTime = RQ3_SSG3000_DELAY ;
2001-05-06 20:50:27 +00:00
break ;
case WP_PISTOL :
2001-06-18 01:59:58 +00:00
addTime = RQ3_PISTOL_DELAY ;
2001-05-06 20:50:27 +00:00
break ;
case WP_M4 :
2001-06-18 01:59:58 +00:00
addTime = RQ3_M4_DELAY ;
2001-05-06 20:50:27 +00:00
break ;
case WP_MP5 :
2001-06-18 01:59:58 +00:00
addTime = RQ3_MP5_DELAY ;
2001-05-06 20:50:27 +00:00
break ;
case WP_KNIFE :
2002-06-16 20:06:15 +00:00
if ( ( pm - > ps - > persistant [ PERS_WEAPONMODES ] & RQ3_KNIFEMODE ) = = RQ3_KNIFEMODE ) {
2001-06-18 01:59:58 +00:00
//knife slash
2001-12-17 15:08:34 +00:00
//agt: hacking it up a little. The alternate time value should be
//a constant, but I have a headache and I'm tired of screwing around
//with the knives. [NiceAss: I'll do it for you!]
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > stats [ STAT_BURST ] ) {
addTime = RQ3_KNIFE_SLASH_BURST ; //NiceAss: Not really a burst, but it fits with everything else =D
2001-12-17 15:08:34 +00:00
} else {
addTime = RQ3_KNIFE_DELAY ;
}
2002-06-16 20:06:15 +00:00
} else {
2001-06-18 01:59:58 +00:00
//knife throw
addTime = RQ3_THROW_DELAY ;
}
2001-05-06 20:50:27 +00:00
break ;
case WP_HANDCANNON :
2001-06-18 01:59:58 +00:00
addTime = RQ3_HANDCANNON_DELAY ;
2001-05-06 20:50:27 +00:00
break ;
case WP_M3 :
2001-06-18 01:59:58 +00:00
addTime = RQ3_M3_DELAY ;
2001-05-06 20:50:27 +00:00
break ;
case WP_AKIMBO :
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > stats [ STAT_BURST ] ) {
2001-09-01 16:14:14 +00:00
addTime = RQ3_AKIMBO_DELAY2 ;
pm - > ps - > stats [ STAT_BURST ] = 0 ;
2002-06-16 20:06:15 +00:00
} else {
2001-09-01 16:14:14 +00:00
pm - > ps - > stats [ STAT_BURST ] = 1 ;
addTime = RQ3_AKIMBO_DELAY ;
}
2001-05-06 20:50:27 +00:00
break ;
case WP_GRENADE :
2001-06-18 01:59:58 +00:00
addTime = RQ3_GRENADE_DELAY ;
2001-05-06 20:50:27 +00:00
break ;
}
pm - > ps - > weaponTime + = addTime ;
2001-06-26 02:06:50 +00:00
//Auto-switch when out of ammo with grenade or knife
2002-06-16 20:06:15 +00:00
if ( ( pm - > ps - > weapon = = WP_KNIFE | | pm - > ps - > weapon = = WP_GRENADE ) & & ! pm - > ps - > ammo [ pm - > ps - > weapon ] ) {
PM_AddEvent ( EV_NOAMMO ) ;
2001-06-26 02:06:50 +00:00
pm - > ps - > weaponTime + = 150 ;
}
2001-05-06 20:50:27 +00:00
}
/*
= = = = = = = = = = = = = = = =
PM_Animate
= = = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_Animate ( void )
{
if ( pm - > cmd . buttons & BUTTON_GESTURE ) {
if ( pm - > ps - > torsoTimer = = 0 ) {
PM_StartTorsoAnim ( TORSO_GESTURE ) ;
2001-05-06 20:50:27 +00:00
pm - > ps - > torsoTimer = TIMER_GESTURE ;
2002-06-16 20:06:15 +00:00
PM_AddEvent ( EV_TAUNT ) ;
2001-05-06 20:50:27 +00:00
}
}
}
/*
= = = = = = = = = = = = = = = =
PM_DropTimers
= = = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_DropTimers ( void )
{
2001-05-06 20:50:27 +00:00
// drop misc timing counter
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > pm_time ) {
if ( pml . msec > = pm - > ps - > pm_time ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > pm_flags & = ~ PMF_ALL_TIMES ;
pm - > ps - > pm_time = 0 ;
} else {
pm - > ps - > pm_time - = pml . msec ;
}
}
// drop animation counter
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > legsTimer > 0 ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > legsTimer - = pml . msec ;
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > legsTimer < 0 ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > legsTimer = 0 ;
}
}
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > torsoTimer > 0 ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > torsoTimer - = pml . msec ;
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > torsoTimer < 0 ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > torsoTimer = 0 ;
}
}
}
/*
= = = = = = = = = = = = = = = =
PM_UpdateViewAngles
This can be used as another entry point when only the viewangles
are being updated isntead of a full move
= = = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
void PM_UpdateViewAngles ( playerState_t * ps , const usercmd_t * cmd )
{
short temp ;
int i ;
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
if ( ps - > pm_type = = PM_INTERMISSION | | ps - > pm_type = = PM_SPINTERMISSION ) {
2001-05-06 20:50:27 +00:00
return ; // no view changes at all
}
2002-06-16 20:06:15 +00:00
if ( ps - > pm_type ! = PM_SPECTATOR & & ps - > stats [ STAT_HEALTH ] < = 0 ) {
2001-05-06 20:50:27 +00:00
return ; // no view changes at all
}
// circularly clamp the angles with deltas
2002-06-16 20:06:15 +00:00
for ( i = 0 ; i < 3 ; i + + ) {
2001-05-06 20:50:27 +00:00
temp = cmd - > angles [ i ] + ps - > delta_angles [ i ] ;
2002-06-16 20:06:15 +00:00
if ( i = = PITCH ) {
2001-05-06 20:50:27 +00:00
// don't let the player look up or down more than 90 degrees
2002-06-16 20:06:15 +00:00
if ( temp > 16000 ) {
2001-05-06 20:50:27 +00:00
ps - > delta_angles [ i ] = 16000 - cmd - > angles [ i ] ;
temp = 16000 ;
2002-06-16 20:06:15 +00:00
} else if ( temp < - 16000 ) {
2001-05-06 20:50:27 +00:00
ps - > delta_angles [ i ] = - 16000 - cmd - > angles [ i ] ;
temp = - 16000 ;
}
}
ps - > viewangles [ i ] = SHORT2ANGLE ( temp ) ;
}
}
2002-06-16 20:06:15 +00:00
2001-05-06 20:50:27 +00:00
/*
= = = = = = = = = = = = = = = = = = =
PM_LadderMove ( )
by : Calrathan [ Arthur Tomlin ]
2001-11-12 07:59:19 +00:00
Right now all I know is that this works for VERTICAL ladders .
2001-05-06 20:50:27 +00:00
Ladders with angles on them ( urban2 for AQ2 ) haven ' t been tested .
= = = = = = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
static void PM_LadderMove ( void )
{
2005-02-15 16:33:39 +00:00
int i , old ;
2001-05-06 20:50:27 +00:00
vec3_t wishvel ;
float wishspeed ;
vec3_t wishdir ;
float scale ;
float vel ;
2001-08-18 19:59:25 +00:00
// Elder: ladder jump crap
2002-06-16 20:06:15 +00:00
trace_t tr ;
vec3_t lookAhead ;
vec3_t trEndTest ;
2001-08-18 19:59:25 +00:00
2001-08-30 09:47:39 +00:00
// 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 ;
2002-06-16 20:06:15 +00:00
VectorNormalize ( lookAhead ) ;
2001-08-30 09:47:39 +00:00
// Calculate end point
2002-06-16 20:06:15 +00:00
VectorMA ( pm - > ps - > origin , 1 , lookAhead , trEndTest ) ;
2001-08-30 09:47:39 +00:00
//trEndTest[2] += 20;
trEndTest [ 2 ] + = 6 ;
// Calculate start point
VectorCopy ( pm - > ps - > origin , lookAhead ) ;
//lookAhead[2] += 16;
lookAhead [ 2 ] + = 2 ;
2002-06-16 20:06:15 +00:00
pm - > trace ( & tr , lookAhead , pm - > mins , pm - > maxs , trEndTest , pm - > ps - > clientNum , MASK_PLAYERSOLID ) ;
2001-08-30 09:47:39 +00:00
2002-06-16 20:06:15 +00:00
if ( tr . fraction = = 1 | | ! ( tr . surfaceFlags & SURF_LADDER ) ) {
2001-08-30 09:47:39 +00:00
// good conditions -- now we can set up a double jump on the ladder
if ( pm - > debugLevel )
Com_Printf ( " Ladder jump conditions met... \n " ) ;
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > stats [ STAT_JUMPTIME ] > 0 & & PM_CheckJump ( ) ) {
2001-08-30 09:47:39 +00:00
if ( pm - > debugLevel )
Com_Printf ( " Trying ladder jump... \n " ) ;
pml . ladder = qfalse ;
}
}
// End ladder jump crap
# endif
2001-08-18 19:59:25 +00:00
2002-06-16 20:06:15 +00:00
PM_Friction ( ) ;
2001-08-30 09:47:39 +00:00
//pml.ladder = qtrue;
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
scale = PM_CmdScale ( & pm - > cmd ) ;
2001-05-06 20:50:27 +00:00
// user intentions [what the user is attempting to do]
2002-06-16 20:06:15 +00:00
if ( ! scale ) {
2001-05-06 20:50:27 +00:00
wishvel [ 0 ] = 0 ;
wishvel [ 1 ] = 0 ;
wishvel [ 2 ] = 0 ;
2002-06-16 20:06:15 +00:00
} else { // if they're trying to move... lets calculate it
for ( i = 0 ; i < 3 ; i + + )
wishvel [ i ] = scale * pml . forward [ i ] * pm - > cmd . forwardmove +
scale * pml . right [ i ] * pm - > cmd . rightmove ;
2001-07-16 01:40:33 +00:00
//Elder: changed from a factor of 2 to 10
2001-07-24 01:50:01 +00:00
wishvel [ 0 ] / = PM_LADDER_MOVE_REDUCTION ;
wishvel [ 1 ] / = PM_LADDER_MOVE_REDUCTION ;
2001-05-06 20:50:27 +00:00
wishvel [ 2 ] + = scale * pm - > cmd . upmove ;
}
2002-06-16 20:06:15 +00:00
VectorCopy ( wishvel , wishdir ) ;
2001-05-06 20:50:27 +00:00
wishspeed = VectorNormalize ( wishdir ) ;
2002-06-16 20:06:15 +00:00
if ( wishspeed > pm - > ps - > speed * pm_ladderScale ) {
2001-05-06 20:50:27 +00:00
wishspeed = pm - > ps - > speed * pm_ladderScale ;
}
2001-08-30 09:47:39 +00:00
// Old ladder jump code -- right now it works better
# if 1
2001-08-18 19:59:25 +00:00
// Elder: ladder jump crap
lookAhead [ 0 ] = pml . forward [ 0 ] ;
lookAhead [ 1 ] = pml . forward [ 1 ] ;
lookAhead [ 2 ] = 0 ;
2002-06-16 20:06:15 +00:00
VectorNormalize ( lookAhead ) ;
2001-08-18 19:59:25 +00:00
// Calculate end point
2002-06-16 20:06:15 +00:00
VectorMA ( pm - > ps - > origin , 1 , lookAhead , trEndTest ) ;
2001-08-18 19:59:25 +00:00
trEndTest [ 2 ] + = 20 ;
// Calculate start point
VectorCopy ( pm - > ps - > origin , lookAhead ) ;
lookAhead [ 2 ] + = 16 ;
2002-06-16 20:06:15 +00:00
pm - > trace ( & tr , lookAhead , pm - > mins , pm - > maxs , trEndTest , pm - > ps - > clientNum , MASK_PLAYERSOLID ) ;
2001-08-18 19:59:25 +00:00
2002-06-16 20:06:15 +00:00
if ( tr . fraction = = 1 | | ! ( tr . surfaceFlags & SURF_LADDER ) ) {
2001-08-18 19:59:25 +00:00
// good conditions -- now we can set up a double jump on the ladder
if ( pm - > debugLevel )
Com_Printf ( " Ladder jump conditions met... \n " ) ;
2002-06-16 20:06:15 +00:00
if ( PM_CheckJump ( ) ) {
2001-08-18 19:59:25 +00:00
if ( pm - > debugLevel )
2001-08-30 09:47:39 +00:00
Com_Printf ( " Trying ladder jump... \n " ) ;
2001-08-18 19:59:25 +00:00
}
}
// End ladder jump crap
2001-08-30 09:47:39 +00:00
# endif
2001-11-12 07:59:19 +00:00
2002-06-16 20:06:15 +00:00
PM_Accelerate ( wishdir , wishspeed , pm_ladderAccelerate ) ;
2001-05-06 20:50:27 +00:00
// This SHOULD help us with sloped ladders, but it remains untested.
2002-06-16 20:06:15 +00:00
if ( pml . groundPlane & & DotProduct ( pm - > ps - > velocity , pml . groundTrace . plane . normal ) < 0 ) {
2001-05-06 20:50:27 +00:00
vel = VectorLength ( pm - > ps - > velocity ) ;
2001-11-12 07:59:19 +00:00
// slide along the ground plane [the ladder section under our feet]
2002-06-16 20:06:15 +00:00
PM_ClipVelocity ( pm - > ps - > velocity , pml . groundTrace . plane . normal , pm - > ps - > velocity , OVERCLIP ) ;
2001-05-06 20:50:27 +00:00
VectorNormalize ( pm - > ps - > velocity ) ;
VectorScale ( pm - > ps - > velocity , vel , pm - > ps - > velocity ) ;
}
2002-06-16 20:06:15 +00:00
PM_StepSlideMove ( qfalse ) ; // move without gravity
2001-08-18 19:59:25 +00:00
// Elder: stop legs from animating
2005-02-15 16:33:39 +00:00
//PM_ForceLegsAnim(LEGS_JUMP);
//Makro - changed to LEGS_IDLE
PM_ForceLegsAnim ( LEGS_IDLE ) ;
//Makro - play footstep sound
2005-09-07 20:27:42 +00:00
//...only if we don't have slippers!
if ( pm - > ps - > velocity [ 2 ] & & ! ( pm - > ps - > stats [ STAT_HOLDABLE_ITEM ] & & ( 1 < < HI_SLIPPERS ) ) )
{
2005-02-15 16:33:39 +00:00
old = pm - > ps - > bobCycle ;
//the faster we move, the more frequent the footsteps
pm - > ps - > bobCycle = ( int ) ( old + 0.45 * fabs ( pm - > ps - > velocity [ 2 ] ) / 225.0f * pml . msec ) & 255 ;
// if we just crossed a cycle boundary, play an apropriate footstep event
2005-09-07 20:27:42 +00:00
if ( ( ( old + 64 ) ^ ( pm - > ps - > bobCycle + 64 ) ) & 128 )
{
2007-07-31 20:02:56 +00:00
//PM_AddEvent(PM_FootstepForSurface(pml.ladderSurface));
2005-02-15 16:33:39 +00:00
}
} else {
pm - > ps - > bobCycle = 0 ;
}
2001-05-06 20:50:27 +00:00
}
/*
= = = = = = = = = = = = =
CheckLadder [ ARTHUR TOMLIN ]
= = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
void CheckLadder ( void )
2001-05-06 20:50:27 +00:00
{
2002-06-16 20:06:15 +00:00
vec3_t flatforward , spot ;
2001-05-06 20:50:27 +00:00
trace_t trace ;
2001-08-18 19:59:25 +00:00
2001-05-06 20:50:27 +00:00
pml . ladder = qfalse ;
2002-06-29 02:50:58 +00:00
2001-05-06 20:50:27 +00:00
// check for ladder
flatforward [ 0 ] = pml . forward [ 0 ] ;
flatforward [ 1 ] = pml . forward [ 1 ] ;
flatforward [ 2 ] = 0 ;
2002-06-16 20:06:15 +00:00
VectorNormalize ( flatforward ) ;
2001-08-18 19:59:25 +00:00
2002-06-16 20:06:15 +00:00
VectorMA ( pm - > ps - > origin , 1 , flatforward , spot ) ;
pm - > trace ( & trace , pm - > ps - > origin , pm - > mins , pm - > maxs , spot , pm - > ps - > clientNum , MASK_PLAYERSOLID ) ;
2001-05-06 20:50:27 +00:00
2005-02-15 16:33:39 +00:00
//Makro - save the surface flags so we can play the appropriate sound
pml . ladderSurface = trace . surfaceFlags ;
2001-05-06 20:50:27 +00:00
if ( ( trace . fraction < 1 ) & & ( trace . surfaceFlags & SURF_LADDER ) )
pml . ladder = qtrue ;
2001-08-18 19:59:25 +00:00
// Elder: does this work?
2001-10-11 22:52:43 +00:00
/*
2002-06-16 20:06:15 +00:00
if ( pml . ladder & & pml . previous_ladder = = qfalse )
{
if ( pm - > debugLevel )
Com_Printf ( " Hit ladder hard \n " ) ;
PM_CrashLand ( ) ;
}
*/
2001-05-06 20:50:27 +00:00
}
/*
= = = = = = = = = = = = = = = =
PmoveSingle
= = = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
void trap_SnapVector ( float * v ) ;
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
void PmoveSingle ( pmove_t * pmove )
{
2001-05-06 20:50:27 +00:00
pm = pmove ;
// this counter lets us debug movement problems with a journal
// by setting a conditional breakpoint fot the previous frame
c_pmove + + ;
// clear results
pm - > numtouch = 0 ;
pm - > watertype = 0 ;
pm - > waterlevel = 0 ;
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > stats [ STAT_HEALTH ] < = 0 ) {
2001-05-06 20:50:27 +00:00
pm - > tracemask & = ~ CONTENTS_BODY ; // corpses can fly through bodies
}
// make sure walking button is clear if they are running, to avoid
// proxy no-footsteps cheats
2002-06-16 20:06:15 +00:00
if ( abs ( pm - > cmd . forwardmove ) > 64 | | abs ( pm - > cmd . rightmove ) > 64 ) {
2001-05-06 20:50:27 +00:00
pm - > cmd . buttons & = ~ BUTTON_WALKING ;
}
// set the talk balloon flag
2002-06-16 20:06:15 +00:00
if ( pm - > cmd . buttons & BUTTON_TALK ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > eFlags | = EF_TALK ;
} else {
pm - > ps - > eFlags & = ~ EF_TALK ;
}
// set the firing flag for continuous beam weapons
2002-06-16 20:06:15 +00:00
if ( ! ( pm - > ps - > pm_flags & PMF_RESPAWNED ) & & pm - > ps - > pm_type ! = PM_INTERMISSION
& & ( pm - > cmd . buttons & BUTTON_ATTACK ) & & pm - > ps - > ammo [ pm - > ps - > weapon ] ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > eFlags | = EF_FIRING ;
} else {
pm - > ps - > eFlags & = ~ EF_FIRING ;
}
// clear the respawned flag if attack and use are cleared
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > stats [ STAT_HEALTH ] > 0 & & ! ( pm - > cmd . buttons & ( BUTTON_ATTACK | BUTTON_USE_HOLDABLE ) ) ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > pm_flags & = ~ PMF_RESPAWNED ;
}
// if talk button is down, dissallow all other input
// this is to prevent any possible intercept proxy from
// adding fake talk balloons
2002-06-16 20:06:15 +00:00
if ( pmove - > cmd . buttons & BUTTON_TALK ) {
2001-05-06 20:50:27 +00:00
// keep the talk button set tho for when the cmd.serverTime > 66 msec
// and the same cmd is used multiple times in Pmove
pmove - > cmd . buttons = BUTTON_TALK ;
pmove - > cmd . forwardmove = 0 ;
pmove - > cmd . rightmove = 0 ;
pmove - > cmd . upmove = 0 ;
}
// clear all pmove local vars
2002-06-16 20:06:15 +00:00
memset ( & pml , 0 , sizeof ( pml ) ) ;
2001-05-06 20:50:27 +00:00
// determine the time
pml . msec = pmove - > cmd . serverTime - pm - > ps - > commandTime ;
2002-06-16 20:06:15 +00:00
if ( pml . msec < 1 ) {
2001-05-06 20:50:27 +00:00
pml . msec = 1 ;
2002-06-16 20:06:15 +00:00
} else if ( pml . msec > 200 ) {
2001-05-06 20:50:27 +00:00
pml . msec = 200 ;
}
pm - > ps - > commandTime = pmove - > cmd . serverTime ;
// save old org in case we get stuck
2002-06-16 20:06:15 +00:00
VectorCopy ( pm - > ps - > origin , pml . previous_origin ) ;
2001-05-06 20:50:27 +00:00
// save old velocity for crashlanding
2002-06-16 20:06:15 +00:00
VectorCopy ( pm - > ps - > velocity , pml . previous_velocity ) ;
2001-05-06 20:50:27 +00:00
pml . frametime = pml . msec * 0.001 ;
// update the viewangles
2001-11-12 07:59:19 +00:00
2002-06-16 20:06:15 +00:00
PM_UpdateViewAngles ( pm - > ps , & pm - > cmd ) ;
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
AngleVectors ( pm - > ps - > viewangles , pml . forward , pml . right , pml . up ) ;
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
if ( pm - > cmd . upmove < 10 ) {
2001-05-06 20:50:27 +00:00
// not holding jump
pm - > ps - > pm_flags & = ~ PMF_JUMP_HELD ;
}
// decide if backpedaling animations should be used
2002-06-16 20:06:15 +00:00
if ( pm - > cmd . forwardmove < 0 ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > pm_flags | = PMF_BACKWARDS_RUN ;
2002-06-16 20:06:15 +00:00
} else if ( pm - > cmd . forwardmove > 0 | | ( pm - > cmd . forwardmove = = 0 & & pm - > cmd . rightmove ) ) {
2001-05-06 20:50:27 +00:00
pm - > ps - > pm_flags & = ~ PMF_BACKWARDS_RUN ;
}
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > pm_type > = PM_DEAD ) {
2001-05-06 20:50:27 +00:00
pm - > cmd . forwardmove = 0 ;
pm - > cmd . rightmove = 0 ;
pm - > cmd . upmove = 0 ;
}
2001-11-12 07:59:19 +00:00
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > pm_type = = PM_SPECTATOR ) {
PM_CheckDuck ( ) ;
PM_FlyMove ( ) ;
PM_DropTimers ( ) ;
2001-05-06 20:50:27 +00:00
return ;
}
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > pm_type = = PM_NOCLIP ) {
PM_NoclipMove ( ) ;
PM_DropTimers ( ) ;
2001-05-06 20:50:27 +00:00
return ;
}
if ( pm - > ps - > pm_type = = PM_FREEZE ) {
return ; // no movement at all
}
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > pm_type = = PM_INTERMISSION | | pm - > ps - > pm_type = = PM_SPINTERMISSION ) {
2001-05-06 20:50:27 +00:00
return ; // no movement at all
}
// set watertype, and waterlevel
PM_SetWaterLevel ( ) ;
pml . previous_waterlevel = pmove - > waterlevel ;
// set mins, maxs, and viewheight
2002-06-16 20:06:15 +00:00
PM_CheckDuck ( ) ;
2001-05-06 20:50:27 +00:00
// set groundentity
PM_GroundTrace ( ) ;
2002-06-16 20:06:15 +00:00
if ( pm - > ps - > pm_type = = PM_DEAD ) {
PM_DeadMove ( ) ;
2001-05-06 20:50:27 +00:00
}
PM_DropTimers ( ) ;
2002-06-16 20:06:15 +00:00
CheckLadder ( ) ; // ARTHUR TOMLIN check and see if they're on a ladder
2001-05-06 20:50:27 +00:00
2002-07-22 06:35:03 +00:00
if ( pm - > ps - > pm_flags & PMF_GRAPPLE_PULL ) {
2001-05-06 20:50:27 +00:00
PM_GrappleMove ( ) ;
// We can wiggle a bit
PM_AirMove ( ) ;
} else if ( pm - > ps - > pm_flags & PMF_TIME_WATERJUMP ) {
PM_WaterJumpMove ( ) ;
2002-06-16 20:06:15 +00:00
} else if ( pm - > waterlevel > 1 & & ! pml . ladder ) { //Blaze: wtf, need to add a comment to make it a big enough change for cvs to notice
2001-05-06 20:50:27 +00:00
// swimming
PM_WaterMove ( ) ;
2002-06-16 20:06:15 +00:00
// Elder: Added !(...) check below to prevent crouch spasms at bottom of ladders
} else if ( pml . ladder
& & ! ( pm - > ps - > viewheight = = CROUCH_VIEWHEIGHT & & pm - > ps - > groundEntityNum ! = ENTITYNUM_NONE ) ) {
2001-05-06 20:50:27 +00:00
PM_LadderMove ( ) ;
2002-06-16 20:06:15 +00:00
} else if ( pml . walking ) {
2001-05-06 20:50:27 +00:00
// walking on ground
PM_WalkMove ( ) ;
2001-11-12 07:59:19 +00:00
2002-05-27 06:48:02 +00:00
// NiceAss: New leg damage, based on the AQ2 leg damage code.
2002-06-18 05:18:55 +00:00
if ( pm - > ps - > stats [ STAT_RQ3 ] & RQ3_LEGDAMAGE & & pm - > ps - > groundEntityNum ! = ENTITYNUM_NONE ) {
2002-05-27 06:48:02 +00:00
int i ;
2002-06-18 05:18:55 +00:00
if ( ( pm - > cmd . serverTime % 600 ) < 250 ) {
for ( i = 0 ; i < 3 ; i + + ) {
if ( i < 2 | | pm - > ps - > velocity [ 2 ] > 0 )
pm - > ps - > velocity [ i ] / = 4 ;
}
2002-05-27 06:48:02 +00:00
}
2001-06-13 01:14:31 +00:00
}
2001-05-06 20:50:27 +00:00
} else {
// airborne
PM_AirMove ( ) ;
}
PM_Animate ( ) ;
// set groundentity, watertype, and waterlevel
PM_GroundTrace ( ) ;
PM_SetWaterLevel ( ) ;
// weapons
2002-09-08 23:25:09 +00:00
if ( pm - > predict ) {
PM_Reload ( ) ;
PM_Weapon ( ) ;
}
2001-05-06 20:50:27 +00:00
// torso animation
PM_TorsoAnimation ( ) ;
// footstep events / legs animations
2005-02-15 16:33:39 +00:00
//Makro - ladder footsteps already handled in PM_LadderMove
if ( ! pml . ladder )
PM_Footsteps ( ) ;
2001-05-06 20:50:27 +00:00
// entering / leaving water splashes
2002-08-03 07:04:18 +00:00
// JBravo: only if you are alive
if ( pm - > ps - > stats [ STAT_HEALTH ] > 0 )
PM_WaterEvents ( ) ;
2001-05-06 20:50:27 +00:00
// snap some parts of playerstate to save network bandwidth
2002-06-16 20:06:15 +00:00
trap_SnapVector ( pm - > ps - > velocity ) ;
2001-05-06 20:50:27 +00:00
}
/*
= = = = = = = = = = = = = = = =
Pmove
Can be called by either the server or the client
= = = = = = = = = = = = = = = =
*/
2002-06-16 20:06:15 +00:00
void Pmove ( pmove_t * pmove )
{
int finalTime ;
2001-05-06 20:50:27 +00:00
finalTime = pmove - > cmd . serverTime ;
2002-06-16 20:06:15 +00:00
if ( finalTime < pmove - > ps - > commandTime ) {
return ; // should not happen
2001-05-06 20:50:27 +00:00
}
2002-06-16 20:06:15 +00:00
if ( finalTime > pmove - > ps - > commandTime + 1000 ) {
2001-05-06 20:50:27 +00:00
pmove - > ps - > commandTime = finalTime - 1000 ;
}
2002-06-16 20:06:15 +00:00
pmove - > ps - > pmove_framecount = ( pmove - > ps - > pmove_framecount + 1 ) & ( ( 1 < < PS_PMOVEFRAMECOUNTBITS ) - 1 ) ;
2001-05-06 20:50:27 +00:00
// chop the move up if it is too long, to prevent framerate
// dependent behavior
2002-06-16 20:06:15 +00:00
while ( pmove - > ps - > commandTime ! = finalTime ) {
int msec ;
2001-05-06 20:50:27 +00:00
msec = finalTime - pmove - > ps - > commandTime ;
2002-06-16 20:06:15 +00:00
if ( pmove - > pmove_fixed ) {
if ( msec > pmove - > pmove_msec ) {
2001-05-06 20:50:27 +00:00
msec = pmove - > pmove_msec ;
}
2002-06-16 20:06:15 +00:00
} else {
if ( msec > 66 ) {
2001-05-06 20:50:27 +00:00
msec = 66 ;
}
}
pmove - > cmd . serverTime = pmove - > ps - > commandTime + msec ;
2002-06-16 20:06:15 +00:00
PmoveSingle ( pmove ) ;
2001-05-06 20:50:27 +00:00
2002-06-16 20:06:15 +00:00
if ( pmove - > ps - > pm_flags & PMF_JUMP_HELD ) {
2001-05-06 20:50:27 +00:00
pmove - > cmd . upmove = 20 ;
}
}
//PM_CheckStuck();
}