Subversion Repositories Games.Descent

Rev

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
}