void SV_Physics_Toss (prvm_edict_t *ent);
+int SV_GetPitchSign(prvm_edict_t *ent)
+{
+ dp_model_t *model;
+ int modelindex;
+ if (
+ ((modelindex = (int)ent->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS && (model = sv.models[modelindex]))
+ ?
+ model->type == mod_alias
+ :
+ (
+ (((unsigned char)PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.pflags)->_float) & PFLAGS_FULLDYNAMIC)
+ ||
+ ((gamemode == GAME_TENEBRAE) && ((unsigned int)ent->fields.server->effects & (16 | 32)))
+ )
+ )
+ return -1;
+ return 1;
+}
+
/*
===============================================================================
// if the modelindex is 0, it shouldn't be SOLID_BSP!
if (modelindex > 0 && modelindex < MAX_MODELS)
model = sv.models[(int)touch->fields.server->modelindex];
- //pitchsign = 1;
- if (
- ((modelindex = (int)touch->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS && (model = sv.models[(int)touch->fields.server->modelindex]))
- ?
- model->type == mod_alias
- :
- (
- (((unsigned char)PRVM_EDICTFIELDVALUE(touch, prog->fieldoffsets.pflags)->_float) & PFLAGS_FULLDYNAMIC)
- ||
- ((gamemode == GAME_TENEBRAE) && ((unsigned int)touch->fields.server->effects & (16 | 32)))
- )
- )
- pitchsign = -1;
+ pitchsign = SV_GetPitchSign(touch);
}
if (model)
Matrix4x4_CreateFromQuakeEntity(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2], pitchsign * touch->fields.server->angles[0], touch->fields.server->angles[1], touch->fields.server->angles[2], 1);
// if the modelindex is 0, it shouldn't be SOLID_BSP!
if (modelindex > 0 && modelindex < MAX_MODELS)
model = sv.models[(int)touch->fields.server->modelindex];
- //pitchsign = 1;
- if (
- ((modelindex = (int)touch->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS && (model = sv.models[(int)touch->fields.server->modelindex]))
- ?
- model->type == mod_alias
- :
- (
- (((unsigned char)PRVM_EDICTFIELDVALUE(touch, prog->fieldoffsets.pflags)->_float) & PFLAGS_FULLDYNAMIC)
- ||
- ((gamemode == GAME_TENEBRAE) && ((unsigned int)touch->fields.server->effects & (16 | 32)))
- )
- )
- pitchsign = -1;
+ pitchsign = SV_GetPitchSign(touch);
}
if (model)
Matrix4x4_CreateFromQuakeEntity(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2], pitchsign * touch->fields.server->angles[0], touch->fields.server->angles[1], touch->fields.server->angles[2], 1);
if (modelindex > 0 && modelindex < MAX_MODELS)
model = sv.models[(int)touch->fields.server->modelindex];
//pitchsign = 1;
- if (
- ((modelindex = (int)touch->fields.server->modelindex) >= 1 && modelindex < MAX_MODELS && (model = sv.models[(int)touch->fields.server->modelindex]))
- ?
- model->type == mod_alias
- :
- (
- (((unsigned char)PRVM_EDICTFIELDVALUE(touch, prog->fieldoffsets.pflags)->_float) & PFLAGS_FULLDYNAMIC)
- ||
- ((gamemode == GAME_TENEBRAE) && ((unsigned int)touch->fields.server->effects & (16 | 32)))
- )
- )
- pitchsign = -1;
+ pitchsign = SV_GetPitchSign(touch);
}
if (model)
Matrix4x4_CreateFromQuakeEntity(&matrix, touch->fields.server->origin[0], touch->fields.server->origin[1], touch->fields.server->origin[2], pitchsign * touch->fields.server->angles[0], touch->fields.server->angles[1], touch->fields.server->angles[2], 1);
===============================================================================
*/
+void SV_LinkEdict_TouchAreaGrid_Call(prvm_edict_t *touch, prvm_edict_t *ent)
+{
+ prvm_eval_t *val;
+ prog->globals.server->self = PRVM_EDICT_TO_PROG(touch);
+ prog->globals.server->other = PRVM_EDICT_TO_PROG(ent);
+ prog->globals.server->time = sv.time;
+ prog->globals.server->trace_allsolid = false;
+ prog->globals.server->trace_startsolid = false;
+ prog->globals.server->trace_fraction = 1;
+ prog->globals.server->trace_inwater = false;
+ prog->globals.server->trace_inopen = true;
+ VectorCopy (touch->fields.server->origin, prog->globals.server->trace_endpos);
+ VectorSet (prog->globals.server->trace_plane_normal, 0, 0, 1);
+ prog->globals.server->trace_plane_dist = 0;
+ prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(ent);
+ if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dpstartcontents)))
+ val->_float = 0;
+ if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitcontents)))
+ val->_float = 0;
+ if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitq3surfaceflags)))
+ val->_float = 0;
+ if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphittexturename)))
+ val->string = 0;
+ PRVM_ExecuteProgram (touch->fields.server->touch, "QC function self.touch is missing");
+}
+
void SV_LinkEdict_TouchAreaGrid(prvm_edict_t *ent)
{
int i, numtouchedicts, old_self, old_other;
touch = touchedicts[i];
if (touch != ent && (int)touch->fields.server->solid == SOLID_TRIGGER && touch->fields.server->touch)
{
- prvm_eval_t *val;
- prog->globals.server->self = PRVM_EDICT_TO_PROG(touch);
- prog->globals.server->other = PRVM_EDICT_TO_PROG(ent);
- prog->globals.server->time = sv.time;
- prog->globals.server->trace_allsolid = false;
- prog->globals.server->trace_startsolid = false;
- prog->globals.server->trace_fraction = 1;
- prog->globals.server->trace_inwater = false;
- prog->globals.server->trace_inopen = true;
- VectorCopy (touch->fields.server->origin, prog->globals.server->trace_endpos);
- VectorSet (prog->globals.server->trace_plane_normal, 0, 0, 1);
- prog->globals.server->trace_plane_dist = 0;
- prog->globals.server->trace_ent = PRVM_EDICT_TO_PROG(ent);
- if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dpstartcontents)))
- val->_float = 0;
- if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitcontents)))
- val->_float = 0;
- if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphitq3surfaceflags)))
- val->_float = 0;
- if ((val = PRVM_GLOBALFIELDVALUE(prog->globaloffsets.trace_dphittexturename)))
- val->string = 0;
- PRVM_ExecuteProgram (touch->fields.server->touch, "QC function self.touch is missing");
+ SV_LinkEdict_TouchAreaGrid_Call(touch, ent);
}
}
prog->globals.server->self = old_self;
prog->globals.server->other = old_other;
}
+static void RotateBBox(const vec3_t mins, const vec3_t maxs, const vec3_t angles, vec3_t rotatedmins, vec3_t rotatedmaxs)
+{
+ vec3_t v, u;
+ matrix4x4_t m;
+ Matrix4x4_CreateFromQuakeEntity(&m, 0, 0, 0, angles[PITCH], angles[YAW], angles[ROLL], 1.0);
+
+ v[0] = mins[0]; v[1] = mins[1]; v[2] = mins[2]; Matrix4x4_Transform(&m, v, u);
+ VectorCopy(u, rotatedmins); VectorCopy(u, rotatedmaxs);
+ v[0] = maxs[0]; v[1] = mins[1]; v[2] = mins[2]; Matrix4x4_Transform(&m, v, u);
+ if(rotatedmins[0] > u[0]) rotatedmins[0] = u[0]; if(rotatedmins[1] > u[1]) rotatedmins[1] = u[1]; if(rotatedmins[2] > u[2]) rotatedmins[2] = u[2];
+ if(rotatedmaxs[0] < u[0]) rotatedmaxs[0] = u[0]; if(rotatedmaxs[1] < u[1]) rotatedmaxs[1] = u[1]; if(rotatedmaxs[2] < u[2]) rotatedmaxs[2] = u[2];
+ v[0] = mins[0]; v[1] = maxs[1]; v[2] = mins[2]; Matrix4x4_Transform(&m, v, u);
+ if(rotatedmins[0] > u[0]) rotatedmins[0] = u[0]; if(rotatedmins[1] > u[1]) rotatedmins[1] = u[1]; if(rotatedmins[2] > u[2]) rotatedmins[2] = u[2];
+ if(rotatedmaxs[0] < u[0]) rotatedmaxs[0] = u[0]; if(rotatedmaxs[1] < u[1]) rotatedmaxs[1] = u[1]; if(rotatedmaxs[2] < u[2]) rotatedmaxs[2] = u[2];
+ v[0] = maxs[0]; v[1] = maxs[1]; v[2] = mins[2]; Matrix4x4_Transform(&m, v, u);
+ if(rotatedmins[0] > u[0]) rotatedmins[0] = u[0]; if(rotatedmins[1] > u[1]) rotatedmins[1] = u[1]; if(rotatedmins[2] > u[2]) rotatedmins[2] = u[2];
+ if(rotatedmaxs[0] < u[0]) rotatedmaxs[0] = u[0]; if(rotatedmaxs[1] < u[1]) rotatedmaxs[1] = u[1]; if(rotatedmaxs[2] < u[2]) rotatedmaxs[2] = u[2];
+ v[0] = mins[0]; v[1] = mins[1]; v[2] = maxs[2]; Matrix4x4_Transform(&m, v, u);
+ if(rotatedmins[0] > u[0]) rotatedmins[0] = u[0]; if(rotatedmins[1] > u[1]) rotatedmins[1] = u[1]; if(rotatedmins[2] > u[2]) rotatedmins[2] = u[2];
+ if(rotatedmaxs[0] < u[0]) rotatedmaxs[0] = u[0]; if(rotatedmaxs[1] < u[1]) rotatedmaxs[1] = u[1]; if(rotatedmaxs[2] < u[2]) rotatedmaxs[2] = u[2];
+ v[0] = maxs[0]; v[1] = mins[1]; v[2] = maxs[2]; Matrix4x4_Transform(&m, v, u);
+ if(rotatedmins[0] > u[0]) rotatedmins[0] = u[0]; if(rotatedmins[1] > u[1]) rotatedmins[1] = u[1]; if(rotatedmins[2] > u[2]) rotatedmins[2] = u[2];
+ if(rotatedmaxs[0] < u[0]) rotatedmaxs[0] = u[0]; if(rotatedmaxs[1] < u[1]) rotatedmaxs[1] = u[1]; if(rotatedmaxs[2] < u[2]) rotatedmaxs[2] = u[2];
+ v[0] = mins[0]; v[1] = maxs[1]; v[2] = maxs[2]; Matrix4x4_Transform(&m, v, u);
+ if(rotatedmins[0] > u[0]) rotatedmins[0] = u[0]; if(rotatedmins[1] > u[1]) rotatedmins[1] = u[1]; if(rotatedmins[2] > u[2]) rotatedmins[2] = u[2];
+ if(rotatedmaxs[0] < u[0]) rotatedmaxs[0] = u[0]; if(rotatedmaxs[1] < u[1]) rotatedmaxs[1] = u[1]; if(rotatedmaxs[2] < u[2]) rotatedmaxs[2] = u[2];
+ v[0] = maxs[0]; v[1] = maxs[1]; v[2] = maxs[2]; Matrix4x4_Transform(&m, v, u);
+ if(rotatedmins[0] > u[0]) rotatedmins[0] = u[0]; if(rotatedmins[1] > u[1]) rotatedmins[1] = u[1]; if(rotatedmins[2] > u[2]) rotatedmins[2] = u[2];
+ if(rotatedmaxs[0] < u[0]) rotatedmaxs[0] = u[0]; if(rotatedmaxs[1] < u[1]) rotatedmaxs[1] = u[1]; if(rotatedmaxs[2] < u[2]) rotatedmaxs[2] = u[2];
+}
+
/*
===============
SV_LinkEdict
// set the abs box
- if (ent->fields.server->solid == SOLID_BSP)
+ if (ent->fields.server->movetype == MOVETYPE_PHYSICS)
+ {
+ // TODO maybe should do this for rotating SOLID_BSP too? Would behave better with rotating doors
+ // TODO special handling for spheres?
+ RotateBBox(ent->fields.server->mins, ent->fields.server->maxs, ent->fields.server->angles, mins, maxs);
+ VectorAdd(ent->fields.server->origin, mins, mins);
+ VectorAdd(ent->fields.server->origin, maxs, maxs);
+ }
+ else if (ent->fields.server->solid == SOLID_BSP)
{
int modelindex = (int)ent->fields.server->modelindex;
if (modelindex < 0 || modelindex >= MAX_MODELS)
}
}
+ // LordHavoc: a hack to ensure that the (rather silly) id1 quakec
+ // player_run/player_stand1 does not horribly malfunction if the
+ // velocity becomes a denormalized float
+ if (VectorLength2(ent->fields.server->velocity) < 0.0001)
+ VectorClear(ent->fields.server->velocity);
+
// LordHavoc: max velocity fix, inspired by Maddes's source fixes, but this is faster
wishspeed = DotProduct(ent->fields.server->velocity, ent->fields.server->velocity);
if (wishspeed > sv_maxvelocity.value * sv_maxvelocity.value)
static qboolean SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, qboolean failonbmodelstartsolid, qboolean dolink)
{
int type;
+ int bump;
+ vec3_t original;
vec3_t end;
+ VectorCopy(ent->fields.server->origin, original);
VectorAdd (ent->fields.server->origin, push, end);
if (ent->fields.server->movetype == MOVETYPE_FLYMISSILE)
type = MOVE_NORMAL;
*trace = SV_TraceBox(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, type, ent, SV_GenericHitSuperContentsMask(ent));
+ bump = 0;
+ while (trace->startsolid && sv_gameplayfix_nudgeoutofsolid.integer)
+ {
+ vec_t nudge = -trace->startdepth + sv_gameplayfix_nudgeoutofsolid_bias.value;
+ VectorMA(ent->fields.server->origin, nudge, trace->startdepthnormal, ent->fields.server->origin);
+ *trace = SV_TraceBox(ent->fields.server->origin, ent->fields.server->mins, ent->fields.server->maxs, end, type, ent, SV_GenericHitSuperContentsMask(ent));
+ bump++;
+ if (bump > 10)
+ {
+ VectorCopy(original, ent->fields.server->origin);
+ break;
+ }
+ }
if (trace->bmodelstartsolid && failonbmodelstartsolid)
return true;
+
VectorCopy (trace->endpos, ent->fields.server->origin);
SV_LinkEdict(ent);
for (e = 0;e < numcheckentities;e++)
{
prvm_edict_t *check = checkentities[e];
- if (check->fields.server->movetype == MOVETYPE_NONE
- || check->fields.server->movetype == MOVETYPE_PUSH
- || check->fields.server->movetype == MOVETYPE_FOLLOW
- || check->fields.server->movetype == MOVETYPE_NOCLIP
- || check->fields.server->movetype == MOVETYPE_FAKEPUSH)
+ int movetype = (int)check->fields.server->movetype;
+ switch(movetype)
+ {
+ case MOVETYPE_NONE:
+ case MOVETYPE_PUSH:
+ case MOVETYPE_FOLLOW:
+ case MOVETYPE_NOCLIP:
+ case MOVETYPE_FAKEPUSH:
continue;
+ default:
+ break;
+ }
if (check->fields.server->owner == pusherprog)
continue;
VectorCopy (check->fields.server->angles, check->priv.server->moved_fromangles);
moved_edicts[num_moved++] = PRVM_NUM_FOR_EDICT(check);
+ // physics objects need better collisions than this code can do
+ if (movetype == MOVETYPE_PHYSICS)
+ {
+ VectorAdd(check->fields.server->origin, move, check->fields.server->origin);
+ SV_LinkEdict(check);
+ SV_LinkEdict_TouchAreaGrid(check);
+ continue;
+ }
+
// try moving the contacted entity
pusher->fields.server->solid = SOLID_NOT;
if(!SV_PushEntity (&trace, check, move, true, true))
vec3_t move;
vec_t movetime;
int bump;
+ prvm_edict_t *groundentity;
// if onground, return without moving
if ((int)ent->fields.server->flags & FL_ONGROUND)
{
+ groundentity = PRVM_PROG_TO_EDICT(ent->fields.server->groundentity);
if (ent->fields.server->velocity[2] >= (1.0 / 32.0) && sv_gameplayfix_upwardvelocityclearsongroundflag.integer)
{
// don't stick to ground if onground and moving upward
// we can trust FL_ONGROUND if groundentity is world because it never moves
return;
}
- else if (ent->priv.server->suspendedinairflag && PRVM_PROG_TO_EDICT(ent->fields.server->groundentity)->priv.server->free)
+ else if (ent->priv.server->suspendedinairflag && groundentity->priv.server->free)
{
// if ent was supported by a brush model on previous frame,
// and groundentity is now freed, set groundentity to 0 (world)
if (sv_gameplayfix_noairborncorpse_allowsuspendeditems.integer)
return;
}
+ else if (BoxesOverlap(ent->priv.server->cullmins, ent->priv.server->cullmaxs, groundentity->priv.server->cullmins, groundentity->priv.server->cullmaxs))
+ {
+ // don't slide if still touching the groundentity
+ return;
+ }
}
ent->priv.server->suspendedinairflag = false;
movetime *= 1 - min(1, trace.fraction);
if (ent->fields.server->movetype == MOVETYPE_BOUNCEMISSILE)
{
- ClipVelocity (ent->fields.server->velocity, trace.plane.normal, ent->fields.server->velocity, 2.0);
+ prvm_eval_t *val;
+ float bouncefactor = 1.0f;
+ val = PRVM_EDICTFIELDVALUE(ent, prog->fieldoffsets.bouncefactor);
+ if (val!=0 && val->_float)
+ bouncefactor = val->_float;
+
+ ClipVelocity (ent->fields.server->velocity, trace.plane.normal, ent->fields.server->velocity, 1 + bouncefactor);
ent->fields.server->flags = (int)ent->fields.server->flags & ~FL_ONGROUND;
}
else if (ent->fields.server->movetype == MOVETYPE_BOUNCE)
{
// freefall if onground and moving upward
// freefall if not standing on a world surface (it may be a lift or trap door)
- if ((ent->fields.server->velocity[2] >= (1.0 / 32.0) && sv_gameplayfix_upwardvelocityclearsongroundflag.integer) || ent->fields.server->groundentity)
+ if (ent->fields.server->velocity[2] >= (1.0 / 32.0) && sv_gameplayfix_upwardvelocityclearsongroundflag.integer)
{
ent->fields.server->flags -= FL_ONGROUND;
SV_CheckVelocity(ent);
if (SV_RunThink (ent))
SV_Physics_Toss (ent);
break;
+ case MOVETYPE_PHYSICS:
+ if (SV_RunThink(ent))
+ {
+ SV_LinkEdict(ent);
+ SV_LinkEdict_TouchAreaGrid(ent);
+ }
+ break;
default:
Con_Printf ("SV_Physics: bad movetype %i\n", (int)ent->fields.server->movetype);
break;
// make sure the velocity is sane (not a NaN)
SV_CheckVelocity(ent);
- // LordHavoc: a hack to ensure that the (rather silly) id1 quakec
- // player_run/player_stand1 does not horribly malfunction if the
- // velocity becomes a number that is both == 0 and != 0
- // (sounds to me like NaN but to be absolutely safe...)
- if (DotProduct(ent->fields.server->velocity, ent->fields.server->velocity) < 0.0001)
- VectorClear(ent->fields.server->velocity);
// perform MOVETYPE_WALK behavior
SV_WalkMove (ent);
}
}
-void SV_Physics_ClientEntity(prvm_edict_t *ent)
+static void SV_Physics_ClientEntity_PreThink(prvm_edict_t *ent)
{
// don't do physics on disconnected clients, FrikBot relies on this
if (!host_client->spawned)
- {
- memset(&host_client->cmd, 0, sizeof(host_client->cmd));
return;
- }
+
+ // make sure the velocity is sane (not a NaN)
+ SV_CheckVelocity(ent);
// don't run physics here if running asynchronously
if (host_client->clmovement_inputtimeout <= 0)
//host_client->cmd.time = max(host_client->cmd.time, sv.time);
}
- // make sure the velocity is sane (not a NaN)
+ // make sure the velocity is still sane (not a NaN)
SV_CheckVelocity(ent);
- // LordHavoc: a hack to ensure that the (rather silly) id1 quakec
- // player_run/player_stand1 does not horribly malfunction if the
- // velocity becomes a number that is both == 0 and != 0
- // (sounds to me like NaN but to be absolutely safe...)
- if (DotProduct(ent->fields.server->velocity, ent->fields.server->velocity) < 0.0001)
- VectorClear(ent->fields.server->velocity);
// call standard client pre-think
prog->globals.server->time = sv.time;
prog->globals.server->self = PRVM_EDICT_TO_PROG(ent);
- PRVM_ExecuteProgram (prog->globals.server->PlayerPreThink, "QC function PlayerPreThink is missing");
- SV_CheckVelocity (ent);
+ PRVM_ExecuteProgram(prog->globals.server->PlayerPreThink, "QC function PlayerPreThink is missing");
+
+ // make sure the velocity is still sane (not a NaN)
+ SV_CheckVelocity(ent);
+}
+
+static void SV_Physics_ClientEntity_PostThink(prvm_edict_t *ent)
+{
+ // don't do physics on disconnected clients, FrikBot relies on this
+ if (!host_client->spawned)
+ return;
+
+ // make sure the velocity is sane (not a NaN)
+ SV_CheckVelocity(ent);
+
+ // call standard player post-think
+ prog->globals.server->time = sv.time;
+ prog->globals.server->self = PRVM_EDICT_TO_PROG(ent);
+ PRVM_ExecuteProgram(prog->globals.server->PlayerPostThink, "QC function PlayerPostThink is missing");
+
+ // make sure the velocity is still sane (not a NaN)
+ SV_CheckVelocity(ent);
+
+ if(ent->fields.server->fixangle)
+ {
+ // angle fixing was requested by physics code...
+ // so store the current angles for later use
+ memcpy(host_client->fixangle_angles, ent->fields.server->angles, sizeof(host_client->fixangle_angles));
+ host_client->fixangle_angles_set = TRUE;
+
+ // and clear fixangle for the next frame
+ ent->fields.server->fixangle = 0;
+ }
+
+ // decrement the countdown variable used to decide when to go back to
+ // synchronous physics
+ if (host_client->clmovement_inputtimeout > sv.frametime)
+ host_client->clmovement_inputtimeout -= sv.frametime;
+ else
+ host_client->clmovement_inputtimeout = 0;
+}
+
+static void SV_Physics_ClientEntity(prvm_edict_t *ent)
+{
+ // don't do physics on disconnected clients, FrikBot relies on this
+ if (!host_client->spawned)
+ {
+ memset(&host_client->cmd, 0, sizeof(host_client->cmd));
+ return;
+ }
+
+ // make sure the velocity is sane (not a NaN)
+ SV_CheckVelocity(ent);
switch ((int) ent->fields.server->movetype)
{
SV_RunThink (ent);
SV_WalkMove (ent);
break;
+ case MOVETYPE_PHYSICS:
+ SV_RunThink (ent);
+ break;
default:
Con_Printf ("SV_Physics_ClientEntity: bad movetype %i\n", (int)ent->fields.server->movetype);
break;
}
- // decrement the countdown variable used to decide when to go back to
- // synchronous physics
- if (host_client->clmovement_inputtimeout > sv.frametime)
- host_client->clmovement_inputtimeout -= sv.frametime;
- else
- host_client->clmovement_inputtimeout = 0;
-
SV_CheckVelocity (ent);
SV_LinkEdict(ent);
SV_LinkEdict_TouchAreaGrid(ent);
SV_CheckVelocity (ent);
-
- // call standard player post-think
- prog->globals.server->time = sv.time;
- prog->globals.server->self = PRVM_EDICT_TO_PROG(ent);
- PRVM_ExecuteProgram (prog->globals.server->PlayerPostThink, "QC function PlayerPostThink is missing");
-
- if(ent->fields.server->fixangle)
- {
- // angle fixing was requested by physics code...
- // so store the current angles for later use
- memcpy(host_client->fixangle_angles, ent->fields.server->angles, sizeof(host_client->fixangle_angles));
- host_client->fixangle_angles_set = TRUE;
-
- // and clear fixangle for the next frame
- ent->fields.server->fixangle = 0;
- }
}
/*
prog->globals.server->frametime = sv.frametime;
PRVM_ExecuteProgram (prog->globals.server->StartFrame, "QC function StartFrame is missing");
+ // run physics engine
+ World_Physics_Frame(&sv.world, sv.frametime, sv_gravity.value);
+
//
// treat each object in turn
//
if (!ent->priv.server->free)
SV_LinkEdict_TouchAreaGrid(ent); // force retouch even for stationary
- // run physics on the client entities
- for (i = 1, ent = PRVM_EDICT_NUM(i), host_client = svs.clients;i <= svs.maxclients;i++, ent = PRVM_NEXT_EDICT(ent), host_client++)
- if (!ent->priv.server->free)
+ if (sv_gameplayfix_consistentplayerprethink.integer)
+ {
+ // run physics on the client entities in 3 stages
+ for (i = 1, ent = PRVM_EDICT_NUM(i), host_client = svs.clients;i <= svs.maxclients;i++, ent = PRVM_NEXT_EDICT(ent), host_client++)
+ if (!ent->priv.server->free)
+ SV_Physics_ClientEntity_PreThink(ent);
+
+ for (i = 1, ent = PRVM_EDICT_NUM(i), host_client = svs.clients;i <= svs.maxclients;i++, ent = PRVM_NEXT_EDICT(ent), host_client++)
+ if (!ent->priv.server->free)
SV_Physics_ClientEntity(ent);
+ for (i = 1, ent = PRVM_EDICT_NUM(i), host_client = svs.clients;i <= svs.maxclients;i++, ent = PRVM_NEXT_EDICT(ent), host_client++)
+ if (!ent->priv.server->free)
+ SV_Physics_ClientEntity_PostThink(ent);
+ }
+ else
+ {
+ // run physics on the client entities
+ for (i = 1, ent = PRVM_EDICT_NUM(i), host_client = svs.clients;i <= svs.maxclients;i++, ent = PRVM_NEXT_EDICT(ent), host_client++)
+ {
+ if (!ent->priv.server->free)
+ {
+ SV_Physics_ClientEntity_PreThink(ent);
+ SV_Physics_ClientEntity(ent);
+ SV_Physics_ClientEntity_PostThink(ent);
+ }
+ }
+ }
+
// run physics on all the non-client entities
if (!sv_freezenonclients.integer)
{