#include "physics.qh"
-#include "triggers/trigger/swamp.qh"
-#include "triggers/trigger/jumppads.qh"
+#include "triggers/include.qh"
+#include "viewloc.qh"
#ifdef SVQC
#include "../server/miscfunctions.qh"
+#include "triggers/trigger/viewloc.qh"
// client side physics
bool Physics_Valid(string thecvar)
{
- if(!autocvar_g_physics_clientselect) { return false; }
-
- string l = strcat(" ", autocvar_g_physics_clientselect_options, " ");
-
- if(strstrofs(l, strcat(" ", thecvar, " "), 0) >= 0)
- return true;
-
- return false;
+ return autocvar_g_physics_clientselect && strhasword(autocvar_g_physics_clientselect_options, thecvar);
}
float Physics_ClientOption(entity pl, string option)
{
if(Physics_Valid(pl.cvar_cl_physics))
{
- string var = sprintf("g_physics_%s_%s", pl.cvar_cl_physics, option);
- if(cvar_type(var) & CVAR_TYPEFLAG_EXISTS)
- return cvar(var);
+ string s = sprintf("g_physics_%s_%s", pl.cvar_cl_physics, option);
+ if(cvar_type(s) & CVAR_TYPEFLAG_EXISTS)
+ return cvar(s);
}
if(autocvar_g_physics_clientselect && autocvar_g_physics_clientselect_default)
{
- string var = sprintf("g_physics_%s_%s", autocvar_g_physics_clientselect_default, option);
- if(cvar_type(var) & CVAR_TYPEFLAG_EXISTS)
- return cvar(var);
+ string s = sprintf("g_physics_%s_%s", autocvar_g_physics_clientselect_default, option);
+ if(cvar_type(s) & CVAR_TYPEFLAG_EXISTS)
+ return cvar(s);
}
return cvar(strcat("sv_", option));
}
addstat(STAT_JETPACK_MAXSPEED_SIDE, AS_FLOAT, stat_jetpack_maxspeed_side);
// hack to fix track_canjump
- addstat(STAT_MOVEVARS_TRACK_CANJUMP, AS_INT, cvar_cl_movement_track_canjump);
+ addstat(STAT_MOVEVARS_CL_TRACK_CANJUMP, AS_INT, cvar_cl_movement_track_canjump);
+ addstat(STAT_MOVEVARS_TRACK_CANJUMP, AS_INT, stat_sv_track_canjump);
// double jump
addstat(STAT_DOUBLEJUMP, AS_INT, stat_doublejump);
// jump speed caps
- addstat(STAT_MOVEVARS_JUMPSPEEDCAP_MIN, AS_FLOAT, stat_jumpspeedcap_min);
- addstat(STAT_MOVEVARS_JUMPSPEEDCAP_MIN, AS_FLOAT, stat_jumpspeedcap_min);
addstat(STAT_MOVEVARS_JUMPSPEEDCAP_DISABLE_ONRAMPS, AS_INT, stat_jumpspeedcap_disable_onramps);
// hacks
}
void Physics_UpdateStats(float maxspd_mod)
-{
+{SELFPARAM();
// blah
self.stat_pl_view_ofs = PL_VIEW_OFS;
self.stat_pl_crouch_view_ofs = PL_CROUCH_VIEW_OFS;
self.stat_jetpack_maxspeed_up = PHYS_JETPACK_MAXSPEED_UP;
self.stat_jetpack_fuel = PHYS_JETPACK_FUEL;
- self.stat_jumpspeedcap_min = PHYS_JUMPSPEEDCAP_MIN;
- self.stat_jumpspeedcap_max = PHYS_JUMPSPEEDCAP_MAX;
self.stat_jumpspeedcap_disable_onramps = PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS;
self.stat_sv_friction_on_land = PHYS_FRICTION_ONLAND;
self.stat_sv_airstopaccelerate = Physics_ClientOption(self, "airstopaccelerate");
self.stat_sv_jumpvelocity = Physics_ClientOption(self, "jumpvelocity");
+ self.stat_sv_track_canjump = Physics_ClientOption(self, "track_canjump");
+
self.stat_gameplayfix_upvelocityclearsonground = UPWARD_VELOCITY_CLEARS_ONGROUND;
}
#endif
};
void PM_ClientMovement_Unstick()
-{
+{SELFPARAM();
float i;
for (i = 0; i < unstick_count; i++)
{
}
void PM_ClientMovement_UpdateStatus(bool ground)
-{
+{SELFPARAM();
// make sure player is not stuck
PM_ClientMovement_Unstick();
}
void PM_ClientMovement_Move()
-{
+{SELFPARAM();
#ifdef CSQC
int bump;
float t;
vector trace1_plane_normal = '0 0 0';
vector trace2_plane_normal = '0 0 0';
vector trace3_plane_normal = '0 0 0';
-
+
PM_ClientMovement_UpdateStatus(false);
primalvelocity = self.velocity;
}
void CPM_PM_Aircontrol(vector wishdir, float wishspeed)
-{
+{SELFPARAM();
float k = 32 * (2 * IsMoveInDirection(self.movement, 0) - 1);
if (k <= 0)
return;
// prvm_globalset server speedclamp_mode 1
// (or 2)
void PM_Accelerate(vector wishdir, float wishspeed, float wishspeed0, float accel, float accelqw, float stretchfactor, float sidefric, float speedlimit)
-{
+{SELFPARAM();
float speedclamp = stretchfactor > 0 ? stretchfactor
: accelqw < 0 ? 1 // full clamping, no stretch
: -1; // no clamping
}
void PM_AirAccelerate(vector wishdir, float wishspeed)
-{
+{SELFPARAM();
if (wishspeed == 0)
return;
=============
*/
bool PlayerJump (void)
-{
+{SELFPARAM();
if (PHYS_FROZEN(self))
return true; // no jumping in freezetag when frozen
bool doublejump = false;
float mjumpheight = PHYS_JUMPVELOCITY;
-
+#ifdef CSQC
player_multijump = doublejump;
player_jumpheight = mjumpheight;
-#ifdef SVQC
- if (MUTATOR_CALLHOOK(PlayerJump))
-#elif defined(CSQC)
- if(PM_multijump_checkjump())
#endif
- return true;
+
+ if (MUTATOR_CALLHOOK(PlayerJump, doublejump, mjumpheight)
+#ifdef CSQC
+ || PM_multijump_checkjump()
+#endif
+ ) { return true; }
doublejump = player_multijump;
mjumpheight = player_jumpheight;
if (!IS_ONGROUND(self))
return IS_JUMP_HELD(self);
- if (PHYS_TRACK_CANJUMP(self))
+ bool track_jump = PHYS_CL_TRACK_CANJUMP(self);
+ if(PHYS_TRACK_CANJUMP(self))
+ track_jump = true;
+
+ if (track_jump)
if (IS_JUMP_HELD(self))
return true;
// velocity bounds. Final velocity is bound between (jumpheight *
// min + jumpheight) and (jumpheight * max + jumpheight);
- if(PHYS_JUMPSPEEDCAP_MIN)
+ if(PHYS_JUMPSPEEDCAP_MIN != "")
{
- float minjumpspeed = mjumpheight * PHYS_JUMPSPEEDCAP_MIN;
+ float minjumpspeed = mjumpheight * stof(PHYS_JUMPSPEEDCAP_MIN);
if (self.velocity_z < minjumpspeed)
mjumpheight += minjumpspeed - self.velocity_z;
}
- if(PHYS_JUMPSPEEDCAP_MAX)
+ if(PHYS_JUMPSPEEDCAP_MAX != "")
{
// don't do jump speedcaps on ramps to preserve old xonotic ramjump style
tracebox(self.origin + '0 0 0.01', self.mins, self.maxs, self.origin - '0 0 0.01', MOVE_NORMAL, self);
if (!(trace_fraction < 1 && trace_plane_normal_z < 0.98 && PHYS_JUMPSPEEDCAP_DISABLE_ONRAMPS))
{
- float maxjumpspeed = mjumpheight * PHYS_JUMPSPEEDCAP_MAX;
+ float maxjumpspeed = mjumpheight * stof(PHYS_JUMPSPEEDCAP_MAX);
if (self.velocity_z > maxjumpspeed)
mjumpheight -= self.velocity_z - maxjumpspeed;
{
#ifdef SVQC
if(autocvar_speedmeter)
- dprint(strcat("landing velocity: ", vtos(self.velocity), " (abs: ", ftos(vlen(self.velocity)), ")\n"));
+ LOG_TRACE(strcat("landing velocity: ", vtos(self.velocity), " (abs: ", ftos(vlen(self.velocity)), ")\n"));
#endif
if(self.lastground < time - 0.3)
{
}
#ifdef SVQC
if(self.jumppadcount > 1)
- dprint(strcat(ftos(self.jumppadcount), "x jumppad combo\n"));
+ LOG_TRACE(strcat(ftos(self.jumppadcount), "x jumppad combo\n"));
self.jumppadcount = 0;
#endif
}
}
void CheckWaterJump()
-{
+{SELFPARAM();
// check for a jump-out-of-water
makevectors(self.v_angle);
vector start = self.origin;
// Hack: shouldn't need to know about this
.float multijump_count;
void CheckPlayerJump()
-{
+{SELFPARAM();
#ifdef SVQC
float was_flying = ITEMS_STAT(self) & IT_USING_JETPACK;
#endif
float activate = JETPACK_JUMP(self) && air_jump && PHYS_INPUT_BUTTON_JUMP(self) || PHYS_INPUT_BUTTON_JETPACK(self);
float has_fuel = !PHYS_JETPACK_FUEL || PHYS_AMMO_FUEL(self) || ITEMS_STAT(self) & IT_UNLIMITED_WEAPON_AMMO;
- if (!(ITEMS_STAT(self) & IT_JETPACK)) { }
+ if (!(ITEMS_STAT(self) & ITEM_Jetpack.m_itemid)) { }
else if (self.jetpack_stopped) { }
else if (!has_fuel)
{
}
void RaceCarPhysics()
-{
+{SELFPARAM();
#ifdef SVQC
// using this move type for "big rigs"
// the engine does not push the entity!
TetrisImpulse();
#else
if (!CheatImpulse(99))
- print("A hollow voice says \"Plugh\".\n");
+ LOG_INFO("A hollow voice says \"Plugh\".\n");
#endif
#endif
}
-float PM_check_keepaway(void)
-{
-#ifdef SVQC
- return (self.ballcarried && g_keepaway) ? autocvar_g_keepaway_ballcarrier_highspeed : 1;
-#else
- return 1;
-#endif
-}
-
-void PM_check_race_movetime(void)
-{
-#ifdef SVQC
- self.race_movetime_frac += PHYS_INPUT_TIMELENGTH;
- float f = floor(self.race_movetime_frac);
- self.race_movetime_frac -= f;
- self.race_movetime_count += f;
- self.race_movetime = self.race_movetime_frac + self.race_movetime_count;
-#endif
-}
-
float PM_check_specialcommand(float buttons)
-{
+{SELFPARAM();
#ifdef SVQC
string c;
if (!buttons)
}
void PM_check_nickspam(void)
-{
+{SELFPARAM();
#ifdef SVQC
if (time >= self.nickspamtime)
return;
}
void PM_check_punch()
-{
+{SELFPARAM();
#ifdef SVQC
if (self.punchangle != '0 0 0')
{
}
void PM_check_spider(void)
-{
+{SELFPARAM();
#ifdef SVQC
if (time >= self.spider_slowness)
return;
// predict frozen movement, as frozen players CAN move in some cases
void PM_check_frozen(void)
-{
+{SELFPARAM();
if (!PHYS_FROZEN(self))
return;
if (PHYS_DODGING_FROZEN
}
void PM_check_hitground()
-{
+{SELFPARAM();
#ifdef SVQC
if (IS_ONGROUND(self))
if (IS_PLAYER(self)) // no fall sounds for observers thank you very much
}
void PM_check_blocked(void)
-{
+{SELFPARAM();
#ifdef SVQC
if (!self.player_blocked)
return;
#endif
}
-#ifdef SVQC
-float speedaward_lastsent;
-float speedaward_lastupdate;
-#endif
-void PM_check_race(void)
-{
-#ifdef SVQC
- if(!(g_cts || g_race))
- return;
- if (vlen(self.velocity - self.velocity_z * '0 0 1') > speedaward_speed)
- {
- speedaward_speed = vlen(self.velocity - self.velocity_z * '0 0 1');
- speedaward_holder = self.netname;
- speedaward_uid = self.crypto_idfp;
- speedaward_lastupdate = time;
- }
- if (speedaward_speed > speedaward_lastsent && time - speedaward_lastupdate > 1)
- {
- string rr = (g_cts) ? CTS_RECORD : RACE_RECORD;
- race_send_speedaward(MSG_ALL);
- speedaward_lastsent = speedaward_speed;
- if (speedaward_speed > speedaward_alltimebest && speedaward_uid != "")
- {
- speedaward_alltimebest = speedaward_speed;
- speedaward_alltimebest_holder = speedaward_holder;
- speedaward_alltimebest_uid = speedaward_uid;
- db_put(ServerProgsDB, strcat(GetMapname(), rr, "speed/speed"), ftos(speedaward_alltimebest));
- db_put(ServerProgsDB, strcat(GetMapname(), rr, "speed/crypto_idfp"), speedaward_alltimebest_uid);
- race_send_speedaward_alltimebest(MSG_ALL);
- }
- }
-#endif
-}
-
void PM_check_vortex(void)
-{
+{SELFPARAM();
#ifdef SVQC
// WEAPONTODO
float xyspeed = vlen(vec2(self.velocity));
- if (self.weapon == WEP_VORTEX && WEP_CVAR(vortex, charge) && WEP_CVAR(vortex, charge_velocity_rate) && xyspeed > WEP_CVAR(vortex, charge_minspeed))
+ if (self.weapon == WEP_VORTEX.m_id && WEP_CVAR(vortex, charge) && WEP_CVAR(vortex, charge_velocity_rate) && xyspeed > WEP_CVAR(vortex, charge_minspeed))
{
// add a maximum of charge_velocity_rate when going fast (f = 1), gradually increasing from minspeed (f = 0) to maxspeed
xyspeed = min(xyspeed, WEP_CVAR(vortex, charge_maxspeed));
}
void PM_fly(float maxspd_mod)
-{
+{SELFPARAM();
// noclipping or flying
UNSET_ONGROUND(self);
}
void PM_swim(float maxspd_mod)
-{
+{SELFPARAM();
// swimming
UNSET_ONGROUND(self);
}
void PM_ladder(float maxspd_mod)
-{
+{SELFPARAM();
// on a spawnfunc_func_ladder or swimming in spawnfunc_func_water
UNSET_ONGROUND(self);
}
void PM_jetpack(float maxspd_mod)
-{
+{SELFPARAM();
//makevectors(self.v_angle.y * '0 1 0');
makevectors(self.v_angle);
vector wishvel = v_forward * self.movement_x
}
void PM_walk(float buttons_prev, float maxspd_mod)
-{
+{SELFPARAM();
if (!WAS_ONGROUND(self))
{
#ifdef SVQC
if (autocvar_speedmeter)
- dprint(strcat("landing velocity: ", vtos(self.velocity), " (abs: ", ftos(vlen(self.velocity)), ")\n"));
+ LOG_TRACE(strcat("landing velocity: ", vtos(self.velocity), " (abs: ", ftos(vlen(self.velocity)), ")\n"));
#endif
if (self.lastground < time - 0.3)
self.velocity *= (1 - PHYS_FRICTION_ONLAND);
#ifdef SVQC
if (self.jumppadcount > 1)
- dprint(strcat(ftos(self.jumppadcount), "x jumppad combo\n"));
+ LOG_TRACE(strcat(ftos(self.jumppadcount), "x jumppad combo\n"));
self.jumppadcount = 0;
#endif
}
}
void PM_air(float buttons_prev, float maxspd_mod)
-{
+{SELFPARAM();
makevectors(self.v_angle.y * '0 1 0');
vector wishvel = v_forward * self.movement.x
+ v_right * self.movement.y;
}
void PM_Main()
-{
+{SELFPARAM();
int buttons = PHYS_INPUT_BUTTON_MASK(self);
#ifdef CSQC
self.items = getstati(STAT_ITEMS, 0, 24);
PM_ClientMovement_UpdateStatus(true);
#endif
-
+
#ifdef SVQC
WarpZone_PlayerPhysics_FixVAngle();
#endif
float maxspeed_mod = 1;
- maxspeed_mod *= PM_check_keepaway();
maxspeed_mod *= PHYS_HIGHSPEED;
#ifdef SVQC
return;
#endif
- PM_check_race_movetime();
#ifdef SVQC
anticheat_physics();
#endif
if (IS_PLAYER(self))
#endif
{
-#ifdef SVQC
- if (self.race_penalty)
- if (time > self.race_penalty)
- self.race_penalty = 0;
-#endif
-
bool not_allowed_to_move = false;
-#ifdef SVQC
- if (self.race_penalty)
- not_allowed_to_move = true;
-#endif
#ifdef SVQC
if (time < game_starttime)
not_allowed_to_move = true;
self.disableclientprediction = 0;
#endif
+ viewloc_PlayerPhysics();
+
PM_check_spider();
PM_check_frozen();
stuffcmd(self, strcat("cl_sidespeed ", temps, "\n"));
stuffcmd(self, strcat("cl_upspeed ", temps, "\n"));
}
+
+ if(self.stat_jumpspeedcap_min != PHYS_JUMPSPEEDCAP_MIN)
+ {
+ self.stat_jumpspeedcap_min = PHYS_JUMPSPEEDCAP_MIN;
+ stuffcmd(self, strcat("cl_jumpspeedcap_min ", PHYS_JUMPSPEEDCAP_MIN, "\n"));
+ }
+ if(self.stat_jumpspeedcap_max != PHYS_JUMPSPEEDCAP_MAX)
+ {
+ self.stat_jumpspeedcap_min = PHYS_JUMPSPEEDCAP_MAX;
+ stuffcmd(self, strcat("cl_jumpspeedcap_max ", PHYS_JUMPSPEEDCAP_MAX, "\n"));
+ }
#endif
if(PHYS_DEAD(self))
RaceCarPhysics();
#endif
- else if (self.movetype == MOVETYPE_NOCLIP || self.movetype == MOVETYPE_FLY || self.movetype == MOVETYPE_FLY_WORLDONLY || (BUFFS(self) & BUFF_FLIGHT))
+ else if (self.movetype == MOVETYPE_NOCLIP || self.movetype == MOVETYPE_FLY || self.movetype == MOVETYPE_FLY_WORLDONLY || (BUFFS_STAT(self) & BUFF_FLIGHT.m_itemid))
PM_fly(maxspeed_mod);
else if (self.waterlevel >= WATERLEVEL_SWIMMING)
else
PM_air(buttons_prev, maxspeed_mod);
-#ifdef SVQC
- if (!IS_OBSERVER(self))
- PM_check_race();
-#endif
PM_check_vortex();
:end
#elif defined(CSQC)
void CSQC_ClientMovement_PlayerMove_Frame(void)
#endif
-{
+{SELFPARAM();
PM_Main();
#ifdef CSQC
- self.pmove_flags =
+ 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);