]> icculus.org git repositories - btb/d2x.git/blob - main/controls.c
start refactoring Controls stuff more logically, now that it no longer has anything...
[btb/d2x.git] / main / controls.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14 /*
15  *
16  * Code for controlling player movement
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <conf.h>
22 #endif
23
24 #include <stdio.h>
25 #include <stdlib.h>
26
27 #include "pstypes.h"
28 #include "mono.h"
29 #include "key.h"
30 #include "joy.h"
31 #include "timer.h"
32 #include "error.h"
33
34 #include "inferno.h"
35 #include "game.h"
36 #include "object.h"
37 #include "player.h"
38
39 #include "controls.h"
40 #include "joydefs.h"
41 #include "render.h"
42 #include "args.h"
43 #include "palette.h"
44 #include "mouse.h"
45 #include "kconfig.h"
46 #include "laser.h"
47 #ifdef NETWORK
48 #include "multi.h"
49 #endif
50 #include "vclip.h"
51 #include "fireball.h"
52
53 //look at keyboard, mouse, joystick, CyberMan, whatever, and set 
54 //physics vars rotvel, velocity
55
56 fix Afterburner_charge=f1_0;
57
58 #define AFTERBURNER_USE_SECS    3                               //use up in 3 seconds
59 #define DROP_DELTA_TIME                 (f1_0/15)       //drop 3 per second
60
61 extern int Drop_afterburner_blob_flag;          //ugly hack
62
63 extern fix      Seismic_tremor_magnitude;
64
65 void read_flying_controls( object * obj )
66 {
67         fix     forward_thrust_time;
68
69         Assert(FrameTime > 0);          //Get MATT if hit this!
70
71 // this section commented and moved to the bottom by WraithX
72 //      if (Player_is_dead) {
73 //              vm_vec_zero(&obj->mtype.phys_info.rotthrust);
74 //              vm_vec_zero(&obj->mtype.phys_info.thrust);
75 //              return;
76 //      }
77 // end of section to be moved.
78
79         if ((obj->type!=OBJ_PLAYER) || (obj->id!=Player_num)) return;   //references to player_ship require that this obj be the player
80
81         if (Guided_missile[Player_num] && Guided_missile[Player_num]->signature==Guided_missile_sig[Player_num]) {
82                 vms_angvec rotangs;
83                 vms_matrix rotmat,tempm;
84                 fix speed;
85
86                 //this is a horrible hack.  guided missile stuff should not be
87                 //handled in the middle of a routine that is dealing with the player
88
89                 vm_vec_zero(&obj->mtype.phys_info.rotthrust);
90
91                 rotangs.p = Controls.pitch_time / 2 + Seismic_tremor_magnitude/64;
92                 rotangs.b = Controls.bank_time / 2 + Seismic_tremor_magnitude/16;
93                 rotangs.h = Controls.heading_time / 2 + Seismic_tremor_magnitude/64;
94
95                 vm_angles_2_matrix(&rotmat,&rotangs);
96
97                 vm_matrix_x_matrix(&tempm,&Guided_missile[Player_num]->orient,&rotmat);
98
99                 Guided_missile[Player_num]->orient = tempm;
100
101                 speed = Weapon_info[Guided_missile[Player_num]->id].speed[Difficulty_level];
102
103                 vm_vec_copy_scale(&Guided_missile[Player_num]->mtype.phys_info.velocity,&Guided_missile[Player_num]->orient.fvec,speed);
104 #ifdef NETWORK
105                 if (Game_mode & GM_MULTI)
106                         multi_send_guided_info (Guided_missile[Player_num],0);
107 #endif
108
109         }
110         else {
111                 obj->mtype.phys_info.rotthrust.x = Controls.pitch_time;
112                 obj->mtype.phys_info.rotthrust.y = Controls.heading_time;
113                 obj->mtype.phys_info.rotthrust.z = Controls.bank_time;
114         }
115
116 //      mprintf( (0, "Rot thrust = %.3f,%.3f,%.3f\n", f2fl(obj->mtype.phys_info.rotthrust.x),f2fl(obj->mtype.phys_info.rotthrust.y), f2fl(obj->mtype.phys_info.rotthrust.z) ));
117
118         forward_thrust_time = Controls.forward_thrust_time;
119
120         if (Players[Player_num].flags & PLAYER_FLAGS_AFTERBURNER)
121         {
122                 if (Controls.state[afterburner]) { // player has key down
123                         //if (forward_thrust_time >= 0) {               //..and isn't moving backward
124                         {
125                                 fix afterburner_scale;
126                                 int old_count,new_count;
127         
128                                 //add in value from 0..1
129                                 afterburner_scale = f1_0 + min(f1_0/2,Afterburner_charge) * 2;
130         
131                                 forward_thrust_time = fixmul(FrameTime,afterburner_scale);      //based on full thrust
132         
133                                 old_count = (Afterburner_charge / (DROP_DELTA_TIME/AFTERBURNER_USE_SECS));
134
135                                 Afterburner_charge -= FrameTime/AFTERBURNER_USE_SECS;
136
137                                 if (Afterburner_charge < 0)
138                                         Afterburner_charge = 0;
139
140                                 new_count = (Afterburner_charge / (DROP_DELTA_TIME/AFTERBURNER_USE_SECS));
141
142                                 if (old_count != new_count)
143                                         Drop_afterburner_blob_flag = 1; //drop blob (after physics called)
144                         }
145                 }
146                 else {
147                         fix cur_energy,charge_up;
148         
149                         //charge up to full
150                         charge_up = min(FrameTime/8,f1_0 - Afterburner_charge); //recharge over 8 seconds
151         
152                         cur_energy = max(Players[Player_num].energy-i2f(10),0); //don't drop below 10
153
154                         //maybe limit charge up by energy
155                         charge_up = min(charge_up,cur_energy/10);
156         
157                         Afterburner_charge += charge_up;
158         
159                         Players[Player_num].energy -= charge_up * 100 / 10;     //full charge uses 10% of energy
160                 }
161         }
162
163         // Set object's thrust vector for forward/backward
164         vm_vec_copy_scale(&obj->mtype.phys_info.thrust,&obj->orient.fvec, forward_thrust_time );
165         
166         // slide left/right
167         vm_vec_scale_add2(&obj->mtype.phys_info.thrust,&obj->orient.rvec, Controls.sideways_thrust_time );
168
169         // slide up/down
170         vm_vec_scale_add2(&obj->mtype.phys_info.thrust,&obj->orient.uvec, Controls.vertical_thrust_time );
171
172         if (obj->mtype.phys_info.flags & PF_WIGGLE)
173         {
174                 fix swiggle;
175                 fix_fastsincos(GameTime, &swiggle, NULL);
176                 if (FrameTime < F1_0) // Only scale wiggle if getting at least 1 FPS, to avoid causing the opposite problem.
177                         swiggle = fixmul(swiggle*20, FrameTime); //make wiggle fps-independent (based on pre-scaled amount of wiggle at 20 FPS)
178                 vm_vec_scale_add2(&obj->mtype.phys_info.velocity,&obj->orient.uvec,fixmul(swiggle,Player_ship->wiggle));
179         }
180
181         // As of now, obj->mtype.phys_info.thrust & obj->mtype.phys_info.rotthrust are 
182         // in units of time... In other words, if thrust==FrameTime, that
183         // means that the user was holding down the Max_thrust key for the
184         // whole frame.  So we just scale them up by the max, and divide by
185         // FrameTime to make them independant of framerate
186
187         //      Prevent divide overflows on high frame rates.
188         //      In a signed divide, you get an overflow if num >= div<<15
189         {
190                 fix     ft = FrameTime;
191
192                 //      Note, you must check for ft < F1_0/2, else you can get an overflow  on the << 15.
193                 if ((ft < F1_0/2) && (ft << 15 <= Player_ship->max_thrust)) {
194                         mprintf((0, "Preventing divide overflow in controls.c for Max_thrust!\n"));
195                         ft = (Player_ship->max_thrust >> 15) + 1;
196                 }
197
198                 vm_vec_scale( &obj->mtype.phys_info.thrust, fixdiv(Player_ship->max_thrust,ft) );
199
200                 if ((ft < F1_0/2) && (ft << 15 <= Player_ship->max_rotthrust)) {
201                         mprintf((0, "Preventing divide overflow in controls.c for max_rotthrust!\n"));
202                         ft = (Player_ship->max_thrust >> 15) + 1;
203                 }
204
205                 vm_vec_scale( &obj->mtype.phys_info.rotthrust, fixdiv(Player_ship->max_rotthrust,ft) );
206         }
207
208         // moved here by WraithX
209         if (Player_is_dead)
210         {
211                 //vm_vec_zero(&obj->mtype.phys_info.rotthrust); // let dead players rotate, changed by WraithX
212                 vm_vec_zero(&obj->mtype.phys_info.thrust);  // don't let dead players move, changed by WraithX
213                 return;
214         }// end if
215
216 }
217
218
219 extern void transfer_energy_to_shield(fix);
220
221 control_info Controls;
222
223 fix Cruise_speed = 0;
224
225 #define PH_SCALE 8
226
227 #ifndef __MSDOS__
228 #define JOYSTICK_READ_TIME (F1_0 / 40) // Read joystick at 40 Hz.
229 #else
230 #define JOYSTICK_READ_TIME (F1_0 / 10) // Read joystick at 10 Hz.
231 #endif
232
233 fix     LastReadTime = 0;
234
235 fix     joy_axis[JOY_MAX_AXES];
236
237
238 void reset_cruise(void)
239 {
240         Cruise_speed = 0;
241 }
242
243
244 static inline void button_down(control_button button)
245 {
246         Controls.count[button]++;
247         Controls.state[button] = 1;
248         Controls.time_went_down[button] = timer_get_fixed_seconds();
249 }
250
251
252 static inline void button_up(control_button button)
253 {
254         Controls.state[button] = 0;
255         Controls.time_held_down[button] += timer_get_fixed_seconds() - Controls.time_went_down[button];
256 }
257
258
259 void controls_cmd_strafe_on(int argc, char **argv)     { button_down(slide_on); }
260 void controls_cmd_strafe_off(int argc, char **argv)    { button_up(slide_on); }
261 void controls_cmd_bank_on(int argc, char **argv)       { button_down(bank_on); }
262 void controls_cmd_bank_off(int argc, char **argv)      { button_up(bank_on); }
263 void controls_cmd_attack_on(int argc, char **argv)     { button_down(fire_primary); }
264 void controls_cmd_attack_off(int argc, char **argv)    { button_up(fire_primary); }
265 void controls_cmd_attack2_on(int argc, char **argv)    { button_down(fire_secondary); }
266 void controls_cmd_attack2_off(int argc, char **argv)   { button_up(fire_secondary); }
267 void controls_cmd_rearview_on(int argc, char **argv)   { button_down(rear_view); }
268 void controls_cmd_rearview_off(int argc, char **argv)  { button_up(rear_view); }
269 void controls_cmd_automap_on(int argc, char **argv)    { button_down(automap); }
270 void controls_cmd_automap_off(int argc, char **argv)   { button_up(automap); }
271 void controls_cmd_afterburn_on(int argc, char **argv)  { button_down(afterburner); }
272 void controls_cmd_afterburn_off(int argc, char **argv) { button_up(afterburner); }
273 void controls_cmd_flare(int argc, char **argv)         { button_down(fire_flare); }
274 void controls_cmd_bomb(int argc, char **argv)          { button_up(drop_bomb); }
275 void controls_cmd_cycle(int argc, char **argv)         { button_down(cycle_primary); }
276 void controls_cmd_cycle2(int argc, char **argv)        { button_up(cycle_secondary); }
277 void controls_cmd_headlight(int argc, char **argv)     { button_down(headlight); }
278
279
280
281 void controls_init(void)
282 {
283         cmd_addcommand("+strafe",      controls_cmd_strafe_on);
284         cmd_addcommand("-strafe",      controls_cmd_strafe_off);
285         cmd_addcommand("+bank",        controls_cmd_bank_on);
286         cmd_addcommand("-bank",        controls_cmd_bank_off);
287         cmd_addcommand("+attack",      controls_cmd_attack_on);
288         cmd_addcommand("-attack",      controls_cmd_attack_off);
289         cmd_addcommand("+attack2",     controls_cmd_attack2_on);
290         cmd_addcommand("-attack2",     controls_cmd_attack2_off);
291         cmd_addcommand("+rearview",    controls_cmd_rearview_on);
292         cmd_addcommand("-rearview",    controls_cmd_rearview_off);
293         cmd_addcommand("+automap",     controls_cmd_automap_on);
294         cmd_addcommand("-automap",     controls_cmd_automap_off);
295         cmd_addcommand("+afterburner", controls_cmd_afterburn_on);
296         cmd_addcommand("-afterburner", controls_cmd_afterburn_off);
297         cmd_addcommand("flare",        controls_cmd_flare);
298         cmd_addcommand("bomb",         controls_cmd_bomb);
299         cmd_addcommand("cycle",        controls_cmd_cycle);
300         cmd_addcommand("cycle2",       controls_cmd_cycle2);
301         cmd_addcommand("headlight",    controls_cmd_headlight);
302 }
303
304
305 /* Preserves pitch, heading, and states */
306 void controls_reset(void)
307 {
308         Controls.forward_thrust_time = 0;
309         Controls.sideways_thrust_time = 0;
310         Controls.vertical_thrust_time = 0;
311         Controls.bank_time = 0;
312         memset(Controls.count, 0, CONTROL_NUM_BUTTONS);
313 }
314
315
316 void controls_read_all()
317 {
318         int i;
319         int slide_on, bank_on;
320         int dx, dy, dz;
321         fix ctime;
322         int raw_joy_axis[JOY_MAX_AXES];
323         fix kp, kh;
324         ubyte channel_masks;
325         fix analog_control[7]; // indexed on control_analog
326
327         memset(analog_control, 0, sizeof(analog_control));
328
329         controls_reset();
330
331         cmd_queue_process();
332
333         slide_on = 0;
334         bank_on = 0;
335
336         ctime = timer_get_fixed_seconds();
337
338         //---------  Read Joystick -----------
339         if ( (LastReadTime + JOYSTICK_READ_TIME > ctime) ) {
340 #ifndef __MSDOS__
341                 if ((ctime < 0) && (LastReadTime >= 0))
342 #else
343                         if ((ctime < 0) && (LastReadTime > 0))
344 #endif
345                                 LastReadTime = ctime;
346         } else if (Config_control_joystick.intval) {
347                 LastReadTime = ctime;
348                 channel_masks = joystick_read_raw_axis( JOY_ALL_AXIS, raw_joy_axis );
349
350                 Assert(joy_num_axes <= 6); // don't have cvar mapping above 6 yet
351                 for (i = 0; i < joy_num_axes; i++) {
352 #ifndef SDL_INPUT
353                         if (channel_masks&(1<<i)) {
354 #endif
355                                 int joy_null_value = f2i(Config_joystick_deadzone[joy_advaxes[i].intval - 1].intval * 128);
356
357                                 raw_joy_axis[i] = joy_get_scaled_reading( raw_joy_axis[i], i );
358
359                                 if (raw_joy_axis[i] > joy_null_value)
360                                         raw_joy_axis[i] = ((raw_joy_axis[i] - joy_null_value) * 128) / (128 - joy_null_value);
361                                 else if (raw_joy_axis[i] < -joy_null_value)
362                                         raw_joy_axis[i] = ((raw_joy_axis[i] + joy_null_value) * 128) / (128 - joy_null_value);
363                                 else
364                                         raw_joy_axis[i] = 0;
365                                 joy_axis[i]     = (raw_joy_axis[i] * FrameTime) / 128;
366 #ifndef SDL_INPUT
367                         } else {
368                                 joy_axis[i] = 0;
369                         }
370 #endif
371                 }
372         } else {
373                 for (i = 0; i < joy_num_axes; i++)
374                         joy_axis[i] = 0;
375         }
376
377         if (Config_control_joystick.intval)
378                 for (i = 0; i < 6; i++)
379                         analog_control[joy_advaxes[i].intval] += joy_axis[i] * (joy_invert[i].intval ? -1 : 1) * Config_joystick_sensitivity[joy_advaxes[i].intval-1].value;
380
381         if (Config_control_mouse.intval) {
382                 //---------  Read Mouse -----------
383                 mouse_get_delta( &dx, &dy, &dz );
384
385                 analog_control[mouse_axes[0].intval] += dx * FrameTime / 35 * (mouse_invert[0].intval ? -1 : 1) * Config_mouse_sensitivity[mouse_axes[0].intval-1].value;
386                 analog_control[mouse_axes[1].intval] += dy * FrameTime / 25 * (mouse_invert[1].intval ? -1 : 1) * Config_mouse_sensitivity[mouse_axes[1].intval-1].value;
387                 analog_control[mouse_axes[2].intval] += dz * FrameTime      * (mouse_invert[2].intval ? -1 : 1) * Config_mouse_sensitivity[mouse_axes[2].intval-1].value;
388         }
389
390         //------------ Read pitch -----------
391         if ( !Controls.state[slide_on] ) {
392                 // mprintf((0, "pitch: %7.3f %7.3f: %7.3f\n", f2fl(k4), f2fl(k6), f2fl(Controls.heading_time)));
393                 kp = 0;
394
395                 kp += console_control_down_time(CONCNTL_LOOKDOWN) / (PH_SCALE * 2);
396                 kp -= console_control_down_time(CONCNTL_LOOKUP) / (PH_SCALE * 2);
397
398                 if (kp == 0)
399                         Controls.pitch_time = 0;
400                 else if (kp > 0) {
401                         if (Controls.pitch_time < 0)
402                                 Controls.pitch_time = 0;
403                 } else // kp < 0
404                         if (Controls.pitch_time > 0)
405                                 Controls.pitch_time = 0;
406                 Controls.pitch_time += kp;
407
408                 Controls.pitch_time -= analog_control[AXIS_PITCH];
409
410         } else
411                 Controls.pitch_time = 0;
412
413         if (!Player_is_dead) {
414
415                 //----------- Read vertical_thrust -----------------
416
417                 if ( Controls.state[slide_on] ) {
418                         Controls.vertical_thrust_time += console_control_down_time(CONCNTL_LOOKDOWN);
419                         Controls.vertical_thrust_time -= console_control_down_time(CONCNTL_LOOKUP);
420                         Controls.vertical_thrust_time += analog_control[AXIS_PITCH];
421                 }
422
423                 Controls.vertical_thrust_time += console_control_down_time(CONCNTL_MOVEUP);
424                 Controls.vertical_thrust_time -= console_control_down_time(CONCNTL_MOVEDOWN);
425                 Controls.vertical_thrust_time += analog_control[AXIS_UPDOWN];
426
427         }
428
429         //---------- Read heading -----------
430
431         if ( !Controls.state[slide_on] && !Controls.state[bank_on] ) {
432                 //mprintf((0, "heading: %7.3f %7.3f: %7.3f\n", f2fl(k4), f2fl(k6), f2fl(Controls.heading_time)));
433                 kh = 0;
434
435                 kh -= console_control_down_time(CONCNTL_LEFT) / PH_SCALE;
436                 kh += console_control_down_time(CONCNTL_RIGHT) / PH_SCALE;
437
438                 if (kh == 0)
439                         Controls.heading_time = 0;
440                 else if (kh > 0) {
441                         if (Controls.heading_time < 0)
442                                 Controls.heading_time = 0;
443                 } else // kh < 0
444                         if (Controls.heading_time > 0)
445                                 Controls.heading_time = 0;
446                 Controls.heading_time += kh;
447
448                 Controls.heading_time += analog_control[AXIS_TURN];
449
450         } else
451                 Controls.heading_time = 0;
452
453         if (!Player_is_dead) {
454
455                 //----------- Read sideways_thrust -----------------
456
457                 if ( slide_on ) {
458                         Controls.sideways_thrust_time -= console_control_down_time(CONCNTL_LEFT);
459                         Controls.sideways_thrust_time += console_control_down_time(CONCNTL_RIGHT);
460                         Controls.sideways_thrust_time += analog_control[AXIS_TURN];
461                 }
462
463                 Controls.sideways_thrust_time -= console_control_down_time(CONCNTL_MOVELEFT);
464                 Controls.sideways_thrust_time += console_control_down_time(CONCNTL_MOVERIGHT);
465                 Controls.sideways_thrust_time += analog_control[AXIS_LEFTRIGHT];
466
467         }
468
469         //----------- Read bank -----------------
470
471         if ( Controls.state[bank_on] ) {
472                 Controls.bank_time += console_control_down_time(CONCNTL_LEFT);
473                 Controls.bank_time -= console_control_down_time(CONCNTL_RIGHT);
474                 Controls.bank_time -= analog_control[AXIS_TURN];
475         }
476
477         Controls.bank_time += console_control_down_time(CONCNTL_BANKLEFT);
478         Controls.bank_time -= console_control_down_time(CONCNTL_BANKRIGHT);
479         Controls.bank_time -= analog_control[AXIS_BANK];
480
481         // the following "if" added by WraithX, 4/14/00
482         // done so that dead players can't move
483         if (!Player_is_dead) {
484
485                 //----------- Read forward_thrust -------------
486
487                 Controls.forward_thrust_time += console_control_down_time(CONCNTL_FORWARD);
488                 Controls.forward_thrust_time -= console_control_down_time(CONCNTL_BACK);
489                 Controls.forward_thrust_time -= analog_control[AXIS_THROTTLE];
490
491                 //---------Read Energy->Shield key----------
492
493                 if ((Players[Player_num].flags & PLAYER_FLAGS_CONVERTER) && console_control_state(CONCNTL_NRGSHIELD))
494                         transfer_energy_to_shield(console_control_down_time(CONCNTL_NRGSHIELD));
495
496         }
497
498         //----------- Read stupid-cruise-control-type of throttle.
499
500         Cruise_speed += console_control_down_time(CONCNTL_CRUISEUP);
501         Cruise_speed -= console_control_down_time(CONCNTL_CRUISEDOWN);
502
503         if (console_control_down_count(CONCNTL_CRUISEOFF))
504                 Cruise_speed = 0;
505
506         if (Cruise_speed > i2f(100))
507                 Cruise_speed = i2f(100);
508         if (Cruise_speed < 0)
509                 Cruise_speed = 0;
510
511         if (Controls.forward_thrust_time == 0)
512                 Controls.forward_thrust_time = fixmul(Cruise_speed,FrameTime) / 100;
513
514 #if 0
515         read_head_tracker();
516 #endif
517
518         //----------- Clamp values between -FrameTime and FrameTime
519         if (FrameTime > F1_0 )
520                 mprintf( (1, "Bogus frame time of %.2f seconds\n", f2fl(FrameTime) ));
521
522         if (Controls.pitch_time         > FrameTime/2 ) Controls.pitch_time         = FrameTime/2;
523         if (Controls.vertical_thrust_time > FrameTime ) Controls.vertical_thrust_time = FrameTime;
524         if (Controls.heading_time         > FrameTime ) Controls.heading_time         = FrameTime;
525         if (Controls.sideways_thrust_time > FrameTime ) Controls.sideways_thrust_time = FrameTime;
526         if (Controls.bank_time            > FrameTime ) Controls.bank_time            = FrameTime;
527         if (Controls.forward_thrust_time  > FrameTime ) Controls.forward_thrust_time  = FrameTime;
528         //if (Controls.afterburner_time   > FrameTime ) Controls.afterburner_time     = FrameTime;
529
530         if (Controls.pitch_time         < -FrameTime/2 ) Controls.pitch_time         = -FrameTime/2;
531         if (Controls.vertical_thrust_time < -FrameTime ) Controls.vertical_thrust_time = -FrameTime;
532         if (Controls.heading_time         < -FrameTime ) Controls.heading_time         = -FrameTime;
533         if (Controls.sideways_thrust_time < -FrameTime ) Controls.sideways_thrust_time = -FrameTime;
534         if (Controls.bank_time            < -FrameTime ) Controls.bank_time            = -FrameTime;
535         if (Controls.forward_thrust_time  < -FrameTime ) Controls.forward_thrust_time  = -FrameTime;
536         //if (Controls.afterburner_time   < -FrameTime ) Controls.afterburner_time     = -FrameTime;
537
538         //--------- Don't do anything if in debug mode
539 #ifndef RELEASE
540         if ( keyd_pressed[KEY_DELETE] ) {
541                 memset( &Controls, 0, sizeof(control_info) );
542         }
543 #endif
544 }