diff --git a/cms_qf/cm_model.c b/cms_qf/cm_model.c index bcf5bb86..81276248 100644 --- a/cms_qf/cm_model.c +++ b/cms_qf/cm_model.c @@ -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 ); } } diff --git a/cms_xr/cm_model.c b/cms_xr/cm_model.c index 0bd63b08..61fa2cc0 100644 --- a/cms_xr/cm_model.c +++ b/cms_xr/cm_model.c @@ -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 ); } } diff --git a/common/entity_def.h b/common/entity_def.h index b52a308d..67334133 100644 --- a/common/entity_def.h +++ b/common/entity_def.h @@ -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) diff --git a/engine/client/cl_cmds.c b/engine/client/cl_cmds.c index 6ee4b51e..e2536b36 100644 --- a/engine/client/cl_cmds.c +++ b/engine/client/cl_cmds.c @@ -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] ); } \ No newline at end of file diff --git a/engine/server/server.h b/engine/server/server.h index b308fabc..df68bac3 100644 --- a/engine/server/server.h +++ b/engine/server/server.h @@ -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 ) diff --git a/engine/server/sv_client.c b/engine/server/sv_client.c index 6aea0b0b..d78aa1a1 100644 --- a/engine/server/sv_client.c +++ b/engine/server/sv_client.c @@ -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 diff --git a/engine/server/sv_frame.c b/engine/server/sv_frame.c index f8a6bea5..5216fc65 100644 --- a/engine/server/sv_frame.c +++ b/engine/server/sv_frame.c @@ -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; } diff --git a/engine/server/sv_game.c b/engine/server/sv_game.c index b72e583b..5339d434 100644 --- a/engine/server/sv_game.c +++ b/engine/server/sv_game.c @@ -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; } } diff --git a/engine/server/sv_move.c b/engine/server/sv_move.c index 1fa5808e..3fcace05 100644 --- a/engine/server/sv_move.c +++ b/engine/server/sv_move.c @@ -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; } diff --git a/engine/server/sv_phys.c b/engine/server/sv_phys.c index 3f4f283d..28290940 100644 --- a/engine/server/sv_phys.c +++ b/engine/server/sv_phys.c @@ -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 ); } diff --git a/pm_shared/pm_shared.cpp b/pm_shared/pm_shared.cpp index c7476d49..46e088ff 100644 --- a/pm_shared/pm_shared.cpp +++ b/pm_shared/pm_shared.cpp @@ -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 ) diff --git a/server/ents/baseinfo.cpp b/server/ents/baseinfo.cpp index 2e2cc78e..685669a1 100644 --- a/server/ents/baseinfo.cpp +++ b/server/ents/baseinfo.cpp @@ -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 ); diff --git a/server/ents/baseinfo.h b/server/ents/baseinfo.h index 583baa47..94aeb863 100644 --- a/server/ents/baseinfo.h +++ b/server/ents/baseinfo.h @@ -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; } }; diff --git a/server/ents/baseitem.cpp b/server/ents/baseitem.cpp index 1ed7d992..63869f8a 100644 --- a/server/ents/baseitem.cpp +++ b/server/ents/baseitem.cpp @@ -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 ); } diff --git a/server/ents/baserockets.cpp b/server/ents/baserockets.cpp index d84edca3..2f514d53 100644 --- a/server/ents/baserockets.cpp +++ b/server/ents/baserockets.cpp @@ -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; diff --git a/server/ents/basetrigger.cpp b/server/ents/basetrigger.cpp index dda855ec..744e48b4 100644 --- a/server/ents/basetrigger.cpp +++ b/server/ents/basetrigger.cpp @@ -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 ); } } } diff --git a/server/ents/baseweapon.cpp b/server/ents/baseweapon.cpp index 23e71af0..62a33bfb 100644 --- a/server/ents/baseweapon.cpp +++ b/server/ents/baseweapon.cpp @@ -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 diff --git a/server/global/client.cpp b/server/global/client.cpp index 9d1776ad..f9d4581a 100644 --- a/server/global/client.cpp +++ b/server/global/client.cpp @@ -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 ) diff --git a/server/monsters/player.cpp b/server/monsters/player.cpp index 8b688bd1..89797284 100644 --- a/server/monsters/player.cpp +++ b/server/monsters/player.cpp @@ -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? diff --git a/todo.log b/todo.log index 9986c5d3..30208b66 100644 --- a/todo.log +++ b/todo.log @@ -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 \ No newline at end of file +163. rewrote sv_phys.c +164. remove vprogs.dll OK +165. fix bsplib error + + \ No newline at end of file