+#include "../common/physics.qh"
+
#if defined(CSQC)
#include "../dpdefs/csprogsdefs.qh"
#include "defs.qh"
#include "../server/t_items.qh"
#elif defined(MENUQC)
#elif defined(SVQC)
+ #include "../server/autocvars.qh"
#endif
+#ifdef SVQC
+#define GRAVITY_UNAFFECTED_BY_TICRATE autocvar_sv_gameplayfix_gravityunaffectedbyticrate
+
+#define TICRATE sys_frametime
+#elif defined(CSQC)
#define GRAVITY_UNAFFECTED_BY_TICRATE (getstati(STAT_MOVEFLAGS) & MOVEFLAG_GRAVITYUNAFFECTEDBYTICRATE)
+#define TICRATE ticrate
+#endif
+
.entity move_groundentity; // FIXME add move_groundnetworkentity?
.float move_suspendedinair;
.float move_didgravity;
float _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);
{
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;
}
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;
{
vel = 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;
}
return trace_fraction;
}
-const float MAX_CLIP_PLANES = 5;
+
+.float ltime;
+.void() blocked;
+void _Movetype_AngleVectorsFLU(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);
+ 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)
+ {
+ angle = myangles_z * (M_PI*2 / 360);
+ sr = sin(angle);
+ cr = cos(angle);
+ 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_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')
+ {
+ self.move_ltime += dt;
+ return;
+ }
+
+ 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;
+ }
+
+ rotated = dotproduct(self.move_angles, self.move_angles) + dotproduct(self.move_avelocity, self.move_avelocity) > 0;
+
+ movetime2 = dt;
+
+ move1 = self.move_velocity * movetime2;
+ moveangle = self.move_avelocity * movetime2;
+
+ a = -moveangle;
+ // sets v_forward, v_right and v_up
+ _Movetype_AngleVectorsFLU(a);
+
+ pushorig = self.move_origin;
+ pushang = self.move_angles;
+ 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;
+
+ 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)
+ {
+ 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;
+
+ pivot = check.mins + 0.5 * (check.maxs - check.mins);
+ //VectorClear(pivot);
+
+ 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;
+ 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))
+ {
+ self = oldself;
+ // entity "check" got teleported
+ check.move_angles_y += trace_fraction * moveangle_y;
+ self.solid = savesolid;
+ continue; // pushed enough
+ }
+ 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));
+}
+
+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)
+ {
+ movetime = thinktime - self.move_ltime;
+ if(movetime < 0)
+ movetime = 0;
+ }
+ else
+ movetime = dt;
+
+ if(movetime)
+ // advances self.move_ltime if not blocked
+ _Movetype_PushMove(movetime);
+
+ if(thinktime > oldltime && thinktime <= self.move_ltime)
+ {
+ self.move_nextthink = 0;
+ self.move_time = time;
+ other = world;
+ if(self.move_think)
+ self.move_think();
+ }
+}
+
void _Movetype_Physics_Toss(float dt) // SV_Physics_Toss
{
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)
return;
if(GRAVITY_UNAFFECTED_BY_TICRATE)
{
if(self.gravity)
- self.move_velocity_z -= 0.5 * dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
+ self.move_velocity_z -= 0.5 * dt * self.gravity * PHYS_GRAVITY;
else
- self.move_velocity_z -= 0.5 * dt * getstatf(STAT_MOVEVARS_GRAVITY);
+ self.move_velocity_z -= 0.5 * dt * PHYS_GRAVITY;
}
else
{
if(self.gravity)
- self.move_velocity_z -= dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
+ self.move_velocity_z -= dt * self.gravity * PHYS_GRAVITY;
else
- self.move_velocity_z -= dt * getstatf(STAT_MOVEVARS_GRAVITY);
+ self.move_velocity_z -= dt * PHYS_GRAVITY;
}
}
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 * getstatf(STAT_MOVEVARS_GRAVITY);
+ bouncestop *= self.gravity * PHYS_GRAVITY;
else
- bouncestop *= getstatf(STAT_MOVEVARS_GRAVITY);
+ bouncestop *= 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)
+ if(trace_plane_normal_z > 0.7 && d < bouncestop && d > -bouncestop)
{
self.move_flags |= FL_ONGROUND;
self.move_groundentity = trace_ent;
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(!(self.move_flags & FL_ONGROUND))
{
if(self.gravity)
- self.move_velocity_z -= 0.5 * dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
+ self.move_velocity_z -= 0.5 * dt * self.gravity * PHYS_GRAVITY;
else
- self.move_velocity_z -= 0.5 * dt * getstatf(STAT_MOVEVARS_GRAVITY);
+ self.move_velocity_z -= 0.5 * dt * PHYS_GRAVITY;
}
_Movetype_CheckWaterTransition(self);
{
case MOVETYPE_PUSH:
case MOVETYPE_FAKEPUSH:
- error("SV_Physics_Pusher not implemented");
+ _Movetype_Physics_Pusher(movedt);
break;
case MOVETYPE_NONE:
break;
break;
case MOVETYPE_NOCLIP:
_Movetype_CheckWater(self);
- self.move_origin = self.move_origin + ticrate * self.move_velocity;
- self.move_angles = self.move_angles + ticrate * self.move_avelocity;
+ self.move_origin = self.move_origin + TICRATE * self.move_velocity;
+ self.move_angles = self.move_angles + TICRATE * self.move_avelocity;
_Movetype_LinkEdict(false);
break;
case MOVETYPE_STEP:
void Movetype_Physics_MatchServer(bool sloppy)
{
- Movetype_Physics_MatchTicrate(ticrate, sloppy);
+ Movetype_Physics_MatchTicrate(TICRATE, sloppy);
}
void Movetype_Physics_MatchTicrate(float tr, bool sloppy) // SV_Physics_Entity
if(GRAVITY_UNAFFECTED_BY_TICRATE)
{
if(self.gravity)
- self.velocity_z -= 0.5 * dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
+ self.velocity_z -= 0.5 * dt * self.gravity * PHYS_GRAVITY;
else
- self.velocity_z -= 0.5 * dt * getstatf(STAT_MOVEVARS_GRAVITY);
+ self.velocity_z -= 0.5 * dt * PHYS_GRAVITY;
}
else
{
if(self.gravity)
- self.velocity_z -= dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
+ self.velocity_z -= dt * self.gravity * PHYS_GRAVITY;
else
- self.velocity_z -= dt * getstatf(STAT_MOVEVARS_GRAVITY);
+ self.velocity_z -= dt * PHYS_GRAVITY;
}
}
if(GRAVITY_UNAFFECTED_BY_TICRATE)
{
if(self.gravity)
- self.velocity_z -= 0.5 * dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
+ self.velocity_z -= 0.5 * dt * self.gravity * PHYS_GRAVITY;
else
- self.velocity_z -= 0.5 * dt * getstatf(STAT_MOVEVARS_GRAVITY);
+ self.velocity_z -= 0.5 * dt * PHYS_GRAVITY;
}
}
}