]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/mutators/mutator/bugrigs/bugrigs.qc
Removed useless comment.
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / mutators / mutator / bugrigs / bugrigs.qc
1 #include "bugrigs.qh"
2
3 #ifdef GAMEQC
4
5 #ifdef SVQC
6         #include <server/antilag.qh>
7 #endif
8 #include <common/physics/player.qh>
9
10
11 #if defined(SVQC)
12 void bugrigs_SetVars();
13
14 REGISTER_MUTATOR(bugrigs, cvar("g_bugrigs"))
15 {
16         MUTATOR_ONADD
17         {
18                 bugrigs_SetVars();
19         }
20         return false;
21 }
22 #elif defined(CSQC)
23 REGISTER_MUTATOR(bugrigs, true);
24 #endif
25
26
27 #define PHYS_BUGRIGS(s)                        STAT(BUGRIGS, s)
28 #define PHYS_BUGRIGS_ACCEL(s)                  STAT(BUGRIGS_ACCEL, s)
29 #define PHYS_BUGRIGS_AIR_STEERING(s)           STAT(BUGRIGS_AIR_STEERING, s)
30 #define PHYS_BUGRIGS_ANGLE_SMOOTHING(s)        STAT(BUGRIGS_ANGLE_SMOOTHING, s)
31 #define PHYS_BUGRIGS_CAR_JUMPING(s)            STAT(BUGRIGS_CAR_JUMPING, s)
32 #define PHYS_BUGRIGS_FRICTION_AIR(s)           STAT(BUGRIGS_FRICTION_AIR, s)
33 #define PHYS_BUGRIGS_FRICTION_BRAKE(s)         STAT(BUGRIGS_FRICTION_BRAKE, s)
34 #define PHYS_BUGRIGS_FRICTION_FLOOR(s)         STAT(BUGRIGS_FRICTION_FLOOR, s)
35 #define PHYS_BUGRIGS_PLANAR_MOVEMENT(s)        STAT(BUGRIGS_PLANAR_MOVEMENT, s)
36 #define PHYS_BUGRIGS_REVERSE_SPEEDING(s)       STAT(BUGRIGS_REVERSE_SPEEDING, s)
37 #define PHYS_BUGRIGS_REVERSE_SPINNING(s)       STAT(BUGRIGS_REVERSE_SPINNING, s)
38 #define PHYS_BUGRIGS_REVERSE_STOPPING(s)       STAT(BUGRIGS_REVERSE_STOPPING, s)
39 #define PHYS_BUGRIGS_SPEED_POW(s)              STAT(BUGRIGS_SPEED_POW, s)
40 #define PHYS_BUGRIGS_SPEED_REF(s)              STAT(BUGRIGS_SPEED_REF, s)
41 #define PHYS_BUGRIGS_STEER(s)                  STAT(BUGRIGS_STEER, s)
42
43 #if defined(SVQC)
44
45 void bugrigs_SetVars()
46 {
47         g_bugrigs = cvar("g_bugrigs");
48         g_bugrigs_planar_movement = cvar("g_bugrigs_planar_movement");
49         g_bugrigs_planar_movement_car_jumping = cvar("g_bugrigs_planar_movement_car_jumping");
50         g_bugrigs_reverse_spinning = cvar("g_bugrigs_reverse_spinning");
51         g_bugrigs_reverse_speeding = cvar("g_bugrigs_reverse_speeding");
52         g_bugrigs_reverse_stopping = cvar("g_bugrigs_reverse_stopping");
53         g_bugrigs_air_steering = cvar("g_bugrigs_air_steering");
54         g_bugrigs_angle_smoothing = cvar("g_bugrigs_angle_smoothing");
55         g_bugrigs_friction_floor = cvar("g_bugrigs_friction_floor");
56         g_bugrigs_friction_brake = cvar("g_bugrigs_friction_brake");
57         g_bugrigs_friction_air = cvar("g_bugrigs_friction_air");
58         g_bugrigs_accel = cvar("g_bugrigs_accel");
59         g_bugrigs_speed_ref = cvar("g_bugrigs_speed_ref");
60         g_bugrigs_speed_pow = cvar("g_bugrigs_speed_pow");
61         g_bugrigs_steer = cvar("g_bugrigs_steer");
62 }
63
64 #endif
65
66 void RaceCarPhysics(entity this, float dt)
67 {
68         // using this move type for "big rigs"
69         // the engine does not push the entity!
70
71         vector rigvel;
72
73         vector angles_save = this.angles;
74         float accel = bound(-1, this.movement.x / PHYS_MAXSPEED(this), 1);
75         float steer = bound(-1, this.movement.y / PHYS_MAXSPEED(this), 1);
76
77         if (PHYS_BUGRIGS_REVERSE_SPEEDING(this))
78         {
79                 if (accel < 0)
80                 {
81                         // back accel is DIGITAL
82                         // to prevent speedhack
83                         if (accel < -0.5)
84                                 accel = -1;
85                         else
86                                 accel = 0;
87                 }
88         }
89
90         this.angles_x = 0;
91         this.angles_z = 0;
92         makevectors(this.angles); // new forward direction!
93
94         if (IS_ONGROUND(this) || PHYS_BUGRIGS_AIR_STEERING(this))
95         {
96                 float myspeed = this.velocity * v_forward;
97                 float upspeed = this.velocity * v_up;
98
99                 // responsiveness factor for steering and acceleration
100                 float f = 1 / (1 + ((max(-myspeed, myspeed) / PHYS_BUGRIGS_SPEED_REF(this)) ** PHYS_BUGRIGS_SPEED_POW(this)));
101                 //MAXIMA: f(v) := 1 / (1 + (v / PHYS_BUGRIGS_SPEED_REF(this)) ^ PHYS_BUGRIGS_SPEED_POW(this));
102
103                 float steerfactor;
104                 if (myspeed < 0 && PHYS_BUGRIGS_REVERSE_SPINNING(this))
105                         steerfactor = -myspeed * PHYS_BUGRIGS_STEER(this);
106                 else
107                         steerfactor = -myspeed * f * PHYS_BUGRIGS_STEER(this);
108
109                 float accelfactor;
110                 if (myspeed < 0 && PHYS_BUGRIGS_REVERSE_SPEEDING(this))
111                         accelfactor = PHYS_BUGRIGS_ACCEL(this);
112                 else
113                         accelfactor = f * PHYS_BUGRIGS_ACCEL(this);
114                 //MAXIMA: accel(v) := f(v) * PHYS_BUGRIGS_ACCEL(this);
115
116                 if (accel < 0)
117                 {
118                         if (myspeed > 0)
119                         {
120                                 myspeed = max(0, myspeed - dt * (PHYS_BUGRIGS_FRICTION_FLOOR(this) - PHYS_BUGRIGS_FRICTION_BRAKE(this) * accel));
121                         }
122                         else
123                         {
124                                 if (!PHYS_BUGRIGS_REVERSE_SPEEDING(this))
125                                         myspeed = min(0, myspeed + dt * PHYS_BUGRIGS_FRICTION_FLOOR(this));
126                         }
127                 }
128                 else
129                 {
130                         if (myspeed >= 0)
131                         {
132                                 myspeed = max(0, myspeed - dt * PHYS_BUGRIGS_FRICTION_FLOOR(this));
133                         }
134                         else
135                         {
136                                 if (PHYS_BUGRIGS_REVERSE_STOPPING(this))
137                                         myspeed = 0;
138                                 else
139                                         myspeed = min(0, myspeed + dt * (PHYS_BUGRIGS_FRICTION_FLOOR(this) + PHYS_BUGRIGS_FRICTION_BRAKE(this) * accel));
140                         }
141                 }
142                 // terminal velocity = velocity at which 50 == accelfactor, that is, 1549 units/sec
143                 //MAXIMA: friction(v) := PHYS_BUGRIGS_FRICTION_FLOOR(this);
144
145                 this.angles_y += steer * dt * steerfactor; // apply steering
146                 makevectors(this.angles); // new forward direction!
147
148                 myspeed += accel * accelfactor * dt;
149
150                 rigvel = myspeed * v_forward + '0 0 1' * upspeed;
151         }
152         else
153         {
154                 float myspeed = vlen(this.velocity);
155
156                 // responsiveness factor for steering and acceleration
157                 float f = 1 / (1 + (max(0, myspeed / PHYS_BUGRIGS_SPEED_REF(this)) ** PHYS_BUGRIGS_SPEED_POW(this)));
158                 float steerfactor = -myspeed * f;
159                 this.angles_y += steer * dt * steerfactor; // apply steering
160
161                 rigvel = this.velocity;
162                 makevectors(this.angles); // new forward direction!
163         }
164
165         rigvel *= max(0, 1 - vlen(rigvel) * PHYS_BUGRIGS_FRICTION_AIR(this) * dt);
166         //MAXIMA: airfriction(v) := v * v * PHYS_BUGRIGS_FRICTION_AIR(this);
167         //MAXIMA: total_acceleration(v) := accel(v) - friction(v) - airfriction(v);
168         //MAXIMA: solve(total_acceleration(v) = 0, v);
169
170         if (PHYS_BUGRIGS_PLANAR_MOVEMENT(this))
171         {
172                 vector rigvel_xy, neworigin, up;
173                 float mt;
174
175                 rigvel_z -= dt * PHYS_GRAVITY(this); // 4x gravity plays better
176                 rigvel_xy = vec2(rigvel);
177
178                 if (PHYS_BUGRIGS_CAR_JUMPING(this))
179                         mt = MOVE_NORMAL;
180                 else
181                         mt = MOVE_NOMONSTERS;
182
183                 tracebox(this.origin, this.mins, this.maxs, this.origin + '0 0 1024', mt, this);
184                 up = trace_endpos - this.origin;
185
186                 // BUG RIGS: align the move to the surface instead of doing collision testing
187                 // can we move?
188                 tracebox(trace_endpos, this.mins, this.maxs, trace_endpos + rigvel_xy * dt, mt, this);
189
190                 // align to surface
191                 tracebox(trace_endpos, this.mins, this.maxs, trace_endpos - up + '0 0 1' * rigvel_z * dt, mt, this);
192
193                 if (trace_fraction < 0.5)
194                 {
195                         trace_fraction = 1;
196                         neworigin = this.origin;
197                 }
198                 else
199                         neworigin = trace_endpos;
200
201                 if (trace_fraction < 1)
202                 {
203                         // now set angles_x so that the car points parallel to the surface
204                         this.angles = vectoangles(
205                                         '1 0 0' * v_forward_x * trace_plane_normal_z
206                                         +
207                                         '0 1 0' * v_forward_y * trace_plane_normal_z
208                                         +
209                                         '0 0 1' * -(v_forward_x * trace_plane_normal_x + v_forward_y * trace_plane_normal_y)
210                                         );
211                         SET_ONGROUND(this);
212                 }
213                 else
214                 {
215                         // now set angles_x so that the car points forward, but is tilted in velocity direction
216                         UNSET_ONGROUND(this);
217                 }
218
219                 this.velocity = (neworigin - this.origin) * (1.0 / dt);
220                 set_movetype(this, MOVETYPE_NOCLIP);
221         }
222         else
223         {
224                 rigvel_z -= dt * PHYS_GRAVITY(this); // 4x gravity plays better
225                 this.velocity = rigvel;
226                 set_movetype(this, MOVETYPE_FLY);
227         }
228
229         trace_fraction = 1;
230         tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 4', MOVE_NORMAL, this);
231         if (trace_fraction != 1)
232         {
233                 this.angles = vectoangles2(
234                                 '1 0 0' * v_forward_x * trace_plane_normal_z
235                                 +
236                                 '0 1 0' * v_forward_y * trace_plane_normal_z
237                                 +
238                                 '0 0 1' * -(v_forward_x * trace_plane_normal_x + v_forward_y * trace_plane_normal_y),
239                                 trace_plane_normal
240                                 );
241         }
242         else
243         {
244                 vector vel_local;
245
246                 vel_local_x = v_forward * this.velocity;
247                 vel_local_y = v_right * this.velocity;
248                 vel_local_z = v_up * this.velocity;
249
250                 this.angles_x = racecar_angle(vel_local_x, vel_local_z);
251                 this.angles_z = racecar_angle(-vel_local_y, vel_local_z);
252         }
253
254         // smooth the angles
255         vector vf1, vu1, smoothangles;
256         makevectors(this.angles);
257         float f = bound(0, dt * PHYS_BUGRIGS_ANGLE_SMOOTHING(this), 1);
258         if (f == 0)
259                 f = 1;
260         vf1 = v_forward * f;
261         vu1 = v_up * f;
262         makevectors(angles_save);
263         vf1 = vf1 + v_forward * (1 - f);
264         vu1 = vu1 + v_up * (1 - f);
265         smoothangles = vectoangles2(vf1, vu1);
266         this.angles_x = -smoothangles_x;
267         this.angles_z =  smoothangles_z;
268 }
269
270 #ifdef SVQC
271 .vector bugrigs_prevangles;
272 #endif
273 MUTATOR_HOOKFUNCTION(bugrigs, PM_Physics)
274 {
275     entity player = M_ARGV(0, entity);
276     float dt = M_ARGV(2, float);
277
278         if(!PHYS_BUGRIGS(player) || !IS_PLAYER(player)) { return; }
279
280 #ifdef SVQC
281         player.angles = player.bugrigs_prevangles;
282 #endif
283
284         RaceCarPhysics(player, dt);
285         return true;
286 }
287
288 MUTATOR_HOOKFUNCTION(bugrigs, PlayerPhysics)
289 {
290         if(!PHYS_BUGRIGS(M_ARGV(0, entity))) { return; }
291 #ifdef SVQC
292         entity player = M_ARGV(0, entity);
293         player.bugrigs_prevangles = player.angles;
294 #endif
295 }
296
297 #ifdef SVQC
298
299 MUTATOR_HOOKFUNCTION(bugrigs, ClientConnect)
300 {
301     entity player = M_ARGV(0, entity);
302
303         stuffcmd(player, "cl_cmd settemp chase_active 1\n");
304 }
305
306 MUTATOR_HOOKFUNCTION(bugrigs, BuildMutatorsString)
307 {
308         M_ARGV(0, string) = strcat(M_ARGV(0, string), ":bugrigs");
309 }
310
311 MUTATOR_HOOKFUNCTION(bugrigs, BuildMutatorsPrettyString)
312 {
313         M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Bug rigs");
314 }
315
316 #endif
317
318 #endif