02 Dec 2009

This commit is contained in:
g-cont 2009-12-02 00:00:00 +03:00 committed by Alibek Omarov
parent 5139a05ba0
commit 4db3ea9d03
20 changed files with 577 additions and 249 deletions

View File

@ -883,8 +883,8 @@ void CM_ModelBounds( model_t handle, vec3_t mins, vec3_t maxs )
else
{
MsgDev( D_ERROR, "Mod_GetBounds: NULL model %i\n", handle );
if( mins ) VectorSet( mins, -32, -32, -32 );
if( maxs ) VectorSet( maxs, 32, 32, 32 );
if( mins ) VectorClear( mins );
if( maxs ) VectorClear( maxs );
}
}

View File

@ -1180,8 +1180,8 @@ void CM_ModelBounds( model_t handle, vec3_t mins, vec3_t maxs )
else
{
MsgDev( D_ERROR, "Mod_GetBounds: NULL model %i\n", handle );
if( mins ) VectorSet( mins, -32, -32, -32 );
if( maxs ) VectorSet( maxs, 32, 32, 32 );
if( mins ) VectorClear( mins );
if( maxs ) VectorClear( maxs );
}
}

View File

@ -24,6 +24,7 @@ typedef struct entvars_s
vec3_t oldorigin; // ENG [all], NET [all]
vec3_t velocity;
vec3_t basevelocity;
vec3_t clbasevelocity; // ENG [player], NET [player]
vec3_t movedir;
@ -141,6 +142,7 @@ typedef struct entvars_s
int flSwimTime; // In process of ducking or ducked already?
int flDuckTime; // Time we started duck
int iStepLeft; // 0 - 4
float flJumpPadTime; // for scale falling damage
float flFallVelocity; // falling velocity z
int oldbuttons; // buttons last usercmd
int groupinfo; // entities culling (on server)

View File

@ -291,5 +291,6 @@ viewpos
*/
void SCR_Viewpos_f( void )
{
Msg( "( %g %g %g )\n", cl.refdef.vieworg[0], cl.refdef.vieworg[1], cl.refdef.vieworg[2] );
Msg( "org ( %g %g %g )\n", cl.refdef.vieworg[0], cl.refdef.vieworg[1], cl.refdef.vieworg[2] );
Msg( "ang ( %g %g %g )\n", cl.refdef.viewangles[0], cl.refdef.viewangles[1], cl.refdef.viewangles[2] );
}

View File

@ -149,7 +149,6 @@ struct sv_priv_s
bool linked; // passed through SV_LinkEdict
bool stuck; // entity stucked in brush
bool suspended; // suspended on a brush entity
// cached position to avoid redundant SV_CheckWaterTransition calls on monsters
bool forceupdate; // force an update on this entity
@ -403,6 +402,8 @@ const char *SV_GetString( string_t iString );
void SV_SetClientMaxspeed( sv_client_t *cl, float fNewMaxspeed );
bool SV_MapIsValid( const char *filename, const char *spawn_entity );
void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float attn, int flags, int pitch );
void SV_UpdateBaseVelocity( edict_t *ent );
bool SV_IsValidEdict( const edict_t *e );
script_t *CM_GetEntityScript( void );
_inline edict_t *SV_EDICT_NUM( int n, const char * file, const int line )

View File

@ -596,6 +596,16 @@ void SV_PutClientInServer( edict_t *ent )
}
else
{
// needs to setup angles on restore
if( ent->v.fixangle )
{
MSG_WriteByte( &sv.multicast, svc_setangle );
MSG_WriteAngle32( &sv.multicast, ent->v.angles[0] );
MSG_WriteAngle32( &sv.multicast, ent->v.angles[1] );
MSG_WriteAngle32( &sv.multicast, 0 );
MSG_DirectSend( MSG_ONE, vec3_origin, client->edict );
ent->v.fixangle = false;
}
}
client->pViewEntity = NULL; // reset pViewEntity

View File

@ -46,7 +46,7 @@ Copy entvars into entity state
*/
void SV_UpdateEntityState( const edict_t *ent, bool baseline )
{
sv_client_t *client = ent->pvServerData->client;
sv_client_t *client = SV_ClientFromEdict( ent, true );
if( !ent->pvServerData->s.classname )
ent->pvServerData->s.classname = SV_ClassIndex( STRING( ent->v.classname ));
@ -61,12 +61,14 @@ void SV_UpdateEntityState( const edict_t *ent, bool baseline )
MSG_WriteAngle32( &sv.multicast, ent->v.angles[0] );
MSG_WriteAngle32( &sv.multicast, ent->v.angles[1] );
MSG_WriteAngle32( &sv.multicast, 0 );
MSG_Send( MSG_ONE, vec3_origin, client->edict );
MSG_DirectSend( MSG_ONE, vec3_origin, client->edict );
}
}
svgame.dllFuncs.pfnUpdateEntityState( &ent->pvServerData->s, (edict_t *)ent, baseline );
if( client ) client->edict->v.fixangle = false;
// always keep an actual
ent->pvServerData->s.number = ent->serialnumber;
}

View File

@ -1452,7 +1452,6 @@ int pfnDropToFloor( edict_t* e )
SV_LinkEdict( e, true );
e->v.flags |= FL_ONGROUND;
e->v.groundentity = trace.pHit;
e->pvServerData->suspended = true;
return true;
}
@ -1469,7 +1468,6 @@ int pfnDropToFloor( edict_t* e )
SV_LinkEdict( e, true );
e->v.flags |= FL_ONGROUND;
e->v.groundentity = trace.pHit;
e->pvServerData->suspended = true;
return true;
}
}

View File

@ -465,6 +465,45 @@ int PM_PointContents( const vec3_t p )
return World_ConvertContents( SV_BaseContents( p, svgame.pmove->player ));
}
void PM_CheckMovingGround( edict_t *ent, float frametime )
{
SV_UpdateBaseVelocity( ent );
if(!( ent->v.flags & FL_BASEVELOCITY ))
{
// apply momentum (add in half of the previous frame of velocity first)
VectorMA( ent->v.velocity, 1.0f + (frametime * 0.5f), ent->v.basevelocity, ent->v.velocity );
VectorClear( ent->v.basevelocity );
}
ent->v.flags &= ~FL_BASEVELOCITY;
}
void PM_SetupMove( playermove_t *pmove, edict_t *clent, usercmd_t *ucmd, const char *physinfo )
{
pmove->realtime = svgame.globals->time;
pmove->frametime = ucmd->msec * 0.001f;
com.strncpy( pmove->physinfo, physinfo, MAX_INFO_STRING );
pmove->clientmaxspeed = clent->v.maxspeed;
pmove->cmd = *ucmd; // setup current cmds
pmove->player = clent; // ptr to client state
pmove->numtouch = 0; // reset touchents
pmove->dead = (clent->v.health <= 0.0f) ? true : false;
pmove->flWaterJumpTime = clent->v.teleport_time;
pmove->onground = clent->v.groundentity;
pmove->usehull = (clent->v.flags & FL_DUCKING) ? 1 : 0; // reset hull
pmove->bInDuck = clent->v.bInDuck;
VectorCopy( clent->v.origin, pmove->origin );
}
void PM_FinishMove( playermove_t *pmove, edict_t *clent )
{
clent->v.teleport_time = pmove->flWaterJumpTime;
clent->v.groundentity = pmove->onground;
VectorCopy( pmove->angles, clent->v.viewangles );
VectorCopy( pmove->origin, clent->v.origin );
clent->v.bInDuck = pmove->bInDuck;
}
/*
===============
SV_InitClientMove
@ -559,6 +598,8 @@ void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd )
return;
}
PM_CheckMovingGround( clent, ucmd->msec * 0.001f );
VectorCopy( clent->v.viewangles, svgame.pmove->oldangles ); // save oldangles
if( !clent->v.fixangle )
VectorCopy( ucmd->viewangles, clent->v.viewangles );
@ -586,38 +627,25 @@ void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd )
svgame.globals->frametime = ucmd->msec * 0.001f;
SV_RunThink( clent );
// If conveyor, or think, set basevelocity, then send to client asap too.
if( VectorLength( clent->v.basevelocity ) > 0.0f )
VectorCopy( clent->v.basevelocity, clent->v.clbasevelocity );
}
// setup playermove state
// setup playermove globals
svgame.pmove->multiplayer = (sv_maxclients->integer > 1) ? true : false;
svgame.pmove->realtime = svs.realtime * 0.001f;
svgame.pmove->frametime = ucmd->msec * 0.001f;
com.strncpy( svgame.pmove->physinfo, cl->physinfo, MAX_INFO_STRING );
svgame.pmove->serverflags = svgame.globals->serverflags;
svgame.pmove->clientmaxspeed = clent->v.maxspeed;
svgame.pmove->serverflags = svgame.globals->serverflags; // shared serverflags
svgame.pmove->maxspeed = svgame.movevars.maxspeed;
svgame.pmove->cmd = *ucmd; // setup current cmds
svgame.pmove->player = clent; // ptr to client state
svgame.pmove->numtouch = 0; // reset touchents
svgame.pmove->dead = (clent->v.health <= 0.0f) ? true : false;
svgame.pmove->flWaterJumpTime = clent->v.teleport_time;
svgame.pmove->onground = clent->v.groundentity;
svgame.pmove->usehull = (clent->v.flags & FL_DUCKING) ? 1 : 0; // reset hull
svgame.pmove->bInDuck = clent->v.bInDuck;
for( i = 0; i < 3; i++ )
svgame.pmove->origin[i] = clent->v.origin[i];
// setup playermove state
PM_SetupMove( svgame.pmove, clent, ucmd, cl->physinfo );
// motor!
svgame.dllFuncs.pfnPM_Move( svgame.pmove, true );
// copy results back to client
clent->v.teleport_time = svgame.pmove->flWaterJumpTime;
clent->v.groundentity = svgame.pmove->onground;
VectorCopy( svgame.pmove->angles, clent->v.viewangles );
clent->v.bInDuck = svgame.pmove->bInDuck;
for( i = 0; i < 3; i++ )
clent->v.origin[i] = svgame.pmove->origin[i];
PM_FinishMove( svgame.pmove, clent );
VectorCopy( clent->v.velocity, oldvel ); // save velocity
if(!( clent->v.flags & FL_SPECTATOR ))
@ -625,17 +653,25 @@ void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd )
// link into place and touch triggers
SV_LinkEdict( clent, true );
// NOTE: one of triggers apply new velocity to client
// e.g trigger_teleport resets it or add new
// so we need to apply new velocity immediately here
if( clent->v.fixangle || clent->v.flJumpPadTime )
VectorCopy( clent->v.velocity, oldvel );
// touch other objects
for( i = 0; i < svgame.pmove->numtouch; i++ )
{
if( i == MAX_PHYSENTS ) break;
if( svgame.pmove->touchents[i] == clent ) continue;
VectorCopy( svgame.pmove->touchvels[i], clent->v.velocity );
svgame.dllFuncs.pfnTouch( svgame.pmove->touchents[i], clent );
}
}
VectorCopy( oldvel, clent->v.velocity ); // save velocity
// restore velocity
VectorCopy( oldvel, clent->v.velocity );
svgame.pmove->numtouch = 0;
}

View File

@ -26,7 +26,7 @@ solid_edge items only clip against bsp models.
*/
#define DIST_EPSILON (0.03125) // 1/32 epsilon to keep floating point happy
#define MOVE_EPSILON 0.01
#define MAX_CLIP_PLANES 32
#define MAX_CLIP_PLANES 5
/*
===============================================================================
@ -73,7 +73,7 @@ void SV_CheckAllEnts( void )
for( i = svgame.globals->maxClients + 1; i < svgame.globals->numEntities; i++ )
{
e = EDICT_NUM( i );
if( e->free ) continue;
if( !SV_IsValidEdict( e )) continue;
switch( e->v.movetype )
{
@ -84,8 +84,9 @@ void SV_CheckAllEnts( void )
continue;
default: break;
}
SV_UnstickEntity( e );
if( e->pvServerData->stuck )
SV_UnstickEntity( e );
}
}
@ -120,6 +121,35 @@ void SV_CheckVelocity( edict_t *ent )
VectorScale( ent->v.velocity, maxvel / VectorLength( ent->v.velocity ), ent->v.velocity );
}
/*
================
SV_UpdateBaseVelocity
================
*/
void SV_UpdateBaseVelocity( edict_t *ent )
{
if( ent->v.flags & FL_ONGROUND )
{
edict_t *groundentity = ent->v.groundentity;
if( SV_IsValidEdict( groundentity ))
{
// On conveyor belt that's moving?
if( groundentity->v.flags & FL_CONVEYOR )
{
vec3_t new_basevel;
VectorScale( groundentity->v.movedir, groundentity->v.speed, new_basevel );
if( ent->v.flags & FL_BASEVELOCITY )
VectorAdd( new_basevel, ent->v.basevelocity, new_basevel );
ent->v.flags |= FL_BASEVELOCITY;
VectorCopy( new_basevel, ent->v.basevelocity );
}
}
}
}
/*
=============
SV_RunThink
@ -260,6 +290,72 @@ void SV_TransformedBBox( edict_t *ent, vec3_t mins, vec3_t maxs )
}
}
/*
=============
SV_AngularMove
may use friction for smooth stopping
=============
*/
void SV_AngularMove( edict_t *ent, float frametime, float friction )
{
int i;
float adjustment;
VectorMA( ent->v.angles, frametime, ent->v.avelocity, ent->v.angles );
if( friction == 0.0f ) return;
adjustment = frametime * (sv_stopspeed->value / 10) * sv_friction->value * fabs( friction );
for( i = 0; i < 3; i++ )
{
if( ent->v.avelocity[i] > 0.0f )
{
ent->v.avelocity[i] -= adjustment;
if( ent->v.avelocity[i] < 0.0f )
ent->v.avelocity[i] = 0.0f;
}
else
{
ent->v.avelocity[i] += adjustment;
if( ent->v.avelocity[i] > 0.0f )
ent->v.avelocity[i] = 0.0f;
}
}
}
/*
=============
SV_LinearMove
use friction for smooth stopping
=============
*/
void SV_LinearMove( edict_t *ent, float frametime, float friction )
{
int i;
float adjustment;
VectorMA( ent->v.origin, frametime, ent->v.velocity, ent->v.origin );
if( friction == 0.0f ) return;
adjustment = frametime * (sv_stopspeed->value / 10) * sv_friction->value * fabs( friction );
for( i = 0; i < 3; i++ )
{
if( ent->v.velocity[i] > 0.0f )
{
ent->v.velocity[i] -= adjustment;
if( ent->v.velocity[i] < 0.0f )
ent->v.velocity[i] = 0.0f;
}
else
{
ent->v.velocity[i] += adjustment;
if( ent->v.velocity[i] > 0.0f )
ent->v.velocity[i] = 0.0f;
}
}
}
/*
=============
SV_CheckWater
@ -486,23 +582,22 @@ Returns the clipflags if the velocity was modified (hit something solid)
if stepnormal is not NULL, the plane normal of any vertical wall hit will be stored
============
*/
int SV_FlyMove( edict_t *ent, float time, vec3_t vecStepNormal )
int SV_FlyMove( edict_t *ent, float time, trace_t *steptrace )
{
int blocked = 0, bumpcount;
int i, j, impact, numplanes;
int i, j, numplanes, bumpcount, blocked;
vec3_t dir, end, planes[MAX_CLIP_PLANES];
vec3_t primal_velocity, original_velocity, new_velocity;
float d, time_left;
trace_t trace;
if( time <= 0.0f ) return 0;
blocked = 0;
VectorCopy( ent->v.velocity, original_velocity );
VectorCopy( ent->v.velocity, primal_velocity );
numplanes = 0;
time_left = time;
for( bumpcount = 0; bumpcount < MAX_CLIP_PLANES - 1; bumpcount++ )
for( bumpcount = 0; bumpcount < MAX_CLIP_PLANES; bumpcount++ )
{
if( VectorIsNull( ent->v.velocity ))
break;
@ -510,69 +605,60 @@ int SV_FlyMove( edict_t *ent, float time, vec3_t vecStepNormal )
VectorMA( ent->v.origin, time_left, ent->v.velocity, end );
trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, end, MOVE_NORMAL, ent );
// break if it moved the entire distance
if( trace.flFraction == 1.0f )
{
VectorCopy( trace.vecEndPos, ent->v.origin );
break;
if( trace.fAllSolid )
{
// entity is trapped in another solid
VectorClear( ent->v.velocity );
return 3;
}
if( !trace.pHit )
{
MsgDev( D_ERROR, "SV_FlyMove: trace.pHit == NULL\n" );
trace.pHit = EDICT_NUM( 0 );
}
impact = !(ent->v.flags & FL_ONGROUND) || ent->v.groundentity != trace.pHit;
if( trace.vecPlaneNormal[2] )
{
if( trace.vecPlaneNormal[2] > 0.7f )
{
// floor
blocked |= 1;
ent->v.flags |= FL_ONGROUND;
ent->v.groundentity = trace.pHit;
}
}
else
{
// step
blocked |= 2;
if( vecStepNormal )
{
// save the trace normal for player extrafriction
VectorCopy( trace.vecPlaneNormal, vecStepNormal );
}
}
if( trace.flFraction >= 0.001f )
{
if( trace.flFraction > 0.0f )
{
// actually covered some distance
VectorCopy( trace.vecEndPos, ent->v.origin );
VectorCopy( ent->v.velocity, original_velocity );
numplanes = 0;
}
// run the impact function
if( impact )
{
SV_Impact( ent, &trace );
if( trace.flFraction == 1.0f )
break; // moved the entire distance
// break if removed by the impact function
if( ent->free ) break;
if( !trace.pHit )
{
MsgDev( D_ERROR, "SV_FlyMove: trace.pHit == NULL\n" );
trace.pHit = EDICT_NUM( 0 ); // world
}
time_left *= 1 - trace.flFraction;
if( trace.vecPlaneNormal[2] > 0.7f )
{
blocked |= 1; // floor
if( trace.pHit->v.solid == SOLID_BSP )
{
ent->v.flags |= FL_ONGROUND;
ent->v.groundentity = trace.pHit;
}
}
if( trace.vecPlaneNormal[2] == 0.0f )
{
blocked |= 2; // step
if( steptrace ) *steptrace = trace; // save for player extrafriction
}
// run the impact function
SV_Impact( ent, &trace );
// break if removed by the impact function
if( ent->free ) break;
time_left -= time_left - trace.flFraction;
// clipped to another plane
if( numplanes >= MAX_CLIP_PLANES )
{
// this shouldn't really happen
VectorClear( ent->v.velocity );
blocked = 3;
break;
return 3;
}
VectorCopy( trace.vecPlaneNormal, planes[numplanes] );
@ -586,9 +672,8 @@ int SV_FlyMove( edict_t *ent, float time, vec3_t vecStepNormal )
{
if( j != i )
{
// not ok
if( DotProduct( new_velocity, planes[j] ) < 0.0f )
break;
break; // not ok
}
}
if( j == numplanes ) break;
@ -605,12 +690,10 @@ int SV_FlyMove( edict_t *ent, float time, vec3_t vecStepNormal )
if( numplanes != 2 )
{
VectorClear( ent->v.velocity );
blocked = 7;
break;
return 7;
}
CrossProduct( planes[0], planes[1], dir );
VectorNormalize( dir );
d = DotProduct( dir, ent->v.velocity );
VectorScale( dir, d, ent->v.velocity );
}
@ -620,7 +703,7 @@ int SV_FlyMove( edict_t *ent, float time, vec3_t vecStepNormal )
if( DotProduct( ent->v.velocity, primal_velocity ) <= 0.0f )
{
VectorClear( ent->v.velocity );
break;
return blocked;
}
}
@ -676,7 +759,7 @@ static bool SV_PushEntity( trace_t *trace, edict_t *ent, vec3_t push, bool failO
type = MOVE_NOMONSTERS; // only clip against bmodels
else type = MOVE_NORMAL;
*trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, end, type, ent );
*trace = SV_Move( ent->v.origin, ent->v.mins, ent->v.maxs, end, type|FTRACE_SIMPLEBOX, ent );
if( trace->fStartStuck && failOnStartStuck )
return true;
@ -756,8 +839,13 @@ void SV_PushMove( edict_t *pusher, float movetime )
pushltime = pusher->v.ltime;
// move the pusher to its final position
#if 1
SV_LinearMove( pusher, movetime, pusher->v.friction );
SV_AngularMove( pusher, movetime, pusher->v.friction );
#else
VectorMA( pusher->v.origin, movetime, pusher->v.velocity, pusher->v.origin );
VectorMA( pusher->v.angles, movetime, pusher->v.avelocity, pusher->v.angles );
#endif
pusher->v.ltime += movetime;
SV_LinkEdict( pusher, false );
savesolid = pusher->v.solid;
@ -1077,12 +1165,12 @@ void SV_CheckWaterTransition( edict_t *ent )
/*
=============
SV_Physics_Toss
SV_Physics_Bounce
Toss, bounce, and fly movement. When onground, do nothing.
=============
*/
void SV_Physics_Toss( edict_t *ent )
void SV_Physics_Bounce( edict_t *ent )
{
trace_t trace;
vec3_t move;
@ -1090,14 +1178,6 @@ void SV_Physics_Toss( edict_t *ent )
int bump;
// check for in water
SV_CheckWaterTransition( ent );
// check for conveyor
if( ent->v.groundentity && ent->v.groundentity->v.flags & FL_CONVEYOR )
VectorScale( ent->v.groundentity->v.movedir, ent->v.groundentity->v.speed, ent->v.basevelocity );
else VectorClear( ent->v.basevelocity );
SV_CheckVelocity( ent );
SV_CheckWater( ent );
// regular thinking
@ -1111,22 +1191,9 @@ void SV_Physics_Toss( edict_t *ent )
// don't stick to ground if onground and moving upward
ent->v.flags &= ~FL_ONGROUND;
}
else if( ent->v.groundentity == EDICT_NUM( 0 ))
{
// we can trust FL_ONGROUND if groundentity is world because it never moves
return;
}
else if( ent->pvServerData->suspended && ( ent->v.groundentity == NULL || ent->v.groundentity->free ))
{
// if ent was supported by a brush model on previous frame,
// and groundentity is now freed, set groundentity to 0 (world)
// which leaves it suspended in the air
ent->v.groundentity = EDICT_NUM( 0 );
return;
}
else return;
}
ent->pvServerData->suspended = false;
SV_CheckVelocity( ent );
// add gravity
@ -1188,29 +1255,15 @@ void SV_Physics_Toss( edict_t *ent )
ent_gravity = ent->v.gravity;
else ent_gravity = 1.0;
if( 1 )
d = fabs( DotProduct( trace.vecPlaneNormal, ent->v.velocity ));
if( trace.vecPlaneNormal[2] > 0.7f && d < sv_gravity->value * bouncestop * ent_gravity )
{
d = fabs( DotProduct( trace.vecPlaneNormal, ent->v.velocity ));
if( trace.vecPlaneNormal[2] > 0.7f && d < sv_gravity->value * bouncestop * ent_gravity )
{
ent->v.flags |= FL_ONGROUND;
ent->v.groundentity = trace.pHit;
VectorClear( ent->v.velocity );
VectorClear( ent->v.avelocity );
}
else ent->v.flags &= ~FL_ONGROUND;
}
else
{
if( trace.vecPlaneNormal[2] > 0.7f && ent->v.velocity[2] < sv_gravity->value * bouncestop * ent_gravity )
{
ent->v.flags |= FL_ONGROUND;
ent->v.groundentity = trace.pHit;
VectorClear( ent->v.velocity );
VectorClear( ent->v.avelocity );
}
else ent->v.flags &= ~FL_ONGROUND;
ent->v.flags |= FL_ONGROUND;
ent->v.groundentity = trace.pHit;
VectorClear( ent->v.velocity );
VectorClear( ent->v.avelocity );
}
else ent->v.flags &= ~FL_ONGROUND;
}
else
{
@ -1219,9 +1272,6 @@ void SV_Physics_Toss( edict_t *ent )
{
ent->v.flags |= FL_ONGROUND;
ent->v.groundentity = trace.pHit;
if( trace.pHit->v.solid == SOLID_BSP )
ent->pvServerData->suspended = true;
VectorClear( ent->v.velocity );
VectorClear( ent->v.avelocity );
}
@ -1235,6 +1285,151 @@ void SV_Physics_Toss( edict_t *ent )
SV_CheckWaterTransition( ent );
}
/*
=============
SV_Physics_Toss
Toss, bounce, and fly movement. When onground, do nothing.
=============
*/
void SV_Physics_Toss( edict_t *ent )
{
trace_t trace;
vec3_t move;
float backoff;
SV_CheckWaterTransition( ent );
SV_CheckWater( ent );
// regular thinking
if( !SV_RunThink( ent )) return;
// if onground, return without moving
if( ent->v.flags & FL_ONGROUND )
return;
if( ent->v.velocity[2] > DIST_EPSILON )
{
ent->v.flags &= ~FL_ONGROUND;
ent->v.groundentity = NULL;
}
// If on ground and not moving, return.
if( SV_IsValidEdict( ent->v.groundentity ))
{
if( VectorIsNull( ent->v.basevelocity ) && VectorIsNull( ent->v.velocity ))
return;
}
SV_CheckVelocity( ent );
// add gravity
switch( ent->v.movetype )
{
case MOVETYPE_FLY:
case MOVETYPE_BOUNCEMISSILE:
case MOVETYPE_FLYMISSILE:
break;
default:
SV_AddGravity( ent );
break;
}
// move angles (with friction)
switch( ent->v.movetype )
{
case MOVETYPE_TOSS:
case MOVETYPE_BOUNCE:
SV_AngularMove( ent, svgame.globals->frametime, ent->v.friction );
break;
default:
SV_AngularMove( ent, svgame.globals->frametime, 0.0f );
break;
}
// move origin
// Base velocity is not properly accounted for since this entity will move again
// after the bounce without taking it into account
VectorAdd( ent->v.velocity, ent->v.basevelocity, ent->v.velocity );
SV_CheckVelocity( ent );
VectorScale( ent->v.velocity, svgame.globals->frametime, move );
VectorSubtract( ent->v.velocity, ent->v.basevelocity, ent->v.velocity );
if( !SV_PushEntity( &trace, ent, move, false, true ))
return; // teleported
if( ent->free ) return;
if( trace.fStartStuck )
{
// try to unstick the entity
SV_UnstickEntity( ent );
if( !SV_PushEntity( &trace, ent, move, false, true ))
return; // teleported
if( ent->free ) return;
}
SV_CheckVelocity( ent );
if( trace.fAllSolid )
{
// entity is trapped in another solid
ent->v.flags |= FL_ONGROUND;
ent->v.groundentity = trace.pHit;
ent->pvServerData->stuck = true;
VectorClear( ent->v.velocity );
return;
}
if( trace.flFraction == 1.0f )
{
SV_CheckWaterTransition( ent );
return;
}
if( ent->v.movetype == MOVETYPE_BOUNCE )
backoff = 2.0f - ent->v.friction;
else if( ent->v.movetype == MOVETYPE_BOUNCEMISSILE )
backoff = 2.0f;
else backoff = 1.0f;
SV_ClipVelocity( ent->v.velocity, trace.vecPlaneNormal, ent->v.velocity, backoff );
// stop if on ground
if( trace.vecPlaneNormal[2] > 0.7f )
{
float vel;
if( ent->v.velocity[2] < sv_gravity->value * svgame.globals->frametime )
{
// we're rolling on the ground, add static friction.
ent->v.groundentity = trace.pHit;
ent->v.velocity[2] = 0.0f;
ent->v.flags |= FL_ONGROUND;
}
vel = DotProduct( ent->v.velocity, ent->v.velocity );
if( vel < 900 || ( ent->v.movetype != MOVETYPE_BOUNCE && ent->v.movetype != MOVETYPE_BOUNCEMISSILE ))
{
ent->v.flags |= FL_ONGROUND;
ent->v.groundentity = trace.pHit;
VectorClear( ent->v.velocity );
VectorClear( ent->v.avelocity );
}
else
{
VectorScale( ent->v.velocity, (1.0f - trace.flFraction) * svgame.globals->frametime * 0.9f, move );
if( !SV_PushEntity( &trace, ent, move, false, true ))
return; // teleported
if( ent->free ) return;
}
}
// check for in water
SV_CheckWater( ent );
}
/*
===============================================================================
@ -1280,63 +1475,93 @@ will fall if the floor is pulled out from under them.
*/
void SV_Physics_Step( edict_t *ent )
{
int flags = ent->v.flags;
bool wasonground;
bool inwater;
float *vel;
float speed, newspeed, control;
float friction;
// check for conveyor
if( ent->v.groundentity && ent->v.groundentity->v.flags & FL_CONVEYOR )
VectorScale( ent->v.groundentity->v.movedir, ent->v.groundentity->v.speed, ent->v.basevelocity );
else VectorClear( ent->v.basevelocity );
SV_CheckVelocity( ent );
wasonground = ent->v.flags & FL_ONGROUND;
if( !VectorIsNull( ent->v.avelocity ))
SV_AddRotationalFriction( ent );
// don't fall at all if fly/swim
if( !( flags & ( FL_FLY|FL_SWIM )))
// add gravity except:
// flying monsters
// swimming monsters who are in the water
inwater = SV_CheckWater( ent );
if( !wasonground )
{
if( flags & FL_ONGROUND )
if( !( ent->v.flags & FL_FLY ))
{
// freefall if onground and moving upward
// freefall if not standing on a world surface (it may be a lift or trap door)
if( ent->v.velocity[2] >= DIST_EPSILON || ent->v.groundentity )
{
ent->v.flags &= ~FL_ONGROUND;
SV_CheckVelocity( ent );
SV_FlyMove( ent, svgame.globals->frametime, NULL );
SV_LinkEdict( ent, true );
ent->pvServerData->forceupdate = true;
}
if(!( ent->v.flags & FL_SWIM && ent->v.waterlevel > 0 ))
if( !inwater ) SV_AddGravity( ent );
}
else
}
if( !VectorIsNull( ent->v.velocity ) || !VectorIsNull( ent->v.basevelocity ))
{
vec3_t mins, maxs, point;
int x, y;
ent->v.flags &= ~FL_ONGROUND;
// apply friction
// let dead monsters who aren't completely onground slide
if( wasonground )
{
// freefall if not onground
int hitsound = ent->v.velocity[2] < sv_gravity->value * -0.1f;
SV_CheckVelocity( ent );
SV_FlyMove( ent, svgame.globals->frametime, NULL );
SV_LinkEdict( ent, true );
// just hit ground
if( hitsound && ent->v.flags & FL_ONGROUND )
if( !( ent->v.health <= 0.0f && !SV_CheckBottom( ent, WALKMOVE_NORMAL )))
{
// debug
Msg( "landing\n" );
vel = ent->v.velocity;
speed = com.sqrt( vel[0] * vel[0] + vel[1] * vel[1] );
if( speed )
{
friction = sv_friction->value;
control = speed < sv_stopspeed->value ? sv_stopspeed->value : speed;
newspeed = speed - svgame.globals->frametime * control * friction;
if( newspeed < 0 ) newspeed = 0;
newspeed /= speed;
vel[0] = vel[0] * newspeed;
vel[1] = vel[1] * newspeed;
}
}
ent->pvServerData->forceupdate = true;
}
VectorAdd( ent->v.velocity, ent->v.basevelocity, ent->v.velocity );
SV_FlyMove( ent, svgame.globals->frametime, NULL );
VectorSubtract (ent->v.velocity, ent->v.basevelocity, ent->v.velocity);
// determine if it's on solid ground at all
VectorAdd( ent->v.origin, ent->v.mins, mins );
VectorAdd( ent->v.origin, ent->v.maxs, maxs );
point[2] = mins[2] - 1;
for( x = 0; x <= 1; x++ )
{
for( y = 0; y <= 1; y++ )
{
point[0] = x ? maxs[0] : mins[0];
point[1] = y ? maxs[1] : mins[1];
if( SV_PointContents( point ) == CONTENTS_SOLID )
{
ent->v.flags |= FL_ONGROUND;
break;
}
}
}
SV_LinkEdict( ent, true );
}
// regular thinking
if( !SV_RunThink( ent ))
return;
if( ent->pvServerData->forceupdate || !VectorCompare( ent->v.origin, ent->pvServerData->water_origin ))
{
ent->pvServerData->forceupdate = false;
VectorCopy( ent->v.origin, ent->pvServerData->water_origin );
SV_CheckWaterTransition( ent );
}
SV_RunThink ( ent );
SV_CheckWaterTransition( ent );
}
/*
@ -1442,6 +1667,16 @@ void SV_Physics_None( edict_t *ent )
static void SV_Physics_Entity( edict_t *ent )
{
SV_UpdateBaseVelocity( ent );
if(!( ent->v.flags & FL_BASEVELOCITY ) && !VectorIsNull( ent->v.basevelocity ))
{
// Apply momentum (add in half of the previous frame of velocity first)
VectorMA( ent->v.velocity, 1.0f + (svgame.globals->frametime * 0.5f), ent->v.basevelocity, ent->v.velocity );
VectorClear( ent->v.basevelocity );
}
ent->v.flags &= ~FL_BASEVELOCITY;
switch( ent->v.movetype )
{
case MOVETYPE_PUSH:
@ -1460,22 +1695,6 @@ static void SV_Physics_Entity( edict_t *ent )
case MOVETYPE_PUSHSTEP:
SV_Physics_Step( ent );
break;
case MOVETYPE_WALK:
if( SV_RunThink( ent ))
{
sv_client_t *cl = SV_ClientFromEdict( ent, true );
if( cl && ent->v.flags & FL_FAKECLIENT )
{
SV_PreRunCmd( cl, &cl->lastcmd );
SV_RunCmd( cl, &cl->lastcmd );
SV_PostRunCmd( cl );
break;
}
Host_Error( "SV_Physics: bad movetype %i\n", ent->v.movetype );
break;
}
break;
case MOVETYPE_FLY:
case MOVETYPE_TOSS:
case MOVETYPE_BOUNCE:
@ -1486,6 +1705,9 @@ static void SV_Physics_Entity( edict_t *ent )
case MOVETYPE_CONVEYOR:
SV_Physics_Conveyor( ent );
break;
case MOVETYPE_WALK:
Host_Error( "SV_Physics: bad movetype %i\n", ent->v.movetype );
break;
default:
svgame.dllFuncs.pfnPhysicsEntity( ent );
break;
@ -1500,8 +1722,8 @@ SV_Physics
*/
void SV_Physics( void )
{
int i;
edict_t *ent;
int i;
// let the progs know that a new frame has started
svgame.globals->time = sv.time * 0.001f;
@ -1520,19 +1742,11 @@ void SV_Physics( void )
}
// treat each object in turn
for( i = i = svgame.globals->maxClients + 1; !sv_playersonly->integer && i < svgame.globals->numEntities; i++ )
for( i = svgame.globals->maxClients + 1; !sv_playersonly->integer && i < svgame.globals->numEntities; i++ )
{
ent = EDICT_NUM( i );
if( ent->free ) continue;
if(!( ent->v.flags & FL_BASEVELOCITY ) && !VectorIsNull( ent->v.basevelocity ))
{
// Apply momentum (add in half of the previous frame of velocity first)
VectorMA( ent->v.velocity, 1.0f + (svgame.globals->frametime * 0.5f), ent->v.basevelocity, ent->v.velocity );
VectorClear( ent->v.basevelocity );
}
ent->v.flags &= ~FL_BASEVELOCITY;
SV_Physics_Entity( ent );
}

View File

@ -2461,6 +2461,13 @@ void PM_CheckFalling( void )
{
float fvol = 0.5;
if( pev->flJumpPadTime && pev->flJumpPadTime < pmove->realtime )
{
// scale delta if was pushed by jump pad
float delta = (1.0f + pmove->realtime - pev->flJumpPadTime) * 0.5f;
pev->flFallVelocity /= delta;
}
if( pev->waterlevel > 0 )
{
// does nothing
@ -2469,8 +2476,7 @@ void PM_CheckFalling( void )
{
// NOTE: In the original game dll, there were no breaks after these cases, causing the first one to
// cascade into the second
#if 0
switch ( RandomLong(0,1) )
switch ( RANDOM_LONG( 0, 1 ))
{
case 0:
EmitSound( CHAN_VOICE, "player/pl_fallpain2.wav", 1, ATTN_NORM, PITCH_NORM );
@ -2479,7 +2485,6 @@ void PM_CheckFalling( void )
EmitSound( CHAN_VOICE, "player/pl_fallpain3.wav", 1, ATTN_NORM, PITCH_NORM );
break;
}
#endif
fvol = 1.0f;
}
else if( pev->flFallVelocity > PLAYER_MAX_SAFE_FALL_SPEED / 2.0f )

View File

@ -350,8 +350,9 @@ LINK_ENTITY_TO_CLASS( target_location, CPointEntity );
LINK_ENTITY_TO_CLASS( info_teleport_destination, CPointEntity );
LINK_ENTITY_TO_CLASS( misc_teleporter_dest, CPointEntity );
LINK_ENTITY_TO_CLASS( misc_portal_surface, CPortalSurface );
LINK_ENTITY_TO_CLASS( info_null, CNullEntity);
LINK_ENTITY_TO_CLASS( misc_model, CNullEntity);
LINK_ENTITY_TO_CLASS( info_notnull, CPointEntity );
LINK_ENTITY_TO_CLASS( info_null, CNullEntity );
LINK_ENTITY_TO_CLASS( misc_model, CNullEntity );
LINK_ENTITY_TO_CLASS( info_texlights, CNullEntity);
LINK_ENTITY_TO_CLASS( info_compile_parameters, CNullEntity);
LINK_ENTITY_TO_CLASS( info_intermission, CInfoIntermission );

View File

@ -8,7 +8,7 @@
class CPointEntity : public CBaseEntity
{
public:
void Spawn( void ){ pev->solid = SOLID_NOT; }
void Spawn( void ){ SetBits( pev->flags, FL_POINTENTITY ); pev->solid = SOLID_NOT; }
virtual int ObjectCaps( void ) { return CBaseEntity :: ObjectCaps() & ~FCAP_ACROSS_TRANSITION; }
};

View File

@ -26,15 +26,14 @@ void CItem::Spawn( void )
pev->movetype = MOVETYPE_TOSS;
pev->solid = SOLID_BBOX;
SetObjectClass( ED_NORMAL );
UTIL_SetModel( ENT( pev ), pev->model, Model() );
UTIL_SetOrigin( this, pev->origin );
UTIL_SetSize( pev, g_vecZero, g_vecZero );
UTIL_SetSize(pev, g_vecZero, g_vecZero );
SetObjectClass( ED_NORMAL );
SetTouch( ItemTouch );
SetThink( ItemFall );
UTIL_SetModel(ENT(pev), pev->model, Model() );
SetNextThink( 0.1 );
}

View File

@ -146,10 +146,9 @@ void CGrenade::BounceTouch( CBaseEntity *pOther )
m_fRegisteredSound = TRUE;
}
if (pev->flags & FL_ONGROUND)
if ( pev->flags & FL_ONGROUND )
{
// add a bit of static friction
Msg( "On ground()\n" );
pev->velocity = pev->velocity * 0.8;
pev->sequence = 1;
}
@ -159,8 +158,8 @@ void CGrenade::BounceTouch( CBaseEntity *pOther )
BounceSound();
}
pev->framerate = pev->velocity.Length() / 200.0;
if (pev->framerate > 1.0) pev->framerate = 1;
else if (pev->framerate < 0.5) pev->framerate = 0;
if( pev->framerate > 1.0 ) pev->framerate = 1;
else if( pev->framerate < 0.5 ) pev->framerate = 0;
}
@ -231,8 +230,7 @@ void CGrenade:: Spawn( void )
pev->solid = SOLID_BBOX;
SetObjectClass( ED_NORMAL );
UTIL_SetModel( ENT( pev ), "models/grenade.mdl");
UTIL_SetSize(pev, Vector( 0, 0, 0), Vector(0, 0, 0));
UTIL_SetModel( ENT( pev ), "models/props/hgrenade.mdl");
pev->dmg = 100;
m_fRegisteredSound = FALSE;
@ -261,7 +259,8 @@ CGrenade *CGrenade::ShootContact( entvars_t *pevOwner, Vector vecStart, Vector v
// Explode on contact
pGrenade->SetTouch( ExplodeTouch );
UTIL_SetModel( ENT( pGrenade->pev ), "models/props/grenade.mdl");
UTIL_SetModel( ENT( pGrenade->pev ), "models/weapons/w_grenade.mdl");
UTIL_SetSize( pGrenade->pev, Vector( 0, 0, 0 ), Vector( 0, 0, 0 ));
pGrenade->pev->dmg = M203_DMG;
return pGrenade;
@ -299,13 +298,14 @@ CGrenade * CGrenade:: ShootTimed( entvars_t *pevOwner, Vector vecStart, Vector v
pGrenade->pev->flags |= FL_PROJECTILE;
// Tumble through the air
// pGrenade->pev->avelocity.x = -400;
pGrenade->pev->avelocity.x = -400;
pGrenade->pev->gravity = 0.5;
pGrenade->pev->friction = 0.8;
pGrenade->pev->scale = 0.5; // original Valve model is too big :)
UTIL_SetModel( ENT( pGrenade->pev ), "models/props/hgrenade.mdl" );
UTIL_SetSize( pGrenade->pev, Vector( 0, 0, 0 ), Vector( 0, 0, 0 ));
pGrenade->pev->dmg = 100;
return pGrenade;
@ -712,6 +712,7 @@ void CWHRocket :: Spawn( void )
SetTouch( NukeTouch );
UTIL_MakeVectors( pev->angles );
pev->angles.x = -(pev->angles.x);
pev->velocity = gpGlobals->v_forward * pev->speed;
m_Center = pev->angles;

View File

@ -274,6 +274,8 @@ class CChangeFriction : public CBaseTrigger
};
LINK_ENTITY_TO_CLASS( func_friction, CChangeFriction );
#define SF_PUSH_ONCE 1
//=======================================================================
// trigger_push - triger that pushes player
//=======================================================================
@ -281,11 +283,13 @@ class CTriggerPush : public CBaseTrigger
{
void Spawn( void )
{
if( pev->angles == g_vecZero ) pev->angles.y = 360;
if( pev->angles == g_vecZero )
pev->angles.y = 360;
if( pev->speed == 0 ) pev->speed = 100;
UTIL_LinearVector( this );
if ( FBitSet (pev->spawnflags, 2) ) pev->solid = SOLID_NOT;
if ( FBitSet( pev->spawnflags, 2 ))
pev->solid = SOLID_NOT;
else pev->solid = SOLID_TRIGGER;
pev->movetype = MOVETYPE_NONE;
@ -304,11 +308,13 @@ class CTriggerPush : public CBaseTrigger
pOwner = UTIL_FindEntityByTargetname( NULL, STRING( pev->target ));
if( !pOwner ) return; // dir set with angles
if( FClassnameIs( pOwner->pev, "target_position" ))
if( pOwner->pev->flags & FL_POINTENTITY )
{
// xash allows to precache from random place
UTIL_PrecacheSound( "world/jumppad.wav" );
pev->owner = pOwner->edict();
pev->movedir = pOwner->pev->origin - ((pev->absmin + pev->absmax) * 0.5f);
pev->movedir.Normalize();
pev->button = TRUE; // Q3A trigger_push
}
}
void Use( CBaseEntity *pActivator, CBaseEntity *pCaller, USE_TYPE useType, float value )
@ -331,11 +337,53 @@ class CTriggerPush : public CBaseTrigger
case MOVETYPE_FOLLOW:
return;
}
if( pOther->pev->solid != SOLID_NOT && pOther->pev->solid != SOLID_BSP )
if( pev->button )
{
if( m_flWait >= gpGlobals->time ) return;
if( !pOther->IsPlayer() || pOther->pev->movetype != MOVETYPE_WALK )
return;
float time, dist, f;
Vector origin, velocity;
origin = (pev->absmin + pev->absmax) * 0.5f;
CBaseEntity *pTarg = CBaseEntity::Instance( pev->owner );
// assume pev->owner is valid
time = sqrt (( pTarg->pev->origin.z - origin.z ) / (0.5f * CVAR_GET_FLOAT( "sv_gravity" )));
if( !time )
{
UTIL_Remove( this );
return;
}
velocity = pTarg->pev->origin - origin;
velocity.z = 0.0f;
dist = velocity.Length();
velocity = velocity.Normalize();
f = dist / time;
velocity *= f;
velocity.z = time * CVAR_GET_FLOAT( "sv_gravity" );
pOther->pev->flJumpPadTime = gpGlobals->time;
pOther->pev->basevelocity = velocity;
pOther->pev->velocity = g_vecZero;
pOther->pev->flags &= ~FL_BASEVELOCITY;
EMIT_SOUND( ENT( pev ), CHAN_VOICE, "world/jumppad.wav", VOL_NORM, ATTN_IDLE );
m_flWait = gpGlobals->time + (2.0f * gpGlobals->frametime);
if( FBitSet( pev->spawnflags, SF_PUSH_ONCE ))
UTIL_Remove( this );
}
else if( pOther->pev->solid != SOLID_NOT && pOther->pev->solid != SOLID_BSP )
{
// instant trigger, just transfer velocity and remove
if( FBitSet( pev->spawnflags, 1 ))
if( FBitSet( pev->spawnflags, SF_PUSH_ONCE ))
{
pOther->pev->velocity = pOther->pev->velocity + (pev->speed * pev->movedir);
if( pOther->pev->velocity.z > 0 ) pOther->pev->flags &= ~FL_ONGROUND;
@ -348,6 +396,7 @@ class CTriggerPush : public CBaseTrigger
vecPush = vecPush + pOther->pev->basevelocity;
pOther->pev->basevelocity = vecPush;
pOther->pev->flags |= FL_BASEVELOCITY;
ALERT( at_console, "Valve trigger_push: vel %g %g %g\n", vecPush.x, vecPush.y, vecPush.z );
}
}
}

View File

@ -284,18 +284,17 @@ void CBasePlayerWeapon :: Spawn( void )
pev->movetype = MOVETYPE_TOSS;
pev->solid = SOLID_BBOX;
pev->sequence = 1; // set world animation
SetObjectClass( ED_NORMAL );
UTIL_SetModel( ENT( pev ), iWorldModel( ));
UTIL_SetOrigin( this, pev->origin );
// pointsize until it lands on the ground.
UTIL_SetSize( pev, Vector( 0, 0, 0 ), Vector( 0, 0, 0 ));
UTIL_SetModel( ENT( pev ), iWorldModel( ));
SetObjectClass( ED_NORMAL );
SetTouch( DefaultTouch );
SetThink( FallThink );
// pointsize until it lands on the ground.
UTIL_SetSize( pev, Vector( 0, 0, 0 ), Vector( 0, 0, 0 ));
m_iSpot = 0;
pev->animtime = gpGlobals->time + 0.1;
b_restored = TRUE; // already restored

View File

@ -1146,7 +1146,6 @@ void UpdateEntityState( entity_state_t *to, edict_t *from, int baseline )
if( pNet->pev->fixangle )
{
to->ed_flags |= ESF_NO_PREDICTION;
pNet->pev->fixangle = 0;
}
if( pNet->pev->teleport_time )

View File

@ -2497,6 +2497,14 @@ void CBasePlayer::PostThink()
{
// ALERT ( at_console, "%f\n", m_flFallVelocity );
if( pev->flJumpPadTime && pev->flJumpPadTime < gpGlobals->time )
{
// scale delta if was pushed by jump pad
float delta = (1.0f + gpGlobals->time - pev->flJumpPadTime) * 0.5f;
m_flFallVelocity /= delta;
pev->flJumpPadTime = 0.0f;
}
if (pev->watertype == CONTENTS_WATER)
{
// Did he hit the world or a non-moving entity?

View File

@ -155,7 +155,7 @@ Beta 13.12.09
128. fixup sprites lerping OK
129. fixup sound orientation OK
130. don't show console on changelevel OK
131. fixup teleports and trigger push's
131. fixup teleports and trigger push's OK
132. prepare configs and gameinfo
133. new sound\render system version replacement OK
134. dx sound engine complete OK
@ -187,5 +187,8 @@ Beta 13.12.09
160. pfnGetPlayerStats OK
161. fix basevelocity OK
162. rewrote auto-classify OK
163. rewrote sv_phys.c OK
164. remove vprogs.dll OK
163. rewrote sv_phys.c
164. remove vprogs.dll OK
165. fix bsplib error