mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-10 15:39:02 +00:00
2116 lines
53 KiB
C++
2116 lines
53 KiB
C++
/*
|
||
This source file is a *modified* version of bg_pmove.c from the Quake 3 Arena source code,
|
||
which was released under the GNU GPL (v2) in 2005.
|
||
Quake 3 Arena is copyright (C) 1999-2005 Id Software, Inc.
|
||
*/
|
||
|
||
|
||
#include "pmove.h"
|
||
|
||
//#include "bprintf.h"
|
||
|
||
//#include "..\..\ESMParser\ESMParser\CELL.h"
|
||
|
||
//#include "GameTime.h"
|
||
|
||
//#include "Sound.h"
|
||
|
||
//#include "..\..\ESMParser\ESMParser\SNDG.h"
|
||
//#include "..\..\ESMParser\ESMParser\SOUN.h"
|
||
|
||
#include <map>
|
||
|
||
#include "trace.h"
|
||
|
||
//SceneInstance* global_lastscene = NULL;
|
||
|
||
// Forward declaration:
|
||
void PM_AirMove();
|
||
|
||
static playerMove* pm = NULL;
|
||
|
||
//extern std::map<CellCoords, CELL* const> ExtCellLookup;
|
||
|
||
static struct playermoveLocal
|
||
{
|
||
playermoveLocal() : frametime(1.0f / 20.0f), groundPlane(true), walking(true), msec(50)
|
||
{
|
||
forward = Ogre::Vector3(0.0f, 0.0f, 0.0f);
|
||
right = Ogre::Vector3(0.0f, 0.0f, 0.0f);
|
||
up = Ogre::Vector3(0.0f, 0.0f, 0.0f);
|
||
|
||
previous_origin = Ogre::Vector3(0.0f, 0.0f, 0.0f);
|
||
previous_velocity = Ogre::Vector3(0.0f, 0.0f, 0.0f);
|
||
}
|
||
|
||
traceResults groundTrace;
|
||
|
||
//SceneInstance* scene;
|
||
|
||
float frametime; // in seconds (usually something like 0.01f)
|
||
float impactSpeed;
|
||
|
||
Ogre::Vector3 forward;
|
||
Ogre::Vector3 right;
|
||
Ogre::Vector3 up;
|
||
|
||
int msec;
|
||
|
||
Ogre::Vector3 previous_origin, previous_velocity;
|
||
|
||
int previous_waterlevel; // the waterlevel before this pmove
|
||
|
||
bool groundPlane; // if we're standing on a groundplane this frame
|
||
|
||
bool walking;
|
||
int waterHeight;
|
||
bool hasWater;
|
||
bool isInterior;
|
||
|
||
} pml;
|
||
|
||
static inline void PM_ClipVelocity(const Ogre::Vector3& in, const Ogre::Vector3& normal, Ogre::Vector3& out, const float overbounce)
|
||
{
|
||
float backoff;
|
||
//float change;
|
||
//int i;
|
||
|
||
// backoff = in dot normal
|
||
//backoff = DotProduct (in, normal);
|
||
backoff = in.dotProduct(normal);
|
||
|
||
if ( backoff < 0 )
|
||
backoff *= overbounce;
|
||
else
|
||
backoff /= overbounce;
|
||
|
||
// change = normal * backoff
|
||
// out = in - change
|
||
/*for ( i=0 ; i<3 ; i++ )
|
||
{
|
||
change = normal[i]*backoff;
|
||
out[i] = in[i] - change;
|
||
|
||
}*/
|
||
float changex = normal.x * backoff;
|
||
out.x = in.x - changex;
|
||
float changey = normal.y * backoff;
|
||
out.y = in.y - changey;
|
||
float changez = normal.z * backoff;
|
||
out.z = in.z - changez;
|
||
}
|
||
|
||
float VectorNormalize2( const Ogre::Vector3& v, Ogre::Vector3& out)
|
||
{
|
||
float length, ilength;
|
||
|
||
length = v.x * v.x+ v.y * v.y + v.z * v.z;
|
||
length = sqrt(length);
|
||
|
||
if (length)
|
||
{
|
||
#ifndef Q3_VM // bk0101022 - FPE related
|
||
// assert( ((Q_fabs(v[0])!=0.0f) || (Q_fabs(v[1])!=0.0f) || (Q_fabs(v[2])!=0.0f)) );
|
||
#endif
|
||
ilength = 1 / length;
|
||
out.x= v.x * ilength;
|
||
out.y = v.y * ilength;
|
||
out.z = v.z * ilength;
|
||
} else
|
||
{
|
||
#ifndef Q3_VM // bk0101022 - FPE related
|
||
// assert( ((Q_fabs(v[0])==0.0f) && (Q_fabs(v[1])==0.0f) && (Q_fabs(v[2])==0.0f)) );
|
||
#endif
|
||
//VectorClear( out );
|
||
out.x = 0; out.y = 0; out.z = 0;
|
||
}
|
||
|
||
return length;
|
||
|
||
}
|
||
|
||
|
||
float VectorNormalize(Ogre::Vector3& out)
|
||
{
|
||
float length, ilength;
|
||
|
||
length = out.x * out.x + out.y * out.y + out.z * out.z;
|
||
length = sqrt(length);
|
||
|
||
if (length)
|
||
{
|
||
#ifndef Q3_VM // bk0101022 - FPE related
|
||
// assert( ((Q_fabs(v[0])!=0.0f) || (Q_fabs(v[1])!=0.0f) || (Q_fabs(v[2])!=0.0f)) );
|
||
#endif
|
||
ilength = 1 / length;
|
||
out.x = out.x * ilength;
|
||
out.y = out.y * ilength;
|
||
out.z = out.z * ilength;
|
||
}
|
||
|
||
return length;
|
||
|
||
}
|
||
|
||
/*
|
||
==================
|
||
PM_SlideMove
|
||
|
||
Returns qtrue if the velocity was clipped in some way
|
||
==================
|
||
*/
|
||
|
||
bool PM_SlideMove( bool gravity )
|
||
{
|
||
int bumpcount, numbumps;
|
||
Ogre::Vector3 dir;
|
||
float d;
|
||
int numplanes;
|
||
Ogre::Vector3 planes[MAX_CLIP_PLANES];
|
||
Ogre::Vector3 primal_velocity;
|
||
Ogre::Vector3 clipVelocity;
|
||
int i, j, k;
|
||
struct traceResults trace;
|
||
Ogre::Vector3 end(0,0,0);
|
||
float time_left;
|
||
float into;
|
||
Ogre::Vector3 endVelocity(0,0,0);
|
||
Ogre::Vector3 endClipVelocity(0,0,0);
|
||
|
||
numbumps = 4;
|
||
|
||
// primal_velocity = pm->ps->velocity
|
||
//VectorCopy (pm->ps->velocity, primal_velocity);
|
||
primal_velocity = pm->ps.velocity;
|
||
|
||
if ( gravity )
|
||
{
|
||
// endVelocity = pm->ps->velocity - vec3(0, 0, pm->ps->gravity * pml.frametime)
|
||
//VectorCopy( pm->ps->velocity, endVelocity );
|
||
endVelocity = pm->ps.velocity;
|
||
//endVelocity[2] -= pm->ps->gravity * pml.frametime;
|
||
endVelocity.z -= pm->ps.gravity * pml.frametime;
|
||
|
||
// pm->ps->velocity = avg(pm->ps->velocity.z, endVelocity.z)
|
||
//pm->ps->velocity[2] = ( pm->ps->velocity[2] + endVelocity[2] ) * 0.5;
|
||
pm->ps.velocity.z= (pm->ps.velocity.z + endVelocity.z) * 0.5f;
|
||
|
||
//primal_velocity[2] = endVelocity[2];
|
||
primal_velocity.z = endVelocity.z;
|
||
|
||
if ( pml.groundPlane )
|
||
// slide along the ground plane
|
||
//PM_ClipVelocity (pm->ps->velocity, pml.groundTrace.plane.normal, pm->ps->velocity, OVERCLIP );
|
||
PM_ClipVelocity(pm->ps.velocity, pml.groundTrace.planenormal, pm->ps.velocity, OVERCLIP);
|
||
}
|
||
|
||
time_left = pml.frametime;
|
||
|
||
// never turn against the ground plane
|
||
if ( pml.groundPlane )
|
||
{
|
||
numplanes = 1;
|
||
|
||
// planes[0] = pml.groundTrace.plane.normal
|
||
//VectorCopy( pml.groundTrace.plane.normal, planes[0] );
|
||
planes[0] = pml.groundTrace.planenormal;
|
||
} else
|
||
numplanes = 0;
|
||
|
||
// never turn against original velocity
|
||
VectorNormalize2( pm->ps.velocity, planes[numplanes] );
|
||
numplanes++;
|
||
|
||
for ( bumpcount = 0; bumpcount < numbumps; bumpcount++ )
|
||
{
|
||
|
||
// calculate position we are trying to move to
|
||
//VectorMA( pm->ps->origin, time_left, pm->ps->velocity, end );
|
||
end = pm->ps.origin + pm->ps.velocity * time_left;
|
||
|
||
// see if we can make it there
|
||
//pm->trace ( &trace, pm->ps->origin, pm->mins, pm->maxs, end, pm->ps->clientNum, pm->tracemaskg);
|
||
//tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&(end), *(const D3DXVECTOR3* const)&(pm->ps.velocity), 0, pml.traceObj);
|
||
newtrace(&trace, pm->ps.origin, end, pm->ps.halfExtents, Ogre::Math::DegreesToRadians (pm->ps.viewangles.y), pm->isInterior, pm->mEngine);
|
||
|
||
if (trace.allsolid)
|
||
{
|
||
// entity is completely trapped in another solid
|
||
//pm->ps->velocity[2] = 0; // don't build up falling damage, but allow sideways acceleration
|
||
pm->ps.velocity = Ogre::Vector3(0,0,0);
|
||
return true;
|
||
}
|
||
|
||
if (trace.fraction > 0)
|
||
// actually covered some distance
|
||
//VectorCopy (trace.endpos, pm->ps->origin);
|
||
pm->ps.origin = trace.endpos;
|
||
|
||
if (trace.fraction == 1)
|
||
break; // moved the entire distance
|
||
|
||
// save entity for contact8
|
||
//PM_AddTouchEnt( trace.entityNum );
|
||
|
||
time_left -= time_left * trace.fraction;
|
||
|
||
if (numplanes >= MAX_CLIP_PLANES)
|
||
{
|
||
// this shouldn't really happen
|
||
//VectorClear( pm->ps->velocity );
|
||
pm->ps.velocity = Ogre::Vector3(0,0,0);
|
||
return true;
|
||
}
|
||
|
||
//
|
||
// if this is the same plane we hit before, nudge velocity
|
||
// out along it, which fixes some epsilon issues with
|
||
// non-axial planes
|
||
//
|
||
for ( i = 0 ; i < numplanes ; i++ )
|
||
{
|
||
if (trace.planenormal.dotProduct(planes[i]) > 0.99) //OGRE::VECTOR3 ?
|
||
//if ( DotProduct( trace.plane.normal, planes[i] ) > 0.99 )
|
||
{
|
||
// pm->ps->velocity += (trace.plane.normal + pm->ps->velocity)
|
||
//VectorAdd( trace.plane.normal, pm->ps->velocity, pm->ps->velocity );
|
||
pm->ps.velocity = trace.planenormal + pm->ps.velocity;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if ( i < numplanes )
|
||
continue;
|
||
|
||
//VectorCopy (trace.plane.normal, planes[numplanes]);
|
||
planes[numplanes] = trace.planenormal;
|
||
numplanes++;
|
||
|
||
//
|
||
// modify velocity so it parallels all of the clip planes
|
||
//
|
||
|
||
// find a plane that it enters
|
||
for ( i = 0 ; i < numplanes ; i++ )
|
||
{
|
||
//into = DotProduct( pm->ps->velocity, planes[i] );
|
||
into = pm->ps.velocity.dotProduct(planes[i]);
|
||
if ( into >= 0.1 )
|
||
continue; // move doesn't interact with the plane
|
||
|
||
|
||
if(planes[i].x >= .70)
|
||
{
|
||
pm->ps.velocity.z = 0;
|
||
return true;
|
||
}
|
||
// see how hard we are hitting things
|
||
if ( -into > pml.impactSpeed )
|
||
pml.impactSpeed = -into;
|
||
|
||
// slide along the plane
|
||
//PM_ClipVelocity (pm->ps->velocity, planes[i], clipVelocity, OVERCLIP );
|
||
PM_ClipVelocity(pm->ps.velocity, planes[i], clipVelocity, OVERCLIP);
|
||
|
||
// slide along the plane
|
||
PM_ClipVelocity (endVelocity, planes[i], endClipVelocity, OVERCLIP );
|
||
|
||
// see if there is a second plane that the new move enters
|
||
for ( j = 0 ; j < numplanes ; j++ )
|
||
{
|
||
if ( j == i )
|
||
continue;
|
||
|
||
if (clipVelocity.dotProduct(planes[j]) >= 0.1)
|
||
//if ( DotProduct( clipVelocity, planes[j] ) >= 0.1 )
|
||
continue; // move doesn't interact with the plane
|
||
|
||
|
||
|
||
|
||
//pm->ps.velocity = Ogre::Vector3(0,0,0);
|
||
//return true;
|
||
|
||
|
||
// try clipping the move to the plane
|
||
PM_ClipVelocity( clipVelocity, planes[j], clipVelocity, OVERCLIP );
|
||
PM_ClipVelocity( endClipVelocity, planes[j], endClipVelocity, OVERCLIP );
|
||
|
||
// see if it goes back into the first clip plane
|
||
if (clipVelocity.dotProduct(planes[i]) >= 0)
|
||
//if ( DotProduct( clipVelocity, planes[i] ) >= 0 )
|
||
continue;
|
||
|
||
|
||
// slide the original velocity along the crease
|
||
//dProduct (planes[i], planes[j], dir);
|
||
dir = planes[i].crossProduct(planes[j]) ;
|
||
|
||
//VectorNormalize( dir );
|
||
//D3DXVec3Normalize( (D3DXVECTOR3* const)&dir, (const D3DXVECTOR3* const)&dir);
|
||
VectorNormalize(dir);
|
||
|
||
//d = DotProduct( dir, pm->ps->velocity );
|
||
d = dir.dotProduct(pm->ps.velocity);
|
||
|
||
//VectorScale( dir, d, clipVelocity );
|
||
clipVelocity = dir * d;
|
||
|
||
//CrossProduct (planes[i], planes[j], dir);
|
||
dir = planes[i].crossProduct(planes[j]) ;
|
||
|
||
|
||
//VectorNormalize( dir );
|
||
//D3DXVec3Normalize( (D3DXVECTOR3* const)&dir, (const D3DXVECTOR3* const)&dir);
|
||
VectorNormalize(dir);
|
||
|
||
//d = DotProduct( dir, endVelocity );
|
||
d = dir.dotProduct(endVelocity);
|
||
|
||
//VectorScale( dir, d, endClipVelocity );
|
||
endClipVelocity = dir * d;
|
||
|
||
// see if there is a third plane the the new move enters
|
||
for ( k = 0 ; k < numplanes ; k++ )
|
||
{
|
||
|
||
if ( k == i || k == j )
|
||
continue;
|
||
|
||
if (clipVelocity.dotProduct(planes[k]) >= 0.1)
|
||
//if ( DotProduct( clipVelocity, planes[k] ) >= 0.1 )
|
||
continue; // move doesn't interact with the plane
|
||
|
||
// stop dead at a tripple plane interaction
|
||
//VectorClear( pm->ps->velocity );
|
||
//printf("Stop dead at a triple plane interaction\n");
|
||
pm->ps.velocity = Ogre::Vector3(0,0,0);
|
||
return true;
|
||
}
|
||
}
|
||
|
||
// if we have fixed all interactions, try another move
|
||
//VectorCopy( clipVelocity, pm->ps->velocity );
|
||
pm->ps.velocity = clipVelocity;
|
||
|
||
//VectorCopy( endClipVelocity, endVelocity );
|
||
endVelocity = endClipVelocity;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if ( gravity )
|
||
//VectorCopy( endVelocity, pm->ps->velocity );
|
||
pm->ps.velocity = endVelocity;
|
||
|
||
// don't change velocity if in a timer (FIXME: is this correct?)
|
||
if ( pm->ps.pm_time )
|
||
//VectorCopy( primal_velocity, pm->ps->velocity );
|
||
pm->ps.velocity = primal_velocity;
|
||
|
||
//return ( (qboolean)(bumpcount != 0) );
|
||
return bumpcount != 0;
|
||
}
|
||
|
||
/*
|
||
==================
|
||
PM_StepSlideMove
|
||
|
||
==================
|
||
*/
|
||
int PM_StepSlideMove( bool gravity )
|
||
{
|
||
Ogre::Vector3 start_o, start_v;
|
||
Ogre::Vector3 down_o, down_v;
|
||
traceResults trace;
|
||
// float down_dist, up_dist;
|
||
// vec3_t delta, delta2;
|
||
Ogre::Vector3 up, down;
|
||
float stepSize;
|
||
|
||
//std::cout << "StepSlideMove\n";
|
||
// start_o = pm->ps->origin
|
||
//VectorCopy (pm->ps->origin, start_o);
|
||
start_o = pm->ps.origin;
|
||
|
||
// start_v = pm->ps->velocity
|
||
//VectorCopy (pm->ps->velocity, start_v);
|
||
start_v = pm->ps.velocity;
|
||
|
||
if ( PM_SlideMove( gravity ) == false )
|
||
return 1; // we got exactly where we wanted to go first try
|
||
|
||
|
||
// down = start_o - vec3(0, 0, STEPSIZE)
|
||
//VectorCopy(start_o, down);
|
||
down = start_o;
|
||
down.z -= STEPSIZE;
|
||
|
||
//pm->trace (&trace, start_o, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask);
|
||
//tracefunc(&trace, start_o, down, , 0, pml.scene);
|
||
//tracefunc(&trace, *(const D3DXVECTOR3* const)&start_o, *(const D3DXVECTOR3* const)&down, D3DXVECTOR3(0.0f, -STEPSIZE, 0.0f), 0, pml.traceObj);
|
||
newtrace(&trace, down, start_o, pm->ps.halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine);
|
||
|
||
// up = vec3(0, 0, 1)
|
||
//VectorSet(up, 0, 0, 1);
|
||
up = Ogre::Vector3(0.0f, 0.0f, 1.0f);
|
||
|
||
// never step up when you still have up velocity
|
||
//if ( pm->ps->velocity[2] > 0 && (trace.fraction == 1.0 || DotProduct(trace.plane.normal, up) < 0.7))
|
||
if (pm->ps.velocity.z > 0 && (
|
||
trace.fraction == 1.0 || trace.planenormal.dotProduct(up) < 0.7
|
||
) )
|
||
return 2;
|
||
|
||
// down_o = pm->ps->origin
|
||
//VectorCopy (pm->ps->origin, down_o);
|
||
down_o = pm->ps.origin;
|
||
|
||
// down_v = pm->ps->velocity
|
||
//VectorCopy (pm->ps->velocity, down_v);
|
||
down_v = pm->ps.velocity;
|
||
|
||
// up = start_o + vec3(0, 0, STEPSIZE)
|
||
//VectorCopy (start_o, up);
|
||
up = start_o;
|
||
//up[2] += STEPSIZE;
|
||
up.z += STEPSIZE;
|
||
|
||
// test the player position if they were a stepheight higher
|
||
//pm->trace (&trace, start_o, pm->mins, pm->maxs, up, pm->ps->clientNum, pm->tracemask);
|
||
//tracefunc(&trace, *(const D3DXVECTOR3* const)&start_o, *(const D3DXVECTOR3* const)&up, D3DXVECTOR3(0.0f, STEPSIZE, 0.0f), 0, pml.traceObj);
|
||
newtrace(&trace, start_o, up, pm->ps.halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine);
|
||
if ( trace.allsolid )
|
||
{
|
||
//if ( pm->debugLevel )
|
||
//Com_Printf("%i:bend can't step\n", c_pmove);
|
||
//bprintf("bend can't step\n");
|
||
return 3; // can't step up
|
||
}
|
||
|
||
//stepSize = trace.endpos[2] - start_o[2];
|
||
stepSize = trace.endpos.z - start_o.z;
|
||
|
||
// try slidemove from this position
|
||
//VectorCopy (trace.endpos, pm->ps->origin); // pm->ps->origin = trace.endpos
|
||
pm->ps.origin = trace.endpos;
|
||
//VectorCopy (start_v, pm->ps->velocity); // pm->ps->velocity = start_v
|
||
pm->ps.velocity = start_v;
|
||
|
||
PM_SlideMove( gravity );
|
||
|
||
// push down the final amount
|
||
|
||
// down = pm->ps->origin - vec3(0, 0, stepSize)
|
||
//VectorCopy (pm->ps->origin, down);
|
||
down = pm->ps.origin;
|
||
//down[2] -= stepSize;
|
||
down.z -= stepSize;
|
||
|
||
|
||
//pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, down, pm->ps->clientNum, pm->tracemask);
|
||
//tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&down, D3DXVECTOR3(0.0f, -STEPSIZE, 0.0f), 0, pml.traceObj);
|
||
newtrace(&trace, pm->ps.origin, down, pm->ps.halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine);
|
||
if ( !trace.allsolid )
|
||
//VectorCopy (trace.endpos, pm->ps->origin);
|
||
pm->ps.origin = trace.endpos;
|
||
|
||
if ( trace.fraction < 1.0 )
|
||
//PM_ClipVelocity( pm->ps->velocity, trace.plane.normal, pm->ps->velocity, OVERCLIP );
|
||
PM_ClipVelocity(pm->ps.velocity, trace.planenormal, pm->ps.velocity, OVERCLIP);
|
||
|
||
{
|
||
// use the step move
|
||
float delta;
|
||
|
||
//delta = pm->ps->origin[2] - start_o[2];
|
||
delta = pm->ps.origin.z - start_o.z;
|
||
if ( delta > 2 )
|
||
{
|
||
pm->ps.counter = 10;
|
||
|
||
/*
|
||
if (gravity)
|
||
printf("g on: %f ", delta);
|
||
else
|
||
printf("g off: %f ", delta);
|
||
|
||
if ( delta < 7 )
|
||
printf("stepped 3 < x < 7\n");
|
||
//PM_AddEvent( EV_STEP_4 );
|
||
else if ( delta < 11 )
|
||
printf("stepped 7 < x < 11\n");
|
||
//PM_AddEvent( EV_STEP_8 );
|
||
else if ( delta < 15 )
|
||
printf("stepped 11 < x < 15\n");
|
||
//PM_AddEvent( EV_STEP_12 );
|
||
else
|
||
printf("stepped 15+\n");
|
||
//PM_AddEvent( EV_STEP_16 );
|
||
*/
|
||
}
|
||
/*if ( pm->debugLevel )
|
||
Com_Printf("%i:stepped\n", c_pmove);*/
|
||
}
|
||
|
||
return 4;
|
||
}
|
||
|
||
void PM_Friction(void)
|
||
{
|
||
|
||
Ogre::Vector3 vec;
|
||
float* vel;
|
||
float speed, newspeed, control;
|
||
float drop;
|
||
|
||
vel = &(pm->ps.velocity.x);
|
||
|
||
// vec = vel
|
||
//VectorCopy( vel, vec );
|
||
vec = pm->ps.velocity;
|
||
|
||
if ( pml.walking )
|
||
//vec[2] = 0; // ignore slope movement
|
||
vec.z = 0;
|
||
|
||
//speed = VectorLength(vec);
|
||
speed = vec.length();
|
||
if (speed < 1)
|
||
{
|
||
vel[0] = 0;
|
||
vel[1] = 0; // allow sinking underwater
|
||
// FIXME: still have z friction underwater?
|
||
//bprintf("Static friction (vec = [%f, %f, %f]) (vec.length = %f)\n", vec.x, vec.y, vec.z, speed);
|
||
return;
|
||
}
|
||
|
||
drop = 0;
|
||
|
||
// apply ground friction
|
||
if ( pm->ps.waterlevel <= 1 )
|
||
{
|
||
if ( pml.walking )//&& !(pml.groundTrace.surfaceFlags & SURF_SLICK) )
|
||
{
|
||
// if getting knocked back, no friction
|
||
//if ( ! (pm->ps->pm_flags & PMF_TIME_KNOCKBACK) )
|
||
{
|
||
control = (speed < pm_stopspeed) ? pm_stopspeed : speed;
|
||
drop += control * pm_friction * pml.frametime;
|
||
}
|
||
}
|
||
}
|
||
|
||
// apply water friction even if just wading
|
||
if ( pm->ps.waterlevel )
|
||
drop += speed * pm_waterfriction * pm->ps.waterlevel * pml.frametime;
|
||
|
||
// apply flying friction
|
||
/*if ( pm->ps->powerups[PW_FLIGHT])
|
||
drop += speed * pm_flightfriction * pml.frametime;
|
||
|
||
if ( pm->ps->pm_type == PM_SPECTATOR)
|
||
drop += speed * pm_spectatorfriction * pml.frametime;*/
|
||
if (pm->ps.move_type == PM_SPECTATOR)
|
||
drop += speed * pm_flightfriction * pml.frametime;
|
||
|
||
// scale the velocity
|
||
newspeed = speed - drop;
|
||
if (newspeed < 0)
|
||
newspeed = 0;
|
||
|
||
newspeed /= speed;
|
||
|
||
// vel *= newspeed
|
||
vel[0] = vel[0] * newspeed;
|
||
vel[1] = vel[1] * newspeed;
|
||
vel[2] = vel[2] * newspeed;
|
||
}
|
||
|
||
float PM_CmdScale(playerMove::playercmd* const cmd)
|
||
{
|
||
int max;
|
||
float total;
|
||
float scale;
|
||
|
||
max = abs( cmd->forwardmove );
|
||
if ( abs( cmd->rightmove ) > max )
|
||
max = abs( cmd->rightmove );
|
||
|
||
if ( abs( cmd->upmove ) > max )
|
||
max = abs( cmd->upmove );
|
||
|
||
if ( !max )
|
||
return 0;
|
||
|
||
total = sqrtf( (const float)(cmd->forwardmove * cmd->forwardmove
|
||
+ cmd->rightmove * cmd->rightmove + cmd->upmove * cmd->upmove) );
|
||
scale = (float)pm->ps.speed * max / ( 127.0f * total );
|
||
if(pm->ps.move_type == PM_NOCLIP)
|
||
scale *= 10;
|
||
|
||
return scale;
|
||
}
|
||
|
||
static void PM_Accelerate( Ogre::Vector3& wishdir, float wishspeed, float accel )
|
||
{
|
||
// int i;
|
||
float addspeed, accelspeed, currentspeed;
|
||
|
||
|
||
// currentspeed = pm->ps->velocity dot wishdir
|
||
//currentspeed = DotProduct (pm->ps->velocity, wishdir);
|
||
currentspeed = pm->ps.velocity.dotProduct(wishdir);
|
||
|
||
addspeed = wishspeed - currentspeed;
|
||
if (addspeed <= 0)
|
||
return;
|
||
|
||
accelspeed = accel * pml.frametime * wishspeed;
|
||
|
||
// Clamp accelspeed at addspeed
|
||
if (accelspeed > addspeed)
|
||
accelspeed = addspeed;
|
||
|
||
// pm->ps->velocity += accelspeed * wishdir
|
||
//for (i=0 ; i<3 ; i++)
|
||
//pm->ps->velocity[i] += accelspeed * wishdir[i];
|
||
pm->ps.velocity += (wishdir * accelspeed);
|
||
//pm->ps.velocity = wishdir * wishspeed; //New, for instant acceleration
|
||
|
||
}
|
||
|
||
static bool PM_CheckJump(void)
|
||
{
|
||
//if ( pm->ps->pm_flags & PMF_RESPAWNED )
|
||
//return qfalse; // don't allow jump until all buttons are up
|
||
|
||
if ( pm->cmd.upmove < 10 )
|
||
// not holding jump
|
||
return false;
|
||
|
||
pm->cmd.upmove = 0;
|
||
|
||
// must wait for jump to be released
|
||
/*if ( pm->ps->pm_flags & PMF_JUMP_HELD )
|
||
{
|
||
// clear upmove so cmdscale doesn't lower running speed
|
||
pm->cmd.upmove = 0;
|
||
return false;
|
||
}*/
|
||
|
||
pml.groundPlane = false; // jumping away
|
||
pml.walking = false;
|
||
//pm->ps->pm_flags |= PMF_JUMP_HELD;
|
||
|
||
pm->ps.groundEntityNum = ENTITYNUM_NONE;
|
||
pm->ps.velocity.z = pm->ps.jump_velocity;
|
||
pm->ps.bSnap = false;
|
||
//PM_AddEvent( EV_JUMP );
|
||
|
||
/*if ( pm->cmd.forwardmove >= 0 )
|
||
{
|
||
PM_ForceLegsAnim( LEGS_JUMP );
|
||
pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP;
|
||
}
|
||
else
|
||
{
|
||
PM_ForceLegsAnim( LEGS_JUMPB );
|
||
pm->ps->pm_flags |= PMF_BACKWARDS_JUMP;
|
||
}*/
|
||
|
||
return true;
|
||
}
|
||
|
||
static void PM_WaterMove( playerMove* const pm )
|
||
{
|
||
//int i;
|
||
//vec3_t wishvel;
|
||
Ogre::Vector3 wishvel;
|
||
float wishspeed;
|
||
//vec3_t wishdir;
|
||
Ogre::Vector3 wishdir;
|
||
float scale;
|
||
float vel;
|
||
|
||
pm->ps.bSnap = false;
|
||
|
||
/*if ( PM_CheckWaterJump() )
|
||
{
|
||
PM_WaterJumpMove();
|
||
return;
|
||
}*/
|
||
#if 0
|
||
// jump = head for surface
|
||
if ( pm->cmd.upmove >= 10 ) {
|
||
if (pm->ps->velocity[2] > -300) {
|
||
if ( pm->watertype == CONTENTS_WATER ) {
|
||
pm->ps->velocity[2] = 100;
|
||
} else if (pm->watertype == CONTENTS_SLIME) {
|
||
pm->ps->velocity[2] = 80;
|
||
} else {
|
||
pm->ps->velocity[2] = 50;
|
||
}
|
||
}
|
||
}
|
||
#endif
|
||
PM_Friction ();
|
||
|
||
if (pm->cmd.forwardmove || pm->cmd.rightmove)
|
||
{
|
||
//NEEDS TO BE REWRITTEN FOR OGRE TIME---------------------------------------------------
|
||
/*
|
||
static const TimeTicks footstep_duration = GetTimeFreq(); // make each splash last 1.0s
|
||
static TimeTicks lastStepTime = 0;
|
||
const TimeTicks thisStepTime = GetTimeQPC();
|
||
static bool lastWasLeft = false;
|
||
if (thisStepTime > lastStepTime)
|
||
{
|
||
if (pm->cmd.ducking)
|
||
lastStepTime = thisStepTime + footstep_duration * 2; // splashes while ducking are twice as slow
|
||
else
|
||
lastStepTime = thisStepTime + footstep_duration;
|
||
|
||
lastWasLeft = !lastWasLeft;
|
||
*/
|
||
//-----------------jhooks1
|
||
|
||
/*
|
||
namestruct defaultCreature;
|
||
const SNDG* const sndg = SNDG::GetFromMap(defaultCreature, lastWasLeft ? SNDG::r_swim : SNDG::l_swim);
|
||
if (sndg)
|
||
{
|
||
const namestruct& SOUNID = sndg->soundID;
|
||
const SOUN* const soun = SOUN::GetSound(SOUNID);
|
||
if (soun)
|
||
{
|
||
PlaySound2D(soun->soundFilename, soun->soundData->GetVolumeFloat() );
|
||
}
|
||
}*/
|
||
//Sound, ignore for now -- jhooks1
|
||
//}
|
||
}
|
||
|
||
scale = PM_CmdScale( &pm->cmd );
|
||
//
|
||
// user intentions
|
||
//
|
||
if ( !scale )
|
||
{
|
||
/*wishvel[0] = 0;
|
||
wishvel[1] = 0;
|
||
wishvel[2] = -60; // sink towards bottom
|
||
*/
|
||
wishvel.x = 0;
|
||
wishvel.z = -60;
|
||
wishvel.y = 0;
|
||
}
|
||
else
|
||
{
|
||
/*for (i=0 ; i<3 ; i++)
|
||
wishvel[i] = scale * pml.forward[i]*pm->cmd.forwardmove + scale * pml.right[i]*pm->cmd.rightmove;*/
|
||
wishvel = pml.forward * scale * pm->cmd.forwardmove + pml.right * scale * pm->cmd.rightmove;
|
||
|
||
//wishvel[2] += scale * pm->cmd.upmove;
|
||
wishvel.z += pm->cmd.upmove * scale;
|
||
}
|
||
|
||
//VectorCopy (wishvel, wishdir);
|
||
wishdir = wishvel;
|
||
wishspeed = VectorNormalize(wishdir);
|
||
|
||
if ( wishspeed > pm->ps.speed * pm_swimScale )
|
||
wishspeed = pm->ps.speed * pm_swimScale;
|
||
|
||
PM_Accelerate (wishdir, wishspeed, pm_wateraccelerate);
|
||
|
||
// make sure we can go up slopes easily under water
|
||
//if ( pml.groundPlane && DotProduct( pm->ps->velocity, pml.groundTrace.plane.normal ) < 0 )
|
||
if (pml.groundPlane && pm->ps.velocity.dotProduct(pml.groundTrace.planenormal) < 0.0f)
|
||
{
|
||
//vel = VectorLength(pm->ps->velocity);
|
||
vel = pm->ps.velocity.length();
|
||
|
||
// slide along the ground plane
|
||
//PM_ClipVelocity (pm->ps->velocity, pml.groundTrace.plane.normal, pm->ps->velocity, OVERCLIP );
|
||
PM_ClipVelocity(pm->ps.velocity, pml.groundTrace.planenormal, pm->ps.velocity, OVERCLIP);
|
||
|
||
VectorNormalize(pm->ps.velocity);
|
||
//VectorScale(pm->ps->velocity, vel, pm->ps->velocity);
|
||
pm->ps.velocity = pm->ps.velocity * vel;
|
||
}
|
||
|
||
PM_SlideMove( false );
|
||
}
|
||
|
||
/*
|
||
===================
|
||
PM_WalkMove
|
||
|
||
===================
|
||
*/
|
||
static void PM_WalkMove( playerMove* const pmove )
|
||
{
|
||
// int i;
|
||
Ogre::Vector3 wishvel;
|
||
float fmove, smove;
|
||
Ogre::Vector3 wishdir;
|
||
float wishspeed;
|
||
float scale;
|
||
playerMove::playercmd cmd;
|
||
float accelerate;
|
||
float vel;
|
||
//pm->ps.gravity = 4000;
|
||
|
||
//std::cout << "Player is walking\n";
|
||
|
||
if ( pm->ps.waterlevel > 2 && //DotProduct( pml.forward, pml.groundTrace.plane.normal ) > 0 )
|
||
pml.forward.dotProduct(pml.groundTrace.planenormal) > 0.0f)
|
||
{
|
||
// begin swimming
|
||
PM_WaterMove(pmove);
|
||
return;
|
||
}
|
||
|
||
|
||
if ( PM_CheckJump () )
|
||
{
|
||
|
||
// jumped away
|
||
if ( pm->ps.waterlevel > 1 )
|
||
PM_WaterMove(pmove);
|
||
else
|
||
PM_AirMove();
|
||
//printf("Jumped away\n");
|
||
return;
|
||
}
|
||
|
||
// Footsteps time
|
||
if (pmove->cmd.forwardmove || pmove->cmd.rightmove)
|
||
{
|
||
bool step_underwater = false;
|
||
//if (pmove->traceObj)
|
||
//{
|
||
|
||
|
||
//jhooks1 - Water handling, deal with later
|
||
|
||
|
||
|
||
if (pmove->hasWater)
|
||
{
|
||
if (pmove->hasWater )
|
||
{
|
||
const float waterHeight = pmove->waterHeight;
|
||
const float waterSoundStepHeight = waterHeight + pm->ps.halfExtents.y;
|
||
if (pmove->ps.origin.y < waterSoundStepHeight)
|
||
step_underwater = true;
|
||
}
|
||
}
|
||
//}
|
||
|
||
/*
|
||
static const TimeTicks footstep_duration = GetTimeFreq() / 2; // make each footstep last 500ms
|
||
static TimeTicks lastStepTime = 0;
|
||
const TimeTicks thisStepTime = GetTimeQPC();
|
||
static bool lastWasLeft = false;
|
||
if (thisStepTime > lastStepTime)
|
||
{
|
||
if (pmove->cmd.ducking)
|
||
lastStepTime = thisStepTime + footstep_duration * 2; // footsteps while ducking are twice as slow
|
||
else
|
||
lastStepTime = thisStepTime + footstep_duration;
|
||
|
||
lastWasLeft = !lastWasLeft;
|
||
*/
|
||
|
||
if (step_underwater)
|
||
{
|
||
/*
|
||
const namestruct ns(lastWasLeft ? "FootWaterRight" : "FootWaterLeft");
|
||
const SOUN* const soun = SOUN::GetSound(ns);
|
||
if (soun)
|
||
{
|
||
PlaySound2D(soun->soundFilename, soun->soundData->GetVolumeFloat() );
|
||
}*/
|
||
}
|
||
else
|
||
{
|
||
/*
|
||
namestruct defaultCreature;
|
||
const SNDG* const sndg = SNDG::GetFromMap(defaultCreature, lastWasLeft ? SNDG::r_foot : SNDG::l_foot);
|
||
if (sndg)
|
||
{
|
||
const namestruct& SOUNID = sndg->soundID;
|
||
const SOUN* const soun = SOUN::GetSound(SOUNID);
|
||
if (soun)
|
||
{
|
||
PlaySound2D(soun->soundFilename, soun->soundData->GetVolumeFloat() );
|
||
}
|
||
}*/
|
||
}
|
||
}
|
||
|
||
|
||
PM_Friction ();
|
||
|
||
|
||
//bprintf("vel: (%f, %f, %f)\n", pm->ps.velocity.x, pm->ps.velocity.y, pm->ps.velocity.z);
|
||
|
||
fmove = pm->cmd.forwardmove;
|
||
smove = pm->cmd.rightmove;
|
||
|
||
|
||
cmd = pm->cmd;
|
||
scale = PM_CmdScale( &cmd );
|
||
|
||
// set the movementDir so clients can rotate the legs for strafing
|
||
//PM_SetMovementDir();
|
||
|
||
// project moves down to flat plane
|
||
//pml.forward[2] = 0;
|
||
pml.forward.z = 0;
|
||
|
||
//pml.right[2] = 0;
|
||
pml.right.z = 0;
|
||
//std::cout << "Further down" << pm->ps.velocity << "\n";
|
||
|
||
|
||
// project the forward and right directions onto the ground plane
|
||
PM_ClipVelocity (pml.forward, pml.groundTrace.planenormal, pml.forward, OVERCLIP );
|
||
PM_ClipVelocity (pml.right, pml.groundTrace.planenormal, pml.right, OVERCLIP );
|
||
//std::cout << "Clip velocity" << pm->ps.velocity << "\n";
|
||
//
|
||
|
||
VectorNormalize (pml.forward);
|
||
VectorNormalize (pml.right);
|
||
//pml.forward = pml.forward.normalise();
|
||
//pml.right = pml.right.normalise();
|
||
//std::cout << "forward2" << pml.forward << "\n";
|
||
//std::cout << "right2" << pml.right << "\n";
|
||
|
||
|
||
// wishvel = (pml.forward * fmove) + (pml.right * smove);
|
||
//for ( i = 0 ; i < 3 ; i++ )
|
||
//wishvel[i] = pml.forward[i] * fmove + pml.right[i] * smove;
|
||
wishvel = pml.forward * fmove + pml.right * smove;
|
||
|
||
|
||
//bprintf("f: (%f, %f, %f), s: (%f, %f, %f)\n", fmove, smove);
|
||
|
||
|
||
// when going up or down slopes the wish velocity should Not be zero
|
||
// wishvel[2] = 0;
|
||
|
||
// wishdir = wishvel
|
||
//VectorCopy (wishvel, wishdir);
|
||
//wishvel = wishdir;
|
||
wishdir = wishvel;
|
||
|
||
wishspeed = VectorNormalize(wishdir);
|
||
//std::cout << "Wishspeed: " << wishspeed << "\n";
|
||
wishspeed *= scale;
|
||
//std::cout << "Wishspeed scaled:" << wishspeed << "\n";
|
||
|
||
// clamp the speed lower if ducking
|
||
if ( pm->cmd.ducking )
|
||
if ( wishspeed > pm->ps.speed * pm_duckScale )
|
||
wishspeed = pm->ps.speed * pm_duckScale;
|
||
|
||
// clamp the speed lower if wading or walking on the bottom
|
||
if ( pm->ps.waterlevel )
|
||
{
|
||
float waterScale;
|
||
|
||
waterScale = pm->ps.waterlevel / 3.0f;
|
||
waterScale = 1.0f - ( 1.0f - pm_swimScale ) * waterScale;
|
||
if ( wishspeed > pm->ps.speed * waterScale )
|
||
wishspeed = pm->ps.speed * waterScale;
|
||
}
|
||
|
||
// when a player gets hit, they temporarily lose
|
||
// full control, which allows them to be moved a bit
|
||
//if ( ( pml.groundTrace.surfaceFlags & SURF_SLICK ) || pm->ps->pm_flags & PMF_TIME_KNOCKBACK )
|
||
//accelerate = pm_airaccelerate;
|
||
//else
|
||
accelerate = pm_accelerate;
|
||
|
||
|
||
PM_Accelerate (wishdir, wishspeed, accelerate);
|
||
//std::cout << "Velocityafter: " << pm->ps.velocity << "\n";
|
||
|
||
//Com_Printf("velocity = %1.1f %1.1f %1.1f\n", pm->ps->velocity[0], pm->ps->velocity[1], pm->ps->velocity[2]);
|
||
//Com_Printf("velocity1 = %1.1f\n", VectorLength(pm->ps->velocity));
|
||
|
||
//if ( ( pml.groundTrace.surfaceFlags & SURF_SLICK ) || pm->ps->pm_flags & PMF_TIME_KNOCKBACK )
|
||
//pm->ps->velocity[2] -= pm->ps->gravity * pml.frametime;
|
||
//else
|
||
//{
|
||
// don't reset the z velocity for slopes
|
||
// pm->ps->velocity[2] = 0;
|
||
//}
|
||
|
||
//vel = VectorLength(pm->ps->velocity);
|
||
vel = pm->ps.velocity.length();
|
||
//std::cout << "The length" << vel << "\n";
|
||
|
||
// slide along the ground plane
|
||
PM_ClipVelocity (pm->ps.velocity, pml.groundTrace.planenormal,
|
||
pm->ps.velocity, OVERCLIP );
|
||
//std::cout << "Velocity clipped" << pm->ps.velocity << "\n";
|
||
|
||
// don't decrease velocity when going up or down a slope
|
||
VectorNormalize(pm->ps.velocity);
|
||
//pm->ps.velocity = pm->ps.velocity.normalise();
|
||
|
||
//std::cout << "Final:" << pm->ps.velocity << "\n";
|
||
//VectorScale(pm->ps->velocity, vel, pm->ps->velocity);
|
||
pm->ps.velocity = pm->ps.velocity * vel;
|
||
|
||
// don't do anything if standing still
|
||
//if (!pm->ps->velocity[0] && !pm->ps->velocity[1])
|
||
if (!pm->ps.velocity.x && !pm->ps.velocity.z)
|
||
return;
|
||
|
||
PM_StepSlideMove( false );
|
||
|
||
//Com_Printf("velocity2 = %1.1f\n", VectorLength(pm->ps->velocity));
|
||
|
||
|
||
}
|
||
|
||
void PM_UpdateViewAngles( playerMove::playerStruct* const ps, playerMove::playercmd* const cmd )
|
||
{
|
||
short temp;
|
||
int i;
|
||
|
||
//while(1);
|
||
|
||
//if ( ps->pm_type == PM_INTERMISSION || ps->pm_type == PM_SPINTERMISSION)
|
||
//return; // no view changes at all
|
||
|
||
//if ( ps->pm_type != PM_SPECTATOR && ps->stats[STAT_HEALTH] <= 0 )
|
||
//return; // no view changes at all
|
||
|
||
// circularly clamp the angles with deltas
|
||
//bprintf("View angles: %i, %i, %i\n", cmd->angles[0], cmd->angles[1], cmd->angles[2]);
|
||
for (i = 0 ; i < 3 ; i++)
|
||
{
|
||
temp = cmd->angles[i];// + ps->delta_angles[i];
|
||
//if ( i == PITCH )
|
||
{
|
||
// don't let the player look up or down more than 90 degrees
|
||
/*if ( temp > 16000 )
|
||
{
|
||
ps->delta_angles[i] = 16000 - cmd->angles[i];
|
||
temp = 16000;
|
||
}
|
||
else if ( temp < -16000 )
|
||
{
|
||
ps->delta_angles[i] = -16000 - cmd->angles[i];
|
||
temp = -16000;
|
||
}*/
|
||
}
|
||
(&(ps->viewangles.x) )[i] = SHORT2ANGLE(temp);
|
||
//cmd->angles[i] += ps->delta_angles[i];
|
||
}
|
||
//ps->delta_angles[0] = ps->delta_angles[1] = ps->delta_angles[2] = 0;
|
||
|
||
}
|
||
|
||
void AngleVectors( const Ogre::Vector3& angles, Ogre::Vector3* const forward, Ogre::Vector3* const right, Ogre::Vector3* const up)
|
||
{
|
||
float angle;
|
||
static float sr, sp, sy, cr, cp, cy;
|
||
// static to help MS compiler fp bugs
|
||
|
||
//angle = angles[YAW] * (M_PI*2 / 360);
|
||
angle = angles.x * (M_PI * 2.0f / 360.0f);
|
||
sp = sinf(angle);
|
||
cp = cosf(angle);
|
||
|
||
//angle = angles[PITCH] * (M_PI*2 / 360);
|
||
angle = angles.y * (-M_PI * 2.0f / 360.0f);
|
||
sy = sinf(angle);
|
||
cy = cosf(angle);
|
||
|
||
//angle = angles[ROLL] * (M_PI*2 / 360);
|
||
angle = angles.z * (M_PI * 2.0f / 360.0f);
|
||
sr = sinf(angle);
|
||
cr = cosf(angle);
|
||
|
||
if (forward)
|
||
{
|
||
forward->x = cp * cy;
|
||
forward->y = cp * sy;
|
||
forward->z = -sp;
|
||
}
|
||
if (right)
|
||
{
|
||
right->x = (-1 * sr * sp * cy + -1 * cr * -sy);
|
||
right->y = (-1 * sr * sp * sy + -1 * cr * cy);
|
||
right->z = 0;
|
||
}
|
||
if (up)
|
||
{
|
||
up->x =(cr * sp * cy + -sr * -sy);
|
||
up->y=(cr * sp * sy + -sr * cy);
|
||
up->z = cr * cp;
|
||
}
|
||
|
||
}
|
||
|
||
void PM_GroundTraceMissed()
|
||
{
|
||
traceResults trace;
|
||
Ogre::Vector3 point;
|
||
//We should not have significant upwards velocity when in the air, unless we jumped.
|
||
//This code protects against flying into the air when moving at high speeds.
|
||
//Z velocity is set to 50, instead of 0, to help move up certain steps.
|
||
|
||
//std::cout << "Ground trace missed\n";
|
||
// we just transitioned into freefall
|
||
//if ( pm->debugLevel )
|
||
//Com_Printf("%i:lift\n", c_pmove);
|
||
|
||
// if they aren't in a jumping animation and the ground is a ways away, force into it
|
||
// if we didn't do the trace, the player would be backflipping down staircases
|
||
//VectorCopy( pm->ps->origin, point );
|
||
point = pm->ps.origin;
|
||
//point[2] -= 64;
|
||
point.z -= 32;
|
||
|
||
//pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask);
|
||
//tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&point, D3DXVECTOR3(0.0f, -64.0f, 0.0f), 0, pml.traceObj);
|
||
newtrace(&trace, pm->ps.origin, point, pm->ps.halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine);
|
||
//It hit the ground below
|
||
if ( trace.fraction < 1.0 && pm->ps.origin.z > trace.endpos.z)
|
||
{
|
||
pm->ps.origin = trace.endpos;
|
||
pml.walking = true;
|
||
pml.groundPlane = true;
|
||
pm->ps.groundEntityNum = trace.entityNum;
|
||
|
||
}
|
||
else{
|
||
pm->ps.groundEntityNum = ENTITYNUM_NONE;
|
||
pml.groundPlane = false;
|
||
pml.walking = false;
|
||
pm->ps.bSnap = false;
|
||
}
|
||
|
||
|
||
}
|
||
|
||
static bool PM_CorrectAllSolid(traceResults* const trace)
|
||
{
|
||
int i, j, k;
|
||
Ogre::Vector3 point;
|
||
|
||
//if ( pm->debugLevel )
|
||
//Com_Printf("%i:allsolid\n", c_pmove);
|
||
//bprintf("allsolid\n");
|
||
|
||
// jitter around
|
||
for (i = -1; i <= 1; i++)
|
||
{
|
||
for (j = -1; j <= 1; j++)
|
||
{
|
||
for (k = -1; k <= 1; k++)
|
||
{
|
||
//VectorCopy(pm->ps->origin, point);
|
||
point = pm->ps.origin;
|
||
|
||
/*point[0] += (float) i;
|
||
point[1] += (float) j;
|
||
point[2] += (float) k;*/
|
||
point += Ogre::Vector3( (const float)i, (const float)j, (const float)k);
|
||
|
||
//pm->trace (trace, point, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask);
|
||
//tracefunc(trace, *(const D3DXVECTOR3* const)&point, *(const D3DXVECTOR3* const)&point, D3DXVECTOR3(0.0f, 0.0f, 0.0f), 0, pml.traceObj);
|
||
newtrace(trace, point, point, pm->ps.halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine);
|
||
|
||
if ( !trace->allsolid )
|
||
{
|
||
/*point[0] = pm->ps->origin[0];
|
||
point[1] = pm->ps->origin[1];
|
||
point[2] = pm->ps->origin[2] - 0.25;*/
|
||
point = pm->ps.origin;
|
||
point.z -= 0.25f;
|
||
|
||
//pm->trace (trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask);
|
||
//tracefunc(trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&point, D3DXVECTOR3(0.0f, -0.25f, 0.0f), 0, pml.traceObj);
|
||
newtrace(trace, pm->ps.origin, point, pm->ps.halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine);
|
||
pml.groundTrace = *trace;
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
//pm->ps->groundEntityNum = ENTITYNUM_NONE;
|
||
pm->ps.groundEntityNum = ENTITYNUM_NONE;
|
||
pml.groundPlane = false;
|
||
pml.walking = false;
|
||
|
||
return false;
|
||
}
|
||
|
||
static void PM_CrashLand( void )
|
||
{
|
||
float delta;
|
||
float dist ;
|
||
float vel, acc;
|
||
float t;
|
||
float a, b, c, den;
|
||
|
||
// decide which landing animation to use
|
||
/*if ( pm->ps->pm_flags & PMF_BACKWARDS_JUMP )
|
||
PM_ForceLegsAnim( LEGS_LANDB );
|
||
else
|
||
PM_ForceLegsAnim( LEGS_LAND );
|
||
|
||
pm->ps->legsTimer = TIMER_LAND;*/
|
||
|
||
// calculate the exact velocity on landing
|
||
//dist = pm->ps->origin[2] - pml.previous_origin[2];
|
||
|
||
dist = pm->ps.origin.z - pml.previous_origin.z;
|
||
|
||
//vel = pml.previous_velocity[2];
|
||
vel = pml.previous_velocity.z;
|
||
|
||
//acc = -pm->ps->gravity;
|
||
acc = -pm->ps.gravity;
|
||
|
||
a = acc / 2;
|
||
b = vel;
|
||
c = -dist;
|
||
|
||
den = b * b - 4 * a * c;
|
||
if ( den < 0 )
|
||
return;
|
||
|
||
t = (-b - sqrtf( den ) ) / ( 2 * a );
|
||
|
||
delta = vel + t * acc;
|
||
delta = delta * delta * 0.0001f;
|
||
|
||
// ducking while falling doubles damage
|
||
/*if ( pm->ps->pm_flags & PMF_DUCKED )
|
||
delta *= 2;*/
|
||
if (pm->cmd.upmove < -20)
|
||
delta *= 2;
|
||
|
||
// never take falling damage if completely underwater
|
||
if ( pm->ps.waterlevel == 3 )
|
||
return;
|
||
|
||
// reduce falling damage if there is standing water
|
||
if ( pm->ps.waterlevel == 2 )
|
||
delta *= 0.25;
|
||
if ( pm->ps.waterlevel == 1 )
|
||
delta *= 0.5;
|
||
|
||
if ( delta < 1 )
|
||
return;
|
||
/*
|
||
if (delta > 60)
|
||
printf("Far crashland: %f\n", delta);
|
||
else if (delta > 40)
|
||
printf("Medium crashland: %f\n", delta);
|
||
else if (delta > 4)
|
||
printf("Short crashland: %f\n", delta);
|
||
*/
|
||
if (delta > 60)
|
||
{
|
||
/*
|
||
static const namestruct healthDamage("Health Damage");
|
||
const SOUN* const soun = SOUN::GetSound(healthDamage);
|
||
if (soun)
|
||
{
|
||
PlaySound2D(soun->soundFilename, soun->soundData->GetVolumeFloat() );
|
||
}*/
|
||
}
|
||
|
||
if (delta > 3) // We need at least a short crashland to proc the sound effects:
|
||
{
|
||
bool splashSound = false;
|
||
|
||
if (pm->hasWater)
|
||
{
|
||
|
||
const float waterHeight = pm->waterHeight;
|
||
const float waterHeightSplash = waterHeight + pm->ps.halfExtents.y;
|
||
if (pm->ps.origin.z < waterHeightSplash)
|
||
{
|
||
splashSound = true;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
if (splashSound)
|
||
{
|
||
//Change this later-----------------------------------
|
||
/*
|
||
const namestruct ns("DefaultLandWater");
|
||
const SOUN* const soun = SOUN::GetSound(ns);
|
||
if (soun)
|
||
{
|
||
PlaySound2D(soun->soundFilename, soun->soundDatga->GetVolumeFloat() );
|
||
}*/
|
||
}
|
||
else
|
||
{
|
||
//Change this later---------------------------------
|
||
/*
|
||
namestruct defaultCreature;
|
||
const SNDG* const sndg = SNDG::GetFromMap(defaultCreature, SNDG::land);
|
||
if (sndg)
|
||
{
|
||
const namestruct& SOUNID = sndg->soundID;
|
||
const SOUN* const soun = SOUN::GetSound(SOUNID);
|
||
if (soun)
|
||
{
|
||
PlaySound2D(soun->soundFilename, soun->soundData->GetVolumeFloat() );
|
||
}
|
||
}*/
|
||
}
|
||
}
|
||
|
||
// create a local entity event to play the sound
|
||
|
||
// SURF_NODAMAGE is used for bounce pads where you don't ever
|
||
// want to take damage or play a crunch sound
|
||
//if ( !(pml.groundTrace.surfaceFlags & SURF_NODAMAGE) )
|
||
{
|
||
/*if ( delta > 60 )
|
||
PM_AddEvent( EV_FALL_FAR );
|
||
else if ( delta > 40 )
|
||
{
|
||
// this is a pain grunt, so don't play it if dead
|
||
if ( pm->ps->stats[STAT_HEALTH] > 0 )
|
||
PM_AddEvent( EV_FALL_MEDIUM );
|
||
}
|
||
else if ( delta > 7 )
|
||
PM_AddEvent( EV_FALL_SHORT );
|
||
else
|
||
PM_AddEvent( PM_FootstepForSurface() );*/
|
||
}
|
||
|
||
// start footstep cycle over
|
||
//pm->ps->bobCycle = 0;
|
||
}
|
||
|
||
static void PM_GroundTrace( void )
|
||
{
|
||
Ogre::Vector3 point;
|
||
traceResults trace;
|
||
|
||
/*point[0] = pm->ps->origin[0];
|
||
point[1] = pm->ps->origin[1];
|
||
point[2] = pm->ps->origin[2] - 0.25;*/
|
||
point = pm->ps.origin;
|
||
point.z -= 0.25f;
|
||
|
||
//pm->trace (&trace, pm->ps->origin, pm->mins, pm->maxs, point, pm->ps->clientNum, pm->tracemask);
|
||
//tracefunc(&trace, *(const D3DXVECTOR3* const)&(pm->ps.origin), *(const D3DXVECTOR3* const)&point, D3DXVECTOR3(0.0f, -0.25f, 0.0f), 0, pml.traceObj);
|
||
newtrace(&trace, pm->ps.origin, point, pm->ps.halfExtents, Ogre::Math::DegreesToRadians(pm->ps.viewangles.y), pm->isInterior, pm->mEngine);
|
||
pml.groundTrace = trace;
|
||
|
||
// do something corrective if the trace starts in a solid...
|
||
if ( trace.allsolid ) {
|
||
//std::cout << "ALL SOLID\n";
|
||
if ( !PM_CorrectAllSolid(&trace) ){
|
||
//std::cout << "Returning after correct all solid\n";
|
||
return;
|
||
}
|
||
}
|
||
// if the trace didn't hit anything, we are in free fall
|
||
if ( trace.fraction == 1.0)
|
||
{
|
||
if(pm->ps.velocity.z > 50.0f && pm->ps.bSnap && pm->ps.speed > 1000.0f)
|
||
pm->ps.velocity.z = 50.0f;
|
||
if(pm->ps.snappingImplemented){
|
||
if(pm->ps.bSnap && pm->ps.counter <= 0)
|
||
PM_GroundTraceMissed();
|
||
}
|
||
|
||
|
||
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
//It hit something, so we are on the ground
|
||
pm->ps.bSnap = true;
|
||
|
||
}
|
||
// check if getting thrown off the ground
|
||
//if ( pm->ps->velocity[2] > 0 && DotProduct( pm->ps->velocity, trace.plane.normal ) > 10 )
|
||
if (pm->ps.velocity.z > 0 && pm->ps.velocity.dotProduct(trace.planenormal) > 10.0f )
|
||
{
|
||
//if ( pm->debugLevel )
|
||
//Com_Printf("%i:kickoff\n", c_pmove);
|
||
|
||
// go into jump animation
|
||
/*if ( pm->cmd.forwardmove >= 0 )
|
||
{
|
||
PM_ForceLegsAnim( LEGS_JUMP );
|
||
pm->ps->pm_flags &= ~PMF_BACKWARDS_JUMP;
|
||
}
|
||
else
|
||
{
|
||
PM_ForceLegsAnim( LEGS_JUMPB );
|
||
pm->ps->pm_flags |= PMF_BACKWARDS_JUMP;
|
||
}*/
|
||
if(!pm->ps.bSnap){
|
||
pm->ps.groundEntityNum = ENTITYNUM_NONE;
|
||
pml.groundPlane = false;
|
||
pml.walking = false;
|
||
}
|
||
else
|
||
{
|
||
pml.groundPlane = true;
|
||
pml.walking = true;
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
|
||
// slopes that are too steep will not be considered onground
|
||
//if ( trace.plane.normal[2] < MIN_WALK_NORMAL )
|
||
//std::cout << "MinWalkNormal" << trace.planenormal.z;
|
||
if (trace.planenormal.z < MIN_WALK_NORMAL)
|
||
{
|
||
//if ( pm->debugLevel )
|
||
//Com_Printf("%i:steep\n", c_pmove);
|
||
|
||
// FIXME: if they can't slide down the slope, let them
|
||
// walk (sharp crevices)
|
||
pm->ps.groundEntityNum = ENTITYNUM_NONE;
|
||
pml.groundPlane = true;
|
||
pml.walking = false;
|
||
return;
|
||
}
|
||
|
||
pml.groundPlane = true;
|
||
pml.walking = true;
|
||
|
||
// hitting solid ground will end a waterjump
|
||
/*if (pm->ps.pm_flags & PMF_TIME_WATERJUMP)
|
||
{
|
||
pm->ps->pm_flags &= ~(PMF_TIME_WATERJUMP | PMF_TIME_LAND);
|
||
pm->ps->pm_time = 0;
|
||
}*/
|
||
|
||
if ( pm->ps.groundEntityNum == ENTITYNUM_NONE )
|
||
{
|
||
// just hit the ground
|
||
/*if ( pm->debugLevel )
|
||
Com_Printf("%i:Land\n", c_pmove);*/
|
||
//bprintf("Land\n");
|
||
|
||
PM_CrashLand();
|
||
|
||
// don't do landing time if we were just going down a slope
|
||
//if ( pml.previous_velocity[2] < -200 )
|
||
if (pml.previous_velocity.z < -200)
|
||
{
|
||
// don't allow another jump for a little while
|
||
//pm->ps->pm_flags |= PMF_TIME_LAND;
|
||
pm->ps.pm_time = 250;
|
||
}
|
||
}
|
||
|
||
pm->ps.groundEntityNum = trace.entityNum;
|
||
|
||
// don't reset the z velocity for slopes
|
||
// pm->ps->velocity[2] = 0;
|
||
|
||
//PM_AddTouchEnt( trace.entityNum );
|
||
}
|
||
|
||
void PM_AirMove()
|
||
{
|
||
//int i;
|
||
Ogre::Vector3 wishvel;
|
||
float fmove, smove;
|
||
Ogre::Vector3 wishdir;
|
||
float wishspeed;
|
||
float scale;
|
||
playerMove::playercmd cmd;
|
||
//pm->ps.gravity = 800;
|
||
PM_Friction();
|
||
|
||
fmove = pm->cmd.forwardmove;
|
||
smove = pm->cmd.rightmove;
|
||
|
||
cmd = pm->cmd;
|
||
scale = PM_CmdScale( &cmd );
|
||
// set the movementDir so clients can rotate the legs for strafing
|
||
//PM_SetMovementDir();
|
||
|
||
// project moves down to flat plane
|
||
//pml.forward[2] = 0;
|
||
pml.forward.z = 0; //Z or Y?
|
||
//pml.right[2] = 0;
|
||
pml.right.z = 0;
|
||
//VectorNormalize (pml.forward);
|
||
VectorNormalize(pml.forward);
|
||
VectorNormalize(pml.right);
|
||
//VectorNormalize (pml.right);
|
||
|
||
//for ( i = 0 ; i < 2 ; i++ )
|
||
//wishvel[i] = pml.forward[i] * fmove + pml.right[i] * smove;
|
||
wishvel = pml.forward * fmove + pml.right * smove;
|
||
|
||
//wishvel[2] = 0;
|
||
wishvel.z = 0;
|
||
|
||
//VectorCopy (wishvel, wishdir);
|
||
wishdir = wishvel;
|
||
//wishspeed = VectorNormalize(wishdir);
|
||
wishspeed = VectorNormalize(wishdir);
|
||
|
||
wishspeed *= scale;
|
||
|
||
// not on ground, so little effect on velocity
|
||
PM_Accelerate (wishdir, wishspeed, pm_airaccelerate);
|
||
|
||
// we may have a ground plane that is very steep, even
|
||
// though we don't have a groundentity
|
||
// slide along the steep plane
|
||
if ( pml.groundPlane )
|
||
PM_ClipVelocity (pm->ps.velocity, pml.groundTrace.planenormal, pm->ps.velocity, OVERCLIP );
|
||
|
||
/*#if 0
|
||
//ZOID: If we are on the grapple, try stair-stepping
|
||
//this allows a player to use the grapple to pull himself
|
||
//over a ledge
|
||
if (pm->ps->pm_flags & PMF_GRAPPLE_PULL)
|
||
PM_StepSlideMove ( qtrue );
|
||
else
|
||
PM_SlideMove ( qtrue );
|
||
#endif*/
|
||
//std::cout << "Moving in the air" << pm->ps.velocity << "\n";
|
||
|
||
/*bprintf("%i ", */PM_StepSlideMove ( true )/* )*/;
|
||
|
||
|
||
}
|
||
|
||
static void PM_NoclipMove( void )
|
||
{
|
||
float speed, drop, friction, control, newspeed;
|
||
// int i;
|
||
Ogre::Vector3 wishvel;
|
||
float fmove, smove;
|
||
Ogre::Vector3 wishdir;
|
||
float wishspeed;
|
||
float scale;
|
||
|
||
//pm->ps->viewheight = DEFAULT_VIEWHEIGHT;
|
||
|
||
// friction
|
||
|
||
//speed = VectorLength (pm->ps->velocity);
|
||
speed = pm->ps.velocity.length();
|
||
if (speed < 1)
|
||
//VectorCopy (vec3_origin, pm->ps->velocity);
|
||
pm->ps.velocity = Ogre::Vector3(0.0f, 0.0f, 0.0f);
|
||
else
|
||
{
|
||
drop = 0;
|
||
|
||
friction = pm_friction * 1.5f; // extra friction
|
||
control = speed < pm_stopspeed ? pm_stopspeed : speed;
|
||
drop += control * friction * pml.frametime;
|
||
|
||
// scale the velocity
|
||
newspeed = speed - drop;
|
||
if (newspeed < 0)
|
||
newspeed = 0;
|
||
newspeed /= speed;
|
||
|
||
//VectorScale (pm->ps->velocity, newspeed, pm->ps->velocity);
|
||
pm->ps.velocity = pm->ps.velocity * newspeed;
|
||
}
|
||
|
||
// accelerate
|
||
scale = PM_CmdScale( &pm->cmd );
|
||
|
||
fmove = pm->cmd.forwardmove;
|
||
smove = pm->cmd.rightmove;
|
||
|
||
//for (i=0 ; i<3 ; i++)
|
||
//wishvel[i] = pml.forward[i] * fmove + pml.right[i] * smove;
|
||
|
||
wishvel = pml.forward * fmove + pml.right * smove;
|
||
//wishvel[2] += pm->cmd.upmove;
|
||
wishvel.z += pm->cmd.upmove;
|
||
|
||
//VectorCopy (wishvel, wishdir);
|
||
wishdir = wishvel;
|
||
wishspeed = VectorNormalize(wishdir);
|
||
wishspeed *= scale;
|
||
|
||
|
||
PM_Accelerate( wishdir, wishspeed, pm_accelerate );
|
||
|
||
// move
|
||
//VectorMA (pm->ps->origin, pml.frametime, pm->ps->velocity, pm->ps->origin);
|
||
pm->ps.origin = pm->ps.origin + pm->ps.velocity * pml.frametime;
|
||
}
|
||
|
||
static void PM_DropTimers( void )
|
||
{
|
||
// drop misc timing counter
|
||
if ( pm->ps.pm_time )
|
||
{
|
||
if ( pml.msec >= pm->ps.pm_time )
|
||
{
|
||
//pm->ps->pm_flags &= ~PMF_ALL_TIMES;
|
||
pm->ps.pm_time = 0;
|
||
}
|
||
else
|
||
pm->ps.pm_time -= pml.msec;
|
||
}
|
||
|
||
//bprintf("Time: %i\n", pm->ps.pm_time);
|
||
|
||
// drop animation counter
|
||
/*if ( pm->ps->legsTimer > 0 )
|
||
{
|
||
pm->ps->legsTimer -= pml.msec;
|
||
if ( pm->ps->legsTimer < 0 )
|
||
pm->ps->legsTimer = 0;
|
||
}
|
||
|
||
if ( pm->ps->torsoTimer > 0 )
|
||
{
|
||
pm->ps->torsoTimer -= pml.msec;
|
||
if ( pm->ps->torsoTimer < 0 )
|
||
pm->ps->torsoTimer = 0;
|
||
}*/
|
||
}
|
||
|
||
static void PM_FlyMove( void )
|
||
{
|
||
//int i;
|
||
Ogre::Vector3 wishvel;
|
||
float wishspeed;
|
||
Ogre::Vector3 wishdir;
|
||
float scale;
|
||
|
||
// normal slowdown
|
||
PM_Friction ();
|
||
|
||
scale = PM_CmdScale( &pm->cmd );
|
||
//
|
||
// user intentions
|
||
//
|
||
if ( !scale )
|
||
{
|
||
/*wishvel[0] = 0;
|
||
wishvel[1] = 0;
|
||
wishvel[2] = 0;*/
|
||
wishvel = Ogre::Vector3(0,0,0);
|
||
}
|
||
else
|
||
{
|
||
//for (i=0 ; i<3 ; i++)
|
||
//wishvel[i] = scale * pml.forward[i]*pm->cmd.forwardmove + scale * pml.right[i]*pm->cmd.rightmove;
|
||
wishvel = pml.forward * scale * pm->cmd.forwardmove + pml.right * scale * pm->cmd.rightmove;
|
||
|
||
//wishvel[2] += scale * pm->cmd.upmove;
|
||
wishvel.z += /*6.35f * */pm->cmd.upmove * scale;
|
||
}
|
||
|
||
//VectorCopy (wishvel, wishdir);
|
||
wishdir = wishvel;
|
||
|
||
//wishspeed = VectorNormalize(wishdir);
|
||
wishspeed = VectorNormalize(wishdir);
|
||
|
||
PM_Accelerate (wishdir, wishspeed, pm_flyaccelerate);
|
||
|
||
PM_StepSlideMove( false );
|
||
}
|
||
|
||
|
||
void PM_SetWaterLevel( playerMove* const pm )
|
||
{
|
||
Ogre::Vector3 point;
|
||
//int cont;
|
||
int sample1;
|
||
int sample2;
|
||
|
||
//
|
||
// get waterlevel, accounting for ducking
|
||
//
|
||
|
||
pm->ps.waterlevel = WL_DRYLAND;
|
||
pm->ps.watertype = 0;
|
||
|
||
/*point[0] = pm->ps->origin[0];
|
||
point[1] = pm->ps->origin[1];
|
||
point[2] = pm->ps->origin[2] + MINS_Z + 1; */
|
||
point.x = pm->ps.origin.x;
|
||
point.y = pm->ps.origin.y;
|
||
point.z = pm->ps.origin.z + MINS_Z + 1;
|
||
|
||
//cont = pm->pointcontents( point, pm->ps->clientNum );
|
||
bool checkWater = (pml.hasWater && pml.waterHeight > point.z);
|
||
//if ( cont & MASK_WATER )
|
||
if ( checkWater)
|
||
{
|
||
sample2 = /*pm->ps.viewheight*/DEFAULT_VIEWHEIGHT - MINS_Z;
|
||
sample1 = sample2 / 2;
|
||
|
||
pm->ps.watertype = CONTENTS_WATER;//cont;
|
||
pm->ps.waterlevel = WL_ANKLE;
|
||
//point[2] = pm->ps->origin[2] + MINS_Z + sample1;
|
||
point.z = pm->ps.origin.z + MINS_Z + sample1;
|
||
checkWater = (pml.hasWater && pml.waterHeight > point.z);
|
||
//cont = pm->pointcontents (point, pm->ps->clientNum );
|
||
//if ( cont & MASK_WATER )
|
||
if (checkWater)
|
||
{
|
||
pm->ps.waterlevel = WL_WAIST;
|
||
//point[2] = pm->ps->origin[2] + MINS_Z + sample2;
|
||
point.z = pm->ps.origin.z + MINS_Z + sample2;
|
||
//cont = pm->pointcontents (point, pm->ps->clientNum );
|
||
//if ( cont & MASK_WATER )
|
||
checkWater = (pml.hasWater && pml.waterHeight > point.z);
|
||
if (checkWater )
|
||
pm->ps.waterlevel = WL_UNDERWATER;
|
||
}
|
||
}
|
||
}
|
||
|
||
void PmoveSingle (playerMove* const pmove)
|
||
{
|
||
pmove->ps.counter--;
|
||
//pm = pmove;
|
||
|
||
// Aedra doesn't support Q3-style VM traps D: //while(1);
|
||
|
||
// this counter lets us debug movement problems with a journal
|
||
// by setting a conditional breakpoint fot the previous frame
|
||
//c_pmove++;
|
||
|
||
// clear results
|
||
//pm->numtouch = 0;
|
||
pm->ps.watertype = 0;
|
||
pm->ps.waterlevel = WL_DRYLAND;
|
||
|
||
//if ( pm->ps->stats[STAT_HEALTH] <= 0 )
|
||
//pm->tracemask &= ~CONTENTS_BODY; // corpses can fly through bodies
|
||
|
||
|
||
// make sure walking button is clear if they are running, to avoid
|
||
// proxy no-footsteps cheats
|
||
//if ( abs( pm->cmd.forwardmove ) > 64 || abs( pm->cmd.rightmove ) > 64 )
|
||
//pm->cmd.buttons &= ~BUTTON_WALKING;
|
||
|
||
|
||
// set the talk balloon flag
|
||
//if ( pm->cmd.buttons & BUTTON_TALK )
|
||
//pm->ps->eFlags |= EF_TALK;
|
||
//else
|
||
//pm->ps->eFlags &= ~EF_TALK;
|
||
|
||
// set the firing flag for continuous beam weapons
|
||
/*if ( !(pm->ps->pm_flags & PMF_RESPAWNED) && pm->ps->pm_type != PM_INTERMISSION
|
||
&& ( pm->cmd.buttons & BUTTON_ATTACK ) && pm->ps->ammo[ pm->ps->weapon ] )
|
||
pm->ps->eFlags |= EF_FIRING;
|
||
else
|
||
pm->ps->eFlags &= ~EF_FIRING;*/
|
||
|
||
// clear the respawned flag if attack and use are cleared
|
||
/*if ( pm->ps->stats[STAT_HEALTH] > 0 &&
|
||
!( pm->cmd.buttons & (BUTTON_ATTACK | BUTTON_USE_HOLDABLE) ) )
|
||
pm->ps->pm_flags &= ~PMF_RESPAWNED;*/
|
||
|
||
// if talk button is down, dissallow all other input
|
||
// this is to prevent any possible intercept proxy from
|
||
// adding fake talk balloons
|
||
/*if ( pmove->cmd.buttons & BUTTON_TALK )
|
||
{
|
||
// keep the talk button set tho for when the cmd.serverTime > 66 msec
|
||
// and the same cmd is used multiple times in Pmove
|
||
pmove->cmd.buttons = BUTTON_TALK;
|
||
pmove->cmd.forwardmove = 0;
|
||
pmove->cmd.rightmove = 0;
|
||
pmove->cmd.upmove = 0;
|
||
}*/
|
||
|
||
// clear all pmove local vars
|
||
memset (&pml, 0, sizeof(pml) );
|
||
|
||
// Aedra-specific code:
|
||
//pml.scene = global_lastscene;
|
||
|
||
|
||
// End Aedra-specific code
|
||
pml.hasWater = pmove->hasWater;
|
||
pml.isInterior = pmove->isInterior;
|
||
pml.waterHeight = pmove->waterHeight;
|
||
|
||
// determine the time
|
||
pml.msec = pmove->cmd.serverTime - pm->ps.commandTime;
|
||
if ( pml.msec < 1 )
|
||
pml.msec = 1;
|
||
else if ( pml.msec > 200 )
|
||
pml.msec = 200;
|
||
|
||
//pm->ps->commandTime = pmove->cmd.serverTime;
|
||
|
||
// Commented out as a hack
|
||
pm->ps.commandTime = pmove->cmd.serverTime;
|
||
|
||
// Handle state change procs:
|
||
if (pm->cmd.activating != pm->cmd.lastActivatingState)
|
||
{
|
||
if (!pm->cmd.lastActivatingState && pm->cmd.activating)
|
||
pm->cmd.procActivating = playerMove::playercmd::KEYDOWN;
|
||
else
|
||
pm->cmd.procActivating = playerMove::playercmd::KEYUP;
|
||
}
|
||
else
|
||
{
|
||
pm->cmd.procActivating = playerMove::playercmd::NO_CHANGE;
|
||
}
|
||
pm->cmd.lastActivatingState = pm->cmd.activating;
|
||
|
||
if (pm->cmd.dropping != pm->cmd.lastDroppingState)
|
||
{
|
||
if (!pm->cmd.lastDroppingState && pm->cmd.dropping)
|
||
pm->cmd.procDropping = playerMove::playercmd::KEYDOWN;
|
||
else
|
||
pm->cmd.procDropping = playerMove::playercmd::KEYUP;
|
||
}
|
||
else
|
||
{
|
||
pm->cmd.procDropping = playerMove::playercmd::NO_CHANGE;
|
||
}
|
||
pm->cmd.lastDroppingState = pm->cmd.dropping;
|
||
|
||
// save old org in case we get stuck
|
||
//VectorCopy (pm->ps->origin, pml.previous_origin);
|
||
pml.previous_origin = pm->ps.origin;
|
||
|
||
// Copy over the lastframe origin
|
||
pmove->ps.lastframe_origin = pmove->ps.origin;
|
||
|
||
//pmove->ps.lastframe_origin = pmove->ps.origin;
|
||
|
||
// save old velocity for crashlanding
|
||
//VectorCopy (pm->ps->velocity, pml.previous_velocity);
|
||
pml.previous_velocity = pm->ps.velocity;
|
||
|
||
pml.frametime = pml.msec * 0.001f;
|
||
|
||
// update the viewangles
|
||
//PM_UpdateViewAngles( &(pm->ps), &(pm->cmd) );
|
||
|
||
AngleVectors (pm->ps.viewangles, &(pml.forward), &(pml.right), &(pml.up) );
|
||
|
||
//if ( pm->cmd.upmove < 10 )
|
||
// not holding jump
|
||
//pm->ps->pm_flags &= ~PMF_JUMP_HELD;
|
||
|
||
// decide if backpedaling animations should be used
|
||
/*if ( pm->cmd.forwardmove < 0 )
|
||
pm->ps->pm_flags |= PMF_BACKWARDS_RUN;
|
||
else if ( pm->cmd.forwardmove > 0 || ( pm->cmd.forwardmove == 0 && pm->cmd.rightmove ) )
|
||
pm->ps->pm_flags &= ~PMF_BACKWARDS_RUN;*/
|
||
|
||
/*if ( pm->ps->pm_type >= PM_DEAD )
|
||
{
|
||
pm->cmd.forwardmove = 0;
|
||
pm->cmd.rightmove = 0;
|
||
pm->cmd.upmove = 0;
|
||
}*/
|
||
|
||
if ( pm->ps.move_type == PM_SPECTATOR )
|
||
{
|
||
|
||
//PM_CheckDuck ();
|
||
PM_FlyMove ();
|
||
PM_DropTimers ();
|
||
return;
|
||
}
|
||
|
||
if ( pm->ps.move_type == PM_NOCLIP )
|
||
{
|
||
|
||
PM_NoclipMove ();
|
||
PM_DropTimers ();
|
||
return;
|
||
}
|
||
|
||
if (pm->ps.move_type == PM_FREEZE){
|
||
|
||
return; // no movement at all
|
||
|
||
}
|
||
|
||
if ( pm->ps.move_type == PM_INTERMISSION || pm->ps.move_type == PM_SPINTERMISSION){
|
||
return; // no movement at all
|
||
}
|
||
|
||
// set watertype, and waterlevel
|
||
PM_SetWaterLevel(pmove);
|
||
pml.previous_waterlevel = pmove->ps.waterlevel;
|
||
|
||
// set mins, maxs, and viewheight
|
||
//PM_CheckDuck ();
|
||
|
||
// set groundentity
|
||
PM_GroundTrace();
|
||
|
||
/*if ( pm->ps->pm_type == PM_DEAD )
|
||
PM_DeadMove ();
|
||
|
||
PM_DropTimers();*/
|
||
|
||
PM_DropTimers();
|
||
|
||
/*#ifdef MISSIONPACK
|
||
if ( pm->ps->powerups[PW_INVULNERABILITY] ) {
|
||
PM_InvulnerabilityMove();
|
||
} else
|
||
#endif*/
|
||
/*if ( pm->ps->powerups[PW_FLIGHT] )
|
||
// flight powerup doesn't allow jump and has different friction
|
||
PM_FlyMove();
|
||
else if (pm->ps->pm_flags & PMF_GRAPPLE_PULL)
|
||
{
|
||
PM_GrappleMove();
|
||
// We can wiggle a bit
|
||
PM_AirMove();
|
||
}
|
||
else if (pm->ps->pm_flags & PMF_TIME_WATERJUMP)
|
||
PM_WaterJumpMove();*/
|
||
if ( pmove->ps.waterlevel > 1 )
|
||
// swimming
|
||
PM_WaterMove(pmove);
|
||
else if ( pml.walking )
|
||
{
|
||
|
||
// walking on ground
|
||
PM_WalkMove(pmove);
|
||
//bprintf("WalkMove\n");
|
||
}
|
||
else
|
||
{
|
||
// airborne
|
||
//std::cout << "AIRMOVE\n";
|
||
PM_AirMove();
|
||
//bprintf("AirMove\n");
|
||
}
|
||
|
||
//PM_Animate();
|
||
|
||
// set groundentity, watertype, and waterlevel
|
||
PM_GroundTrace();
|
||
PM_SetWaterLevel(pmove);
|
||
|
||
// weapons
|
||
/*PM_Weapon();
|
||
|
||
// torso animation
|
||
PM_TorsoAnimation();
|
||
|
||
// footstep events / legs animations
|
||
PM_Footsteps();
|
||
|
||
// entering / leaving water splashes
|
||
PM_WaterEvents();
|
||
|
||
// snap some parts of playerstate to save network bandwidth
|
||
trap_SnapVector( pm->ps->velocity );*/
|
||
}
|
||
|
||
void Ext_UpdateViewAngles(playerMove* const pm)
|
||
{
|
||
playerMove::playerStruct* const ps = &(pm->ps);
|
||
playerMove::playercmd* const cmd = &(pm->cmd);
|
||
PM_UpdateViewAngles(ps, cmd);
|
||
}
|
||
|
||
void Pmove (playerMove* const pmove)
|
||
{
|
||
// warning: unused variable ‘fmove’
|
||
//int fmove = pmove->cmd.forwardmove;
|
||
|
||
pm = pmove;
|
||
|
||
int finalTime;
|
||
|
||
finalTime = pmove->cmd.serverTime;
|
||
|
||
pmove->ps.commandTime = 40;
|
||
|
||
if ( finalTime < pmove->ps.commandTime )
|
||
return; // should not happen
|
||
|
||
if ( finalTime > pmove->ps.commandTime + 1000 )
|
||
pmove->ps.commandTime = finalTime - 1000;
|
||
|
||
pmove->ps.pmove_framecount = (pmove->ps.pmove_framecount + 1) & ( (1 << PS_PMOVEFRAMECOUNTBITS) - 1);
|
||
|
||
// chop the move up if it is too long, to prevent framerate
|
||
// dependent behavior
|
||
while ( pmove->ps.commandTime != finalTime )
|
||
{
|
||
int msec;
|
||
|
||
msec = finalTime - pmove->ps.commandTime;
|
||
|
||
if ( pmove->pmove_fixed )
|
||
{
|
||
if ( msec > pmove->pmove_msec )
|
||
msec = pmove->pmove_msec;
|
||
}
|
||
else
|
||
{
|
||
if ( msec > 66 )
|
||
msec = 66;
|
||
}
|
||
|
||
pmove->cmd.serverTime = pmove->ps.commandTime + msec;
|
||
|
||
if (pmove->isInterior)
|
||
{
|
||
PmoveSingle( pmove );
|
||
}
|
||
else
|
||
{
|
||
PmoveSingle( pmove );
|
||
/*
|
||
std::map<CellCoords, CELL* const>::const_iterator it = ExtCellLookup.find(PositionToCell(pmove->ps.origin) );
|
||
if (it != ExtCellLookup.end() )
|
||
{
|
||
pmove->traceObj->incellptr = it->second;
|
||
}*/
|
||
}
|
||
|
||
//if ( pmove->ps->pm_flags & PMF_JUMP_HELD )
|
||
//pmove->cmd.upmove = 20;
|
||
}
|
||
|
||
//pmove->ps.last_compute_time = GetTimeQPC();
|
||
//pmove->ps.lerp_multiplier = (pmove->ps.origin - pmove->ps.lastframe_origin);// * (1.000 / 31.0);
|
||
|
||
//PM_CheckStuck();
|
||
|
||
}
|
||
|
||
|