]> icculus.org git repositories - btb/d2x.git/blob - main/controls.c
use the orientation parameter of g3_draw_bitmap
[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 "mono.h"
28 #include "key.h"
29 #include "joy.h"
30 #include "timer.h"
31 #include "dxxerror.h"
32 #include "inferno.h"
33 #include "args.h"
34 #include "gr.h"
35 #include "mouse.h"
36
37
38 //look at keyboard, mouse, joystick, CyberMan, whatever, and set 
39 //physics vars rotvel, velocity
40
41 fix Afterburner_charge=f1_0;
42
43 #define AFTERBURNER_USE_SECS    3                               //use up in 3 seconds
44 #define DROP_DELTA_TIME                 (f1_0/15)       //drop 3 per second
45
46 extern int Drop_afterburner_blob_flag;          //ugly hack
47
48 extern fix      Seismic_tremor_magnitude;
49
50 void read_flying_controls( object * obj )
51 {
52         fix     forward_thrust_time;
53
54         Assert(FrameTime > 0);          //Get MATT if hit this!
55
56 // this section commented and moved to the bottom by WraithX
57 //      if (Player_is_dead) {
58 //              vm_vec_zero(&obj->mtype.phys_info.rotthrust);
59 //              vm_vec_zero(&obj->mtype.phys_info.thrust);
60 //              return;
61 //      }
62 // end of section to be moved.
63
64         if ((obj->type!=OBJ_PLAYER) || (obj->id!=Player_num)) return;   //references to player_ship require that this obj be the player
65
66         if (Guided_missile[Player_num] && Guided_missile[Player_num]->signature==Guided_missile_sig[Player_num]) {
67                 vms_angvec rotangs;
68                 vms_matrix rotmat,tempm;
69                 fix speed;
70
71                 //this is a horrible hack.  guided missile stuff should not be
72                 //handled in the middle of a routine that is dealing with the player
73
74                 vm_vec_zero(&obj->mtype.phys_info.rotthrust);
75
76                 rotangs.p = Controls.pitch_time / 2 + Seismic_tremor_magnitude/64;
77                 rotangs.b = Controls.bank_time / 2 + Seismic_tremor_magnitude/16;
78                 rotangs.h = Controls.heading_time / 2 + Seismic_tremor_magnitude/64;
79
80                 vm_angles_2_matrix(&rotmat,&rotangs);
81
82                 vm_matrix_x_matrix(&tempm,&Guided_missile[Player_num]->orient,&rotmat);
83
84                 Guided_missile[Player_num]->orient = tempm;
85
86                 speed = Weapon_info[Guided_missile[Player_num]->id].speed[Difficulty_level];
87
88                 vm_vec_copy_scale(&Guided_missile[Player_num]->mtype.phys_info.velocity,&Guided_missile[Player_num]->orient.fvec,speed);
89 #ifdef NETWORK
90                 if (Game_mode & GM_MULTI)
91                         multi_send_guided_info (Guided_missile[Player_num],0);
92 #endif
93
94         }
95         else {
96                 obj->mtype.phys_info.rotthrust.x = Controls.pitch_time;
97                 obj->mtype.phys_info.rotthrust.y = Controls.heading_time;
98                 obj->mtype.phys_info.rotthrust.z = Controls.bank_time;
99         }
100
101 //      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) ));
102
103         forward_thrust_time = Controls.forward_thrust_time;
104
105         if (Players[Player_num].flags & PLAYER_FLAGS_AFTERBURNER)
106         {
107                 if (Controls.state[afterburner]) { // player has key down
108                         //if (forward_thrust_time >= 0) {               //..and isn't moving backward
109                         {
110                                 fix afterburner_scale;
111                                 int old_count,new_count;
112         
113                                 //add in value from 0..1
114                                 afterburner_scale = f1_0 + min(f1_0/2,Afterburner_charge) * 2;
115         
116                                 forward_thrust_time = fixmul(FrameTime,afterburner_scale);      //based on full thrust
117         
118                                 old_count = (Afterburner_charge / (DROP_DELTA_TIME/AFTERBURNER_USE_SECS));
119
120                                 Afterburner_charge -= FrameTime/AFTERBURNER_USE_SECS;
121
122                                 if (Afterburner_charge < 0)
123                                         Afterburner_charge = 0;
124
125                                 new_count = (Afterburner_charge / (DROP_DELTA_TIME/AFTERBURNER_USE_SECS));
126
127                                 if (old_count != new_count)
128                                         Drop_afterburner_blob_flag = 1; //drop blob (after physics called)
129                         }
130                 }
131                 else {
132                         fix cur_energy,charge_up;
133         
134                         //charge up to full
135                         charge_up = min(FrameTime/8,f1_0 - Afterburner_charge); //recharge over 8 seconds
136         
137                         cur_energy = max(Players[Player_num].energy-i2f(10),0); //don't drop below 10
138
139                         //maybe limit charge up by energy
140                         charge_up = min(charge_up,cur_energy/10);
141         
142                         Afterburner_charge += charge_up;
143         
144                         Players[Player_num].energy -= charge_up * 100 / 10;     //full charge uses 10% of energy
145                 }
146         }
147
148         // Set object's thrust vector for forward/backward
149         vm_vec_copy_scale(&obj->mtype.phys_info.thrust,&obj->orient.fvec, forward_thrust_time );
150         
151         // slide left/right
152         vm_vec_scale_add2(&obj->mtype.phys_info.thrust,&obj->orient.rvec, Controls.sideways_thrust_time );
153
154         // slide up/down
155         vm_vec_scale_add2(&obj->mtype.phys_info.thrust,&obj->orient.uvec, Controls.vertical_thrust_time );
156
157         if (obj->mtype.phys_info.flags & PF_WIGGLE)
158         {
159                 fix swiggle;
160                 fix_fastsincos(GameTime, &swiggle, NULL);
161                 if (FrameTime < F1_0) // Only scale wiggle if getting at least 1 FPS, to avoid causing the opposite problem.
162                         swiggle = fixmul(swiggle*20, FrameTime); //make wiggle fps-independent (based on pre-scaled amount of wiggle at 20 FPS)
163                 vm_vec_scale_add2(&obj->mtype.phys_info.velocity,&obj->orient.uvec,fixmul(swiggle,Player_ship->wiggle));
164         }
165
166         // As of now, obj->mtype.phys_info.thrust & obj->mtype.phys_info.rotthrust are 
167         // in units of time... In other words, if thrust==FrameTime, that
168         // means that the user was holding down the Max_thrust key for the
169         // whole frame.  So we just scale them up by the max, and divide by
170         // FrameTime to make them independant of framerate
171
172         //      Prevent divide overflows on high frame rates.
173         //      In a signed divide, you get an overflow if num >= div<<15
174         {
175                 fix     ft = FrameTime;
176
177                 //      Note, you must check for ft < F1_0/2, else you can get an overflow  on the << 15.
178                 if ((ft < F1_0/2) && (ft << 15 <= Player_ship->max_thrust)) {
179                         mprintf((0, "Preventing divide overflow in controls.c for Max_thrust!\n"));
180                         ft = (Player_ship->max_thrust >> 15) + 1;
181                 }
182
183                 vm_vec_scale( &obj->mtype.phys_info.thrust, fixdiv(Player_ship->max_thrust,ft) );
184
185                 if ((ft < F1_0/2) && (ft << 15 <= Player_ship->max_rotthrust)) {
186                         mprintf((0, "Preventing divide overflow in controls.c for max_rotthrust!\n"));
187                         ft = (Player_ship->max_thrust >> 15) + 1;
188                 }
189
190                 vm_vec_scale( &obj->mtype.phys_info.rotthrust, fixdiv(Player_ship->max_rotthrust,ft) );
191         }
192
193         // moved here by WraithX
194         if (Player_is_dead)
195         {
196                 //vm_vec_zero(&obj->mtype.phys_info.rotthrust); // let dead players rotate, changed by WraithX
197                 vm_vec_zero(&obj->mtype.phys_info.thrust);  // don't let dead players move, changed by WraithX
198                 return;
199         }// end if
200
201 }
202
203
204 extern void transfer_energy_to_shield(fix);
205
206 control_info Controls;
207
208 fix Cruise_speed = 0;
209
210 #define PH_SCALE 8
211
212 #ifndef __MSDOS__
213 #define JOYSTICK_READ_TIME (F1_0 / 40) // Read joystick at 40 Hz.
214 #else
215 #define JOYSTICK_READ_TIME (F1_0 / 10) // Read joystick at 10 Hz.
216 #endif
217
218 fix     LastReadTime = 0;
219
220 fix     joy_axis[JOY_MAX_AXES];
221
222
223 void reset_cruise(void)
224 {
225         Cruise_speed = 0;
226 }
227
228
229 static inline void button_down(control_button button)
230 {
231         Controls.count[button]++;
232         Controls.state[button] = 1;
233         Controls.time_went_down[button] = timer_get_fixed_seconds();
234 }
235
236
237 static inline void button_up(control_button button)
238 {
239         Controls.state[button] = 0;
240         Controls.time_held_down[button] += timer_get_fixed_seconds() - Controls.time_went_down[button];
241 }
242
243
244 // Returns the number of seconds this 'button' has been down since last call.
245 static inline fix button_down_time(control_button button)
246 {
247         fix time_down, time;
248
249         if (!Controls.state[button]) {
250                 time_down = Controls.time_held_down[button];
251                 Controls.time_held_down[button] = 0;
252         } else {
253                 time = timer_get_fixed_seconds();
254                 time_down = time - Controls.time_went_down[button];
255                 Controls.time_went_down[button] = time;
256         }
257
258         return time_down;
259 }
260
261
262 void controls_cmd_lookdown_on(int argc, char **argv)   { button_down(pitch_forward); }
263 void controls_cmd_lookdown_off(int argc, char **argv)  { button_up(pitch_forward); }
264 void controls_cmd_lookup_on(int argc, char **argv)     { button_down(pitch_backward); }
265 void controls_cmd_lookup_off(int argc, char **argv)    { button_up(pitch_backward); }
266 void controls_cmd_left_on(int argc, char **argv)       { button_down(turn_left); }
267 void controls_cmd_left_off(int argc, char **argv)      { button_up(turn_left); }
268 void controls_cmd_right_on(int argc, char **argv)      { button_down(turn_right); }
269 void controls_cmd_right_off(int argc, char **argv)     { button_up(turn_right); }
270 void controls_cmd_strafe_on(int argc, char **argv)     { button_down(slide_on); }
271 void controls_cmd_strafe_off(int argc, char **argv)    { button_up(slide_on); }
272 void controls_cmd_moveleft_on(int argc, char **argv)   { button_down(slide_left); }
273 void controls_cmd_moveleft_off(int argc, char **argv)  { button_up(slide_left); }
274 void controls_cmd_moveright_on(int argc, char **argv)  { button_down(slide_right); }
275 void controls_cmd_moveright_off(int argc, char **argv) { button_up(slide_right); }
276 void controls_cmd_moveup_on(int argc, char **argv)     { button_down(slide_up); }
277 void controls_cmd_moveup_off(int argc, char **argv)    { button_up(slide_up); }
278 void controls_cmd_movedown_on(int argc, char **argv)   { button_down(slide_down); }
279 void controls_cmd_movedown_off(int argc, char **argv)  { button_up(slide_down); }
280 void controls_cmd_bank_on(int argc, char **argv)       { button_down(bank_on); }
281 void controls_cmd_bank_off(int argc, char **argv)      { button_up(bank_on); }
282 void controls_cmd_bankleft_on(int argc, char **argv)   { button_down(bank_left); }
283 void controls_cmd_bankleft_off(int argc, char **argv)  { button_up(bank_left); }
284 void controls_cmd_bankright_on(int argc, char **argv)  { button_down(bank_right); }
285 void controls_cmd_bankright_off(int argc, char **argv) { button_up(bank_right); }
286 void controls_cmd_forward_on(int argc, char **argv)    { button_down(accelerate); }
287 void controls_cmd_forward_off(int argc, char **argv)   { button_up(accelerate); }
288 void controls_cmd_back_on(int argc, char **argv)       { button_down(reverse); }
289 void controls_cmd_back_off(int argc, char **argv)      { button_up(reverse); }
290 void controls_cmd_cruiseup_on(int argc, char **argv)   { button_down(cruise_faster); }
291 void controls_cmd_cruiseup_off(int argc, char **argv)  { button_up(cruise_faster); }
292 void controls_cmd_cruisedown_on(int argc, char **argv) { button_down(cruise_slower); }
293 void controls_cmd_cruisedown_off(int argc, char **argv){ button_up(cruise_slower); }
294 void controls_cmd_cruiseoff_on(int argc, char **argv)  { button_down(cruise_off); }
295 void controls_cmd_cruiseoff_off(int argc, char **argv) { button_up(cruise_off); }
296 void controls_cmd_nrgshield_on(int argc, char **argv)  { button_down(energy_shield); }
297 void controls_cmd_nrgshield_off(int argc, char **argv) { button_up(energy_shield); }
298 void controls_cmd_attack_on(int argc, char **argv)     { button_down(fire_primary); }
299 void controls_cmd_attack_off(int argc, char **argv)    { button_up(fire_primary); }
300 void controls_cmd_attack2_on(int argc, char **argv)    { button_down(fire_secondary); }
301 void controls_cmd_attack2_off(int argc, char **argv)   { button_up(fire_secondary); }
302 void controls_cmd_rearview_on(int argc, char **argv)   { button_down(rear_view); }
303 void controls_cmd_rearview_off(int argc, char **argv)  { button_up(rear_view); }
304 void controls_cmd_automap_on(int argc, char **argv)    { button_down(automap); }
305 void controls_cmd_automap_off(int argc, char **argv)   { button_up(automap); }
306 void controls_cmd_afterburn_on(int argc, char **argv)  { button_down(afterburner); }
307 void controls_cmd_afterburn_off(int argc, char **argv) { button_up(afterburner); }
308
309 void controls_cmd_flare(int argc, char **argv)         { button_down(fire_flare); }
310 void controls_cmd_bomb(int argc, char **argv)          { button_down(drop_bomb); }
311 void controls_cmd_cycle(int argc, char **argv)         { button_down(cycle_primary); }
312 void controls_cmd_cycle2(int argc, char **argv)        { button_down(cycle_secondary); }
313 void controls_cmd_headlight(int argc, char **argv)     { button_down(headlight); }
314
315 void controls_cmd_togglebomb(int argc, char **argv)
316 {
317         weapon_toggle_bomb();
318 }
319
320 void controls_cmd_weapon(int argc, char **argv)
321 {
322         int n;
323
324         if (argc < 2 || !stricmp(argv[1], "-h")) {
325                 con_printf(CON_NORMAL, "%s <num>\n", argv[0]);
326                 con_printf(CON_NORMAL, "    select or toggle weapon <num>\n");
327                 return;
328         }
329
330         n = atoi(argv[1]);
331         if (n == 0)
332                 n = 10;
333         if (n < 1 || n > 10)
334                 return;
335
336         do_weapon_select((n-1) % 5, (n-1) / 5);
337 }
338
339
340 void controls_init(void)
341 {
342         cmd_addcommand("+lookdown",    controls_cmd_lookdown_on, NULL);
343         cmd_addcommand("-lookdown",    controls_cmd_lookdown_off, NULL);
344         cmd_addcommand("+lookup",      controls_cmd_lookup_on, NULL);
345         cmd_addcommand("-lookup",      controls_cmd_lookup_off, NULL);
346         cmd_addcommand("+left",        controls_cmd_left_on, NULL);
347         cmd_addcommand("-left",        controls_cmd_left_off, NULL);
348         cmd_addcommand("+right",       controls_cmd_right_on, NULL);
349         cmd_addcommand("-right",       controls_cmd_right_off, NULL);
350         cmd_addcommand("+strafe",      controls_cmd_strafe_on, NULL);
351         cmd_addcommand("-strafe",      controls_cmd_strafe_off, NULL);
352         cmd_addcommand("+moveleft",    controls_cmd_moveleft_on, NULL);
353         cmd_addcommand("-moveleft",    controls_cmd_moveleft_off, NULL);
354         cmd_addcommand("+moveright",   controls_cmd_moveright_on, NULL);
355         cmd_addcommand("-moveright",   controls_cmd_moveright_off, NULL);
356         cmd_addcommand("+moveup",      controls_cmd_moveup_on, NULL);
357         cmd_addcommand("-moveup",      controls_cmd_moveup_off, NULL);
358         cmd_addcommand("+movedown",    controls_cmd_movedown_on, NULL);
359         cmd_addcommand("-movedown",    controls_cmd_movedown_off, NULL);
360         cmd_addcommand("+bank",        controls_cmd_bank_on, NULL);
361         cmd_addcommand("-bank",        controls_cmd_bank_off, NULL);
362         cmd_addcommand("+bankleft",    controls_cmd_bankleft_on, NULL);
363         cmd_addcommand("-bankleft",    controls_cmd_bankleft_off, NULL);
364         cmd_addcommand("+bankright",   controls_cmd_bankright_on, NULL);
365         cmd_addcommand("-bankright",   controls_cmd_bankright_off, NULL);
366         cmd_addcommand("+forward",     controls_cmd_forward_on, NULL);
367         cmd_addcommand("-forward",     controls_cmd_forward_off, NULL);
368         cmd_addcommand("+back",        controls_cmd_back_on, NULL);
369         cmd_addcommand("-back",        controls_cmd_back_off, NULL);
370         cmd_addcommand("+cruiseup",    controls_cmd_cruiseup_on, NULL);
371         cmd_addcommand("-cruiseup",    controls_cmd_cruiseup_off, NULL);
372         cmd_addcommand("+cruisedown",  controls_cmd_cruisedown_on, NULL);
373         cmd_addcommand("-cruisedown",  controls_cmd_cruisedown_off, NULL);
374         cmd_addcommand("+cruiseoff",   controls_cmd_cruiseoff_on, NULL);
375         cmd_addcommand("-cruiseoff",   controls_cmd_cruiseoff_off, NULL);
376         cmd_addcommand("+nrgshield",   controls_cmd_nrgshield_on, NULL);
377         cmd_addcommand("-nrgshield",   controls_cmd_nrgshield_off, NULL);
378         cmd_addcommand("+rearview",    controls_cmd_rearview_on, NULL);
379         cmd_addcommand("-rearview",    controls_cmd_rearview_off, NULL);
380         cmd_addcommand("+attack",      controls_cmd_attack_on, NULL);
381         cmd_addcommand("-attack",      controls_cmd_attack_off, NULL);
382         cmd_addcommand("+attack2",     controls_cmd_attack2_on, NULL);
383         cmd_addcommand("-attack2",     controls_cmd_attack2_off, NULL);
384         cmd_addcommand("+automap",     controls_cmd_automap_on, NULL);
385         cmd_addcommand("-automap",     controls_cmd_automap_off, NULL);
386         cmd_addcommand("+afterburner", controls_cmd_afterburn_on, NULL);
387         cmd_addcommand("-afterburner", controls_cmd_afterburn_off, NULL);
388         cmd_addcommand("flare",        controls_cmd_flare, NULL);
389         cmd_addcommand("bomb",         controls_cmd_bomb, NULL);
390         cmd_addcommand("cycle",        controls_cmd_cycle, NULL);
391         cmd_addcommand("cycle2",       controls_cmd_cycle2, NULL);
392         cmd_addcommand("headlight",    controls_cmd_headlight, NULL);
393         cmd_addcommand("togglebomb",   controls_cmd_togglebomb, NULL);
394         cmd_addcommand("weapon",       controls_cmd_weapon, NULL);
395 }
396
397
398 /* Preserves pitch, heading, and states */
399 void controls_reset(void)
400 {
401         Controls.forward_thrust_time = 0;
402         Controls.sideways_thrust_time = 0;
403         Controls.vertical_thrust_time = 0;
404         Controls.bank_time = 0;
405         memset(Controls.count, 0, CONTROL_NUM_BUTTONS);
406 }
407
408
409 void controls_read_all()
410 {
411         int i;
412         int dx, dy, dz;
413         fix ctime;
414         int raw_joy_axis[JOY_MAX_AXES];
415         fix kp, kh;
416         fix temp;
417         ubyte channel_masks;
418         fix analog_control[7]; // indexed on control_analog
419
420         memset(analog_control, 0, sizeof(analog_control));
421
422         controls_reset();
423
424         cmd_queue_process();
425
426         ctime = timer_get_fixed_seconds();
427
428         //---------  Read Joystick -----------
429         if ( (LastReadTime + JOYSTICK_READ_TIME > ctime) ) {
430 #ifndef __MSDOS__
431                 if ((ctime < 0) && (LastReadTime >= 0))
432 #else
433                         if ((ctime < 0) && (LastReadTime > 0))
434 #endif
435                                 LastReadTime = ctime;
436         } else if (Config_control_joystick.intval) {
437                 LastReadTime = ctime;
438                 channel_masks = joystick_read_raw_axis( JOY_ALL_AXIS, raw_joy_axis );
439
440                 Assert(joy_num_axes <= 6); // don't have cvar mapping above 6 yet
441                 for (i = 0; i < joy_num_axes; i++) {
442 #ifndef SDL_INPUT
443                         if (channel_masks&(1<<i)) {
444 #endif
445                                 int joy_null_value = f2i(Config_joystick_deadzone[joy_advaxes[i].intval - 1].intval * 128);
446
447                                 raw_joy_axis[i] = joy_get_scaled_reading( raw_joy_axis[i], i );
448
449                                 if (raw_joy_axis[i] > joy_null_value)
450                                         raw_joy_axis[i] = ((raw_joy_axis[i] - joy_null_value) * 128) / (128 - joy_null_value);
451                                 else if (raw_joy_axis[i] < -joy_null_value)
452                                         raw_joy_axis[i] = ((raw_joy_axis[i] + joy_null_value) * 128) / (128 - joy_null_value);
453                                 else
454                                         raw_joy_axis[i] = 0;
455                                 joy_axis[i]     = (raw_joy_axis[i] * FrameTime) / 128;
456 #ifndef SDL_INPUT
457                         } else {
458                                 joy_axis[i] = 0;
459                         }
460 #endif
461                 }
462         } else {
463                 for (i = 0; i < joy_num_axes; i++)
464                         joy_axis[i] = 0;
465         }
466
467         if (Config_control_joystick.intval)
468                 for (i = 0; i < 6; i++)
469                 {
470                         temp = fixmul(joy_axis[i], Config_joystick_sensitivity[joy_advaxes[i].intval-1].fixval);
471                         if (joy_invert[i].intval)
472                                 analog_control[joy_advaxes[i].intval] -= temp;
473                         else
474                                 analog_control[joy_advaxes[i].intval] += temp;
475                 }
476
477         if (Config_control_mouse.intval) {
478                 //---------  Read Mouse -----------
479                 mouse_get_delta( &dx, &dy, &dz );
480
481                 temp = fixmul(dx * FrameTime / 35, Config_mouse_sensitivity[mouse_axes[0].intval-1].fixval);
482                 if (mouse_invert[0].intval)
483                         analog_control[mouse_axes[0].intval] -= temp;
484                 else
485                         analog_control[mouse_axes[0].intval] += temp;
486                 temp = fixmul(dy * FrameTime / 25, Config_mouse_sensitivity[mouse_axes[1].intval-1].fixval);
487                 if (mouse_invert[1].intval)
488                         analog_control[mouse_axes[1].intval] -= temp;
489                 else
490                         analog_control[mouse_axes[1].intval] += temp;
491                 temp = fixmul(dz * FrameTime, Config_mouse_sensitivity[mouse_axes[2].intval-1].fixval);
492                 if (mouse_invert[2].intval)
493                         analog_control[mouse_axes[2].intval] -= temp;
494                 else
495                         analog_control[mouse_axes[2].intval] += temp;
496         }
497
498         //------------ Read pitch_time -----------
499         if ( !Controls.state[slide_on] ) {
500                 // mprintf((0, "pitch: %7.3f %7.3f: %7.3f\n", f2fl(k4), f2fl(k6), f2fl(Controls.heading_time)));
501                 kp = 0;
502
503                 kp += button_down_time(pitch_forward) / (PH_SCALE * 2);
504                 kp -= button_down_time(pitch_backward) / (PH_SCALE * 2);
505
506                 if (kp == 0)
507                         Controls.pitch_time = 0;
508                 else if (kp > 0) {
509                         if (Controls.pitch_time < 0)
510                                 Controls.pitch_time = 0;
511                 } else // kp < 0
512                         if (Controls.pitch_time > 0)
513                                 Controls.pitch_time = 0;
514                 Controls.pitch_time += kp;
515
516                 Controls.pitch_time -= analog_control[AXIS_PITCH];
517
518         } else
519                 Controls.pitch_time = 0;
520
521         if (!Player_is_dead) {
522
523                 //----------- Read vertical_thrust_time -----------------
524
525                 if ( Controls.state[slide_on] ) {
526                         Controls.vertical_thrust_time += button_down_time(pitch_forward);
527                         Controls.vertical_thrust_time -= button_down_time(pitch_backward);
528                         Controls.vertical_thrust_time += analog_control[AXIS_PITCH];
529                 }
530
531                 Controls.vertical_thrust_time += button_down_time(slide_up);
532                 Controls.vertical_thrust_time -= button_down_time(slide_down);
533                 Controls.vertical_thrust_time += analog_control[AXIS_UPDOWN];
534
535         }
536
537         //---------- Read heading_time -----------
538
539         if ( !Controls.state[slide_on] && !Controls.state[bank_on] ) {
540                 //mprintf((0, "heading: %7.3f %7.3f: %7.3f\n", f2fl(k4), f2fl(k6), f2fl(Controls.heading_time)));
541                 kh = 0;
542
543                 kh -= button_down_time(turn_left) / PH_SCALE;
544                 kh += button_down_time(turn_right) / PH_SCALE;
545
546                 if (kh == 0)
547                         Controls.heading_time = 0;
548                 else if (kh > 0) {
549                         if (Controls.heading_time < 0)
550                                 Controls.heading_time = 0;
551                 } else // kh < 0
552                         if (Controls.heading_time > 0)
553                                 Controls.heading_time = 0;
554                 Controls.heading_time += kh;
555
556                 Controls.heading_time += analog_control[AXIS_TURN];
557
558         } else
559                 Controls.heading_time = 0;
560
561         if (!Player_is_dead) {
562
563                 //----------- Read sideways_thrust_time -----------------
564
565                 if ( Controls.state[slide_on] ) {
566                         Controls.sideways_thrust_time -= button_down_time(turn_left);
567                         Controls.sideways_thrust_time += button_down_time(turn_right);
568                         Controls.sideways_thrust_time += analog_control[AXIS_TURN];
569                 }
570
571                 Controls.sideways_thrust_time -= button_down_time(slide_left);
572                 Controls.sideways_thrust_time += button_down_time(slide_right);
573                 Controls.sideways_thrust_time += analog_control[AXIS_LEFTRIGHT];
574
575         }
576
577         //----------- Read bank_time -----------------
578
579         if ( Controls.state[bank_on] ) {
580                 Controls.bank_time += button_down_time(turn_left);
581                 Controls.bank_time -= button_down_time(turn_right);
582                 Controls.bank_time -= analog_control[AXIS_TURN];
583         }
584
585         Controls.bank_time += button_down_time(bank_left);
586         Controls.bank_time -= button_down_time(bank_right);
587         Controls.bank_time -= analog_control[AXIS_BANK];
588
589         // the following "if" added by WraithX, 4/14/00
590         // done so that dead players can't move
591         if (!Player_is_dead) {
592
593                 //----------- Read forward_thrust_time -------------
594
595                 Controls.forward_thrust_time += button_down_time(accelerate);
596                 Controls.forward_thrust_time -= button_down_time(reverse);
597                 Controls.forward_thrust_time -= analog_control[AXIS_THROTTLE];
598
599                 //---------Read Energy->Shield key----------
600
601                 if ((Players[Player_num].flags & PLAYER_FLAGS_CONVERTER) && Controls.state[energy_shield])
602                         transfer_energy_to_shield(button_down_time(energy_shield));
603
604         }
605
606         //----------- Read stupid-cruise-control-type of throttle.
607
608         Cruise_speed += button_down_time(cruise_faster);
609         Cruise_speed -= button_down_time(cruise_slower);
610
611         if (Controls.count[cruise_off])
612                 Cruise_speed = 0;
613
614         if (Cruise_speed > i2f(100))
615                 Cruise_speed = i2f(100);
616         if (Cruise_speed < 0)
617                 Cruise_speed = 0;
618
619         if (Controls.forward_thrust_time == 0)
620                 Controls.forward_thrust_time = fixmul(Cruise_speed,FrameTime) / 100;
621
622 #if 0
623         read_head_tracker();
624 #endif
625
626         //----------- Clamp values between -FrameTime and FrameTime
627         if (FrameTime > F1_0 )
628                 mprintf( (1, "Bogus frame time of %.2f seconds\n", f2fl(FrameTime) ));
629
630         if (Controls.pitch_time         > FrameTime/2 ) Controls.pitch_time         = FrameTime/2;
631         if (Controls.vertical_thrust_time > FrameTime ) Controls.vertical_thrust_time = FrameTime;
632         if (Controls.heading_time         > FrameTime ) Controls.heading_time         = FrameTime;
633         if (Controls.sideways_thrust_time > FrameTime ) Controls.sideways_thrust_time = FrameTime;
634         if (Controls.bank_time            > FrameTime ) Controls.bank_time            = FrameTime;
635         if (Controls.forward_thrust_time  > FrameTime ) Controls.forward_thrust_time  = FrameTime;
636         //if (Controls.afterburner_time   > FrameTime ) Controls.afterburner_time     = FrameTime;
637
638         if (Controls.pitch_time         < -FrameTime/2 ) Controls.pitch_time         = -FrameTime/2;
639         if (Controls.vertical_thrust_time < -FrameTime ) Controls.vertical_thrust_time = -FrameTime;
640         if (Controls.heading_time         < -FrameTime ) Controls.heading_time         = -FrameTime;
641         if (Controls.sideways_thrust_time < -FrameTime ) Controls.sideways_thrust_time = -FrameTime;
642         if (Controls.bank_time            < -FrameTime ) Controls.bank_time            = -FrameTime;
643         if (Controls.forward_thrust_time  < -FrameTime ) Controls.forward_thrust_time  = -FrameTime;
644         //if (Controls.afterburner_time   < -FrameTime ) Controls.afterburner_time     = -FrameTime;
645
646         //--------- Don't do anything if in debug mode
647 #ifndef RELEASE
648         if ( keyd_pressed[KEY_DELETE] ) {
649                 memset( &Controls, 0, sizeof(control_info) );
650         }
651 #endif
652 }