X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=sv_phys.c;h=a69f278321db9405436d3d41f3af1a2974812875;hb=c9a3ad45ef5f5c6958d9410c7caae4e3b2ad27fc;hp=e031f19e6e5074e28db9f6bcd4295df7efaf1eeb;hpb=97d61bec83f6475e58128ac915c50d013b8fec48;p=xonotic%2Fdarkplaces.git diff --git a/sv_phys.c b/sv_phys.c index e031f19e..a69f2783 100644 --- a/sv_phys.c +++ b/sv_phys.c @@ -247,16 +247,35 @@ int SV_FlyMove (edict_t *ent, float time, float *stepnormal) VectorMA(ent->v->origin, time, ent->v->velocity, end); trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent); //Con_Printf("trace %f %f %f : %f : %f %f %f\n", trace.endpos[0], trace.endpos[1], trace.endpos[2], trace.fraction, trace.plane.normal[0], trace.plane.normal[1], trace.plane.normal[2]); +#if COLLISIONPARANOID >= 1 + { + int endstuck; + vec3_t temp; + VectorCopy(trace.endpos, temp); + endstuck = SV_Move(temp, ent->v->mins, ent->v->maxs, temp, MOVE_WORLDONLY, ent).startsolid; +#if COLLISIONPARANOID < 2 + if (trace.startsolid || endstuck) +#endif + { + Con_Printf("%s{e%i:%i:%f %f %f:%f %f %f:%f:%f %f %f%s%s}\n", (trace.startsolid || endstuck) ? "\002" : "", ent - sv.edicts, bumpcount, ent->v->origin[0], ent->v->origin[1], ent->v->origin[2], end[0] - ent->v->origin[0], end[1] - ent->v->origin[1], end[2] - ent->v->origin[2], trace.fraction, trace.endpos[0] - ent->v->origin[0], trace.endpos[1] - ent->v->origin[1], trace.endpos[2] - ent->v->origin[2], trace.startsolid ? " startstuck" : "", endstuck ? " endstuck" : ""); + //Con_Printf("trace %f %f %f : %f : %f %f %f\n", trace.endpos[0], trace.endpos[1], trace.endpos[2], trace.fraction, trace.plane.normal[0], trace.plane.normal[1], trace.plane.normal[2]); + if (endstuck) + Cbuf_AddText("disconnect\n"); + } + } +#endif - if (trace.allsolid) + /* + if (trace.startsolid) { // LordHavoc: note: this code is what makes entities stick in place if embedded in another object (which can be the world) // entity is trapped in another solid VectorClear(ent->v->velocity); return 3; } + */ - if (trace.fraction > 0) + if (trace.fraction >= 0.001) { // actually covered some distance VectorCopy (trace.endpos, ent->v->origin); @@ -341,13 +360,15 @@ int SV_FlyMove (edict_t *ent, float time, float *stepnormal) trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent); - if (trace.allsolid) + /* + if (trace.startsolid) { // LordHavoc: note: this code is what makes entities stick in place if embedded in another object (which can be the world) // entity is trapped in another solid VectorClear(ent->v->velocity); return 3; } + */ if (trace.fraction > 0) { @@ -515,13 +536,30 @@ trace_t SV_PushEntity (edict_t *ent, vec3_t push, vec3_t pushangles) trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NOMONSTERS, ent); else trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent); +#if COLLISIONPARANOID >= 1 + { + int endstuck; + vec3_t temp; + VectorCopy(trace.endpos, temp); + endstuck = SV_Move(temp, ent->v->mins, ent->v->maxs, temp, MOVE_WORLDONLY, ent).startsolid; +#if COLLISIONPARANOID < 2 + if (trace.startsolid || endstuck) +#endif + { + Con_Printf("%s{e%i:%f %f %f:%f %f %f:%f:%f %f %f%s%s}\n", (trace.startsolid || endstuck) ? "\002" : "", ent - sv.edicts, ent->v->origin[0], ent->v->origin[1], ent->v->origin[2], end[0] - ent->v->origin[0], end[1] - ent->v->origin[1], end[2] - ent->v->origin[2], trace.fraction, trace.endpos[0] - ent->v->origin[0], trace.endpos[1] - ent->v->origin[1], trace.endpos[2] - ent->v->origin[2], trace.startsolid ? " startstuck" : "", endstuck ? " endstuck" : ""); + //Con_Printf("trace %f %f %f : %f : %f %f %f\n", trace.endpos[0], trace.endpos[1], trace.endpos[2], trace.fraction, trace.plane.normal[0], trace.plane.normal[1], trace.plane.normal[2]); + if (endstuck) + Cbuf_AddText("disconnect\n"); + } + } +#endif VectorCopy (trace.endpos, ent->v->origin); // FIXME: turn players specially ent->v->angles[1] += trace.fraction * pushangles[1]; SV_LinkEdict (ent, true); - if (trace.ent && (!((int)ent->v->flags & FL_ONGROUND) || ent->v->groundentity != EDICT_TO_PROG(trace.ent))) + if (trace.fraction < 1 && trace.ent && (!((int)ent->v->flags & FL_ONGROUND) || ent->v->groundentity != EDICT_TO_PROG(trace.ent))) SV_Impact (ent, trace.ent); return trace; } @@ -542,7 +580,6 @@ void SV_PushMove (edict_t *pusher, float movetime) vec3_t mins, maxs, move, move1, moveangle, pushorig, pushang, a, forward, left, up, org, org2; int num_moved; model_t *pushermodel; - trace_t trace; switch ((int) pusher->v->solid) { @@ -665,12 +702,11 @@ void SV_PushMove (edict_t *pusher, float movetime) || check->v->absmax[2] <= mins[2]) continue; - trace = SV_ClipMoveToEntity (pusher, check->v->origin, check->v->mins, check->v->maxs, check->v->origin); - if (!trace.startsolid) + if (!SV_ClipMoveToEntity(pusher, check->v->origin, check->v->mins, check->v->maxs, check->v->origin).startsolid) continue; } - if (forward[0] < 0.999f) // quick way to check if any rotation is used + if (forward[0] != 1) // quick way to check if any rotation is used { VectorSubtract (check->v->origin, pusher->v->origin, org); org2[0] = DotProduct (org, forward); @@ -692,18 +728,18 @@ void SV_PushMove (edict_t *pusher, float movetime) // try moving the contacted entity pusher->v->solid = SOLID_NOT; - trace = SV_PushEntity (check, move, moveangle); + SV_PushEntity (check, move, moveangle); pusher->v->solid = savesolid; // was SOLID_BSP // if it is still inside the pusher, block - if (SV_TestEntityPosition (check)) + if (SV_ClipMoveToEntity(pusher, check->v->origin, check->v->mins, check->v->maxs, check->v->origin).startsolid) { // try moving the contacted entity a tiny bit further to account for precision errors pusher->v->solid = SOLID_NOT; VectorScale(move, 0.1, move); - trace = SV_PushEntity (check, move, vec3_origin); + SV_PushEntity (check, move, vec3_origin); pusher->v->solid = savesolid; - if (SV_TestEntityPosition (check)) + if (SV_ClipMoveToEntity(pusher, check->v->origin, check->v->mins, check->v->maxs, check->v->origin).startsolid) { // still inside pusher, so it's really blocked @@ -778,10 +814,7 @@ void SV_Physics_Pusher (edict_t *ent) pr_global_struct->self = EDICT_TO_PROG(ent); pr_global_struct->other = EDICT_TO_PROG(sv.edicts); PR_ExecuteProgram (ent->v->think, "NULL think function"); - if (ent->e->free) - return; } - } @@ -857,18 +890,18 @@ qboolean SV_CheckWater (edict_t *ent) ent->v->waterlevel = 0; ent->v->watertype = CONTENTS_EMPTY; - cont = Mod_PointContents(point, sv.worldmodel); + cont = SV_PointQ1Contents(point); if (cont <= CONTENTS_WATER) { ent->v->watertype = cont; ent->v->waterlevel = 1; point[2] = ent->v->origin[2] + (ent->v->mins[2] + ent->v->maxs[2])*0.5; - cont = Mod_PointContents(point, sv.worldmodel); + cont = SV_PointQ1Contents(point); if (cont <= CONTENTS_WATER) { ent->v->waterlevel = 2; point[2] = ent->v->origin[2] + ent->v->view_ofs[2]; - cont = Mod_PointContents(point, sv.worldmodel); + cont = SV_PointQ1Contents(point); if (cont <= CONTENTS_WATER) ent->v->waterlevel = 3; } @@ -889,19 +922,15 @@ void SV_WallFriction (edict_t *ent, float *stepnormal) vec3_t forward, into, side; AngleVectors (ent->v->v_angle, forward, NULL, NULL); - d = DotProduct (stepnormal, forward); - - d += 0.5; - if (d >= 0) - return; - - // cut the tangential velocity - i = DotProduct (stepnormal, ent->v->velocity); - VectorScale (stepnormal, i, into); - VectorSubtract (ent->v->velocity, into, side); - - ent->v->velocity[0] = side[0] * (1 + d); - ent->v->velocity[1] = side[1] * (1 + d); + if ((d = DotProduct (stepnormal, forward) + 0.5) < 0) + { + // cut the tangential velocity + i = DotProduct (stepnormal, ent->v->velocity); + VectorScale (stepnormal, i, into); + VectorSubtract (ent->v->velocity, into, side); + ent->v->velocity[0] = side[0] * (1 + d); + ent->v->velocity[1] = side[1] * (1 + d); + } } /* @@ -949,7 +978,10 @@ int SV_TryUnstick (edict_t *ent, vec3_t oldvel) if (fabs(oldorg[1] - ent->v->origin[1]) > 4 || fabs(oldorg[0] - ent->v->origin[0]) > 4) + { + Con_DPrintf("TryUnstick - success.\n"); return clip; + } // go back to the original pos and try again VectorCopy (oldorg, ent->v->origin); @@ -957,6 +989,7 @@ int SV_TryUnstick (edict_t *ent, vec3_t oldvel) // still not moving VectorClear (ent->v->velocity); + Con_Printf("TryUnstick - failure.\n"); return 7; } @@ -973,6 +1006,8 @@ void SV_WalkMove (edict_t *ent) vec3_t upmove, downmove, oldorg, oldvel, nosteporg, nostepvel, stepnormal; trace_t downtrace; + SV_CheckVelocity(ent); + // do a regular slide move unless it looks like you ran into a step oldonground = (int)ent->v->flags & FL_ONGROUND; ent->v->flags = (int)ent->v->flags & ~FL_ONGROUND; @@ -982,6 +1017,8 @@ void SV_WalkMove (edict_t *ent) clip = SV_FlyMove (ent, sv.frametime, NULL); + SV_CheckVelocity(ent); + // if move didn't block on a step, return if ( !(clip & 2) ) return; @@ -997,10 +1034,9 @@ void SV_WalkMove (edict_t *ent) return; } - if (sv_nostep.integer) - return; + SV_CheckVelocity(ent); - if ( (int)ent->v->flags & FL_WATERJUMP ) + if (sv_nostep.integer || (int)ent->v->flags & FL_WATERJUMP ) return; VectorCopy (ent->v->origin, nosteporg); @@ -1059,83 +1095,8 @@ void SV_WalkMove (edict_t *ent) VectorCopy (nosteporg, ent->v->origin); VectorCopy (nostepvel, ent->v->velocity); } -} - - -/* -================ -SV_Physics_Client - -Player character actions -================ -*/ -void SV_Physics_Client (edict_t *ent, int num) -{ - if (!svs.clients[num-1].active) - return; // unconnected slot - - SV_CheckVelocity (ent); - - // call standard client pre-think - pr_global_struct->time = sv.time; - pr_global_struct->self = EDICT_TO_PROG(ent); - PR_ExecuteProgram (pr_global_struct->PlayerPreThink, "QC function PlayerPreThink is missing"); - - // do a move - SV_CheckVelocity (ent); - - // decide which move function to call - switch ((int)ent->v->movetype) - { - case MOVETYPE_NONE: - if (!SV_RunThink (ent)) - return; - break; - - case MOVETYPE_WALK: - if (!SV_RunThink (ent)) - return; - if (!SV_CheckWater (ent) && ! ((int)ent->v->flags & FL_WATERJUMP) ) - SV_AddGravity (ent); - SV_CheckStuck (ent); - SV_WalkMove (ent); - break; - - case MOVETYPE_TOSS: - case MOVETYPE_BOUNCE: - SV_Physics_Toss (ent); - break; - - case MOVETYPE_FLY: - if (!SV_RunThink (ent)) - return; - SV_CheckWater (ent); - //SV_FlyMove (ent, sv.frametime, NULL); - SV_WalkMove (ent); - break; - - case MOVETYPE_NOCLIP: - if (!SV_RunThink (ent)) - return; - SV_CheckWater (ent); - VectorMA (ent->v->origin, sv.frametime, ent->v->velocity, ent->v->origin); - VectorMA (ent->v->angles, sv.frametime, ent->v->avelocity, ent->v->angles); - break; - - default: - Host_Error ("SV_Physics_client: bad movetype %i", (int)ent->v->movetype); - } - - SV_CheckVelocity (ent); - - // call standard player post-think - SV_LinkEdict (ent, true); - SV_CheckVelocity (ent); - - pr_global_struct->time = sv.time; - pr_global_struct->self = EDICT_TO_PROG(ent); - PR_ExecuteProgram (pr_global_struct->PlayerPostThink, "QC function PlayerPostThink is missing"); + SV_CheckVelocity(ent); } //============================================================================ @@ -1184,25 +1145,6 @@ void SV_Physics_Follow (edict_t *ent) SV_LinkEdict (ent, true); } -/* -============= -SV_Physics_Noclip - -A moving object that doesn't obey physics -============= -*/ -void SV_Physics_Noclip (edict_t *ent) -{ - // regular thinking - if (!SV_RunThink (ent)) - return; - - VectorMA (ent->v->angles, sv.frametime, ent->v->avelocity, ent->v->angles); - VectorMA (ent->v->origin, sv.frametime, ent->v->velocity, ent->v->origin); - - SV_LinkEdict (ent, false); -} - /* ============================================================================== @@ -1220,7 +1162,7 @@ SV_CheckWaterTransition void SV_CheckWaterTransition (edict_t *ent) { int cont; - cont = Mod_PointContents(ent->v->origin, sv.worldmodel); + cont = SV_PointQ1Contents(ent->v->origin); if (!ent->v->watertype) { // just spawned here @@ -1229,23 +1171,19 @@ void SV_CheckWaterTransition (edict_t *ent) return; } + // check if the entity crossed into or out of water + if ((ent->v->watertype == CONTENTS_WATER || ent->v->watertype == CONTENTS_SLIME) != (cont == CONTENTS_WATER || cont == CONTENTS_SLIME)) + SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); + if (cont <= CONTENTS_WATER) { - if (ent->v->watertype == CONTENTS_EMPTY && cont != CONTENTS_LAVA) - // just crossed into water - SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); - ent->v->watertype = cont; ent->v->waterlevel = 1; } else { - if (ent->v->watertype != CONTENTS_EMPTY && ent->v->watertype != CONTENTS_LAVA) - // just crossed into water - SV_StartSound (ent, 0, "misc/h2ohit1.wav", 255, 1); - ent->v->watertype = CONTENTS_EMPTY; - ent->v->waterlevel = cont; + ent->v->waterlevel = 0; } } @@ -1269,7 +1207,6 @@ void SV_Physics_Toss (edict_t *ent) // if onground, return without moving if ((int)ent->v->flags & FL_ONGROUND) { - VectorClear(ent->v->velocity); if (ent->v->groundentity == 0) return; // if ent was supported by a brush model on previous frame, @@ -1366,50 +1303,25 @@ will fall if the floor is pulled out from under them. */ void SV_Physics_Step (edict_t *ent) { - int flags, fall, hitsound; - - // freefall if not fly/swim - fall = true; - flags = (int)ent->v->flags; - if (flags & (FL_FLY | FL_SWIM)) + // freefall if not onground/fly/swim + if (!((int)ent->v->flags & (FL_ONGROUND | FL_FLY | FL_SWIM))) { - if (flags & FL_FLY) - fall = false; - else if ((flags & FL_SWIM) && Mod_PointContents(ent->v->origin, sv.worldmodel) != CONTENTS_EMPTY) - fall = false; - } - if (fall && (flags & FL_ONGROUND) && ent->v->groundentity == 0) - fall = false; + int hitsound = ent->v->velocity[2] < sv_gravity.value * -0.1; - if (fall) - { - if (ent->v->velocity[2] < sv_gravity.value*-0.1) - { - hitsound = true; - if (flags & FL_ONGROUND) - hitsound = false; - } - else - hitsound = false; - - SV_AddGravity (ent); - SV_CheckVelocity (ent); - SV_FlyMove (ent, sv.frametime, NULL); - SV_LinkEdict (ent, false); + SV_AddGravity(ent); + SV_CheckVelocity(ent); + SV_FlyMove(ent, sv.frametime, NULL); + SV_LinkEdict(ent, false); // just hit ground - if ((int)ent->v->flags & FL_ONGROUND) - { - VectorClear(ent->v->velocity); - if (hitsound) - SV_StartSound (ent, 0, "demon/dland2.wav", 255, 1); - } + if (hitsound && (int)ent->v->flags & FL_ONGROUND) + SV_StartSound(ent, 0, "demon/dland2.wav", 255, 1); } // regular thinking - SV_RunThink (ent); + SV_RunThink(ent); - SV_CheckWaterTransition (ent); + SV_CheckWaterTransition(ent); } //============================================================================ @@ -1445,10 +1357,18 @@ void SV_Physics (void) if (i > 0 && i <= svs.maxclients) { - SV_Physics_Client (ent, i); - continue; + if (!svs.clients[i-1].spawned) + continue; + // connected slot + // call standard client pre-think + SV_CheckVelocity (ent); + pr_global_struct->time = sv.time; + pr_global_struct->self = EDICT_TO_PROG(ent); + PR_ExecuteProgram (pr_global_struct->PlayerPreThink, "QC function PlayerPreThink is missing"); + SV_CheckVelocity (ent); } + // LordHavoc: merged client and normal entity physics switch ((int) ent->v->movetype) { case MOVETYPE_PUSH: @@ -1463,12 +1383,19 @@ void SV_Physics (void) SV_Physics_Follow (ent); break; case MOVETYPE_NOCLIP: - SV_Physics_Noclip (ent); + if (SV_RunThink(ent)) + { + SV_CheckWater(ent); + VectorMA(ent->v->origin, sv.frametime, ent->v->velocity, ent->v->origin); + VectorMA(ent->v->angles, sv.frametime, ent->v->avelocity, ent->v->angles); + } + // relink normal entities here, players always get relinked so don't relink twice + if (!(i > 0 && i <= svs.maxclients)) + SV_LinkEdict(ent, false); break; case MOVETYPE_STEP: SV_Physics_Step (ent); break; - // LordHavoc: added support for MOVETYPE_WALK on normal entities! :) case MOVETYPE_WALK: if (SV_RunThink (ent)) { @@ -1482,14 +1409,39 @@ void SV_Physics (void) case MOVETYPE_TOSS: case MOVETYPE_BOUNCE: case MOVETYPE_BOUNCEMISSILE: - case MOVETYPE_FLY: case MOVETYPE_FLYMISSILE: SV_Physics_Toss (ent); break; + case MOVETYPE_FLY: + if (i > 0 && i <= svs.maxclients) + { + if (SV_RunThink (ent)) + { + SV_CheckWater (ent); + SV_WalkMove (ent); + } + } + else + SV_Physics_Toss (ent); + break; default: Host_Error ("SV_Physics: bad movetype %i", (int)ent->v->movetype); break; } + + if (i > 0 && i <= svs.maxclients && !ent->e->free) + { + SV_CheckVelocity (ent); + + // call standard player post-think + SV_LinkEdict (ent, true); + + SV_CheckVelocity (ent); + + pr_global_struct->time = sv.time; + pr_global_struct->self = EDICT_TO_PROG(ent); + PR_ExecuteProgram (pr_global_struct->PlayerPostThink, "QC function PlayerPostThink is missing"); + } } if (pr_global_struct->force_retouch)