#include "push.qc"
#include "toss.qc"
+#include "walk.qc"
#include "movetypes.qc"
#include "push.qh"
#include "toss.qh"
+#include "walk.qh"
-#endif
\ No newline at end of file
+#endif
#include "../../server/autocvars.qh"
#endif
-void _Movetype_CheckVelocity() // SV_CheckVelocity
+void _Movetype_WallFriction(vector stepnormal) // SV_WallFriction
{
+ /*float d, i;
+ vector into, side;
+ makevectors(self.v_angle);
+ d = (stepnormal * v_forward) + 0.5;
+
+ if(d < 0)
+ {
+ i = (stepnormal * self.move_velocity);
+ into = i * stepnormal;
+ side = self.move_velocity - into;
+ self.move_velocity_x = side.x * (1 * d);
+ self.move_velocity_y = side.y * (1 * d);
+ }*/
+}
+
+vector planes[MAX_CLIP_PLANES];
+int _Movetype_FlyMove(float dt, bool applygravity, vector stepnormal, float stepheight) // SV_FlyMove
+{
+ int blocked = 0, bumpcount;
+ int i, j, numplanes = 0;
+ float time_left = dt, grav = 0;
+ vector push;
+ vector primal_velocity, original_velocity, new_velocity = '0 0 0', restore_velocity;
+
+ for(i = 0; i <= MAX_CLIP_PLANES; ++i)
+ planes[i] = '0 0 0';
+
+ grav = 0;
+
+ restore_velocity = self.move_velocity;
+
+ if(applygravity)
+ {
+ self.move_didgravity = 1;
+ grav = dt * (PHYS_ENTGRAVITY(self) ? PHYS_ENTGRAVITY(self) : 1) * PHYS_GRAVITY;
+
+ if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !(self.move_flags & FL_ONGROUND))
+ {
+ if(GRAVITY_UNAFFECTED_BY_TICRATE)
+ self.move_velocity_z -= grav * 0.5;
+ else
+ self.move_velocity_z -= grav;
+ }
+ }
+
+ original_velocity = primal_velocity = self.move_velocity;
+
+ for(bumpcount = 0;bumpcount < MAX_CLIP_PLANES;bumpcount++)
+ {
+ if(!self.move_velocity_x && !self.move_velocity_y && !self.move_velocity_z)
+ break;
+
+ push = self.move_velocity * time_left;
+ if(!_Movetype_PushEntity(push, false))
+ {
+ // we got teleported by a touch function
+ // let's abort the move
+ blocked |= 8;
+ break;
+ }
+
+ // this code is used by MOVETYPE_WALK and MOVETYPE_STEP and SV_UnstickEntity
+ // abort move if we're stuck in the world (and didn't make it out)
+ if(trace_startsolid && trace_allsolid)
+ {
+ self.move_velocity = restore_velocity;
+ return 3;
+ }
+
+ if(trace_fraction == 1)
+ break;
+ if(trace_plane_normal_z)
+ {
+ if(trace_plane_normal_z > 0.7)
+ {
+ // floor
+ blocked |= 1;
+
+ if(!trace_ent)
+ {
+ //dprint("_Movetype_FlyMove: !trace_ent\n");
+ trace_ent = world;
+ }
+
+ self.move_flags |= FL_ONGROUND;
+ self.move_groundentity = trace_ent;
+ }
+ }
+ else if(stepheight)
+ {
+ // step - handle it immediately
+ vector org;
+ vector steppush;
+ //Con_Printf("step %f %f %f : ", self.move_origin_x, PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
+ steppush = '0 0 1' * stepheight;
+ org = self.move_origin;
+ if(!_Movetype_PushEntity(steppush, false))
+ {
+ blocked |= 8;
+ break;
+ }
+ //Con_Printf("%f %f %f : ", self.move_origin_x, PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
+ if(!_Movetype_PushEntity(push, false))
+ {
+ blocked |= 8;
+ break;
+ }
+ float trace2_fraction = trace_fraction;
+ //Con_Printf("%f %f %f : ", self.move_origin_x, PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
+ steppush = '0 0 1' * (org_z - self.move_origin_z);
+ if(!_Movetype_PushEntity(steppush, false))
+ {
+ blocked |= 8;
+ break;
+ }
+ //Con_Printf("%f %f %f : ", self.move_origin_x, PRVM_serveredictvector(ent, origin)[1], PRVM_serveredictvector(ent, origin)[2]);
+ // accept the new position if it made some progress...
+ if(fabs(self.move_origin_x - org_x) >= 0.03125 || fabs(self.move_origin_y - org_y) >= 0.03125)
+ {
+ //Con_Printf("accepted (delta %f %f %f)\n", self.move_origin_x - org_x, PRVM_serveredictvector(ent, origin)[1] - org[1], PRVM_serveredictvector(ent, origin)[2] - org[2]);
+ trace_endpos = self.move_origin;
+ time_left *= 1 - trace2_fraction;
+ numplanes = 0;
+ continue;
+ }
+ else
+ {
+ //Con_Printf("REJECTED (delta %f %f %f)\n", self.move_origin_x - org_x, PRVM_serveredictvector(ent, origin)[1] - org[1], PRVM_serveredictvector(ent, origin)[2] - org[2]);
+ self.move_origin = org;
+ }
+ }
+ else
+ {
+ // step - return it to caller
+ blocked |= 2;
+ // save the trace for player extrafriction
+ if(stepnormal)
+ stepnormal = trace_plane_normal;
+ }
+ if(trace_fraction >= 0.001)
+ {
+ // actually covered some distance
+ original_velocity = self.move_velocity;
+ numplanes = 0;
+ }
+
+ time_left *= 1 - trace_fraction;
+
+ // clipped to another plane
+ if(numplanes >= MAX_CLIP_PLANES)
+ {
+ // this shouldn't really happen
+ self.move_velocity = '0 0 0';
+ blocked = 3;
+ break;
+ }
+
+ planes[numplanes] = trace_plane_normal;
+ numplanes++;
+
+ // modify original_velocity so it parallels all of the clip planes
+ for (i = 0;i < numplanes;i++)
+ {
+ new_velocity = _Movetype_ClipVelocity(original_velocity, planes[i], 1);
+ for (j = 0;j < numplanes;j++)
+ {
+ if(j != i)
+ {
+ // not ok
+ if((new_velocity * planes[j]) < 0)
+ break;
+ }
+ }
+ if(j == numplanes)
+ break;
+ }
+
+ if(i != numplanes)
+ {
+ // go along this plane
+ self.move_velocity = new_velocity;
+ }
+ else
+ {
+ // go along the crease
+ if(numplanes != 2)
+ {
+ self.move_velocity = '0 0 0';
+ blocked = 7;
+ break;
+ }
+ vector dir;
+ dir.x = planes[0].y * planes[1].z - planes[0].z * planes[1].y;
+ dir.y = planes[0].z * planes[1].x - planes[0].x * planes[1].z;
+ dir.z = planes[0].x * planes[1].y - planes[0].y * planes[1].x;
+ // LordHavoc: thanks to taniwha of QuakeForge for pointing out this fix for slowed falling in corners
+ float ilength = sqrt((dir * dir));
+ if(ilength)
+ ilength = 1.0 / ilength;
+ dir.x *= ilength;
+ dir.y *= ilength;
+ dir.z *= ilength;
+ float d = (dir * self.move_velocity);
+ self.move_velocity = dir * d;
+ }
+
+ // if current velocity is against the original velocity,
+ // stop dead to avoid tiny occilations in sloping corners
+ if((self.move_velocity * primal_velocity) <= 0)
+ {
+ self.move_velocity = '0 0 0';
+ break;
+ }
+ }
+
+ // LordHavoc: this came from QW and allows you to get out of water more easily
+ if(GAMEPLAYFIX_EASIERWATERJUMP && (self.move_flags & FL_WATERJUMP) && !(blocked & 8))
+ self.move_velocity = primal_velocity;
+
+ if(applygravity)
+ {
+ if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !(self.move_flags & FL_ONGROUND))
+ {
+ if(GRAVITY_UNAFFECTED_BY_TICRATE)
+ self.move_velocity_z -= grav * 0.5f;
+ }
+ }
+
+ return blocked;
}
-float _Movetype_CheckWater(entity ent) // SV_CheckWater
+void _Movetype_CheckVelocity() // SV_CheckVelocity
+{
+ // if(vlen(self.move_velocity) < 0.0001)
+ // self.move_velocity = '0 0 0';
+}
+
+bool _Movetype_CheckWater(entity ent) // SV_CheckWater
{
vector point = ent.move_origin;
- point_z += (ent.mins_z + 1);
+ point.z += (ent.mins.z + 1);
int nativecontents = pointcontents(point);
-
- if(ent.move_watertype)
- if(ent.move_watertype != nativecontents)
+ if(ent.move_watertype && ent.move_watertype != nativecontents)
{
- //dprintf("_Movetype_CheckWater(): Original: '%d', New: '%d'\n", ent.move_watertype, nativecontents);
+ // dprintf("_Movetype_CheckWater(): Original: '%d', New: '%d'\n", ent.move_watertype, nativecontents);
if(ent.contentstransition)
ent.contentstransition(ent.move_watertype, nativecontents);
}
{
ent.move_watertype = nativecontents;
ent.move_waterlevel = 1;
- point_y = (ent.origin_y + ((ent.mins_z + ent.maxs_y) * 0.5));
+ point.y = (ent.origin.y + ((ent.mins.z + ent.maxs.y) * 0.5));
if(Mod_Q1BSP_SuperContentsFromNativeContents(pointcontents(point)) & DPCONTENTS_LIQUIDSMASK)
{
ent.move_waterlevel = 2;
- point_y = ent.origin_y + ent.view_ofs_y;
+ point.y = ent.origin.y + ent.view_ofs.y;
if(Mod_Q1BSP_SuperContentsFromNativeContents(pointcontents(point)) & DPCONTENTS_LIQUIDSMASK)
ent.move_waterlevel = 3;
}
}
- return (ent.move_waterlevel > 1);
+ return ent.move_waterlevel > 1;
}
-void _Movetype_CheckWaterTransition(entity ent) // SV_CheckWaterTransition
+void _Movetype_CheckWaterTransition(entity ent) // SV_CheckWaterTransition
{
- float contents = pointcontents(ent.move_origin);
+ int contents = pointcontents(ent.move_origin);
if(!ent.move_watertype)
{
}
else if(ent.move_watertype != contents)
{
- //dprintf("_Movetype_CheckWaterTransition(): Origin: %s, Direct: '%d', Original: '%d', New: '%d'\n", vtos(ent.move_origin), pointcontents(ent.move_origin), ent.move_watertype, contents);
+ // dprintf("_Movetype_CheckWaterTransition(): Origin: %s, Direct: '%d', Original: '%d', New: '%d'\n", vtos(ent.move_origin), pointcontents(ent.move_origin), ent.move_watertype, contents);
if(ent.contentstransition)
ent.contentstransition(ent.move_watertype, contents);
}
}
}
-void _Movetype_Impact(entity oth) // SV_Impact
+void _Movetype_Impact(entity oth) // SV_Impact
{
- entity oldother, oldself;
-
- oldself = self;
- oldother = other;
+ entity oldself = self;
+ entity oldother = other;
if(self.move_touch)
{
}
}
-void _Movetype_LinkEdict_TouchAreaGrid() // SV_LinkEdict_TouchAreaGrid
+void _Movetype_LinkEdict_TouchAreaGrid() // SV_LinkEdict_TouchAreaGrid
{
- entity e, oldself, oldother;
-
- oldself = self;
- oldother = other;
+ entity oldself = self;
+ entity oldother = other;
- for(e = findradius(0.5 * (self.absmin + self.absmax), 0.5 * vlen(self.absmax - self.absmin)); e; e = e.chain)
+ for (entity e = findradius(0.5 * (self.absmin + self.absmax), 0.5 * vlen(self.absmax - self.absmin)); e; e = e.chain)
{
- if(e.move_touch)
- if(boxesoverlap(e.absmin, e.absmax, oldself.absmin, oldself.absmax))
+ if(e.move_touch && boxesoverlap(e.absmin, e.absmax, oldself.absmin, oldself.absmax))
{
self = e;
other = oldself;
self = oldself;
}
-void _Movetype_LinkEdict(float touch_triggers) // SV_LinkEdict
+void _Movetype_LinkEdict(bool touch_triggers) // SV_LinkEdict
{
vector mi, ma;
if(self.solid == SOLID_BSP)
mi = self.mins;
ma = self.maxs;
}
- mi = mi + self.origin;
- ma = ma + self.origin;
+ mi += self.move_origin;
+ ma += self.move_origin;
if(self.move_flags & FL_ITEM)
{
- mi_x -= 15;
- mi_y -= 15;
- mi_z -= 1;
- ma_x += 15;
- ma_y += 15;
- ma_z += 1;
+ mi.x -= 15;
+ mi.y -= 15;
+ mi.z -= 1;
+ ma.x += 15;
+ ma.y += 15;
+ ma.z += 1;
}
else
{
- mi_x -= 1;
- mi_y -= 1;
- mi_z -= 1;
- ma_x += 1;
- ma_y += 1;
- ma_z += 1;
+ mi.x -= 1;
+ mi.y -= 1;
+ mi.z -= 1;
+ ma.x += 1;
+ ma.y += 1;
+ ma.z += 1;
}
self.absmin = mi;
_Movetype_LinkEdict_TouchAreaGrid();
}
-float _Movetype_TestEntityPosition(vector ofs) // SV_TestEntityPosition
+bool _Movetype_TestEntityPosition(vector ofs) // SV_TestEntityPosition
{
- vector org;
- org = self.move_origin + ofs;
+// vector org = self.move_origin + ofs;
int cont = self.dphitcontentsmask;
self.dphitcontentsmask = DPCONTENTS_SOLID;
return false;
}
-float _Movetype_UnstickEntity() // SV_UnstickEntity
+bool _Movetype_UnstickEntity() // SV_UnstickEntity
{
- if(!_Movetype_TestEntityPosition('0 0 0'))
- return true;
+ if(!_Movetype_TestEntityPosition('0 0 0')) return true;
if(!_Movetype_TestEntityPosition('-1 0 0')) goto success;
if(!_Movetype_TestEntityPosition('1 0 0')) goto success;
if(!_Movetype_TestEntityPosition('0 -1 0')) goto success;
if(!_Movetype_TestEntityPosition('1 -1 0')) goto success;
if(!_Movetype_TestEntityPosition('-1 1 0')) goto success;
if(!_Movetype_TestEntityPosition('1 1 0')) goto success;
- float i;
- for(i = 1; i <= 17; ++i)
+ for (int i = 1; i <= 17; ++i)
{
if(!_Movetype_TestEntityPosition('0 0 -1' * i)) goto success;
if(!_Movetype_TestEntityPosition('0 0 1' * i)) goto success;
}
- dprintf("Can't unstick an entity (edict: %d, classname: %s, origin: %s)\n", num_for_edict(self), self.classname, vtos(self.move_origin));
+ dprintf("Can't unstick an entity (edict: %d, classname: %s, origin: %s)\n",
+ num_for_edict(self), self.classname, vtos(self.move_origin));
return false;
-:success
- dprintf("Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)\n", num_for_edict(self), self.classname, vtos(self.move_origin));
+ : success;
+ dprintf("Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)\n",
+ num_for_edict(self), self.classname, vtos(self.move_origin));
_Movetype_LinkEdict(true);
return true;
}
-vector _Movetype_ClipVelocity(vector vel, vector norm, float f) // SV_ClipVelocity
+vector _Movetype_ClipVelocity(vector vel, vector norm, float f) // SV_ClipVelocity
{
- vel = vel - ((vel * norm) * norm) * f;
+ vel -= ((vel * norm) * norm) * f;
- if(vel_x > -0.1 && vel_x < 0.1) vel_x = 0;
- if(vel_y > -0.1 && vel_y < 0.1) vel_y = 0;
- if(vel_z > -0.1 && vel_z < 0.1) vel_z = 0;
+ if(vel.x > -0.1 && vel.x < 0.1) vel.x = 0;
+ if(vel.y > -0.1 && vel.y < 0.1) vel.y = 0;
+ if(vel.z > -0.1 && vel.z < 0.1) vel.z = 0;
return vel;
}
void _Movetype_PushEntityTrace(vector push)
{
- vector end;
- float type;
-
- end = self.move_origin + push;
-
+ vector end = self.move_origin + push;
+ int type;
if(self.move_nomonsters)
type = max(0, self.move_nomonsters);
else if(self.move_movetype == MOVETYPE_FLYMISSILE)
tracebox(self.move_origin, self.mins, self.maxs, end, type, self);
}
-float _Movetype_PushEntity(vector push, float failonstartsolid) // SV_PushEntity
+float _Movetype_PushEntity(vector push, bool failonstartsolid) // SV_PushEntity
{
_Movetype_PushEntityTrace(push);
.float ltime;
.void() blocked;
// matrix version of makevectors, sets v_forward, v_right and v_up
-void makevectors_matrix(vector myangles) // AngleVectorsFLU
+void makevectors_matrix(vector myangles) // AngleVectorsFLU
{
- float angle, sr, sp, sy, cr, cp, cy;
-
v_forward = v_right = v_up = '0 0 0';
- angle = myangles_y * (M_PI*2 / 360);
- sy = sin(angle);
- cy = cos(angle);
- angle = myangles_x * (M_PI*2 / 360);
- sp = sin(angle);
- cp = cos(angle);
+ float y = myangles.y * (M_PI * 2 / 360);
+ float sy = sin(y);
+ float cy = cos(y);
+ float p = myangles.x * (M_PI * 2 / 360);
+ float sp = sin(p);
+ float cp = cos(p);
if(v_forward)
{
- v_forward_x = cp*cy;
- v_forward_y = cp*sy;
- v_forward_z = -sp;
+ v_forward.x = cp * cy;
+ v_forward.y = cp * sy;
+ v_forward.z = -sp;
}
if(v_right || v_up)
{
- if(myangles_z)
+ if(myangles.z)
{
- angle = myangles_z * (M_PI*2 / 360);
- sr = sin(angle);
- cr = cos(angle);
+ float r = myangles.z * (M_PI * 2 / 360);
+ float sr = sin(r);
+ float cr = cos(r);
if(v_right)
{
- v_right_x = sr*sp*cy+cr*-sy;
- v_right_y = sr*sp*sy+cr*cy;
- v_right_z = sr*cp;
+ v_right.x = sr * sp * cy + cr * -sy;
+ v_right.y = sr * sp * sy + cr * cy;
+ v_right.z = sr * cp;
}
if(v_up)
{
- v_up_x = cr*sp*cy+-sr*-sy;
- v_up_y = cr*sp*sy+-sr*cy;
- v_up_z = cr*cp;
+ v_up.x = cr * sp * cy + -sr * -sy;
+ v_up.y = cr * sp * sy + -sr * cy;
+ v_up.z = cr * cp;
}
}
else
{
if(v_right)
{
- v_right_x = -sy;
- v_right_y = cy;
- v_right_z = 0;
+ v_right.x = -sy;
+ v_right.y = cy;
+ v_right.z = 0;
}
if(v_up)
{
- v_up_x = sp*cy;
- v_up_y = sp*sy;
- v_up_z = cp;
+ v_up.x = sp * cy;
+ v_up.y = sp * sy;
+ v_up.z = cp;
}
}
}
void _Movetype_Physics_Frame(float movedt)
{
self.move_didgravity = -1;
- switch(self.move_movetype)
+ switch (self.move_movetype)
{
case MOVETYPE_PUSH:
case MOVETYPE_FAKEPUSH:
error("SV_Physics_Step not implemented");
break;
case MOVETYPE_WALK:
- error("SV_Physics_Walk not implemented");
+ _Movetype_Physics_Walk(movedt);
break;
case MOVETYPE_TOSS:
case MOVETYPE_BOUNCE:
}
}
-void Movetype_Physics_NoMatchServer() // optimized
+void Movetype_Physics_NoMatchServer() // optimized
{
- float movedt;
-
- movedt = time - self.move_time;
+ float movedt = time - self.move_time;
self.move_time = time;
_Movetype_Physics_Frame(movedt);
Movetype_Physics_MatchTicrate(TICRATE, sloppy);
}
-void Movetype_Physics_MatchTicrate(float tr, bool sloppy) // SV_Physics_Entity
+void Movetype_Physics_MatchTicrate(float tr, bool sloppy) // SV_Physics_Entity
{
- float n, i, dt, movedt;
-
if(tr <= 0)
{
Movetype_Physics_NoMatchServer();
return;
}
- dt = time - self.move_time;
+ float dt = time - self.move_time;
- movedt = tr;
- n = max(0, floor(dt / tr));
+ int n = max(0, floor(dt / tr));
dt -= n * tr;
self.move_time += n * tr;
if(!self.move_didgravity)
self.move_didgravity = ((self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS) && !(self.move_flags & FL_ONGROUND));
- for(i = 0; i < n; ++i)
+ for (int i = 0; i < n; ++i)
{
- _Movetype_Physics_Frame(movedt);
+ _Movetype_Physics_Frame(tr);
if(wasfreed(self))
return;
}
if(self.move_didgravity > 0)
{
- if(GRAVITY_UNAFFECTED_BY_TICRATE)
- {
- if(self.gravity)
- self.velocity_z -= 0.5 * dt * self.gravity * PHYS_GRAVITY;
- else
- self.velocity_z -= 0.5 * dt * PHYS_GRAVITY;
- }
- else
- {
- if(self.gravity)
- self.velocity_z -= dt * self.gravity * PHYS_GRAVITY;
- else
- self.velocity_z -= dt * PHYS_GRAVITY;
- }
+ self.velocity_z -= (GRAVITY_UNAFFECTED_BY_TICRATE ? 0.5 : 1)
+ * dt
+ * (self.gravity ? self.gravity : 1)
+ * PHYS_GRAVITY;
}
self.angles = self.move_angles + dt * self.avelocity;
- if(sloppy || self.movetype == MOVETYPE_NOCLIP)
+ if(sloppy || self.move_movetype == MOVETYPE_NOCLIP)
{
setorigin(self, self.move_origin + dt * self.velocity);
}
setorigin(self, trace_endpos);
}
- if(self.move_didgravity > 0)
- {
- if(GRAVITY_UNAFFECTED_BY_TICRATE)
- {
- if(self.gravity)
- self.velocity_z -= 0.5 * dt * self.gravity * PHYS_GRAVITY;
- else
- self.velocity_z -= 0.5 * dt * PHYS_GRAVITY;
- }
- }
+ if(self.move_didgravity > 0 && GRAVITY_UNAFFECTED_BY_TICRATE)
+ self.velocity_z -= 0.5 * dt * (self.gravity ? self.gravity : 1) * PHYS_GRAVITY;
}
else
{
#define MOVETYPES_H
.float move_ltime;
-.void(void) move_think;
+.void(void)move_think;
.float move_nextthink;
-.void(void) move_blocked;
+.void(void)move_blocked;
.float move_movetype;
.float move_time;
.int move_flags;
.int move_watertype;
.int move_waterlevel;
-.void(void) move_touch;
-.void(float, float) contentstransition;
+.void(void)move_touch;
+.void(float, float)contentstransition;
.float move_bounce_factor;
.float move_bounce_stopspeed;
-.float move_nomonsters; // -1 for MOVE_NORMAL, otherwise a MOVE_ constant
+.float move_nomonsters; // -1 for MOVE_NORMAL, otherwise a MOVE_ constant
// should match sv_gameplayfix_fixedcheckwatertransition
float autocvar_cl_gameplayfix_fixedcheckwatertransition = 1;
#define TICRATE ticrate
#endif
-.entity move_groundentity; // FIXME add move_groundnetworkentity?
+.entity move_groundentity; // FIXME add move_groundnetworkentity?
.float move_suspendedinair;
.float move_didgravity;
+void _Movetype_WallFriction(vector stepnormal);
+int _Movetype_FlyMove(float dt, bool applygravity, vector stepnormal, float stepheight);
void _Movetype_CheckVelocity();
void _Movetype_CheckWaterTransition(entity ent);
+float _Movetype_CheckWater(entity ent);
void _Movetype_LinkEdict_TouchAreaGrid();
void _Movetype_LinkEdict(float touch_triggers);
float _Movetype_TestEntityPosition(vector ofs);
const int MAX_CLIP_PLANES = 5;
#ifdef CSQC
-const int MOVETYPE_NONE = 0;
-const int MOVETYPE_ANGLENOCLIP = 1;
-const int MOVETYPE_ANGLECLIP = 2;
-const int MOVETYPE_WALK = 3;
-const int MOVETYPE_STEP = 4;
-const int MOVETYPE_FLY = 5;
-const int MOVETYPE_TOSS = 6;
-const int MOVETYPE_PUSH = 7;
-const int MOVETYPE_NOCLIP = 8;
-const int MOVETYPE_FLYMISSILE = 9;
-const int MOVETYPE_BOUNCE = 10;
-const int MOVETYPE_BOUNCEMISSILE = 11; // Like bounce but doesn't lose speed on bouncing
+const int MOVETYPE_NONE = 0;
+const int MOVETYPE_ANGLENOCLIP = 1;
+const int MOVETYPE_ANGLECLIP = 2;
+const int MOVETYPE_WALK = 3;
+const int MOVETYPE_STEP = 4;
+const int MOVETYPE_FLY = 5;
+const int MOVETYPE_TOSS = 6;
+const int MOVETYPE_PUSH = 7;
+const int MOVETYPE_NOCLIP = 8;
+const int MOVETYPE_FLYMISSILE = 9;
+const int MOVETYPE_BOUNCE = 10;
+const int MOVETYPE_BOUNCEMISSILE = 11; // Like bounce but doesn't lose speed on bouncing
const int MOVETYPE_FOLLOW = 12;
const int MOVETYPE_FLY_WORLDONLY = 33;
-void _Movetype_PushMove(float dt) // SV_PushMove
+void _Movetype_PushMove(float dt) // SV_PushMove
{
- bool rotated;
- int savesolid;
- float movetime2, pushltime;
- vector move, move1, moveangle, pushorig, pushang;
- vector a;
- vector pivot;
- entity oldself;
- entity check;
-
- if(self.move_velocity == '0 0 0' && self.move_avelocity == '0 0 0')
+ if (self.move_velocity == '0 0 0' && self.move_avelocity == '0 0 0')
{
self.move_ltime += dt;
return;
}
- switch(self.solid)
+ switch (self.solid)
{
- // LordHavoc: valid pusher types
- case SOLID_BSP:
- case SOLID_BBOX:
- case SOLID_SLIDEBOX:
- case SOLID_CORPSE: // LordHavoc: this would be weird...
- break;
- // LordHavoc: no collisions
- case SOLID_NOT:
- case SOLID_TRIGGER:
- self.move_origin = self.move_origin + dt * self.move_velocity;
- self.move_angles = self.move_angles + dt * self.move_avelocity;
- self.move_angles_x -= 360.0 * floor(self.move_angles_x * (1.0 / 360.0));
- self.move_angles_y -= 360.0 * floor(self.move_angles_y * (1.0 / 360.0));
- self.move_angles_z -= 360.0 * floor(self.move_angles_z * (1.0 / 360.0));
- self.move_ltime += dt;
- _Movetype_LinkEdict(true);
- return;
- default:
- dprintf("_Movetype_PushMove: entity %e, unrecognized solid type %d\n", self, self.solid);
- return;
+ // LordHavoc: valid pusher types
+ case SOLID_BSP:
+ case SOLID_BBOX:
+ case SOLID_SLIDEBOX:
+ case SOLID_CORPSE: // LordHavoc: this would be weird...
+ break;
+ // LordHavoc: no collisions
+ case SOLID_NOT:
+ case SOLID_TRIGGER:
+ self.move_origin = self.move_origin + dt * self.move_velocity;
+ self.move_angles = self.move_angles + dt * self.move_avelocity;
+ self.move_angles_x -= 360.0 * floor(self.move_angles.x * (1.0 / 360.0));
+ self.move_angles_y -= 360.0 * floor(self.move_angles.y * (1.0 / 360.0));
+ self.move_angles_z -= 360.0 * floor(self.move_angles.z * (1.0 / 360.0));
+ self.move_ltime += dt;
+ _Movetype_LinkEdict(true);
+ return;
+ default:
+ dprintf("_Movetype_PushMove: entity %e, unrecognized solid type %d\n", self, self.solid);
+ return;
}
- rotated = (self.move_angles * self.move_angles) + (self.move_avelocity * self.move_avelocity) > 0;
+ bool rotated = (self.move_angles * self.move_angles) + (self.move_avelocity * self.move_avelocity) > 0;
- movetime2 = dt;
+ vector move1 = self.move_velocity * dt;
+ vector moveangle = self.move_avelocity * dt;
- move1 = self.move_velocity * movetime2;
- moveangle = self.move_avelocity * movetime2;
+ makevectors_matrix(-moveangle);
- a = -moveangle;
- makevectors_matrix(a);
-
- pushorig = self.move_origin;
- pushang = self.move_angles;
- pushltime = self.move_ltime;
+// vector pushorig = self.move_origin;
+// vector pushang = self.move_angles;
+// float pushltime = self.move_ltime;
// move the pusher to its final position
self.move_origin = self.move_origin + dt * self.move_velocity;
self.move_angles = self.move_angles + dt * self.move_avelocity;
-
+
self.move_ltime += dt;
_Movetype_LinkEdict(true);
- savesolid = self.solid;
+ int savesolid = self.solid;
- if(self.move_movetype != MOVETYPE_FAKEPUSH)
- for(check = findradius(0.5 * (self.absmin + self.absmax), 0.5 * vlen(self.absmax - self.absmin)); check; check = check.chain)
+ if (self.move_movetype != MOVETYPE_FAKEPUSH)
{
- switch(check.move_movetype)
+ for (entity check = findradius(0.5 * (self.absmin + self.absmax), 0.5 * vlen(self.absmax - self.absmin)); check; check = check.chain)
{
- case MOVETYPE_NONE:
- case MOVETYPE_PUSH:
- case MOVETYPE_FOLLOW:
- case MOVETYPE_NOCLIP:
- case MOVETYPE_FLY_WORLDONLY:
- continue;
- default:
- break;
- }
-
- if(check.owner == self)
- continue;
-
- if(self.owner == check)
- continue;
-
- pivot = check.mins + 0.5 * (check.maxs - check.mins);
-
- if (rotated)
- {
- vector org2;
- vector org = check.move_origin - self.move_origin;
- org = org + pivot;
- org2_x = dotproduct(org, v_forward);
- org2_y = dotproduct(org, v_right);
- org2_z = dotproduct(org, v_up);
- move = org2 - org;
- move = move + move1;
- }
- else
- move = move1;
-
- // physics objects need better collisions than this code can do
- if(check.move_movetype == 32) // MOVETYPE_PHYSICS
- {
- check.move_origin = check.move_origin + move;
- oldself = self;
+ switch (check.move_movetype)
+ {
+ case MOVETYPE_NONE:
+ case MOVETYPE_PUSH:
+ case MOVETYPE_FOLLOW:
+ case MOVETYPE_NOCLIP:
+ case MOVETYPE_FLY_WORLDONLY:
+ continue;
+ default:
+ break;
+ }
+
+ if (check.owner == self)
+ continue;
+
+ if (self.owner == check)
+ continue;
+
+ vector pivot = check.mins + 0.5 * (check.maxs - check.mins);
+ vector move;
+ if (rotated)
+ {
+ vector org = (check.move_origin - self.move_origin) + pivot;
+ vector org2;
+ org2.x = org * v_forward;
+ org2.y = org * v_right;
+ org2.z = org * v_up;
+ move = (org2 - org) + move1;
+ }
+ else
+ {
+ move = move1;
+ }
+
+ // physics objects need better collisions than this code can do
+ if (check.move_movetype == 32) // MOVETYPE_PHYSICS
+ {
+ check.move_origin = check.move_origin + move;
+ entity oldself = self;
+ self = check;
+ _Movetype_LinkEdict(true);
+ self = oldself;
+ continue;
+ }
+
+ // try moving the contacted entity
+ self.solid = SOLID_NOT;
+ entity oldself = self;
self = check;
- _Movetype_LinkEdict(true);
- self = oldself;
- continue;
- }
-
- // try moving the contacted entity
- self.solid = SOLID_NOT;
- oldself = self;
- self = check;
- if(!_Movetype_PushEntity(move, true))
- {
+ if (!_Movetype_PushEntity(move, true))
+ {
+ self = oldself;
+ // entity "check" got teleported
+ check.move_angles_y += trace_fraction * moveangle.y;
+ self.solid = savesolid;
+ continue; // pushed enough
+ }
self = oldself;
- // entity "check" got teleported
- check.move_angles_y += trace_fraction * moveangle_y;
+ // FIXME: turn players specially
+ check.move_angles_y += trace_fraction * moveangle.y;
self.solid = savesolid;
- continue; // pushed enough
+
+ // this trace.fraction < 1 check causes items to fall off of pushers
+ // if they pass under or through a wall
+ // the groundentity check causes items to fall off of ledges
+ if (check.move_movetype != MOVETYPE_WALK && (trace_fraction < 1 || check.move_groundentity != self))
+ check.move_flags &= ~FL_ONGROUND;
}
- self = oldself;
- // FIXME: turn players specially
- check.move_angles_y += trace_fraction * moveangle_y;
- self.solid = savesolid;
-
- // this trace.fraction < 1 check causes items to fall off of pushers
- // if they pass under or through a wall
- // the groundentity check causes items to fall off of ledges
- if(check.move_movetype != MOVETYPE_WALK && (trace_fraction < 1 || check.move_groundentity != self))
- check.move_flags &= ~FL_ONGROUND;
}
- self.move_angles_x -= 360.0 * floor(self.move_angles_x * (1.0 / 360.0));
- self.move_angles_y -= 360.0 * floor(self.move_angles_y * (1.0 / 360.0));
- self.move_angles_z -= 360.0 * floor(self.move_angles_z * (1.0 / 360.0));
+ self.move_angles_x -= 360.0 * floor(self.move_angles.x * (1.0 / 360.0));
+ self.move_angles_y -= 360.0 * floor(self.move_angles.y * (1.0 / 360.0));
+ self.move_angles_z -= 360.0 * floor(self.move_angles.z * (1.0 / 360.0));
}
-void _Movetype_Physics_Pusher(float dt) // SV_Physics_Pusher
+void _Movetype_Physics_Pusher(float dt) // SV_Physics_Pusher
{
- float thinktime, oldltime, movetime;
-
- oldltime = self.move_ltime;
-
- thinktime = self.move_nextthink;
- if(thinktime < self.move_ltime + dt)
+ float oldltime = self.move_ltime;
+ float thinktime = self.move_nextthink;
+ float movetime;
+ if (thinktime < self.move_ltime + dt)
{
movetime = thinktime - self.move_ltime;
- if(movetime < 0)
+ if (movetime < 0)
movetime = 0;
}
else
+ {
movetime = dt;
+ }
- if(movetime)
+ if (movetime)
// advances self.move_ltime if not blocked
_Movetype_PushMove(movetime);
- if(thinktime > oldltime && thinktime <= self.move_ltime)
+ if (thinktime > oldltime && thinktime <= self.move_ltime)
{
self.move_nextthink = 0;
self.move_time = time;
other = world;
- if(self.move_think)
+ if (self.move_think)
self.move_think();
}
}
#include "../physics.qh"
-void _Movetype_Physics_Toss(float dt) // SV_Physics_Toss
+void _Movetype_Physics_Toss(float dt) // SV_Physics_Toss
{
- if(self.move_flags & FL_ONGROUND)
+ if (self.move_flags & FL_ONGROUND)
{
- if(self.move_velocity_z >= 1/32)
+ if (self.move_velocity.z >= 1 / 32)
+ {
self.move_flags &= ~FL_ONGROUND;
- else if(!self.move_groundentity)
+ }
+ else if (!self.move_groundentity)
+ {
return;
- else if(self.move_suspendedinair && wasfreed(self.move_groundentity))
+ }
+ else if (self.move_suspendedinair && wasfreed(self.move_groundentity))
{
self.move_groundentity = world;
return;
_Movetype_CheckVelocity();
- if(self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS)
+ if (self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS)
{
self.move_didgravity = 1;
- if(GRAVITY_UNAFFECTED_BY_TICRATE)
- {
- if(self.gravity)
- self.move_velocity_z -= 0.5 * dt * self.gravity * PHYS_GRAVITY;
- else
- self.move_velocity_z -= 0.5 * dt * PHYS_GRAVITY;
- }
- else
- {
- if(self.gravity)
- self.move_velocity_z -= dt * self.gravity * PHYS_GRAVITY;
- else
- self.move_velocity_z -= dt * PHYS_GRAVITY;
- }
+ self.move_velocity_z -= (GRAVITY_UNAFFECTED_BY_TICRATE ? 0.5 : 1)
+ * dt
+ * (self.gravity ? self.gravity : 1)
+ * PHYS_GRAVITY;
}
self.move_angles = self.move_angles + self.move_avelocity * dt;
- float movetime, bump;
- movetime = dt;
- for(bump = 0; bump < MAX_CLIP_PLANES && movetime > 0; ++bump)
+ float movetime = dt;
+ for (int bump = 0; bump < MAX_CLIP_PLANES && movetime > 0; ++bump)
{
- vector move;
- move = self.move_velocity * movetime;
+ vector move = self.move_velocity * movetime;
_Movetype_PushEntity(move, true);
- if(wasfreed(self))
+ if (wasfreed(self))
return;
- if(trace_startsolid)
+ if (trace_startsolid)
{
_Movetype_UnstickEntity();
_Movetype_PushEntity(move, false);
- if(wasfreed(self))
+ if (wasfreed(self))
return;
}
- if(trace_fraction == 1)
+ if (trace_fraction == 1)
break;
movetime *= 1 - min(1, trace_fraction);
- if(self.move_movetype == MOVETYPE_BOUNCEMISSILE)
+ if (self.move_movetype == MOVETYPE_BOUNCEMISSILE)
{
self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 2.0);
self.move_flags &= ~FL_ONGROUND;
}
- else if(self.move_movetype == MOVETYPE_BOUNCE)
+ else if (self.move_movetype == MOVETYPE_BOUNCE)
{
- float d, bouncefac, bouncestop;
-
- bouncefac = self.move_bounce_factor; if(!bouncefac) bouncefac = 0.5;
- bouncestop = self.move_bounce_stopspeed; if(!bouncestop) bouncestop = 60 / 800;
- if(self.gravity)
- bouncestop *= self.gravity * PHYS_GRAVITY;
- else
- bouncestop *= PHYS_GRAVITY;
+ float bouncefac = self.move_bounce_factor; if (!bouncefac) bouncefac = 0.5;
+ float bouncestop = self.move_bounce_stopspeed; if (!bouncestop) bouncestop = 60 / 800;
+ bouncestop *= (self.gravity ? self.gravity : 1) * PHYS_GRAVITY;
self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 1 + bouncefac);
- d = trace_plane_normal * self.move_velocity;
- if(trace_plane_normal_z > 0.7 && d < bouncestop && d > -bouncestop)
+ float d = trace_plane_normal * self.move_velocity;
+ if (trace_plane_normal.z > 0.7 && d < bouncestop && d > -bouncestop)
{
self.move_flags |= FL_ONGROUND;
self.move_groundentity = trace_ent;
self.move_avelocity = '0 0 0';
}
else
+ {
self.move_flags &= ~FL_ONGROUND;
+ }
}
else
{
self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 1.0);
- if(trace_plane_normal_z > 0.7)
+ if (trace_plane_normal.z > 0.7)
{
self.move_flags |= FL_ONGROUND;
self.move_groundentity = trace_ent;
- if(trace_ent.solid == SOLID_BSP)
+ if (trace_ent.solid == SOLID_BSP)
self.move_suspendedinair = true;
self.move_velocity = '0 0 0';
self.move_avelocity = '0 0 0';
}
else
+ {
self.move_flags &= ~FL_ONGROUND;
+ }
}
// DP revision 8905 (just, WHY...)
- if(self.move_movetype == MOVETYPE_BOUNCEMISSILE)
+ if (self.move_movetype == MOVETYPE_BOUNCEMISSILE)
break;
// DP revision 8918 (WHY...)
- if(self.move_flags & FL_ONGROUND)
+ if (self.move_flags & FL_ONGROUND)
break;
}
- if(GRAVITY_UNAFFECTED_BY_TICRATE)
- if(self.move_didgravity > 0)
- if(!(self.move_flags & FL_ONGROUND))
- {
- if(self.gravity)
- self.move_velocity_z -= 0.5 * dt * self.gravity * PHYS_GRAVITY;
- else
- self.move_velocity_z -= 0.5 * dt * PHYS_GRAVITY;
- }
+ if (GRAVITY_UNAFFECTED_BY_TICRATE && self.move_didgravity > 0 && !(self.move_flags & FL_ONGROUND))
+ self.move_velocity_z -= 0.5 * dt * (self.gravity ? self.gravity : 1) * PHYS_GRAVITY;
_Movetype_CheckWaterTransition(self);
}
--- /dev/null
+void _Movetype_Physics_Walk(float dt) // SV_WalkMove
+{
+ vector stepnormal = '0 0 0';
+
+ // if frametime is 0 (due to client sending the same timestamp twice), don't move
+ if (dt <= 0)
+ return;
+
+ if (GAMEPLAYFIX_UNSTICKPLAYERS)
+ _Movetype_UnstickEntity();
+
+ bool applygravity = (!_Movetype_CheckWater(self) && self.move_movetype == MOVETYPE_WALK && !(self.move_flags & FL_WATERJUMP));
+
+ _Movetype_CheckVelocity();
+
+ // do a regular slide move unless it looks like you ran into a step
+ bool oldonground = (self.move_flags & FL_ONGROUND);
+
+ vector start_origin = self.move_origin;
+ vector start_velocity = self.move_velocity;
+
+ int clip = _Movetype_FlyMove(dt, applygravity, stepnormal, GAMEPLAYFIX_STEPMULTIPLETIMES ? PHYS_STEPHEIGHT : 0);
+
+ if (GAMEPLAYFIX_DOWNTRACEONGROUND && !(clip & 1))
+ {
+ // only try this if there was no floor in the way in the trace (no,
+ // this check seems to be not REALLY necessary, because if clip & 1,
+ // our trace will hit that thing too)
+ vector upmove = self.move_origin + '0 0 1';
+ vector downmove = self.move_origin - '0 0 1';
+ int type;
+ if (self.move_movetype == MOVETYPE_FLYMISSILE) type = MOVE_MISSILE; else if (self.move_movetype == MOVETYPE_FLY_WORLDONLY)
+ type = MOVE_WORLDONLY;
+ else if (self.solid == SOLID_TRIGGER || self.solid == SOLID_NOT)
+ type = MOVE_NOMONSTERS;
+ else type = MOVE_NORMAL;
+ tracebox(upmove, self.mins, self.maxs, downmove, type, self);
+ if (trace_fraction < 1 && trace_plane_normal.z > 0.7)
+ clip |= 1; // but we HAVE found a floor
+ }
+
+ // if the move did not hit the ground at any point, we're not on ground
+ if (!(clip & 1))
+ self.move_flags &= ~FL_ONGROUND;
+
+ _Movetype_CheckVelocity();
+ _Movetype_LinkEdict(true);
+
+ if (clip & 8) // teleport
+ return;
+
+ if (self.move_flags & FL_WATERJUMP)
+ return;
+
+ if (PHYS_NOSTEP)
+ return;
+
+ vector originalmove_origin = self.move_origin;
+ vector originalmove_velocity = self.move_velocity;
+ // originalmove_clip = clip;
+ int originalmove_flags = self.move_flags;
+ entity originalmove_groundentity = self.move_groundentity;
+
+ // 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.x) < 0.03125 && fabs(start_velocity.y) < 0.03125)
+ return;
+
+ if (self.move_movetype != MOVETYPE_FLY)
+ {
+ // return if gibbed by a trigger
+ if (self.move_movetype != MOVETYPE_WALK)
+ return;
+
+ // return if attempting to jump while airborn (unless sv_jumpstep)
+ if (!PHYS_JUMPSTEP)
+ if (!oldonground && self.move_waterlevel == 0)
+ return;
+ }
+
+ // try moving up and forward to go up a step
+ // back to start pos
+ self.move_origin = start_origin;
+ self.move_velocity = start_velocity;
+
+ // move up
+ vector upmove = '0 0 1' * PHYS_STEPHEIGHT;
+ if (!_Movetype_PushEntity(upmove, true))
+ {
+ // we got teleported when upstepping... must abort the move
+ return;
+ }
+
+ // move forward
+ self.move_velocity_z = 0;
+ clip = _Movetype_FlyMove(dt, applygravity, stepnormal, 0);
+ self.move_velocity_z += start_velocity.z;
+ if (clip & 8)
+ {
+ // we got teleported when upstepping... must abort the move
+ // note that z velocity handling may not be what QC expects here, but we cannot help it
+ return;
+ }
+
+ _Movetype_CheckVelocity();
+ _Movetype_LinkEdict(true);
+
+ // check for stuckness, possibly due to the limited precision of floats
+ // in the clipping hulls
+ if (clip
+ && fabs(originalmove_origin.y - self.move_origin.y) < 0.03125
+ && fabs(originalmove_origin.x - self.move_origin.x) < 0.03125)
+ {
+ // Con_Printf("wall\n");
+ // stepping up didn't make any progress, revert to original move
+ self.move_origin = originalmove_origin;
+ self.move_velocity = originalmove_velocity;
+ // clip = originalmove_clip;
+ self.move_flags = originalmove_flags;
+ self.move_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 && PHYS_WALLFRICTION)
+ _Movetype_WallFriction(stepnormal);
+ }
+ // don't do the down move if stepdown is disabled, moving upward, not in water, or the move started offground or ended onground
+ else if (!GAMEPLAYFIX_STEPDOWN || self.move_waterlevel >= 3 || start_velocity.z >= (1.0 / 32.0) || !oldonground || (self.move_flags & FL_ONGROUND))
+ {
+ return;
+ }
+
+ // move down
+ vector downmove = '0 0 1' * (-PHYS_STEPHEIGHT + start_velocity.z * dt);
+ if (!_Movetype_PushEntity(downmove, true))
+ {
+ // we got teleported when downstepping... must abort the move
+ return;
+ }
+
+ if (trace_fraction < 1 && trace_plane_normal.z > 0.7)
+ {
+ // this has been disabled so that you can't jump when you are stepping
+ // up while already jumping (also known as the Quake2 double jump bug)
+ }
+ 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
+ self.move_origin = originalmove_origin;
+ self.move_velocity = originalmove_velocity;
+ self.move_flags = originalmove_flags;
+ self.move_groundentity = originalmove_groundentity;
+ }
+
+ _Movetype_CheckVelocity();
+ _Movetype_LinkEdict(true);
+}
--- /dev/null
+#ifndef MOVETYPE_WALK_H
+#define MOVETYPE_WALK_H
+
+void _Movetype_Physics_Walk(float dt);
+
+#endif
PM_Main();
#ifdef CSQC
- self.pmove_flags = self.flags; // TODO
+ self.pmove_flags =
+ ((self.flags & FL_DUCKED) ? PMF_DUCKED : 0) |
+ (!(self.flags & FL_JUMPRELEASED) ? 0 : PMF_JUMP_HELD) |
+ ((self.flags & FL_ONGROUND) ? PMF_ONGROUND : 0);
#endif
}
#define GAMEPLAYFIX_NOGRAVITYONGROUND cvar("sv_gameplayfix_nogravityonground")
#define GAMEPLAYFIX_Q2AIRACCELERATE cvar("sv_gameplayfix_q2airaccelerate")
#define GAMEPLAYFIX_EASIERWATERJUMP getstati(STAT_GAMEPLAYFIX_EASIERWATERJUMP)
+ #define GAMEPLAYFIX_DOWNTRACEONGROUND getstati(STAT_GAMEPLAYFIX_DOWNTRACEONGROUND)
+ #define GAMEPLAYFIX_STEPMULTIPLETIMES getstati(STAT_GAMEPLAYFIX_STEPMULTIPLETIMES)
+ #define GAMEPLAYFIX_UNSTICKPLAYERS getstati(STAT_GAMEPLAYFIX_UNSTICKPLAYERS)
+ #define GAMEPLAYFIX_STEPDOWN getstati(STAT_GAMEPLAYFIX_STEPDOWN)
#define IS_DUCKED(s) !!(s.flags & FL_DUCKED)
#define SET_DUCKED(s) s.flags |= FL_DUCKED
#define PHYS_DOUBLEJUMP getstati(STAT_DOUBLEJUMP)
+ #define PHYS_BUGRIGS getstati(STAT_BUGRIGS)
+ #define PHYS_BUGRIGS_ANGLE_SMOOTHING getstati(STAT_BUGRIGS_ANGLE_SMOOTHING)
+ #define PHYS_BUGRIGS_PLANAR_MOVEMENT getstati(STAT_BUGRIGS_PLANAR_MOVEMENT)
+ #define PHYS_BUGRIGS_REVERSE_SPEEDING getstati(STAT_BUGRIGS_REVERSE_SPEEDING)
+ #define PHYS_BUGRIGS_FRICTION_FLOOR getstatf(STAT_BUGRIGS_FRICTION_FLOOR)
+ #define PHYS_BUGRIGS_AIR_STEERING getstati(STAT_BUGRIGS_AIR_STEERING)
+ #define PHYS_BUGRIGS_FRICTION_BRAKE getstatf(STAT_BUGRIGS_FRICTION_BRAKE)
+ #define PHYS_BUGRIGS_ACCEL getstatf(STAT_BUGRIGS_ACCEL)
+ #define PHYS_BUGRIGS_SPEED_REF getstatf(STAT_BUGRIGS_SPEED_REF)
+ #define PHYS_BUGRIGS_SPEED_POW getstatf(STAT_BUGRIGS_SPEED_POW)
+ #define PHYS_BUGRIGS_STEER getstatf(STAT_BUGRIGS_STEER)
+ #define PHYS_BUGRIGS_FRICTION_AIR getstatf(STAT_BUGRIGS_FRICTION_AIR)
+ #define PHYS_BUGRIGS_CAR_JUMPING getstatf(STAT_BUGRIGS_CAR_JUMPING)
+ #define PHYS_BUGRIGS_REVERSE_SPINNING getstatf(STAT_BUGRIGS_REVERSE_SPINNING)
+ #define PHYS_BUGRIGS_REVERSE_STOPPING getstatf(STAT_BUGRIGS_REVERSE_STOPPING)
+
#define PHYS_JUMPSPEEDCAP_MIN getstatf(STAT_MOVEVARS_JUMPSPEEDCAP_MIN)
#define PHYS_JUMPSPEEDCAP_MAX getstatf(STAT_MOVEVARS_JUMPSPEEDCAP_MAX)
#define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS getstati(STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS)
#define PHYS_WARSOWBUNNY_TOPSPEED getstatf(STAT_MOVEVARS_WARSOWBUNNY_TOPSPEED)
#define PHYS_WARSOWBUNNY_TURNACCEL getstatf(STAT_MOVEVARS_WARSOWBUNNY_TURNACCEL)
+ #define PHYS_WALLFRICTION getstati(STAT_MOVEVARS_WALLFRICTION)
+
#define PHYS_JETPACK_ACCEL_UP getstatf(STAT_JETPACK_ACCEL_UP)
#define PHYS_JETPACK_ACCEL_SIDE getstatf(STAT_JETPACK_ACCEL_SIDE)
#define PHYS_JETPACK_ANTIGRAVITY getstatf(STAT_JETPACK_ANTIGRAVITY)
#define PHYS_DODGING_FROZEN getstati(STAT_DODGING_FROZEN)
+ #define PHYS_NOSTEP getstati(STAT_NOSTEP)
+ #define PHYS_JUMPSTEP getstati(STAT_MOVEVARS_JUMPSTEP)
+
#elif defined(SVQC)
.float stat_sv_airaccel_qw;
.float stat_jetpack_maxspeed_up;
.float stat_jetpack_maxspeed_side;
.float stat_gameplayfix_easierwaterjump;
+ .float stat_gameplayfix_downtracesupportsongroundflag;
+ .float stat_gameplayfix_stepmultipletimes;
+ .float stat_gameplayfix_unstickplayers;
+ .float stat_gameplayfix_stepdown;
+
+ .float stat_bugrigs;
+ .float stat_bugrigs_angle_smoothing;
+ .float stat_bugrigs_planar_movement;
+ .float stat_bugrigs_reverse_speeding;
+ .float stat_bugrigs_friction_floor;
+ .float stat_bugrigs_air_steering;
+ .float stat_bugrigs_friction_brake;
+ .float stat_bugrigs_accel;
+ .float stat_bugrigs_speed_ref;
+ .float stat_bugrigs_speed_pow;
+ .float stat_bugrigs_steer;
+ .float stat_bugrigs_friction_air;
+ .float stat_bugrigs_car_jumping;
+ .float stat_bugrigs_reverse_spinning;
+ .float stat_bugrigs_reverse_stopping;
+
+ .float stat_nostep;
+ .float stat_jumpstep;
#define PHYS_INPUT_ANGLES(s) s.v_angle
#define PHYS_WORLD_ANGLES(s) s.angles
#define GAMEPLAYFIX_NOGRAVITYONGROUND cvar("sv_gameplayfix_nogravityonground")
#define GAMEPLAYFIX_Q2AIRACCELERATE autocvar_sv_gameplayfix_q2airaccelerate
#define GAMEPLAYFIX_EASIERWATERJUMP cvar("sv_gameplayfix_easierwaterjump")
+ #define GAMEPLAYFIX_DOWNTRACEONGROUND cvar("sv_gameplayfix_downtracesupportsongroundflag")
+ #define GAMEPLAYFIX_STEPMULTIPLETIMES cvar("sv_gameplayfix_stepmultipletimes")
+ #define GAMEPLAYFIX_UNSTICKPLAYERS cvar("sv_gameplayfix_unstickplayers")
+ #define GAMEPLAYFIX_STEPDOWN cvar("sv_gameplayfix_stepdown")
#define IS_DUCKED(s) s.crouch
#define SET_DUCKED(s) s.crouch = true
#define PHYS_DOUBLEJUMP autocvar_sv_doublejump
+ #define PHYS_BUGRIGS g_bugrigs
+ #define PHYS_BUGRIGS_ANGLE_SMOOTHING g_bugrigs_angle_smoothing
+ #define PHYS_BUGRIGS_PLANAR_MOVEMENT g_bugrigs_planar_movement
+ #define PHYS_BUGRIGS_REVERSE_SPEEDING g_bugrigs_reverse_speeding
+ #define PHYS_BUGRIGS_FRICTION_FLOOR g_bugrigs_friction_floor
+ #define PHYS_BUGRIGS_AIR_STEERING g_bugrigs_air_steering
+ #define PHYS_BUGRIGS_FRICTION_BRAKE g_bugrigs_friction_brake
+ #define PHYS_BUGRIGS_ACCEL g_bugrigs_accel
+ #define PHYS_BUGRIGS_SPEED_REF g_bugrigs_speed_ref
+ #define PHYS_BUGRIGS_SPEED_POW g_bugrigs_speed_pow
+ #define PHYS_BUGRIGS_STEER g_bugrigs_steer
+ #define PHYS_BUGRIGS_FRICTION_AIR g_bugrigs_friction_air
+ #define PHYS_BUGRIGS_CAR_JUMPING g_bugrigs_planar_movement_car_jumping
+ #define PHYS_BUGRIGS_REVERSE_SPINNING g_bugrigs_reverse_spinning
+ #define PHYS_BUGRIGS_REVERSE_STOPPING g_bugrigs_reverse_stopping
+
#define PHYS_JUMPSPEEDCAP_MIN autocvar_sv_jumpspeedcap_min
#define PHYS_JUMPSPEEDCAP_MAX autocvar_sv_jumpspeedcap_max
#define PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS autocvar_sv_jumpspeedcap_max_disable_on_ramps
#define PHYS_WARSOWBUNNY_TOPSPEED autocvar_sv_warsowbunny_topspeed
#define PHYS_WARSOWBUNNY_TURNACCEL autocvar_sv_warsowbunny_turnaccel
+ #define PHYS_WALLFRICTION cvar("sv_wallfriction")
+
#define PHYS_JETPACK_ACCEL_UP autocvar_g_jetpack_acceleration_up
#define PHYS_JETPACK_ACCEL_SIDE autocvar_g_jetpack_acceleration_side
#define PHYS_JETPACK_ANTIGRAVITY autocvar_g_jetpack_antigravity
#define PHYS_DODGING_FROZEN autocvar_sv_dodging_frozen
+ #define PHYS_NOSTEP cvar("sv_nostep")
+ #define PHYS_JUMPSTEP cvar("sv_jumpstep")
+
#endif
#endif
// 166 empty?
// 167 empty?
// 168 empty?
-// 169 empty?
-// 170 empty?
-// 171 empty?
-// 172 empty?
-// 173 empty?
-// 174 empty?
-// 175 empty?
-// 176 empty?
-// 177 empty?
-// 178 empty?
-// 179 empty?
-// 180 empty?
-// 181 empty?
-// 182 empty?
-// 183 empty?
-// 184 empty?
-// 185 empty?
-// 186 empty?
-// 187 empty?
-// 188 empty?
-// 189 empty?
-const int STAT_GAMEPLAYFIX_EASIERWATERJUMP = 190;
+const int STAT_BUGRIGS_REVERSE_STOPPING = 169;
+const int STAT_BUGRIGS_REVERSE_SPINNING = 170;
+const int STAT_BUGRIGS_CAR_JUMPING = 171;
+const int STAT_BUGRIGS_FRICTION_AIR = 172;
+const int STAT_BUGRIGS_STEER = 173;
+const int STAT_BUGRIGS_SPEED_POW = 174;
+const int STAT_BUGRIGS_SPEED_REF = 175;
+const int STAT_BUGRIGS_ACCEL = 176;
+const int STAT_BUGRIGS_FRICTION_BRAKE = 177;
+const int STAT_BUGRIGS_AIR_STEERING = 178;
+const int STAT_BUGRIGS_FRICTION_FLOOR = 179;
+const int STAT_BUGRIGS_REVERSE_SPEEDING = 180;
+const int STAT_BUGRIGS_PLANAR_MOVEMENT = 181;
+const int STAT_BUGRIGS_ANGLE_SMOOTHING = 182;
+const int STAT_BUGRIGS = 183;
+const int STAT_GAMEPLAYFIX_STEPDOWN = 184;
+const int STAT_MOVEVARS_JUMPSTEP = 185;
+const int STAT_NOSTEP = 186;
+const int STAT_GAMEPLAYFIX_UNSTICKPLAYERS = 187;
+const int STAT_GAMEPLAYFIX_STEPMULTIPLETIMES = 188;
+const int STAT_GAMEPLAYFIX_DOWNTRACEONGROUND = 189;
+const int STAT_GAMEPLAYFIX_EASIERWATERJUMP = 190;
const int STAT_MOVEVARS_FRICTION_SLICK = 191;
const int STAT_MOVEVARS_FRICTION_ONLAND = 192;
const int STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS = 193;
other.lastpushtime = time;
if(!pushdeltatime) return;
-#ifdef CSQC
- print("Touchie!\n");
-#endif
-
other.velocity = other.velocity + normalize(targ.origin - self.origin) * str * pushdeltatime;
other.flags &= ~FL_ONGROUND;
#ifdef SVQC