]> icculus.org git repositories - btb/d2x.git/blob - main/controls.c
remove rcs tags
[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.afterburner_state) {                       //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 }