X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=sv_phys.c;h=4e6f88d6bd16be90a486b9efb1501a103cfcc1dd;hb=HEAD;hp=77c3bacfc71058bb7a66e957ded188571f8be71a;hpb=8b55f9cad4ddeb1760e21d34474bba55252e442f;p=xonotic%2Fdarkplaces.git diff --git a/sv_phys.c b/sv_phys.c index 77c3bacf..a61bc2f8 100644 --- a/sv_phys.c +++ b/sv_phys.c @@ -1041,12 +1041,12 @@ void SV_CheckVelocity (prvm_edict_t *ent) // for (i=0 ; i<3 ; i++) { - if (PRVM_IS_NAN(PRVM_serveredictvector(ent, velocity)[i])) + if (isnan(PRVM_serveredictvector(ent, velocity)[i])) { Con_Printf("Got a NaN velocity on entity #%i (%s)\n", PRVM_NUM_FOR_EDICT(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname))); PRVM_serveredictvector(ent, velocity)[i] = 0; } - if (PRVM_IS_NAN(PRVM_serveredictvector(ent, origin)[i])) + if (isnan(PRVM_serveredictvector(ent, origin)[i])) { Con_Printf("Got a NaN origin on entity #%i (%s)\n", PRVM_NUM_FOR_EDICT(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname))); PRVM_serveredictvector(ent, origin)[i] = 0; @@ -1112,15 +1112,18 @@ static qbool SV_RunThink (prvm_edict_t *ent) SV_Impact Two entities have touched, so run their touch functions +Returns true if the push did not result in the entity being teleported by QC code. ================== */ -static void SV_Impact (prvm_edict_t *e1, trace_t *trace) +static qbool SV_Impact (prvm_edict_t *e1, trace_t *trace) { prvm_prog_t *prog = SVVM_prog; int restorevm_tempstringsbuf_cursize; int old_self, old_other; prvm_edict_t *e2 = (prvm_edict_t *)trace->ent; + e1->priv.required->mark = PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN; // -2: setorigin running + old_self = PRVM_serverglobaledict(self); old_other = PRVM_serverglobaledict(other); restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize; @@ -1154,6 +1157,22 @@ static void SV_Impact (prvm_edict_t *e1, trace_t *trace) PRVM_serverglobaledict(self) = old_self; PRVM_serverglobaledict(other) = old_other; prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize; + + if(e1->priv.required->mark == PRVM_EDICT_MARK_SETORIGIN_CAUGHT) + { + e1->priv.required->mark = 0; + return false; + } + else if(e1->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN) + { + e1->priv.required->mark = 0; + return true; + } + else + { + Con_Printf(CON_ERROR "The edict mark had been overwritten! Please debug this.\n"); + return true; + } } @@ -1194,13 +1213,12 @@ 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 qbool SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, qbool dolink, qbool checkstuck); +static qbool SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, qbool dotouch, qbool checkstuck); #define MAX_CLIP_PLANES 5 static int SV_FlyMove (prvm_edict_t *ent, float time, qbool applygravity, float *stepnormal, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, float stepheight) { prvm_prog_t *prog = SVVM_prog; - int blocked, bumpcount; - int i, j, numplanes; + unsigned int i, j, numplanes, blocked, bumpcount; float d, time_left, gravity; vec3_t dir, push, planes[MAX_CLIP_PLANES]; prvm_vec3_t primal_velocity, original_velocity, new_velocity, restore_velocity; @@ -1238,7 +1256,7 @@ static int SV_FlyMove (prvm_edict_t *ent, float time, qbool applygravity, float break; VectorScale(PRVM_serveredictvector(ent, velocity), time_left, push); - if(!SV_PushEntity(&trace, ent, push, false, true)) + if(!SV_PushEntity(&trace, ent, push, sv_gameplayfix_impactbeforeonground.integer, true)) { // we got teleported by a touch function // let's abort the move @@ -1248,7 +1266,7 @@ static int SV_FlyMove (prvm_edict_t *ent, float time, qbool applygravity, float // this code is used by MOVETYPE_WALK and MOVETYPE_STEP and SV_UnstickEntity // abort move if we're stuck in the world (and didn't make it out) - if (trace.worldstartsolid && trace.allsolid && trace.startdepth < 0) + if (trace.worldstartsolid && trace.allsolid) { VectorCopy(restore_velocity, PRVM_serveredictvector(ent, velocity)); return 3; @@ -1333,12 +1351,19 @@ static int SV_FlyMove (prvm_edict_t *ent, float time, qbool applygravity, float VectorCopy(trace.plane.normal, stepnormal); } - // Unlike some other movetypes Quake's SV_FlyMove calls SV_Impact only after setting ONGROUND which id1 fiends rely on. - // If we stepped up (sv_gameplayfix_stepmultipletimes) this will impact the steptrace2 plane instead of the original. - if (PRVM_serveredictfloat(ent, solid) >= SOLID_TRIGGER && trace.ent) - SV_Impact(ent, &trace); - if (ent->free) - return blocked; // removed by the impact function + if (!sv_gameplayfix_impactbeforeonground.integer) + { + // Unlike some other movetypes Quake's SV_FlyMove calls SV_Impact only after setting ONGROUND which id1 fiends rely on. + // If we stepped up (sv_gameplayfix_stepmultipletimes) this will impact the steptrace2 plane instead of the original. + if (PRVM_serveredictfloat(ent, solid) >= SOLID_TRIGGER && trace.ent) + if (!SV_Impact(ent, &trace)) + { + blocked |= 8; + break; + } + if (ent->free) + return blocked; // removed by the impact function + } if (trace.fraction >= 0.001) { @@ -1560,7 +1585,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 qbool SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, qbool dolink, qbool checkstuck) +static qbool SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, qbool dotouch, qbool checkstuck) { prvm_prog_t *prog = SVVM_prog; int solid; @@ -1588,41 +1613,21 @@ static qbool SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, qboo type = MOVE_NORMAL; *trace = SV_TraceBox(start, mins, maxs, end, type, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value); - // abort move if we're stuck in the world (and didn't make it out) - if (trace->worldstartsolid && trace->allsolid && trace->startdepth < 0 && checkstuck) + if (trace->allsolid && checkstuck) { - // checking startdepth eliminates many false positives on Q1BSP with mod_q1bsp_polygoncollisions 0 - // but it's still not guaranteed that we're stuck in a bmodel at this point - if (sv_gameplayfix_nudgeoutofsolid.integer && sv_gameplayfix_nudgeoutofsolid_separation.value >= 0) + if (SV_UnstickEntity(ent)) { - switch (PHYS_NudgeOutOfSolid(prog, ent)) - { - case 0: - Con_Printf(CON_WARN "NudgeOutOfSolid couldn't fix stuck entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname))); - return true; // definitely stuck in a bmodel - case 1: - Con_DPrintf("NudgeOutOfSolid fixed stuck entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)), PRVM_serveredictvector(ent, origin)[0] - start[0], PRVM_serveredictvector(ent, origin)[1] - start[1], PRVM_serveredictvector(ent, origin)[2] - start[2]); - VectorCopy(PRVM_serveredictvector(ent, origin), start); - VectorAdd(start, push, end); - *trace = SV_TraceBox(start, mins, maxs, end, type, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value); - - // definitely not stuck in a bmodel, move may proceed - } - } - else if (sv_gameplayfix_unstickentities.integer && SV_UnstickEntity(ent)) - { - // bones_was_here: pretty sure we can deprecate sv_gameplayfix_unstickentities, sv_gameplayfix_nudgeoutofsolid is much nicer VectorCopy(PRVM_serveredictvector(ent, origin), start); VectorAdd(start, push, end); *trace = SV_TraceBox(start, mins, maxs, end, type, ent, SV_GenericHitSuperContentsMask(ent), 0, 0, collision_extendmovelength.value); } - else - return true; // assuming stuck, bones_was_here TODO: always use PHYS_NudgeOutOfSolid (remove sv_gameplayfix_nudgeoutofsolid)? + // abort move if we're stuck in the world (and didn't make it out) + else if (trace->worldstartsolid) + return true; } VectorCopy(trace->endpos, PRVM_serveredictvector(ent, origin)); - - ent->priv.required->mark = PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN; // -2: setorigin running + VectorCopy(trace->endpos, PRVM_serveredictvector(ent, oldorigin)); // for SV_UnstickEntity() SV_LinkEdict(ent); @@ -1634,29 +1639,15 @@ static qbool SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, qboo } #endif - if (dolink) + if (dotouch) { SV_LinkEdict_TouchAreaGrid(ent); if((PRVM_serveredictfloat(ent, solid) >= SOLID_TRIGGER && trace->ent && (!((int)PRVM_serveredictfloat(ent, flags) & FL_ONGROUND) || PRVM_serveredictedict(ent, groundentity) != PRVM_EDICT_TO_PROG(trace->ent)))) - SV_Impact (ent, trace); + return SV_Impact (ent, trace); } - if(ent->priv.required->mark == PRVM_EDICT_MARK_SETORIGIN_CAUGHT) - { - ent->priv.required->mark = 0; - return false; - } - else if(ent->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN) - { - ent->priv.required->mark = 0; - return true; - } - else - { - Con_Printf("The edict mark had been overwritten! Please debug this.\n"); - return true; - } + return true; } @@ -2035,9 +2026,10 @@ static float unstickoffsets[] = typedef enum unstickresult_e { + // matching the DP_QC_NUDGEOUTOFSOLID return values UNSTICK_STUCK = 0, - UNSTICK_GOOD = 1, - UNSTICK_UNSTUCK = 2 + UNSTICK_GOOD = -1, ///< didn't need to be unstuck + UNSTICK_UNSTUCK = 1 } unstickresult_t; @@ -2055,8 +2047,6 @@ static unstickresult_t SV_UnstickEntityReturnOffset (prvm_edict_t *ent, vec3_t o if (!SV_TestEntityPosition(ent, unstickoffsets + i)) { VectorCopy(unstickoffsets + i, offset); - SV_LinkEdict(ent); - //SV_LinkEdict_TouchAreaGrid(ent); return UNSTICK_UNSTUCK; } } @@ -2069,44 +2059,15 @@ static unstickresult_t SV_UnstickEntityReturnOffset (prvm_edict_t *ent, vec3_t o VectorClear(offset); offset[2] = -i; if (!SV_TestEntityPosition(ent, offset)) - { - SV_LinkEdict(ent); - //SV_LinkEdict_TouchAreaGrid(ent); return UNSTICK_UNSTUCK; - } offset[2] = i; if (!SV_TestEntityPosition(ent, offset)) - { - SV_LinkEdict(ent); - //SV_LinkEdict_TouchAreaGrid(ent); return UNSTICK_UNSTUCK; - } } return UNSTICK_STUCK; } -qbool SV_UnstickEntity (prvm_edict_t *ent) -{ - prvm_prog_t *prog = SVVM_prog; - vec3_t offset; - switch(SV_UnstickEntityReturnOffset(ent, offset)) - { - case UNSTICK_GOOD: - return true; - case UNSTICK_UNSTUCK: - Con_DPrintf("Unstuck entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)), offset[0], offset[1], offset[2]); - return true; - case UNSTICK_STUCK: - if (developer_extra.integer) - Con_DPrintf("Stuck entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname))); - return false; - default: - Con_Printf("SV_UnstickEntityReturnOffset returned a value outside its enum.\n"); - return false; - } -} - /* ============= SV_CheckStuck @@ -2115,32 +2076,54 @@ This is a big hack to try and fix the rare case of getting stuck in the world clipping hull. ============= */ -static void SV_CheckStuck (prvm_edict_t *ent) +qbool SV_UnstickEntity (prvm_edict_t *ent) { prvm_prog_t *prog = SVVM_prog; vec3_t offset; + if (sv_gameplayfix_nudgeoutofsolid.integer && sv_gameplayfix_nudgeoutofsolid_separation.value >= 0 + && sv.worldmodel->TraceBox == Mod_CollisionBIH_TraceBox) // Mod_Q1BSP_TraceBox doesn't support startdepth + { + VectorCopy(PRVM_serveredictvector(ent, origin), offset); + switch (PHYS_NudgeOutOfSolid(prog, ent)) + { + case UNSTICK_GOOD: + return true; + case UNSTICK_UNSTUCK: + VectorSubtract(PRVM_serveredictvector(ent, origin), offset, offset); + Con_DPrintf("NudgeOutOfSolid fixed stuck entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)), offset[0], offset[1], offset[2]); + return true; + case UNSTICK_STUCK: + Con_DPrintf(CON_WARN "NudgeOutOfSolid couldn't fix stuck entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname))); + return false; + default: + Con_Printf("NudgeOutOfSolid returned a value outside its enum.\n"); + return false; + } + } + + if (!(PRVM_NUM_FOR_EDICT(ent) <= svs.maxclients ? sv_gameplayfix_unstickplayers : sv_gameplayfix_unstickentities).integer) + return false; + switch(SV_UnstickEntityReturnOffset(ent, offset)) { case UNSTICK_GOOD: - VectorCopy (PRVM_serveredictvector(ent, origin), PRVM_serveredictvector(ent, oldorigin)); - break; + return true; case UNSTICK_UNSTUCK: - Con_DPrintf("Unstuck player entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)), offset[0], offset[1], offset[2]); - break; + Con_DPrintf("Unstuck entity %i (classname \"%s\") with offset %f %f %f.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname)), offset[0], offset[1], offset[2]); + return true; case UNSTICK_STUCK: VectorSubtract(PRVM_serveredictvector(ent, oldorigin), PRVM_serveredictvector(ent, origin), offset); if (!SV_TestEntityPosition(ent, offset)) { - Con_DPrintf("Unstuck player entity %i (classname \"%s\") by restoring oldorigin.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname))); - SV_LinkEdict(ent); - //SV_LinkEdict_TouchAreaGrid(ent); + Con_DPrintf("Unstuck entity %i (classname \"%s\") by restoring oldorigin.\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname))); + return true; } - else - Con_DPrintf("Stuck player entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname))); - break; + Con_DPrintf(CON_WARN "Stuck entity %i (classname \"%s\").\n", (int)PRVM_EDICT_TO_PROG(ent), PRVM_GetString(prog, PRVM_serveredictstring(ent, classname))); + return false; default: Con_Printf("SV_UnstickEntityReturnOffset returned a value outside its enum.\n"); + return false; } } @@ -2311,9 +2294,6 @@ static void SV_WalkMove (prvm_edict_t *ent) if (sv.frametime <= 0) return; - if (sv_gameplayfix_unstickplayers.integer) - SV_CheckStuck (ent); - applygravity = !SV_CheckWater (ent) && PRVM_serveredictfloat(ent, movetype) == MOVETYPE_WALK && ! ((int)PRVM_serveredictfloat(ent, flags) & FL_WATERJUMP); SV_CheckVelocity(ent);