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 |