3 void sys_phys_fix(entity this, float dt)
5 WarpZone_PlayerPhysics_FixVAngle(this);
6 Physics_UpdateStats(this);
9 bool sys_phys_override(entity this, float dt)
11 int buttons = PHYS_INPUT_BUTTON_MASK(this);
12 float idlesince = CS(this).parm_idlesince;
13 CS(this).parm_idlesince = time; // in the case that physics are overridden
14 if (PM_check_specialcommand(this, buttons)) { return true; }
15 if (this.PlayerPhysplug && this.PlayerPhysplug(this, dt)) { return true; }
16 CS(this).parm_idlesince = idlesince;
20 void sys_phys_monitor(entity this, float dt)
22 int buttons = PHYS_INPUT_BUTTON_MASK(this);
23 anticheat_physics(this);
25 if (buttons != CS(this).buttons_old
26 || CS(this).movement != CS(this).movement_old
27 || this.v_angle != this.v_angle_old) { CS(this).parm_idlesince = time; }
29 PM_check_nickspam(this);
30 PM_check_punch(this, dt);
32 CS(this).buttons_old = PHYS_INPUT_BUTTON_MASK(this);
35 void sys_phys_ai(entity this)
37 if (!IS_BOT_CLIENT(this)) { return; }
38 if (playerdemo_read(this)) { return; }
42 void sys_phys_pregame_hold(entity this)
44 if (!IS_PLAYER(this)) { return; }
45 const bool allowed_to_move = (time >= game_starttime && !game_stopped);
46 if (!allowed_to_move) {
47 this.velocity = '0 0 0';
48 set_movetype(this, MOVETYPE_NONE);
49 this.disableclientprediction = 2;
50 } else if (this.disableclientprediction == 2) {
51 if (this.move_movetype == MOVETYPE_NONE) { set_movetype(this, MOVETYPE_WALK); }
52 this.disableclientprediction = 0;
56 void sys_phys_spectator_control(entity this)
58 float maxspeed_mod = autocvar_sv_spectator_speed_multiplier;
59 if (!this.spectatorspeed) { this.spectatorspeed = maxspeed_mod; }
60 if ((CS(this).impulse >= 1 && CS(this).impulse <= 19)
61 || (CS(this).impulse >= 200 && CS(this).impulse <= 209)
62 || (CS(this).impulse >= 220 && CS(this).impulse <= 229)
64 if (this.lastclassname != STR_PLAYER) {
65 if (CS(this).impulse == 10
66 || CS(this).impulse == 15
67 || CS(this).impulse == 18
68 || (CS(this).impulse >= 200 && CS(this).impulse <= 209)
69 ) { this.spectatorspeed = bound(1, this.spectatorspeed + 0.5, 5); } else if (CS(this).impulse == 11) {
70 this.spectatorspeed = maxspeed_mod;
71 } else if (CS(this).impulse == 12
72 || CS(this).impulse == 16
73 || CS(this).impulse == 19
74 || (CS(this).impulse >= 220 && CS(this).impulse <= 229)
76 this.spectatorspeed = bound(1, this.spectatorspeed - 0.5, 5);
77 } else if (CS(this).impulse >= 1 && CS(this).impulse <= 9) {
78 this.spectatorspeed = 1 + 0.5 * (CS(this).impulse - 1);
80 } // otherwise just clear
85 void sys_phys_fixspeed(entity this, float maxspeed_mod)
87 float spd = max(PHYS_MAXSPEED(this), PHYS_MAXAIRSPEED(this)) * maxspeed_mod;
88 if (this.speed != spd) {
90 string temps = ftos(spd);
91 stuffcmd(this, strcat("cl_forwardspeed ", temps, "\n"));
92 stuffcmd(this, strcat("cl_backspeed ", temps, "\n"));
93 stuffcmd(this, strcat("cl_sidespeed ", temps, "\n"));
94 stuffcmd(this, strcat("cl_upspeed ", temps, "\n"));
97 if (this.jumpspeedcap_min != autocvar_sv_jumpspeedcap_min) {
98 this.jumpspeedcap_min = autocvar_sv_jumpspeedcap_min;
99 stuffcmd(this, sprintf("\ncl_jumpspeedcap_min \"%s\"\n", autocvar_sv_jumpspeedcap_min));
101 if (this.jumpspeedcap_max != autocvar_sv_jumpspeedcap_max) {
102 this.jumpspeedcap_max = autocvar_sv_jumpspeedcap_max;
103 stuffcmd(this, sprintf("\ncl_jumpspeedcap_max \"%s\"\n", autocvar_sv_jumpspeedcap_max));
107 void sys_phys_land(entity this)
109 if (autocvar_speedmeter) {
110 LOG_TRACEF("landing velocity: %v (abs: %f)", this.velocity, vlen(this.velocity));
112 if (this.jumppadcount > 1) {
113 LOG_TRACEF("%dx jumppad combo", this.jumppadcount);
115 this.jumppadcount = 0;
118 STATIC_INIT(sys_phys)
120 entity listener = new_pure(sys_phys);
121 subscribe(listener, phys_land, sys_phys_land);