X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=sv_phys.c;h=fa0101f3dfe59ab7a0b5817530b0c95f6140bb92;hb=df8727697622029dd7a03047999ffc19b49e44ea;hp=b25bc527af729dfd6a4fc22e9e4285eb81a032d3;hpb=d3dd8ca4413bd509856f4dfd6978a13d627edcd6;p=xonotic%2Fdarkplaces.git diff --git a/sv_phys.c b/sv_phys.c index b25bc527..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) { @@ -563,6 +563,8 @@ 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; @@ -592,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]; @@ -673,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 @@ -687,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); @@ -769,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; } @@ -812,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"); } } @@ -889,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; } } @@ -1025,49 +1015,49 @@ void SV_WalkMove (edict_t *ent) originalmove_flags = (int)ent->v->flags; originalmove_groundentity = ent->v->groundentity; + if ((int)ent->v->flags & FL_WATERJUMP) + return; + + if (sv_nostep.integer) + return; + // if move didn't block on a step, return if (clip & 2) { // 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 (sv_nostep.integer) - return; - - if ((int)ent->v->flags & FL_WATERJUMP) - return; - + if (ent->v->movetype != MOVETYPE_FLY) { // return if gibbed by a trigger if (ent->v->movetype != MOVETYPE_WALK) return; - + // only step up while jumping if that is enabled if (!(sv_jumpstep.integer && sv_gameplayfix_stepwhilejumping.integer)) if (!oldonground && ent->v->waterlevel == 0) 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); - + // move forward ent->v->velocity[2] = 0; clip = SV_FlyMove (ent, sv.frametime, stepnormal); ent->v->velocity[2] += start_velocity[2]; - + SV_CheckVelocity(ent); - + // check for stuckness, possibly due to the limited precision of floats // in the clipping hulls if (clip @@ -1080,7 +1070,7 @@ void SV_WalkMove (edict_t *ent) VectorCopy(originalmove_velocity, ent->v->velocity); //clip = originalmove_clip; ent->v->flags = originalmove_flags; - ent->v->groundentity = originalmove_groundentity; + ent->v->groundentity = originalmove_groundentity; // now try to unstick if needed //clip = SV_TryUnstick (ent, oldvel); return; @@ -1092,7 +1082,8 @@ void SV_WalkMove (edict_t *ent) if (clip & 2 && sv_wallfriction.integer) SV_WallFriction (ent, stepnormal); } - else if (!sv_gameplayfix_stepdown.integer || !oldonground || ((int)ent->v->flags & FL_ONGROUND)) + // 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 @@ -1121,7 +1112,7 @@ void SV_WalkMove (edict_t *ent) VectorCopy(originalmove_velocity, ent->v->velocity); //clip = originalmove_clip; ent->v->flags = originalmove_flags; - ent->v->groundentity = originalmove_groundentity; + ent->v->groundentity = originalmove_groundentity; } SV_SetOnGround (ent); @@ -1229,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) @@ -1351,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))) { @@ -1362,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); } @@ -1382,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); @@ -1391,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; @@ -1403,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; @@ -1466,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); @@ -1500,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) @@ -1509,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)