3 #include "../../../../server/antilag.qh"
5 #include "../../../physics.qh"
9 void bugrigs_SetVars();
10 void bugrigs_AddStats();
12 REGISTER_MUTATOR(bugrigs, cvar("g_bugrigs"))
22 REGISTER_MUTATOR(bugrigs, true);
28 #define PHYS_BUGRIGS getstati(STAT_BUGRIGS)
29 #define PHYS_BUGRIGS_ANGLE_SMOOTHING getstati(STAT_BUGRIGS_ANGLE_SMOOTHING)
30 #define PHYS_BUGRIGS_PLANAR_MOVEMENT getstati(STAT_BUGRIGS_PLANAR_MOVEMENT)
31 #define PHYS_BUGRIGS_REVERSE_SPEEDING getstati(STAT_BUGRIGS_REVERSE_SPEEDING)
32 #define PHYS_BUGRIGS_FRICTION_FLOOR getstatf(STAT_BUGRIGS_FRICTION_FLOOR)
33 #define PHYS_BUGRIGS_AIR_STEERING getstati(STAT_BUGRIGS_AIR_STEERING)
34 #define PHYS_BUGRIGS_FRICTION_BRAKE getstatf(STAT_BUGRIGS_FRICTION_BRAKE)
35 #define PHYS_BUGRIGS_ACCEL getstatf(STAT_BUGRIGS_ACCEL)
36 #define PHYS_BUGRIGS_SPEED_REF getstatf(STAT_BUGRIGS_SPEED_REF)
37 #define PHYS_BUGRIGS_SPEED_POW getstatf(STAT_BUGRIGS_SPEED_POW)
38 #define PHYS_BUGRIGS_STEER getstatf(STAT_BUGRIGS_STEER)
39 #define PHYS_BUGRIGS_FRICTION_AIR getstatf(STAT_BUGRIGS_FRICTION_AIR)
40 #define PHYS_BUGRIGS_CAR_JUMPING getstatf(STAT_BUGRIGS_CAR_JUMPING)
41 #define PHYS_BUGRIGS_REVERSE_SPINNING getstatf(STAT_BUGRIGS_REVERSE_SPINNING)
42 #define PHYS_BUGRIGS_REVERSE_STOPPING getstatf(STAT_BUGRIGS_REVERSE_STOPPING)
47 bool g_bugrigs_planar_movement;
48 bool g_bugrigs_planar_movement_car_jumping;
49 float g_bugrigs_reverse_spinning;
50 float g_bugrigs_reverse_speeding;
51 float g_bugrigs_reverse_stopping;
52 float g_bugrigs_air_steering;
53 float g_bugrigs_angle_smoothing;
54 float g_bugrigs_friction_floor;
55 float g_bugrigs_friction_brake;
56 float g_bugrigs_friction_air;
57 float g_bugrigs_accel;
58 float g_bugrigs_speed_ref;
59 float g_bugrigs_speed_pow;
60 float g_bugrigs_steer;
62 #define PHYS_BUGRIGS g_bugrigs
63 #define PHYS_BUGRIGS_ANGLE_SMOOTHING g_bugrigs_angle_smoothing
64 #define PHYS_BUGRIGS_PLANAR_MOVEMENT g_bugrigs_planar_movement
65 #define PHYS_BUGRIGS_REVERSE_SPEEDING g_bugrigs_reverse_speeding
66 #define PHYS_BUGRIGS_FRICTION_FLOOR g_bugrigs_friction_floor
67 #define PHYS_BUGRIGS_AIR_STEERING g_bugrigs_air_steering
68 #define PHYS_BUGRIGS_FRICTION_BRAKE g_bugrigs_friction_brake
69 #define PHYS_BUGRIGS_ACCEL g_bugrigs_accel
70 #define PHYS_BUGRIGS_SPEED_REF g_bugrigs_speed_ref
71 #define PHYS_BUGRIGS_SPEED_POW g_bugrigs_speed_pow
72 #define PHYS_BUGRIGS_STEER g_bugrigs_steer
73 #define PHYS_BUGRIGS_FRICTION_AIR g_bugrigs_friction_air
74 #define PHYS_BUGRIGS_CAR_JUMPING g_bugrigs_planar_movement_car_jumping
75 #define PHYS_BUGRIGS_REVERSE_SPINNING g_bugrigs_reverse_spinning
76 #define PHYS_BUGRIGS_REVERSE_STOPPING g_bugrigs_reverse_stopping
79 .float stat_bugrigs_angle_smoothing;
80 .float stat_bugrigs_planar_movement;
81 .float stat_bugrigs_reverse_speeding;
82 .float stat_bugrigs_friction_floor;
83 .float stat_bugrigs_air_steering;
84 .float stat_bugrigs_friction_brake;
85 .float stat_bugrigs_accel;
86 .float stat_bugrigs_speed_ref;
87 .float stat_bugrigs_speed_pow;
88 .float stat_bugrigs_steer;
89 .float stat_bugrigs_friction_air;
90 .float stat_bugrigs_car_jumping;
91 .float stat_bugrigs_reverse_spinning;
92 .float stat_bugrigs_reverse_stopping;
94 void bugrigs_SetVars()
96 g_bugrigs = cvar("g_bugrigs");
97 g_bugrigs_planar_movement = cvar("g_bugrigs_planar_movement");
98 g_bugrigs_planar_movement_car_jumping = cvar("g_bugrigs_planar_movement_car_jumping");
99 g_bugrigs_reverse_spinning = cvar("g_bugrigs_reverse_spinning");
100 g_bugrigs_reverse_speeding = cvar("g_bugrigs_reverse_speeding");
101 g_bugrigs_reverse_stopping = cvar("g_bugrigs_reverse_stopping");
102 g_bugrigs_air_steering = cvar("g_bugrigs_air_steering");
103 g_bugrigs_angle_smoothing = cvar("g_bugrigs_angle_smoothing");
104 g_bugrigs_friction_floor = cvar("g_bugrigs_friction_floor");
105 g_bugrigs_friction_brake = cvar("g_bugrigs_friction_brake");
106 g_bugrigs_friction_air = cvar("g_bugrigs_friction_air");
107 g_bugrigs_accel = cvar("g_bugrigs_accel");
108 g_bugrigs_speed_ref = cvar("g_bugrigs_speed_ref");
109 g_bugrigs_speed_pow = cvar("g_bugrigs_speed_pow");
110 g_bugrigs_steer = cvar("g_bugrigs_steer");
113 void bugrigs_UpdateStats(entity this)
115 this.stat_bugrigs = PHYS_BUGRIGS;
116 this.stat_bugrigs_angle_smoothing = PHYS_BUGRIGS_ANGLE_SMOOTHING;
117 this.stat_bugrigs_planar_movement = PHYS_BUGRIGS_PLANAR_MOVEMENT;
118 this.stat_bugrigs_reverse_speeding = PHYS_BUGRIGS_REVERSE_SPEEDING;
119 this.stat_bugrigs_friction_floor = PHYS_BUGRIGS_FRICTION_FLOOR;
120 this.stat_bugrigs_air_steering = PHYS_BUGRIGS_AIR_STEERING;
121 this.stat_bugrigs_friction_brake = PHYS_BUGRIGS_FRICTION_BRAKE;
122 this.stat_bugrigs_accel = PHYS_BUGRIGS_ACCEL;
123 this.stat_bugrigs_speed_ref = PHYS_BUGRIGS_SPEED_REF;
124 this.stat_bugrigs_speed_pow = PHYS_BUGRIGS_SPEED_POW;
125 this.stat_bugrigs_steer = PHYS_BUGRIGS_STEER;
126 this.stat_bugrigs_friction_air = PHYS_BUGRIGS_FRICTION_AIR;
127 this.stat_bugrigs_car_jumping = PHYS_BUGRIGS_CAR_JUMPING;
128 this.stat_bugrigs_reverse_spinning = PHYS_BUGRIGS_REVERSE_SPINNING;
129 this.stat_bugrigs_reverse_stopping = PHYS_BUGRIGS_REVERSE_STOPPING;
132 void bugrigs_AddStats()
134 addstat(STAT_BUGRIGS, AS_INT, stat_bugrigs);
135 addstat(STAT_BUGRIGS_ANGLE_SMOOTHING, AS_INT, stat_bugrigs_angle_smoothing);
136 addstat(STAT_BUGRIGS_PLANAR_MOVEMENT, AS_INT, stat_bugrigs_planar_movement);
137 addstat(STAT_BUGRIGS_REVERSE_SPEEDING, AS_INT, stat_bugrigs_reverse_speeding);
138 addstat(STAT_BUGRIGS_FRICTION_FLOOR, AS_FLOAT, stat_bugrigs_friction_floor);
139 addstat(STAT_BUGRIGS_AIR_STEERING, AS_INT, stat_bugrigs_air_steering);
140 addstat(STAT_BUGRIGS_FRICTION_BRAKE, AS_FLOAT, stat_bugrigs_friction_brake);
141 addstat(STAT_BUGRIGS_ACCEL, AS_FLOAT, stat_bugrigs_accel);
142 addstat(STAT_BUGRIGS_SPEED_REF, AS_FLOAT, stat_bugrigs_speed_ref);
143 addstat(STAT_BUGRIGS_SPEED_POW, AS_FLOAT, stat_bugrigs_speed_pow);
144 addstat(STAT_BUGRIGS_STEER, AS_FLOAT, stat_bugrigs_steer);
145 addstat(STAT_BUGRIGS_FRICTION_AIR, AS_FLOAT, stat_bugrigs_friction_air);
146 addstat(STAT_BUGRIGS_CAR_JUMPING, AS_FLOAT, stat_bugrigs_car_jumping);
147 addstat(STAT_BUGRIGS_REVERSE_SPINNING, AS_FLOAT, stat_bugrigs_reverse_spinning);
148 addstat(STAT_BUGRIGS_REVERSE_STOPPING, AS_FLOAT, stat_bugrigs_reverse_stopping);
153 void RaceCarPhysics(entity this)
155 // using this move type for "big rigs"
156 // the engine does not push the entity!
160 vector angles_save = this.angles;
161 float accel = bound(-1, this.movement.x / PHYS_MAXSPEED(this), 1);
162 float steer = bound(-1, this.movement.y / PHYS_MAXSPEED(this), 1);
164 if (PHYS_BUGRIGS_REVERSE_SPEEDING)
168 // back accel is DIGITAL
169 // to prevent speedhack
179 makevectors(this.angles); // new forward direction!
181 if (IS_ONGROUND(this) || PHYS_BUGRIGS_AIR_STEERING)
183 float myspeed = this.velocity * v_forward;
184 float upspeed = this.velocity * v_up;
186 // responsiveness factor for steering and acceleration
187 float f = 1 / (1 + pow(max(-myspeed, myspeed) / PHYS_BUGRIGS_SPEED_REF, PHYS_BUGRIGS_SPEED_POW));
188 //MAXIMA: f(v) := 1 / (1 + (v / PHYS_BUGRIGS_SPEED_REF) ^ PHYS_BUGRIGS_SPEED_POW);
191 if (myspeed < 0 && PHYS_BUGRIGS_REVERSE_SPINNING)
192 steerfactor = -myspeed * PHYS_BUGRIGS_STEER;
194 steerfactor = -myspeed * f * PHYS_BUGRIGS_STEER;
197 if (myspeed < 0 && PHYS_BUGRIGS_REVERSE_SPEEDING)
198 accelfactor = PHYS_BUGRIGS_ACCEL;
200 accelfactor = f * PHYS_BUGRIGS_ACCEL;
201 //MAXIMA: accel(v) := f(v) * PHYS_BUGRIGS_ACCEL;
207 myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * (PHYS_BUGRIGS_FRICTION_FLOOR - PHYS_BUGRIGS_FRICTION_BRAKE * accel));
211 if (!PHYS_BUGRIGS_REVERSE_SPEEDING)
212 myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_FRICTION_FLOOR);
219 myspeed = max(0, myspeed - PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_FRICTION_FLOOR);
223 if (PHYS_BUGRIGS_REVERSE_STOPPING)
226 myspeed = min(0, myspeed + PHYS_INPUT_TIMELENGTH * (PHYS_BUGRIGS_FRICTION_FLOOR + PHYS_BUGRIGS_FRICTION_BRAKE * accel));
229 // terminal velocity = velocity at which 50 == accelfactor, that is, 1549 units/sec
230 //MAXIMA: friction(v) := PHYS_BUGRIGS_FRICTION_FLOOR;
232 this.angles_y += steer * PHYS_INPUT_TIMELENGTH * steerfactor; // apply steering
233 makevectors(this.angles); // new forward direction!
235 myspeed += accel * accelfactor * PHYS_INPUT_TIMELENGTH;
237 rigvel = myspeed * v_forward + '0 0 1' * upspeed;
241 float myspeed = vlen(this.velocity);
243 // responsiveness factor for steering and acceleration
244 float f = 1 / (1 + pow(max(0, myspeed / PHYS_BUGRIGS_SPEED_REF), PHYS_BUGRIGS_SPEED_POW));
245 float steerfactor = -myspeed * f;
246 this.angles_y += steer * PHYS_INPUT_TIMELENGTH * steerfactor; // apply steering
248 rigvel = this.velocity;
249 makevectors(this.angles); // new forward direction!
252 rigvel *= max(0, 1 - vlen(rigvel) * PHYS_BUGRIGS_FRICTION_AIR * PHYS_INPUT_TIMELENGTH);
253 //MAXIMA: airfriction(v) := v * v * PHYS_BUGRIGS_FRICTION_AIR;
254 //MAXIMA: total_acceleration(v) := accel(v) - friction(v) - airfriction(v);
255 //MAXIMA: solve(total_acceleration(v) = 0, v);
257 if (PHYS_BUGRIGS_PLANAR_MOVEMENT)
259 vector rigvel_xy, neworigin, up;
262 rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY; // 4x gravity plays better
263 rigvel_xy = vec2(rigvel);
265 if (PHYS_BUGRIGS_CAR_JUMPING)
268 mt = MOVE_NOMONSTERS;
270 tracebox(this.origin, this.mins, this.maxs, this.origin + '0 0 1024', mt, this);
271 up = trace_endpos - this.origin;
273 // BUG RIGS: align the move to the surface instead of doing collision testing
275 tracebox(trace_endpos, this.mins, this.maxs, trace_endpos + rigvel_xy * PHYS_INPUT_TIMELENGTH, mt, this);
278 tracebox(trace_endpos, this.mins, this.maxs, trace_endpos - up + '0 0 1' * rigvel_z * PHYS_INPUT_TIMELENGTH, mt, this);
280 if (trace_fraction < 0.5)
283 neworigin = this.origin;
286 neworigin = trace_endpos;
288 if (trace_fraction < 1)
290 // now set angles_x so that the car points parallel to the surface
291 this.angles = vectoangles(
292 '1 0 0' * v_forward_x * trace_plane_normal_z
294 '0 1 0' * v_forward_y * trace_plane_normal_z
296 '0 0 1' * -(v_forward_x * trace_plane_normal_x + v_forward_y * trace_plane_normal_y)
302 // now set angles_x so that the car points forward, but is tilted in velocity direction
303 UNSET_ONGROUND(this);
306 this.velocity = (neworigin - this.origin) * (1.0 / PHYS_INPUT_TIMELENGTH);
307 this.movetype = MOVETYPE_NOCLIP;
311 rigvel_z -= PHYS_INPUT_TIMELENGTH * PHYS_GRAVITY; // 4x gravity plays better
312 this.velocity = rigvel;
313 this.movetype = MOVETYPE_FLY;
317 tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 4', MOVE_NORMAL, this);
318 if (trace_fraction != 1)
320 this.angles = vectoangles2(
321 '1 0 0' * v_forward_x * trace_plane_normal_z
323 '0 1 0' * v_forward_y * trace_plane_normal_z
325 '0 0 1' * -(v_forward_x * trace_plane_normal_x + v_forward_y * trace_plane_normal_y),
333 vel_local_x = v_forward * this.velocity;
334 vel_local_y = v_right * this.velocity;
335 vel_local_z = v_up * this.velocity;
337 this.angles_x = racecar_angle(vel_local_x, vel_local_z);
338 this.angles_z = racecar_angle(-vel_local_y, vel_local_z);
342 vector vf1, vu1, smoothangles;
343 makevectors(this.angles);
344 float f = bound(0, PHYS_INPUT_TIMELENGTH * PHYS_BUGRIGS_ANGLE_SMOOTHING, 1);
349 makevectors(angles_save);
350 vf1 = vf1 + v_forward * (1 - f);
351 vu1 = vu1 + v_up * (1 - f);
352 smoothangles = vectoangles2(vf1, vu1);
353 this.angles_x = -smoothangles_x;
354 this.angles_z = smoothangles_z;
356 PM_ClientMovement_Move();
360 .vector bugrigs_prevangles;
362 MUTATOR_HOOKFUNCTION(bugrigs, PM_Physics)
364 if(!PHYS_BUGRIGS || !IS_PLAYER(self)) { return false; }
367 self.angles = self.bugrigs_prevangles;
370 RaceCarPhysics(self);
374 MUTATOR_HOOKFUNCTION(bugrigs, PlayerPhysics)
376 if(!PHYS_BUGRIGS) { return false; }
378 self.bugrigs_prevangles = self.angles;
380 bugrigs_UpdateStats(self);
387 MUTATOR_HOOKFUNCTION(bugrigs, ClientConnect)
389 stuffcmd(self, "cl_cmd settemp chase_active 1\n");
393 MUTATOR_HOOKFUNCTION(bugrigs, BuildMutatorsString)
395 ret_string = strcat(ret_string, ":bugrigs");
399 MUTATOR_HOOKFUNCTION(bugrigs, BuildMutatorsPrettyString)
401 ret_string = strcat(ret_string, ", Bug rigs");