}
else if (passedict->fields.server->solid == SOLID_CORPSE)
return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY;
+ else if (passedict->fields.server->solid == SOLID_TRIGGER)
+ return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY;
else
return SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY | SUPERCONTENTS_CORPSE;
}
trace.ent = prog->edicts;
}
- if (((int) ent->fields.server->flags & FL_ONGROUND) && ent->fields.server->groundentity == PRVM_EDICT_TO_PROG(trace.ent))
- impact = false;
- else
- {
- ent->fields.server->flags = (int)ent->fields.server->flags & ~FL_ONGROUND;
- impact = true;
- }
+ impact = !((int) ent->fields.server->flags & FL_ONGROUND) || ent->fields.server->groundentity != PRVM_EDICT_TO_PROG(trace.ent);
if (trace.plane.normal[2])
{
continue;
// if the entity is standing on the pusher, it will definitely be moved
- if (((int)check->fields.server->flags & FL_ONGROUND) && PRVM_PROG_TO_EDICT(check->fields.server->groundentity) == pusher)
+ // if the entity is not standing on the pusher, but is in the pusher's
+ // final position, move it
+ if (!((int)check->fields.server->flags & FL_ONGROUND) || PRVM_PROG_TO_EDICT(check->fields.server->groundentity) != pusher)
{
- // remove the onground flag for non-players
- if (check->fields.server->movetype != MOVETYPE_WALK)
- check->fields.server->flags = (int)check->fields.server->flags & ~FL_ONGROUND;
- }
- else
- {
- // if the entity is not inside the pusher's final position, leave it alone
Collision_ClipToGenericEntity(&trace, pushermodel, pusher->fields.server->frame, pusher->fields.server->mins, pusher->fields.server->maxs, SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
if (!trace.startsolid)
continue;
pusher->fields.server->solid = savesolid; // was SOLID_BSP
//Con_Printf("%s:%d frac %f startsolid %d bmodelstartsolid %d allsolid %d\n", __FILE__, __LINE__, trace.fraction, trace.startsolid, trace.bmodelstartsolid, trace.allsolid);
+ // this check is for items riding platforms that are passing under (or
+ // through) walls intended to knock the items off
+ if (trace.fraction < 1 && check->fields.server->movetype != MOVETYPE_WALK)
+ check->fields.server->flags = (int)check->fields.server->flags & ~FL_ONGROUND;
+
// if it is still inside the pusher, block
Collision_ClipToGenericEntity(&trace, pushermodel, pusher->fields.server->frame, pusher->fields.server->mins, pusher->fields.server->maxs, SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, check->fields.server->origin, check->fields.server->mins, check->fields.server->maxs, check->fields.server->origin, SUPERCONTENTS_SOLID | SUPERCONTENTS_BODY);
if (trace.startsolid)
// do a regular slide move unless it looks like you ran into a step
oldonground = (int)ent->fields.server->flags & FL_ONGROUND;
- ent->fields.server->flags = (int)ent->fields.server->flags & ~FL_ONGROUND;
VectorCopy (ent->fields.server->origin, start_origin);
VectorCopy (ent->fields.server->velocity, start_velocity);
clip = SV_FlyMove (ent, sv.frametime, NULL, hitsupercontentsmask);
+ // if the move did not hit the ground at any point, we're not on ground
+ if (!(clip & 1))
+ ent->fields.server->flags = (int)ent->fields.server->flags & ~FL_ONGROUND;
+
SV_CheckVelocity(ent);
VectorCopy(ent->fields.server->origin, originalmove_origin);
if (clip & 2 && sv_wallfriction.integer)
SV_WallFriction (ent, stepnormal);
}
- // skip out if stepdown is enabled, moving downward, not in water, and the move started onground and ended offground
- else if (!(sv_gameplayfix_stepdown.integer && ent->fields.server->waterlevel < 2 && start_velocity[2] < (1.0 / 32.0) && oldonground && !((int)ent->fields.server->flags & FL_ONGROUND)))
+ // don't do the down move if stepdown is disabled, moving upward, not in water, or the move started offground or ended onground
+ else if (!sv_gameplayfix_stepdown.integer || ent->fields.server->waterlevel >= 3 || start_velocity[2] >= (1.0 / 32.0) || !oldonground || ((int)ent->fields.server->flags & FL_ONGROUND))
return;
// move down
if (downtrace.fraction < 1 && downtrace.plane.normal[2] > 0.7)
{
// this has been disabled so that you can't jump when you are stepping
- // up while already jumping (also known as the Quake2 stair jump bug)
+ // up while already jumping (also known as the Quake2 double jump bug)
#if 0
// LordHavoc: disabled this check so you can walk on monsters/players
//if (ent->fields.server->solid == SOLID_BSP)
}
}
-void SV_Physics_ClientEntity (prvm_edict_t *ent)
+void SV_Physics_ClientMove(void)
{
- SV_ApplyClientMove();
- // make sure the velocity is sane (not a NaN)
- SV_CheckVelocity(ent);
- // LordHavoc: QuakeC replacement for SV_ClientThink (player movement)
- if (prog->funcoffsets.SV_PlayerPhysics && sv_playerphysicsqc.integer)
+ prvm_edict_t *ent;
+ ent = host_client->edict;
+ if (!SV_CheckWater (ent) && ! ((int)ent->fields.server->flags & FL_WATERJUMP) )
+ SV_AddGravity (ent);
+ SV_CheckStuck (ent);
+ SV_WalkMove (ent);
+}
+
+void SV_Physics_ClientEntity(prvm_edict_t *ent)
+{
+ // don't do physics on disconnected clients, FrikBot relies on this
+ if (!host_client->spawned)
{
- prog->globals.server->time = sv.time;
- prog->globals.server->self = PRVM_EDICT_TO_PROG(ent);
- PRVM_ExecuteProgram (prog->funcoffsets.SV_PlayerPhysics, "QC function SV_PlayerPhysics is missing");
+ memset(&host_client->cmd, 0, sizeof(host_client->cmd));
+ return;
}
- else
- SV_ClientThink ();
+
+ SV_ClientThink();
+
// make sure the velocity is sane (not a NaN)
SV_CheckVelocity(ent);
// LordHavoc: a hack to ensure that the (rather silly) id1 quakec
SV_Physics_Follow (ent);
break;
case MOVETYPE_NOCLIP:
- if (SV_RunThink(ent))
- {
- SV_CheckWater(ent);
- VectorMA(ent->fields.server->origin, sv.frametime, ent->fields.server->velocity, ent->fields.server->origin);
- VectorMA(ent->fields.server->angles, sv.frametime, ent->fields.server->avelocity, ent->fields.server->angles);
- }
+ SV_RunThink(ent);
+ SV_CheckWater(ent);
+ VectorMA(ent->fields.server->origin, sv.frametime, ent->fields.server->velocity, ent->fields.server->origin);
+ VectorMA(ent->fields.server->angles, sv.frametime, ent->fields.server->avelocity, ent->fields.server->angles);
break;
case MOVETYPE_STEP:
SV_Physics_Step (ent);
break;
case MOVETYPE_WALK:
- if (SV_RunThink (ent))
- {
- if (!SV_CheckWater (ent) && ! ((int)ent->fields.server->flags & FL_WATERJUMP) )
- SV_AddGravity (ent);
- SV_CheckStuck (ent);
- SV_WalkMove (ent);
- }
+ SV_RunThink (ent);
+ // don't run physics here if running asynchronously
+ if (host_client->clmovement_skipphysicsframes <= 0)
+ SV_Physics_ClientMove();
break;
case MOVETYPE_TOSS:
case MOVETYPE_BOUNCE:
case MOVETYPE_BOUNCEMISSILE:
case MOVETYPE_FLYMISSILE:
// regular thinking
- if (SV_RunThink (ent))
- SV_Physics_Toss (ent);
+ SV_RunThink (ent);
+ SV_Physics_Toss (ent);
break;
case MOVETYPE_FLY:
- if (SV_RunThink (ent))
- {
- SV_CheckWater (ent);
- SV_WalkMove (ent);
- }
+ SV_RunThink (ent);
+ SV_CheckWater (ent);
+ SV_WalkMove (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_skipphysicsframes > 0)
+ host_client->clmovement_skipphysicsframes--;
+
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;
+ }
}
/*
// 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)
- {
- // don't do physics on disconnected clients, FrikBot relies on this
- if (!host_client->spawned)
- memset(&host_client->cmd, 0, sizeof(host_client->cmd));
- // don't run physics here if running asynchronously
- else if (host_client->clmovement_skipphysicsframes > 0)
- host_client->clmovement_skipphysicsframes--;
- else
SV_Physics_ClientEntity(ent);
- }
- }
// run physics on all the non-client entities
if (!sv_freezenonclients.integer)