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
 * Header for robot.c
23
 *
24
 */
25
 
26
#pragma once
27
 
28
#include "vecmat.h"
29
#include "game.h"
30
 
31
#ifdef __cplusplus
32
#include "pack.h"
33
#include "ai.h"
34
#include "aistruct.h"
35
#include "polyobj.h"
36
#include "weapon_id.h"
37
#include "object.h"
38
#include "fwd-partial_range.h"
39
 
40
#define MAX_GUNS 8      //should be multiple of 4 for ubyte array
41
 
42
//Animation states
43
#define AS_REST         0
44
#define AS_ALERT        1
45
#define AS_FIRE         2
46
#define AS_RECOIL       3
47
#define AS_FLINCH       4
48
#define N_ANIM_STATES   5
49
 
50
#define RI_CLOAKED_ALWAYS           1
51
 
52
namespace dcx {
53
 
54
//describes the position of a certain joint
55
struct jointpos : prohibit_void_ptr<jointpos>
56
{
57
        uint16_t jointnum;
58
        vms_angvec angles;
59
};
60
 
61
//describes a list of joint positions
62
struct jointlist
63
{
64
        short n_joints;
65
        short offset;
66
};
67
 
68
constexpr std::integral_constant<unsigned, 16> ROBOT_NAME_LENGTH{};
69
}
70
 
71
#if defined(DXX_BUILD_DESCENT_I) || defined(DXX_BUILD_DESCENT_II)
72
namespace dsx {
73
#if defined(DXX_BUILD_DESCENT_II)
74
//robot info flags
75
#define RIF_BIG_RADIUS  1   //pad the radius to fix robots firing through walls
76
#define RIF_THIEF       2   //this guy steals!
77
#endif
78
 
79
//  Robot information
80
struct robot_info : prohibit_void_ptr<robot_info>
81
{
82
        int     model_num;                  // which polygon model?
83
        std::array<vms_vector, MAX_GUNS>  gun_points;   // where each gun model is
84
        std::array<uint8_t, MAX_GUNS>   gun_submodels;    // which submodel is each gun in?
85
        uint16_t score_value;                                           //      Score from this robot.
86
        short   exp1_vclip_num;
87
        short   exp1_sound_num;
88
        short   exp2_vclip_num;
89
        short   exp2_sound_num;
90
        weapon_id_type weapon_type;
91
        uint8_t   n_guns;         // how many different gun positions
92
        sbyte   contains_id;    //  ID of powerup this robot can contain.
93
 
94
        sbyte   contains_count; //  Max number of things this instance can contain.
95
        sbyte   contains_prob;  //  Probability that this instance will contain something in N/16
96
        sbyte   contains_type;  //  Type of thing contained, robot or powerup, in bitmaps.tbl, !0=robot, 0=powerup
97
#if defined(DXX_BUILD_DESCENT_I)
98
#elif defined(DXX_BUILD_DESCENT_II)
99
        sbyte   kamikaze;       //  !0 means commits suicide when hits you, strength thereof. 0 means no.
100
 
101
        sbyte   badass;         //  Dies with badass explosion, and strength thereof, 0 means NO.
102
        sbyte   energy_drain;   //  Points of energy drained at each collision.
103
        weapon_id_type   weapon_type2;   //  Secondary weapon number, -1 means none, otherwise gun #0 fires this weapon.
104
#endif
105
        fix     lighting;       // should this be here or with polygon model?
106
        fix     strength;       // Initial shields of robot
107
 
108
        fix     mass;           // how heavy is this thing?
109
        fix     drag;           // how much drag does it have?
110
 
111
        std::array<fix, NDL>     field_of_view, // compare this value with forward_vector.dot.vector_to_player, if field_of_view <, then robot can see player
112
                firing_wait,   //  time in seconds between shots
113
#if defined(DXX_BUILD_DESCENT_II)
114
                firing_wait2,  //  time in seconds between shots
115
#endif
116
                turn_time,     // time in seconds to rotate 360 degrees in a dimension
117
                max_speed,         //  maximum speed attainable by this robot
118
                circle_distance;   //  distance at which robot circles player
119
 
120
        std::array<int8_t, NDL>   rapidfire_count,   //  number of shots fired rapidly
121
                evade_speed;       //  rate at which robot can evade shots, 0=none, 4=very fast
122
        sbyte   cloak_type;     //  0=never, 1=always, 2=except-when-firing
123
        sbyte   attack_type;    //  0=firing, 1=charge (like green guy)
124
 
125
        ubyte   see_sound;      //  sound robot makes when it first sees the player
126
        ubyte   attack_sound;   //  sound robot makes when it attacks the player
127
        ubyte   claw_sound;     //  sound robot makes as it claws you (attack_type should be 1)
128
        sbyte   boss_flag;      //  0 = not boss, 1 = boss.  Is that surprising?
129
#if defined(DXX_BUILD_DESCENT_II)
130
        ubyte   taunt_sound;    //  sound robot makes after you die
131
 
132
        sbyte   companion;      //  Companion robot, leads you to things.
133
        sbyte   smart_blobs;    //  how many smart blobs are emitted when this guy dies!
134
        sbyte   energy_blobs;   //  how many smart blobs are emitted when this guy gets hit by energy weapon!
135
 
136
        sbyte   thief;          //  !0 means this guy can steal when he collides with you!
137
        sbyte   pursuit;        //  !0 means pursues player after he goes around a corner.  4 = 4/2 pursue up to 4/2 seconds after becoming invisible if up to 4 segments away
138
        sbyte   lightcast;      //  Amount of light cast. 1 is default.  10 is very large.
139
        sbyte   death_roll;     //  0 = dies without death roll. !0 means does death roll, larger = faster and louder
140
 
141
        //boss_flag, companion, thief, & pursuit probably should also be bits in the flags byte.
142
        ubyte   flags;          // misc properties
143
 
144
        ubyte   deathroll_sound;    // if has deathroll, what sound?
145
        ubyte   glow;               // apply this light to robot itself. stored as 4:4 fixed-point
146
        ai_behavior behavior;           //  Default behavior.
147
        ubyte   aim;                //  255 = perfect, less = more likely to miss.  0 != random, would look stupid.  0=45 degree spread.  Specify in bitmaps.tbl in range 0.0..1.0
148
#endif
149
        //animation info
150
        std::array<std::array<jointlist, N_ANIM_STATES>, MAX_GUNS+1> anim_states;
151
        int     always_0xabcd;      // debugging
152
};
153
}
154
 
155
constexpr auto weapon_none = weapon_id_type::unspecified;
156
 
157
namespace dsx {
158
imobjptridx_t robot_create(unsigned id, vmsegptridx_t segnum, const vms_vector &pos, const vms_matrix *orient, fix size, ai_behavior behavior, const imsegidx_t hide_segment = segment_none);
159
 
160
#if defined(DXX_BUILD_DESCENT_I)
161
// maximum number of robot types
162
constexpr std::integral_constant<unsigned, 30> MAX_ROBOT_TYPES{};
163
constexpr std::integral_constant<unsigned, 600> MAX_ROBOT_JOINTS{};
164
 
165
static inline int robot_is_companion(const robot_info &)
166
{
167
        return 0;
168
}
169
 
170
static inline int robot_is_thief(const robot_info &)
171
{
172
        return 0;
173
}
174
#elif defined(DXX_BUILD_DESCENT_II)
175
// maximum number of robot types
176
constexpr std::integral_constant<unsigned, 85> MAX_ROBOT_TYPES{};
177
constexpr std::integral_constant<unsigned, 1600> MAX_ROBOT_JOINTS{};
178
 
179
static inline int robot_is_companion(const robot_info &robptr)
180
{
181
        return robptr.companion;
182
}
183
 
184
static inline int robot_is_thief(const robot_info &robptr)
185
{
186
        return robptr.thief;
187
}
188
#endif
189
 
190
//the array of robots types
191
struct d_level_shared_robot_info_state
192
{
193
        using d_robot_info_array = std::array<robot_info, MAX_ROBOT_TYPES>;
194
        //how many kinds of robots
195
        unsigned N_robot_types;      // Number of robot types.  We used to assume this was the same as N_polygon_models.
196
        // Robot info for AI system, loaded from bitmaps.tbl.
197
        d_robot_info_array Robot_info;
198
};
199
 
200
extern d_level_shared_robot_info_state LevelSharedRobotInfoState;
201
 
202
#if defined(DXX_BUILD_DESCENT_II)
203
// returns ptr to escort robot, or NULL
204
imobjptridx_t find_escort(fvmobjptridx &vmobjptridx, const d_level_shared_robot_info_state::d_robot_info_array &Robot_info);
205
#endif
206
 
207
#if DXX_USE_EDITOR
208
using robot_names_array = std::array<std::array<char, ROBOT_NAME_LENGTH>, MAX_ROBOT_TYPES>;
209
extern robot_names_array Robot_names;
210
#endif
211
 
212
/* Robot joints can be customized by hxm files, which are per-level.
213
 */
214
struct d_level_shared_robot_joint_state
215
{
216
        //Big array of joint positions.  All robots index into this array
217
        std::array<jointpos, MAX_ROBOT_JOINTS> Robot_joints;
218
};
219
 
220
extern d_level_shared_robot_joint_state LevelSharedRobotJointState;
221
}
222
 
223
namespace dcx {
224
 
225
extern unsigned N_robot_joints;
226
}
227
 
228
namespace dsx {
229
//given an object and a gun number, return position in 3-space of gun
230
//fills in gun_point
231
void calc_gun_point(vms_vector &gun_point, const object_base &obj, unsigned gun_num);
232
 
233
//  Tells joint positions for a gun to be in a specified state.
234
//  A gun can have associated with it any number of joints.  In order to tell whether a gun is a certain
235
//  state (such as FIRE or ALERT), you should call this function and check the returned joint positions
236
//  against the robot's gun's joint positions.  This function should also be called to determine how to
237
//  move a gun into a desired position.
238
//  For now (May 30, 1994), it is assumed that guns will linearly interpolate from one joint position to another.
239
//  There is no ordering of joint movement, so it's impossible to guarantee that a strange starting position won't
240
//  cause a gun to move through a robot's body, for example.
241
 
242
//  Given:
243
//      jp_list_ptr     pointer to list of joint angles, on exit, this is pointing at a static array
244
//      robot_type      type of robot for which to get joint information.  A particular type, not an instance of a robot.
245
//      gun_num         gun number.  If in 0..Robot_info[robot_type].n_guns-1, then it is a gun, else it refers to non-animating parts of robot.
246
//      state           state about which to get information.  Legal states in range 0..N_ANIM_STATES-1, defined in robot.h, are:
247
//                          AS_REST, AS_ALERT, AS_FIRE, AS_RECOIL, AS_FLINCH
248
 
249
//  On exit:
250
//      Returns number of joints in list.
251
//      jp_list_ptr is stuffed with a pointer to a static array of joint positions.  This pointer is valid forever.
252
partial_range_t<const jointpos *> robot_get_anim_state(const d_level_shared_robot_info_state::d_robot_info_array &, const std::array<jointpos, MAX_ROBOT_JOINTS> &, unsigned robot_type, unsigned gun_num, unsigned state);
253
 
254
/*
255
 * reads n robot_info structs from a PHYSFS_File
256
 */
257
void robot_info_read(PHYSFS_File *fp, robot_info &r);
258
}
259
#endif
260
 
261
/*
262
 * reads n jointpos structs from a PHYSFS_File
263
 */
264
void jointpos_read(PHYSFS_File *fp, jointpos &jp);
265
#if 0
266
void jointpos_write(PHYSFS_File *fp, const jointpos &jp);
267
#endif
268
#ifdef dsx
269
namespace dsx {
270
void robot_set_angles(robot_info *r,polymodel *pm, std::array<std::array<vms_angvec, MAX_SUBMODELS>, N_ANIM_STATES> &angs);
271
weapon_id_type get_robot_weapon(const robot_info &ri, const unsigned gun_num);
272
 
273
static inline void boss_link_see_sound(const vcobjptridx_t objp)
274
{
275
#if defined(DXX_BUILD_DESCENT_I)
276
        constexpr unsigned soundnum = SOUND_BOSS_SHARE_SEE;
277
#elif defined(DXX_BUILD_DESCENT_II)
278
        auto &Robot_info = LevelSharedRobotInfoState.Robot_info;
279
        const unsigned soundnum = Robot_info[get_robot_id(objp)].see_sound;
280
#endif
281
        digi_link_sound_to_object2(soundnum, objp, 1, F1_0, sound_stack::allow_stacking, vm_distance{F1_0*512});        //      F1_0*512 means play twice as loud
282
}
283
}
284
#endif
285
 
286
#endif