torg = tgt.origin + (tgt.mins + tgt.maxs) * 0.5;
grav = PHYS_GRAVITY(NULL);
- if(pushed_entity && PHYS_ENTGRAVITY(pushed_entity))
- grav *= PHYS_ENTGRAVITY(pushed_entity);
+ if(pushed_entity && pushed_entity.gravity)
+ grav *= pushed_entity.gravity;
zdist = torg.z - org.z;
sdist = vlen(torg - org - zdist * '0 0 1');
if(applygravity)
{
this.move_didgravity = 1;
- grav = dt * (PHYS_ENTGRAVITY(this) ? PHYS_ENTGRAVITY(this) : 1) * PHYS_GRAVITY(this);
+ grav = dt * (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !IS_ONGROUND(this))
{
void _Movetype_Impact(entity this, entity oth) // SV_Impact
{
- if(gettouch(this))
+ if(!this && !oth)
+ return;
+
+ if(this.solid != SOLID_NOT && gettouch(this))
gettouch(this)(this, oth);
- if(gettouch(oth))
+ if(oth.solid != SOLID_NOT && gettouch(oth))
+ {
+ trace_endpos = oth.origin;
+ trace_plane_normal = -trace_plane_normal;
+ trace_plane_dist = -trace_plane_dist;
+ trace_ent = this;
+ trace_dpstartcontents = 0;
+ trace_dphitcontents = 0;
+ trace_dphitq3surfaceflags = 0;
+ trace_dphittexturename = string_null;
gettouch(oth)(oth, this);
+ }
}
void _Movetype_LinkEdict_TouchAreaGrid(entity this) // SV_LinkEdict_TouchAreaGrid
vector last_origin = this.origin;
- if(dolink)
- _Movetype_LinkEdict(this, true);
+ _Movetype_LinkEdict(this, dolink);
- if(trace_fraction < 1)
- if(this.solid >= SOLID_TRIGGER && trace_ent && (!IS_ONGROUND(this) || (this.groundentity != trace_ent)))
- _Movetype_Impact(this, trace_ent);
+ if((this.solid >= SOLID_TRIGGER && trace_fraction < 1 && (!IS_ONGROUND(this) || this.groundentity != trace_ent)))
+ _Movetype_Impact(this, trace_ent);
return (this.origin == last_origin); // false if teleported by touch
}
Movetype_Physics_MatchTicrate(this, TICRATE, sloppy);
}
+// saved .move_*
.vector tic_origin;
.vector tic_velocity;
.int tic_flags;
.vector tic_avelocity;
.vector tic_angles;
+// saved .*
.vector tic_saved_origin;
.vector tic_saved_velocity;
.int tic_saved_flags;
.vector tic_saved_angles;
void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy) // SV_Physics_Entity
{
+ // this hack exists to contain the physics feature
+ // (so entities can place themselves in the world and not need to update .tic_* themselves)
#define X(s) \
if(this.(s) != this.tic_saved_##s) \
this.tic_##s = this.(s)
X(angles);
#undef X
+ this.flags = this.tic_flags;
+ this.velocity = this.tic_velocity;
+ setorigin(this, this.tic_origin);
+ this.avelocity = this.tic_avelocity;
+ this.angles = this.tic_angles;
+
if(tr <= 0)
{
- this.flags = this.tic_flags;
- this.velocity = this.tic_velocity;
- this.origin = this.tic_origin;
- this.avelocity = this.tic_avelocity;
- this.angles = this.tic_angles;
Movetype_Physics_NoMatchServer(this);
- this.tic_origin = this.origin;
- this.tic_velocity = this.velocity;
- this.tic_avelocity = this.avelocity;
- this.tic_angles = this.angles;
- this.tic_flags = this.flags;
this.tic_saved_flags = this.flags;
this.tic_saved_velocity = this.velocity;
if(!this.move_didgravity)
this.move_didgravity = ((this.move_movetype == MOVETYPE_BOUNCE || this.move_movetype == MOVETYPE_TOSS) && !(this.tic_flags & FL_ONGROUND));
- for (int i = 0; i < n; ++i)
+ for (int j = 0; j < n; ++j)
{
- this.flags = this.tic_flags;
- this.velocity = this.tic_velocity;
- setorigin(this, this.tic_origin);
- this.avelocity = this.tic_avelocity;
- this.angles = this.tic_angles;
_Movetype_Physics_Frame(this, tr);
- this.tic_origin = this.origin;
- this.tic_velocity = this.velocity;
- this.tic_avelocity = this.avelocity;
- this.tic_angles = this.angles;
- this.tic_flags = this.flags;
if(wasfreed(this))
return;
}
+ // update the physics fields
+ this.tic_origin = this.origin;
+ this.tic_velocity = this.velocity;
+ this.tic_avelocity = this.avelocity;
+ this.tic_angles = this.angles;
+ this.tic_flags = this.flags;
+
+ // restore their actual values
+ this.flags = this.tic_saved_flags;
+ this.velocity = this.tic_saved_velocity;
+ setorigin(this, this.tic_saved_origin);
+ //this.avelocity = this.tic_saved_avelocity;
+ this.angles = this.tic_saved_angles;
+
this.avelocity = this.tic_avelocity;
if(dt > 0 && this.move_movetype != MOVETYPE_NONE && !(this.tic_flags & FL_ONGROUND))
{
this.velocity_z -= (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1)
* dt
- * (this.gravity ? this.gravity : 1)
+ * ((this.gravity) ? this.gravity : 1)
* PHYS_GRAVITY(this);
}
}
else
{
- vector oldorg = this.origin;
- this.origin = this.tic_origin;
+ setorigin(this, this.tic_origin);
_Movetype_PushEntityTrace(this, dt * this.velocity);
- this.origin = oldorg;
if(!trace_startsolid)
setorigin(this, trace_endpos);
+ else
+ setorigin(this, this.tic_saved_origin);
}
if(this.move_didgravity > 0 && GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
- this.velocity_z -= 0.5 * dt * (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
+ this.velocity_z -= 0.5 * dt * ((this.gravity) ? this.gravity : 1) * PHYS_GRAVITY(this);
}
else
{
setorigin(this, this.tic_origin);
}
+ this.flags = this.tic_flags;
+
this.tic_saved_flags = this.flags;
this.tic_saved_velocity = this.velocity;
this.tic_saved_origin = this.origin;
#define GAMEPLAYFIX_STEPMULTIPLETIMES(s) STAT(GAMEPLAYFIX_STEPMULTIPLETIMES)
#define GAMEPLAYFIX_UNSTICKPLAYERS(s) STAT(GAMEPLAYFIX_UNSTICKPLAYERS)
#define GAMEPLAYFIX_WATERTRANSITION(s) STAT(GAMEPLAYFIX_WATERTRANSITION)
+#define GAMEPLAYFIX_SLIDEMOVEPROJECTILES(s) STAT(GAMEPLAYFIX_SLIDEMOVEPROJECTILES)
+#define GAMEPLAYFIX_GRENADEBOUNCESLOPES(s) STAT(GAMEPLAYFIX_GRENADEBOUNCESLOPES)
+#define GAMEPLAYFIX_NOAIRBORNCORPSE(s) STAT(GAMEPLAYFIX_NOAIRBORNCORPSE)
+#define NOAIRBORNCORPSE_ALLOWSUSPENDED(s) STAT(NOAIRBORNCORPSE_ALLOWSUSPENDED)
#define UPWARD_VELOCITY_CLEARS_ONGROUND(s) STAT(GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND)
+
#define PHYS_STEPHEIGHT(s) STAT(MOVEVARS_STEPHEIGHT)
#define PHYS_NOSTEP(s) STAT(NOSTEP)
#define PHYS_JUMPSTEP(s) STAT(MOVEVARS_JUMPSTEP)
void _Movetype_Physics_Toss(entity this, float dt) // SV_Physics_Toss
{
- if (IS_ONGROUND(this))
+ if(IS_ONGROUND(this))
{
- if (this.velocity.z >= 1 / 32 && UPWARD_VELOCITY_CLEARS_ONGROUND(this))
+ if(this.velocity.z >= (1 / 32) && UPWARD_VELOCITY_CLEARS_ONGROUND(this))
{
+ // don't stick to ground if onground and moving upward
UNSET_ONGROUND(this);
}
- else if (!this.groundentity)
+ else if(!this.groundentity || !GAMEPLAYFIX_NOAIRBORNCORPSE(this))
{
return;
}
- else if (this.move_suspendedinair && wasfreed(this.groundentity))
+ else if(this.move_suspendedinair && wasfreed(this.groundentity))
{
this.groundentity = NULL;
+ if(NOAIRBORNCORPSE_ALLOWSUSPENDED(this))
+ return;
+ }
+ else if(boxesoverlap(this.absmin, this.absmax, this.groundentity.absmin, this.groundentity.absmax))
+ {
+ // don't slide if still touching the groundentity
return;
}
}
_Movetype_CheckVelocity(this);
- /*if (this.move_movetype == MOVETYPE_BOUNCE || this.move_movetype == MOVETYPE_TOSS)
+ if(this.move_movetype == MOVETYPE_BOUNCE || this.move_movetype == MOVETYPE_TOSS)
{
- this.move_didgravity = 1;
+ this.move_didgravity = true;
this.velocity_z -= (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1)
* dt
- * (this.gravity ? this.gravity : 1)
+ * ((this.gravity) ? this.gravity : 1)
* PHYS_GRAVITY(this);
- }*/
+ }
- if (this.move_movetype == MOVETYPE_BOUNCE || this.move_movetype == MOVETYPE_TOSS)
+ /*if (this.move_movetype == MOVETYPE_BOUNCE || this.move_movetype == MOVETYPE_TOSS)
{
this.move_didgravity = true;
this.velocity_z -= (((this.gravity) ? this.gravity : 1) * PHYS_GRAVITY(this) * dt);
- }
+ }*/
this.angles = this.angles + this.avelocity * dt;
float movetime = dt;
- for (int bump = 0; bump < MAX_CLIP_PLANES && movetime > 0; ++bump)
+ for (int bump = 0; bump < MAX_CLIP_PLANES && movetime > 0; bump++)
{
vector move = this.velocity * movetime;
- _Movetype_PushEntity(this, move, true, false);
+ if(!_Movetype_PushEntity(this, move, true, true))
+ return;
if (wasfreed(this))
return;
if (trace_startsolid)
{
_Movetype_UnstickEntity(this);
- _Movetype_PushEntity(this, move, false, false);
+ if(!_Movetype_PushEntity(this, move, true, true))
+ return;
if (wasfreed(this))
return;
}
if (this.move_movetype == MOVETYPE_BOUNCEMISSILE)
{
- this.velocity = _Movetype_ClipVelocity(this.velocity, trace_plane_normal, 2.0);
+ float bouncefac = (!this.bouncefactor) ? 1.0 : this.bouncefactor;
+ this.velocity = _Movetype_ClipVelocity(this.velocity, trace_plane_normal, 1 + bouncefac);
UNSET_ONGROUND(this);
+ if(!GAMEPLAYFIX_SLIDEMOVEPROJECTILES(this))
+ movetime = 0;
}
else if (this.move_movetype == MOVETYPE_BOUNCE)
{
- float bouncefac = this.bouncefactor; if (!bouncefac) bouncefac = 0.5;
- float bstop = this.bouncestop; if (!bstop) bstop = 60 / 800;
- bstop *= (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
+ float bouncefac = (!this.bouncefactor) ? 0.5 : this.bouncefactor;
+ float bstop = (!this.bouncestop) ? (60 / 800) : this.bouncestop;
+ float grav = ((this.gravity) ? this.gravity : 1);
this.velocity = _Movetype_ClipVelocity(this.velocity, trace_plane_normal, 1 + bouncefac);
float d = trace_plane_normal * this.velocity;
- if (trace_plane_normal.z > 0.7 && d < bstop && d > -bstop)
+ if(!GAMEPLAYFIX_GRENADEBOUNCESLOPES(this))
+ d = this.velocity.z;
+ if (trace_plane_normal.z > 0.7 && d < PHYS_GRAVITY(this) * bstop * grav)
{
SET_ONGROUND(this);
this.groundentity = trace_ent;
this.velocity = '0 0 0';
this.avelocity = '0 0 0';
+ movetime = 0;
}
else
{
UNSET_ONGROUND(this);
+ if(!GAMEPLAYFIX_SLIDEMOVEPROJECTILES(this))
+ movetime = 0;
}
}
else
this.move_suspendedinair = true;
this.velocity = '0 0 0';
this.avelocity = '0 0 0';
+ movetime = 0;
}
else
{
UNSET_ONGROUND(this);
+ if(!GAMEPLAYFIX_SLIDEMOVEPROJECTILES(this))
+ movetime = 0;
}
}
// DP revision 8905 (just, WHY...)
- if (this.move_movetype == MOVETYPE_BOUNCEMISSILE)
- break;
+ //if (this.move_movetype == MOVETYPE_BOUNCEMISSILE)
+ //break;
// DP revision 8918 (WHY...)
- if (IS_ONGROUND(this))
- break;
+ //if (IS_ONGROUND(this))
+ //break;
}
- //if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE && this.move_didgravity > 0 && !IS_ONGROUND(this))
- // this.velocity_z -= 0.5 * dt * (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
+ if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE && this.move_didgravity > 0 && !IS_ONGROUND(this))
+ this.velocity_z -= 0.5 * dt * ((this.gravity) ? this.gravity : 1) * PHYS_GRAVITY(this);
_Movetype_CheckWaterTransition(this);
}
int autocvar_sv_gameplayfix_stepmultipletimes = 1;
int autocvar_sv_gameplayfix_unstickplayers = 1;
int autocvar_sv_gameplayfix_fixedcheckwatertransition = 1;
+int autocvar_sv_gameplayfix_slidemoveprojectiles = 1;
+int autocvar_sv_gameplayfix_grenadebouncedownslopes = 1;
+int autocvar_sv_gameplayfix_noairborncorpse = 1;
+int autocvar_sv_gameplayfix_noairborncorpse_allowsuspendeditems = 1;
#endif
REGISTER_STAT(GAMEPLAYFIX_DOWNTRACEONGROUND, int, autocvar_sv_gameplayfix_downtracesupportsongroundflag)
REGISTER_STAT(GAMEPLAYFIX_EASIERWATERJUMP, int, autocvar_sv_gameplayfix_easierwaterjump)
REGISTER_STAT(GAMEPLAYFIX_UNSTICKPLAYERS, int, autocvar_sv_gameplayfix_unstickplayers)
REGISTER_STAT(GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND, int, autocvar_sv_gameplayfix_upwardvelocityclearsongroundflag)
REGISTER_STAT(GAMEPLAYFIX_WATERTRANSITION, int, autocvar_sv_gameplayfix_fixedcheckwatertransition)
+REGISTER_STAT(GAMEPLAYFIX_SLIDEMOVEPROJECTILES, int, autocvar_sv_gameplayfix_slidemoveprojectiles)
+REGISTER_STAT(GAMEPLAYFIX_GRENADEBOUNCESLOPES, int, autocvar_sv_gameplayfix_grenadebouncedownslopes)
+REGISTER_STAT(GAMEPLAYFIX_NOAIRBORNCORPSE, int, autocvar_sv_gameplayfix_noairborncorpse)
+REGISTER_STAT(NOAIRBORNCORPSE_ALLOWSUSPENDED, int, autocvar_sv_gameplayfix_noairborncorpse_allowsuspendeditems)
REGISTER_STAT(MOVEVARS_JUMPSTEP, int, cvar("sv_jumpstep"))
REGISTER_STAT(NOSTEP, int, cvar("sv_nostep"))