diff --git a/Quake/sv_main.c b/Quake/sv_main.c index 093e733b..b09a37ca 100644 --- a/Quake/sv_main.c +++ b/Quake/sv_main.c @@ -1136,6 +1136,7 @@ void SV_Init (void) extern cvar_t sv_gameplayfix_spawnbeforethinks; extern cvar_t sv_gameplayfix_bouncedownslopes; extern cvar_t sv_gameplayfix_elevators; + extern cvar_t sv_fastpushmove; extern cvar_t sv_friction; extern cvar_t sv_edgefriction; extern cvar_t sv_stopspeed; @@ -1162,6 +1163,7 @@ void SV_Init (void) Cvar_RegisterVariable (&sv_gameplayfix_spawnbeforethinks); Cvar_RegisterVariable (&sv_gameplayfix_bouncedownslopes); Cvar_RegisterVariable (&sv_gameplayfix_elevators); + Cvar_RegisterVariable (&sv_fastpushmove); Cvar_RegisterVariable (&pr_checkextension); Cvar_RegisterVariable (&sv_altnoclip); // johnfitz Cvar_RegisterVariable (&sv_netsort); diff --git a/Quake/sv_phys.c b/Quake/sv_phys.c index efe35688..26218db5 100644 --- a/Quake/sv_phys.c +++ b/Quake/sv_phys.c @@ -49,6 +49,7 @@ cvar_t sv_nostep = {"sv_nostep", "0", CVAR_NONE}; cvar_t sv_freezenonclients = {"sv_freezenonclients", "0", CVAR_NONE}; cvar_t sv_gameplayfix_spawnbeforethinks = {"sv_gameplayfix_spawnbeforethinks", "0", CVAR_NONE}; cvar_t sv_gameplayfix_bouncedownslopes = {"sv_gameplayfix_bouncedownslopes", "1", CVAR_NONE}; // fixes grenades making horrible noises on slopes. +cvar_t sv_fastpushmove = {"sv_fastpushmove", "0", CVAR_ARCHIVE}; // 0=old SV_PushMove processing; 1= faster SV_PushMove, with bugs ? #define MOVE_EPSILON 0.01 @@ -486,34 +487,66 @@ static void SV_PushMove (edict_t *pusher, float movetime) // see if any solid entities are inside the final position num_moved = 0; - for (e = 0; e < num_pushable_ent_cache; e++) - { - check = pushable_ent_cache[e]; + const bool fast_pushers = (sv_fastpushmove.value > 0.f); - qboolean riding = false; + // beware, we skip entity 0: + const int effective_num_edicts = (fast_pushers ? num_pushable_ent_cache : qcvm->num_edicts - 1); + check = NEXT_EDICT (qcvm->edicts); + + for (e = 0; e < effective_num_edicts; e++) + { + if (fast_pushers) + { + check = pushable_ent_cache[e]; + } if (check->free) + { + if (!fast_pushers) + check = NEXT_EDICT (check); continue; - if (check->v.movetype == MOVETYPE_PUSH || check->v.movetype == MOVETYPE_NONE || check->v.movetype == MOVETYPE_NOCLIP) - continue; + } + + if (!fast_pushers) + { + if (check->v.movetype == MOVETYPE_PUSH || check->v.movetype == MOVETYPE_NONE || check->v.movetype == MOVETYPE_NOCLIP) + { + check = NEXT_EDICT (check); + continue; + } + } + + qboolean riding = false; // if the entity is standing on the pusher, it will definately 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.absmin[1] >= maxs[1] || check->v.absmin[2] >= maxs[2] || check->v.absmax[0] <= mins[0] || check->v.absmax[1] <= mins[1] || check->v.absmax[2] <= mins[2]) + { + if (!fast_pushers) + check = NEXT_EDICT (check); continue; + } // see if the ent's bbox is inside the pusher's final position if (pusher->v.skin < 0) { // a more precise check... if (!SV_ClipMoveToEntity (pusher, check->v.origin, check->v.mins, check->v.maxs, check->v.origin, CONTENTMASK_ANYSOLID).startsolid) + { + if (!fast_pushers) + check = NEXT_EDICT (check); continue; + } } else { if (!SV_TestEntityPosition (check)) + { + if (!fast_pushers) + check = NEXT_EDICT (check); continue; + } riding = false; } @@ -557,12 +590,20 @@ static void SV_PushMove (edict_t *pusher, float movetime) if (block) { // fail the move if (check->v.mins[0] == check->v.maxs[0]) + { + if (!fast_pushers) + check = NEXT_EDICT (check); continue; + } if (check->v.solid == SOLID_NOT || check->v.solid == SOLID_TRIGGER) { // corpse check->v.mins[0] = check->v.mins[1] = 0; VectorCopy (check->v.mins, check->v.maxs); - continue; + { + if (!fast_pushers) + check = NEXT_EDICT (check); + continue; + } } // try moving the entity up a bit if it's blocked by the pusher while also standing on it @@ -570,7 +611,11 @@ static void SV_PushMove (edict_t *pusher, float movetime) { check->v.origin[2] += DIST_EPSILON; if (!SV_TestEntityPosition (check)) + { + if (!fast_pushers) + check = NEXT_EDICT (check); continue; + } } VectorCopy (entorig, check->v.origin); @@ -597,7 +642,9 @@ static void SV_PushMove (edict_t *pusher, float movetime) } break; } // end if block - } // foreach pushable entities + if (!fast_pushers) + check = NEXT_EDICT (check); + } // foreach pushable entities } /* @@ -1282,25 +1329,28 @@ void SV_Physics (void) else entity_cap = qcvm->num_edicts; - // fill the pushable entities cache - num_pushable_ent_cache = 0; + // backup the previous callback before iterating: + ed_allocation_callback_t previous_callback = ED_GetAllocCallback (); - edict_t *check = NEXT_EDICT (qcvm->edicts); - for (int e = 1; e < qcvm->num_edicts; e++, check = NEXT_EDICT (check)) + // fill the pushable entities cache + if (sv_fastpushmove.value > 0.f) { - if (check->free) - continue; - if (check->v.movetype == MOVETYPE_PUSH || check->v.movetype == MOVETYPE_NONE || check->v.movetype == MOVETYPE_NOCLIP) - continue; - - pushable_ent_cache[num_pushable_ent_cache++] = check; - } + num_pushable_ent_cache = 0; + // beware, we skip entity 0 here: + edict_t *check = NEXT_EDICT (qcvm->edicts); + for (int e = 1; e < qcvm->num_edicts; e++, check = NEXT_EDICT (check)) + { + if (check->free) + continue; + if (check->v.movetype == MOVETYPE_PUSH || check->v.movetype == MOVETYPE_NONE || check->v.movetype == MOVETYPE_NOCLIP) + continue; - // backup the previous callback before iterating: - ed_allocation_callback_t previous_callback = ED_GetAllocCallback (); + pushable_ent_cache[num_pushable_ent_cache++] = check; + } - // plug ours: - ED_SetAllocCallback (intercept_allocs_in_pr_execute_program); + // plug ours: + ED_SetAllocCallback (intercept_allocs_in_pr_execute_program); + } // for (i=0 ; i 0.f) + { + // restore previous callback: + ED_SetAllocCallback (previous_callback); + } if (pr_global_struct->force_retouch) pr_global_struct->force_retouch--;