cvar_t sv_gameplayfix_findradiusdistancetobox = {CF_SERVER, "sv_gameplayfix_findradiusdistancetobox", "1", "causes findradius to check the distance to the corner of a box rather than the center of the box, makes findradius detect bmodels such as very large doors that would otherwise be unaffected by splash damage"};
cvar_t sv_gameplayfix_gravityunaffectedbyticrate = {CF_SERVER, "sv_gameplayfix_gravityunaffectedbyticrate", "0", "fix some ticrate issues in physics."};
cvar_t sv_gameplayfix_grenadebouncedownslopes = {CF_SERVER, "sv_gameplayfix_grenadebouncedownslopes", "1", "prevents MOVETYPE_BOUNCE (grenades) from getting stuck when fired down a downward sloping surface"};
+cvar_t sv_gameplayfix_impactbeforeonground = {CF_SERVER, "sv_gameplayfix_impactbeforeonground", "0", "enables a bug from old DP versions in which entity .touch functions are called before FL_ONGROUND is set when a collision is detected in SV_FlyMove() (used by MOVETYPE_WALK and MOVETYPE_STEP), Quake 1.5 and Combat+ mods require this, it breaks id1 fiends"};
cvar_t sv_gameplayfix_multiplethinksperframe = {CF_SERVER, "sv_gameplayfix_multiplethinksperframe", "1", "allows entities to think more often than the server framerate, primarily useful for very high fire rate weapons"};
cvar_t sv_gameplayfix_noairborncorpse = {CF_SERVER, "sv_gameplayfix_noairborncorpse", "1", "causes entities (corpses, items, etc) sitting ontop of moving entities (players) to fall when the moving entity (player) is no longer supporting them"};
cvar_t sv_gameplayfix_noairborncorpse_allowsuspendeditems = {CF_SERVER, "sv_gameplayfix_noairborncorpse_allowsuspendeditems", "1", "causes entities sitting ontop of objects that are instantaneously remove to float in midair (special hack to allow a common level design trick for floating items)"};
Cvar_RegisterVariable (&sv_gameplayfix_findradiusdistancetobox);
Cvar_RegisterVariable (&sv_gameplayfix_gravityunaffectedbyticrate);
Cvar_RegisterVariable (&sv_gameplayfix_grenadebouncedownslopes);
+ Cvar_RegisterVariable (&sv_gameplayfix_impactbeforeonground);
Cvar_RegisterVariable (&sv_gameplayfix_multiplethinksperframe);
Cvar_RegisterVariable (&sv_gameplayfix_noairborncorpse);
Cvar_RegisterVariable (&sv_gameplayfix_noairborncorpse_allowsuspendeditems);
SV_Impact
Two entities have touched, so run their touch functions
+Returns true if the push did not result in the entity being teleported by QC code.
==================
*/
-static void SV_Impact (prvm_edict_t *e1, trace_t *trace)
+static qbool SV_Impact (prvm_edict_t *e1, trace_t *trace)
{
prvm_prog_t *prog = SVVM_prog;
int restorevm_tempstringsbuf_cursize;
int old_self, old_other;
prvm_edict_t *e2 = (prvm_edict_t *)trace->ent;
+ e1->priv.required->mark = PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN; // -2: setorigin running
+
old_self = PRVM_serverglobaledict(self);
old_other = PRVM_serverglobaledict(other);
restorevm_tempstringsbuf_cursize = prog->tempstringsbuf.cursize;
PRVM_serverglobaledict(self) = old_self;
PRVM_serverglobaledict(other) = old_other;
prog->tempstringsbuf.cursize = restorevm_tempstringsbuf_cursize;
+
+ if(e1->priv.required->mark == PRVM_EDICT_MARK_SETORIGIN_CAUGHT)
+ {
+ e1->priv.required->mark = 0;
+ return false;
+ }
+ else if(e1->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
+ {
+ e1->priv.required->mark = 0;
+ return true;
+ }
+ else
+ {
+ Con_Printf(CON_ERROR "The edict mark had been overwritten! Please debug this.\n");
+ return true;
+ }
}
============
*/
static float SV_Gravity (prvm_edict_t *ent);
-static qbool SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, qbool dolink, qbool checkstuck);
+static qbool SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, qbool dotouch, qbool checkstuck);
#define MAX_CLIP_PLANES 5
static int SV_FlyMove (prvm_edict_t *ent, float time, qbool applygravity, float *stepnormal, int hitsupercontentsmask, int skipsupercontentsmask, int skipmaterialflagsmask, float stepheight)
{
break;
VectorScale(PRVM_serveredictvector(ent, velocity), time_left, push);
- if(!SV_PushEntity(&trace, ent, push, false, true))
+ if(!SV_PushEntity(&trace, ent, push, sv_gameplayfix_impactbeforeonground.integer, true))
{
// we got teleported by a touch function
// let's abort the move
VectorCopy(trace.plane.normal, stepnormal);
}
- // Unlike some other movetypes Quake's SV_FlyMove calls SV_Impact only after setting ONGROUND which id1 fiends rely on.
- // If we stepped up (sv_gameplayfix_stepmultipletimes) this will impact the steptrace2 plane instead of the original.
- if (PRVM_serveredictfloat(ent, solid) >= SOLID_TRIGGER && trace.ent)
- SV_Impact(ent, &trace);
- if (ent->free)
- return blocked; // removed by the impact function
+ if (!sv_gameplayfix_impactbeforeonground.integer)
+ {
+ // Unlike some other movetypes Quake's SV_FlyMove calls SV_Impact only after setting ONGROUND which id1 fiends rely on.
+ // If we stepped up (sv_gameplayfix_stepmultipletimes) this will impact the steptrace2 plane instead of the original.
+ if (PRVM_serveredictfloat(ent, solid) >= SOLID_TRIGGER && trace.ent)
+ if (!SV_Impact(ent, &trace))
+ {
+ blocked |= 8;
+ break;
+ }
+ if (ent->free)
+ return blocked; // removed by the impact function
+ }
if (trace.fraction >= 0.001)
{
Returns true if the push did not result in the entity being teleported by QC code.
============
*/
-static qbool SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, qbool dolink, qbool checkstuck)
+static qbool SV_PushEntity (trace_t *trace, prvm_edict_t *ent, vec3_t push, qbool dotouch, qbool checkstuck)
{
prvm_prog_t *prog = SVVM_prog;
int solid;
VectorCopy(trace->endpos, PRVM_serveredictvector(ent, origin));
VectorCopy(trace->endpos, PRVM_serveredictvector(ent, oldorigin)); // for SV_UnstickEntity()
- ent->priv.required->mark = PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN; // -2: setorigin running
-
SV_LinkEdict(ent);
#if 0
}
#endif
- if (dolink)
+ if (dotouch)
{
SV_LinkEdict_TouchAreaGrid(ent);
if((PRVM_serveredictfloat(ent, solid) >= SOLID_TRIGGER && trace->ent && (!((int)PRVM_serveredictfloat(ent, flags) & FL_ONGROUND) || PRVM_serveredictedict(ent, groundentity) != PRVM_EDICT_TO_PROG(trace->ent))))
- SV_Impact (ent, trace);
+ return SV_Impact (ent, trace);
}
- if(ent->priv.required->mark == PRVM_EDICT_MARK_SETORIGIN_CAUGHT)
- {
- ent->priv.required->mark = 0;
- return false;
- }
- else if(ent->priv.required->mark == PRVM_EDICT_MARK_WAIT_FOR_SETORIGIN)
- {
- ent->priv.required->mark = 0;
- return true;
- }
- else
- {
- Con_Printf("The edict mark had been overwritten! Please debug this.\n");
- return true;
- }
+ return true;
}