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 file for AI system. |
||
23 | * |
||
24 | */ |
||
25 | |||
26 | #pragma once |
||
27 | |||
28 | #include <cstddef> |
||
29 | #include <utility> |
||
30 | #include "dxxsconf.h" |
||
31 | #include "dsx-ns.h" |
||
32 | #include "fmtcheck.h" |
||
33 | #include "vecmat.h" |
||
34 | |||
35 | #define PARALLAX 0 // If !0, then special debugging info for Parallax eyes only enabled. |
||
36 | |||
37 | #ifdef __cplusplus |
||
38 | #include "pstypes.h" |
||
39 | #include "fwd-object.h" |
||
40 | #include "fwd-segment.h" |
||
41 | #ifdef dsx |
||
42 | #include "countarray.h" |
||
43 | #include "aistruct.h" |
||
44 | #include "valptridx.h" |
||
45 | #endif |
||
46 | |||
47 | namespace dcx { |
||
48 | struct point_seg; |
||
49 | |||
50 | #ifdef dsx |
||
51 | struct awareness_event |
||
52 | { |
||
53 | segnum_t segnum; // segment the event occurred in |
||
54 | player_awareness_type_t type; // type of event, defines behavior |
||
55 | vms_vector pos; // absolute 3 space location of event |
||
56 | }; |
||
57 | |||
58 | struct d_level_unique_robot_awareness_state |
||
59 | { |
||
60 | unsigned Num_awareness_events; |
||
61 | std::array<awareness_event, 64> Awareness_events; |
||
62 | }; |
||
63 | |||
64 | extern d_level_unique_robot_awareness_state LevelUniqueRobotAwarenessState; |
||
65 | #endif |
||
66 | |||
67 | } |
||
68 | struct PHYSFS_File; |
||
69 | |||
70 | #define PLAYER_AWARENESS_INITIAL_TIME (3*F1_0) |
||
71 | #define MAX_PATH_LENGTH 30 // Maximum length of path in ai path following. |
||
72 | #define MAX_DEPTH_TO_SEARCH_FOR_PLAYER 10 |
||
73 | #define BOSS_GATE_MATCEN_NUM -1 |
||
74 | |||
75 | #define ROBOT_BRAIN 7 |
||
76 | #define ROBOT_BOSS1 17 |
||
77 | |||
78 | #define ROBOT_FIRE_AGITATION 94 |
||
79 | |||
80 | #ifdef dsx |
||
81 | |||
82 | #define BOSS_D1 1 |
||
83 | #define BOSS_SUPER 2 |
||
84 | #if defined(DXX_BUILD_DESCENT_II) |
||
85 | #include "player-flags.h" |
||
86 | namespace dsx { |
||
87 | #define BOSS_D2 21 // Minimum D2 boss value. |
||
88 | #define BOSS_COOL 21 |
||
89 | #define BOSS_WATER 22 |
||
90 | #define BOSS_FIRE 23 |
||
91 | #define BOSS_ICE 24 |
||
92 | #define BOSS_ALIEN1 25 |
||
93 | #define BOSS_ALIEN2 26 |
||
94 | |||
95 | #define NUM_D2_BOSSES 8 |
||
96 | |||
97 | using boss_flags_t = std::array<ubyte, NUM_D2_BOSSES>; |
||
98 | extern const boss_flags_t Boss_spew_more; // Set byte if this boss can teleport |
||
99 | extern const boss_flags_t Boss_spews_bots_energy; // Set byte if boss spews bots when hit by energy weapon. |
||
100 | extern const boss_flags_t Boss_spews_bots_matter; // Set byte if boss spews bots when hit by matter weapon. |
||
101 | extern const boss_flags_t Boss_invulnerable_energy; // Set byte if boss is invulnerable to energy weapons. |
||
102 | extern const boss_flags_t Boss_invulnerable_matter; // Set byte if boss is invulnerable to matter weapons. |
||
103 | extern const boss_flags_t Boss_invulnerable_spot; // Set byte if boss is invulnerable in all but a certain spot. (Dot product fvec|vec_to_collision < BOSS_INVULNERABLE_DOT) |
||
104 | extern segnum_t Believed_player_seg; |
||
105 | extern const object *Ai_last_missile_camera; |
||
106 | } |
||
107 | #endif |
||
108 | |||
109 | namespace dsx { |
||
110 | void create_awareness_event(object &objp, player_awareness_type_t type, d_level_unique_robot_awareness_state &LevelUniqueRobotAwarenessState); // object *objp can create awareness of player, amount based on "type" |
||
111 | ai_mode ai_behavior_to_mode(ai_behavior behavior); |
||
112 | void do_ai_robot_hit(vmobjptridx_t robot, player_awareness_type_t type); |
||
113 | void init_ai_object(vmobjptridx_t objp, ai_behavior initial_mode, imsegidx_t hide_segment); |
||
114 | } |
||
115 | |||
116 | namespace dcx { |
||
117 | |||
118 | struct d_level_shared_boss_state |
||
119 | { |
||
120 | struct special_segment_array_t : public count_array_t<vcsegidx_t, 100> {}; |
||
121 | struct gate_segment_array_t : public special_segment_array_t {}; |
||
122 | struct teleport_segment_array_t : public special_segment_array_t {}; |
||
123 | gate_segment_array_t Gate_segs; |
||
124 | teleport_segment_array_t Teleport_segs; |
||
125 | }; |
||
126 | |||
127 | constexpr fix Boss_cloak_duration = F1_0*7; |
||
128 | |||
129 | extern vms_vector Believed_player_pos; |
||
130 | } |
||
131 | |||
132 | namespace dsx { |
||
133 | |||
134 | struct d_level_shared_boss_state : ::dcx::d_level_shared_boss_state |
||
135 | { |
||
136 | // Time between cloaks |
||
137 | using D1_Boss_cloak_interval = std::integral_constant<fix, F1_0 * 10>; |
||
138 | using D1_Boss_teleport_interval = std::integral_constant<fix, F1_0 * 8>; |
||
139 | #if defined(DXX_BUILD_DESCENT_I) |
||
140 | static constexpr D1_Boss_cloak_interval Boss_cloak_interval{}; |
||
141 | static constexpr D1_Boss_teleport_interval Boss_teleport_interval{}; |
||
142 | #elif defined(DXX_BUILD_DESCENT_II) |
||
143 | fix Boss_cloak_interval; |
||
144 | fix Boss_teleport_interval; |
||
145 | #endif |
||
146 | }; |
||
147 | |||
148 | extern d_level_shared_boss_state LevelSharedBossState; |
||
149 | void move_towards_segment_center(const d_level_shared_segment_state &, object_base &objp); |
||
150 | imobjptridx_t gate_in_robot(unsigned type, vmsegptridx_t segnum); |
||
151 | void do_ai_frame(vmobjptridx_t objp); |
||
152 | void do_ai_frame_all(); |
||
153 | } |
||
154 | extern void create_all_paths(void); |
||
155 | namespace dsx { |
||
156 | void create_path_to_station(vmobjptridx_t objp, int max_length); |
||
157 | #if defined(DXX_BUILD_DESCENT_I) |
||
158 | #define ai_follow_path(o,pv,vec) ai_follow_path(o,pv) |
||
159 | #else |
||
160 | #undef ai_follow_path |
||
161 | #endif |
||
162 | void ai_follow_path(vmobjptridx_t objp, const player_visibility_state player_visibility, const vms_vector *vec_to_player); |
||
163 | void ai_turn_towards_vector(const vms_vector &vec_to_player, object_base &obj, fix rate); |
||
164 | extern void init_ai_objects(void); |
||
165 | void create_n_segment_path(vmobjptridx_t objp, unsigned path_length, imsegidx_t avoid_seg); |
||
166 | void create_n_segment_path_to_door(vmobjptridx_t objp, unsigned path_length); |
||
167 | } |
||
168 | #endif |
||
169 | namespace dcx { |
||
170 | void make_random_vector(vms_vector &vec); |
||
171 | __attribute_warn_unused_result |
||
172 | static inline vms_vector make_random_vector() |
||
173 | { |
||
174 | vms_vector v; |
||
175 | return make_random_vector(v), v; |
||
176 | } |
||
177 | |||
178 | } |
||
179 | #ifdef dsx |
||
180 | namespace dsx { |
||
181 | void init_robots_for_level(); |
||
182 | #if defined(DXX_BUILD_DESCENT_II) |
||
183 | int polish_path(vmobjptridx_t objp, point_seg *psegs, int num_points); |
||
184 | void move_towards_player(object &objp, const vms_vector &vec_to_player); |
||
185 | #endif |
||
186 | |||
187 | // max_length is maximum depth of path to create. |
||
188 | // If -1, use default: MAX_DEPTH_TO_SEARCH_FOR_PLAYER |
||
189 | void attempt_to_resume_path(vmobjptridx_t objp); |
||
190 | |||
191 | // When a robot and a player collide, some robots attack! |
||
192 | void do_ai_robot_hit_attack(vmobjptridx_t robot, vmobjptridx_t player, const vms_vector &collision_point); |
||
193 | int ai_door_is_openable( |
||
194 | vmobjptr_t, |
||
195 | #if defined(DXX_BUILD_DESCENT_II) |
||
196 | player_flags, |
||
197 | #endif |
||
198 | const shared_segment &segp, unsigned sidenum); |
||
199 | player_visibility_state player_is_visible_from_object(vmobjptridx_t objp, vms_vector &pos, fix field_of_view, const vms_vector &vec_to_player); |
||
200 | extern void ai_reset_all_paths(void); // Reset all paths. Call at the start of a level. |
||
201 | int ai_multiplayer_awareness(vmobjptridx_t objp, int awareness_level); |
||
202 | |||
203 | #if defined(DXX_BUILD_DESCENT_II) |
||
204 | // In escort.c |
||
205 | void do_escort_frame(vmobjptridx_t objp, const object &plrobj, player_visibility_state player_visibility); |
||
206 | void do_snipe_frame(vmobjptridx_t objp, fix dist_to_player, player_visibility_state player_visibility, const vms_vector &vec_to_player); |
||
207 | void do_thief_frame(vmobjptridx_t objp, fix dist_to_player, player_visibility_state player_visibility, const vms_vector &vec_to_player); |
||
208 | #endif |
||
209 | } |
||
210 | |||
211 | #if PARALLAX |
||
212 | extern void force_dump_ai_objects_all(const char *msg); |
||
213 | #else |
||
214 | static inline void force_dump_ai_objects_all(const char *msg) |
||
215 | { |
||
216 | (void)msg; |
||
217 | } |
||
218 | #endif |
||
219 | |||
220 | namespace dsx { |
||
221 | void start_boss_death_sequence(object &objp); |
||
222 | extern void ai_init_boss_for_ship(void); |
||
223 | void init_ai_for_ship(); |
||
224 | |||
225 | #if defined(DXX_BUILD_DESCENT_II) |
||
226 | extern vms_vector Last_fired_upon_player_pos; |
||
227 | |||
228 | #define MIN_ESCORT_DISTANCE (F1_0*40) |
||
229 | |||
230 | #define SNIPE_RETREAT_TIME (F1_0*5) |
||
231 | #define SNIPE_ABORT_RETREAT_TIME (SNIPE_RETREAT_TIME/2) // Can abort a retreat with this amount of time left in retreat |
||
232 | #define SNIPE_ATTACK_TIME (F1_0*10) |
||
233 | #define SNIPE_WAIT_TIME (F1_0*5) |
||
234 | #define SNIPE_FIRE_TIME (F1_0*2) |
||
235 | |||
236 | #define THIEF_PROBABILITY 16384 // 50% chance of stealing an item at each attempt |
||
237 | |||
238 | extern void create_buddy_bot(void); |
||
239 | |||
240 | imobjptridx_t boss_spew_robot(const object_base &objp, const vms_vector &pos); |
||
241 | |||
242 | // Amount of time since the current robot was last processed for things such as movement. |
||
243 | // It is not valid to use FrameTime because robots do not get moved every frame. |
||
244 | |||
245 | // --------- John: These variables must be saved as part of gamesave. --------- |
||
246 | // ------ John: End of variables which must be saved as part of gamesave. ----- |
||
247 | |||
248 | // These globals are set by a call to find_vector_intersection, which is a slow routine, |
||
249 | // so we don't want to call it again (for this object) unless we have to. |
||
250 | |||
251 | // -- unused, 08/07/95 -- extern void ai_turn_randomly(vms_vector *vec_to_player, object *obj, fix rate, int previous_visibility); |
||
252 | void init_ai_frame(player_flags); |
||
253 | |||
254 | __attribute_warn_unused_result |
||
255 | std::size_t create_bfs_list(vmobjptr_t robot, vcsegidx_t start_seg, player_flags, segnum_t *bfs_list, std::size_t max_segs); |
||
256 | |||
257 | template <std::size_t N> |
||
258 | __attribute_warn_unused_result |
||
259 | std::size_t create_bfs_list(const vmobjptr_t &robot, const vcsegidx_t &start_seg, const player_flags powerup_flags, std::array<segnum_t, N> &bfs_list) |
||
260 | { |
||
261 | return create_bfs_list(robot, start_seg, powerup_flags, bfs_list.data(), N); |
||
262 | } |
||
263 | extern void init_thief_for_level(); |
||
264 | |||
265 | void start_robot_death_sequence(object &objp); |
||
266 | void buddy_message_str(const char * str) __attribute_nonnull(); |
||
267 | void buddy_message(const char * format, ... ) __attribute_format_printf(1, 2); |
||
268 | #define buddy_message(F,...) dxx_call_printf_checked(buddy_message,buddy_message_str,(),(F),##__VA_ARGS__) |
||
269 | |||
270 | #define SPECIAL_REACTOR_ROBOT 65 |
||
271 | extern void special_reactor_stuff(void); |
||
272 | #endif |
||
273 | } |
||
274 | |||
275 | namespace dcx { |
||
276 | struct point_seg_array_t : public std::array<point_seg, MAX_POINT_SEGS> {}; |
||
277 | extern point_seg_array_t Point_segs; |
||
278 | extern point_seg_array_t::iterator Point_segs_free_ptr; |
||
279 | static inline std::size_t operator-(point_seg_array_t::iterator i, point_seg_array_t &p) |
||
280 | { |
||
281 | return std::distance(p.begin(), i); |
||
282 | } |
||
283 | |||
284 | enum class create_path_random_flag : uint8_t |
||
285 | { |
||
286 | nonrandom, |
||
287 | random, |
||
288 | }; |
||
289 | |||
290 | enum class create_path_safety_flag : uint8_t |
||
291 | { |
||
292 | unsafe, |
||
293 | safe, |
||
294 | }; |
||
295 | |||
296 | enum class create_path_result : uint8_t |
||
297 | { |
||
298 | early, |
||
299 | finished, |
||
300 | }; |
||
301 | |||
302 | } |
||
303 | |||
304 | namespace dsx { |
||
305 | |||
306 | #if defined(DXX_BUILD_DESCENT_II) |
||
307 | void create_path_to_segment(vmobjptridx_t objp, segnum_t goalseg, unsigned max_length, create_path_safety_flag safety_flag); |
||
308 | #endif |
||
309 | |||
310 | void create_path_to_segment(vmobjptridx_t objp, unsigned max_length, create_path_safety_flag safety_flag, icsegidx_t); |
||
311 | void create_path_to_believed_player_segment(vmobjptridx_t objp, unsigned max_length, create_path_safety_flag safety_flag); |
||
312 | void create_path_to_guidebot_player_segment(vmobjptridx_t objp, unsigned max_length, create_path_safety_flag safety_flag); |
||
313 | std::pair<create_path_result, unsigned> create_path_points(vmobjptridx_t objp, vcsegidx_t start_seg, icsegidx_t end_seg, point_seg_array_t::iterator point_segs, unsigned max_depth, create_path_random_flag random_flag, create_path_safety_flag safety_flag, icsegidx_t avoid_seg); |
||
314 | |||
315 | int ai_save_state(PHYSFS_File * fp); |
||
316 | int ai_restore_state(PHYSFS_File *fp, int version, int swap); |
||
317 | |||
318 | #if DXX_USE_EDITOR |
||
319 | void player_follow_path(object &objp); |
||
320 | void check_create_player_path(); |
||
321 | #endif |
||
322 | } |
||
323 | #endif |
||
324 | |||
325 | #endif |