3 #include <server/antilag.qh>
5 #include <common/physics/player.qh>
9 void bugrigs_SetVars();
11 REGISTER_MUTATOR(bugrigs, cvar("g_bugrigs"))
20 REGISTER_MUTATOR(bugrigs, true);
24 #define PHYS_BUGRIGS(s) STAT(BUGRIGS, s)
25 #define PHYS_BUGRIGS_ACCEL(s) STAT(BUGRIGS_ACCEL, s)
26 #define PHYS_BUGRIGS_AIR_STEERING(s) STAT(BUGRIGS_AIR_STEERING, s)
27 #define PHYS_BUGRIGS_ANGLE_SMOOTHING(s) STAT(BUGRIGS_ANGLE_SMOOTHING, s)
28 #define PHYS_BUGRIGS_CAR_JUMPING(s) STAT(BUGRIGS_CAR_JUMPING, s)
29 #define PHYS_BUGRIGS_FRICTION_AIR(s) STAT(BUGRIGS_FRICTION_AIR, s)
30 #define PHYS_BUGRIGS_FRICTION_BRAKE(s) STAT(BUGRIGS_FRICTION_BRAKE, s)
31 #define PHYS_BUGRIGS_FRICTION_FLOOR(s) STAT(BUGRIGS_FRICTION_FLOOR, s)
32 #define PHYS_BUGRIGS_PLANAR_MOVEMENT(s) STAT(BUGRIGS_PLANAR_MOVEMENT, s)
33 #define PHYS_BUGRIGS_REVERSE_SPEEDING(s) STAT(BUGRIGS_REVERSE_SPEEDING, s)
34 #define PHYS_BUGRIGS_REVERSE_SPINNING(s) STAT(BUGRIGS_REVERSE_SPINNING, s)
35 #define PHYS_BUGRIGS_REVERSE_STOPPING(s) STAT(BUGRIGS_REVERSE_STOPPING, s)
36 #define PHYS_BUGRIGS_SPEED_POW(s) STAT(BUGRIGS_SPEED_POW, s)
37 #define PHYS_BUGRIGS_SPEED_REF(s) STAT(BUGRIGS_SPEED_REF, s)
38 #define PHYS_BUGRIGS_STEER(s) STAT(BUGRIGS_STEER, s)
42 void bugrigs_SetVars()
44 g_bugrigs = cvar("g_bugrigs");
45 g_bugrigs_planar_movement = cvar("g_bugrigs_planar_movement");
46 g_bugrigs_planar_movement_car_jumping = cvar("g_bugrigs_planar_movement_car_jumping");
47 g_bugrigs_reverse_spinning = cvar("g_bugrigs_reverse_spinning");
48 g_bugrigs_reverse_speeding = cvar("g_bugrigs_reverse_speeding");
49 g_bugrigs_reverse_stopping = cvar("g_bugrigs_reverse_stopping");
50 g_bugrigs_air_steering = cvar("g_bugrigs_air_steering");
51 g_bugrigs_angle_smoothing = cvar("g_bugrigs_angle_smoothing");
52 g_bugrigs_friction_floor = cvar("g_bugrigs_friction_floor");
53 g_bugrigs_friction_brake = cvar("g_bugrigs_friction_brake");
54 g_bugrigs_friction_air = cvar("g_bugrigs_friction_air");
55 g_bugrigs_accel = cvar("g_bugrigs_accel");
56 g_bugrigs_speed_ref = cvar("g_bugrigs_speed_ref");
57 g_bugrigs_speed_pow = cvar("g_bugrigs_speed_pow");
58 g_bugrigs_steer = cvar("g_bugrigs_steer");
63 void RaceCarPhysics(entity this)
65 // using this move type for "big rigs"
66 // the engine does not push the entity!
70 vector angles_save = this.angles;
71 float accel = bound(-1, this.movement.x / PHYS_MAXSPEED(this), 1);
72 float steer = bound(-1, this.movement.y / PHYS_MAXSPEED(this), 1);
74 if (PHYS_BUGRIGS_REVERSE_SPEEDING(this))
78 // back accel is DIGITAL
79 // to prevent speedhack
89 makevectors(this.angles); // new forward direction!
91 if (IS_ONGROUND(this) || PHYS_BUGRIGS_AIR_STEERING(this))
93 float myspeed = this.velocity * v_forward;
94 float upspeed = this.velocity * v_up;
96 // responsiveness factor for steering and acceleration
97 float f = 1 / (1 + pow(max(-myspeed, myspeed) / PHYS_BUGRIGS_SPEED_REF(this), PHYS_BUGRIGS_SPEED_POW(this)));
98 //MAXIMA: f(v) := 1 / (1 + (v / PHYS_BUGRIGS_SPEED_REF(this)) ^ PHYS_BUGRIGS_SPEED_POW(this));
101 if (myspeed < 0 && PHYS_BUGRIGS_REVERSE_SPINNING(this))
102 steerfactor = -myspeed * PHYS_BUGRIGS_STEER(this);
104 steerfactor = -myspeed * f * PHYS_BUGRIGS_STEER(this);
107 if (myspeed < 0 && PHYS_BUGRIGS_REVERSE_SPEEDING(this))
108 accelfactor = PHYS_BUGRIGS_ACCEL(this);
110 accelfactor = f * PHYS_BUGRIGS_ACCEL(this);
111 //MAXIMA: accel(v) := f(v) * PHYS_BUGRIGS_ACCEL(this);
117 myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * (PHYS_BUGRIGS_FRICTION_FLOOR(this) - PHYS_BUGRIGS_FRICTION_BRAKE(this) * accel));
121 if (!PHYS_BUGRIGS_REVERSE_SPEEDING(this))
122 myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_FRICTION_FLOOR(this));
129 myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_FRICTION_FLOOR(this));
133 if (PHYS_BUGRIGS_REVERSE_STOPPING(this))
136 myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * (PHYS_BUGRIGS_FRICTION_FLOOR(this) + PHYS_BUGRIGS_FRICTION_BRAKE(this) * accel));
139 // terminal velocity = velocity at which 50 == accelfactor, that is, 1549 units/sec
140 //MAXIMA: friction(v) := PHYS_BUGRIGS_FRICTION_FLOOR(this);
142 this.angles_y += steer * PHYS_INPUT_TIMELENGTH * steerfactor; // apply steering
143 makevectors(this.angles); // new forward direction!
145 myspeed += accel * accelfactor * PHYS_INPUT_TIMELENGTH;
147 rigvel = myspeed * v_forward + '0 0 1' * upspeed;
151 float myspeed = vlen(this.velocity);
153 // responsiveness factor for steering and acceleration
154 float f = 1 / (1 + pow(max(0, myspeed / PHYS_BUGRIGS_SPEED_REF(this)), PHYS_BUGRIGS_SPEED_POW(this)));
155 float steerfactor = -myspeed * f;
156 this.angles_y += steer * PHYS_INPUT_TIMELENGTH * steerfactor; // apply steering
158 rigvel = this.velocity;
159 makevectors(this.angles); // new forward direction!
162 rigvel *= max(0, 1 - vlen(rigvel) * PHYS_BUGRIGS_FRICTION_AIR(this) * PHYS_INPUT_TIMELENGTH);
163 //MAXIMA: airfriction(v) := v * v * PHYS_BUGRIGS_FRICTION_AIR(this);
164 //MAXIMA: total_acceleration(v) := accel(v) - friction(v) - airfriction(v);
165 //MAXIMA: solve(total_acceleration(v) = 0, v);
167 if (PHYS_BUGRIGS_PLANAR_MOVEMENT(this))
169 vector rigvel_xy, neworigin, up;
172 rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY(this); // 4x gravity plays better
173 rigvel_xy = vec2(rigvel);
175 if (PHYS_BUGRIGS_CAR_JUMPING(this))
178 mt = MOVE_NOMONSTERS;
180 tracebox(this.origin, this.mins, this.maxs, this.origin + '0 0 1024', mt, this);
181 up = trace_endpos - this.origin;
183 // BUG RIGS: align the move to the surface instead of doing collision testing
185 tracebox(trace_endpos, this.mins, this.maxs, trace_endpos + rigvel_xy * PHYS_INPUT_TIMELENGTH, mt, this);
188 tracebox(trace_endpos, this.mins, this.maxs, trace_endpos - up + '0 0 1' * rigvel_z * PHYS_INPUT_TIMELENGTH, mt, this);
190 if (trace_fraction < 0.5)
193 neworigin = this.origin;
196 neworigin = trace_endpos;
198 if (trace_fraction < 1)
200 // now set angles_x so that the car points parallel to the surface
201 this.angles = vectoangles(
202 '1 0 0' * v_forward_x * trace_plane_normal_z
204 '0 1 0' * v_forward_y * trace_plane_normal_z
206 '0 0 1' * -(v_forward_x * trace_plane_normal_x + v_forward_y * trace_plane_normal_y)
212 // now set angles_x so that the car points forward, but is tilted in velocity direction
213 UNSET_ONGROUND(this);
216 this.velocity = (neworigin - this.origin) * (1.0 / PHYS_INPUT_TIMELENGTH);
217 this.movetype = MOVETYPE_NOCLIP;
221 rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY(this); // 4x gravity plays better
222 this.velocity = rigvel;
223 this.movetype = MOVETYPE_FLY;
227 tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 4', MOVE_NORMAL, this);
228 if (trace_fraction != 1)
230 this.angles = vectoangles2(
231 '1 0 0' * v_forward_x * trace_plane_normal_z
233 '0 1 0' * v_forward_y * trace_plane_normal_z
235 '0 0 1' * -(v_forward_x * trace_plane_normal_x + v_forward_y * trace_plane_normal_y),
243 vel_local_x = v_forward * this.velocity;
244 vel_local_y = v_right * this.velocity;
245 vel_local_z = v_up * this.velocity;
247 this.angles_x = racecar_angle(vel_local_x, vel_local_z);
248 this.angles_z = racecar_angle(-vel_local_y, vel_local_z);
252 vector vf1, vu1, smoothangles;
253 makevectors(this.angles);
254 float f = bound(0, PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_ANGLE_SMOOTHING(this), 1);
259 makevectors(angles_save);
260 vf1 = vf1 + v_forward * (1 - f);
261 vu1 = vu1 + v_up * (1 - f);
262 smoothangles = vectoangles2(vf1, vu1);
263 this.angles_x = -smoothangles_x;
264 this.angles_z = smoothangles_z;
266 PM_ClientMovement_Move(this);
270 .vector bugrigs_prevangles;
272 MUTATOR_HOOKFUNCTION(bugrigs, PM_Physics)
275 if(!PHYS_BUGRIGS(self) || !IS_PLAYER(self)) { return false; }
278 self.angles = self.bugrigs_prevangles;
281 RaceCarPhysics(self);
285 MUTATOR_HOOKFUNCTION(bugrigs, PlayerPhysics)
290 if(!PHYS_BUGRIGS(self)) { return false; }
292 self.bugrigs_prevangles = self.angles;
299 MUTATOR_HOOKFUNCTION(bugrigs, ClientConnect)
302 stuffcmd(self, "cl_cmd settemp chase_active 1\n");
306 MUTATOR_HOOKFUNCTION(bugrigs, BuildMutatorsString)
308 ret_string = strcat(ret_string, ":bugrigs");
312 MUTATOR_HOOKFUNCTION(bugrigs, BuildMutatorsPrettyString)
314 ret_string = strcat(ret_string, ", Bug rigs");