-#include "../player.qh"
-
-#if defined(CSQC)
- #include <client/defs.qh>
- #include <common/stats.qh>
- #include <common/util.qh>
- #include "movetypes.qh"
- #include <lib/csqcmodel/common.qh>
- #include <common/t_items.qh>
-#elif defined(MENUQC)
-#elif defined(SVQC)
- #include <server/autocvars.qh>
+#include "movetypes.qh"
+
+#ifdef SVQC
+void set_movetype(entity this, int mt)
+{
+ this.move_movetype = mt;
+ if (mt == MOVETYPE_PHYSICS || mt == MOVETYPE_PUSH || mt == MOVETYPE_FAKEPUSH) {
+ this.move_qcphysics = false;
+ }
+ if(!IL_CONTAINS(g_moveables, this))
+ IL_PUSH(g_moveables, this); // add it to the moveable entities list (even if it doesn't move!) logic: if an object never sets its movetype, we assume it never does anything notable
+ this.movetype = (this.move_qcphysics) ? MOVETYPE_NONE : mt;
+}
+#elif defined(CSQC)
+void set_movetype(entity this, int mt)
+{
+ this.move_movetype = mt;
+}
#endif
void _Movetype_WallFriction(entity this, vector stepnormal) // SV_WallFriction
if(d < 0)
{
- i = (stepnormal * this.move_velocity);
+ i = (stepnormal * this.velocity);
into = i * stepnormal;
- side = this.move_velocity - into;
- this.move_velocity_x = side.x * (1 * d);
- this.move_velocity_y = side.y * (1 * d);
+ side = this.velocity - into;
+ this.velocity_x = side.x * (1 * d);
+ this.velocity_y = side.y * (1 * d);
}*/
}
vector planes[MAX_CLIP_PLANES];
-int _Movetype_FlyMove(entity this, float dt, bool applygravity, vector stepnormal, float stepheight) // SV_FlyMove
+int _Movetype_FlyMove(entity this, float dt, bool applygravity, bool applystepnormal, float stepheight) // SV_FlyMove
{
- int blocked = 0, bumpcount;
+ move_stepnormal = '0 0 0';
+
+ if(dt <= 0)
+ return 0;
+
+ int blocked = 0;
int i, j, numplanes = 0;
float time_left = dt, grav = 0;
vector push;
- vector primal_velocity, original_velocity, restore_velocity;
+ vector primal_velocity, original_velocity;
+ vector restore_velocity = this.velocity;
for(i = 0; i < MAX_CLIP_PLANES; ++i)
planes[i] = '0 0 0';
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 || !(this.move_flags & FL_ONGROUND))
+ if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !IS_ONGROUND(this))
{
if(GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
- this.move_velocity_z -= grav * 0.5;
+ this.velocity_z -= grav * 0.5;
else
- this.move_velocity_z -= grav;
+ this.velocity_z -= grav;
}
}
- original_velocity = primal_velocity = restore_velocity = this.move_velocity;
+ original_velocity = primal_velocity = this.velocity;
- for(bumpcount = 0;bumpcount < MAX_CLIP_PLANES;bumpcount++)
+ for(int bumpcount = 0;bumpcount < MAX_CLIP_PLANES;bumpcount++)
{
- if(this.move_velocity == '0 0 0')
+ if(this.velocity == '0 0 0')
break;
- push = this.move_velocity * time_left;
- _Movetype_PushEntity(this, push, true);
- if(trace_startsolid)
+ push = this.velocity * time_left;
+ if(!_Movetype_PushEntity(this, push, true, false))
{
// we got teleported by a touch function
// let's abort the move
// abort move if we're stuck in the world (and didn't make it out)
if(trace_startsolid && trace_allsolid)
{
- this.move_velocity = restore_velocity;
+ this.velocity = restore_velocity;
return 3;
}
trace_ent = NULL;
}
- this.move_flags |= FL_ONGROUND;
- this.move_groundentity = trace_ent;
+ SET_ONGROUND(this);
+ this.groundentity = trace_ent;
}
}
else if(stepheight)
{
// step - handle it immediately
- vector org = this.move_origin;
+ vector org = this.origin;
vector steppush = '0 0 1' * stepheight;
- _Movetype_PushEntity(this, steppush, true);
- if(trace_startsolid)
+ if(!_Movetype_PushEntity(this, steppush, true, false))
{
blocked |= 8;
break;
}
- _Movetype_PushEntity(this, push, true);
- if(trace_startsolid)
+ if(!_Movetype_PushEntity(this, push, true, false))
{
blocked |= 8;
break;
}
float trace2_fraction = trace_fraction;
- steppush = '0 0 1' * (org_z - this.move_origin_z);
- _Movetype_PushEntity(this, steppush, true);
- if(trace_startsolid)
+ steppush = vec3(0, 0, org.z - this.origin_z);
+ if(!_Movetype_PushEntity(this, steppush, true, false))
{
blocked |= 8;
break;
}
// accept the new position if it made some progress...
- if(fabs(this.move_origin_x - org_x) >= 0.03125 || fabs(this.move_origin_y - org_y) >= 0.03125)
+ if(fabs(this.origin_x - org.x) >= 0.03125 || fabs(this.origin_y - org.y) >= 0.03125)
{
- trace_endpos = this.move_origin;
+ trace_endpos = this.origin;
time_left *= 1 - trace2_fraction;
numplanes = 0;
continue;
}
else
- this.move_origin = org;
+ this.origin = org;
}
else
{
// step - return it to caller
blocked |= 2;
// save the trace for player extrafriction
- if(stepnormal)
- stepnormal = trace_plane_normal;
+ if(applystepnormal)
+ move_stepnormal = trace_plane_normal;
}
if(my_trace_fraction >= 0.001)
{
// actually covered some distance
- original_velocity = this.move_velocity;
+ original_velocity = this.velocity;
numplanes = 0;
}
if(numplanes >= MAX_CLIP_PLANES)
{
// this shouldn't really happen
- this.move_velocity = '0 0 0';
+ this.velocity = '0 0 0';
blocked = 3;
break;
}
if(i != numplanes)
{
// go along this plane
- this.move_velocity = new_velocity;
+ this.velocity = new_velocity;
}
else
{
// go along the crease
if(numplanes != 2)
{
- this.move_velocity = '0 0 0';
+ this.velocity = '0 0 0';
blocked = 7;
break;
}
dir.x *= ilength;
dir.y *= ilength;
dir.z *= ilength;
- float d = (dir * this.move_velocity);
- this.move_velocity = dir * d;
+ float d = (dir * this.velocity);
+ this.velocity = dir * d;
}
// if current velocity is against the original velocity,
// stop dead to avoid tiny occilations in sloping corners
- if((this.move_velocity * primal_velocity) <= 0)
+ if((this.velocity * primal_velocity) <= 0)
{
- this.move_velocity = '0 0 0';
+ this.velocity = '0 0 0';
break;
}
}
// LordHavoc: this came from QW and allows you to get out of water more easily
- if(GAMEPLAYFIX_EASIERWATERJUMP(this) && (this.move_flags & FL_WATERJUMP) && !(blocked & 8))
- this.move_velocity = primal_velocity;
+ if(GAMEPLAYFIX_EASIERWATERJUMP(this) && (this.flags & FL_WATERJUMP) && !(blocked & 8))
+ this.velocity = primal_velocity;
+
+ if(PHYS_WALLCLIP(this) && this.pm_time && !(this.flags & FL_WATERJUMP) && !(blocked & 8))
+ this.velocity = primal_velocity;
if(applygravity)
{
- if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !(this.move_flags & FL_ONGROUND))
+ if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !IS_ONGROUND(this))
{
if(GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
- this.move_velocity_z -= grav * 0.5f;
+ this.velocity_z -= grav * 0.5f;
}
}
void _Movetype_CheckVelocity(entity this) // SV_CheckVelocity
{
- // if(vlen(this.move_velocity) < 0.0001)
- // this.move_velocity = '0 0 0';
+ // if(vlen(this.velocity) < 0.0001)
+ // this.velocity = '0 0 0';
}
bool _Movetype_CheckWater(entity this) // SV_CheckWater
{
- vector point = this.move_origin;
+ vector point = this.origin;
point.z += this.mins.z + 1;
int nativecontents = pointcontents(point);
- if(this.move_watertype && this.move_watertype != nativecontents)
+ if(this.watertype && this.watertype != nativecontents)
{
- // dprintf("_Movetype_CheckWater(): Original: '%d', New: '%d'\n", this.move_watertype, nativecontents);
+ // dprintf("_Movetype_CheckWater(): Original: '%d', New: '%d'\n", this.watertype, nativecontents);
if(this.contentstransition)
- this.contentstransition(this.move_watertype, nativecontents);
+ this.contentstransition(this.watertype, nativecontents);
}
- this.move_waterlevel = WATERLEVEL_NONE;
- this.move_watertype = CONTENT_EMPTY;
+ this.waterlevel = WATERLEVEL_NONE;
+ this.watertype = CONTENT_EMPTY;
int supercontents = Mod_Q1BSP_SuperContentsFromNativeContents(nativecontents);
if(supercontents & DPCONTENTS_LIQUIDSMASK)
{
- this.move_watertype = nativecontents;
- this.move_waterlevel = WATERLEVEL_WETFEET;
- point.z = this.move_origin.z + (this.mins.z + this.maxs.z) * 0.5;
+ this.watertype = nativecontents;
+ this.waterlevel = WATERLEVEL_WETFEET;
+ point.z = this.origin.z + (this.mins.z + this.maxs.z) * 0.5;
if(Mod_Q1BSP_SuperContentsFromNativeContents(pointcontents(point)) & DPCONTENTS_LIQUIDSMASK)
{
- this.move_waterlevel = WATERLEVEL_SWIMMING;
- point.z = this.move_origin.z + this.view_ofs.z;
+ this.waterlevel = WATERLEVEL_SWIMMING;
+ point.z = this.origin.z + this.view_ofs.z;
if(Mod_Q1BSP_SuperContentsFromNativeContents(pointcontents(point)) & DPCONTENTS_LIQUIDSMASK)
- this.move_waterlevel = WATERLEVEL_SUBMERGED;
+ this.waterlevel = WATERLEVEL_SUBMERGED;
}
}
- return this.move_waterlevel > 1;
+ return this.waterlevel > 1;
}
void _Movetype_CheckWaterTransition(entity ent) // SV_CheckWaterTransition
{
- int contents = pointcontents(ent.move_origin);
+ int contents = pointcontents(ent.origin);
- if(!ent.move_watertype)
+ if(!ent.watertype)
{
// just spawned here
- if(!autocvar_cl_gameplayfix_fixedcheckwatertransition)
+ if(!GAMEPLAYFIX_WATERTRANSITION(ent))
{
- ent.move_watertype = contents;
- ent.move_waterlevel = 1;
+ ent.watertype = contents;
+ ent.waterlevel = 1;
return;
}
}
- else if(ent.move_watertype != contents)
+ else if(ent.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.origin), pointcontents(ent.origin), ent.watertype, contents);
if(ent.contentstransition)
- ent.contentstransition(ent.move_watertype, contents);
+ ent.contentstransition(ent.watertype, contents);
}
if(contents <= CONTENT_WATER)
{
- ent.move_watertype = contents;
- ent.move_waterlevel = 1;
+ ent.watertype = contents;
+ ent.waterlevel = 1;
}
else
{
- ent.move_watertype = CONTENT_EMPTY;
- ent.move_waterlevel = (autocvar_cl_gameplayfix_fixedcheckwatertransition ? 0 : contents);
+ ent.watertype = CONTENT_EMPTY;
+ ent.waterlevel = (GAMEPLAYFIX_WATERTRANSITION(ent) ? 0 : contents);
}
}
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))
gettouch(oth)(oth, this);
}
trace_fraction = 1;
trace_inwater = false;
trace_inopen = true;
- trace_endpos = it.move_origin;
+ trace_endpos = it.origin;
trace_plane_normal = '0 0 1';
trace_plane_dist = 0;
trace_ent = this;
+ trace_dpstartcontents = 0;
+ trace_dphitcontents = 0;
+ trace_dphitq3surfaceflags = 0;
+ trace_dphittexturename = string_null;
gettouch(it)(it, this);
}
});
}
+bool autocvar__movetype_debug = false;
void _Movetype_LinkEdict(entity this, bool touch_triggers) // SV_LinkEdict
{
- vector mi, ma;
- if(this.solid == SOLID_BSP)
- {
- // TODO set the absolute bbox
- mi = this.mins;
- ma = this.maxs;
- }
- else
+ if(autocvar__movetype_debug)
{
- mi = this.mins;
- ma = this.maxs;
- }
- mi += this.move_origin;
- ma += this.move_origin;
+ vector mi, ma;
+ if(this.solid == SOLID_BSP)
+ {
+ // TODO set the absolute bbox
+ mi = this.mins;
+ ma = this.maxs;
+ }
+ else
+ {
+ mi = this.mins;
+ ma = this.maxs;
+ }
+ mi += this.origin;
+ ma += this.origin;
- if(this.move_flags & FL_ITEM)
- {
- mi.x -= 15;
- mi.y -= 15;
- mi.z -= 1;
- ma.x += 15;
- ma.y += 15;
- ma.z += 1;
+ if(this.flags & FL_ITEM)
+ {
+ mi -= '15 15 1';
+ ma += '15 15 1';
+ }
+ else
+ {
+ mi -= '1 1 1';
+ ma += '1 1 1';
+ }
+
+ this.absmin = mi;
+ this.absmax = ma;
}
else
{
- mi.x -= 1;
- mi.y -= 1;
- mi.z -= 1;
- ma.x += 1;
- ma.y += 1;
- ma.z += 1;
+ setorigin(this, this.origin); // calls SV_LinkEdict
+ #ifdef CSQC
+ // NOTE: CSQC's version of setorigin doesn't expand
+ this.absmin -= '1 1 1';
+ this.absmax += '1 1 1';
+ #endif
}
- this.absmin = mi;
- this.absmax = ma;
-
if(touch_triggers)
_Movetype_LinkEdict_TouchAreaGrid(this);
}
+int _Movetype_ContentsMask(entity this) // SV_GenericHitSuperContentsMask
+{
+ if(this)
+ {
+ if(this.dphitcontentsmask)
+ return this.dphitcontentsmask;
+ else if(this.solid == SOLID_SLIDEBOX)
+ {
+ if(this.flags & 32) // TODO: FL_MONSTER
+ return DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_MONSTERCLIP;
+ else
+ return DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP;
+ }
+ else if(this.solid == SOLID_CORPSE)
+ return DPCONTENTS_SOLID | DPCONTENTS_BODY;
+ else if(this.solid == SOLID_TRIGGER)
+ return DPCONTENTS_SOLID | DPCONTENTS_BODY;
+ else
+ return DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
+ }
+ else
+ return DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
+}
+
entity _Movetype_TestEntityPosition_ent;
bool _Movetype_TestEntityPosition(vector ofs) // SV_TestEntityPosition
{
entity this = _Movetype_TestEntityPosition_ent;
-// vector org = this.move_origin + ofs;
+ vector org = this.origin + ofs;
- int cont = this.dphitcontentsmask;
- this.dphitcontentsmask = DPCONTENTS_SOLID;
- tracebox(this.move_origin, this.mins, this.maxs, this.move_origin, ((this.move_movetype == MOVETYPE_FLY_WORLDONLY) ? MOVE_WORLDONLY : MOVE_NOMONSTERS), this);
- this.dphitcontentsmask = cont;
-
- if(trace_startsolid)
+ //int cont = this.dphitcontentsmask;
+ //this.dphitcontentsmask = DPCONTENTS_SOLID;
+ tracebox(org, this.mins, this.maxs, this.origin, ((this.move_movetype == MOVETYPE_FLY_WORLDONLY) ? MOVE_WORLDONLY : MOVE_NOMONSTERS), this);
+ //this.dphitcontentsmask = cont;
+ if(trace_dpstartcontents & _Movetype_ContentsMask(this))
return true;
- if(vdist(trace_endpos - this.move_origin, >, 0.0001))
- this.move_origin = trace_endpos;
+ if(vlen2(trace_endpos - this.origin) >= 0.0001)
+ {
+ tracebox(trace_endpos, this.mins, this.maxs, trace_endpos, MOVE_NOMONSTERS, this);
+ if(!trace_startsolid)
+ this.origin = trace_endpos;
+ }
return false;
}
-bool _Movetype_UnstickEntity(entity this) // SV_UnstickEntity
+bool _Movetype_TestEntityPosition_Offset(int offset)
+{
+ // NOTE: expects _Movetype_TestEntityPosition_ent to be set to the correct entity
+ // returns true if stuck
+
+ // start at 2, since the first position has already been checked
+ for(int j = 2; j <= offset; ++j)
+ {
+ if(!_Movetype_TestEntityPosition('0 0 -1' * j))
+ return false;
+ if(!_Movetype_TestEntityPosition('0 0 1' * j))
+ return false;
+ }
+
+ return true;
+}
+
+int _Movetype_UnstickEntity(entity this) // SV_UnstickEntity
{
_Movetype_TestEntityPosition_ent = this;
if (!_Movetype_TestEntityPosition(' 0 0 0')) {
- return true;
+ return UNSTICK_FINE;
}
#define X(v) if (_Movetype_TestEntityPosition(v))
+ X('0 0 -1') X(' 0 0 1')
X('-1 0 0') X(' 1 0 0')
X(' 0 -1 0') X(' 0 1 0')
X('-1 -1 0') X(' 1 -1 0')
X('-1 1 0') X(' 1 1 0')
#undef X
{
- #define X(i) \
- if (_Movetype_TestEntityPosition('0 0 -1' * i)) \
- if (_Movetype_TestEntityPosition('0 0 1' * i))
- X(01) X(02) X(03) X(04) X(05) X(06) X(07) X(08)
- X(09) X(10) X(11) X(12) X(13) X(14) X(15) X(16)
- X(17)
- #undef X
+ if(_Movetype_TestEntityPosition_Offset(rint((this.maxs.z - this.mins.z) * 0.36)))
{
- LOG_DEBUGF("Can't unstick an entity (edict: %d, classname: %s, origin: %s)\n",
- etof(this), this.classname, vtos(this.move_origin));
- return false;
+ LOG_DEBUGF("Can't unstick an entity (edict: %d, classname: %s, origin: %s)",
+ etof(this), this.classname, vtos(this.origin));
+ return UNSTICK_STUCK;
}
}
- LOG_DEBUGF("Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)\n",
- etof(this), this.classname, vtos(this.move_origin));
- _Movetype_LinkEdict(this, true);
- return true;
+ LOG_DEBUGF("Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)",
+ etof(this), this.classname, vtos(this.origin));
+ _Movetype_LinkEdict(this, false);
+ return UNSTICK_FIXED;
+}
+
+void _Movetype_CheckStuck(entity this) // SV_CheckStuck
+{
+ int unstick = _Movetype_UnstickEntity(this); // sets test position entity
+ switch(unstick)
+ {
+ case UNSTICK_FINE:
+ this.oldorigin = this.origin;
+ break;
+ case UNSTICK_FIXED:
+ break; // already sorted
+ case UNSTICK_STUCK:
+ vector offset = this.oldorigin - this.origin;
+ if(!_Movetype_TestEntityPosition(offset))
+ _Movetype_LinkEdict(this, false);
+ // couldn't unstick, should we warn about this?
+ break;
+ }
}
vector _Movetype_ClipVelocity(vector vel, vector norm, float f) // SV_ClipVelocity
void _Movetype_PushEntityTrace(entity this, vector push)
{
- vector end = this.move_origin + push;
+ vector end = this.origin + push;
int type;
if(this.move_nomonsters)
type = max(0, this.move_nomonsters);
else
type = MOVE_NORMAL;
- tracebox(this.move_origin, this.mins, this.maxs, end, type, this);
+ tracebox(this.origin, this.mins, this.maxs, end, type, this);
}
-float _Movetype_PushEntity(entity this, vector push, bool failonstartsolid) // SV_PushEntity
+bool _Movetype_PushEntity(entity this, vector push, bool failonstartsolid, bool dolink) // SV_PushEntity
{
_Movetype_PushEntityTrace(this, push);
+ // NOTE: this is a workaround for the QC's lack of a worldstartsolid trace parameter
if(trace_startsolid && failonstartsolid)
- return trace_fraction;
+ {
+ int oldtype = this.move_nomonsters;
+ this.move_nomonsters = MOVE_WORLDONLY;
+ _Movetype_PushEntityTrace(this, push);
+ this.move_nomonsters = oldtype;
+ if(trace_startsolid)
+ return true;
+ }
+
+ this.origin = trace_endpos;
+
+ vector last_origin = this.origin;
- this.move_origin = trace_endpos;
+ _Movetype_LinkEdict(this, dolink);
- if(trace_fraction < 1)
- if(this.solid >= SOLID_TRIGGER && (!(this.move_flags & FL_ONGROUND) || (this.move_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 trace_fraction;
+ return (this.origin == last_origin); // false if teleported by touch
}
.float ltime;
.void() blocked;
-// matrix version of makevectors, sets v_forward, v_right and v_up
-void makevectors_matrix(vector myangles) // AngleVectorsFLU
-{
- v_forward = v_right = v_up = '0 0 0';
-
- 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;
- }
- if(v_right || v_up)
- {
- if(myangles.z)
- {
- 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;
- }
- if(v_up)
- {
- 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;
- }
- if(v_up)
- {
- v_up.x = sp * cy;
- v_up.y = sp * sy;
- v_up.z = cp;
- }
- }
- }
-}
void _Movetype_Physics_Frame(entity this, float movedt)
{
{
case MOVETYPE_PUSH:
case MOVETYPE_FAKEPUSH:
- _Movetype_Physics_Pusher(this, movedt);
+ LOG_DEBUG("Physics: Lacking QuakeC support for Push movetype, FIX ME by using engine physics!");
break;
case MOVETYPE_NONE:
break;
break;
case MOVETYPE_NOCLIP:
_Movetype_CheckWater(this);
- this.move_origin = this.move_origin + TICRATE * this.move_velocity;
- this.move_angles = this.move_angles + TICRATE * this.move_avelocity;
+ this.origin = this.origin + movedt * this.velocity;
+ this.angles = this.angles + movedt * this.avelocity;
_Movetype_LinkEdict(this, false);
break;
case MOVETYPE_STEP:
case MOVETYPE_FLY:
case MOVETYPE_FLY_WORLDONLY:
_Movetype_Physics_Toss(this, movedt);
+ if(wasfreed(this))
+ return;
_Movetype_LinkEdict(this, true);
break;
case MOVETYPE_PHYSICS:
{
case MOVETYPE_PUSH:
case MOVETYPE_FAKEPUSH:
- _Movetype_Physics_Pusher(this, movedt);
+ LOG_DEBUG("Physics: Lacking QuakeC support for Push movetype, FIX ME by using engine physics!");
break;
case MOVETYPE_NONE:
break;
break;
case MOVETYPE_NOCLIP:
_Movetype_CheckWater(this);
- this.move_origin = this.move_origin + movedt * this.move_velocity;
- this.move_angles = this.move_angles + movedt * this.move_avelocity;
- _Movetype_LinkEdict(this, false);
+ this.origin = this.origin + movedt * this.velocity;
+ this.angles = this.angles + movedt * this.avelocity;
break;
case MOVETYPE_STEP:
_Movetype_Physics_Step(this, movedt);
case MOVETYPE_PHYSICS:
break;
}
+
+ //_Movetype_CheckVelocity(this);
+
+ _Movetype_LinkEdict(this, true);
+
+ //_Movetype_CheckVelocity(this);
+}
+
+void Movetype_Physics_NoMatchTicrate(entity this, float movedt, bool isclient) // to be run every move frame
+{
+ this.move_time = time;
+
+ if(isclient)
+ _Movetype_Physics_ClientFrame(this, movedt);
+ else
+ _Movetype_Physics_Frame(this, movedt);
+ if(wasfreed(this))
+ return;
+
+ setorigin(this, this.origin);
}
void Movetype_Physics_NoMatchServer(entity this) // optimized
if(wasfreed(this))
return;
- this.avelocity = this.move_avelocity;
- this.velocity = this.move_velocity;
- this.angles = this.move_angles;
- setorigin(this, this.move_origin);
+ setorigin(this, this.origin);
}
void Movetype_Physics_MatchServer(entity this, bool sloppy)
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_avelocity;
+.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(origin);
+ X(velocity);
+ X(flags);
+ X(avelocity);
+ 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)
{
Movetype_Physics_NoMatchServer(this);
+
+ this.tic_saved_flags = this.tic_flags = this.flags;
+ this.tic_saved_velocity = this.tic_velocity = this.velocity;
+ this.tic_saved_origin = this.tic_origin = this.origin;
+ this.tic_saved_avelocity = this.tic_avelocity = this.avelocity;
+ this.tic_saved_angles = this.tic_angles = this.angles;
return;
}
this.move_time += n * tr;
if(!this.move_didgravity)
- this.move_didgravity = ((this.move_movetype == MOVETYPE_BOUNCE || this.move_movetype == MOVETYPE_TOSS) && !(this.move_flags & FL_ONGROUND));
+ 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)
{
_Movetype_Physics_Frame(this, tr);
if(wasfreed(this))
return;
}
- this.avelocity = this.move_avelocity;
+ // 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.move_flags & FL_ONGROUND))
+ if(dt > 0 && this.move_movetype != MOVETYPE_NONE && !(this.tic_flags & FL_ONGROUND))
{
// now continue the move from move_time to time
- this.velocity = this.move_velocity;
+ this.velocity = this.tic_velocity;
if(this.move_didgravity > 0)
{
this.velocity_z -= (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1)
* dt
- * (this.gravity ? this.gravity : 1)
+ * ((this.gravity) ? this.gravity : 1)
* PHYS_GRAVITY(this);
}
- this.angles = this.move_angles + dt * this.avelocity;
+ this.angles = this.tic_angles + dt * this.avelocity;
if(sloppy || this.move_movetype == MOVETYPE_NOCLIP)
{
- setorigin(this, this.move_origin + dt * this.velocity);
+ setorigin(this, this.tic_origin + dt * this.velocity);
}
else
{
+ setorigin(this, this.tic_origin);
_Movetype_PushEntityTrace(this, dt * this.velocity);
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
{
- this.velocity = this.move_velocity;
- this.angles = this.move_angles;
- setorigin(this, this.move_origin);
+ this.velocity = this.tic_velocity;
+ this.angles = this.tic_angles;
+ 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;
+ this.tic_saved_avelocity = this.avelocity;
+ this.tic_saved_angles = this.angles;
}