X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;ds=sidebyside;f=sv_phys.c;h=7b9d705a4bd3d4270c549774fb6df9c9be38157e;hb=152cd461f194a0c4b3e81fce9d75744e322eab12;hp=9c8b532b111ed547aee40bacc962a7e68de41328;hpb=f1f0ca1dc12483e48e70b763479e6b7e517a1e1f;p=xonotic%2Fdarkplaces.git diff --git a/sv_phys.c b/sv_phys.c index 9c8b532b..7b9d705a 100644 --- a/sv_phys.c +++ b/sv_phys.c @@ -919,7 +919,7 @@ static int SV_TestEntityPosition (prvm_edict_t *ent, vec3_t offset) trace_t trace; contents = SV_GenericHitSuperContentsMask(ent); VectorAdd(PRVM_serveredictvector(ent, origin), offset, org); - trace = SV_TraceBox(org, PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), PRVM_serveredictvector(ent, origin), MOVE_NOMONSTERS, ent, contents); + trace = SV_TraceBox(org, PRVM_serveredictvector(ent, mins), PRVM_serveredictvector(ent, maxs), PRVM_serveredictvector(ent, origin), ((PRVM_serveredictfloat(ent, movetype) == MOVETYPE_FLY_WORLDONLY) ? MOVE_WORLDONLY : MOVE_NOMONSTERS), ent, contents); if (trace.startsupercontents & contents) return true; else @@ -987,7 +987,8 @@ void SV_CheckAllEnts (void) if (PRVM_serveredictfloat(check, movetype) == MOVETYPE_PUSH || PRVM_serveredictfloat(check, movetype) == MOVETYPE_NONE || PRVM_serveredictfloat(check, movetype) == MOVETYPE_FOLLOW - || PRVM_serveredictfloat(check, movetype) == MOVETYPE_NOCLIP) + || PRVM_serveredictfloat(check, movetype) == MOVETYPE_NOCLIP + || PRVM_serveredictfloat(check, movetype) == MOVETYPE_FLY_WORLDONLY) continue; if (SV_TestEntityPosition (check, vec3_origin)) @@ -1449,6 +1450,120 @@ PUSHMOVE =============================================================================== */ +static qboolean SV_NudgeOutOfSolid_PivotIsKnownGood(prvm_edict_t *ent, vec3_t pivot) +{ + int bump; + trace_t stucktrace; + vec3_t stuckorigin; + vec3_t stuckmins, stuckmaxs; + vec3_t goodmins, goodmaxs; + vec3_t testorigin; + vec_t nudge; + vec3_t move; + VectorCopy(PRVM_serveredictvector(ent, origin), stuckorigin); + VectorCopy(PRVM_serveredictvector(ent, mins), stuckmins); + VectorCopy(PRVM_serveredictvector(ent, maxs), stuckmaxs); + VectorCopy(pivot, goodmins); + VectorCopy(pivot, goodmaxs); + for (bump = 0;bump < 6;bump++) + { + int coord = 2-(bump >> 1); + //int coord = (bump >> 1); + int dir = (bump & 1); + int subbump; + + for(subbump = 0; ; ++subbump) + { + VectorCopy(stuckorigin, testorigin); + if(dir) + { + // pushing maxs + testorigin[coord] += stuckmaxs[coord] - goodmaxs[coord]; + } + else + { + // pushing mins + testorigin[coord] += stuckmins[coord] - goodmins[coord]; + } + + stucktrace = SV_TraceBox(stuckorigin, goodmins, goodmaxs, testorigin, MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent)); + if (stucktrace.bmodelstartsolid) + { + // BAD BAD, can't fix that + return false; + } + + if (stucktrace.fraction >= 1) + break; // it WORKS! + + if(subbump >= 10) + { + // BAD BAD, can't fix that + return false; + } + + // we hit something... let's move out of it + VectorSubtract(stucktrace.endpos, testorigin, move); + nudge = DotProduct(stucktrace.plane.normal, move) + 0.03125f; // FIXME cvar this constant + VectorMA(stuckorigin, nudge, stucktrace.plane.normal, stuckorigin); + } + /* + if(subbump > 0) + Con_Printf("subbump: %d\n", subbump); + */ + + if(dir) + { + // pushing maxs + goodmaxs[coord] = stuckmaxs[coord]; + } + else + { + // pushing mins + goodmins[coord] = stuckmins[coord]; + } + } + + // WE WIN + VectorCopy(stuckorigin, PRVM_serveredictvector(ent, origin)); + + return true; +} + +static qboolean SV_NudgeOutOfSolid(prvm_edict_t *ent) +{ + int bump; + trace_t stucktrace; + vec3_t stuckorigin; + vec3_t stuckmins, stuckmaxs; + vec_t nudge; + 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; + stuckmins[1] -= separation; + stuckmins[2] -= separation; + stuckmaxs[0] += separation; + stuckmaxs[1] += separation; + stuckmaxs[2] += separation; + for (bump = 0;bump < 10;bump++) + { + stucktrace = SV_TraceBox(stuckorigin, stuckmins, stuckmaxs, stuckorigin, 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); + } + return false; +} + /* ============ SV_PushEntity @@ -1463,7 +1578,6 @@ static qboolean SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, q int solid; int movetype; int type; - int bump; vec3_t mins, maxs; vec3_t original, original_velocity; vec3_t start; @@ -1477,34 +1591,7 @@ static qboolean SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, q // move start position out of solids if (sv_gameplayfix_nudgeoutofsolid.integer && sv_gameplayfix_nudgeoutofsolid_separation.value >= 0) { - trace_t stucktrace; - vec3_t stuckorigin; - vec3_t stuckmins, stuckmaxs; - vec_t nudge; - 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(mins, stuckmins); - VectorCopy(maxs, stuckmaxs); - stuckmins[0] -= separation; - stuckmins[1] -= separation; - stuckmins[2] -= separation; - stuckmaxs[0] += separation; - stuckmaxs[1] += separation; - stuckmaxs[2] += separation; - for (bump = 0;bump < 10;bump++) - { - stucktrace = SV_TraceBox(stuckorigin, stuckmins, stuckmaxs, stuckorigin, MOVE_NOMONSTERS, ent, SV_GenericHitSuperContentsMask(ent)); - if (!stucktrace.bmodelstartsolid || stucktrace.startdepth >= 0) - { - // found a good location, use it - VectorCopy(stuckorigin, PRVM_serveredictvector(ent, origin)); - break; - } - nudge = -stucktrace.startdepth; - VectorMA(stuckorigin, nudge, stucktrace.startdepthnormal, stuckorigin); - } + SV_NudgeOutOfSolid(ent); } VectorCopy(PRVM_serveredictvector(ent, origin), start); @@ -1512,6 +1599,8 @@ static qboolean SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, q if (movetype == MOVETYPE_FLYMISSILE) type = MOVE_MISSILE; + else if (movetype == MOVETYPE_FLY_WORLDONLY) + type = MOVE_WORLDONLY; else if (solid == SOLID_TRIGGER || solid == SOLID_NOT) type = MOVE_NOMONSTERS; // only clip against bmodels else @@ -1567,6 +1656,7 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) trace_t trace, trace2; matrix4x4_t pusherfinalmatrix, pusherfinalimatrix; static unsigned short moved_edicts[MAX_EDICTS]; + vec3_t pivot; if (!PRVM_serveredictvector(pusher, velocity)[0] && !PRVM_serveredictvector(pusher, velocity)[1] && !PRVM_serveredictvector(pusher, velocity)[2] && !PRVM_serveredictvector(pusher, avelocity)[0] && !PRVM_serveredictvector(pusher, avelocity)[1] && !PRVM_serveredictvector(pusher, avelocity)[2]) { @@ -1684,7 +1774,10 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) // see if any solid entities are inside the final position num_moved = 0; - numcheckentities = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, checkentities); + if (PRVM_serveredictfloat(pusher, movetype) == MOVETYPE_FAKEPUSH) // Tenebrae's MOVETYPE_PUSH variant that doesn't push... + numcheckentities = 0; + else // MOVETYPE_PUSH + numcheckentities = World_EntitiesInBox(&sv.world, mins, maxs, MAX_EDICTS, checkentities); for (e = 0;e < numcheckentities;e++) { prvm_edict_t *check = checkentities[e]; @@ -1695,7 +1788,7 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) case MOVETYPE_PUSH: case MOVETYPE_FOLLOW: case MOVETYPE_NOCLIP: - case MOVETYPE_FAKEPUSH: + case MOVETYPE_FLY_WORLDONLY: continue; default: break; @@ -1728,10 +1821,14 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) } } + VectorLerp(PRVM_serveredictvector(check, mins), 0.5f, PRVM_serveredictvector(check, maxs), pivot); + //VectorClear(pivot); + if (rotated) { vec3_t org2; VectorSubtract (PRVM_serveredictvector(check, origin), PRVM_serveredictvector(pusher, origin), org); + VectorAdd (org, pivot, org); org2[0] = DotProduct (org, forward); org2[1] = DotProduct (org, left); org2[2] = DotProduct (org, up); @@ -1780,72 +1877,55 @@ void SV_PushMove (prvm_edict_t *pusher, float movetime) Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, PRVM_serveredictvector(pusher, mins), PRVM_serveredictvector(pusher, maxs), SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, PRVM_serveredictvector(check, origin), PRVM_serveredictvector(check, mins), PRVM_serveredictvector(check, maxs), PRVM_serveredictvector(check, origin), checkcontents); if (trace.startsolid) { - // try moving the contacted entity a tiny bit further to account for precision errors vec3_t move2; - PRVM_serveredictfloat(pusher, solid) = SOLID_NOT; - VectorScale(move, 1.1, move2); - VectorCopy (check->priv.server->moved_from, PRVM_serveredictvector(check, origin)); - VectorCopy (check->priv.server->moved_fromangles, PRVM_serveredictvector(check, angles)); - if(!SV_PushEntity (&trace2, check, move2, true, true)) - { - // entity "check" got teleported - continue; - } - PRVM_serveredictfloat(pusher, solid) = savesolid; - Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, PRVM_serveredictvector(pusher, mins), PRVM_serveredictvector(pusher, maxs), SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, PRVM_serveredictvector(check, origin), PRVM_serveredictvector(check, mins), PRVM_serveredictvector(check, maxs), PRVM_serveredictvector(check, origin), checkcontents); - if (trace.startsolid) + if(SV_NudgeOutOfSolid_PivotIsKnownGood(check, pivot)) { - // try moving the contacted entity a tiny bit less to account for precision errors - PRVM_serveredictfloat(pusher, solid) = SOLID_NOT; - VectorScale(move, 0.9, move2); - VectorCopy (check->priv.server->moved_from, PRVM_serveredictvector(check, origin)); - VectorCopy (check->priv.server->moved_fromangles, PRVM_serveredictvector(check, angles)); - if(!SV_PushEntity (&trace2, check, move2, true, true)) + // hack to invoke all necessary movement triggers + VectorClear(move2); + if(!SV_PushEntity(&trace2, check, move2, true, true)) { // entity "check" got teleported continue; } - PRVM_serveredictfloat(pusher, solid) = savesolid; - Collision_ClipToGenericEntity(&trace, pushermodel, pusher->priv.server->frameblend, &pusher->priv.server->skeleton, PRVM_serveredictvector(pusher, mins), PRVM_serveredictvector(pusher, maxs), SUPERCONTENTS_BODY, &pusherfinalmatrix, &pusherfinalimatrix, PRVM_serveredictvector(check, origin), PRVM_serveredictvector(check, mins), PRVM_serveredictvector(check, maxs), PRVM_serveredictvector(check, origin), checkcontents); - if (trace.startsolid) - { - // still inside pusher, so it's really blocked - - // fail the move - if (PRVM_serveredictvector(check, mins)[0] == PRVM_serveredictvector(check, maxs)[0]) - continue; - if (PRVM_serveredictfloat(check, solid) == SOLID_NOT || PRVM_serveredictfloat(check, solid) == SOLID_TRIGGER) - { - // corpse - PRVM_serveredictvector(check, mins)[0] = PRVM_serveredictvector(check, mins)[1] = 0; - VectorCopy (PRVM_serveredictvector(check, mins), PRVM_serveredictvector(check, maxs)); - continue; - } - - VectorCopy (pushorig, PRVM_serveredictvector(pusher, origin)); - VectorCopy (pushang, PRVM_serveredictvector(pusher, angles)); - PRVM_serveredictfloat(pusher, ltime) = pushltime; - SV_LinkEdict(pusher); - - // move back any entities we already moved - for (i = 0;i < num_moved;i++) - { - prvm_edict_t *ed = PRVM_EDICT_NUM(moved_edicts[i]); - VectorCopy (ed->priv.server->moved_from, PRVM_serveredictvector(ed, origin)); - VectorCopy (ed->priv.server->moved_fromangles, PRVM_serveredictvector(ed, angles)); - SV_LinkEdict(ed); - } - - // if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone - if (PRVM_serveredictfunction(pusher, blocked)) - { - PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(pusher); - PRVM_serverglobaledict(other) = PRVM_EDICT_TO_PROG(check); - PRVM_ExecuteProgram (PRVM_serveredictfunction(pusher, blocked), "QC function self.blocked is missing"); - } - break; - } + // we could fix it + continue; + } + + // still inside pusher, so it's really blocked + + // fail the move + if (PRVM_serveredictvector(check, mins)[0] == PRVM_serveredictvector(check, maxs)[0]) + continue; + if (PRVM_serveredictfloat(check, solid) == SOLID_NOT || PRVM_serveredictfloat(check, solid) == SOLID_TRIGGER) + { + // corpse + PRVM_serveredictvector(check, mins)[0] = PRVM_serveredictvector(check, mins)[1] = 0; + VectorCopy (PRVM_serveredictvector(check, mins), PRVM_serveredictvector(check, maxs)); + continue; } + + VectorCopy (pushorig, PRVM_serveredictvector(pusher, origin)); + VectorCopy (pushang, PRVM_serveredictvector(pusher, angles)); + PRVM_serveredictfloat(pusher, ltime) = pushltime; + SV_LinkEdict(pusher); + + // move back any entities we already moved + for (i = 0;i < num_moved;i++) + { + prvm_edict_t *ed = PRVM_EDICT_NUM(moved_edicts[i]); + VectorCopy (ed->priv.server->moved_from, PRVM_serveredictvector(ed, origin)); + VectorCopy (ed->priv.server->moved_fromangles, PRVM_serveredictvector(ed, angles)); + SV_LinkEdict(ed); + } + + // if the pusher has a "blocked" function, call it, otherwise just stay in place until the obstacle is gone + if (PRVM_serveredictfunction(pusher, blocked)) + { + PRVM_serverglobaledict(self) = PRVM_EDICT_TO_PROG(pusher); + PRVM_serverglobaledict(other) = PRVM_EDICT_TO_PROG(check); + PRVM_ExecuteProgram (PRVM_serveredictfunction(pusher, blocked), "QC function self.blocked is missing"); + } + break; } } PRVM_serveredictvector(pusher, angles)[0] -= 360.0 * floor(PRVM_serveredictvector(pusher, angles)[0] * (1.0 / 360.0)); @@ -2210,6 +2290,8 @@ void SV_WalkMove (prvm_edict_t *ent) VectorSet(downmove, PRVM_serveredictvector(ent, origin)[0], PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2] - 1); if (PRVM_serveredictfloat(ent, movetype) == MOVETYPE_FLYMISSILE) type = MOVE_MISSILE; + else if (PRVM_serveredictfloat(ent, movetype) == MOVETYPE_FLY_WORLDONLY) + type = MOVE_WORLDONLY; else if (PRVM_serveredictfloat(ent, solid) == SOLID_TRIGGER || PRVM_serveredictfloat(ent, solid) == SOLID_NOT) type = MOVE_NOMONSTERS; // only clip against bmodels else @@ -2440,7 +2522,7 @@ void SV_CheckWaterTransition (prvm_edict_t *ent) { // Contents Transition Function Invalid; Potentially Play Water Sound // check if the entity crossed into or out of water if (sv_sound_watersplash.string && ((PRVM_serveredictfloat(ent, watertype) == CONTENTS_WATER || PRVM_serveredictfloat(ent, watertype) == CONTENTS_SLIME) != (cont == CONTENTS_WATER || cont == CONTENTS_SLIME))) - SV_StartSound (ent, 0, sv_sound_watersplash.string, 255, 1); + SV_StartSound (ent, 0, sv_sound_watersplash.string, 255, 1, false); } if (cont <= CONTENTS_WATER) @@ -2683,7 +2765,7 @@ void SV_Physics_Step (prvm_edict_t *ent) else // Check for Engine Landing Sound if(sv_sound_land.string) - SV_StartSound(ent, 0, sv_sound_land.string, 255, 1); + SV_StartSound(ent, 0, sv_sound_land.string, 255, 1, false); } ent->priv.server->waterposition_forceupdate = true; } @@ -2750,6 +2832,7 @@ static void SV_Physics_Entity (prvm_edict_t *ent) case MOVETYPE_BOUNCEMISSILE: case MOVETYPE_FLYMISSILE: case MOVETYPE_FLY: + case MOVETYPE_FLY_WORLDONLY: // regular thinking if (SV_RunThink (ent)) SV_Physics_Toss (ent); @@ -2922,6 +3005,7 @@ static void SV_Physics_ClientEntity(prvm_edict_t *ent) SV_Physics_Toss (ent); break; case MOVETYPE_FLY: + case MOVETYPE_FLY_WORLDONLY: SV_RunThink (ent); SV_WalkMove (ent); break;