1 /* $Id: controls.c,v 1.5 2003-08-02 20:36:12 btb Exp $ */
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
17 * Code for controlling player movement
20 * Revision 1.3 1995/11/20 17:17:27 allender
21 * call fix_fastsincos with tmp variable to prevent
24 * Revision 1.2 1995/08/11 16:00:04 allender
25 * fixed bug we think we never saw (overflow on max_rotthrust
27 * Revision 1.1 1995/05/16 15:23:53 allender
30 * Revision 2.0 1995/02/27 11:27:11 john
31 * New version 2.0, which has no anonymous unions, builds with
32 * Watcom 10.0, and doesn't require parsing BITMAPS.TBL.
34 * Revision 1.50 1995/02/22 14:11:19 allender
35 * remove anonymous unions from object structure
37 * Revision 1.49 1994/12/15 13:04:10 mike
38 * Replace Players[Player_num].time_total references with GameTime.
40 * Revision 1.48 1994/11/27 23:12:13 matt
41 * Made changes for new mprintf calling convention
43 * Revision 1.47 1994/11/25 22:15:54 matt
44 * Added asserts to try to trap frametime < 0 bug
46 * Revision 1.46 1994/11/16 11:25:40 matt
47 * Took out int3's since I determined that the errors are caused by neg frametime
49 * Revision 1.45 1994/11/15 13:07:23 matt
50 * Added int3's to try to trap bug
52 * Revision 1.44 1994/10/14 16:18:12 john
53 * Made Assert that the object was player just nicely exit
56 * Revision 1.43 1994/10/13 11:35:25 john
57 * Made Thrustmaster FCS Hat work. Put a background behind the
58 * keyboard configure. Took out turn_sensitivity. Changed sound/config
59 * menu to new menu. Made F6 be calibrate joystick.
61 * Revision 1.42 1994/09/29 11:22:02 mike
62 * Zero thrust when player dies.
64 * Revision 1.41 1994/09/16 13:10:30 mike
65 * Hook in afterburner stuff.
67 * Revision 1.40 1994/09/14 22:21:54 matt
68 * Avoid post-death assert
70 * Revision 1.39 1994/09/11 20:30:27 matt
71 * Cleaned up thrust vars, changing a few names
73 * Revision 1.38 1994/09/10 15:46:31 john
74 * First version of new keyboard configuration.
76 * Revision 1.37 1994/09/07 15:58:12 mike
77 * Check for player dead in controls so you can't fire or move after dead, logical, huh?
79 * Revision 1.36 1994/09/06 14:51:56 john
80 * Added sensitivity adjustment, fixed bug with joystick button not
83 * Revision 1.35 1994/09/01 15:43:26 john
84 * Put pitch bak like it was.
86 * Revision 1.34 1994/08/31 18:59:35 john
87 * Made rotthrust back like it was.
89 * Revision 1.33 1994/08/31 18:49:17 john
90 * Slowed Maxrothrust a bit,
93 * Revision 1.32 1994/08/31 18:32:05 john
94 * Lower max rotational thrust
96 * Revision 1.31 1994/08/29 21:18:27 john
97 * First version of new keyboard/oystick remapping stuff.
99 * Revision 1.30 1994/08/29 16:18:30 mike
100 * trap divide overflow.
102 * Revision 1.29 1994/08/26 14:40:45 john
103 * *** empty log message ***
105 * Revision 1.28 1994/08/26 12:23:50 john
106 * MAde joystick read up to 15 times per second max.
108 * Revision 1.27 1994/08/26 10:50:59 john
109 * Took out Controls_always_stopped.
111 * Revision 1.26 1994/08/26 10:47:27 john
112 * *** empty log message ***
114 * Revision 1.25 1994/08/26 10:46:50 john
115 * New version of controls.
117 * Revision 1.24 1994/08/25 19:41:44 john
118 * *** empty log message ***
120 * Revision 1.23 1994/08/25 18:44:55 john
121 * *** empty log message ***
123 * Revision 1.22 1994/08/25 18:43:46 john
124 * First revision of new control code.
126 * Revision 1.21 1994/08/24 20:02:46 john
127 * Added cyberman support; made keys work key_down_time
128 * returning seconds instead of milliseconds,.
131 * Revision 1.20 1994/08/24 19:00:27 john
132 * Changed key_down_time to return fixed seconds instead of
135 * Revision 1.19 1994/08/19 15:22:12 mike
136 * Fix divide overflow in sliding.
138 * Revision 1.18 1994/08/19 14:42:50 john
139 * Added joystick sensitivity.
141 * Revision 1.17 1994/08/17 16:50:01 john
142 * Added damaging fireballs, missiles.
144 * Revision 1.16 1994/08/12 22:41:54 john
145 * Took away Player_stats; added Players array.
147 * Revision 1.15 1994/08/09 16:03:56 john
148 * Added network players to editor.
150 * Revision 1.14 1994/07/28 12:33:31 matt
151 * Made sliding use thrust, rather than changing velocity directly
153 * Revision 1.13 1994/07/27 20:53:21 matt
154 * Added rotational drag & thrust, so turning now has momemtum like moving
156 * Revision 1.12 1994/07/25 10:24:06 john
159 * Revision 1.11 1994/07/22 17:53:16 john
160 * Added better victormax support
162 * Revision 1.10 1994/07/21 21:31:29 john
163 * First cheapo version of VictorMaxx tracking.
165 * Revision 1.9 1994/07/15 15:16:18 john
166 * Fixed some joystick stuff.
168 * Revision 1.8 1994/07/15 09:32:09 john
169 * Changes player movement.
171 * Revision 1.7 1994/07/13 00:14:58 matt
172 * Moved all (or nearly all) of the values that affect player movement to
175 * Revision 1.6 1994/07/12 12:40:14 matt
176 * Revamped physics system
178 * Revision 1.5 1994/07/02 13:50:39 matt
179 * Cleaned up includes
181 * Revision 1.4 1994/07/01 10:55:25 john
182 * Added analog joystick throttle
184 * Revision 1.3 1994/06/30 20:04:28 john
185 * Added -joydef support.
187 * Revision 1.2 1994/06/30 19:01:58 matt
188 * Moved flying controls code from physics.c to controls.c
190 * Revision 1.1 1994/06/30 18:41:25 matt
201 static char rcsid[] = "$Id: controls.c,v 1.5 2003-08-02 20:36:12 btb Exp $";
219 #include "controls.h"
231 #include "fireball.h"
233 //look at keyboard, mouse, joystick, CyberMan, whatever, and set
234 //physics vars rotvel, velocity
236 fix Afterburner_charge=f1_0;
238 #define AFTERBURNER_USE_SECS 3 //use up in 3 seconds
239 #define DROP_DELTA_TIME (f1_0/15) //drop 3 per second
241 extern int Drop_afterburner_blob_flag; //ugly hack
243 extern fix Seismic_tremor_magnitude;
245 void read_flying_controls( object * obj )
247 fix forward_thrust_time;
249 Assert(FrameTime > 0); //Get MATT if hit this!
251 if (Player_is_dead) {
252 vm_vec_zero(&obj->mtype.phys_info.rotthrust);
253 vm_vec_zero(&obj->mtype.phys_info.thrust);
257 if ((obj->type!=OBJ_PLAYER) || (obj->id!=Player_num)) return; //references to player_ship require that this obj be the player
259 if (Guided_missile[Player_num] && Guided_missile[Player_num]->signature==Guided_missile_sig[Player_num]) {
261 vms_matrix rotmat,tempm;
264 //this is a horrible hack. guided missile stuff should not be
265 //handled in the middle of a routine that is dealing with the player
267 vm_vec_zero(&obj->mtype.phys_info.rotthrust);
269 rotangs.p = Controls.pitch_time / 2 + Seismic_tremor_magnitude/64;
270 rotangs.b = Controls.bank_time / 2 + Seismic_tremor_magnitude/16;
271 rotangs.h = Controls.heading_time / 2 + Seismic_tremor_magnitude/64;
273 vm_angles_2_matrix(&rotmat,&rotangs);
275 vm_matrix_x_matrix(&tempm,&Guided_missile[Player_num]->orient,&rotmat);
277 Guided_missile[Player_num]->orient = tempm;
279 speed = Weapon_info[Guided_missile[Player_num]->id].speed[Difficulty_level];
281 vm_vec_copy_scale(&Guided_missile[Player_num]->mtype.phys_info.velocity,&Guided_missile[Player_num]->orient.fvec,speed);
283 if (Game_mode & GM_MULTI)
284 multi_send_guided_info (Guided_missile[Player_num],0);
289 obj->mtype.phys_info.rotthrust.x = Controls.pitch_time;
290 obj->mtype.phys_info.rotthrust.y = Controls.heading_time;
291 obj->mtype.phys_info.rotthrust.z = Controls.bank_time;
294 // 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) ));
296 forward_thrust_time = Controls.forward_thrust_time;
298 if (Players[Player_num].flags & PLAYER_FLAGS_AFTERBURNER)
300 if (Controls.afterburner_state) { //player has key down
301 //if (forward_thrust_time >= 0) { //..and isn't moving backward
303 fix afterburner_scale;
304 int old_count,new_count;
306 //add in value from 0..1
307 afterburner_scale = f1_0 + min(f1_0/2,Afterburner_charge) * 2;
309 forward_thrust_time = fixmul(FrameTime,afterburner_scale); //based on full thrust
311 old_count = (Afterburner_charge / (DROP_DELTA_TIME/AFTERBURNER_USE_SECS));
313 Afterburner_charge -= FrameTime/AFTERBURNER_USE_SECS;
315 if (Afterburner_charge < 0)
316 Afterburner_charge = 0;
318 new_count = (Afterburner_charge / (DROP_DELTA_TIME/AFTERBURNER_USE_SECS));
320 if (old_count != new_count)
321 Drop_afterburner_blob_flag = 1; //drop blob (after physics called)
325 fix cur_energy,charge_up;
328 charge_up = min(FrameTime/8,f1_0 - Afterburner_charge); //recharge over 8 seconds
330 cur_energy = max(Players[Player_num].energy-i2f(10),0); //don't drop below 10
332 //maybe limit charge up by energy
333 charge_up = min(charge_up,cur_energy/10);
335 Afterburner_charge += charge_up;
337 Players[Player_num].energy -= charge_up * 100 / 10; //full charge uses 10% of energy
341 // Set object's thrust vector for forward/backward
342 vm_vec_copy_scale(&obj->mtype.phys_info.thrust,&obj->orient.fvec, forward_thrust_time );
345 vm_vec_scale_add2(&obj->mtype.phys_info.thrust,&obj->orient.rvec, Controls.sideways_thrust_time );
348 vm_vec_scale_add2(&obj->mtype.phys_info.thrust,&obj->orient.uvec, Controls.vertical_thrust_time );
350 if (obj->mtype.phys_info.flags & PF_WIGGLE)
353 fix_fastsincos(GameTime, &swiggle, NULL);
354 if (FrameTime < F1_0) // Only scale wiggle if getting at least 1 FPS, to avoid causing the opposite problem.
355 swiggle = fixmul(swiggle*20, FrameTime); //make wiggle fps-independent (based on pre-scaled amount of wiggle at 20 FPS)
356 vm_vec_scale_add2(&obj->mtype.phys_info.velocity,&obj->orient.uvec,fixmul(swiggle,Player_ship->wiggle));
359 // As of now, obj->mtype.phys_info.thrust & obj->mtype.phys_info.rotthrust are
360 // in units of time... In other words, if thrust==FrameTime, that
361 // means that the user was holding down the Max_thrust key for the
362 // whole frame. So we just scale them up by the max, and divide by
363 // FrameTime to make them independant of framerate
365 // Prevent divide overflows on high frame rates.
366 // In a signed divide, you get an overflow if num >= div<<15
370 // Note, you must check for ft < F1_0/2, else you can get an overflow on the << 15.
371 if ((ft < F1_0/2) && (ft << 15 <= Player_ship->max_thrust)) {
372 mprintf((0, "Preventing divide overflow in controls.c for Max_thrust!\n"));
373 ft = (Player_ship->max_thrust >> 15) + 1;
376 vm_vec_scale( &obj->mtype.phys_info.thrust, fixdiv(Player_ship->max_thrust,ft) );
378 if ((ft < F1_0/2) && (ft << 15 <= Player_ship->max_rotthrust)) {
379 mprintf((0, "Preventing divide overflow in controls.c for max_rotthrust!\n"));
380 ft = (Player_ship->max_thrust >> 15) + 1;
383 vm_vec_scale( &obj->mtype.phys_info.rotthrust, fixdiv(Player_ship->max_rotthrust,ft) );