2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
2012-11-28 15:47:07 +00:00
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
2012-11-26 18:58:24 +00:00
Doom 3 BFG Edition Source Code is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 BFG Edition Source Code is also subject to certain additional terms . You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code . If not , please request a copy in writing from id Software at the address below .
If you have questions concerning this license or the applicable additional terms , you may contact in writing id Software LLC , c / o ZeniMax Media Inc . , Suite 120 , Rockville , Maryland 20850 USA .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# pragma hdrstop
# include "../../idlib/precompiled.h"
# include "../Game_local.h"
CLASS_DECLARATION ( idPhysics_Actor , idPhysics_Player )
END_CLASS
// movement parameters
const float PM_STOPSPEED = 100.0f ;
const float PM_SWIMSCALE = 0.5f ;
const float PM_LADDERSPEED = 100.0f ;
const float PM_STEPSCALE = 1.0f ;
const float PM_ACCELERATE = 10.0f ;
const float PM_AIRACCELERATE = 1.0f ;
const float PM_WATERACCELERATE = 4.0f ;
const float PM_FLYACCELERATE = 8.0f ;
const float PM_FRICTION = 6.0f ;
const float PM_AIRFRICTION = 0.0f ;
const float PM_WATERFRICTION = 1.0f ;
const float PM_FLYFRICTION = 3.0f ;
const float PM_NOCLIPFRICTION = 12.0f ;
const float MIN_WALK_NORMAL = 0.7f ; // can't walk on very steep slopes
const float OVERCLIP = 1.001f ;
// movementFlags
const int PMF_DUCKED = 1 ; // set when ducking
const int PMF_JUMPED = 2 ; // set when the player jumped this frame
const int PMF_STEPPED_UP = 4 ; // set when the player stepped up this frame
const int PMF_STEPPED_DOWN = 8 ; // set when the player stepped down this frame
const int PMF_JUMP_HELD = 16 ; // set when jump button is held down
const int PMF_TIME_LAND = 32 ; // movementTime is time before rejump
const int PMF_TIME_KNOCKBACK = 64 ; // movementTime is an air-accelerate only time
const int PMF_TIME_WATERJUMP = 128 ; // movementTime is waterjump
2012-11-28 15:47:07 +00:00
const int PMF_ALL_TIMES = ( PMF_TIME_WATERJUMP | PMF_TIME_LAND | PMF_TIME_KNOCKBACK ) ;
2012-11-26 18:58:24 +00:00
int c_pmove = 0 ;
extern idCVar pm_clientInterpolation_Divergence ;
/*
= = = = = = = = = = = =
idPhysics_Player : : 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 .
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
float idPhysics_Player : : CmdScale ( const usercmd_t & cmd ) const
{
2012-11-26 18:58:24 +00:00
int max ;
float total ;
float scale ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int forwardmove = cmd . forwardmove ;
int rightmove = cmd . rightmove ;
int upmove = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// since the crouch key doubles as downward movement, ignore downward movement when we're on the ground
// otherwise crouch speed will be lower than specified
2012-11-28 15:47:07 +00:00
if ( ! walking )
{
2012-11-26 18:58:24 +00:00
upmove = ( ( cmd . buttons & BUTTON_JUMP ) ? 127 : 0 ) - ( ( cmd . buttons & BUTTON_CROUCH ) ? 127 : 0 ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
max = abs ( forwardmove ) ;
2012-11-28 15:47:07 +00:00
if ( abs ( rightmove ) > max )
{
2012-11-26 18:58:24 +00:00
max = abs ( rightmove ) ;
}
2012-11-28 15:47:07 +00:00
if ( abs ( upmove ) > max )
{
2012-11-26 18:58:24 +00:00
max = abs ( upmove ) ;
}
2012-11-28 15:47:07 +00:00
if ( ! max )
{
2012-11-26 18:58:24 +00:00
return 0.0f ;
}
2012-11-28 15:47:07 +00:00
total = idMath : : Sqrt ( ( float ) forwardmove * forwardmove + rightmove * rightmove + upmove * upmove ) ;
scale = ( float ) playerSpeed * max / ( 127.0f * total ) ;
2012-11-26 18:58:24 +00:00
return scale ;
}
/*
= = = = = = = = = = = = = =
idPhysics_Player : : Accelerate
Handles user intended acceleration
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : Accelerate ( const idVec3 & wishdir , const float wishspeed , const float accel )
{
2012-11-26 18:58:24 +00:00
# if 1
// q2 style
float addspeed , accelspeed , currentspeed ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
currentspeed = current . velocity * wishdir ;
addspeed = wishspeed - currentspeed ;
2012-11-28 15:47:07 +00:00
if ( addspeed < = 0 )
{
2012-11-26 18:58:24 +00:00
return ;
}
accelspeed = accel * frametime * wishspeed ;
2012-11-28 15:47:07 +00:00
if ( accelspeed > addspeed )
{
2012-11-26 18:58:24 +00:00
accelspeed = addspeed ;
}
current . velocity + = accelspeed * wishdir ;
# else
// proper way (avoids strafe jump maxspeed bug), but feels bad
idVec3 wishVelocity ;
idVec3 pushDir ;
float pushLen ;
float canPush ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
wishVelocity = wishdir * wishspeed ;
pushDir = wishVelocity - current . velocity ;
pushLen = pushDir . Normalize ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
canPush = accel * frametime * wishspeed ;
2012-11-28 15:47:07 +00:00
if ( canPush > pushLen )
{
2012-11-26 18:58:24 +00:00
canPush = pushLen ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
current . velocity + = canPush * pushDir ;
# endif
}
/*
= = = = = = = = = = = = = = = = = =
idPhysics_Player : : SlideMove
Returns true if the velocity was clipped in some way
= = = = = = = = = = = = = = = = = =
*/
# define MAX_CLIP_PLANES 5
2012-11-28 15:47:07 +00:00
bool idPhysics_Player : : SlideMove ( bool gravity , bool stepUp , bool stepDown , bool push )
{
2012-11-26 18:58:24 +00:00
int i , j , k , pushFlags ;
int bumpcount , numbumps , numplanes ;
float d , time_left , into , totalMass ;
idVec3 dir , planes [ MAX_CLIP_PLANES ] ;
idVec3 end , stepEnd , primal_velocity , endVelocity , endClipVelocity , clipVelocity ;
trace_t trace , stepTrace , downTrace ;
bool nearGround , stepped , pushed ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
numbumps = 4 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
primal_velocity = current . velocity ;
2012-11-28 15:47:07 +00:00
if ( gravity )
{
2012-11-26 18:58:24 +00:00
endVelocity = current . velocity + gravityVector * frametime ;
current . velocity = ( current . velocity + endVelocity ) * 0.5f ;
primal_velocity = endVelocity ;
2012-11-28 15:47:07 +00:00
if ( groundPlane )
{
2012-11-26 18:58:24 +00:00
// slide along the ground plane
current . velocity . ProjectOntoPlane ( groundTrace . c . normal , OVERCLIP ) ;
}
}
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
endVelocity = current . velocity ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
time_left = frametime ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// never turn against the ground plane
2012-11-28 15:47:07 +00:00
if ( groundPlane )
{
2012-11-26 18:58:24 +00:00
numplanes = 1 ;
planes [ 0 ] = groundTrace . c . normal ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
numplanes = 0 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// never turn against original velocity
planes [ numplanes ] = current . velocity ;
planes [ numplanes ] . Normalize ( ) ;
numplanes + + ;
2012-11-28 15:47:07 +00:00
for ( bumpcount = 0 ; bumpcount < numbumps ; bumpcount + + )
{
2012-11-26 18:58:24 +00:00
// calculate position we are trying to move to
end = current . origin + time_left * current . velocity ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// see if we can make it there
gameLocal . clip . Translation ( trace , current . origin , end , clipModel , clipModel - > GetAxis ( ) , clipMask , self ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
time_left - = time_left * trace . fraction ;
current . origin = trace . endpos ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if moved the entire distance
2012-11-28 15:47:07 +00:00
if ( trace . fraction > = 1.0f )
{
2012-11-26 18:58:24 +00:00
break ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
stepped = pushed = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if we are allowed to step up
2012-11-28 15:47:07 +00:00
if ( stepUp )
{
2012-11-26 18:58:24 +00:00
nearGround = groundPlane | ladder ;
2012-11-28 15:47:07 +00:00
if ( ! nearGround )
{
2012-11-26 18:58:24 +00:00
// trace down to see if the player is near the ground
// step checking when near the ground allows the player to move up stairs smoothly while jumping
stepEnd = current . origin + maxStepHeight * gravityNormal ;
gameLocal . clip . Translation ( downTrace , current . origin , stepEnd , clipModel , clipModel - > GetAxis ( ) , clipMask , self ) ;
2012-11-28 15:47:07 +00:00
nearGround = ( downTrace . fraction < 1.0f & & ( downTrace . c . normal * - gravityNormal ) > MIN_WALK_NORMAL ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// may only step up if near the ground or on a ladder
2012-11-28 15:47:07 +00:00
if ( nearGround )
{
2012-11-26 18:58:24 +00:00
// step up
stepEnd = current . origin - maxStepHeight * gravityNormal ;
gameLocal . clip . Translation ( downTrace , current . origin , stepEnd , clipModel , clipModel - > GetAxis ( ) , clipMask , self ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// trace along velocity
stepEnd = downTrace . endpos + time_left * current . velocity ;
gameLocal . clip . Translation ( stepTrace , downTrace . endpos , stepEnd , clipModel , clipModel - > GetAxis ( ) , clipMask , self ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// step down
stepEnd = stepTrace . endpos + maxStepHeight * gravityNormal ;
gameLocal . clip . Translation ( downTrace , stepTrace . endpos , stepEnd , clipModel , clipModel - > GetAxis ( ) , clipMask , self ) ;
2012-11-28 15:47:07 +00:00
if ( downTrace . fraction > = 1.0f | | ( downTrace . c . normal * - gravityNormal ) > MIN_WALK_NORMAL )
{
2012-11-26 18:58:24 +00:00
// if moved the entire distance
2012-11-28 15:47:07 +00:00
if ( stepTrace . fraction > = 1.0f )
{
2012-11-26 18:58:24 +00:00
time_left = 0 ;
current . stepUp - = ( downTrace . endpos - current . origin ) * gravityNormal ;
current . origin = downTrace . endpos ;
current . movementFlags | = PMF_STEPPED_UP ;
current . velocity * = PM_STEPSCALE ;
break ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the move is further when stepping up
2012-11-28 15:47:07 +00:00
if ( stepTrace . fraction > trace . fraction )
{
2012-11-26 18:58:24 +00:00
time_left - = time_left * stepTrace . fraction ;
current . stepUp - = ( downTrace . endpos - current . origin ) * gravityNormal ;
current . origin = downTrace . endpos ;
current . movementFlags | = PMF_STEPPED_UP ;
current . velocity * = PM_STEPSCALE ;
trace = stepTrace ;
stepped = true ;
}
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if we can push other entities and not blocked by the world
2012-11-28 15:47:07 +00:00
if ( push & & trace . c . entityNum ! = ENTITYNUM_WORLD )
{
2012-11-26 18:58:24 +00:00
clipModel - > SetPosition ( current . origin , clipModel - > GetAxis ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clip movement, only push idMoveables, don't push entities the player is standing on
// apply impact to pushed objects
2012-11-28 15:47:07 +00:00
pushFlags = PUSHFL_CLIP | PUSHFL_ONLYMOVEABLE | PUSHFL_NOGROUNDENTITIES | PUSHFL_APPLYIMPULSE ;
2012-11-26 18:58:24 +00:00
// clip & push
totalMass = gameLocal . push . ClipTranslationalPush ( trace , self , pushFlags , end , end - current . origin ) ;
2012-11-28 15:47:07 +00:00
if ( totalMass > 0.0f )
{
2012-11-26 18:58:24 +00:00
// decrease velocity based on the total mass of the objects being pushed ?
current . velocity * = 1.0f - idMath : : ClampFloat ( 0.0f , 1000.0f , totalMass - 20.0f ) * ( 1.0f / 950.0f ) ;
pushed = true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
current . origin = trace . endpos ;
time_left - = time_left * trace . fraction ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if moved the entire distance
2012-11-28 15:47:07 +00:00
if ( trace . fraction > = 1.0f )
{
2012-11-26 18:58:24 +00:00
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( ! stepped )
{
2012-11-26 18:58:24 +00:00
// let the entity know about the collision
self - > Collide ( trace , current . velocity ) ;
}
2012-11-28 15:47:07 +00:00
if ( numplanes > = MAX_CLIP_PLANES )
{
2012-11-26 18:58:24 +00:00
// MrElusive: I think we have some relatively high poly LWO models with a lot of slanted tris
// where it may hit the max clip planes
current . velocity = vec3_origin ;
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//
// if this is the same plane we hit before, nudge velocity
// out along it, which fixes some epsilon issues with
// non-axial planes
//
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < numplanes ; i + + )
{
if ( ( trace . c . normal * planes [ i ] ) > 0.999f )
{
2012-11-26 18:58:24 +00:00
current . velocity + = trace . c . normal ;
break ;
}
}
2012-11-28 15:47:07 +00:00
if ( i < numplanes )
{
2012-11-26 18:58:24 +00:00
continue ;
}
planes [ numplanes ] = trace . c . normal ;
numplanes + + ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//
// modify velocity so it parallels all of the clip planes
//
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// find a plane that it enters
2012-11-28 15:47:07 +00:00
for ( i = 0 ; i < numplanes ; i + + )
{
2012-11-26 18:58:24 +00:00
into = current . velocity * planes [ i ] ;
2012-11-28 15:47:07 +00:00
if ( into > = 0.1f )
{
2012-11-26 18:58:24 +00:00
continue ; // move doesn't interact with the plane
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// slide along the plane
clipVelocity = current . velocity ;
clipVelocity . ProjectOntoPlane ( planes [ i ] , OVERCLIP ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// slide along the plane
endClipVelocity = endVelocity ;
endClipVelocity . ProjectOntoPlane ( planes [ i ] , OVERCLIP ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// see if there is a second plane that the new move enters
2012-11-28 15:47:07 +00:00
for ( j = 0 ; j < numplanes ; j + + )
{
if ( j = = i )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ( clipVelocity * planes [ j ] ) > = 0.1f )
{
2012-11-26 18:58:24 +00:00
continue ; // move doesn't interact with the plane
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// try clipping the move to the plane
clipVelocity . ProjectOntoPlane ( planes [ j ] , OVERCLIP ) ;
endClipVelocity . ProjectOntoPlane ( planes [ j ] , OVERCLIP ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// see if it goes back into the first clip plane
2012-11-28 15:47:07 +00:00
if ( ( clipVelocity * planes [ i ] ) > = 0 )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// slide the original velocity along the crease
dir = planes [ i ] . Cross ( planes [ j ] ) ;
dir . Normalize ( ) ;
d = dir * current . velocity ;
clipVelocity = d * dir ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
dir = planes [ i ] . Cross ( planes [ j ] ) ;
dir . Normalize ( ) ;
d = dir * endVelocity ;
endClipVelocity = d * dir ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// see if there is a third plane the the new move enters
2012-11-28 15:47:07 +00:00
for ( k = 0 ; k < numplanes ; k + + )
{
if ( k = = i | | k = = j )
{
2012-11-26 18:58:24 +00:00
continue ;
}
2012-11-28 15:47:07 +00:00
if ( ( clipVelocity * planes [ k ] ) > = 0.1f )
{
2012-11-26 18:58:24 +00:00
continue ; // move doesn't interact with the plane
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// stop dead at a tripple plane interaction
current . velocity = vec3_origin ;
return true ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if we have fixed all interactions, try another move
current . velocity = clipVelocity ;
endVelocity = endClipVelocity ;
break ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// step down
2012-11-28 15:47:07 +00:00
if ( stepDown & & groundPlane )
{
2012-11-26 18:58:24 +00:00
stepEnd = current . origin + gravityNormal * maxStepHeight ;
gameLocal . clip . Translation ( downTrace , current . origin , stepEnd , clipModel , clipModel - > GetAxis ( ) , clipMask , self ) ;
2012-11-28 15:47:07 +00:00
if ( downTrace . fraction > 1e-4 f & & downTrace . fraction < 1.0f )
{
2012-11-26 18:58:24 +00:00
current . stepUp - = ( downTrace . endpos - current . origin ) * gravityNormal ;
current . origin = downTrace . endpos ;
current . movementFlags | = PMF_STEPPED_DOWN ;
current . velocity * = PM_STEPSCALE ;
}
}
2012-11-28 15:47:07 +00:00
if ( gravity )
{
2012-11-26 18:58:24 +00:00
current . velocity = endVelocity ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// come to a dead stop when the velocity orthogonal to the gravity flipped
clipVelocity = current . velocity - gravityNormal * current . velocity * gravityNormal ;
endClipVelocity = endVelocity - gravityNormal * endVelocity * gravityNormal ;
2012-11-28 15:47:07 +00:00
if ( clipVelocity * endClipVelocity < 0.0f )
{
2012-11-26 18:58:24 +00:00
current . velocity = gravityNormal * current . velocity * gravityNormal ;
}
2012-11-28 15:47:07 +00:00
return ( bool ) ( bumpcount = = 0 ) ;
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = = = =
idPhysics_Player : : Friction
Handles both ground friction and water friction
= = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : Friction ( )
{
2012-11-26 18:58:24 +00:00
idVec3 vel ;
float speed , newspeed , control ;
float drop ;
vel = current . velocity ;
2012-11-28 15:47:07 +00:00
if ( walking )
{
2012-11-26 18:58:24 +00:00
// ignore slope movement, remove all velocity in gravity direction
2012-11-28 15:47:07 +00:00
vel + = ( vel * gravityNormal ) * gravityNormal ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
speed = vel . Length ( ) ;
2012-11-28 15:47:07 +00:00
if ( speed < 1.0f )
{
2012-11-26 18:58:24 +00:00
// remove all movement orthogonal to gravity, allows for sinking underwater
2012-11-28 15:47:07 +00:00
if ( fabs ( current . velocity * gravityNormal ) < 1e-5 f )
{
2012-11-26 18:58:24 +00:00
current . velocity . Zero ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
current . velocity = ( current . velocity * gravityNormal ) * gravityNormal ;
2012-11-26 18:58:24 +00:00
}
// FIXME: still have z friction underwater?
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
drop = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// spectator friction
2012-11-28 15:47:07 +00:00
if ( current . movementType = = PM_SPECTATOR )
{
2012-11-26 18:58:24 +00:00
drop + = speed * PM_FLYFRICTION * frametime ;
}
// apply ground friction
2012-11-28 15:47:07 +00:00
else if ( walking & & waterLevel < = WATERLEVEL_FEET )
{
2012-11-26 18:58:24 +00:00
// no friction on slick surfaces
2012-11-28 15:47:07 +00:00
if ( ! ( groundMaterial & & groundMaterial - > GetSurfaceFlags ( ) & SURF_SLICK ) )
{
2012-11-26 18:58:24 +00:00
// if getting knocked back, no friction
2012-11-28 15:47:07 +00:00
if ( ! ( current . movementFlags & PMF_TIME_KNOCKBACK ) )
{
2012-11-26 18:58:24 +00:00
control = speed < PM_STOPSPEED ? PM_STOPSPEED : speed ;
drop + = control * PM_FRICTION * frametime ;
}
}
}
// apply water friction even if just wading
2012-11-28 15:47:07 +00:00
else if ( waterLevel )
{
2012-11-26 18:58:24 +00:00
drop + = speed * PM_WATERFRICTION * waterLevel * frametime ;
}
// apply air friction
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
drop + = speed * PM_AIRFRICTION * frametime ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// scale the velocity
newspeed = speed - drop ;
2012-11-28 15:47:07 +00:00
if ( newspeed < 0 )
{
2012-11-26 18:58:24 +00:00
newspeed = 0 ;
}
current . velocity * = ( newspeed / speed ) ;
}
/*
= = = = = = = = = = = = = = = = = = =
idPhysics_Player : : WaterJumpMove
Flying out of the water
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : WaterJumpMove ( )
{
2012-11-26 18:58:24 +00:00
// waterjump has no control, but falls
idPhysics_Player : : SlideMove ( true , true , false , false ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// add gravity
current . velocity + = gravityNormal * frametime ;
// if falling down
2012-11-28 15:47:07 +00:00
if ( current . velocity * gravityNormal > 0.0f )
{
2012-11-26 18:58:24 +00:00
// cancel as soon as we are falling down again
current . movementFlags & = ~ PMF_ALL_TIMES ;
current . movementTime = 0 ;
}
}
/*
= = = = = = = = = = = = = = = = = = =
idPhysics_Player : : WaterMove
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : WaterMove ( )
{
2012-11-26 18:58:24 +00:00
idVec3 wishvel ;
float wishspeed ;
idVec3 wishdir ;
float scale ;
float vel ;
2012-11-28 15:47:07 +00:00
if ( idPhysics_Player : : CheckWaterJump ( ) )
{
2012-11-26 18:58:24 +00:00
idPhysics_Player : : WaterJumpMove ( ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idPhysics_Player : : Friction ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
scale = idPhysics_Player : : CmdScale ( command ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// user intentions
2012-11-28 15:47:07 +00:00
if ( ! scale )
{
2012-11-26 18:58:24 +00:00
wishvel = gravityNormal * 60 ; // sink towards bottom
2012-11-28 15:47:07 +00:00
}
else
{
wishvel = scale * ( viewForward * command . forwardmove + viewRight * command . rightmove ) ;
2012-11-26 18:58:24 +00:00
wishvel - = scale * gravityNormal * ( ( ( command . buttons & BUTTON_JUMP ) ? 127 : 0 ) - ( ( command . buttons & BUTTON_CROUCH ) ? 127 : 0 ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
wishdir = wishvel ;
wishspeed = wishdir . Normalize ( ) ;
2012-11-28 15:47:07 +00:00
if ( wishspeed > playerSpeed * PM_SWIMSCALE )
{
2012-11-26 18:58:24 +00:00
wishspeed = playerSpeed * PM_SWIMSCALE ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idPhysics_Player : : Accelerate ( wishdir , wishspeed , PM_WATERACCELERATE ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// make sure we can go up slopes easily under water
2012-11-28 15:47:07 +00:00
if ( groundPlane & & ( current . velocity * groundTrace . c . normal ) < 0.0f )
{
2012-11-26 18:58:24 +00:00
vel = current . velocity . Length ( ) ;
// slide along the ground plane
current . velocity . ProjectOntoPlane ( groundTrace . c . normal , OVERCLIP ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
current . velocity . Normalize ( ) ;
current . velocity * = vel ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idPhysics_Player : : SlideMove ( false , true , false , false ) ;
}
/*
= = = = = = = = = = = = = = = = = = =
idPhysics_Player : : FlyMove
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : FlyMove ( )
{
2012-11-26 18:58:24 +00:00
idVec3 wishvel ;
float wishspeed ;
idVec3 wishdir ;
float scale ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// normal slowdown
idPhysics_Player : : Friction ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
scale = idPhysics_Player : : CmdScale ( command ) ;
2012-11-28 15:47:07 +00:00
if ( ! scale )
{
2012-11-26 18:58:24 +00:00
wishvel = vec3_origin ;
2012-11-28 15:47:07 +00:00
}
else
{
wishvel = scale * ( viewForward * command . forwardmove + viewRight * command . rightmove ) ;
2012-11-26 18:58:24 +00:00
wishvel - = scale * gravityNormal * ( ( ( command . buttons & BUTTON_JUMP ) ? 127 : 0 ) - ( ( command . buttons & BUTTON_CROUCH ) ? 127 : 0 ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
wishdir = wishvel ;
wishspeed = wishdir . Normalize ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idPhysics_Player : : Accelerate ( wishdir , wishspeed , PM_FLYACCELERATE ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idPhysics_Player : : SlideMove ( false , false , false , false ) ;
}
/*
= = = = = = = = = = = = = = = = = = =
idPhysics_Player : : AirMove
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : AirMove ( )
{
2012-11-26 18:58:24 +00:00
idVec3 wishvel ;
idVec3 wishdir ;
float wishspeed ;
float scale ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idPhysics_Player : : Friction ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
scale = idPhysics_Player : : CmdScale ( command ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// project moves down to flat plane
2012-11-28 15:47:07 +00:00
viewForward - = ( viewForward * gravityNormal ) * gravityNormal ;
viewRight - = ( viewRight * gravityNormal ) * gravityNormal ;
2012-11-26 18:58:24 +00:00
viewForward . Normalize ( ) ;
viewRight . Normalize ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
wishvel = viewForward * command . forwardmove + viewRight * command . rightmove ;
2012-11-28 15:47:07 +00:00
wishvel - = ( wishvel * gravityNormal ) * gravityNormal ;
2012-11-26 18:58:24 +00:00
wishdir = wishvel ;
wishspeed = wishdir . Normalize ( ) ;
wishspeed * = scale ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// not on ground, so little effect on velocity
idPhysics_Player : : Accelerate ( wishdir , wishspeed , PM_AIRACCELERATE ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +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
2012-11-28 15:47:07 +00:00
if ( groundPlane )
{
2012-11-26 18:58:24 +00:00
current . velocity . ProjectOntoPlane ( groundTrace . c . normal , OVERCLIP ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idPhysics_Player : : SlideMove ( true , false , false , false ) ;
}
/*
= = = = = = = = = = = = = = = = = = =
idPhysics_Player : : WalkMove
= = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : WalkMove ( )
{
2012-11-26 18:58:24 +00:00
idVec3 wishvel ;
idVec3 wishdir ;
float wishspeed ;
float scale ;
float accelerate ;
idVec3 oldVelocity , vel ;
float oldVel , newVel ;
2012-11-28 15:47:07 +00:00
if ( waterLevel > WATERLEVEL_WAIST & & ( viewForward * groundTrace . c . normal ) > 0.0f )
{
2012-11-26 18:58:24 +00:00
// begin swimming
idPhysics_Player : : WaterMove ( ) ;
return ;
}
2012-11-28 15:47:07 +00:00
if ( idPhysics_Player : : CheckJump ( ) )
{
2012-11-26 18:58:24 +00:00
// jumped away
2012-11-28 15:47:07 +00:00
if ( waterLevel > WATERLEVEL_FEET )
{
2012-11-26 18:58:24 +00:00
idPhysics_Player : : WaterMove ( ) ;
}
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
idPhysics_Player : : AirMove ( ) ;
}
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idPhysics_Player : : Friction ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
scale = idPhysics_Player : : CmdScale ( command ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// project moves down to flat plane
2012-11-28 15:47:07 +00:00
viewForward - = ( viewForward * gravityNormal ) * gravityNormal ;
viewRight - = ( viewRight * gravityNormal ) * gravityNormal ;
2012-11-26 18:58:24 +00:00
// project the forward and right directions onto the ground plane
viewForward . ProjectOntoPlane ( groundTrace . c . normal , OVERCLIP ) ;
viewRight . ProjectOntoPlane ( groundTrace . c . normal , OVERCLIP ) ;
//
viewForward . Normalize ( ) ;
viewRight . Normalize ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
wishvel = viewForward * command . forwardmove + viewRight * command . rightmove ;
wishdir = wishvel ;
wishspeed = wishdir . Normalize ( ) ;
wishspeed * = scale ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// clamp the speed lower if wading or walking on the bottom
2012-11-28 15:47:07 +00:00
if ( waterLevel )
{
2012-11-26 18:58:24 +00:00
float waterScale ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
waterScale = waterLevel / 3.0f ;
waterScale = 1.0f - ( 1.0f - PM_SWIMSCALE ) * waterScale ;
2012-11-28 15:47:07 +00:00
if ( wishspeed > playerSpeed * waterScale )
{
2012-11-26 18:58:24 +00:00
wishspeed = playerSpeed * waterScale ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// when a player gets hit, they temporarily lose full control, which allows them to be moved a bit
2012-11-28 15:47:07 +00:00
if ( ( groundMaterial & & groundMaterial - > GetSurfaceFlags ( ) & SURF_SLICK ) | | current . movementFlags & PMF_TIME_KNOCKBACK )
{
2012-11-26 18:58:24 +00:00
accelerate = PM_AIRACCELERATE ;
}
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
accelerate = PM_ACCELERATE ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idPhysics_Player : : Accelerate ( wishdir , wishspeed , accelerate ) ;
2012-11-28 15:47:07 +00:00
if ( ( groundMaterial & & groundMaterial - > GetSurfaceFlags ( ) & SURF_SLICK ) | | current . movementFlags & PMF_TIME_KNOCKBACK )
{
2012-11-26 18:58:24 +00:00
current . velocity + = gravityVector * frametime ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
oldVelocity = current . velocity ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// slide along the ground plane
current . velocity . ProjectOntoPlane ( groundTrace . c . normal , OVERCLIP ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if not clipped into the opposite direction
2012-11-28 15:47:07 +00:00
if ( oldVelocity * current . velocity > 0.0f )
{
2012-11-26 18:58:24 +00:00
newVel = current . velocity . LengthSqr ( ) ;
2012-11-28 15:47:07 +00:00
if ( newVel > 1.0f )
{
2012-11-26 18:58:24 +00:00
oldVel = oldVelocity . LengthSqr ( ) ;
2012-11-28 15:47:07 +00:00
if ( oldVel > 1.0f )
{
2012-11-26 18:58:24 +00:00
// don't decrease velocity when going up or down a slope
current . velocity * = idMath : : Sqrt ( oldVel / newVel ) ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// don't do anything if standing still
2012-11-28 15:47:07 +00:00
vel = current . velocity - ( current . velocity * gravityNormal ) * gravityNormal ;
if ( ! vel . LengthSqr ( ) )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
gameLocal . push . InitSavingPushedEntityPositions ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idPhysics_Player : : SlideMove ( false , true , true , true ) ;
}
/*
= = = = = = = = = = = = = =
idPhysics_Player : : DeadMove
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : DeadMove ( )
{
2012-11-26 18:58:24 +00:00
float forward ;
2012-11-28 15:47:07 +00:00
if ( ! walking )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// extra friction
forward = current . velocity . Length ( ) ;
forward - = 20 ;
2012-11-28 15:47:07 +00:00
if ( forward < = 0 )
{
2012-11-26 18:58:24 +00:00
current . velocity = vec3_origin ;
}
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
current . velocity . Normalize ( ) ;
current . velocity * = forward ;
}
}
/*
= = = = = = = = = = = = = = =
idPhysics_Player : : NoclipMove
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : NoclipMove ( )
{
2012-11-26 18:58:24 +00:00
float speed , drop , friction , newspeed , stopspeed ;
float scale , wishspeed ;
idVec3 wishdir ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// friction
speed = current . velocity . Length ( ) ;
2012-11-28 15:47:07 +00:00
if ( speed < 20.0f )
{
2012-11-26 18:58:24 +00:00
current . velocity = vec3_origin ;
}
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
stopspeed = playerSpeed * 0.3f ;
2012-11-28 15:47:07 +00:00
if ( speed < stopspeed )
{
2012-11-26 18:58:24 +00:00
speed = stopspeed ;
}
friction = PM_NOCLIPFRICTION ;
drop = speed * friction * frametime ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// scale the velocity
newspeed = speed - drop ;
2012-11-28 15:47:07 +00:00
if ( newspeed < 0 )
{
2012-11-26 18:58:24 +00:00
newspeed = 0 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
current . velocity * = newspeed / speed ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// accelerate
scale = idPhysics_Player : : CmdScale ( command ) ;
2012-11-28 15:47:07 +00:00
wishdir = scale * ( viewForward * command . forwardmove + viewRight * command . rightmove ) ;
2012-11-26 18:58:24 +00:00
wishdir - = scale * gravityNormal * ( ( ( command . buttons & BUTTON_JUMP ) ? 127 : 0 ) - ( ( command . buttons & BUTTON_CROUCH ) ? 127 : 0 ) ) ;
wishspeed = wishdir . Normalize ( ) ;
wishspeed * = scale ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idPhysics_Player : : Accelerate ( wishdir , wishspeed , PM_ACCELERATE ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// move
current . origin + = frametime * current . velocity ;
}
/*
= = = = = = = = = = = = = = =
idPhysics_Player : : SpectatorMove
= = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : SpectatorMove ( )
{
2012-11-26 18:58:24 +00:00
idVec3 wishvel ;
float wishspeed ;
idVec3 wishdir ;
float scale ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
trace_t trace ;
idVec3 end ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// fly movement
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idPhysics_Player : : Friction ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
scale = idPhysics_Player : : CmdScale ( command ) ;
2012-11-28 15:47:07 +00:00
if ( ! scale )
{
2012-11-26 18:58:24 +00:00
wishvel = vec3_origin ;
}
2012-11-28 15:47:07 +00:00
else
{
wishvel = scale * ( viewForward * command . forwardmove + viewRight * command . rightmove ) ;
}
2012-11-26 18:58:24 +00:00
wishdir = wishvel ;
wishspeed = wishdir . Normalize ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idPhysics_Player : : Accelerate ( wishdir , wishspeed , PM_FLYACCELERATE ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idPhysics_Player : : SlideMove ( false , false , false , false ) ;
}
/*
= = = = = = = = = = = =
idPhysics_Player : : LadderMove
= = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : LadderMove ( )
{
2012-11-26 18:58:24 +00:00
idVec3 wishdir , wishvel , right ;
float wishspeed , scale ;
float upscale ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// stick to the ladder
wishvel = - 100.0f * ladderNormal ;
2012-11-28 15:47:07 +00:00
current . velocity = ( gravityNormal * current . velocity ) * gravityNormal + wishvel ;
upscale = ( - gravityNormal * viewForward + 0.5f ) * 2.5f ;
if ( upscale > 1.0f )
{
2012-11-26 18:58:24 +00:00
upscale = 1.0f ;
}
2012-11-28 15:47:07 +00:00
else if ( upscale < - 1.0f )
{
2012-11-26 18:58:24 +00:00
upscale = - 1.0f ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
scale = idPhysics_Player : : CmdScale ( command ) ;
2012-11-28 15:47:07 +00:00
wishvel = - 0.9f * gravityNormal * upscale * scale * ( float ) command . forwardmove ;
2012-11-26 18:58:24 +00:00
// strafe
2012-11-28 15:47:07 +00:00
if ( command . rightmove )
{
2012-11-26 18:58:24 +00:00
// right vector orthogonal to gravity
2012-11-28 15:47:07 +00:00
right = viewRight - ( gravityNormal * viewRight ) * gravityNormal ;
2012-11-26 18:58:24 +00:00
// project right vector into ladder plane
2012-11-28 15:47:07 +00:00
right = right - ( ladderNormal * right ) * ladderNormal ;
2012-11-26 18:58:24 +00:00
right . Normalize ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if we are looking away from the ladder, reverse the right vector
2012-11-28 15:47:07 +00:00
if ( ladderNormal * viewForward > 0.0f )
{
2012-11-26 18:58:24 +00:00
right = - right ;
}
2012-11-28 15:47:07 +00:00
wishvel + = 2.0f * right * scale * ( float ) command . rightmove ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// up down movement
2012-11-28 15:47:07 +00:00
if ( command . buttons & ( BUTTON_JUMP | BUTTON_CROUCH ) )
{
wishvel + = - 0.5f * gravityNormal * scale * ( float ) ( ( ( command . buttons & BUTTON_JUMP ) ? 127 : 0 ) - ( ( command . buttons & BUTTON_CROUCH ) ? 127 : 0 ) ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// do strafe friction
idPhysics_Player : : Friction ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// accelerate
wishspeed = wishvel . Normalize ( ) ;
idPhysics_Player : : Accelerate ( wishvel , wishspeed , PM_ACCELERATE ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// cap the vertical velocity
upscale = current . velocity * - gravityNormal ;
2012-11-28 15:47:07 +00:00
if ( upscale < - PM_LADDERSPEED )
{
current . velocity + = gravityNormal * ( upscale + PM_LADDERSPEED ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
else if ( upscale > PM_LADDERSPEED )
{
current . velocity + = gravityNormal * ( upscale - PM_LADDERSPEED ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
if ( ( wishvel * gravityNormal ) = = 0.0f )
{
if ( current . velocity * gravityNormal < 0.0f )
{
2012-11-26 18:58:24 +00:00
current . velocity + = gravityVector * frametime ;
2012-11-28 15:47:07 +00:00
if ( current . velocity * gravityNormal > 0.0f )
{
current . velocity - = ( gravityNormal * current . velocity ) * gravityNormal ;
2012-11-26 18:58:24 +00:00
}
}
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
current . velocity - = gravityVector * frametime ;
2012-11-28 15:47:07 +00:00
if ( current . velocity * gravityNormal < 0.0f )
{
current . velocity - = ( gravityNormal * current . velocity ) * gravityNormal ;
2012-11-26 18:58:24 +00:00
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idPhysics_Player : : SlideMove ( false , ( command . forwardmove > 0 ) , false , false ) ;
}
/*
= = = = = = = = = = = = =
idPhysics_Player : : CorrectAllSolid
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : CorrectAllSolid ( trace_t & trace , int contents )
{
if ( debugLevel )
{
2012-11-26 18:58:24 +00:00
gameLocal . Printf ( " %i:allsolid \n " , c_pmove ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// FIXME: jitter around to find a free spot ?
2012-11-28 15:47:07 +00:00
if ( trace . fraction > = 1.0f )
{
2012-11-26 18:58:24 +00:00
memset ( & trace , 0 , sizeof ( trace ) ) ;
trace . endpos = current . origin ;
trace . endAxis = clipModelAxis ;
trace . fraction = 0.0f ;
trace . c . dist = current . origin . z ;
trace . c . normal . Set ( 0 , 0 , 1 ) ;
trace . c . point = current . origin ;
trace . c . entityNum = ENTITYNUM_WORLD ;
trace . c . id = 0 ;
trace . c . type = CONTACT_TRMVERTEX ;
trace . c . material = NULL ;
trace . c . contents = contents ;
}
}
/*
= = = = = = = = = = = = =
idPhysics_Player : : CheckGround
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : CheckGround ( )
{
2012-11-26 18:58:24 +00:00
int i , contents ;
idVec3 point ;
bool hadGroundContacts ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
hadGroundContacts = HasGroundContacts ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set the clip model origin before getting the contacts
clipModel - > SetPosition ( current . origin , clipModel - > GetAxis ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
EvaluateContacts ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// setup a ground trace from the contacts
groundTrace . endpos = current . origin ;
groundTrace . endAxis = clipModel - > GetAxis ( ) ;
2012-11-28 15:47:07 +00:00
if ( contacts . Num ( ) )
{
2012-11-26 18:58:24 +00:00
groundTrace . fraction = 0.0f ;
groundTrace . c = contacts [ 0 ] ;
2012-11-28 15:47:07 +00:00
for ( i = 1 ; i < contacts . Num ( ) ; i + + )
{
2012-11-26 18:58:24 +00:00
groundTrace . c . normal + = contacts [ i ] . normal ;
}
groundTrace . c . normal . Normalize ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
groundTrace . fraction = 1.0f ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
contents = gameLocal . clip . Contents ( current . origin , clipModel , clipModel - > GetAxis ( ) , - 1 , self ) ;
2012-11-28 15:47:07 +00:00
if ( contents & MASK_SOLID )
{
2012-11-26 18:58:24 +00:00
// do something corrective if stuck in solid
idPhysics_Player : : CorrectAllSolid ( groundTrace , contents ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the trace didn't hit anything, we are in free fall
2012-11-28 15:47:07 +00:00
if ( groundTrace . fraction = = 1.0f )
{
2012-11-26 18:58:24 +00:00
groundPlane = false ;
walking = false ;
groundEntityPtr = NULL ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
groundMaterial = groundTrace . c . material ;
groundEntityPtr = gameLocal . entities [ groundTrace . c . entityNum ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check if getting thrown off the ground
2012-11-28 15:47:07 +00:00
if ( ( current . velocity * - gravityNormal ) > 0.0f & & ( current . velocity * groundTrace . c . normal ) > 10.0f )
{
if ( debugLevel )
{
2012-11-26 18:58:24 +00:00
gameLocal . Printf ( " %i:kickoff \n " , c_pmove ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
groundPlane = false ;
walking = false ;
return ;
}
// slopes that are too steep will not be considered onground
2012-11-28 15:47:07 +00:00
if ( ( groundTrace . c . normal * - gravityNormal ) < MIN_WALK_NORMAL )
{
if ( debugLevel )
{
2012-11-26 18:58:24 +00:00
gameLocal . Printf ( " %i:steep \n " , c_pmove ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// FIXME: if they can't slide down the slope, let them walk (sharp crevices)
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// make sure we don't die from sliding down a steep slope
2012-11-28 15:47:07 +00:00
if ( current . velocity * gravityNormal > 150.0f )
{
2012-11-26 18:58:24 +00:00
current . velocity - = ( current . velocity * gravityNormal - 150.0f ) * gravityNormal ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
groundPlane = true ;
walking = false ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
groundPlane = true ;
walking = true ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// hitting solid ground will end a waterjump
2012-11-28 15:47:07 +00:00
if ( current . movementFlags & PMF_TIME_WATERJUMP )
{
2012-11-26 18:58:24 +00:00
current . movementFlags & = ~ ( PMF_TIME_WATERJUMP | PMF_TIME_LAND ) ;
current . movementTime = 0 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if the player didn't have ground contacts the previous frame
2012-11-28 15:47:07 +00:00
if ( ! hadGroundContacts )
{
2012-11-26 18:58:24 +00:00
// don't do landing time if we were just going down a slope
2012-11-28 15:47:07 +00:00
if ( ( current . velocity * - gravityNormal ) < - 200.0f )
{
2012-11-26 18:58:24 +00:00
// don't allow another jump for a little while
current . movementFlags | = PMF_TIME_LAND ;
current . movementTime = 250 ;
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// let the entity know about the collision
self - > Collide ( groundTrace , current . velocity ) ;
2012-11-28 15:47:07 +00:00
if ( groundEntityPtr . GetEntity ( ) )
{
2012-11-26 18:58:24 +00:00
impactInfo_t info ;
groundEntityPtr . GetEntity ( ) - > GetImpactInfo ( self , groundTrace . c . id , groundTrace . c . point , & info ) ;
2012-11-28 15:47:07 +00:00
if ( info . invMass ! = 0.0f )
{
2012-11-26 18:58:24 +00:00
groundEntityPtr . GetEntity ( ) - > ApplyImpulse ( self , groundTrace . c . id , groundTrace . c . point , current . velocity / ( info . invMass * 10.0f ) ) ;
}
}
}
/*
= = = = = = = = = = = = = =
idPhysics_Player : : CheckDuck
Sets clip model size
= = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : CheckDuck ( )
{
2012-11-26 18:58:24 +00:00
trace_t trace ;
idVec3 end ;
idBounds bounds ;
float maxZ ;
2012-11-28 15:47:07 +00:00
if ( current . movementType = = PM_DEAD )
{
2012-11-26 18:58:24 +00:00
maxZ = pm_deadheight . GetFloat ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// stand up when up against a ladder
2012-11-28 15:47:07 +00:00
if ( ( command . buttons & BUTTON_CROUCH ) & & ! ladder )
{
2012-11-26 18:58:24 +00:00
// duck
current . movementFlags | = PMF_DUCKED ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
// stand up if possible
2012-11-28 15:47:07 +00:00
if ( current . movementFlags & PMF_DUCKED )
{
2012-11-26 18:58:24 +00:00
// try to stand up
end = current . origin - ( pm_normalheight . GetFloat ( ) - pm_crouchheight . GetFloat ( ) ) * gravityNormal ;
gameLocal . clip . Translation ( trace , current . origin , end , clipModel , clipModel - > GetAxis ( ) , clipMask , self ) ;
2012-11-28 15:47:07 +00:00
if ( trace . fraction > = 1.0f )
{
2012-11-26 18:58:24 +00:00
current . movementFlags & = ~ PMF_DUCKED ;
}
}
}
2012-11-28 15:47:07 +00:00
if ( current . movementFlags & PMF_DUCKED )
{
2012-11-26 18:58:24 +00:00
playerSpeed = crouchSpeed ;
maxZ = pm_crouchheight . GetFloat ( ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
maxZ = pm_normalheight . GetFloat ( ) ;
}
}
// if the clipModel height should change
2012-11-28 15:47:07 +00:00
if ( clipModel - > GetBounds ( ) [ 1 ] [ 2 ] ! = maxZ )
{
2012-11-26 18:58:24 +00:00
bounds = clipModel - > GetBounds ( ) ;
bounds [ 1 ] [ 2 ] = maxZ ;
2012-11-28 15:47:07 +00:00
if ( pm_usecylinder . GetBool ( ) )
{
2012-11-26 18:58:24 +00:00
clipModel - > LoadModel ( idTraceModel ( bounds , 8 ) ) ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
clipModel - > LoadModel ( idTraceModel ( bounds ) ) ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : CheckLadder
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : CheckLadder ( )
{
2012-11-26 18:58:24 +00:00
idVec3 forward , start , end ;
trace_t trace ;
float tracedist ;
2012-11-28 15:47:07 +00:00
if ( current . movementTime )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if on the ground moving backwards
2012-11-28 15:47:07 +00:00
if ( walking & & command . forwardmove < = 0 )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// forward vector orthogonal to gravity
2012-11-28 15:47:07 +00:00
forward = viewForward - ( gravityNormal * viewForward ) * gravityNormal ;
2012-11-26 18:58:24 +00:00
forward . Normalize ( ) ;
2012-11-28 15:47:07 +00:00
if ( walking )
{
2012-11-26 18:58:24 +00:00
// don't want to get sucked towards the ladder when still walking
tracedist = 1.0f ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
tracedist = 48.0f ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
end = current . origin + tracedist * forward ;
gameLocal . clip . Translation ( trace , current . origin , end , clipModel , clipModel - > GetAxis ( ) , clipMask , self ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if near a surface
2012-11-28 15:47:07 +00:00
if ( trace . fraction < 1.0f )
{
2012-11-26 18:58:24 +00:00
// if a ladder surface
2012-11-28 15:47:07 +00:00
if ( trace . c . material & & ( trace . c . material - > GetSurfaceFlags ( ) & SURF_LADDER ) )
{
2012-11-26 18:58:24 +00:00
// check a step height higher
end = current . origin - gravityNormal * ( maxStepHeight * 0.75f ) ;
gameLocal . clip . Translation ( trace , current . origin , end , clipModel , clipModel - > GetAxis ( ) , clipMask , self ) ;
start = trace . endpos ;
end = start + tracedist * forward ;
gameLocal . clip . Translation ( trace , start , end , clipModel , clipModel - > GetAxis ( ) , clipMask , self ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if also near a surface a step height higher
2012-11-28 15:47:07 +00:00
if ( trace . fraction < 1.0f )
{
2012-11-26 18:58:24 +00:00
// if it also is a ladder surface
2012-11-28 15:47:07 +00:00
if ( trace . c . material & & trace . c . material - > GetSurfaceFlags ( ) & SURF_LADDER )
{
2012-11-26 18:58:24 +00:00
ladder = true ;
ladderNormal = trace . c . normal ;
}
}
}
}
}
/*
= = = = = = = = = = = = =
idPhysics_Player : : CheckJump
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPhysics_Player : : CheckJump ( )
{
2012-11-26 18:58:24 +00:00
idVec3 addVelocity ;
2012-11-28 15:47:07 +00:00
if ( ( command . buttons & BUTTON_JUMP ) = = 0 )
{
2012-11-26 18:58:24 +00:00
// not holding jump
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// must wait for jump to be released
2012-11-28 15:47:07 +00:00
if ( current . movementFlags & PMF_JUMP_HELD )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// don't jump if we can't stand up
2012-11-28 15:47:07 +00:00
if ( current . movementFlags & PMF_DUCKED )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
groundPlane = false ; // jumping away
walking = false ;
current . movementFlags | = PMF_JUMP_HELD | PMF_JUMPED ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
addVelocity = 2.0f * maxJumpHeight * - gravityVector ;
addVelocity * = idMath : : Sqrt ( addVelocity . Normalize ( ) ) ;
current . velocity + = addVelocity ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = =
idPhysics_Player : : CheckWaterJump
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPhysics_Player : : CheckWaterJump ( )
{
2012-11-26 18:58:24 +00:00
idVec3 spot ;
int cont ;
idVec3 flatforward ;
2012-11-28 15:47:07 +00:00
if ( current . movementTime )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check for water jump
2012-11-28 15:47:07 +00:00
if ( waterLevel ! = WATERLEVEL_WAIST )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
flatforward = viewForward - ( viewForward * gravityNormal ) * gravityNormal ;
2012-11-26 18:58:24 +00:00
flatforward . Normalize ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
spot = current . origin + 30.0f * flatforward ;
spot - = 4.0f * gravityNormal ;
cont = gameLocal . clip . Contents ( spot , NULL , mat3_identity , - 1 , self ) ;
2012-11-28 15:47:07 +00:00
if ( ! ( cont & CONTENTS_SOLID ) )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
spot - = 16.0f * gravityNormal ;
cont = gameLocal . clip . Contents ( spot , NULL , mat3_identity , - 1 , self ) ;
2012-11-28 15:47:07 +00:00
if ( cont )
{
2012-11-26 18:58:24 +00:00
return false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// jump out of water
current . velocity = 200.0f * viewForward - 350.0f * gravityNormal ;
current . movementFlags | = PMF_TIME_WATERJUMP ;
current . movementTime = 2000 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ;
}
/*
= = = = = = = = = = = = =
idPhysics_Player : : SetWaterLevel
= = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : SetWaterLevel ( )
{
2012-11-26 18:58:24 +00:00
idVec3 point ;
idBounds bounds ;
int contents ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//
// get waterlevel, accounting for ducking
//
waterLevel = WATERLEVEL_NONE ;
waterType = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bounds = clipModel - > GetBounds ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check at feet level
point = current . origin - ( bounds [ 0 ] [ 2 ] + 1.0f ) * gravityNormal ;
contents = gameLocal . clip . Contents ( point , NULL , mat3_identity , - 1 , self ) ;
2012-11-28 15:47:07 +00:00
if ( contents & MASK_WATER )
{
2012-11-26 18:58:24 +00:00
waterType = contents ;
waterLevel = WATERLEVEL_FEET ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check at waist level
point = current . origin - ( bounds [ 1 ] [ 2 ] - bounds [ 0 ] [ 2 ] ) * 0.5f * gravityNormal ;
contents = gameLocal . clip . Contents ( point , NULL , mat3_identity , - 1 , self ) ;
2012-11-28 15:47:07 +00:00
if ( contents & MASK_WATER )
{
2012-11-26 18:58:24 +00:00
waterLevel = WATERLEVEL_WAIST ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check at head level
point = current . origin - ( bounds [ 1 ] [ 2 ] - 1.0f ) * gravityNormal ;
contents = gameLocal . clip . Contents ( point , NULL , mat3_identity , - 1 , self ) ;
2012-11-28 15:47:07 +00:00
if ( contents & MASK_WATER )
{
2012-11-26 18:58:24 +00:00
waterLevel = WATERLEVEL_HEAD ;
}
}
}
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : DropTimers
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : DropTimers ( )
{
2012-11-26 18:58:24 +00:00
// drop misc timing counter
2012-11-28 15:47:07 +00:00
if ( current . movementTime )
{
if ( framemsec > = current . movementTime )
{
2012-11-26 18:58:24 +00:00
current . movementFlags & = ~ PMF_ALL_TIMES ;
current . movementTime = 0 ;
}
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
current . movementTime - = framemsec ;
}
}
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : MovePlayer
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : MovePlayer ( int msec )
{
2012-11-26 18:58:24 +00:00
// this counter lets us debug movement problems with a journal
// by setting a conditional breakpoint for the previous frame
c_pmove + + ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
walking = false ;
groundPlane = false ;
ladder = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// determine the time
framemsec = msec ;
frametime = framemsec * 0.001f ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// default speed
playerSpeed = walkSpeed ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// remove jumped and stepped up flag
2012-11-28 15:47:07 +00:00
current . movementFlags & = ~ ( PMF_JUMPED | PMF_STEPPED_UP | PMF_STEPPED_DOWN ) ;
2012-11-26 18:58:24 +00:00
current . stepUp = 0.0f ;
2012-11-28 15:47:07 +00:00
if ( ( command . buttons & BUTTON_JUMP ) = = 0 )
{
2012-11-26 18:58:24 +00:00
// not holding jump
current . movementFlags & = ~ PMF_JUMP_HELD ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if no movement at all
2012-11-28 15:47:07 +00:00
if ( current . movementType = = PM_FREEZE )
{
2012-11-26 18:58:24 +00:00
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// move the player velocity into the frame of a pusher
current . velocity - = current . pushVelocity ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// view vectors
viewForward = commandForward * clipModelAxis ;
viewRight = gravityNormal . Cross ( viewForward ) ;
viewRight . Normalize ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// fly in spectator mode
2012-11-28 15:47:07 +00:00
if ( current . movementType = = PM_SPECTATOR )
{
2012-11-26 18:58:24 +00:00
SpectatorMove ( ) ;
idPhysics_Player : : DropTimers ( ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// special no clip mode
2012-11-28 15:47:07 +00:00
if ( current . movementType = = PM_NOCLIP )
{
2012-11-26 18:58:24 +00:00
idPhysics_Player : : NoclipMove ( ) ;
idPhysics_Player : : DropTimers ( ) ;
return ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// no control when dead
2012-11-28 15:47:07 +00:00
if ( current . movementType = = PM_DEAD )
{
2012-11-26 18:58:24 +00:00
command . forwardmove = 0 ;
command . rightmove = 0 ;
2012-11-28 15:47:07 +00:00
command . buttons & = ~ ( BUTTON_JUMP | BUTTON_CROUCH ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set watertype and waterlevel
idPhysics_Player : : SetWaterLevel ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check for ground
idPhysics_Player : : CheckGround ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// check if up against a ladder
idPhysics_Player : : CheckLadder ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set clip model size
idPhysics_Player : : CheckDuck ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// handle timers
idPhysics_Player : : DropTimers ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// move
2012-11-28 15:47:07 +00:00
if ( current . movementType = = PM_DEAD )
{
2012-11-26 18:58:24 +00:00
// dead
idPhysics_Player : : DeadMove ( ) ;
}
2012-11-28 15:47:07 +00:00
else if ( ladder )
{
2012-11-26 18:58:24 +00:00
// going up or down a ladder
idPhysics_Player : : LadderMove ( ) ;
}
2012-11-28 15:47:07 +00:00
else if ( current . movementFlags & PMF_TIME_WATERJUMP )
{
2012-11-26 18:58:24 +00:00
// jumping out of water
idPhysics_Player : : WaterJumpMove ( ) ;
}
2012-11-28 15:47:07 +00:00
else if ( waterLevel > 1 )
{
2012-11-26 18:58:24 +00:00
// swimming
idPhysics_Player : : WaterMove ( ) ;
}
2012-11-28 15:47:07 +00:00
else if ( walking )
{
2012-11-26 18:58:24 +00:00
// walking on ground
idPhysics_Player : : WalkMove ( ) ;
}
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
// airborne
idPhysics_Player : : AirMove ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// set watertype, waterlevel and groundentity
idPhysics_Player : : SetWaterLevel ( ) ;
idPhysics_Player : : CheckGround ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// move the player velocity back into the world frame
current . velocity + = current . pushVelocity ;
current . pushVelocity . Zero ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : GetWaterLevel
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
waterLevel_t idPhysics_Player : : GetWaterLevel ( ) const
{
2012-11-26 18:58:24 +00:00
return waterLevel ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : GetWaterType
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idPhysics_Player : : GetWaterType ( ) const
{
2012-11-26 18:58:24 +00:00
return waterType ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : HasJumped
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPhysics_Player : : HasJumped ( ) const
{
2012-11-26 18:58:24 +00:00
return ( ( current . movementFlags & PMF_JUMPED ) ! = 0 ) ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : HasSteppedUp
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPhysics_Player : : HasSteppedUp ( ) const
{
2012-11-26 18:58:24 +00:00
return ( ( current . movementFlags & ( PMF_STEPPED_UP | PMF_STEPPED_DOWN ) ) ! = 0 ) ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : GetStepUp
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
float idPhysics_Player : : GetStepUp ( ) const
{
2012-11-26 18:58:24 +00:00
return current . stepUp ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : IsCrouching
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPhysics_Player : : IsCrouching ( ) const
{
2012-11-26 18:58:24 +00:00
return ( ( current . movementFlags & PMF_DUCKED ) ! = 0 ) ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : OnLadder
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPhysics_Player : : OnLadder ( ) const
{
2012-11-26 18:58:24 +00:00
return ladder ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : idPhysics_Player
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
idPhysics_Player : : idPhysics_Player ( )
{
2012-11-26 18:58:24 +00:00
debugLevel = false ;
clipModel = NULL ;
clipMask = 0 ;
memset ( & current , 0 , sizeof ( current ) ) ;
saved = current ;
walkSpeed = 0 ;
crouchSpeed = 0 ;
maxStepHeight = 0 ;
maxJumpHeight = 0 ;
memset ( & command , 0 , sizeof ( command ) ) ;
commandForward = idVec3 ( 1 , 0 , 0 ) ;
framemsec = 0 ;
frametime = 0 ;
playerSpeed = 0 ;
viewForward . Zero ( ) ;
viewRight . Zero ( ) ;
walking = false ;
groundPlane = false ;
memset ( & groundTrace , 0 , sizeof ( groundTrace ) ) ;
groundMaterial = NULL ;
ladder = false ;
ladderNormal . Zero ( ) ;
waterLevel = WATERLEVEL_NONE ;
waterType = 0 ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player_SavePState
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player_SavePState ( idSaveGame * savefile , const playerPState_t & state )
{
2012-11-26 18:58:24 +00:00
savefile - > WriteVec3 ( state . origin ) ;
savefile - > WriteVec3 ( state . velocity ) ;
savefile - > WriteVec3 ( state . localOrigin ) ;
savefile - > WriteVec3 ( state . pushVelocity ) ;
savefile - > WriteFloat ( state . stepUp ) ;
savefile - > WriteInt ( state . movementType ) ;
savefile - > WriteInt ( state . movementFlags ) ;
savefile - > WriteInt ( state . movementTime ) ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player_RestorePState
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player_RestorePState ( idRestoreGame * savefile , playerPState_t & state )
{
2012-11-26 18:58:24 +00:00
savefile - > ReadVec3 ( state . origin ) ;
savefile - > ReadVec3 ( state . velocity ) ;
savefile - > ReadVec3 ( state . localOrigin ) ;
savefile - > ReadVec3 ( state . pushVelocity ) ;
savefile - > ReadFloat ( state . stepUp ) ;
savefile - > ReadInt ( state . movementType ) ;
savefile - > ReadInt ( state . movementFlags ) ;
savefile - > ReadInt ( state . movementTime ) ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : Save
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : Save ( idSaveGame * savefile ) const
{
2012-11-26 18:58:24 +00:00
idPhysics_Player_SavePState ( savefile , current ) ;
idPhysics_Player_SavePState ( savefile , saved ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteFloat ( walkSpeed ) ;
savefile - > WriteFloat ( crouchSpeed ) ;
savefile - > WriteFloat ( maxStepHeight ) ;
savefile - > WriteFloat ( maxJumpHeight ) ;
savefile - > WriteInt ( debugLevel ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteUsercmd ( command ) ;
savefile - > WriteVec3 ( commandForward ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( framemsec ) ;
savefile - > WriteFloat ( frametime ) ;
savefile - > WriteFloat ( playerSpeed ) ;
savefile - > WriteVec3 ( viewForward ) ;
savefile - > WriteVec3 ( viewRight ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteBool ( walking ) ;
savefile - > WriteBool ( groundPlane ) ;
savefile - > WriteTrace ( groundTrace ) ;
savefile - > WriteMaterial ( groundMaterial ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > WriteBool ( ladder ) ;
savefile - > WriteVec3 ( ladderNormal ) ;
2012-11-28 15:47:07 +00:00
savefile - > WriteInt ( ( int ) waterLevel ) ;
2012-11-26 18:58:24 +00:00
savefile - > WriteInt ( waterType ) ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : Restore
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : Restore ( idRestoreGame * savefile )
{
2012-11-26 18:58:24 +00:00
idPhysics_Player_RestorePState ( savefile , current ) ;
idPhysics_Player_RestorePState ( savefile , saved ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadFloat ( walkSpeed ) ;
savefile - > ReadFloat ( crouchSpeed ) ;
savefile - > ReadFloat ( maxStepHeight ) ;
savefile - > ReadFloat ( maxJumpHeight ) ;
savefile - > ReadInt ( debugLevel ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadUsercmd ( command ) ;
savefile - > ReadVec3 ( commandForward ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( framemsec ) ;
savefile - > ReadFloat ( frametime ) ;
savefile - > ReadFloat ( playerSpeed ) ;
savefile - > ReadVec3 ( viewForward ) ;
savefile - > ReadVec3 ( viewRight ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadBool ( walking ) ;
savefile - > ReadBool ( groundPlane ) ;
savefile - > ReadTrace ( groundTrace ) ;
savefile - > ReadMaterial ( groundMaterial ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
savefile - > ReadBool ( ladder ) ;
savefile - > ReadVec3 ( ladderNormal ) ;
2012-11-28 15:47:07 +00:00
savefile - > ReadInt ( ( int & ) waterLevel ) ;
2012-11-26 18:58:24 +00:00
savefile - > ReadInt ( waterType ) ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : SetPlayerInput
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : SetPlayerInput ( const usercmd_t & cmd , const idVec3 & forwardVector )
{
2012-11-26 18:58:24 +00:00
command = cmd ;
commandForward = forwardVector ; // can't use cmd.angles cause of the delta_angles
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : SetSpeed
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : SetSpeed ( const float newWalkSpeed , const float newCrouchSpeed )
{
2012-11-26 18:58:24 +00:00
walkSpeed = newWalkSpeed ;
crouchSpeed = newCrouchSpeed ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : SetMaxStepHeight
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : SetMaxStepHeight ( const float newMaxStepHeight )
{
2012-11-26 18:58:24 +00:00
maxStepHeight = newMaxStepHeight ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : GetMaxStepHeight
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
float idPhysics_Player : : GetMaxStepHeight ( ) const
{
2012-11-26 18:58:24 +00:00
return maxStepHeight ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : SetMaxJumpHeight
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : SetMaxJumpHeight ( const float newMaxJumpHeight )
{
2012-11-26 18:58:24 +00:00
maxJumpHeight = newMaxJumpHeight ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : SetMovementType
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : SetMovementType ( const pmtype_t type )
{
2012-11-26 18:58:24 +00:00
current . movementType = type ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : SetKnockBack
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : SetKnockBack ( const int knockBackTime )
{
if ( current . movementTime )
{
2012-11-26 18:58:24 +00:00
return ;
}
current . movementFlags | = PMF_TIME_KNOCKBACK ;
current . movementTime = knockBackTime ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : SetDebugLevel
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : SetDebugLevel ( bool set )
{
2012-11-26 18:58:24 +00:00
debugLevel = set ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : Evaluate
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPhysics_Player : : Evaluate ( int timeStepMSec , int endTimeMSec )
{
2012-11-26 18:58:24 +00:00
idVec3 masterOrigin , oldOrigin ;
idMat3 masterAxis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
waterLevel = WATERLEVEL_NONE ;
waterType = 0 ;
oldOrigin = current . origin ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
clipModel - > Unlink ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// if bound to a master
2012-11-28 15:47:07 +00:00
if ( masterEntity )
{
2012-11-26 18:58:24 +00:00
self - > GetMasterPosition ( masterOrigin , masterAxis ) ;
current . origin = masterOrigin + current . localOrigin * masterAxis ;
clipModel - > Link ( gameLocal . clip , self , 0 , current . origin , clipModel - > GetAxis ( ) ) ;
current . velocity = ( current . origin - oldOrigin ) / ( timeStepMSec * 0.001f ) ;
masterDeltaYaw = masterYaw ;
masterYaw = masterAxis [ 0 ] . ToYaw ( ) ;
masterDeltaYaw = masterYaw - masterDeltaYaw ;
return true ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ActivateContactEntities ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idPhysics_Player : : MovePlayer ( timeStepMSec ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
clipModel - > Link ( gameLocal . clip , self , 0 , current . origin , clipModel - > GetAxis ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( IsOutsideWorld ( ) )
{
gameLocal . Warning ( " clip model outside world bounds for entity '%s' at (%s) " , self - > name . c_str ( ) , current . origin . ToString ( 0 ) ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return true ; //( current.origin != oldOrigin );
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : Interpolate
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPhysics_Player : : Interpolate ( const float fraction )
{
2012-11-26 18:58:24 +00:00
/*
// Client is on a pusher... ignore him so he doesn't lag behind
bool becameUnlocked = false ;
if ( ClientPusherLocked ( becameUnlocked ) ) {
return true ;
}
*/
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Test to see how far we are interolating to, if it's a large jump
// in positions, then dont interpolate just do a straight set.
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idVec3 deltaVec = previous . origin - next . origin ;
float deltaLengthSq = idMath : : Fabs ( deltaVec . LengthSqr ( ) ) ;
2012-11-28 15:47:07 +00:00
if ( deltaLengthSq > pm_clientInterpolation_Divergence . GetFloat ( ) )
{
2012-11-26 18:58:24 +00:00
idLib : : Printf ( " Client Interpolation Divergence exceeded, snapping client to next position \n " ) ;
2012-11-28 15:47:07 +00:00
current . origin = next . origin ;
2012-11-26 18:58:24 +00:00
previous . origin = next . origin ;
2012-11-28 15:47:07 +00:00
}
else
{
2012-11-26 18:58:24 +00:00
current . origin = Lerp ( previous . origin , next . origin , fraction ) ;
}
//current.localOrigin = Lerp( previous.localOrigin, next.localOrigin, fraction );
2012-11-28 15:47:07 +00:00
if ( self ! = NULL & & ( self - > entityNumber ! = gameLocal . GetLocalClientNum ( ) ) )
{
2012-11-26 18:58:24 +00:00
current . velocity = Lerp ( previous . velocity , next . velocity , fraction ) ;
}
//current.pushVelocity = Lerp( previous.pushVelocity, next.pushVelocity, fraction );
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//current.movementTime = Lerp( previous.movementTime, next.movementTime, fraction );
//current.stepUp = Lerp( previous.stepUp, next.stepUp, fraction );
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Since we can't lerp between flag-type variables, use the previous flags if
// fraction is < 0.5 and the next flags if fraction is > 0.5.
//const playerPState_t & flagStateToUse = ( fraction < 0.5f ) ? previous : next;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//current.movementFlags = flagStateToUse.movementFlags;
2012-11-28 15:47:07 +00:00
//current.movementType = flagStateToUse.movementType;
if ( clipModel )
{
2012-11-26 18:58:24 +00:00
clipModel - > Link ( gameLocal . clip , self , 0 , next . origin , clipModel - > GetAxis ( ) ) ;
}
return true ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : UpdateTime
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : UpdateTime ( int endTimeMSec )
{
2012-11-26 18:58:24 +00:00
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : GetTime
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idPhysics_Player : : GetTime ( ) const
{
2012-11-26 18:58:24 +00:00
return gameLocal . time ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : GetImpactInfo
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : GetImpactInfo ( const int id , const idVec3 & point , impactInfo_t * info ) const
{
2012-11-26 18:58:24 +00:00
info - > invMass = invMass ;
info - > invInertiaTensor . Zero ( ) ;
info - > position . Zero ( ) ;
info - > velocity = current . velocity ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : ApplyImpulse
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : ApplyImpulse ( const int id , const idVec3 & point , const idVec3 & impulse )
{
if ( current . movementType ! = PM_NOCLIP )
{
2012-11-26 18:58:24 +00:00
current . velocity + = impulse * invMass ;
}
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : IsAtRest
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPhysics_Player : : IsAtRest ( ) const
{
2012-11-26 18:58:24 +00:00
return false ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : GetRestStartTime
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
int idPhysics_Player : : GetRestStartTime ( ) const
{
2012-11-26 18:58:24 +00:00
return - 1 ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : SaveState
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : SaveState ( )
{
2012-11-26 18:58:24 +00:00
saved = current ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : RestoreState
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : RestoreState ( )
{
2012-11-26 18:58:24 +00:00
current = saved ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
clipModel - > Link ( gameLocal . clip , self , 0 , current . origin , clipModel - > GetAxis ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
EvaluateContacts ( ) ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : SetOrigin
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : SetOrigin ( const idVec3 & newOrigin , int id )
{
2012-11-26 18:58:24 +00:00
idVec3 masterOrigin ;
idMat3 masterAxis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
current . localOrigin = newOrigin ;
2012-11-28 15:47:07 +00:00
if ( masterEntity )
{
2012-11-26 18:58:24 +00:00
self - > GetMasterPosition ( masterOrigin , masterAxis ) ;
current . origin = masterOrigin + newOrigin * masterAxis ;
}
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
current . origin = newOrigin ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
clipModel - > Link ( gameLocal . clip , self , 0 , newOrigin , clipModel - > GetAxis ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
previous = next = current ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : GetOrigin
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const idVec3 & idPhysics_Player : : PlayerGetOrigin ( ) const
{
2012-11-26 18:58:24 +00:00
return current . origin ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : SetAxis
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : SetAxis ( const idMat3 & newAxis , int id )
{
2012-11-26 18:58:24 +00:00
clipModel - > Link ( gameLocal . clip , self , 0 , clipModel - > GetOrigin ( ) , newAxis ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
previous = next = current ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : Translate
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : Translate ( const idVec3 & translation , int id )
{
2012-11-26 18:58:24 +00:00
current . localOrigin + = translation ;
current . origin + = translation ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
clipModel - > Link ( gameLocal . clip , self , 0 , current . origin , clipModel - > GetAxis ( ) ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
previous = next = current ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : Rotate
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : Rotate ( const idRotation & rotation , int id )
{
2012-11-26 18:58:24 +00:00
idVec3 masterOrigin ;
idMat3 masterAxis ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
current . origin * = rotation ;
2012-11-28 15:47:07 +00:00
if ( masterEntity )
{
2012-11-26 18:58:24 +00:00
self - > GetMasterPosition ( masterOrigin , masterAxis ) ;
current . localOrigin = ( current . origin - masterOrigin ) * masterAxis . Transpose ( ) ;
}
2012-11-28 15:47:07 +00:00
else
{
2012-11-26 18:58:24 +00:00
current . localOrigin = current . origin ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
clipModel - > Link ( gameLocal . clip , self , 0 , current . origin , clipModel - > GetAxis ( ) * rotation . ToMat3 ( ) ) ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : SetLinearVelocity
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : SetLinearVelocity ( const idVec3 & newLinearVelocity , int id )
{
2012-11-26 18:58:24 +00:00
current . velocity = newLinearVelocity ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : GetLinearVelocity
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const idVec3 & idPhysics_Player : : GetLinearVelocity ( int id ) const
{
2012-11-26 18:58:24 +00:00
return current . velocity ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : SetPushed
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : SetPushed ( int deltaTime )
{
2012-11-26 18:58:24 +00:00
idVec3 velocity ;
float d ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Dont push non Local clients on clients.
2012-11-28 15:47:07 +00:00
if ( self - > entityNumber ! = gameLocal . GetLocalClientNum ( ) & & common - > IsClient ( ) )
{
return ;
}
2012-11-26 18:58:24 +00:00
// velocity with which the player is pushed
velocity = ( current . origin - saved . origin ) / ( deltaTime * idMath : : M_MS2SEC ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// remove any downward push velocity
d = velocity * gravityNormal ;
2012-11-28 15:47:07 +00:00
if ( d > 0.0f )
{
2012-11-26 18:58:24 +00:00
velocity - = d * gravityNormal ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
current . pushVelocity + = velocity ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : SetPushedWithAbnormalVelocityHack
NOTE : Aside from the velocity hack , this MUST be identical to idPhysics_Player : : SetPushed
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : SetPushedWithAbnormalVelocityHack ( int deltaTime )
{
2012-11-26 18:58:24 +00:00
idVec3 velocity ;
float d ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Dont push non Local clients on clients.
2012-11-28 15:47:07 +00:00
if ( self - > entityNumber ! = gameLocal . GetLocalClientNum ( ) & & common - > IsClient ( ) )
{
return ;
}
2012-11-26 18:58:24 +00:00
// velocity with which the player is pushed
velocity = ( current . origin - saved . origin ) / ( deltaTime * idMath : : M_MS2SEC ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// START ABNORMAL VELOCITY HACK
// There is a bug where on the first 1 to 2 frames after a load, the player on the boat
// in le_hell_post will be pushed an abnormal amount by the boat mover, causing them to
// be thrown off of the boat.
//
// We're resolving this by just watching for the abnormal velocities and ignoring the push
// in those cases. Since it is literally only 1 or 2 frames, the remaining updates should
// continue to push the player by sane values.
//
const float ABNORMAL_VELOCITY = 600.0f ; // anything with a magnitude of this or higher will be ignored
const float len = velocity . LengthSqr ( ) ;
2012-11-28 15:47:07 +00:00
if ( len > = Square ( ABNORMAL_VELOCITY ) )
{
2012-11-26 18:58:24 +00:00
velocity . Zero ( ) ; // just ignore the large velocity change completely
}
// END ABNORMAL VELOCITY HACK
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// remove any downward push velocity
d = velocity * gravityNormal ;
2012-11-28 15:47:07 +00:00
if ( d > 0.0f )
{
2012-11-26 18:58:24 +00:00
velocity - = d * gravityNormal ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
current . pushVelocity + = velocity ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : GetPushedLinearVelocity
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
const idVec3 & idPhysics_Player : : GetPushedLinearVelocity ( const int id ) const
{
2012-11-26 18:58:24 +00:00
return current . pushVelocity ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : ClearPushedVelocity
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : ClearPushedVelocity ( )
{
2012-11-26 18:58:24 +00:00
current . pushVelocity . Zero ( ) ;
}
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idPhysics_Player : : ClientPusherLocked
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
bool idPhysics_Player : : ClientPusherLocked ( bool & justBecameUnlocked )
{
2012-11-26 18:58:24 +00:00
bool hasPhysicsContact = false ;
bool hasGroundContact = false ;
2012-11-28 15:47:07 +00:00
for ( int i = 0 ; i < contacts . Num ( ) ; i + + )
{
idEntity * ent = gameLocal . entities [ contacts [ i ] . entityNum ] ;
if ( ent )
{
idPhysics * p = ent - > GetPhysics ( ) ;
if ( p ! = NULL )
{
2012-11-26 18:58:24 +00:00
// Testing IsAtRest seems cleaner but there are edge cases of clients jumping right before a mover starts to move
2012-11-28 15:47:07 +00:00
if ( p - > IsType ( idPhysics_Static : : Type ) = = false & & p - > IsType ( idPhysics_StaticMulti : : Type ) = = false )
{
2012-11-26 18:58:24 +00:00
hasPhysicsContact = true ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
clientPusherLocked = true ; // locked until you have a ground contact that isn't a non static phys obj
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// HACK - Tomiko Reactor rotating disks screw up if server locks the pushed clients, but elevators need clients to be locked ( otherwise clients will clip through elevators )
2012-11-28 15:47:07 +00:00
if ( strcmp ( ent - > GetName ( ) , " cylinder_disk1 " ) = = 0 | | strcmp ( ent - > GetName ( ) , " cylinder_disk2 " ) = = 0 | | strcmp ( ent - > GetName ( ) , " cylinder_disk3 " ) = = 0 )
{
2012-11-26 18:58:24 +00:00
clientPusherLocked = false ;
}
}
}
2012-11-28 15:47:07 +00:00
if ( contacts [ i ] . normal * - gravityNormal > 0.0f )
{
2012-11-26 18:58:24 +00:00
hasGroundContact = true ;
}
}
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
justBecameUnlocked = false ;
2012-11-28 15:47:07 +00:00
if ( hasGroundContact & & ! hasPhysicsContact )
{
if ( clientPusherLocked )
{
2012-11-26 18:58:24 +00:00
justBecameUnlocked = true ;
}
clientPusherLocked = false ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return clientPusherLocked ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : SetMaster
the binding is never orientated
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : SetMaster ( idEntity * master , const bool orientated )
{
2012-11-26 18:58:24 +00:00
idVec3 masterOrigin ;
idMat3 masterAxis ;
2012-11-28 15:47:07 +00:00
if ( master )
{
if ( ! masterEntity )
{
2012-11-26 18:58:24 +00:00
// transform from world space to master space
self - > GetMasterPosition ( masterOrigin , masterAxis ) ;
current . localOrigin = ( current . origin - masterOrigin ) * masterAxis . Transpose ( ) ;
masterEntity = master ;
masterYaw = masterAxis [ 0 ] . ToYaw ( ) ;
}
ClearContacts ( ) ;
}
2012-11-28 15:47:07 +00:00
else
{
if ( masterEntity )
{
2012-11-26 18:58:24 +00:00
masterEntity = NULL ;
}
}
}
const float PLAYER_VELOCITY_MAX = 4000 ;
const int PLAYER_VELOCITY_TOTAL_BITS = 16 ;
const int PLAYER_VELOCITY_EXPONENT_BITS = idMath : : BitsForInteger ( idMath : : BitsForFloat ( PLAYER_VELOCITY_MAX ) ) + 1 ;
const int PLAYER_VELOCITY_MANTISSA_BITS = PLAYER_VELOCITY_TOTAL_BITS - 1 - PLAYER_VELOCITY_EXPONENT_BITS ;
const int PLAYER_MOVEMENT_TYPE_BITS = 3 ;
const int PLAYER_MOVEMENT_FLAGS_BITS = 8 ;
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : WriteToSnapshot
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : WriteToSnapshot ( idBitMsg & msg ) const
{
2012-11-26 18:58:24 +00:00
msg . WriteFloat ( current . origin [ 0 ] ) ;
msg . WriteFloat ( current . origin [ 1 ] ) ;
msg . WriteFloat ( current . origin [ 2 ] ) ;
msg . WriteFloat ( current . velocity [ 0 ] , PLAYER_VELOCITY_EXPONENT_BITS , PLAYER_VELOCITY_MANTISSA_BITS ) ;
msg . WriteFloat ( current . velocity [ 1 ] , PLAYER_VELOCITY_EXPONENT_BITS , PLAYER_VELOCITY_MANTISSA_BITS ) ;
msg . WriteFloat ( current . velocity [ 2 ] , PLAYER_VELOCITY_EXPONENT_BITS , PLAYER_VELOCITY_MANTISSA_BITS ) ;
//idLib::Printf("Writing Velocity: x %2f, y %2f, z %2f \n", current.velocity[0], current.velocity[1], current.velocity[2] );
msg . WriteDeltaFloat ( current . origin [ 0 ] , current . localOrigin [ 0 ] ) ;
msg . WriteDeltaFloat ( current . origin [ 1 ] , current . localOrigin [ 1 ] ) ;
msg . WriteDeltaFloat ( current . origin [ 2 ] , current . localOrigin [ 2 ] ) ;
}
/*
= = = = = = = = = = = = = = = =
idPhysics_Player : : ReadFromSnapshot
= = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
void idPhysics_Player : : ReadFromSnapshot ( const idBitMsg & msg )
{
2012-11-26 18:58:24 +00:00
previous = next ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
next . origin = ReadFloatArray < idVec3 > ( msg ) ;
next . velocity [ 0 ] = msg . ReadFloat ( PLAYER_VELOCITY_EXPONENT_BITS , PLAYER_VELOCITY_MANTISSA_BITS ) ;
next . velocity [ 1 ] = msg . ReadFloat ( PLAYER_VELOCITY_EXPONENT_BITS , PLAYER_VELOCITY_MANTISSA_BITS ) ;
next . velocity [ 2 ] = msg . ReadFloat ( PLAYER_VELOCITY_EXPONENT_BITS , PLAYER_VELOCITY_MANTISSA_BITS ) ;
//idLib::Printf("Reading Velocity: x %2f, y %2f, z %2f \n", next.velocity[0], next.velocity[1], next.velocity[2] );
next . localOrigin = ReadDeltaFloatArray ( msg , next . origin ) ;
2012-11-28 15:47:07 +00:00
if ( clipModel )
{
2012-11-26 18:58:24 +00:00
clipModel - > Link ( gameLocal . clip , self , 0 , next . origin , clipModel - > GetAxis ( ) ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
}