]> icculus.org git repositories - btb/d2x.git/blob - main/controls.c
fix level number position
[btb/d2x.git] / main / controls.c
1 /* $Id: controls.c,v 1.5 2003-08-02 20:36:12 btb Exp $ */
2 /*
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.
13 */
14
15 /*
16  *
17  * Code for controlling player movement
18  *
19  * Old Log:
20  * Revision 1.3  1995/11/20  17:17:27  allender
21  * call fix_fastsincos with tmp variable to prevent
22  * writing to NULL
23  *
24  * Revision 1.2  1995/08/11  16:00:04  allender
25  * fixed bug we think we never saw (overflow on max_rotthrust
26  *
27  * Revision 1.1  1995/05/16  15:23:53  allender
28  * Initial revision
29  *
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.
33  *
34  * Revision 1.50  1995/02/22  14:11:19  allender
35  * remove anonymous unions from object structure
36  *
37  * Revision 1.49  1994/12/15  13:04:10  mike
38  * Replace Players[Player_num].time_total references with GameTime.
39  *
40  * Revision 1.48  1994/11/27  23:12:13  matt
41  * Made changes for new mprintf calling convention
42  *
43  * Revision 1.47  1994/11/25  22:15:54  matt
44  * Added asserts to try to trap frametime < 0 bug
45  *
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
48  *
49  * Revision 1.45  1994/11/15  13:07:23  matt
50  * Added int3's to try to trap bug
51  *
52  * Revision 1.44  1994/10/14  16:18:12  john
53  * Made Assert that the object was player just nicely exit
54  * the function.
55  *
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.
60  *
61  * Revision 1.42  1994/09/29  11:22:02  mike
62  * Zero thrust when player dies.
63  *
64  * Revision 1.41  1994/09/16  13:10:30  mike
65  * Hook in afterburner stuff.
66  *
67  * Revision 1.40  1994/09/14  22:21:54  matt
68  * Avoid post-death assert
69  *
70  * Revision 1.39  1994/09/11  20:30:27  matt
71  * Cleaned up thrust vars, changing a few names
72  *
73  * Revision 1.38  1994/09/10  15:46:31  john
74  * First version of new keyboard configuration.
75  *
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?
78  *
79  * Revision 1.36  1994/09/06  14:51:56  john
80  * Added sensitivity adjustment, fixed bug with joystick button not
81  * staying down.
82  *
83  * Revision 1.35  1994/09/01  15:43:26  john
84  * Put pitch bak like it was.
85  *
86  * Revision 1.34  1994/08/31  18:59:35  john
87  * Made rotthrust back like it was.
88  *
89  * Revision 1.33  1994/08/31  18:49:17  john
90  * Slowed Maxrothrust a bit,
91  * ..
92  *
93  * Revision 1.32  1994/08/31  18:32:05  john
94  * Lower max rotational thrust
95  *
96  * Revision 1.31  1994/08/29  21:18:27  john
97  * First version of new keyboard/oystick remapping stuff.
98  *
99  * Revision 1.30  1994/08/29  16:18:30  mike
100  * trap divide overflow.
101  *
102  * Revision 1.29  1994/08/26  14:40:45  john
103  * *** empty log message ***
104  *
105  * Revision 1.28  1994/08/26  12:23:50  john
106  * MAde joystick read up to 15 times per second max.
107  *
108  * Revision 1.27  1994/08/26  10:50:59  john
109  * Took out Controls_always_stopped.
110  *
111  * Revision 1.26  1994/08/26  10:47:27  john
112  * *** empty log message ***
113  *
114  * Revision 1.25  1994/08/26  10:46:50  john
115  * New version of controls.
116  *
117  * Revision 1.24  1994/08/25  19:41:44  john
118  * *** empty log message ***
119  *
120  * Revision 1.23  1994/08/25  18:44:55  john
121  * *** empty log message ***
122  *
123  * Revision 1.22  1994/08/25  18:43:46  john
124  * First revision of new control code.
125  *
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,.
129  *
130  *
131  * Revision 1.20  1994/08/24  19:00:27  john
132  * Changed key_down_time to return fixed seconds instead of
133  * milliseconds.
134  *
135  * Revision 1.19  1994/08/19  15:22:12  mike
136  * Fix divide overflow in sliding.
137  *
138  * Revision 1.18  1994/08/19  14:42:50  john
139  * Added joystick sensitivity.
140  *
141  * Revision 1.17  1994/08/17  16:50:01  john
142  * Added damaging fireballs, missiles.
143  *
144  * Revision 1.16  1994/08/12  22:41:54  john
145  * Took away Player_stats; added Players array.
146  *
147  * Revision 1.15  1994/08/09  16:03:56  john
148  * Added network players to editor.
149  *
150  * Revision 1.14  1994/07/28  12:33:31  matt
151  * Made sliding use thrust, rather than changing velocity directly
152  *
153  * Revision 1.13  1994/07/27  20:53:21  matt
154  * Added rotational drag & thrust, so turning now has momemtum like moving
155  *
156  * Revision 1.12  1994/07/25  10:24:06  john
157  * Victor stuff.
158  *
159  * Revision 1.11  1994/07/22  17:53:16  john
160  * Added better victormax support
161  *
162  * Revision 1.10  1994/07/21  21:31:29  john
163  * First cheapo version of VictorMaxx tracking.
164  *
165  * Revision 1.9  1994/07/15  15:16:18  john
166  * Fixed some joystick stuff.
167  *
168  * Revision 1.8  1994/07/15  09:32:09  john
169  * Changes player movement.
170  *
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
173  * bitmaps.tbl
174  *
175  * Revision 1.6  1994/07/12  12:40:14  matt
176  * Revamped physics system
177  *
178  * Revision 1.5  1994/07/02  13:50:39  matt
179  * Cleaned up includes
180  *
181  * Revision 1.4  1994/07/01  10:55:25  john
182  * Added analog joystick throttle
183  *
184  * Revision 1.3  1994/06/30  20:04:28  john
185  * Added -joydef support.
186  *
187  * Revision 1.2  1994/06/30  19:01:58  matt
188  * Moved flying controls code from physics.c to controls.c
189  *
190  * Revision 1.1  1994/06/30  18:41:25  matt
191  * Initial revision
192  *
193  *
194  */
195
196 #ifdef HAVE_CONFIG_H
197 #include <conf.h>
198 #endif
199
200 #ifdef RCS
201 static char rcsid[] = "$Id: controls.c,v 1.5 2003-08-02 20:36:12 btb Exp $";
202 #endif
203
204 #include <stdio.h>
205 #include <stdlib.h>
206
207 #include "pstypes.h"
208 #include "mono.h"
209 #include "key.h"
210 #include "joy.h"
211 #include "timer.h"
212 #include "error.h"
213
214 #include "inferno.h"
215 #include "game.h"
216 #include "object.h"
217 #include "player.h"
218
219 #include "controls.h"
220 #include "joydefs.h"
221 #include "render.h"
222 #include "args.h"
223 #include "palette.h"
224 #include "mouse.h"
225 #include "kconfig.h"
226 #include "laser.h"
227 #ifdef NETWORK
228 #include "multi.h"
229 #endif
230 #include "vclip.h"
231 #include "fireball.h"
232
233 //look at keyboard, mouse, joystick, CyberMan, whatever, and set 
234 //physics vars rotvel, velocity
235
236 fix Afterburner_charge=f1_0;
237
238 #define AFTERBURNER_USE_SECS    3                               //use up in 3 seconds
239 #define DROP_DELTA_TIME                 (f1_0/15)       //drop 3 per second
240
241 extern int Drop_afterburner_blob_flag;          //ugly hack
242
243 extern fix      Seismic_tremor_magnitude;
244
245 void read_flying_controls( object * obj )
246 {
247         fix     forward_thrust_time;
248
249         Assert(FrameTime > 0);          //Get MATT if hit this!
250
251         if (Player_is_dead) {
252                 vm_vec_zero(&obj->mtype.phys_info.rotthrust);
253                 vm_vec_zero(&obj->mtype.phys_info.thrust);
254                 return;
255         }
256
257         if ((obj->type!=OBJ_PLAYER) || (obj->id!=Player_num)) return;   //references to player_ship require that this obj be the player
258
259         if (Guided_missile[Player_num] && Guided_missile[Player_num]->signature==Guided_missile_sig[Player_num]) {
260                 vms_angvec rotangs;
261                 vms_matrix rotmat,tempm;
262                 fix speed;
263
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
266
267                 vm_vec_zero(&obj->mtype.phys_info.rotthrust);
268
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;
272
273                 vm_angles_2_matrix(&rotmat,&rotangs);
274
275                 vm_matrix_x_matrix(&tempm,&Guided_missile[Player_num]->orient,&rotmat);
276
277                 Guided_missile[Player_num]->orient = tempm;
278
279                 speed = Weapon_info[Guided_missile[Player_num]->id].speed[Difficulty_level];
280
281                 vm_vec_copy_scale(&Guided_missile[Player_num]->mtype.phys_info.velocity,&Guided_missile[Player_num]->orient.fvec,speed);
282 #ifdef NETWORK
283                 if (Game_mode & GM_MULTI)
284                         multi_send_guided_info (Guided_missile[Player_num],0);
285 #endif
286
287         }
288         else {
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;
292         }
293
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) ));
295
296         forward_thrust_time = Controls.forward_thrust_time;
297
298         if (Players[Player_num].flags & PLAYER_FLAGS_AFTERBURNER)
299         {
300                 if (Controls.afterburner_state) {                       //player has key down
301                         //if (forward_thrust_time >= 0) {               //..and isn't moving backward
302                         {
303                                 fix afterburner_scale;
304                                 int old_count,new_count;
305         
306                                 //add in value from 0..1
307                                 afterburner_scale = f1_0 + min(f1_0/2,Afterburner_charge) * 2;
308         
309                                 forward_thrust_time = fixmul(FrameTime,afterburner_scale);      //based on full thrust
310         
311                                 old_count = (Afterburner_charge / (DROP_DELTA_TIME/AFTERBURNER_USE_SECS));
312
313                                 Afterburner_charge -= FrameTime/AFTERBURNER_USE_SECS;
314
315                                 if (Afterburner_charge < 0)
316                                         Afterburner_charge = 0;
317
318                                 new_count = (Afterburner_charge / (DROP_DELTA_TIME/AFTERBURNER_USE_SECS));
319
320                                 if (old_count != new_count)
321                                         Drop_afterburner_blob_flag = 1; //drop blob (after physics called)
322                         }
323                 }
324                 else {
325                         fix cur_energy,charge_up;
326         
327                         //charge up to full
328                         charge_up = min(FrameTime/8,f1_0 - Afterburner_charge); //recharge over 8 seconds
329         
330                         cur_energy = max(Players[Player_num].energy-i2f(10),0); //don't drop below 10
331
332                         //maybe limit charge up by energy
333                         charge_up = min(charge_up,cur_energy/10);
334         
335                         Afterburner_charge += charge_up;
336         
337                         Players[Player_num].energy -= charge_up * 100 / 10;     //full charge uses 10% of energy
338                 }
339         }
340
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 );
343         
344         // slide left/right
345         vm_vec_scale_add2(&obj->mtype.phys_info.thrust,&obj->orient.rvec, Controls.sideways_thrust_time );
346
347         // slide up/down
348         vm_vec_scale_add2(&obj->mtype.phys_info.thrust,&obj->orient.uvec, Controls.vertical_thrust_time );
349
350         if (obj->mtype.phys_info.flags & PF_WIGGLE)
351         {
352                 fix swiggle;
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));
357         }
358
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
364
365         //      Prevent divide overflows on high frame rates.
366         //      In a signed divide, you get an overflow if num >= div<<15
367         {
368                 fix     ft = FrameTime;
369
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;
374                 }
375
376                 vm_vec_scale( &obj->mtype.phys_info.thrust, fixdiv(Player_ship->max_thrust,ft) );
377
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;
381                 }
382
383                 vm_vec_scale( &obj->mtype.phys_info.rotthrust, fixdiv(Player_ship->max_rotthrust,ft) );
384         }
385
386 }