// clip to world
Collision_ClipPointToWorld(&cliptrace, sv.worldmodel, clipstart, hitsupercontentsmask);
- cliptrace.bmodelstartsolid = cliptrace.startsolid;
+ cliptrace.worldstartsolid = cliptrace.bmodelstartsolid = cliptrace.startsolid;
if (cliptrace.startsolid || cliptrace.fraction < 1)
cliptrace.ent = prog->edicts;
if (type == MOVE_WORLDONLY)
// clip to world
Collision_ClipLineToWorld(&cliptrace, sv.worldmodel, clipstart, clipend, hitsupercontentsmask, false);
- cliptrace.bmodelstartsolid = cliptrace.startsolid;
+ cliptrace.worldstartsolid = cliptrace.bmodelstartsolid = cliptrace.startsolid;
if (cliptrace.startsolid || cliptrace.fraction < 1)
cliptrace.ent = prog->edicts;
if (type == MOVE_WORLDONLY)
// clip to world
Collision_ClipToWorld(&cliptrace, sv.worldmodel, clipstart, clipmins, clipmaxs, clipend, hitsupercontentsmask);
- cliptrace.bmodelstartsolid = cliptrace.startsolid;
+ cliptrace.worldstartsolid = cliptrace.bmodelstartsolid = cliptrace.startsolid;
if (cliptrace.startsolid || cliptrace.fraction < 1)
cliptrace.ent = prog->edicts;
if (type == MOVE_WORLDONLY)
============
*/
static float SV_Gravity (prvm_edict_t *ent);
-static qboolean SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, qboolean failonbmodelstartsolid, qboolean dolink);
+static qboolean SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, qboolean dolink);
#define MAX_CLIP_PLANES 5
static int SV_FlyMove (prvm_edict_t *ent, float time, qboolean applygravity, float *stepnormal, int hitsupercontentsmask, float stepheight)
{
break;
VectorScale(PRVM_serveredictvector(ent, velocity), time_left, push);
- if(!SV_PushEntity(&trace, ent, push, true, false))
+ if(!SV_PushEntity(&trace, ent, push, false))
{
// we got teleported by a touch function
// let's abort the move
}
// this code is used by MOVETYPE_WALK and MOVETYPE_STEP and SV_UnstickEntity
- // abort move if it started in SUPERCONTENTS_SOLID (not SUPERCONTENTS_BODY used by SOLID_BBOX)
- // note the SV_PushEntity call above must pass true for failonbmodelstartsolid
- if (trace.allsolid && (trace.startsupercontents & SUPERCONTENTS_SOLID))
+ // abort move if we're stuck in the world (and didn't make it out)
+ if (trace.worldstartsolid && trace.allsolid)
{
VectorCopy(restore_velocity, PRVM_serveredictvector(ent, velocity));
return 3;
//Con_Printf("step %f %f %f : ", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
VectorSet(steppush, 0, 0, stepheight);
VectorCopy(PRVM_serveredictvector(ent, origin), org);
- if(!SV_PushEntity(&steptrace, ent, steppush, false, false))
+ if(!SV_PushEntity(&steptrace, ent, steppush, false))
{
blocked |= 8;
break;
}
//Con_Printf("%f %f %f : ", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
- if(!SV_PushEntity(&steptrace2, ent, push, false, false))
+ if(!SV_PushEntity(&steptrace2, ent, push, false))
{
blocked |= 8;
break;
}
//Con_Printf("%f %f %f : ", PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
VectorSet(steppush, 0, 0, org[2] - PRVM_serveredictvector(ent, origin)[2]);
- if(!SV_PushEntity(&steptrace3, ent, steppush, false, false))
+ if(!SV_PushEntity(&steptrace3, ent, steppush, false))
{
blocked |= 8;
break;
qboolean SV_NudgeOutOfSolid(prvm_edict_t *ent)
{
prvm_prog_t *prog = SVVM_prog;
- int bump;
+ int bump, pass;
trace_t stucktrace;
vec3_t stuckorigin;
vec3_t stuckmins, stuckmaxs;
vec_t separation = sv_gameplayfix_nudgeoutofsolid_separation.value;
if (sv.worldmodel && sv.worldmodel->brushq1.numclipnodes)
separation = 0.0f; // when using hulls, it can not be enlarged
- VectorCopy(PRVM_serveredictvector(ent, origin), stuckorigin);
VectorCopy(PRVM_serveredictvector(ent, mins), stuckmins);
VectorCopy(PRVM_serveredictvector(ent, maxs), stuckmaxs);
stuckmins[0] -= separation;
stuckmaxs[0] += separation;
stuckmaxs[1] += separation;
stuckmaxs[2] += separation;
- for (bump = 0;bump < 10;bump++)
+ // first pass we try to get it out of brush entities
+ // second pass we try to get it out of world only (can't win them all)
+ for (pass = 0;pass < 2;pass++)
{
- stucktrace = SV_TraceBox(stuckorigin, stuckmins, stuckmaxs, stuckorigin, MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent));
- if (!stucktrace.bmodelstartsolid || stucktrace.startdepth >= 0)
+ VectorCopy(PRVM_serveredictvector(ent, origin), stuckorigin);
+ for (bump = 0;bump < 10;bump++)
{
- // found a good location, use it
- VectorCopy(stuckorigin, PRVM_serveredictvector(ent, origin));
- return true;
+ stucktrace = SV_TraceBox(stuckorigin, stuckmins, stuckmaxs, stuckorigin, pass ? MOVE_WORLDONLY : MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent));
+ if (!stucktrace.bmodelstartsolid || stucktrace.startdepth >= 0)
+ {
+ // found a good location, use it
+ VectorCopy(stuckorigin, PRVM_serveredictvector(ent, origin));
+ return true;
+ }
+ nudge = -stucktrace.startdepth;
+ VectorMA(stuckorigin, nudge, stucktrace.startdepthnormal, stuckorigin);
}
- nudge = -stucktrace.startdepth;
- VectorMA(stuckorigin, nudge, stucktrace.startdepthnormal, stuckorigin);
}
return false;
}
Returns true if the push did not result in the entity being teleported by QC code.
============
*/
-static qboolean SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, qboolean failonbmodelstartsolid, qboolean dolink)
+static qboolean SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, qboolean dolink)
{
prvm_prog_t *prog = SVVM_prog;
int solid;
type = MOVE_NORMAL;
*trace = SV_TraceBox(start, mins, maxs, end, type, ent, SV_GenericHitSuperContentsMask(ent));
- if (trace->bmodelstartsolid && failonbmodelstartsolid)
+ // fail the move if stuck in world
+ if (trace->worldstartsolid)
return true;
VectorCopy(trace->endpos, PRVM_serveredictvector(ent, origin));
// try moving the contacted entity
PRVM_serveredictfloat(pusher, solid) = SOLID_NOT;
- if(!SV_PushEntity (&trace, check, move, true, true))
+ if(!SV_PushEntity (&trace, check, move, true))
{
// entity "check" got teleported
PRVM_serveredictvector(check, angles)[1] += trace.fraction * moveangle[1];
{
// hack to invoke all necessary movement triggers
VectorClear(move2);
- if(!SV_PushEntity(&trace2, check, move2, true, true))
+ if(!SV_PushEntity(&trace2, check, move2, true))
{
// entity "check" got teleported
continue;
// move up
VectorClear (upmove);
upmove[2] = sv_stepheight.value;
- if(!SV_PushEntity(&trace, ent, upmove, false, true))
+ if(!SV_PushEntity(&trace, ent, upmove, true))
{
// we got teleported when upstepping... must abort the move
return;
// move down
VectorClear (downmove);
downmove[2] = -sv_stepheight.value + start_velocity[2]*sv.frametime;
- if(!SV_PushEntity (&downtrace, ent, downmove, false, true))
+ if(!SV_PushEntity (&downtrace, ent, downmove, true))
{
// we got teleported when downstepping... must abort the move
return;
{
// move origin
VectorScale(PRVM_serveredictvector(ent, velocity), movetime, move);
- if(!SV_PushEntity(&trace, ent, move, true, true))
+ if(!SV_PushEntity(&trace, ent, move, true))
return; // teleported
if (ent->priv.server->free)
return;
- if (trace.bmodelstartsolid)
+ if (trace.bmodelstartsolid && sv_gameplayfix_unstickentities.integer)
{
// try to unstick the entity
- if (sv_gameplayfix_unstickentities.integer)
- SV_UnstickEntity(ent);
- if(!SV_PushEntity(&trace, ent, move, false, true))
+ SV_UnstickEntity(ent);
+ if(!SV_PushEntity(&trace, ent, move, true))
return; // teleported
if (ent->priv.server->free)
return;