X-Git-Url: http://de.git.xonotic.org/?a=blobdiff_plain;f=sv_phys.c;h=fa0101f3dfe59ab7a0b5817530b0c95f6140bb92;hb=af0dcabc0e2b5e187cc9182015b612d5ae4efb0b;hp=909dbb4cbfc8c38e51c0fa6de53a9d3a9d1a9896;hpb=81b4e80a3a74aae7360854ff587be59360d46450;p=xonotic%2Fdarkplaces.git diff --git a/sv_phys.c b/sv_phys.c index 909dbb4c..fa0101f3 100644 --- a/sv_phys.c +++ b/sv_phys.c @@ -155,7 +155,7 @@ qboolean SV_RunThink (edict_t *ent) pr_global_struct->time = thinktime; 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"); + PR_ExecuteProgram (ent->v->think, "QC function self.think is missing"); return !ent->e->free; } @@ -178,14 +178,14 @@ void SV_Impact (edict_t *e1, edict_t *e2) { pr_global_struct->self = EDICT_TO_PROG(e1); pr_global_struct->other = EDICT_TO_PROG(e2); - PR_ExecuteProgram (e1->v->touch, ""); + PR_ExecuteProgram (e1->v->touch, "QC function self.touch is missing"); } if (e2->v->touch && e2->v->solid != SOLID_NOT) { pr_global_struct->self = EDICT_TO_PROG(e2); pr_global_struct->other = EDICT_TO_PROG(e1); - PR_ExecuteProgram (e2->v->touch, ""); + PR_ExecuteProgram (e2->v->touch, "QC function self.touch is missing"); } pr_global_struct->self = old_self; @@ -459,7 +459,7 @@ int SV_FlyMove (edict_t *ent, float time, float *stepnormal) ent->v->groundentity = EDICT_TO_PROG(hackongroundentity); } */ - + /* if ((blocked & 1) == 0 && bumpcount > 1) { @@ -471,6 +471,22 @@ int SV_FlyMove (edict_t *ent, float time, float *stepnormal) return blocked; } +int SV_SetOnGround (edict_t *ent) +{ + vec3_t end; + trace_t trace; + if ((int)ent->v->flags & FL_ONGROUND) + return 1; + VectorSet(end, ent->v->origin[0], ent->v->origin[1], ent->v->origin[2] - 1); + trace = SV_Move(ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent); + if (trace.fraction < 1 && trace.plane.normal[2] >= 0.7) + { + ent->v->flags = (int)ent->v->flags | FL_ONGROUND; + ent->v->groundentity = EDICT_TO_PROG(trace.ent); + return 1; + } + return 0; +} /* ============ @@ -507,24 +523,24 @@ SV_PushEntity Does not change the entities velocity at all ============ */ -trace_t SV_PushEntity (edict_t *ent, vec3_t push, vec3_t pushangles) +trace_t SV_PushEntity (edict_t *ent, vec3_t push) { + int type; trace_t trace; vec3_t end; VectorAdd (ent->v->origin, push, end); if (ent->v->movetype == MOVETYPE_FLYMISSILE) - trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_MISSILE, ent); + type = MOVE_MISSILE; else if (ent->v->solid == SOLID_TRIGGER || ent->v->solid == SOLID_NOT) - // only clip against bmodels - trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NOMONSTERS, ent); + type = MOVE_NOMONSTERS; // only clip against bmodels else - trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, MOVE_NORMAL, ent); + type = MOVE_NORMAL; + + trace = SV_Move (ent->v->origin, ent->v->mins, ent->v->maxs, end, type, ent); 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))) @@ -547,7 +563,10 @@ void SV_PushMove (edict_t *pusher, float movetime) float savesolid, movetime2, pushltime; vec3_t mins, maxs, move, move1, moveangle, pushorig, pushang, a, forward, left, up, org, org2; int num_moved; + int numcheckentities; + static edict_t *checkentities[MAX_EDICTS]; model_t *pushermodel; + trace_t trace; if (!pusher->v->velocity[0] && !pusher->v->velocity[1] && !pusher->v->velocity[2] && !pusher->v->avelocity[0] && !pusher->v->avelocity[1] && !pusher->v->avelocity[2]) { @@ -575,13 +594,13 @@ void SV_PushMove (edict_t *pusher, float movetime) SV_LinkEdict (pusher, false); return; default: - Con_DPrintf("SV_PushMove: unrecognized solid type %f\n", pusher->v->solid); + Con_Printf("SV_PushMove: unrecognized solid type %f\n", pusher->v->solid); return; } index = (int) pusher->v->modelindex; if (index < 1 || index >= MAX_MODELS) { - Con_DPrintf("SV_PushMove: invalid modelindex %f\n", pusher->v->modelindex); + Con_Printf("SV_PushMove: invalid modelindex %f\n", pusher->v->modelindex); return; } pushermodel = sv.models[index]; @@ -656,11 +675,11 @@ void SV_PushMove (edict_t *pusher, float movetime) // see if any solid entities are inside the final position num_moved = 0; - check = NEXT_EDICT(sv.edicts); - for (e = 1;e < sv.num_edicts;e++, check = NEXT_EDICT(check)) + + numcheckentities = SV_EntitiesInBox(mins, maxs, MAX_EDICTS, checkentities); + for (e = 0;e < numcheckentities;e++) { - if (check->e->free) - continue; + check = checkentities[e]; if (check->v->movetype == MOVETYPE_PUSH || check->v->movetype == MOVETYPE_NONE || check->v->movetype == MOVETYPE_FOLLOW @@ -670,20 +689,10 @@ void SV_PushMove (edict_t *pusher, float movetime) // if the entity is standing on the pusher, it will definitely be moved if (!(((int)check->v->flags & FL_ONGROUND) && PROG_TO_EDICT(check->v->groundentity) == pusher)) - { - if (check->v->absmin[0] >= maxs[0] - || check->v->absmax[0] <= mins[0] - || check->v->absmin[1] >= maxs[1] - || check->v->absmax[1] <= mins[1] - || check->v->absmin[2] >= maxs[2] - || check->v->absmax[2] <= mins[2]) - continue; - if (!SV_ClipMoveToEntity(pusher, check->v->origin, check->v->mins, check->v->maxs, check->v->origin).startsolid) continue; - } - if (forward[0] != 1) // quick way to check if any rotation is used + if (forward[0] != 1 || left[1] != 1) // quick way to check if any rotation is used { VectorSubtract (check->v->origin, pusher->v->origin, org); org2[0] = DotProduct (org, forward); @@ -705,7 +714,9 @@ void SV_PushMove (edict_t *pusher, float movetime) // try moving the contacted entity pusher->v->solid = SOLID_NOT; - SV_PushEntity (check, move, moveangle); + trace = SV_PushEntity (check, move); + // FIXME: turn players specially + check->v->angles[1] += trace.fraction * moveangle[1]; pusher->v->solid = savesolid; // was SOLID_BSP // if it is still inside the pusher, block @@ -714,7 +725,7 @@ void SV_PushMove (edict_t *pusher, float movetime) // try moving the contacted entity a tiny bit further to account for precision errors pusher->v->solid = SOLID_NOT; VectorScale(move, 0.1, move); - SV_PushEntity (check, move, vec3_origin); + SV_PushEntity (check, move); pusher->v->solid = savesolid; if (SV_ClipMoveToEntity(pusher, check->v->origin, check->v->mins, check->v->maxs, check->v->origin).startsolid) { @@ -750,7 +761,7 @@ void SV_PushMove (edict_t *pusher, float movetime) { pr_global_struct->self = EDICT_TO_PROG(pusher); pr_global_struct->other = EDICT_TO_PROG(check); - PR_ExecuteProgram (pusher->v->blocked, ""); + PR_ExecuteProgram (pusher->v->blocked, "QC function self.blocked is missing"); } break; } @@ -793,7 +804,7 @@ void SV_Physics_Pusher (edict_t *ent) pr_global_struct->time = sv.time; 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"); + PR_ExecuteProgram (ent->v->think, "QC function self.think is missing"); } } @@ -870,19 +881,17 @@ qboolean SV_CheckWater (edict_t *ent) ent->v->waterlevel = 0; ent->v->watertype = CONTENTS_EMPTY; - cont = SV_PointQ1Contents(point); - if (cont <= CONTENTS_WATER) + cont = SV_PointSuperContents(point); + if (cont & (SUPERCONTENTS_LIQUIDSMASK)) { - ent->v->watertype = cont; + ent->v->watertype = Mod_Q1BSP_NativeContentsFromSuperContents(NULL, cont); ent->v->waterlevel = 1; point[2] = ent->v->origin[2] + (ent->v->mins[2] + ent->v->maxs[2])*0.5; - cont = SV_PointQ1Contents(point); - if (cont <= CONTENTS_WATER) + if (SV_PointSuperContents(point) & (SUPERCONTENTS_LIQUIDSMASK)) { ent->v->waterlevel = 2; point[2] = ent->v->origin[2] + ent->v->view_ofs[2]; - cont = SV_PointQ1Contents(point); - if (cont <= CONTENTS_WATER) + if (SV_PointSuperContents(point) & (SUPERCONTENTS_LIQUIDSMASK)) ent->v->waterlevel = 3; } } @@ -948,7 +957,7 @@ int SV_TryUnstick (edict_t *ent, vec3_t oldvel) case 7: dir[0] = -2; dir[1] = -2; break; } - SV_PushEntity (ent, dir, vec3_origin); + SV_PushEntity (ent, dir); // retry the original move ent->v->velocity[0] = oldvel[0]; @@ -983,7 +992,7 @@ Only used by players void SV_WalkMove (edict_t *ent) { int clip, oldonground, originalmove_clip, originalmove_flags, originalmove_groundentity; - vec3_t upmove, downmove, oldorg, oldvel, nosteporg, nostepvel, stepnormal, originalmove_origin, originalmove_velocity; + vec3_t upmove, downmove, start_origin, start_velocity, stepnormal, originalmove_origin, originalmove_velocity; trace_t downtrace; SV_CheckVelocity(ent); @@ -992,108 +1001,121 @@ void SV_WalkMove (edict_t *ent) oldonground = (int)ent->v->flags & FL_ONGROUND; ent->v->flags = (int)ent->v->flags & ~FL_ONGROUND; - VectorCopy (ent->v->origin, oldorg); - VectorCopy (ent->v->velocity, oldvel); + VectorCopy (ent->v->origin, start_origin); + VectorCopy (ent->v->velocity, start_velocity); clip = SV_FlyMove (ent, sv.frametime, NULL); + + SV_SetOnGround (ent); + SV_CheckVelocity(ent); + VectorCopy(ent->v->origin, originalmove_origin); VectorCopy(ent->v->velocity, originalmove_velocity); originalmove_clip = clip; originalmove_flags = (int)ent->v->flags; - originalmove_groundentity = ent->v->groundentity; + originalmove_groundentity = ent->v->groundentity; - SV_CheckVelocity(ent); - - // if move didn't block on a step, return - if ( !(clip & 2) ) + if ((int)ent->v->flags & FL_WATERJUMP) return; - // if move was not trying to move into the step, return - if (fabs(oldvel[0]) < 0.03125 && fabs(oldvel[1]) < 0.03125) + if (sv_nostep.integer) return; - if (ent->v->movetype != MOVETYPE_FLY) + // if move didn't block on a step, return + if (clip & 2) { - if (!oldonground && ent->v->waterlevel == 0 && (!sv_jumpstep.integer || !sv_gameplayfix_stepwhilejumping.integer)) - // don't stair up while jumping + // if move was not trying to move into the step, return + if (fabs(start_velocity[0]) < 0.03125 && fabs(start_velocity[1]) < 0.03125) return; - if (ent->v->movetype != MOVETYPE_WALK) - // gibbed by a trigger - return; - } + if (ent->v->movetype != MOVETYPE_FLY) + { + // return if gibbed by a trigger + if (ent->v->movetype != MOVETYPE_WALK) + return; - SV_CheckVelocity(ent); + // only step up while jumping if that is enabled + if (!(sv_jumpstep.integer && sv_gameplayfix_stepwhilejumping.integer)) + if (!oldonground && ent->v->waterlevel == 0) + return; + } - if (sv_nostep.integer || (int)ent->v->flags & FL_WATERJUMP ) - return; + // try moving up and forward to go up a step + // back to start pos + VectorCopy (start_origin, ent->v->origin); + VectorCopy (start_velocity, ent->v->velocity); + + // move up + VectorClear (upmove); + upmove[2] = sv_stepheight.value; + // FIXME: don't link? + SV_PushEntity(ent, upmove); - VectorCopy (ent->v->origin, nosteporg); - VectorCopy (ent->v->velocity, nostepvel); + // move forward + ent->v->velocity[2] = 0; + clip = SV_FlyMove (ent, sv.frametime, stepnormal); + ent->v->velocity[2] += start_velocity[2]; - // try moving up and forward to go up a step - // back to start pos - VectorCopy (oldorg, ent->v->origin); + SV_CheckVelocity(ent); - VectorClear (upmove); - VectorClear (downmove); - upmove[2] = sv_stepheight.value; - downmove[2] = -sv_stepheight.value + oldvel[2]*sv.frametime; + // check for stuckness, possibly due to the limited precision of floats + // in the clipping hulls + if (clip + && fabs(originalmove_origin[1] - ent->v->origin[1]) < 0.03125 + && fabs(originalmove_origin[0] - ent->v->origin[0]) < 0.03125) + { + //Con_Printf("wall\n"); + // stepping up didn't make any progress, revert to original move + VectorCopy(originalmove_origin, ent->v->origin); + VectorCopy(originalmove_velocity, ent->v->velocity); + //clip = originalmove_clip; + ent->v->flags = originalmove_flags; + ent->v->groundentity = originalmove_groundentity; + // now try to unstick if needed + //clip = SV_TryUnstick (ent, oldvel); + return; + } - // move up - // FIXME: don't link? - SV_PushEntity(ent, upmove, vec3_origin); - - // move forward - ent->v->velocity[0] = oldvel[0]; - ent->v->velocity[1] = oldvel[1]; - ent->v->velocity[2] = 0; - clip = SV_FlyMove (ent, sv.frametime, stepnormal); - ent->v->velocity[2] += oldvel[2]; - - // check for stuckness, possibly due to the limited precision of floats - // in the clipping hulls - if (clip - && fabs(oldorg[1] - ent->v->origin[1]) < 0.03125 - && fabs(oldorg[0] - ent->v->origin[0]) < 0.03125) - { - // stepping up didn't make any progress, revert to original move - VectorCopy(originalmove_origin, ent->v->origin); - VectorCopy(originalmove_velocity, ent->v->velocity); - clip = originalmove_clip; - ent->v->flags = originalmove_flags; - ent->v->groundentity = originalmove_groundentity; - // now try to unstick if needed - //clip = SV_TryUnstick (ent, oldvel); - return; - } + //Con_Printf("step - "); - // extra friction based on view angle - if (clip & 2 && sv_wallfriction.integer) - SV_WallFriction (ent, stepnormal); + // extra friction based on view angle + if (clip & 2 && sv_wallfriction.integer) + SV_WallFriction (ent, stepnormal); + } + // skip out if stepdown is enabled, moving downward, not in water, and the move started onground and ended offground + else if (!(sv_gameplayfix_stepdown.integer && ent->v->waterlevel < 2 && start_velocity[2] < (1.0 / 32.0) && oldonground && !((int)ent->v->flags & FL_ONGROUND))) + return; // move down + VectorClear (downmove); + downmove[2] = -sv_stepheight.value + start_velocity[2]*sv.frametime; // FIXME: don't link? - downtrace = SV_PushEntity (ent, downmove, vec3_origin); + downtrace = SV_PushEntity (ent, downmove); - if (downtrace.plane.normal[2] > 0.7) + if (downtrace.fraction < 1 && downtrace.plane.normal[2] > 0.7) { - // LordHavoc: disabled this so you can walk on monsters/players + // LordHavoc: disabled this check so you can walk on monsters/players //if (ent->v->solid == SOLID_BSP) { + //Con_Printf("onground\n"); ent->v->flags = (int)ent->v->flags | FL_ONGROUND; ent->v->groundentity = EDICT_TO_PROG(downtrace.ent); } } else { + //Con_Printf("slope\n"); // if the push down didn't end up on good ground, use the move without // the step up. This happens near wall / slope combinations, and can // cause the player to hop up higher on a slope too steep to climb - VectorCopy (nosteporg, ent->v->origin); - VectorCopy (nostepvel, ent->v->velocity); + VectorCopy(originalmove_origin, ent->v->origin); + VectorCopy(originalmove_velocity, ent->v->velocity); + //clip = originalmove_clip; + ent->v->flags = originalmove_flags; + ent->v->groundentity = originalmove_groundentity; } + SV_SetOnGround (ent); SV_CheckVelocity(ent); } @@ -1198,9 +1220,9 @@ void SV_Physics_Toss (edict_t *ent) vec3_t move; edict_t *groundentity; - // regular thinking - if (!SV_RunThink (ent)) - return; + // don't stick to ground if onground and moving upward + if (ent->v->velocity[2] >= (1.0 / 32.0) && ((int)ent->v->flags & FL_ONGROUND)) + ent->v->flags = (int)ent->v->flags & ~FL_ONGROUND; // if onground, return without moving if ((int)ent->v->flags & FL_ONGROUND) @@ -1238,7 +1260,7 @@ void SV_Physics_Toss (edict_t *ent) // move origin VectorScale (ent->v->velocity, sv.frametime, move); - trace = SV_PushEntity (ent, move, vec3_origin); + trace = SV_PushEntity (ent, move); if (ent->e->free) return; @@ -1320,6 +1342,10 @@ will fall if the floor is pulled out from under them. */ void SV_Physics_Step (edict_t *ent) { + // don't stick to ground if onground and moving upward + if (ent->v->velocity[2] >= (1.0 / 32.0) && ((int)ent->v->flags & FL_ONGROUND)) + ent->v->flags = (int)ent->v->flags & ~FL_ONGROUND; + // freefall if not onground/fly/swim if (!((int)ent->v->flags & (FL_ONGROUND | FL_FLY | FL_SWIM))) { @@ -1331,7 +1357,7 @@ void SV_Physics_Step (edict_t *ent) SV_LinkEdict(ent, true); // just hit ground - if (hitsound && (int)ent->v->flags & FL_ONGROUND) + if (hitsound && (int)ent->v->flags & FL_ONGROUND && gamemode != GAME_NEXUIZ) SV_StartSound(ent, 0, "demon/dland2.wav", 255, 1); } @@ -1351,8 +1377,9 @@ SV_Physics */ void SV_Physics (void) { - int i; + int i, newnum_edicts; edict_t *ent; + qbyte runmove[MAX_EDICTS]; // let the progs know that a new frame has started pr_global_struct->self = EDICT_TO_PROG(sv.edicts); @@ -1360,11 +1387,17 @@ void SV_Physics (void) pr_global_struct->time = sv.time; PR_ExecuteProgram (pr_global_struct->StartFrame, "QC function StartFrame is missing"); + newnum_edicts = 0; + for (i = 0, ent = sv.edicts;i < sv.num_edicts;i++, ent = NEXT_EDICT(ent)) + if ((runmove[i] = !ent->e->free)) + newnum_edicts = i + 1; + sv.num_edicts = max(svs.maxclients + 1, newnum_edicts); + // // treat each object in turn // - ent = sv.edicts; - for (i=0 ; ie->free) continue; @@ -1372,20 +1405,18 @@ void SV_Physics (void) if (pr_global_struct->force_retouch) SV_LinkEdict (ent, true); // force retouch even for stationary - if (i <= svs.maxclients) + if (i >= 1 && i <= svs.maxclients) { - if (i > 0) - { - 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); - } + // don't do physics on disconnected clients, FrikBot relies on this + 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); } else if (sv_freezenonclients.integer) continue; @@ -1435,26 +1466,28 @@ void SV_Physics (void) case MOVETYPE_BOUNCE: case MOVETYPE_BOUNCEMISSILE: case MOVETYPE_FLYMISSILE: - SV_Physics_Toss (ent); + // regular thinking + if (SV_RunThink (ent) && runmove[i]) + SV_Physics_Toss (ent); break; case MOVETYPE_FLY: - if (i > 0 && i <= svs.maxclients) + if (SV_RunThink (ent) && runmove[i]) { - if (SV_RunThink (ent)) + if (i > 0 && i <= svs.maxclients) { SV_CheckWater (ent); SV_WalkMove (ent); } + else + SV_Physics_Toss (ent); } - else - SV_Physics_Toss (ent); break; default: Host_Error ("SV_Physics: bad movetype %i", (int)ent->v->movetype); break; } - if (i <= svs.maxclients && i > 0 && !ent->e->free) + if (i >= 1 && i <= svs.maxclients) { SV_CheckVelocity (ent); @@ -1469,8 +1502,8 @@ void SV_Physics (void) } } - if (pr_global_struct->force_retouch) - pr_global_struct->force_retouch--; + if (pr_global_struct->force_retouch > 0) + pr_global_struct->force_retouch = max(0, pr_global_struct->force_retouch - 1); // LordHavoc: endframe support if (EndFrameQC) @@ -1478,7 +1511,7 @@ void SV_Physics (void) pr_global_struct->self = EDICT_TO_PROG(sv.edicts); pr_global_struct->other = EDICT_TO_PROG(sv.edicts); pr_global_struct->time = sv.time; - PR_ExecuteProgram ((func_t)(EndFrameQC - pr_functions), ""); + PR_ExecuteProgram ((func_t)(EndFrameQC - pr_functions), "QC function EndFrame is missing"); } if (!sv_freezenonclients.integer)