Portable Half-Life SDK. GoldSource and Xash3D. Crossplatform.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3341 lines
78 KiB

/***
*
* Copyright (c) 1996-2002, Valve LLC. All rights reserved.
*
* This product contains software technology licensed from Id
* Software, Inc. ("Id Technology"). Id Technology (c) 1996 Id Software, Inc.
* All Rights Reserved.
*
* Use, distribution, and modification of this source code and/or resulting
* object code is restricted to non-commercial enhancements to products from
* Valve LLC. All other use, distribution, or modification is prohibited
* without written permission from Valve LLC.
*
****/
#include <assert.h>
#include "mathlib.h"
#include "const.h"
#include "usercmd.h"
#include "pm_defs.h"
#include "pm_shared.h"
#include "pm_movevars.h"
#include "pm_debug.h"
//#include <stdio.h> // NULL
#include <math.h> // sqrt
#include <string.h> // strcpy
#ifdef stricmp
#include <strings.h> // strncasecmp
#endif
#include <stdlib.h> // atoi
#include <ctype.h> // isspace
#ifdef CLIENT_DLL
// Spectator Mode
8 years ago
int iJumpSpectator;
extern float vJumpOrigin[3];
extern float vJumpAngles[3];
#endif
static int pm_shared_initialized = 0;
#pragma warning( disable : 4305 )
playermove_t *pmove = NULL;
// Ducking time
8 years ago
#define TIME_TO_DUCK 0.4
#define VEC_DUCK_HULL_MIN -18
#define VEC_DUCK_HULL_MAX 18
#define VEC_DUCK_VIEW 12
#define PM_DEAD_VIEWHEIGHT -8
8 years ago
#define MAX_CLIMB_SPEED 200
#define STUCK_MOVEUP 1
#define STUCK_MOVEDOWN -1
#define VEC_HULL_MIN -36
#define VEC_HULL_MAX 36
8 years ago
#define VEC_VIEW 28
#define STOP_EPSILON 0.1
#define CTEXTURESMAX 512 // max number of textures loaded
#define CBTEXTURENAMEMAX 13 // only load first n chars of name
#define CHAR_TEX_CONCRETE 'C' // texture types
#define CHAR_TEX_METAL 'M'
#define CHAR_TEX_DIRT 'D'
#define CHAR_TEX_VENT 'V'
#define CHAR_TEX_GRATE 'G'
#define CHAR_TEX_TILE 'T'
#define CHAR_TEX_SLOSH 'S'
#define CHAR_TEX_WOOD 'W'
#define CHAR_TEX_COMPUTER 'P'
#define CHAR_TEX_GLASS 'Y'
#define CHAR_TEX_FLESH 'F'
8 years ago
#define STEP_CONCRETE 0 // default step sound
#define STEP_METAL 1 // metal floor
#define STEP_DIRT 2 // dirt, sand, rock
#define STEP_VENT 3 // ventillation duct
#define STEP_GRATE 4 // metal grating
#define STEP_TILE 5 // floor tiles
#define STEP_SLOSH 6 // shallow liquid puddle
#define STEP_WADE 7 // wading in liquid
#define STEP_LADDER 8 // climbing ladder
#define PLAYER_FATAL_FALL_SPEED 1024// approx 60 feet
#define PLAYER_MAX_SAFE_FALL_SPEED 580// approx 20 feet
#define DAMAGE_FOR_FALL_SPEED (float) 100 / ( PLAYER_FATAL_FALL_SPEED - PLAYER_MAX_SAFE_FALL_SPEED )// damage per unit per second.
#define PLAYER_MIN_BOUNCE_SPEED 200
8 years ago
#define PLAYER_FALL_PUNCH_THRESHHOLD (float)350 // won't punch player's screen/make scrape noise unless player falling at least this fast.
8 years ago
#define PLAYER_LONGJUMP_SPEED 350 // how fast we longjump
// double to float warning
#pragma warning(disable : 4244)
#define max(a, b) (((a) > (b)) ? (a) : (b))
#define min(a, b) (((a) < (b)) ? (a) : (b))
// up / down
8 years ago
#define PITCH 0
// left / right
#define YAW 1
// fall over
8 years ago
#define ROLL 2
8 years ago
#define MAX_CLIENTS 32
#define CONTENTS_CURRENT_0 -9
#define CONTENTS_CURRENT_90 -10
8 years ago
#define CONTENTS_CURRENT_180 -11
#define CONTENTS_CURRENT_270 -12
#define CONTENTS_CURRENT_UP -13
8 years ago
#define CONTENTS_CURRENT_DOWN -14
8 years ago
#define CONTENTS_TRANSLUCENT -15
static vec3_t rgv3tStuckTable[54];
static int rgStuckLast[MAX_CLIENTS][2];
// Texture names
static int gcTextures = 0;
static char grgszTextureName[CTEXTURESMAX][CBTEXTURENAMEMAX];
static char grgchTextureType[CTEXTURESMAX];
int g_onladder = 0;
#ifdef CLIENT_DLL
#define materials_path "sound/materials.txt"
#else
#include "cvardef.h"
extern cvar_t materials_txt;
#define materials_path materials_txt.string
#endif
void PM_SwapTextures( int i, int j )
{
char chTemp;
8 years ago
char szTemp[CBTEXTURENAMEMAX];
8 years ago
strcpy( szTemp, grgszTextureName[i] );
chTemp = grgchTextureType[i];
8 years ago
strcpy( grgszTextureName[i], grgszTextureName[j] );
grgchTextureType[i] = grgchTextureType[j];
8 years ago
strcpy( grgszTextureName[j], szTemp );
grgchTextureType[j] = chTemp;
}
void PM_SortTextures( void )
{
// Bubble sort, yuck, but this only occurs at startup and it's only 512 elements...
//
int i, j;
8 years ago
for( i = 0; i < gcTextures; i++ )
{
8 years ago
for( j = i + 1; j < gcTextures; j++ )
{
8 years ago
if( stricmp( grgszTextureName[i], grgszTextureName[j] ) > 0 )
{
// Swap
//
PM_SwapTextures( i, j );
}
}
}
}
void PM_InitTextureTypes()
{
char buffer[512];
int i, j;
byte *pMemFile;
int fileSize, filePos;
static qboolean bTextureTypeInit = false;
8 years ago
if( bTextureTypeInit )
return;
8 years ago
memset(&( grgszTextureName[0][0] ), 0, CTEXTURESMAX * CBTEXTURENAMEMAX );
memset( grgchTextureType, 0, CTEXTURESMAX );
gcTextures = 0;
fileSize = pmove->COM_FileSize( materials_path );
pMemFile = pmove->COM_LoadFile( materials_path, 5, NULL );
8 years ago
if( !pMemFile )
return;
memset( buffer, 0, 512 );
filePos = 0;
// for each line in the file...
8 years ago
while( pmove->memfgets( pMemFile, fileSize, &filePos, buffer, 511 ) != NULL && (gcTextures < CTEXTURESMAX ) )
{
// skip whitespace
i = 0;
8 years ago
while( buffer[i] && isspace( buffer[i] ) )
i++;
8 years ago
if( !buffer[i] )
continue;
// skip comment lines
8 years ago
if( buffer[i] == '/' || !isalpha( buffer[i] ) )
continue;
// get texture type
8 years ago
grgchTextureType[gcTextures] = toupper( buffer[i++] );
// skip whitespace
8 years ago
while( buffer[i] && isspace( buffer[i] ) )
i++;
8 years ago
if( !buffer[i] )
continue;
// get sentence name
j = i;
8 years ago
while( buffer[j] && !isspace( buffer[j] ) )
j++;
8 years ago
if( !buffer[j] )
continue;
// null-terminate name and save in sentences array
8 years ago
j = min( j, CBTEXTURENAMEMAX - 1 + i );
buffer[j] = 0;
8 years ago
strcpy( &( grgszTextureName[gcTextures++][0] ), &( buffer[i] ) );
}
// Must use engine to free since we are in a .dll
8 years ago
pmove->COM_FreeFile( pMemFile );
PM_SortTextures();
bTextureTypeInit = true;
}
char PM_FindTextureType( char *name )
{
int left, right, pivot;
int val;
assert( pm_shared_initialized );
left = 0;
right = gcTextures - 1;
8 years ago
while( left <= right )
{
pivot = ( left + right ) / 2;
8 years ago
val = strnicmp( name, grgszTextureName[pivot], CBTEXTURENAMEMAX - 1 );
if( val == 0 )
{
8 years ago
return grgchTextureType[pivot];
}
8 years ago
else if( val > 0 )
{
left = pivot + 1;
}
8 years ago
else if( val < 0 )
{
right = pivot - 1;
}
}
return CHAR_TEX_CONCRETE;
}
void PM_PlayStepSound( int step, float fvol )
{
static int iSkipStep = 0;
int irand;
vec3_t hvel;
pmove->iStepLeft = !pmove->iStepLeft;
8 years ago
if( !pmove->runfuncs )
{
return;
}
8 years ago
irand = pmove->RandomLong( 0, 1 ) + ( pmove->iStepLeft * 2 );
// FIXME mp_footsteps needs to be a movevar
8 years ago
if( pmove->multiplayer && !pmove->movevars->footsteps )
return;
VectorCopy( pmove->velocity, hvel );
hvel[2] = 0.0;
8 years ago
if( pmove->multiplayer && ( !g_onladder && Length( hvel ) <= 220 ) )
return;
// irand - 0,1 for right foot, 2,3 for left foot
// used to alternate left and right foot
// FIXME, move to player state
8 years ago
switch( step )
{
default:
case STEP_CONCRETE:
8 years ago
switch( irand )
{
// right foot
8 years ago
case 0:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_step1.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
case 1:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_step3.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
// left foot
8 years ago
case 2:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_step2.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
case 3:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_step4.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
}
break;
case STEP_METAL:
8 years ago
switch( irand )
{
// right foot
8 years ago
case 0:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_metal1.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
case 1:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_metal3.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
// left foot
8 years ago
case 2:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_metal2.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
case 3:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_metal4.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
}
break;
case STEP_DIRT:
8 years ago
switch( irand )
{
// right foot
8 years ago
case 0:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_dirt1.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
case 1:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_dirt3.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
// left foot
8 years ago
case 2:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_dirt2.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
case 3:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_dirt4.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
}
break;
case STEP_VENT:
8 years ago
switch( irand )
{
// right foot
8 years ago
case 0:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_duct1.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
case 1:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_duct3.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
// left foot
8 years ago
case 2:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_duct2.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
case 3:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_duct4.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
}
break;
case STEP_GRATE:
8 years ago
switch( irand )
{
// right foot
8 years ago
case 0:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_grate1.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
case 1:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_grate3.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
// left foot
8 years ago
case 2:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_grate2.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
case 3:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_grate4.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
}
break;
case STEP_TILE:
8 years ago
if( !pmove->RandomLong( 0, 4 ) )
irand = 4;
8 years ago
switch( irand )
{
// right foot
8 years ago
case 0:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_tile1.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
case 1:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_tile3.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
// left foot
8 years ago
case 2:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_tile2.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
case 3:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_tile4.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
case 4:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_tile5.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
}
break;
case STEP_SLOSH:
8 years ago
switch( irand )
{
// right foot
8 years ago
case 0:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_slosh1.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
case 1:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_slosh3.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
// left foot
8 years ago
case 2:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_slosh2.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
case 3:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_slosh4.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
}
break;
case STEP_WADE:
8 years ago
if( iSkipStep == 0 )
{
iSkipStep++;
break;
}
8 years ago
if( iSkipStep++ == 3 )
{
iSkipStep = 0;
}
8 years ago
switch( irand )
{
// right foot
8 years ago
case 0:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_wade1.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
case 1:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_wade2.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
// left foot
8 years ago
case 2:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_wade3.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
case 3:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_wade4.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
}
break;
case STEP_LADDER:
8 years ago
switch( irand )
{
// right foot
8 years ago
case 0:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_ladder1.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
case 1:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_ladder3.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
// left foot
8 years ago
case 2:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_ladder2.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
case 3:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_ladder4.wav", fvol, ATTN_NORM, 0, PITCH_NORM );
break;
}
break;
}
}
8 years ago
int PM_MapTextureTypeStepType( char chTextureType )
{
8 years ago
switch( chTextureType )
{
default:
8 years ago
case CHAR_TEX_CONCRETE:
return STEP_CONCRETE;
case CHAR_TEX_METAL:
return STEP_METAL;
case CHAR_TEX_DIRT:
return STEP_DIRT;
case CHAR_TEX_VENT:
return STEP_VENT;
case CHAR_TEX_GRATE:
return STEP_GRATE;
case CHAR_TEX_TILE:
return STEP_TILE;
case CHAR_TEX_SLOSH:
return STEP_SLOSH;
}
}
/*
====================
PM_CatagorizeTextureType
Determine texture info for the texture we are standing on.
====================
*/
void PM_CatagorizeTextureType( void )
{
vec3_t start, end;
const char *pTextureName;
VectorCopy( pmove->origin, start );
VectorCopy( pmove->origin, end );
// Straight down
end[2] -= 64;
// Fill in default values, just in case.
pmove->sztexturename[0] = '\0';
pmove->chtexturetype = CHAR_TEX_CONCRETE;
pTextureName = pmove->PM_TraceTexture( pmove->onground, start, end );
8 years ago
if( !pTextureName )
return;
// strip leading '-0' or '+0~' or '{' or '!'
8 years ago
if( *pTextureName == '-' || *pTextureName == '+' )
pTextureName += 2;
8 years ago
if( *pTextureName == '{' || *pTextureName == '!' || *pTextureName == '~' || *pTextureName == ' ' )
pTextureName++;
// '}}'
strcpy( pmove->sztexturename, pTextureName);
8 years ago
pmove->sztexturename[CBTEXTURENAMEMAX - 1] = 0;
// get texture type
pmove->chtexturetype = PM_FindTextureType( pmove->sztexturename );
}
void PM_UpdateStepSound( void )
{
8 years ago
int fWalking;
float fvol;
vec3_t knee;
vec3_t feet;
vec3_t center;
float height;
float speed;
float velrun;
float velwalk;
float flduck;
8 years ago
int fLadder;
int step;
8 years ago
if( pmove->flTimeStepSound > 0 )
return;
8 years ago
if( pmove->flags & FL_FROZEN )
return;
PM_CatagorizeTextureType();
speed = Length( pmove->velocity );
// determine if we are on a ladder
fLadder = ( pmove->movetype == MOVETYPE_FLY );// IsOnLadder();
// UNDONE: need defined numbers for run, walk, crouch, crouch run velocities!!!!
8 years ago
if( ( pmove->flags & FL_DUCKING) || fLadder )
{
velwalk = 60; // These constants should be based on cl_movespeedkey * cl_forwardspeed somehow
velrun = 80; // UNDONE: Move walking to server
flduck = 100;
}
else
{
velwalk = 120;
velrun = 210;
flduck = 0;
}
// If we're on a ladder or on the ground, and we're moving fast enough,
// play step sound. Also, if pmove->flTimeStepSound is zero, get the new
// sound right away - we just started moving in new level.
8 years ago
if( ( fLadder || ( pmove->onground != -1 ) ) && ( Length( pmove->velocity ) > 0.0 ) && ( speed >= velwalk || !pmove->flTimeStepSound ) )
{
fWalking = speed < velrun;
VectorCopy( pmove->origin, center );
VectorCopy( pmove->origin, knee );
VectorCopy( pmove->origin, feet );
8 years ago
height = pmove->player_maxs[pmove->usehull][2] - pmove->player_mins[pmove->usehull][2];
knee[2] = pmove->origin[2] - 0.3 * height;
feet[2] = pmove->origin[2] - 0.5 * height;
// find out what we're stepping in or on...
8 years ago
if( fLadder )
{
step = STEP_LADDER;
fvol = 0.35;
pmove->flTimeStepSound = 350;
}
8 years ago
else if( pmove->PM_PointContents( knee, NULL ) == CONTENTS_WATER )
{
step = STEP_WADE;
fvol = 0.65;
pmove->flTimeStepSound = 600;
}
8 years ago
else if( pmove->PM_PointContents( feet, NULL ) == CONTENTS_WATER )
{
step = STEP_SLOSH;
fvol = fWalking ? 0.2 : 0.5;
pmove->flTimeStepSound = fWalking ? 400 : 300;
}
else
{
// find texture under player, if different from current texture,
// get material type
step = PM_MapTextureTypeStepType( pmove->chtexturetype );
8 years ago
switch( pmove->chtexturetype )
{
default:
case CHAR_TEX_CONCRETE:
fvol = fWalking ? 0.2 : 0.5;
pmove->flTimeStepSound = fWalking ? 400 : 300;
break;
case CHAR_TEX_METAL:
fvol = fWalking ? 0.2 : 0.5;
pmove->flTimeStepSound = fWalking ? 400 : 300;
break;
case CHAR_TEX_DIRT:
fvol = fWalking ? 0.25 : 0.55;
pmove->flTimeStepSound = fWalking ? 400 : 300;
break;
case CHAR_TEX_VENT:
fvol = fWalking ? 0.4 : 0.7;
pmove->flTimeStepSound = fWalking ? 400 : 300;
break;
case CHAR_TEX_GRATE:
fvol = fWalking ? 0.2 : 0.5;
pmove->flTimeStepSound = fWalking ? 400 : 300;
break;
case CHAR_TEX_TILE:
fvol = fWalking ? 0.2 : 0.5;
pmove->flTimeStepSound = fWalking ? 400 : 300;
break;
case CHAR_TEX_SLOSH:
fvol = fWalking ? 0.2 : 0.5;
pmove->flTimeStepSound = fWalking ? 400 : 300;
break;
}
}
8 years ago
pmove->flTimeStepSound += flduck; // slower step time if ducking
// play the sound
// 35% volume if ducking
8 years ago
if( pmove->flags & FL_DUCKING )
{
fvol *= 0.35;
}
PM_PlayStepSound( step, fvol );
}
}
/*
================
PM_AddToTouched
Add's the trace result to touch list, if contact is not already in list.
================
*/
8 years ago
qboolean PM_AddToTouched( pmtrace_t tr, vec3_t impactvelocity )
{
int i;
8 years ago
for( i = 0; i < pmove->numtouch; i++ )
{
8 years ago
if( pmove->touchindex[i].ent == tr.ent )
break;
}
8 years ago
if( i != pmove->numtouch ) // Already in list.
return false;
VectorCopy( impactvelocity, tr.deltavelocity );
8 years ago
if( pmove->numtouch >= MAX_PHYSENTS )
pmove->Con_DPrintf( "Too many entities were touched!\n" );
pmove->touchindex[pmove->numtouch++] = tr;
return true;
}
/*
================
PM_CheckVelocity
See if the player has a bogus velocity value.
================
*/
8 years ago
void PM_CheckVelocity()
{
8 years ago
int i;
//
// bound velocity
//
8 years ago
for( i = 0; i < 3; i++ )
{
// See if it's bogus.
8 years ago
if( IS_NAN( pmove->velocity[i] ) )
{
8 years ago
pmove->Con_Printf( "PM Got a NaN velocity %i\n", i );
pmove->velocity[i] = 0;
}
8 years ago
if( IS_NAN( pmove->origin[i] ) )
{
8 years ago
pmove->Con_Printf( "PM Got a NaN origin on %i\n", i );
pmove->origin[i] = 0;
}
// Bound it.
8 years ago
if( pmove->velocity[i] > pmove->movevars->maxvelocity )
{
8 years ago
pmove->Con_DPrintf( "PM Got a velocity too high on %i\n", i );
pmove->velocity[i] = pmove->movevars->maxvelocity;
}
8 years ago
else if( pmove->velocity[i] < -pmove->movevars->maxvelocity )
{
8 years ago
pmove->Con_DPrintf( "PM Got a velocity too low on %i\n", i );
pmove->velocity[i] = -pmove->movevars->maxvelocity;
}
}
}
/*
==================
PM_ClipVelocity
Slide off of the impacting object
returns the blocked flags:
0x01 == floor
0x02 == step / wall
==================
*/
8 years ago
int PM_ClipVelocity( vec3_t in, vec3_t normal, vec3_t out, float overbounce )
{
8 years ago
float backoff;
float change;
float angle;
8 years ago
int i, blocked;
8 years ago
angle = normal[2];
blocked = 0x00; // Assume unblocked.
8 years ago
if( angle > 0 ) // If the plane that is blocking us has a positive z component, then assume it's a floor.
blocked |= 0x01;
if( !angle ) // If the plane has no Z, it is vertical (wall/step)
blocked |= 0x02;
// Determine how far along plane to slide based on incoming direction.
// Scale by overbounce factor.
8 years ago
backoff = DotProduct( in, normal ) * overbounce;
8 years ago
for( i = 0; i < 3; i++ )
{
8 years ago
change = normal[i] * backoff;
out[i] = in[i] - change;
// If out velocity is too small, zero it out.
8 years ago
if( out[i] > -STOP_EPSILON && out[i] < STOP_EPSILON )
out[i] = 0;
}
8 years ago
// Return blocking flags.
return blocked;
}
8 years ago
void PM_AddCorrectGravity()
{
8 years ago
float ent_gravity;
8 years ago
if( pmove->waterjumptime )
return;
8 years ago
if( pmove->gravity )
ent_gravity = pmove->gravity;
else
ent_gravity = 1.0;
// Add gravity so they'll be in the correct position during movement
// yes, this 0.5 looks wrong, but it's not.
8 years ago
pmove->velocity[2] -= ( ent_gravity * pmove->movevars->gravity * 0.5 * pmove->frametime );
pmove->velocity[2] += pmove->basevelocity[2] * pmove->frametime;
pmove->basevelocity[2] = 0;
PM_CheckVelocity();
}
8 years ago
void PM_FixupGravityVelocity()
{
8 years ago
float ent_gravity;
8 years ago
if( pmove->waterjumptime )
return;
8 years ago
if( pmove->gravity )
ent_gravity = pmove->gravity;
else
ent_gravity = 1.0;
// Get the correct velocity for the end of the dt
8 years ago
pmove->velocity[2] -= ( ent_gravity * pmove->movevars->gravity * pmove->frametime * 0.5 );
PM_CheckVelocity();
}
/*
============
PM_FlyMove
The basic solid body movement clip that slides along multiple planes
============
*/
8 years ago
int PM_FlyMove( void )
{
8 years ago
int bumpcount, numbumps;
vec3_t dir;
float d;
int numplanes;
vec3_t planes[MAX_CLIP_PLANES];
vec3_t primal_velocity, original_velocity;
vec3_t new_velocity;
int i, j;
pmtrace_t trace;
vec3_t end;
float time_left, allFraction;
int blocked;
numbumps = 4; // Bump up to four times
blocked = 0; // Assume not blocked
numplanes = 0; // and not sliding along any planes
8 years ago
VectorCopy( pmove->velocity, original_velocity ); // Store original velocity
VectorCopy( pmove->velocity, primal_velocity );
allFraction = 0;
time_left = pmove->frametime; // Total time for this movement operation.
8 years ago
for( bumpcount = 0; bumpcount < numbumps; bumpcount++ )
{
8 years ago
if( !pmove->velocity[0] && !pmove->velocity[1] && !pmove->velocity[2] )
break;
// Assume we can move all the way from the current origin to the
// end point.
8 years ago
for( i = 0;i < 3; i++ )
end[i] = pmove->origin[i] + time_left * pmove->velocity[i];
// See if we can make it from origin to end point.
8 years ago
trace = pmove->PM_PlayerTrace( pmove->origin, end, PM_NORMAL, -1 );
allFraction += trace.fraction;
// If we started in a solid object, or we were in solid space
// the whole way, zero out our velocity and return that we
// are blocked by floor and wall.
8 years ago
if( trace.allsolid )
{ // entity is trapped in another solid
8 years ago
VectorCopy( vec3_origin, pmove->velocity );
//Con_DPrintf( "Trapped 4\n" );
return 4;
}
// If we moved some portion of the total distance, then
// copy the end position into the pmove->origin and
// zero the plane counter.
8 years ago
if( trace.fraction > 0 )
{ // actually covered some distance
8 years ago
VectorCopy( trace.endpos, pmove->origin );
VectorCopy( pmove->velocity, original_velocity );
numplanes = 0;
}
// If we covered the entire distance, we are done
// and can return.
8 years ago
if( trace.fraction == 1 )
break; // moved the entire distance
8 years ago
//if( !trace.ent )
// Sys_Error( "PM_PlayerTrace: !trace.ent" );
// Save entity that blocked us (since fraction was < 1.0)
// for contact
// Add it if it's not already in the list!!!
8 years ago
PM_AddToTouched( trace, pmove->velocity );
// If the plane we hit has a high z component in the normal, then
// it's probably a floor
8 years ago
if( trace.plane.normal[2] > 0.7 )
{
8 years ago
blocked |= 1; // floor
}
// If the plane has a zero z component in the normal, then it's a
// step or wall
8 years ago
if( !trace.plane.normal[2] )
{
8 years ago
blocked |= 2; // step / wall
//Con_DPrintf( "Blocked by %i\n", trace.ent );
}
// Reduce amount of pmove->frametime left by total time left * fraction
// that we covered.
time_left -= time_left * trace.fraction;
// Did we run out of planes to clip against?
8 years ago
if( numplanes >= MAX_CLIP_PLANES )
{ // this shouldn't really happen
// Stop our movement if so.
8 years ago
VectorCopy( vec3_origin, pmove->velocity );
//Con_DPrintf( "Too many planes 4\n" );
break;
}
// Set up next clipping plane
8 years ago
VectorCopy( trace.plane.normal, planes[numplanes] );
numplanes++;
8 years ago
// modify original_velocity so it parallels all of the clip planes
//
if( pmove->movetype == MOVETYPE_WALK && ( ( pmove->onground == -1 ) || ( pmove->friction != 1 ) ) ) // relfect player velocity
{
8 years ago
for( i = 0; i < numplanes; i++ )
{
8 years ago
if( planes[i][2] > 0.7 )
{
// floor or slope
PM_ClipVelocity( original_velocity, planes[i], new_velocity, 1 );
VectorCopy( new_velocity, original_velocity );
}
8 years ago
else
PM_ClipVelocity( original_velocity, planes[i], new_velocity, 1.0 + pmove->movevars->bounce * ( 1 - pmove->friction ) );
}
VectorCopy( new_velocity, pmove->velocity );
VectorCopy( new_velocity, original_velocity );
}
else
{
8 years ago
for( i = 0; i < numplanes; i++ )
{
8 years ago
PM_ClipVelocity( original_velocity, planes[i], pmove->velocity, 1 );
for( j = 0; j < numplanes; j++ )
if( j != i )
{
// Are we now moving against this plane?
8 years ago
if( DotProduct( pmove->velocity, planes[j] ) < 0 )
break; // not ok
}
8 years ago
if( j == numplanes ) // Didn't have to clip, so we're ok
break;
}
// Did we go all the way through plane set
8 years ago
if( i != numplanes )
{
// go along this plane
// pmove->velocity is set in clipping call, no need to set again.
}
else
{ // go along the crease
8 years ago
if( numplanes != 2 )
{
8 years ago
//Con_Printf( "clip velocity, numplanes == %i\n",numplanes );
VectorCopy( vec3_origin, pmove->velocity );
//Con_DPrintf( "Trapped 4\n" );
break;
}
8 years ago
CrossProduct( planes[0], planes[1], dir );
d = DotProduct( dir, pmove->velocity );
VectorScale( dir, d, pmove->velocity );
}
8 years ago
//
// if original velocity is against the original velocity, stop dead
// to avoid tiny occilations in sloping corners
//
if( DotProduct( pmove->velocity, primal_velocity ) <= 0 )
{
8 years ago
//Con_DPrintf( "Back\n" );
VectorCopy( vec3_origin, pmove->velocity );
break;
}
}
}
8 years ago
if( allFraction == 0 )
{
8 years ago
VectorCopy( vec3_origin, pmove->velocity );
//Con_DPrintf( "Don't stick\n" );
}
return blocked;
}
/*
==============
PM_Accelerate
==============
*/
8 years ago
void PM_Accelerate( vec3_t wishdir, float wishspeed, float accel )
{
8 years ago
int i;
float addspeed, accelspeed, currentspeed;
// Dead player's don't accelerate
8 years ago
if( pmove->dead )
return;
// If waterjumping, don't accelerate
8 years ago
if( pmove->waterjumptime )
return;
// See if we are changing direction a bit
8 years ago
currentspeed = DotProduct( pmove->velocity, wishdir );
// Reduce wishspeed by the amount of veer.
addspeed = wishspeed - currentspeed;
// If not going to add any speed, done.
8 years ago
if( addspeed <= 0 )
return;
// Determine amount of accleration.
accelspeed = accel * pmove->frametime * wishspeed * pmove->friction;
// Cap at addspeed
8 years ago
if( accelspeed > addspeed )
accelspeed = addspeed;
// Adjust velocity.
8 years ago
for( i = 0; i < 3; i++ )
{
pmove->velocity[i] += accelspeed * wishdir[i];
}
}
/*
=====================
PM_WalkMove
Only used by players. Moves along the ground when player is a MOVETYPE_WALK.
======================
*/
8 years ago
void PM_WalkMove()
{
8 years ago
int clip;
int oldonground;
int i;
8 years ago
vec3_t wishvel;
float spd;
float fmove, smove;
vec3_t wishdir;
float wishspeed;
vec3_t dest, start;
vec3_t original, originalvel;
vec3_t down, downvel;
float downdist, updist;
pmtrace_t trace;
8 years ago
// Copy movement amounts
fmove = pmove->cmd.forwardmove;
smove = pmove->cmd.sidemove;
8 years ago
// Zero out z components of movement vectors
pmove->forward[2] = 0;
8 years ago
pmove->right[2] = 0;
VectorNormalize( pmove->forward ); // Normalize remainder of vectors.
VectorNormalize( pmove->right ); //
for( i = 0; i < 2; i++ ) // Determine x and y parts of velocity
wishvel[i] = pmove->forward[i] * fmove + pmove->right[i] * smove;
wishvel[2] = 0; // Zero out z part of velocity
8 years ago
VectorCopy( wishvel, wishdir ); // Determine maginitude of speed of move
wishspeed = VectorNormalize( wishdir );
8 years ago
//
// Clamp to server defined max speed
//
if( wishspeed > pmove->maxspeed )
{
8 years ago
VectorScale( wishvel, pmove->maxspeed / wishspeed, wishvel );
wishspeed = pmove->maxspeed;
}
// Set pmove velocity
pmove->velocity[2] = 0;
8 years ago
PM_Accelerate( wishdir, wishspeed, pmove->movevars->accelerate );
pmove->velocity[2] = 0;
// Add in any base velocity to the current velocity.
8 years ago
VectorAdd( pmove->velocity, pmove->basevelocity, pmove->velocity );
spd = Length( pmove->velocity );
8 years ago
if( spd < 1.0f )
{
VectorClear( pmove->velocity );
return;
}
// If we are not moving, do nothing
8 years ago
//if( !pmove->velocity[0] && !pmove->velocity[1] && !pmove->velocity[2] )
// return;
oldonground = pmove->onground;
8 years ago
// first try just moving to the destination
dest[0] = pmove->origin[0] + pmove->velocity[0] * pmove->frametime;
dest[1] = pmove->origin[1] + pmove->velocity[1] * pmove->frametime;
dest[2] = pmove->origin[2];
// first try moving directly to the next spot
8 years ago
VectorCopy( dest, start );
trace = pmove->PM_PlayerTrace( pmove->origin, dest, PM_NORMAL, -1 );
// If we made it all the way, then copy trace end
// as new player position.
8 years ago
if( trace.fraction == 1 )
{
8 years ago
VectorCopy( trace.endpos, pmove->origin );
return;
}
8 years ago
// Don't walk up stairs if not on ground.
if( oldonground == -1 && pmove->waterlevel == 0 )
return;
8 years ago
if( pmove->waterjumptime ) // If we are jumping out of water, don't do anything more.
return;
// Try sliding forward both on ground and up 16 pixels
// take the move that goes farthest
8 years ago
VectorCopy( pmove->origin, original ); // Save out original pos &
VectorCopy( pmove->velocity, originalvel ); // velocity.
// Slide move
8 years ago
clip = PM_FlyMove();
// Copy the results out
8 years ago
VectorCopy( pmove->origin, down );
VectorCopy( pmove->velocity, downvel );
// Reset original values.
8 years ago
VectorCopy( original, pmove->origin );
8 years ago
VectorCopy( originalvel, pmove->velocity );
// Start out up one stair height
8 years ago
VectorCopy( pmove->origin, dest );
dest[2] += pmove->movevars->stepsize;
8 years ago
trace = pmove->PM_PlayerTrace( pmove->origin, dest, PM_NORMAL, -1 );
// If we started okay and made it part of the way at least,
// copy the results to the movement start position and then
// run another move try.
8 years ago
if( !trace.startsolid && !trace.allsolid )
{
8 years ago
VectorCopy( trace.endpos, pmove->origin );
}
8 years ago
// slide move the rest of the way.
clip = PM_FlyMove();
8 years ago
// Now try going back down from the end point
// press down the stepheight
VectorCopy( pmove->origin, dest );
dest[2] -= pmove->movevars->stepsize;
8 years ago
trace = pmove->PM_PlayerTrace( pmove->origin, dest, PM_NORMAL, -1 );
// If we are not on the ground any more then
// use the original movement attempt
8 years ago
if( trace.plane.normal[2] < 0.7 )
goto usedown;
// If the trace ended up in empty space, copy the end
// over to the origin.
8 years ago
if( !trace.startsolid && !trace.allsolid )
{
8 years ago
VectorCopy( trace.endpos, pmove->origin );
}
// Copy this origion to up.
8 years ago
VectorCopy( pmove->origin, pmove->up );
// decide which one went farther
8 years ago
downdist = ( down[0] - original[0] ) * ( down[0] - original[0] )
+ ( down[1] - original[1] ) * ( down[1] - original[1] );
updist = ( pmove->up[0] - original[0] ) * ( pmove->up[0] - original[0] )
+ ( pmove->up[1] - original[1] ) * ( pmove->up[1] - original[1] );
8 years ago
if( downdist > updist )
{
usedown:
8 years ago
VectorCopy( down, pmove->origin );
VectorCopy( downvel, pmove->velocity );
} else // copy z value from slide move
pmove->velocity[2] = downvel[2];
}
/*
==================
PM_Friction
Handles both ground friction and water friction
==================
*/
8 years ago
void PM_Friction( void )
{
8 years ago
float *vel;
float speed, newspeed, control;
float friction;
float drop;
vec3_t newvel;
8 years ago
// If we are in water jump cycle, don't apply friction
8 years ago
if( pmove->waterjumptime )
return;
// Get velocity
vel = pmove->velocity;
// Calculate speed
8 years ago
speed = sqrt( vel[0] * vel[0] + vel[1] * vel[1] + vel[2] * vel[2] );
// If too slow, return
8 years ago
if( speed < 0.1f )
{
return;
}
drop = 0;
8 years ago
// apply ground friction
if( pmove->onground != -1 ) // On an entity that is the ground
{
vec3_t start, stop;
pmtrace_t trace;
8 years ago
start[0] = stop[0] = pmove->origin[0] + vel[0] / speed * 16;
start[1] = stop[1] = pmove->origin[1] + vel[1] / speed * 16;
start[2] = pmove->origin[2] + pmove->player_mins[pmove->usehull][2];
stop[2] = start[2] - 34;
8 years ago
trace = pmove->PM_PlayerTrace( start, stop, PM_NORMAL, -1 );
8 years ago
if( trace.fraction == 1.0 )
friction = pmove->movevars->friction*pmove->movevars->edgefriction;
else
friction = pmove->movevars->friction;
// Grab friction value.
//friction = pmove->movevars->friction;
friction *= pmove->friction; // player friction?
// Bleed off some speed, but if we have less than the bleed
// threshhold, bleed the theshold amount.
8 years ago
control = ( speed < pmove->movevars->stopspeed ) ? pmove->movevars->stopspeed : speed;
// Add the amount to t'he drop amount.
8 years ago
drop += control * friction * pmove->frametime;
}
8 years ago
// apply water friction
//if( pmove->waterlevel )
// drop += speed * pmove->movevars->waterfriction * waterlevel * pmove->frametime;
8 years ago
// scale the velocity
newspeed = speed - drop;
8 years ago
if( newspeed < 0 )
newspeed = 0;
// Determine proportion of old speed we are using.
newspeed /= speed;
// Adjust velocity according to proportion.
newvel[0] = vel[0] * newspeed;
newvel[1] = vel[1] * newspeed;
newvel[2] = vel[2] * newspeed;
VectorCopy( newvel, pmove->velocity );
}
8 years ago
void PM_AirAccelerate( vec3_t wishdir, float wishspeed, float accel )
{
8 years ago
int i;
float addspeed, accelspeed, currentspeed, wishspd = wishspeed;
if( pmove->dead )
return;
8 years ago
if( pmove->waterjumptime )
return;
// Cap speed
8 years ago
//wishspd = VectorNormalize( pmove->wishveloc );
if( wishspd > 30 )
wishspd = 30;
// Determine veer amount
8 years ago
currentspeed = DotProduct( pmove->velocity, wishdir );
// See how much to add
addspeed = wishspd - currentspeed;
// If not adding any, done.
8 years ago
if( addspeed <= 0 )
return;
// Determine acceleration speed after acceleration
accelspeed = accel * wishspeed * pmove->frametime * pmove->friction;
// Cap it
8 years ago
if( accelspeed > addspeed )
accelspeed = addspeed;
8 years ago
// Adjust pmove vel.
8 years ago
for( i = 0; i < 3; i++ )
{
8 years ago
pmove->velocity[i] += accelspeed * wishdir[i];
}
}
/*
===================
PM_WaterMove
===================
*/
8 years ago
void PM_WaterMove( void )
{
8 years ago
int i;
vec3_t wishvel;
float wishspeed;
vec3_t wishdir;
vec3_t start, dest;
vec3_t temp;
pmtrace_t trace;
float speed, newspeed, addspeed, accelspeed;
//
// user intentions
//
8 years ago
for( i = 0; i < 3; i++ )
wishvel[i] = pmove->forward[i] * pmove->cmd.forwardmove + pmove->right[i] * pmove->cmd.sidemove;
// Sinking after no other movement occurs
8 years ago
if( !pmove->cmd.forwardmove && !pmove->cmd.sidemove && !pmove->cmd.upmove )
wishvel[2] -= 60; // drift towards bottom
else // Go straight up by upmove amount.
wishvel[2] += pmove->cmd.upmove;
// Copy it over and determine speed
8 years ago
VectorCopy( wishvel, wishdir );
wishspeed = VectorNormalize( wishdir );
// Cap speed.
8 years ago
if( wishspeed > pmove->maxspeed )
{
8 years ago
VectorScale( wishvel, pmove->maxspeed / wishspeed, wishvel );
wishspeed = pmove->maxspeed;
}
// Slow us down a bit.
wishspeed *= 0.8;
8 years ago
VectorAdd( pmove->velocity, pmove->basevelocity, pmove->velocity );
// Water friction
VectorCopy( pmove->velocity, temp );
speed = VectorNormalize( temp );
if( speed )
{
newspeed = speed - pmove->frametime * speed * pmove->movevars->friction * pmove->friction;
8 years ago
if( newspeed < 0 )
newspeed = 0;
8 years ago
VectorScale( pmove->velocity, newspeed / speed, pmove->velocity );
}
else
newspeed = 0;
//
// water acceleration
//
8 years ago
if( wishspeed < 0.1f )
{
return;
}
addspeed = wishspeed - newspeed;
8 years ago
if( addspeed > 0 )
{
8 years ago
VectorNormalize( wishvel );
accelspeed = pmove->movevars->accelerate * wishspeed * pmove->frametime * pmove->friction;
8 years ago
if( accelspeed > addspeed )
accelspeed = addspeed;
8 years ago
for( i = 0; i < 3; i++ )
pmove->velocity[i] += accelspeed * wishvel[i];
}
// Now move
// assume it is a stair or a slope, so press down from stepheight above
8 years ago
VectorMA( pmove->origin, pmove->frametime, pmove->velocity, dest );
VectorCopy( dest, start );
start[2] += pmove->movevars->stepsize + 1;
8 years ago
trace = pmove->PM_PlayerTrace( start, dest, PM_NORMAL, -1 );
if( !trace.startsolid && !trace.allsolid ) // FIXME: check steep slope?
{ // walked up the step, so just keep result and exit
8 years ago
VectorCopy( trace.endpos, pmove->origin );
return;
}
8 years ago
// Try moving straight along out normal path.
8 years ago
PM_FlyMove();
}
/*
===================
PM_AirMove
===================
*/
8 years ago
void PM_AirMove( void )
{
8 years ago
int i;
vec3_t wishvel;
float fmove, smove;
vec3_t wishdir;
float wishspeed;
// Copy movement amounts
fmove = pmove->cmd.forwardmove;
smove = pmove->cmd.sidemove;
8 years ago
// Zero out z components of movement vectors
pmove->forward[2] = 0;
8 years ago
pmove->right[2] = 0;
// Renormalize
8 years ago
VectorNormalize( pmove->forward );
VectorNormalize( pmove->right );
// Determine x and y parts of velocity
8 years ago
for( i = 0; i < 2; i++ )
{
8 years ago
wishvel[i] = pmove->forward[i] * fmove + pmove->right[i] * smove;
}
// Zero out z part of velocity
8 years ago
wishvel[2] = 0;
// Determine maginitude of speed of move
8 years ago
VectorCopy( wishvel, wishdir );
wishspeed = VectorNormalize( wishdir );
// Clamp to server defined max speed
8 years ago
if( wishspeed > pmove->maxspeed )
{
8 years ago
VectorScale( wishvel, pmove->maxspeed/wishspeed, wishvel );
wishspeed = pmove->maxspeed;
}
8 years ago
PM_AirAccelerate( wishdir, wishspeed, pmove->movevars->airaccelerate );
// Add in any base velocity to the current velocity.
8 years ago
VectorAdd( pmove->velocity, pmove->basevelocity, pmove->velocity );
8 years ago
PM_FlyMove();
}
qboolean PM_InWater( void )
{
return ( pmove->waterlevel > 1 );
}
/*
=============
PM_CheckWater
Sets pmove->waterlevel and pmove->watertype values.
=============
*/
8 years ago
qboolean PM_CheckWater()
{
8 years ago
vec3_t point;
int cont;
int truecont;
float height;
float heightover2;
// Pick a spot just above the players feet.
8 years ago
point[0] = pmove->origin[0] + ( pmove->player_mins[pmove->usehull][0] + pmove->player_maxs[pmove->usehull][0] ) * 0.5;
point[1] = pmove->origin[1] + ( pmove->player_mins[pmove->usehull][1] + pmove->player_maxs[pmove->usehull][1] ) * 0.5;
point[2] = pmove->origin[2] + pmove->player_mins[pmove->usehull][2] + 1;
8 years ago
// Assume that we are not in water at all.
pmove->waterlevel = 0;
pmove->watertype = CONTENTS_EMPTY;
// Grab point contents.
cont = pmove->PM_PointContents (point, &truecont );
// Are we under water? (not solid and not empty?)
8 years ago
if( cont <= CONTENTS_WATER && cont > CONTENTS_TRANSLUCENT )
{
// Set water type
pmove->watertype = cont;
// We are at least at level one
pmove->waterlevel = 1;
8 years ago
height = ( pmove->player_mins[pmove->usehull][2] + pmove->player_maxs[pmove->usehull][2] );
heightover2 = height * 0.5;
// Now check a point that is at the player hull midpoint.
point[2] = pmove->origin[2] + heightover2;
8 years ago
cont = pmove->PM_PointContents( point, NULL );
// If that point is also under water...
8 years ago
if( cont <= CONTENTS_WATER && cont > CONTENTS_TRANSLUCENT )
{
// Set a higher water level.
pmove->waterlevel = 2;
// Now check the eye position. (view_ofs is relative to the origin)
point[2] = pmove->origin[2] + pmove->view_ofs[2];
8 years ago
cont = pmove->PM_PointContents( point, NULL );
if( cont <= CONTENTS_WATER && cont > CONTENTS_TRANSLUCENT )
pmove->waterlevel = 3; // In over our eyes
}
// Adjust velocity based on water current, if any.
8 years ago
if( ( truecont <= CONTENTS_CURRENT_0 ) && ( truecont >= CONTENTS_CURRENT_DOWN ) )
{
// The deeper we are, the stronger the current.
static vec3_t current_table[] =
{
8 years ago
{1, 0, 0},
{0, 1, 0},
{-1, 0, 0},
{0, -1, 0},
{0, 0, 1},
{0, 0, -1}
};
8 years ago
VectorMA( pmove->basevelocity, 50.0*pmove->waterlevel, current_table[CONTENTS_CURRENT_0 - truecont], pmove->basevelocity );
}
}
return pmove->waterlevel > 1;
}
/*
=============
PM_CatagorizePosition
=============
*/
8 years ago
void PM_CatagorizePosition( void )
{
8 years ago
vec3_t point;
pmtrace_t tr;
// if the player hull point one unit down is solid, the player
// is on ground
// see if standing on something solid
// Doing this before we move may introduce a potential latency in water detection, but
// doing it after can get us stuck on the bottom in water if the amount we move up
// is less than the 1 pixel 'threshold' we're about to snap to. Also, we'll call
// this several times per frame, so we really need to avoid sticking to the bottom of
// water on each call, and the converse case will correct itself if called twice.
PM_CheckWater();
point[0] = pmove->origin[0];
point[1] = pmove->origin[1];
point[2] = pmove->origin[2] - 2;
8 years ago
if( pmove->velocity[2] > 180 ) // Shooting up really fast. Definitely not on ground.
{
pmove->onground = -1;
}
else
{
// Try and move down.
8 years ago
tr = pmove->PM_PlayerTrace( pmove->origin, point, PM_NORMAL, -1 );
// If we hit a steep plane, we are not on ground
8 years ago
if( tr.plane.normal[2] < 0.7 )
pmove->onground = -1; // too steep
else
pmove->onground = tr.ent; // Otherwise, point to index of ent under us.
// If we are on something...
8 years ago
if( pmove->onground != -1 )
{
// Then we are not in water jump sequence
pmove->waterjumptime = 0;
// If we could make the move, drop us down that 1 pixel
8 years ago
if( pmove->waterlevel < 2 && !tr.startsolid && !tr.allsolid )
VectorCopy( tr.endpos, pmove->origin );
}
// Standing on an entity other than the world
8 years ago
if( tr.ent > 0 ) // So signal that we are touching something.
{
8 years ago
PM_AddToTouched( tr, pmove->velocity );
}
}
}
/*
=================
PM_GetRandomStuckOffsets
When a player is stuck, it's costly to try and unstick them
Grab a test offset for the player based on a passed in index
=================
*/
8 years ago
int PM_GetRandomStuckOffsets( int nIndex, int server, vec3_t offset )
{
8 years ago
// Last time we did a full
int idx;
idx = rgStuckLast[nIndex][server]++;
8 years ago
VectorCopy( rgv3tStuckTable[idx % 54], offset );
8 years ago
return ( idx % 54 );
}
8 years ago
void PM_ResetStuckOffsets( int nIndex, int server )
{
rgStuckLast[nIndex][server] = 0;
}
/*
=================
NudgePosition
If pmove->origin is in a solid position,
try nudging slightly on all axis to
allow for the cut precision of the net coordinates
=================
*/
#define PM_CHECKSTUCK_MINTIME 0.05 // Don't check again too quickly.
8 years ago
int PM_CheckStuck( void )
{
8 years ago
vec3_t base;
vec3_t offset;
vec3_t test;
int hitent;
int idx;
float fTime;
int i;
pmtrace_t traceresult;
static float rgStuckCheckTime[MAX_CLIENTS][2]; // Last time we did a full
// If position is okay, exit
8 years ago
hitent = pmove->PM_TestPlayerPosition( pmove->origin, &traceresult );
if( hitent == -1 )
{
PM_ResetStuckOffsets( pmove->player_index, pmove->server );
return 0;
}
8 years ago
VectorCopy( pmove->origin, base );
8 years ago
//
// Deal with precision error in network.
8 years ago
//
if( !pmove->server )
{
// World or BSP model
8 years ago
if( ( hitent == 0 ) || ( pmove->physents[hitent].model != NULL ) )
{
int nReps = 0;
PM_ResetStuckOffsets( pmove->player_index, pmove->server );
do
{
8 years ago
i = PM_GetRandomStuckOffsets( pmove->player_index, pmove->server, offset );
8 years ago
VectorAdd( base, offset, test );
if( pmove->PM_TestPlayerPosition( test, &traceresult ) == -1 )
{
PM_ResetStuckOffsets( pmove->player_index, pmove->server );
8 years ago
VectorCopy( test, pmove->origin );
return 0;
}
nReps++;
8 years ago
} while( nReps < 54 );
}
}
// Only an issue on the client.
8 years ago
if( pmove->server )
idx = 0;
else
idx = 1;
fTime = pmove->Sys_FloatTime();
// Too soon?
8 years ago
if( rgStuckCheckTime[pmove->player_index][idx] >= ( fTime - PM_CHECKSTUCK_MINTIME ) )
{
return 1;
}
rgStuckCheckTime[pmove->player_index][idx] = fTime;
pmove->PM_StuckTouch( hitent, &traceresult );
8 years ago
i = PM_GetRandomStuckOffsets( pmove->player_index, pmove->server, offset );
8 years ago
VectorAdd( base, offset, test );
if( ( hitent = pmove->PM_TestPlayerPosition( test, NULL ) ) == -1 )
{
8 years ago
//Con_DPrintf( "Nudged\n" );
PM_ResetStuckOffsets( pmove->player_index, pmove->server );
8 years ago
VectorCopy( test, pmove->origin );
return 0;
}
// If player is flailing while stuck in another player ( should never happen ), then see
// if we can't "unstick" them forceably.
8 years ago
if( pmove->cmd.buttons & ( IN_JUMP | IN_DUCK | IN_ATTACK ) && ( pmove->physents[hitent].player != 0 ) )
{
float x, y, z;
float xystep = 8.0;
float zstep = 18.0;
float xyminmax = xystep;
float zminmax = 4 * zstep;
8 years ago
for( z = 0; z <= zminmax; z += zstep )
{
8 years ago
for( x = -xyminmax; x <= xyminmax; x += xystep )
{
8 years ago
for( y = -xyminmax; y <= xyminmax; y += xystep )
{
VectorCopy( base, test );
test[0] += x;
test[1] += y;
test[2] += z;
8 years ago
if( pmove->PM_TestPlayerPosition( test, NULL ) == -1 )
{
VectorCopy( test, pmove->origin );
return 0;
}
}
}
}
}
8 years ago
//VectorCopy( base, pmove->origin );
return 1;
}
/*
===============
PM_SpectatorMove
===============
*/
8 years ago
void PM_SpectatorMove( void )
{
8 years ago
float speed, drop, friction, control, newspeed;
//float accel;
float currentspeed, addspeed, accelspeed;
int i;
vec3_t wishvel;
float fmove, smove;
vec3_t wishdir;
float wishspeed;
// this routine keeps track of the spectators psoition
// there a two different main move types : track player or moce freely (OBS_ROAMING)
// doesn't need excate track position, only to generate PVS, so just copy
// targets position and real view position is calculated on client (saves server CPU)
8 years ago
if( pmove->iuser1 == OBS_ROAMING )
{
#ifdef CLIENT_DLL
// jump only in roaming mode
8 years ago
if( iJumpSpectator )
{
VectorCopy( vJumpOrigin, pmove->origin );
VectorCopy( vJumpAngles, pmove->angles );
VectorCopy( vec3_origin, pmove->velocity );
iJumpSpectator = 0;
return;
}
8 years ago
#endif
// Move around in normal spectator method
8 years ago
speed = Length( pmove->velocity );
if( speed < 1 )
{
8 years ago
VectorCopy( vec3_origin, pmove->velocity )
}
else
{
drop = 0;
8 years ago
friction = pmove->movevars->friction * 1.5; // extra friction
control = speed < pmove->movevars->stopspeed ? pmove->movevars->stopspeed : speed;
8 years ago
drop += control * friction*pmove->frametime;
// scale the velocity
newspeed = speed - drop;
8 years ago
if( newspeed < 0 )
newspeed = 0;
newspeed /= speed;
8 years ago
VectorScale( pmove->velocity, newspeed, pmove->velocity );
}
// accelerate
fmove = pmove->cmd.forwardmove;
smove = pmove->cmd.sidemove;
8 years ago
VectorNormalize( pmove->forward );
VectorNormalize( pmove->right );
for( i = 0; i < 3; i++ )
{
8 years ago
wishvel[i] = pmove->forward[i] * fmove + pmove->right[i] * smove;
}
wishvel[2] += pmove->cmd.upmove;
8 years ago
VectorCopy( wishvel, wishdir );
wishspeed = VectorNormalize( wishdir );
//
// clamp to server defined max speed
//
8 years ago
if( wishspeed > pmove->movevars->spectatormaxspeed )
{
8 years ago
VectorScale( wishvel, pmove->movevars->spectatormaxspeed/wishspeed, wishvel );
wishspeed = pmove->movevars->spectatormaxspeed;
}
8 years ago
currentspeed = DotProduct( pmove->velocity, wishdir );
addspeed = wishspeed - currentspeed;
8 years ago
if( addspeed <= 0 )
return;
8 years ago
accelspeed = pmove->movevars->accelerate * pmove->frametime * wishspeed;
if( accelspeed > addspeed )
accelspeed = addspeed;
8 years ago
for( i = 0; i < 3; i++ )
pmove->velocity[i] += accelspeed*wishdir[i];
// move
8 years ago
VectorMA( pmove->origin, pmove->frametime, pmove->velocity, pmove->origin );
}
else
{
// all other modes just track some kind of target, so spectator PVS = target PVS
int target;
// no valid target ?
8 years ago
if( pmove->iuser2 <= 0 )
return;
// Find the client this player's targeting
8 years ago
for( target = 0; target < pmove->numphysent; target++ )
{
8 years ago
if( pmove->physents[target].info == pmove->iuser2 )
break;
}
8 years ago
if( target == pmove->numphysent )
return;
// use targets position as own origin for PVS
VectorCopy( pmove->physents[target].angles, pmove->angles );
VectorCopy( pmove->physents[target].origin, pmove->origin );
// no velocity
VectorCopy( vec3_origin, pmove->velocity );
}
}
/*
==================
PM_SplineFraction
Use for ease-in, ease-out style interpolation (accel/decel)
Used by ducking code.
==================
*/
float PM_SplineFraction( float value, float scale )
{
float valueSquared;
value = scale * value;
valueSquared = value * value;
// Nice little ease-in, ease-out spline-like curve
return 3 * valueSquared - 2 * valueSquared * value;
}
void PM_FixPlayerCrouchStuck( int direction )
{
8 years ago
int hitent;
int i;
vec3_t test;
8 years ago
hitent = pmove->PM_TestPlayerPosition( pmove->origin, NULL );
if( hitent == -1 )
return;
8 years ago
VectorCopy( pmove->origin, test );
for( i = 0; i < 36; i++ )
{
pmove->origin[2] += direction;
8 years ago
hitent = pmove->PM_TestPlayerPosition( pmove->origin, NULL );
if( hitent == -1 )
return;
}
VectorCopy( test, pmove->origin ); // Failed
}
void PM_UnDuck( void )
{
int i;
pmtrace_t trace;
vec3_t newOrigin;
VectorCopy( pmove->origin, newOrigin );
8 years ago
if( pmove->onground != -1 )
{
8 years ago
for( i = 0; i < 3; i++ )
{
newOrigin[i] += ( pmove->player_mins[1][i] - pmove->player_mins[0][i] );
}
}
8 years ago
trace = pmove->PM_PlayerTrace( newOrigin, newOrigin, PM_NORMAL, -1 );
8 years ago
if( !trace.startsolid )
{
pmove->usehull = 0;
// Oh, no, changing hulls stuck us into something, try unsticking downward first.
8 years ago
trace = pmove->PM_PlayerTrace( newOrigin, newOrigin, PM_NORMAL, -1 );
if( trace.startsolid )
{
// See if we are stuck? If so, stay ducked with the duck hull until we have a clear spot
//Con_Printf( "unstick got stuck\n" );
pmove->usehull = 1;
return;
}
pmove->flags &= ~FL_DUCKING;
pmove->bInDuck = false;
pmove->view_ofs[2] = VEC_VIEW;
pmove->flDuckTime = 0;
8 years ago
VectorCopy( newOrigin, pmove->origin );
// Recatagorize position since ducking can change origin
PM_CatagorizePosition();
}
}
void PM_Duck( void )
{
int i;
float time;
float duckFraction;
8 years ago
int buttonsChanged = ( pmove->oldbuttons ^ pmove->cmd.buttons ); // These buttons have changed this frame
int nButtonPressed = buttonsChanged & pmove->cmd.buttons; // The changed ones still down are "pressed"
8 years ago
int duckchange = buttonsChanged & IN_DUCK ? 1 : 0;
int duckpressed = nButtonPressed & IN_DUCK ? 1 : 0;
8 years ago
if( pmove->cmd.buttons & IN_DUCK )
{
pmove->oldbuttons |= IN_DUCK;
}
else
{
pmove->oldbuttons &= ~IN_DUCK;
}
// Prevent ducking if the iuser3 variable is set
8 years ago
if( pmove->iuser3 || pmove->dead )
{
// Try to unduck
8 years ago
if( pmove->flags & FL_DUCKING )
{
PM_UnDuck();
}
return;
}
8 years ago
if( pmove->flags & FL_DUCKING )
{
pmove->cmd.forwardmove *= 0.333;
8 years ago
pmove->cmd.sidemove *= 0.333;
pmove->cmd.upmove *= 0.333;
}
8 years ago
if( ( pmove->cmd.buttons & IN_DUCK ) || ( pmove->bInDuck ) || ( pmove->flags & FL_DUCKING ) )
{
8 years ago
if( pmove->cmd.buttons & IN_DUCK )
{
8 years ago
if( (nButtonPressed & IN_DUCK ) && !( pmove->flags & FL_DUCKING ) )
{
// Use 1 second so super long jump will work
pmove->flDuckTime = 1000;
8 years ago
pmove->bInDuck = true;
}
time = max( 0.0, ( 1.0 - (float)pmove->flDuckTime / 1000.0 ) );
8 years ago
if( pmove->bInDuck )
{
// Finish ducking immediately if duck time is over or not on ground
8 years ago
if( ( (float)pmove->flDuckTime / 1000.0 <= ( 1.0 - TIME_TO_DUCK ) ) || ( pmove->onground == -1 ) )
{
pmove->usehull = 1;
pmove->view_ofs[2] = VEC_DUCK_VIEW;
pmove->flags |= FL_DUCKING;
pmove->bInDuck = false;
// HACKHACK - Fudge for collision bug - no time to fix this properly
8 years ago
if( pmove->onground != -1 )
{
8 years ago
for( i = 0; i < 3; i++ )
{
pmove->origin[i] -= ( pmove->player_mins[1][i] - pmove->player_mins[0][i] );
}
// See if we are stuck?
PM_FixPlayerCrouchStuck( STUCK_MOVEUP );
// Recatagorize position since ducking can change origin
PM_CatagorizePosition();
}
}
else
{
8 years ago
float fMore = VEC_DUCK_HULL_MIN - VEC_HULL_MIN;
// Calc parametric time
duckFraction = PM_SplineFraction( time, (1.0/TIME_TO_DUCK) );
8 years ago
pmove->view_ofs[2] = ( ( VEC_DUCK_VIEW - fMore ) * duckFraction ) + ( VEC_VIEW * ( 1 - duckFraction ) );
}
}
}
else
{
// Try to unduck
PM_UnDuck();
}
}
}
void PM_LadderMove( physent_t *pLadder )
{
8 years ago
vec3_t ladderCenter;
trace_t trace;
qboolean onFloor;
vec3_t floor;
vec3_t modelmins, modelmaxs;
8 years ago
if( pmove->movetype == MOVETYPE_NOCLIP )
return;
pmove->PM_GetModelBounds( pLadder->model, modelmins, modelmaxs );
VectorAdd( modelmins, modelmaxs, ladderCenter );
VectorScale( ladderCenter, 0.5, ladderCenter );
pmove->movetype = MOVETYPE_FLY;
// On ladder, convert movement to be relative to the ladder
VectorCopy( pmove->origin, floor );
floor[2] += pmove->player_mins[pmove->usehull][2] - 1;
8 years ago
if( pmove->PM_PointContents( floor, NULL ) == CONTENTS_SOLID )
onFloor = true;
else
onFloor = false;
pmove->gravity = 0;
pmove->PM_TraceModel( pLadder, pmove->origin, ladderCenter, &trace );
8 years ago
if( trace.fraction != 1.0 )
{
float forward = 0, right = 0;
vec3_t vpn, v_right;
AngleVectors( pmove->angles, vpn, v_right, NULL );
8 years ago
if( pmove->cmd.buttons & IN_BACK )
forward -= MAX_CLIMB_SPEED;
8 years ago
if( pmove->cmd.buttons & IN_FORWARD )
forward += MAX_CLIMB_SPEED;
8 years ago
if( pmove->cmd.buttons & IN_MOVELEFT )
right -= MAX_CLIMB_SPEED;
8 years ago
if( pmove->cmd.buttons & IN_MOVERIGHT )
right += MAX_CLIMB_SPEED;
8 years ago
if( pmove->cmd.buttons & IN_JUMP )
{
pmove->movetype = MOVETYPE_WALK;
VectorScale( trace.plane.normal, 270, pmove->velocity );
}
else
{
8 years ago
if( forward != 0 || right != 0 )
{
vec3_t velocity, perp, cross, lateral, tmp;
float normal;
8 years ago
//ALERT( at_console, "pev %.2f %.2f %.2f - ",
// pev->velocity.x, pev->velocity.y, pev->velocity.z );
// Calculate player's intended velocity
8 years ago
//Vector velocity = ( forward * gpGlobals->v_forward ) + ( right * gpGlobals->v_right );
VectorScale( vpn, forward, velocity );
VectorMA( velocity, right, v_right, velocity );
// Perpendicular in the ladder plane
8 years ago
// Vector perp = CrossProduct( Vector( 0, 0, 1 ), trace.vecPlaneNormal );
// perp = perp.Normalize();
VectorClear( tmp );
tmp[2] = 1;
CrossProduct( tmp, trace.plane.normal, perp );
VectorNormalize( perp );
// decompose velocity into ladder plane
normal = DotProduct( velocity, trace.plane.normal );
// This is the velocity into the face of the ladder
VectorScale( trace.plane.normal, normal, cross );
// This is the player's additional velocity
VectorSubtract( velocity, cross, lateral );
// This turns the velocity into the face of the ladder into velocity that
// is roughly vertically perpendicular to the face of the ladder.
// NOTE: It IS possible to face up and move down or face down and move up
// because the velocity is a sum of the directional velocity and the converted
// velocity through the face of the ladder -- by design.
CrossProduct( trace.plane.normal, perp, tmp );
VectorMA( lateral, -normal, tmp, pmove->velocity );
8 years ago
if( onFloor && normal > 0 ) // On ground moving away from the ladder
{
VectorMA( pmove->velocity, MAX_CLIMB_SPEED, trace.plane.normal, pmove->velocity );
}
8 years ago
//pev->velocity = lateral - ( CrossProduct( trace.vecPlaneNormal, perp ) * normal );
}
else
{
VectorClear( pmove->velocity );
}
}
}
}
physent_t *PM_Ladder( void )
{
8 years ago
int i;
physent_t *pe;
hull_t *hull;
int num;
vec3_t test;
8 years ago
for( i = 0; i < pmove->nummoveent; i++ )
{
pe = &pmove->moveents[i];
8 years ago
if( pe->model && (modtype_t)pmove->PM_GetModelType( pe->model ) == mod_brush && pe->skin == CONTENTS_LADDER )
{
hull = (hull_t *)pmove->PM_HullForBsp( pe, test );
num = hull->firstclipnode;
// Offset the test point appropriately for this hull.
8 years ago
VectorSubtract( pmove->origin, test, test );
// Test the player's hull for intersection with this model
8 years ago
if( pmove->PM_HullPointContents( hull, num, test ) == CONTENTS_EMPTY )
continue;
8 years ago
return pe;
}
}
return NULL;
}
8 years ago
void PM_WaterJump( void )
{
8 years ago
if( pmove->waterjumptime > 10000 )
{
pmove->waterjumptime = 10000;
}
8 years ago
if( !pmove->waterjumptime )
return;
pmove->waterjumptime -= pmove->cmd.msec;
8 years ago
if( pmove->waterjumptime < 0 || !pmove->waterlevel )
{
pmove->waterjumptime = 0;
pmove->flags &= ~FL_WATERJUMP;
}
pmove->velocity[0] = pmove->movedir[0];
pmove->velocity[1] = pmove->movedir[1];
}
/*
============
PM_AddGravity
============
*/
8 years ago
void PM_AddGravity()
{
8 years ago
float ent_gravity;
8 years ago
if( pmove->gravity )
ent_gravity = pmove->gravity;
else
ent_gravity = 1.0;
// Add gravity incorrectly
8 years ago
pmove->velocity[2] -= ( ent_gravity * pmove->movevars->gravity * pmove->frametime );
pmove->velocity[2] += pmove->basevelocity[2] * pmove->frametime;
pmove->basevelocity[2] = 0;
PM_CheckVelocity();
}
/*
============
PM_PushEntity
Does not change the entities velocity at all
============
*/
8 years ago
pmtrace_t PM_PushEntity( vec3_t push )
{
8 years ago
pmtrace_t trace;
vec3_t end;
8 years ago
VectorAdd( pmove->origin, push, end );
trace = pmove->PM_PlayerTrace( pmove->origin, end, PM_NORMAL, -1 );
VectorCopy( trace.endpos, pmove->origin );
// So we can run impact function afterwards.
8 years ago
if( trace.fraction < 1.0 && !trace.allsolid )
{
8 years ago
PM_AddToTouched( trace, pmove->velocity );
}
return trace;
}
/*
============
PM_Physics_Toss()
Dead player flying through air., e.g.
============
*/
void PM_Physics_Toss()
{
pmtrace_t trace;
8 years ago
vec3_t move;
float backoff;
PM_CheckWater();
8 years ago
if( pmove->velocity[2] > 0 )
pmove->onground = -1;
// If on ground and not moving, return.
8 years ago
if( pmove->onground != -1 )
{
8 years ago
if( VectorCompare( pmove->basevelocity, vec3_origin ) && VectorCompare( pmove->velocity, vec3_origin ) )
return;
}
8 years ago
PM_CheckVelocity();
8 years ago
// add gravity
if( pmove->movetype != MOVETYPE_FLY && pmove->movetype != MOVETYPE_BOUNCEMISSILE && pmove->movetype != MOVETYPE_FLYMISSILE )
PM_AddGravity ();
8 years ago
// move origin
// Base velocity is not properly accounted for since this entity will move again after the bounce without
// taking it into account
8 years ago
VectorAdd( pmove->velocity, pmove->basevelocity, pmove->velocity );
PM_CheckVelocity();
8 years ago
VectorScale( pmove->velocity, pmove->frametime, move );
VectorSubtract( pmove->velocity, pmove->basevelocity, pmove->velocity );
8 years ago
trace = PM_PushEntity( move ); // Should this clear basevelocity
PM_CheckVelocity();
8 years ago
if( trace.allsolid )
{
// entity is trapped in another solid
pmove->onground = trace.ent;
8 years ago
VectorCopy( vec3_origin, pmove->velocity );
return;
}
8 years ago
if( trace.fraction == 1 )
{
PM_CheckWater();
return;
}
8 years ago
if( pmove->movetype == MOVETYPE_BOUNCE )
backoff = 2.0 - pmove->friction;
8 years ago
else if( pmove->movetype == MOVETYPE_BOUNCEMISSILE )
backoff = 2.0;
else
backoff = 1;
8 years ago
PM_ClipVelocity( pmove->velocity, trace.plane.normal, pmove->velocity, backoff );
// stop if on ground
8 years ago
if( trace.plane.normal[2] > 0.7 )
{
float vel;
vec3_t base;
VectorClear( base );
8 years ago
if( pmove->velocity[2] < pmove->movevars->gravity * pmove->frametime )
{
// we're rolling on the ground, add static friction.
pmove->onground = trace.ent;
pmove->velocity[2] = 0;
}
vel = DotProduct( pmove->velocity, pmove->velocity );
8 years ago
// Con_DPrintf( "%f %f: %.0f %.0f %.0f\n", vel, trace.fraction, ent->velocity[0], ent->velocity[1], ent->velocity[2] );
8 years ago
if( vel < ( 30 * 30 ) || ( pmove->movetype != MOVETYPE_BOUNCE && pmove->movetype != MOVETYPE_BOUNCEMISSILE ) )
{
pmove->onground = trace.ent;
8 years ago
VectorCopy( vec3_origin, pmove->velocity );
}
else
{
8 years ago
VectorScale( pmove->velocity, ( 1.0 - trace.fraction) * pmove->frametime * 0.9, move );
trace = PM_PushEntity( move );
}
VectorSubtract( pmove->velocity, base, pmove->velocity )
}
8 years ago
// check for in water
PM_CheckWater();
}
/*
====================
PM_NoClip
====================
*/
void PM_NoClip()
{
8 years ago
int i;
vec3_t wishvel;
float fmove, smove;
//float currentspeed, addspeed, accelspeed;
// Copy movement amounts
fmove = pmove->cmd.forwardmove;
smove = pmove->cmd.sidemove;
8 years ago
VectorNormalize( pmove->forward );
VectorNormalize( pmove->right );
for( i = 0; i < 3; i++ ) // Determine x and y parts of velocity
{
8 years ago
wishvel[i] = pmove->forward[i] * fmove + pmove->right[i] * smove;
}
wishvel[2] += pmove->cmd.upmove;
8 years ago
VectorMA (pmove->origin, pmove->frametime, wishvel, pmove->origin );
// Zero out the velocity so that we don't accumulate a huge downward velocity from
8 years ago
// gravity, etc.
VectorClear( pmove->velocity );
}
// Only allow bunny jumping up to 1.7x server / player maxspeed setting
#define BUNNYJUMP_MAX_SPEED_FACTOR 1.7f
//-----------------------------------------------------------------------------
// Purpose: Corrects bunny jumping ( where player initiates a bunny jump before other
// movement logic runs, thus making onground == -1 thus making PM_Friction get skipped and
// running PM_AirMove, which doesn't crop velocity to maxspeed like the ground / other
// movement logic does.
//-----------------------------------------------------------------------------
void PM_PreventMegaBunnyJumping( void )
{
// Current player speed
float spd;
// If we have to crop, apply this cropping fraction to velocity
float fraction;
// Speed at which bunny jumping is limited
float maxscaledspeed;
maxscaledspeed = BUNNYJUMP_MAX_SPEED_FACTOR * pmove->maxspeed;
// Don't divide by zero
8 years ago
if( maxscaledspeed <= 0.0f )
return;
spd = Length( pmove->velocity );
8 years ago
if( spd <= maxscaledspeed )
return;
fraction = ( maxscaledspeed / spd ) * 0.65; //Returns the modifier for the velocity
VectorScale( pmove->velocity, fraction, pmove->velocity ); //Crop it down!.
}
/*
=============
PM_Jump
=============
*/
8 years ago
void PM_Jump( void )
{
int i;
qboolean tfc = false;
qboolean cansuperjump = false;
8 years ago
if( pmove->dead )
{
8 years ago
pmove->oldbuttons |= IN_JUMP; // don't jump again until released
return;
}
tfc = atoi( pmove->PM_Info_ValueForKey( pmove->physinfo, "tfc" ) ) == 1 ? true : false;
// Spy that's feigning death cannot jump
8 years ago
if( tfc && ( pmove->deadflag == ( DEAD_DISCARDBODY + 1 ) ) )
{
return;
}
// See if we are waterjumping. If so, decrement count and return.
8 years ago
if( pmove->waterjumptime )
{
pmove->waterjumptime -= pmove->cmd.msec;
8 years ago
if( pmove->waterjumptime < 0 )
{
pmove->waterjumptime = 0;
}
return;
}
// If we are in the water most of the way...
8 years ago
if( pmove->waterlevel >= 2 )
{
// swimming, not jumping
pmove->onground = -1;
8 years ago
if( pmove->watertype == CONTENTS_WATER ) // We move up a certain amount
pmove->velocity[2] = 100;
8 years ago
else if( pmove->watertype == CONTENTS_SLIME )
pmove->velocity[2] = 80;
8 years ago
else // LAVA
pmove->velocity[2] = 50;
// play swiming sound
8 years ago
if( pmove->flSwimTime <= 0 )
{
// Don't play sound again for 1 second
pmove->flSwimTime = 1000;
8 years ago
switch( pmove->RandomLong( 0, 3 ) )
{
case 0:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_wade1.wav", 1, ATTN_NORM, 0, PITCH_NORM );
break;
case 1:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_wade2.wav", 1, ATTN_NORM, 0, PITCH_NORM );
break;
case 2:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_wade3.wav", 1, ATTN_NORM, 0, PITCH_NORM );
break;
case 3:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_wade4.wav", 1, ATTN_NORM, 0, PITCH_NORM );
break;
}
}
return;
}
// No more effect
8 years ago
if( pmove->onground == -1 )
{
// Flag that we jumped.
// HACK HACK HACK
// Remove this when the game .dll no longer does physics code!!!!
pmove->oldbuttons |= IN_JUMP; // don't jump again until released
return; // in air, so no effect
}
8 years ago
if( pmove->oldbuttons & IN_JUMP )
return; // don't pogo stick
// In the air now.
8 years ago
pmove->onground = -1;
PM_PreventMegaBunnyJumping();
8 years ago
if( tfc )
{
pmove->PM_PlaySound( CHAN_BODY, "player/plyrjmp8.wav", 0.5, ATTN_NORM, 0, PITCH_NORM );
}
else
{
PM_PlayStepSound( PM_MapTextureTypeStepType( pmove->chtexturetype ), 1.0 );
}
// See if user can super long jump?
cansuperjump = atoi( pmove->PM_Info_ValueForKey( pmove->physinfo, "slj" ) ) == 1 ? true : false;
// Acclerate upward
// If we are ducking...
8 years ago
if( ( pmove->bInDuck ) || ( pmove->flags & FL_DUCKING ) )
{
// Adjust for super long jump module
// UNDONE -- note this should be based on forward angles, not current velocity.
8 years ago
if( cansuperjump && ( pmove->cmd.buttons & IN_DUCK ) && ( pmove->flDuckTime > 0 ) &&
Length( pmove->velocity ) > 50 )
{
pmove->punchangle[0] = -5;
8 years ago
for( i = 0; i < 2; i++ )
{
pmove->velocity[i] = pmove->forward[i] * PLAYER_LONGJUMP_SPEED * 1.6;
}
8 years ago
pmove->velocity[2] = sqrt( 2 * 800 * 56.0 );
}
else
{
8 years ago
pmove->velocity[2] = sqrt( 2 * 800 * 45.0 );
}
}
else
{
8 years ago
pmove->velocity[2] = sqrt( 2 * 800 * 45.0 );
}
// Decay it for simulation
PM_FixupGravityVelocity();
// Flag that we jumped.
pmove->oldbuttons |= IN_JUMP; // don't jump again until released
}
/*
=============
PM_CheckWaterJump
=============
*/
#define WJ_HEIGHT 8
8 years ago
void PM_CheckWaterJump( void )
{
8 years ago
vec3_t vecStart, vecEnd;
vec3_t flatforward;
vec3_t flatvelocity;
float curspeed;
pmtrace_t tr;
8 years ago
int savehull;
// Already water jumping.
8 years ago
if( pmove->waterjumptime )
return;
// Don't hop out if we just jumped in
8 years ago
if( pmove->velocity[2] < -180 )
return; // only hop out if we are moving up
// See if we are backing up
flatvelocity[0] = pmove->velocity[0];
flatvelocity[1] = pmove->velocity[1];
flatvelocity[2] = 0;
// Must be moving
curspeed = VectorNormalize( flatvelocity );
8 years ago
// see if near an edge
flatforward[0] = pmove->forward[0];
flatforward[1] = pmove->forward[1];
flatforward[2] = 0;
8 years ago
VectorNormalize( flatforward );
// Are we backing into water from steps or something? If so, don't pop forward
8 years ago
if( curspeed != 0.0 && ( DotProduct( flatvelocity, flatforward ) < 0.0 ) )
return;
VectorCopy( pmove->origin, vecStart );
vecStart[2] += WJ_HEIGHT;
8 years ago
VectorMA( vecStart, 24, flatforward, vecEnd );
// Trace, this trace should use the point sized collision hull
savehull = pmove->usehull;
pmove->usehull = 2;
tr = pmove->PM_PlayerTrace( vecStart, vecEnd, PM_NORMAL, -1 );
8 years ago
if( tr.fraction < 1.0 && fabs( tr.plane.normal[2] ) < 0.1f ) // Facing a near vertical wall?
{
8 years ago
vecStart[2] += pmove->player_maxs[savehull][2] - WJ_HEIGHT;
VectorMA( vecStart, 24, flatforward, vecEnd );
VectorMA( vec3_origin, -50, tr.plane.normal, pmove->movedir );
tr = pmove->PM_PlayerTrace( vecStart, vecEnd, PM_NORMAL, -1 );
8 years ago
if( tr.fraction == 1.0 )
{
pmove->waterjumptime = 2000;
pmove->velocity[2] = 225;
pmove->oldbuttons |= IN_JUMP;
pmove->flags |= FL_WATERJUMP;
}
}
// Reset the collision hull
pmove->usehull = savehull;
}
void PM_CheckFalling( void )
{
8 years ago
if( pmove->onground != -1 && !pmove->dead && pmove->flFallVelocity >= PLAYER_FALL_PUNCH_THRESHHOLD )
{
float fvol = 0.5;
8 years ago
if( pmove->waterlevel > 0 )
{
}
8 years ago
else if( pmove->flFallVelocity > PLAYER_MAX_SAFE_FALL_SPEED )
{
8 years ago
// NOTE: In the original game dll, there were no breaks after these cases, causing the first one to
// cascade into the second
8 years ago
//switch( RandomLong( 0, 1 ) )
//{
//case 0:
//pmove->PM_PlaySound( CHAN_VOICE, "player/pl_fallpain2.wav", 1, ATTN_NORM, 0, PITCH_NORM );
//break;
//case 1:
pmove->PM_PlaySound( CHAN_VOICE, "player/pl_fallpain3.wav", 1, ATTN_NORM, 0, PITCH_NORM );
// break;
//}
fvol = 1.0;
}
8 years ago
else if( pmove->flFallVelocity > PLAYER_MAX_SAFE_FALL_SPEED / 2 )
{
qboolean tfc = false;
tfc = atoi( pmove->PM_Info_ValueForKey( pmove->physinfo, "tfc" ) ) == 1 ? true : false;
8 years ago
if( tfc )
{
pmove->PM_PlaySound( CHAN_VOICE, "player/pl_fallpain3.wav", 1, ATTN_NORM, 0, PITCH_NORM );
}
fvol = 0.85;
}
8 years ago
else if( pmove->flFallVelocity < PLAYER_MIN_BOUNCE_SPEED )
{
fvol = 0;
}
8 years ago
if( fvol > 0.0 )
{
// Play landing step right away
pmove->flTimeStepSound = 0;
8 years ago
PM_UpdateStepSound();
8 years ago
// play step sound for current texture
PM_PlayStepSound( PM_MapTextureTypeStepType( pmove->chtexturetype ), fvol );
// Knock the screen around a little bit, temporary effect
8 years ago
pmove->punchangle[2] = pmove->flFallVelocity * 0.013; // punch z axis
8 years ago
if( pmove->punchangle[0] > 8 )
{
8 years ago
pmove->punchangle[0] = 8;
}
}
}
8 years ago
if( pmove->onground != -1 )
{
pmove->flFallVelocity = 0;
}
}
/*
=================
PM_PlayWaterSounds
=================
*/
void PM_PlayWaterSounds( void )
{
// Did we enter or leave water?
8 years ago
if( ( pmove->oldwaterlevel == 0 && pmove->waterlevel != 0 ) || ( pmove->oldwaterlevel != 0 && pmove->waterlevel == 0 ) )
{
8 years ago
switch( pmove->RandomLong( 0, 3 ) )
{
case 0:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_wade1.wav", 1, ATTN_NORM, 0, PITCH_NORM );
break;
case 1:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_wade2.wav", 1, ATTN_NORM, 0, PITCH_NORM );
break;
case 2:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_wade3.wav", 1, ATTN_NORM, 0, PITCH_NORM );
break;
case 3:
pmove->PM_PlaySound( CHAN_BODY, "player/pl_wade4.wav", 1, ATTN_NORM, 0, PITCH_NORM );
break;
}
}
}
/*
===============
PM_CalcRoll
===============
*/
8 years ago
float PM_CalcRoll( vec3_t angles, vec3_t velocity, float rollangle, float rollspeed )
{
8 years ago
float sign;
float side;
float value;
vec3_t forward, right, up;
AngleVectors( angles, forward, right, up );
side = DotProduct( velocity, right );
sign = side < 0 ? -1 : 1;
8 years ago
side = fabs( side );
value = rollangle;
8 years ago
if( side < rollspeed )
{
side = side * value / rollspeed;
}
8 years ago
else
{
side = value;
}
8 years ago
return side * sign;
}
/*
=============
PM_DropPunchAngle
=============
*/
8 years ago
void PM_DropPunchAngle( vec3_t punchangle )
{
8 years ago
float len;
8 years ago
len = VectorNormalize( punchangle );
len -= ( 10.0 + len * 0.5 ) * pmove->frametime;
len = max( len, 0.0 );
8 years ago
VectorScale( punchangle, len, punchangle );
}
/*
==============
PM_CheckParamters
==============
*/
void PM_CheckParamters( void )
{
float spd;
float maxspeed;
8 years ago
vec3_t v_angle;
8 years ago
spd = ( pmove->cmd.forwardmove * pmove->cmd.forwardmove ) + ( pmove->cmd.sidemove * pmove->cmd.sidemove ) +
( pmove->cmd.upmove * pmove->cmd.upmove );
spd = sqrt( spd );
maxspeed = pmove->clientmaxspeed; //atof( pmove->PM_Info_ValueForKey( pmove->physinfo, "maxspd" ) );
8 years ago
if( maxspeed != 0.0 )
{
pmove->maxspeed = min( maxspeed, pmove->maxspeed );
}
8 years ago
if( ( spd != 0.0 ) && ( spd > pmove->maxspeed ) )
{
float fRatio = pmove->maxspeed / spd;
pmove->cmd.forwardmove *= fRatio;
8 years ago
pmove->cmd.sidemove *= fRatio;
pmove->cmd.upmove *= fRatio;
}
8 years ago
if( pmove->flags & FL_FROZEN || pmove->flags & FL_ONTRAIN || pmove->dead )
{
pmove->cmd.forwardmove = 0;
8 years ago
pmove->cmd.sidemove = 0;
pmove->cmd.upmove = 0;
}
PM_DropPunchAngle( pmove->punchangle );
// Take angles from command.
8 years ago
if( !pmove->dead )
{
8 years ago
VectorCopy( pmove->cmd.viewangles, v_angle );
VectorAdd( v_angle, pmove->punchangle, v_angle );
// Set up view angles.
8 years ago
pmove->angles[ROLL] = PM_CalcRoll( v_angle, pmove->velocity, pmove->movevars->rollangle, pmove->movevars->rollspeed ) * 4;
pmove->angles[PITCH] = v_angle[PITCH];
pmove->angles[YAW] = v_angle[YAW];
}
else
{
VectorCopy( pmove->oldangles, pmove->angles );
}
// Set dead player view_offset
8 years ago
if( pmove->dead )
{
pmove->view_ofs[2] = PM_DEAD_VIEWHEIGHT;
}
// Adjust client view angles to match values used on server.
8 years ago
if( pmove->angles[YAW] > 180.0f )
{
pmove->angles[YAW] -= 360.0f;
}
}
void PM_ReduceTimers( void )
{
8 years ago
if( pmove->flTimeStepSound > 0 )
{
pmove->flTimeStepSound -= pmove->cmd.msec;
8 years ago
if( pmove->flTimeStepSound < 0 )
{
pmove->flTimeStepSound = 0;
}
}
8 years ago
if( pmove->flDuckTime > 0 )
{
pmove->flDuckTime -= pmove->cmd.msec;
8 years ago
if( pmove->flDuckTime < 0 )
{
pmove->flDuckTime = 0;
}
}
8 years ago
if( pmove->flSwimTime > 0 )
{
pmove->flSwimTime -= pmove->cmd.msec;
8 years ago
if( pmove->flSwimTime < 0 )
{
pmove->flSwimTime = 0;
}
}
}
/*
=============
PlayerMove
Returns with origin, angles, and velocity modified in place.
Numtouch and touchindex[] will be set if any of the physents
were contacted during the move.
=============
*/
8 years ago
void PM_PlayerMove( qboolean server )
{
physent_t *pLadder = NULL;
// Are we running server code?
pmove->server = server;
// Adjust speeds etc.
PM_CheckParamters();
// Assume we don't touch anything
pmove->numtouch = 0;
// # of msec to apply movement
pmove->frametime = pmove->cmd.msec * 0.001;
PM_ReduceTimers();
// Convert view angles to vectors
8 years ago
AngleVectors( pmove->angles, pmove->forward, pmove->right, pmove->up );
// PM_ShowClipBox();
// Special handling for spectator and observers. (iuser1 is set if the player's in observer mode)
8 years ago
if( pmove->spectator || pmove->iuser1 > 0 )
{
PM_SpectatorMove();
PM_CatagorizePosition();
return;
}
// Always try and unstick us unless we are in NOCLIP mode
8 years ago
if( pmove->movetype != MOVETYPE_NOCLIP && pmove->movetype != MOVETYPE_NONE )
{
8 years ago
if( PM_CheckStuck() )
{
return; // Can't move, we're stuck
}
}
// Now that we are "unstuck", see where we are ( waterlevel and type, pmove->onground ).
PM_CatagorizePosition();
// Store off the starting water level
pmove->oldwaterlevel = pmove->waterlevel;
// If we are not on ground, store off how fast we are moving down
8 years ago
if( pmove->onground == -1 )
{
pmove->flFallVelocity = -pmove->velocity[2];
}
g_onladder = 0;
// Don't run ladder code if dead or on a train
8 years ago
if( !pmove->dead && !( pmove->flags & FL_ONTRAIN ) )
{
pLadder = PM_Ladder();
8 years ago
if( pLadder )
{
g_onladder = 1;
}
}
PM_UpdateStepSound();
PM_Duck();
// Don't run ladder code if dead or on a train
8 years ago
if( !pmove->dead && !( pmove->flags & FL_ONTRAIN ) )
{
8 years ago
if( pLadder )
{
PM_LadderMove( pLadder );
}
8 years ago
else if( pmove->movetype != MOVETYPE_WALK && pmove->movetype != MOVETYPE_NOCLIP )
{
// Clear ladder stuff unless player is noclipping
// it will be set immediately again next frame if necessary
pmove->movetype = MOVETYPE_WALK;
}
}
// Slow down, I'm pulling it! (a box maybe) but only when I'm standing on ground
8 years ago
if( ( pmove->onground != -1 ) && ( pmove->cmd.buttons & IN_USE ) )
{
VectorScale( pmove->velocity, 0.3, pmove->velocity );
}
// Handle movement
8 years ago
switch( pmove->movetype )
{
default:
8 years ago
pmove->Con_DPrintf( "Bogus pmove player movetype %i on (%i) 0=cl 1=sv\n", pmove->movetype, pmove->server );
break;
case MOVETYPE_NONE:
break;
case MOVETYPE_NOCLIP:
PM_NoClip();
break;
case MOVETYPE_TOSS:
case MOVETYPE_BOUNCE:
PM_Physics_Toss();
break;
case MOVETYPE_FLY:
PM_CheckWater();
// Was jump button pressed?
// If so, set velocity to 270 away from ladder. This is currently wrong.
// Also, set MOVE_TYPE to walk, too.
8 years ago
if( pmove->cmd.buttons & IN_JUMP )
{
8 years ago
if( !pLadder )
{
8 years ago
PM_Jump();
}
}
else
{
pmove->oldbuttons &= ~IN_JUMP;
}
8 years ago
// Perform the move accounting for any base velocity.
8 years ago
VectorAdd( pmove->velocity, pmove->basevelocity, pmove->velocity );
PM_FlyMove();
VectorSubtract( pmove->velocity, pmove->basevelocity, pmove->velocity );
break;
case MOVETYPE_WALK:
8 years ago
if( !PM_InWater() )
{
PM_AddCorrectGravity();
}
// If we are leaping out of the water, just update the counters.
8 years ago
if( pmove->waterjumptime )
{
PM_WaterJump();
PM_FlyMove();
// Make sure waterlevel is set correctly
PM_CheckWater();
return;
}
// If we are swimming in the water, see if we are nudging against a place we can jump up out
// of, and, if so, start out jump. Otherwise, if we are not moving up, then reset jump timer to 0
8 years ago
if( pmove->waterlevel >= 2 )
{
8 years ago
if( pmove->waterlevel == 2 )
{
PM_CheckWaterJump();
}
// If we are falling again, then we must not trying to jump out of water any more.
8 years ago
if( pmove->velocity[2] < 0 && pmove->waterjumptime )
{
pmove->waterjumptime = 0;
}
// Was jump button pressed?
8 years ago
if( pmove->cmd.buttons & IN_JUMP )
{
8 years ago
PM_Jump();
}
else
{
pmove->oldbuttons &= ~IN_JUMP;
}
// Perform regular water movement
PM_WaterMove();
8 years ago
VectorSubtract( pmove->velocity, pmove->basevelocity, pmove->velocity );
// Get a final position
PM_CatagorizePosition();
}
else
// Not underwater
{
// Was jump button pressed?
8 years ago
if( pmove->cmd.buttons & IN_JUMP )
{
8 years ago
if( !pLadder )
{
8 years ago
PM_Jump();
}
}
else
{
pmove->oldbuttons &= ~IN_JUMP;
}
// Fricion is handled before we add in any base velocity. That way, if we are on a conveyor,
// we don't slow when standing still, relative to the conveyor.
8 years ago
if( pmove->onground != -1 )
{
pmove->velocity[2] = 0.0;
PM_Friction();
}
// Make sure velocity is valid.
PM_CheckVelocity();
// Are we on ground now
8 years ago
if( pmove->onground != -1 )
{
PM_WalkMove();
}
else
{
PM_AirMove(); // Take into account movement when in air.
}
// Set final flags.
PM_CatagorizePosition();
// Now pull the base velocity back out.
// Base velocity is set if you are on a moving object, like
// a conveyor (or maybe another monster?)
8 years ago
VectorSubtract( pmove->velocity, pmove->basevelocity, pmove->velocity );
// Make sure velocity is valid.
PM_CheckVelocity();
// Add any remaining gravitational component.
8 years ago
if( !PM_InWater() )
{
PM_FixupGravityVelocity();
}
// If we are on ground, no downward velocity.
8 years ago
if( pmove->onground != -1 )
{
pmove->velocity[2] = 0;
}
// See if we landed on the ground with enough force to play
// a landing sound.
PM_CheckFalling();
}
// Did we enter or leave the water?
PM_PlayWaterSounds();
break;
}
}
void PM_CreateStuckTable( void )
{
float x, y, z;
int idx;
int i;
float zi[3];
8 years ago
memset( rgv3tStuckTable, 0, 54 * sizeof(vec3_t) );
idx = 0;
// Little Moves.
x = y = 0;
// Z moves
8 years ago
for( z = -0.125; z <= 0.125; z += 0.125 )
{
rgv3tStuckTable[idx][0] = x;
rgv3tStuckTable[idx][1] = y;
rgv3tStuckTable[idx][2] = z;
idx++;
}
x = z = 0;
// Y moves
8 years ago
for( y = -0.125; y <= 0.125; y += 0.125 )
{
rgv3tStuckTable[idx][0] = x;
rgv3tStuckTable[idx][1] = y;
rgv3tStuckTable[idx][2] = z;
idx++;
}
y = z = 0;
// X moves
8 years ago
for( x = -0.125; x <= 0.125; x += 0.125 )
{
rgv3tStuckTable[idx][0] = x;
rgv3tStuckTable[idx][1] = y;
rgv3tStuckTable[idx][2] = z;
idx++;
}
// Remaining multi axis nudges.
8 years ago
for( x = - 0.125; x <= 0.125; x += 0.250 )
{
8 years ago
for( y = - 0.125; y <= 0.125; y += 0.250 )
{
8 years ago
for( z = - 0.125; z <= 0.125; z += 0.250 )
{
rgv3tStuckTable[idx][0] = x;
rgv3tStuckTable[idx][1] = y;
rgv3tStuckTable[idx][2] = z;
idx++;
}
}
}
// Big Moves.
x = y = 0;
zi[0] = 0.0f;
zi[1] = 1.0f;
zi[2] = 6.0f;
8 years ago
for( i = 0; i < 3; i++ )
{
// Z moves
z = zi[i];
rgv3tStuckTable[idx][0] = x;
rgv3tStuckTable[idx][1] = y;
rgv3tStuckTable[idx][2] = z;
idx++;
}
x = z = 0;
// Y moves
8 years ago
for( y = -2.0f ; y <= 2.0f ; y += 2.0 )
{
rgv3tStuckTable[idx][0] = x;
rgv3tStuckTable[idx][1] = y;
rgv3tStuckTable[idx][2] = z;
idx++;
}
y = z = 0;
// X moves
8 years ago
for( x = -2.0f ; x <= 2.0f ; x += 2.0f )
{
rgv3tStuckTable[idx][0] = x;
rgv3tStuckTable[idx][1] = y;
rgv3tStuckTable[idx][2] = z;
idx++;
}
// Remaining multi axis nudges.
8 years ago
for( i = 0 ; i < 3; i++ )
{
z = zi[i];
8 years ago
for( x = -2.0f; x <= 2.0f; x += 2.0f )
{
8 years ago
for( y = -2.0f; y <= 2.0f; y += 2.0 )
{
rgv3tStuckTable[idx][0] = x;
rgv3tStuckTable[idx][1] = y;
rgv3tStuckTable[idx][2] = z;
idx++;
}
}
}
}
/*
This modume implements the shared player physics code between any particular game and
the engine. The same PM_Move routine is built into the game .dll and the client .dll and is
invoked by each side as appropriate. There should be no distinction, internally, between server
and client. This will ensure that prediction behaves appropriately.
*/
8 years ago
void PM_Move( struct playermove_s *ppmove, int server )
{
assert( pm_shared_initialized );
pmove = ppmove;
8 years ago
//pmove->Con_Printf( "PM_Move: %g, frametime %g, onground %i\n", pmove->time, pmove->frametime, pmove->onground );
PM_PlayerMove( ( server != 0 ) ? true : false );
8 years ago
if( pmove->onground != -1 )
{
pmove->flags |= FL_ONGROUND;
}
else
{
pmove->flags &= ~FL_ONGROUND;
}
// In single player, reset friction after each movement to FrictionModifier Triggers work still.
8 years ago
if( !pmove->multiplayer && ( pmove->movetype == MOVETYPE_WALK ) )
{
pmove->friction = 1.0f;
}
}
int PM_GetVisEntInfo( int ent )
{
8 years ago
if( ent >= 0 && ent <= pmove->numvisent )
{
8 years ago
return pmove->visents[ent].info;
}
return -1;
}
int PM_GetPhysEntInfo( int ent )
{
8 years ago
if( ent >= 0 && ent <= pmove->numphysent )
{
8 years ago
return pmove->physents[ent].info;
}
return -1;
}
void PM_Init( struct playermove_s *ppmove )
{
assert( !pm_shared_initialized );
pmove = ppmove;
PM_CreateStuckTable();
PM_InitTextureTypes();
pm_shared_initialized = 1;
}