]> icculus.org git repositories - btb/d2x.git/blob - main/controls.c
finish refactoring Controls
[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 // Returns the number of seconds this 'button' has been down since last call.
260 static inline fix button_down_time(control_button button)
261 {
262         fix time_down, time;
263
264         if (!Controls.state[button]) {
265                 time_down = Controls.time_held_down[button];
266                 Controls.time_held_down[button] = 0;
267         } else {
268                 time = timer_get_fixed_seconds();
269                 time_down = time - Controls.time_went_down[button];
270                 Controls.time_went_down[button] = time;
271         }
272
273         return time_down;
274 }
275
276
277 void controls_cmd_lookdown_on(int argc, char **argv)   { button_down(pitch_forward); }
278 void controls_cmd_lookdown_off(int argc, char **argv)  { button_up(pitch_forward); }
279 void controls_cmd_lookup_on(int argc, char **argv)     { button_down(pitch_backward); }
280 void controls_cmd_lookup_off(int argc, char **argv)    { button_up(pitch_backward); }
281 void controls_cmd_left_on(int argc, char **argv)       { button_down(turn_left); }
282 void controls_cmd_left_off(int argc, char **argv)      { button_up(turn_left); }
283 void controls_cmd_right_on(int argc, char **argv)      { button_down(turn_right); }
284 void controls_cmd_right_off(int argc, char **argv)     { button_up(turn_right); }
285 void controls_cmd_strafe_on(int argc, char **argv)     { button_down(slide_on); }
286 void controls_cmd_strafe_off(int argc, char **argv)    { button_up(slide_on); }
287 void controls_cmd_moveleft_on(int argc, char **argv)   { button_down(slide_left); }
288 void controls_cmd_moveleft_off(int argc, char **argv)  { button_up(slide_left); }
289 void controls_cmd_moveright_on(int argc, char **argv)  { button_down(slide_right); }
290 void controls_cmd_moveright_off(int argc, char **argv) { button_up(slide_right); }
291 void controls_cmd_moveup_on(int argc, char **argv)     { button_down(slide_up); }
292 void controls_cmd_moveup_off(int argc, char **argv)    { button_up(slide_up); }
293 void controls_cmd_movedown_on(int argc, char **argv)   { button_down(slide_down); }
294 void controls_cmd_movedown_off(int argc, char **argv)  { button_up(slide_down); }
295 void controls_cmd_bank_on(int argc, char **argv)       { button_down(bank_on); }
296 void controls_cmd_bank_off(int argc, char **argv)      { button_up(bank_on); }
297 void controls_cmd_bankleft_on(int argc, char **argv)   { button_down(bank_left); }
298 void controls_cmd_bankleft_off(int argc, char **argv)  { button_up(bank_left); }
299 void controls_cmd_bankright_on(int argc, char **argv)  { button_down(bank_right); }
300 void controls_cmd_bankright_off(int argc, char **argv) { button_up(bank_right); }
301 void controls_cmd_forward_on(int argc, char **argv)    { button_down(accelerate); }
302 void controls_cmd_forward_off(int argc, char **argv)   { button_up(accelerate); }
303 void controls_cmd_back_on(int argc, char **argv)       { button_down(reverse); }
304 void controls_cmd_back_off(int argc, char **argv)      { button_up(reverse); }
305 void controls_cmd_cruiseup_on(int argc, char **argv)   { button_down(cruise_faster); }
306 void controls_cmd_cruiseup_off(int argc, char **argv)  { button_up(cruise_faster); }
307 void controls_cmd_cruisedown_on(int argc, char **argv) { button_down(cruise_slower); }
308 void controls_cmd_cruisedown_off(int argc, char **argv){ button_up(cruise_slower); }
309 void controls_cmd_cruiseoff_on(int argc, char **argv)  { button_down(cruise_off); }
310 void controls_cmd_cruiseoff_off(int argc, char **argv) { button_up(cruise_off); }
311 void controls_cmd_nrgshield_on(int argc, char **argv)  { button_down(energy_shield); }
312 void controls_cmd_nrgshield_off(int argc, char **argv) { button_up(energy_shield); }
313 void controls_cmd_attack_on(int argc, char **argv)     { button_down(fire_primary); }
314 void controls_cmd_attack_off(int argc, char **argv)    { button_up(fire_primary); }
315 void controls_cmd_attack2_on(int argc, char **argv)    { button_down(fire_secondary); }
316 void controls_cmd_attack2_off(int argc, char **argv)   { button_up(fire_secondary); }
317 void controls_cmd_rearview_on(int argc, char **argv)   { button_down(rear_view); }
318 void controls_cmd_rearview_off(int argc, char **argv)  { button_up(rear_view); }
319 void controls_cmd_automap_on(int argc, char **argv)    { button_down(automap); }
320 void controls_cmd_automap_off(int argc, char **argv)   { button_up(automap); }
321 void controls_cmd_afterburn_on(int argc, char **argv)  { button_down(afterburner); }
322 void controls_cmd_afterburn_off(int argc, char **argv) { button_up(afterburner); }
323 void controls_cmd_flare(int argc, char **argv)         { button_down(fire_flare); }
324 void controls_cmd_bomb(int argc, char **argv)          { button_up(drop_bomb); }
325 void controls_cmd_cycle(int argc, char **argv)         { button_down(cycle_primary); }
326 void controls_cmd_cycle2(int argc, char **argv)        { button_up(cycle_secondary); }
327 void controls_cmd_headlight(int argc, char **argv)     { button_down(headlight); }
328
329 void controls_cmd_togglebomb(int argc, char **argv)
330 {
331         weapon_toggle_bomb();
332 }
333
334 void controls_cmd_weapon(int argc, char **argv)
335 {
336         int n;
337
338         if (argc < 2 || !stricmp(argv[1], "-h")) {
339                 con_printf(CON_NORMAL, "%s <num>\n", argv[0]);
340                 con_printf(CON_NORMAL, "    select or toggle weapon <num>\n");
341                 return;
342         }
343
344         n = atoi(argv[1]);
345         if (n == 0)
346                 n = 10;
347         if (n < 1 || n > 10)
348                 return;
349
350         do_weapon_select((n-1) % 5, (n-1) / 5);
351 }
352
353
354 void controls_init(void)
355 {
356         cmd_addcommand("+lookdown",    controls_cmd_lookdown_on);
357         cmd_addcommand("-lookdown",    controls_cmd_lookdown_off);
358         cmd_addcommand("+lookup",      controls_cmd_lookup_on);
359         cmd_addcommand("-lookup",      controls_cmd_lookup_off);
360         cmd_addcommand("+left",        controls_cmd_left_on);
361         cmd_addcommand("-left",        controls_cmd_left_off);
362         cmd_addcommand("+right",       controls_cmd_right_on);
363         cmd_addcommand("-right",       controls_cmd_right_off);
364         cmd_addcommand("+strafe",      controls_cmd_strafe_on);
365         cmd_addcommand("-strafe",      controls_cmd_strafe_off);
366         cmd_addcommand("+moveleft",    controls_cmd_moveleft_on);
367         cmd_addcommand("-moveleft",    controls_cmd_moveleft_off);
368         cmd_addcommand("+moveright",   controls_cmd_moveright_on);
369         cmd_addcommand("-moveright",   controls_cmd_moveright_off);
370         cmd_addcommand("+moveup",      controls_cmd_moveup_on);
371         cmd_addcommand("-moveup",      controls_cmd_moveup_off);
372         cmd_addcommand("+movedown",    controls_cmd_movedown_on);
373         cmd_addcommand("-movedown",    controls_cmd_movedown_off);
374         cmd_addcommand("+bank",        controls_cmd_bank_on);
375         cmd_addcommand("-bank",        controls_cmd_bank_off);
376         cmd_addcommand("+bankleft",    controls_cmd_bankleft_on);
377         cmd_addcommand("-bankleft",    controls_cmd_bankleft_off);
378         cmd_addcommand("+bankright",   controls_cmd_bankright_on);
379         cmd_addcommand("-bankright",   controls_cmd_bankright_off);
380         cmd_addcommand("+forward",     controls_cmd_forward_on);
381         cmd_addcommand("-forward",     controls_cmd_forward_off);
382         cmd_addcommand("+back",        controls_cmd_back_on);
383         cmd_addcommand("-back",        controls_cmd_back_off);
384         cmd_addcommand("+cruiseup",    controls_cmd_cruiseup_on);
385         cmd_addcommand("-cruiseup",    controls_cmd_cruiseup_off);
386         cmd_addcommand("+cruisedown",  controls_cmd_cruisedown_on);
387         cmd_addcommand("-cruisedown",  controls_cmd_cruisedown_off);
388         cmd_addcommand("+cruiseoff",   controls_cmd_cruiseoff_on);
389         cmd_addcommand("-cruiseoff",   controls_cmd_cruiseoff_off);
390         cmd_addcommand("+nrgshield",   controls_cmd_nrgshield_on);
391         cmd_addcommand("-nrgshield",   controls_cmd_nrgshield_off);
392         cmd_addcommand("+rearview",    controls_cmd_rearview_on);
393         cmd_addcommand("-rearview",    controls_cmd_rearview_off);
394         cmd_addcommand("+attack",      controls_cmd_attack_on);
395         cmd_addcommand("-attack",      controls_cmd_attack_off);
396         cmd_addcommand("+attack2",     controls_cmd_attack2_on);
397         cmd_addcommand("-attack2",     controls_cmd_attack2_off);
398         cmd_addcommand("+automap",     controls_cmd_automap_on);
399         cmd_addcommand("-automap",     controls_cmd_automap_off);
400         cmd_addcommand("+afterburner", controls_cmd_afterburn_on);
401         cmd_addcommand("-afterburner", controls_cmd_afterburn_off);
402         cmd_addcommand("flare",        controls_cmd_flare);
403         cmd_addcommand("bomb",         controls_cmd_bomb);
404         cmd_addcommand("cycle",        controls_cmd_cycle);
405         cmd_addcommand("cycle2",       controls_cmd_cycle2);
406         cmd_addcommand("headlight",    controls_cmd_headlight);
407         cmd_addcommand("togglebomb",   controls_cmd_togglebomb);
408         cmd_addcommand("weapon",       controls_cmd_weapon);
409 }
410
411
412 /* Preserves pitch, heading, and states */
413 void controls_reset(void)
414 {
415         Controls.forward_thrust_time = 0;
416         Controls.sideways_thrust_time = 0;
417         Controls.vertical_thrust_time = 0;
418         Controls.bank_time = 0;
419         memset(Controls.count, 0, CONTROL_NUM_BUTTONS);
420 }
421
422
423 void controls_read_all()
424 {
425         int i;
426         int dx, dy, dz;
427         fix ctime;
428         int raw_joy_axis[JOY_MAX_AXES];
429         fix kp, kh;
430         ubyte channel_masks;
431         fix analog_control[7]; // indexed on control_analog
432
433         memset(analog_control, 0, sizeof(analog_control));
434
435         controls_reset();
436
437         cmd_queue_process();
438
439         ctime = timer_get_fixed_seconds();
440
441         //---------  Read Joystick -----------
442         if ( (LastReadTime + JOYSTICK_READ_TIME > ctime) ) {
443 #ifndef __MSDOS__
444                 if ((ctime < 0) && (LastReadTime >= 0))
445 #else
446                         if ((ctime < 0) && (LastReadTime > 0))
447 #endif
448                                 LastReadTime = ctime;
449         } else if (Config_control_joystick.intval) {
450                 LastReadTime = ctime;
451                 channel_masks = joystick_read_raw_axis( JOY_ALL_AXIS, raw_joy_axis );
452
453                 Assert(joy_num_axes <= 6); // don't have cvar mapping above 6 yet
454                 for (i = 0; i < joy_num_axes; i++) {
455 #ifndef SDL_INPUT
456                         if (channel_masks&(1<<i)) {
457 #endif
458                                 int joy_null_value = f2i(Config_joystick_deadzone[joy_advaxes[i].intval - 1].intval * 128);
459
460                                 raw_joy_axis[i] = joy_get_scaled_reading( raw_joy_axis[i], i );
461
462                                 if (raw_joy_axis[i] > joy_null_value)
463                                         raw_joy_axis[i] = ((raw_joy_axis[i] - joy_null_value) * 128) / (128 - joy_null_value);
464                                 else if (raw_joy_axis[i] < -joy_null_value)
465                                         raw_joy_axis[i] = ((raw_joy_axis[i] + joy_null_value) * 128) / (128 - joy_null_value);
466                                 else
467                                         raw_joy_axis[i] = 0;
468                                 joy_axis[i]     = (raw_joy_axis[i] * FrameTime) / 128;
469 #ifndef SDL_INPUT
470                         } else {
471                                 joy_axis[i] = 0;
472                         }
473 #endif
474                 }
475         } else {
476                 for (i = 0; i < joy_num_axes; i++)
477                         joy_axis[i] = 0;
478         }
479
480         if (Config_control_joystick.intval)
481                 for (i = 0; i < 6; i++)
482                         analog_control[joy_advaxes[i].intval] += joy_axis[i] * (joy_invert[i].intval ? -1 : 1) * Config_joystick_sensitivity[joy_advaxes[i].intval-1].value;
483
484         if (Config_control_mouse.intval) {
485                 //---------  Read Mouse -----------
486                 mouse_get_delta( &dx, &dy, &dz );
487
488                 analog_control[mouse_axes[0].intval] += dx * FrameTime / 35 * (mouse_invert[0].intval ? -1 : 1) * Config_mouse_sensitivity[mouse_axes[0].intval-1].value;
489                 analog_control[mouse_axes[1].intval] += dy * FrameTime / 25 * (mouse_invert[1].intval ? -1 : 1) * Config_mouse_sensitivity[mouse_axes[1].intval-1].value;
490                 analog_control[mouse_axes[2].intval] += dz * FrameTime      * (mouse_invert[2].intval ? -1 : 1) * Config_mouse_sensitivity[mouse_axes[2].intval-1].value;
491         }
492
493         //------------ Read pitch_time -----------
494         if ( !Controls.state[slide_on] ) {
495                 // mprintf((0, "pitch: %7.3f %7.3f: %7.3f\n", f2fl(k4), f2fl(k6), f2fl(Controls.heading_time)));
496                 kp = 0;
497
498                 kp += button_down_time(pitch_forward) / (PH_SCALE * 2);
499                 kp -= button_down_time(pitch_backward) / (PH_SCALE * 2);
500
501                 if (kp == 0)
502                         Controls.pitch_time = 0;
503                 else if (kp > 0) {
504                         if (Controls.pitch_time < 0)
505                                 Controls.pitch_time = 0;
506                 } else // kp < 0
507                         if (Controls.pitch_time > 0)
508                                 Controls.pitch_time = 0;
509                 Controls.pitch_time += kp;
510
511                 Controls.pitch_time -= analog_control[AXIS_PITCH];
512
513         } else
514                 Controls.pitch_time = 0;
515
516         if (!Player_is_dead) {
517
518                 //----------- Read vertical_thrust_time -----------------
519
520                 if ( Controls.state[slide_on] ) {
521                         Controls.vertical_thrust_time += button_down_time(pitch_forward);
522                         Controls.vertical_thrust_time -= button_down_time(pitch_backward);
523                         Controls.vertical_thrust_time += analog_control[AXIS_PITCH];
524                 }
525
526                 Controls.vertical_thrust_time += button_down_time(slide_up);
527                 Controls.vertical_thrust_time -= button_down_time(slide_down);
528                 Controls.vertical_thrust_time += analog_control[AXIS_UPDOWN];
529
530         }
531
532         //---------- Read heading_time -----------
533
534         if ( !Controls.state[slide_on] && !Controls.state[bank_on] ) {
535                 //mprintf((0, "heading: %7.3f %7.3f: %7.3f\n", f2fl(k4), f2fl(k6), f2fl(Controls.heading_time)));
536                 kh = 0;
537
538                 kh -= button_down_time(turn_left) / PH_SCALE;
539                 kh += button_down_time(turn_right) / PH_SCALE;
540
541                 if (kh == 0)
542                         Controls.heading_time = 0;
543                 else if (kh > 0) {
544                         if (Controls.heading_time < 0)
545                                 Controls.heading_time = 0;
546                 } else // kh < 0
547                         if (Controls.heading_time > 0)
548                                 Controls.heading_time = 0;
549                 Controls.heading_time += kh;
550
551                 Controls.heading_time += analog_control[AXIS_TURN];
552
553         } else
554                 Controls.heading_time = 0;
555
556         if (!Player_is_dead) {
557
558                 //----------- Read sideways_thrust_time -----------------
559
560                 if ( Controls.state[slide_on] ) {
561                         Controls.sideways_thrust_time -= button_down_time(turn_left);
562                         Controls.sideways_thrust_time += button_down_time(turn_right);
563                         Controls.sideways_thrust_time += analog_control[AXIS_TURN];
564                 }
565
566                 Controls.sideways_thrust_time -= button_down_time(slide_left);
567                 Controls.sideways_thrust_time += button_down_time(slide_right);
568                 Controls.sideways_thrust_time += analog_control[AXIS_LEFTRIGHT];
569
570         }
571
572         //----------- Read bank_time -----------------
573
574         if ( Controls.state[bank_on] ) {
575                 Controls.bank_time += button_down_time(turn_left);
576                 Controls.bank_time -= button_down_time(turn_right);
577                 Controls.bank_time -= analog_control[AXIS_TURN];
578         }
579
580         Controls.bank_time += button_down_time(bank_left);
581         Controls.bank_time -= button_down_time(bank_right);
582         Controls.bank_time -= analog_control[AXIS_BANK];
583
584         // the following "if" added by WraithX, 4/14/00
585         // done so that dead players can't move
586         if (!Player_is_dead) {
587
588                 //----------- Read forward_thrust_time -------------
589
590                 Controls.forward_thrust_time += button_down_time(accelerate);
591                 Controls.forward_thrust_time -= button_down_time(reverse);
592                 Controls.forward_thrust_time -= analog_control[AXIS_THROTTLE];
593
594                 //---------Read Energy->Shield key----------
595
596                 if ((Players[Player_num].flags & PLAYER_FLAGS_CONVERTER) && Controls.state[energy_shield])
597                         transfer_energy_to_shield(button_down_time(energy_shield));
598
599         }
600
601         //----------- Read stupid-cruise-control-type of throttle.
602
603         Cruise_speed += button_down_time(cruise_faster);
604         Cruise_speed -= button_down_time(cruise_slower);
605
606         if (Controls.count[cruise_off])
607                 Cruise_speed = 0;
608
609         if (Cruise_speed > i2f(100))
610                 Cruise_speed = i2f(100);
611         if (Cruise_speed < 0)
612                 Cruise_speed = 0;
613
614         if (Controls.forward_thrust_time == 0)
615                 Controls.forward_thrust_time = fixmul(Cruise_speed,FrameTime) / 100;
616
617 #if 0
618         read_head_tracker();
619 #endif
620
621         //----------- Clamp values between -FrameTime and FrameTime
622         if (FrameTime > F1_0 )
623                 mprintf( (1, "Bogus frame time of %.2f seconds\n", f2fl(FrameTime) ));
624
625         if (Controls.pitch_time         > FrameTime/2 ) Controls.pitch_time         = FrameTime/2;
626         if (Controls.vertical_thrust_time > FrameTime ) Controls.vertical_thrust_time = FrameTime;
627         if (Controls.heading_time         > FrameTime ) Controls.heading_time         = FrameTime;
628         if (Controls.sideways_thrust_time > FrameTime ) Controls.sideways_thrust_time = FrameTime;
629         if (Controls.bank_time            > FrameTime ) Controls.bank_time            = FrameTime;
630         if (Controls.forward_thrust_time  > FrameTime ) Controls.forward_thrust_time  = FrameTime;
631         //if (Controls.afterburner_time   > FrameTime ) Controls.afterburner_time     = FrameTime;
632
633         if (Controls.pitch_time         < -FrameTime/2 ) Controls.pitch_time         = -FrameTime/2;
634         if (Controls.vertical_thrust_time < -FrameTime ) Controls.vertical_thrust_time = -FrameTime;
635         if (Controls.heading_time         < -FrameTime ) Controls.heading_time         = -FrameTime;
636         if (Controls.sideways_thrust_time < -FrameTime ) Controls.sideways_thrust_time = -FrameTime;
637         if (Controls.bank_time            < -FrameTime ) Controls.bank_time            = -FrameTime;
638         if (Controls.forward_thrust_time  < -FrameTime ) Controls.forward_thrust_time  = -FrameTime;
639         //if (Controls.afterburner_time   < -FrameTime ) Controls.afterburner_time     = -FrameTime;
640
641         //--------- Don't do anything if in debug mode
642 #ifndef RELEASE
643         if ( keyd_pressed[KEY_DELETE] ) {
644                 memset( &Controls, 0, sizeof(control_info) );
645         }
646 #endif
647 }