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 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