From: havoc Date: Sun, 24 Mar 2013 18:20:15 +0000 (+0000) Subject: reworked the MOVETYPE_WALK and MOVETYPE_STEP sticking logic so that it X-Git-Tag: xonotic-v0.7.0~26 X-Git-Url: http://git.xonotic.org/?p=xonotic%2Fdarkplaces.git;a=commitdiff_plain;h=37401af678290a0284cc90820a611259bcb49303 reworked the MOVETYPE_WALK and MOVETYPE_STEP sticking logic so that it only cares about world when deciding to be stuck, this means if you get into a bmodel entity you can still move out of it git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@11926 d7cf8633-e32d-0410-b094-e92efae38249 ::stable-branch::merge=17f95319455e01172cfdd806c8b7bc97064203fc --- diff --git a/cl_collision.c b/cl_collision.c index 05b1a799..f0e0f7de 100644 --- a/cl_collision.c +++ b/cl_collision.c @@ -265,7 +265,7 @@ trace_t CL_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int // clip to world Collision_ClipPointToWorld(&cliptrace, cl.worldmodel, clipstart, hitsupercontentsmask); - cliptrace.bmodelstartsolid = cliptrace.startsolid; + cliptrace.worldstartsolid = cliptrace.bmodelstartsolid = cliptrace.startsolid; if (cliptrace.startsolid || cliptrace.fraction < 1) cliptrace.ent = prog ? prog->edicts : NULL; if (type == MOVE_WORLDONLY) @@ -503,7 +503,7 @@ trace_t CL_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_ // clip to world Collision_ClipLineToWorld(&cliptrace, cl.worldmodel, clipstart, clipend, hitsupercontentsmask, hitsurfaces); - cliptrace.bmodelstartsolid = cliptrace.startsolid; + cliptrace.worldstartsolid = cliptrace.bmodelstartsolid = cliptrace.startsolid; if (cliptrace.startsolid || cliptrace.fraction < 1) cliptrace.ent = prog ? prog->edicts : NULL; if (type == MOVE_WORLDONLY) @@ -771,7 +771,7 @@ trace_t CL_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, co // clip to world Collision_ClipToWorld(&cliptrace, cl.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 ? prog->edicts : NULL; if (type == MOVE_WORLDONLY) @@ -1008,7 +1008,7 @@ trace_t CL_Cache_TraceLineSurfaces(const vec3_t start, const vec3_t end, int typ // clip to world Collision_Cache_ClipLineToWorldSurfaces(&cliptrace, cl.worldmodel, clipstart, clipend, hitsupercontentsmask); - cliptrace.bmodelstartsolid = cliptrace.startsolid; + cliptrace.worldstartsolid = cliptrace.bmodelstartsolid = cliptrace.startsolid; if (cliptrace.startsolid || cliptrace.fraction < 1) cliptrace.ent = prog ? prog->edicts : NULL; if (type == MOVE_WORLDONLY) diff --git a/collision.h b/collision.h index 78da6459..0da12477 100644 --- a/collision.h +++ b/collision.h @@ -16,6 +16,8 @@ typedef struct trace_s int allsolid; // if true, the initial point was in solid (see hitsupercontentsmask) int startsolid; + // this is set to true in world.c if startsolid was set in a trace against world + int worldstartsolid; // this is set to true in world.c if startsolid was set in a trace against a SOLID_BSP entity, in other words this is true if the entity is stuck in a door or wall, but not if stuck in another normal entity int bmodelstartsolid; // if true, the trace passed through empty somewhere diff --git a/sv_phys.c b/sv_phys.c index 6b1c8c6c..e88baa25 100644 --- a/sv_phys.c +++ b/sv_phys.c @@ -138,7 +138,7 @@ trace_t SV_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int // 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) @@ -309,7 +309,7 @@ trace_t SV_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_ // 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) @@ -516,7 +516,7 @@ trace_t SV_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, co // 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) @@ -1239,7 +1239,7 @@ If stepnormal is not NULL, the plane normal of any vertical wall hit will be sto ============ */ 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) { @@ -1283,7 +1283,7 @@ static int SV_FlyMove (prvm_edict_t *ent, float time, qboolean applygravity, flo 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 @@ -1292,9 +1292,8 @@ static int SV_FlyMove (prvm_edict_t *ent, float time, qboolean applygravity, flo } // 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; @@ -1330,20 +1329,20 @@ static int SV_FlyMove (prvm_edict_t *ent, float time, qboolean applygravity, flo //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; @@ -1589,7 +1588,7 @@ static qboolean SV_NudgeOutOfSolid_PivotIsKnownGood(prvm_edict_t *ent, vec3_t pi 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; @@ -1597,7 +1596,6 @@ qboolean SV_NudgeOutOfSolid(prvm_edict_t *ent) 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; @@ -1606,17 +1604,23 @@ qboolean SV_NudgeOutOfSolid(prvm_edict_t *ent) 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; } @@ -1630,7 +1634,7 @@ The trace struct is filled with the trace that has been done. 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; @@ -1664,7 +1668,8 @@ static qboolean SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, q 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)); @@ -1931,7 +1936,7 @@ static void SV_PushMove (prvm_edict_t *pusher, float movetime) // 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]; @@ -1963,7 +1968,7 @@ static void SV_PushMove (prvm_edict_t *pusher, float movetime) { // 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; @@ -2444,7 +2449,7 @@ static void SV_WalkMove (prvm_edict_t *ent) // 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; @@ -2496,7 +2501,7 @@ static void SV_WalkMove (prvm_edict_t *ent) // 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; @@ -2702,16 +2707,15 @@ void SV_Physics_Toss (prvm_edict_t *ent) { // 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;