Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | pmbaty | 1 | /* |
2 | * Portions of this file are copyright Rebirth contributors and licensed as |
||
3 | * described in COPYING.txt. |
||
4 | * Portions of this file are copyright Parallax Software and licensed |
||
5 | * according to the Parallax license below. |
||
6 | * See COPYING.txt for license details. |
||
7 | |||
8 | THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX |
||
9 | SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO |
||
10 | END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A |
||
11 | ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS |
||
12 | IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS |
||
13 | SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE |
||
14 | FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE |
||
15 | CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS |
||
16 | AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE. |
||
17 | COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED. |
||
18 | */ |
||
19 | |||
20 | /* |
||
21 | * |
||
22 | * Code for controlling player movement |
||
23 | * |
||
24 | */ |
||
25 | |||
26 | |||
27 | #include <algorithm> |
||
28 | #include <stdlib.h> |
||
29 | #include "key.h" |
||
30 | #include "joy.h" |
||
31 | #include "timer.h" |
||
32 | #include "dxxerror.h" |
||
33 | #include "inferno.h" |
||
34 | #include "game.h" |
||
35 | #include "object.h" |
||
36 | #include "player.h" |
||
37 | #include "weapon.h" |
||
38 | #include "bm.h" |
||
39 | #include "controls.h" |
||
40 | #include "render.h" |
||
41 | #include "args.h" |
||
42 | #include "palette.h" |
||
43 | #include "mouse.h" |
||
44 | #include "kconfig.h" |
||
45 | #if defined(DXX_BUILD_DESCENT_II) |
||
46 | #include "laser.h" |
||
47 | #include "multi.h" |
||
48 | #include "vclip.h" |
||
49 | #include "fireball.h" |
||
50 | |||
51 | //look at keyboard, mouse, joystick, CyberMan, whatever, and set |
||
52 | //physics vars rotvel, velocity |
||
53 | |||
54 | fix Afterburner_charge=f1_0; |
||
55 | |||
56 | #define AFTERBURNER_USE_SECS 3 //use up in 3 seconds |
||
57 | #define DROP_DELTA_TIME (f1_0/15) //drop 3 per second |
||
58 | #endif |
||
59 | |||
60 | using std::min; |
||
61 | using std::max; |
||
62 | |||
63 | namespace dsx { |
||
64 | void read_flying_controls(object &obj) |
||
65 | { |
||
66 | fix forward_thrust_time; |
||
67 | |||
68 | Assert(FrameTime > 0); //Get MATT if hit this! |
||
69 | |||
70 | #if defined(DXX_BUILD_DESCENT_II) |
||
71 | if (obj.type != OBJ_PLAYER || get_player_id(obj) != Player_num) |
||
72 | return; //references to player_ship require that this obj be the player |
||
73 | |||
74 | const auto control_guided_missile = [&] { |
||
75 | const auto &&gimobj = LevelUniqueObjectState.Guided_missile.get_player_active_guided_missile(LevelUniqueObjectState.get_objects().vmptr, Player_num); |
||
76 | if (gimobj == nullptr) |
||
77 | return false; |
||
78 | auto &gmobj = *gimobj; |
||
79 | const auto gmid = get_weapon_id(gmobj); |
||
80 | const auto speed = Weapon_info[gmid].speed[GameUniqueState.Difficulty_level]; |
||
81 | vms_angvec rotangs; |
||
82 | //this is a horrible hack. guided missile stuff should not be |
||
83 | //handled in the middle of a routine that is dealing with the player |
||
84 | |||
85 | vm_vec_zero(obj.mtype.phys_info.rotthrust); |
||
86 | |||
87 | const auto Seismic_tremor_magnitude = LevelUniqueSeismicState.Seismic_tremor_magnitude; |
||
88 | rotangs.p = Controls.pitch_time / 2 + Seismic_tremor_magnitude/64; |
||
89 | rotangs.b = Controls.bank_time / 2 + Seismic_tremor_magnitude/16; |
||
90 | rotangs.h = Controls.heading_time / 2 + Seismic_tremor_magnitude/64; |
||
91 | |||
92 | const auto &&rotmat = vm_angles_2_matrix(rotangs); |
||
93 | gmobj.orient = vm_matrix_x_matrix(gmobj.orient, rotmat); |
||
94 | |||
95 | vm_vec_copy_scale(gmobj.mtype.phys_info.velocity, gmobj.orient.fvec, speed); |
||
96 | if (Game_mode & GM_MULTI) |
||
97 | multi_send_guided_info(gmobj, 0); |
||
98 | return true; |
||
99 | }; |
||
100 | if (!control_guided_missile()) |
||
101 | #endif |
||
102 | { |
||
103 | auto &rotthrust = obj.mtype.phys_info.rotthrust; |
||
104 | rotthrust.x = Controls.pitch_time; |
||
105 | rotthrust.y = Controls.heading_time; |
||
106 | rotthrust.z = Controls.bank_time; |
||
107 | } |
||
108 | |||
109 | forward_thrust_time = Controls.forward_thrust_time; |
||
110 | |||
111 | #if defined(DXX_BUILD_DESCENT_II) |
||
112 | auto &player_info = obj.ctype.player_info; |
||
113 | if (player_info.powerup_flags & PLAYER_FLAGS_AFTERBURNER) |
||
114 | { |
||
115 | if (Controls.state.afterburner) { //player has key down |
||
116 | { |
||
117 | fix afterburner_scale; |
||
118 | int old_count,new_count; |
||
119 | |||
120 | //add in value from 0..1 |
||
121 | afterburner_scale = f1_0 + min(f1_0/2,Afterburner_charge) * 2; |
||
122 | |||
123 | forward_thrust_time = fixmul(FrameTime,afterburner_scale); //based on full thrust |
||
124 | |||
125 | old_count = (Afterburner_charge / (DROP_DELTA_TIME/AFTERBURNER_USE_SECS)); |
||
126 | |||
127 | Afterburner_charge -= FrameTime/AFTERBURNER_USE_SECS; |
||
128 | |||
129 | if (Afterburner_charge < 0) |
||
130 | Afterburner_charge = 0; |
||
131 | |||
132 | new_count = (Afterburner_charge / (DROP_DELTA_TIME/AFTERBURNER_USE_SECS)); |
||
133 | |||
134 | if (old_count != new_count) |
||
135 | Drop_afterburner_blob_flag = 1; //drop blob (after physics called) |
||
136 | } |
||
137 | } |
||
138 | else { |
||
139 | fix cur_energy,charge_up; |
||
140 | |||
141 | //charge up to full |
||
142 | charge_up = min(FrameTime/8,f1_0 - Afterburner_charge); //recharge over 8 seconds |
||
143 | |||
144 | auto &energy = player_info.energy; |
||
145 | cur_energy = max(energy - i2f(10), 0); //don't drop below 10 |
||
146 | |||
147 | //maybe limit charge up by energy |
||
148 | charge_up = min(charge_up,cur_energy/10); |
||
149 | |||
150 | Afterburner_charge += charge_up; |
||
151 | |||
152 | energy -= charge_up * 100 / 10; //full charge uses 10% of energy |
||
153 | } |
||
154 | } |
||
155 | #endif |
||
156 | |||
157 | // Set object's thrust vector for forward/backward |
||
158 | vm_vec_copy_scale(obj.mtype.phys_info.thrust, obj.orient.fvec, forward_thrust_time ); |
||
159 | |||
160 | // slide left/right |
||
161 | vm_vec_scale_add2(obj.mtype.phys_info.thrust, obj.orient.rvec, Controls.sideways_thrust_time ); |
||
162 | |||
163 | // slide up/down |
||
164 | vm_vec_scale_add2(obj.mtype.phys_info.thrust, obj.orient.uvec, Controls.vertical_thrust_time ); |
||
165 | |||
166 | if (obj.mtype.phys_info.flags & PF_WIGGLE) |
||
167 | { |
||
168 | auto swiggle = fix_fastsin(static_cast<fix>(GameTime64)); |
||
169 | if (FrameTime < F1_0) // Only scale wiggle if getting at least 1 FPS, to avoid causing the opposite problem. |
||
170 | swiggle = fixmul(swiggle*DESIGNATED_GAME_FPS, FrameTime); //make wiggle fps-independent (based on pre-scaled amount of wiggle at DESIGNATED_GAME_FPS) |
||
171 | vm_vec_scale_add2(obj.mtype.phys_info.velocity, obj.orient.uvec, fixmul(swiggle, Player_ship->wiggle)); |
||
172 | } |
||
173 | |||
174 | // As of now, obj.mtype.phys_info.thrust & obj->mtype.phys_info.rotthrust are |
||
175 | // in units of time... In other words, if thrust==FrameTime, that |
||
176 | // means that the user was holding down the Max_thrust key for the |
||
177 | // whole frame. So we just scale them up by the max, and divide by |
||
178 | // FrameTime to make them independant of framerate |
||
179 | |||
180 | // Prevent divide overflows on high frame rates. |
||
181 | // In a signed divide, you get an overflow if num >= div<<15 |
||
182 | { |
||
183 | fix ft = FrameTime; |
||
184 | |||
185 | // Note, you must check for ft < F1_0/2, else you can get an overflow on the << 15. |
||
186 | if ((ft < F1_0/2) && (ft << 15 <= Player_ship->max_thrust)) { |
||
187 | ft = (Player_ship->max_thrust >> 15) + 1; |
||
188 | } |
||
189 | |||
190 | vm_vec_scale(obj.mtype.phys_info.thrust, fixdiv(Player_ship->max_thrust, ft)); |
||
191 | |||
192 | if ((ft < F1_0/2) && (ft << 15 <= Player_ship->max_rotthrust)) { |
||
193 | ft = (Player_ship->max_thrust >> 15) + 1; |
||
194 | } |
||
195 | |||
196 | vm_vec_scale(obj.mtype.phys_info.rotthrust, fixdiv(Player_ship->max_rotthrust, ft)); |
||
197 | } |
||
198 | |||
199 | // moved here by WraithX |
||
200 | if (Player_dead_state != player_dead_state::no) |
||
201 | { |
||
202 | //vm_vec_zero(&obj.mtype.phys_info.rotthrust); // let dead players rotate, changed by WraithX |
||
203 | vm_vec_zero(obj.mtype.phys_info.thrust); // don't let dead players move, changed by WraithX |
||
204 | return; |
||
205 | }// end if |
||
206 | |||
207 | } |
||
208 | } |