1 #ifndef __MONSTERS_H
2 #define __MONSTERS_H
3 
4 /*
5 MONSTERS.H
6 
7 	Copyright (C) 1991-2001 and beyond by Bungie Studios, Inc.
8 	and the "Aleph One" developers.
9 
10 	This program is free software; you can redistribute it and/or modify
11 	it under the terms of the GNU General Public License as published by
12 	the Free Software Foundation; either version 3 of the License, or
13 	(at your option) any later version.
14 
15 	This program is distributed in the hope that it will be useful,
16 	but WITHOUT ANY WARRANTY; without even the implied warranty of
17 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 	GNU General Public License for more details.
19 
20 	This license is contained in the file "COPYING",
21 	which is included with this source code; it is available online at
22 	http://www.gnu.org/licenses/gpl.html
23 
24 Tuesday, June 28, 1994 7:07:59 PM
25 
26 Feb 3, 2000 (Loren Petrich):
27 	Added VacBobs
28 
29 Feb 6, 2000 (Loren Petrich):
30 	Added access to size of monster-definition structure
31 
32 Feb 10, 2000 (Loren Petrich):
33 	Added dynamic-limits setting of MAXIMUM_MONSTERS_PER_MAP
34 
35 Feb 19, 2000 (Loren Petrich):
36 	Added growable lists of indices of objects to be checked for collisions
37 
38 Aug 30, 2000 (Loren Petrich):
39 	Added stuff for unpacking and packing
40 
41 Oct 13, 2000 (Loren Petrich)
42 	Converted the intersected-objects list into a Standard Template Library vector
43 
44 Oct 24, 2000 (Mark Levin)
45 	Revealed some functions for P-tran
46 */
47 
48 // LP additions:
49 #include "dynamic_limits.h"
50 #include <vector>
51 
52 #include "world.h"
53 
54 using std::vector;
55 
56 /* ---------- constants */
57 
58 #define FLAMING_DEAD_SHAPE BUILD_DESCRIPTOR(_collection_rocket, 7)
59 #define FLAMING_DYING_SHAPE BUILD_DESCRIPTOR(_collection_rocket, 8)
60 
61 enum /* constants for activate_nearby_monsters */
62 {
63 	_pass_one_zone_border= 0x0001,
64 	_passed_zone_border= 0x0002,
65 	_activate_invisible_monsters= 0x0004, // sound or teleport trigger
66 	_activate_deaf_monsters= 0x0008, // i.e., trigger
67 	_pass_solid_lines= 0x0010, // i.e., not a sound (trigger)
68 	_use_activation_biases= 0x0020, // inactive monsters follow their editor instructions (trigger)
69 	_activation_cannot_be_avoided= 0x0040, // cannot be suppressed because of recent activation (trigger)
70 	_cannot_pass_superglue= 0x0080, // i.e., glue trigger
71 	_activate_glue_monsters= 0x0100 // glue trigger
72 };
73 
74 /* activation biases are only used when the monster is activated by a trigger */
75 enum /* activation biases (set in editor) */
76 {
77 	_activate_on_player,
78 	_activate_on_nearest_hostile,
79 	_activate_on_goal,
80 	_activate_randomly
81 };
82 
83 /* ---------- monsters */
84 
85 // LP change: made this settable from the resource fork
86 #define MAXIMUM_MONSTERS_PER_MAP (get_dynamic_limit(_dynamic_limit_monsters))
87 
88 /* player monsters are never active */
89 
90 #define MONSTER_IS_PLAYER(m) ((m)->type==_monster_marine)
91 enum /* monster types */
92 {
93 	_monster_marine,
94 	_monster_tick_energy,
95 	_monster_tick_oxygen,
96 	_monster_tick_kamakazi,
97 	_monster_compiler_minor,
98 	_monster_compiler_major,
99 	_monster_compiler_minor_invisible,
100 	_monster_compiler_major_invisible,
101 	_monster_fighter_minor,
102 	_monster_fighter_major,
103 	_monster_fighter_minor_projectile,
104 	_monster_fighter_major_projectile,
105 	_civilian_crew,
106 	_civilian_science,
107 	_civilian_security,
108 	_civilian_assimilated,
109 	_monster_hummer_minor, // slow hummer
110 	_monster_hummer_major, // fast hummer
111 	_monster_hummer_big_minor, // big hummer
112 	_monster_hummer_big_major, // angry hummer
113 	_monster_hummer_possessed, // hummer from durandal
114 	_monster_cyborg_minor,
115 	_monster_cyborg_major,
116 	_monster_cyborg_flame_minor,
117 	_monster_cyborg_flame_major,
118 	_monster_enforcer_minor,
119 	_monster_enforcer_major,
120 	_monster_hunter_minor,
121 	_monster_hunter_major,
122 	_monster_trooper_minor,
123 	_monster_trooper_major,
124 	_monster_mother_of_all_cyborgs,
125 	_monster_mother_of_all_hunters,
126 	_monster_sewage_yeti,
127 	_monster_water_yeti,
128 	_monster_lava_yeti,
129 	_monster_defender_minor,
130 	_monster_defender_major,
131 	_monster_juggernaut_minor,
132 	_monster_juggernaut_major,
133 	_monster_tiny_fighter,
134 	_monster_tiny_bob,
135 	_monster_tiny_yeti,
136 	// LP addition:
137 	_civilian_fusion_crew,
138 	_civilian_fusion_science,
139 	_civilian_fusion_security,
140 	_civilian_fusion_assimilated,
141 	NUMBER_OF_MONSTER_TYPES
142 };
143 
144 /* uses SLOT_IS_USED(), SLOT_IS_FREE(), MARK_SLOT_AS_FREE(), MARK_SLOT_AS_USED() macros (0x8000 bit) */
145 
146 #define MONSTER_NEEDS_PATH(m) ((m)->flags&(uint16)0x4000)
147 #define SET_MONSTER_NEEDS_PATH_STATUS(m,v) ((void)((v)?((m)->flags|=(uint16)0x4000):((m)->flags&=(uint16)~0x4000)))
148 
149 /* the recovering from hit flag is set randomly after a monster finishes his being-hit
150 	animation, and when set it prevents him from being immediately dragged into another
151 	being-hit animation.  this makes monsters twitch when being pinned down by a big gun,
152 	and allows them a small chance to react.  the flag is cleared every frame. */
153 #define MONSTER_RECOVERING_FROM_HIT(m) ((m)->flags&(uint16)0x2000)
154 #define CLEAR_MONSTER_RECOVERING_FROM_HIT(m) ((m)->flags&=(uint16)~0x2000)
155 #define SET_MONSTER_RECOVERING_FROM_HIT(m) ((m)->flags|=(uint16)0x2000)
156 
157 #define MONSTER_IS_ACTIVE(m) ((m)->flags&(uint16)0x1000)
158 #define SET_MONSTER_ACTIVE_STATUS(m,v) ((void)((v)?((m)->flags|=(uint16)0x1000):((m)->flags&=(uint16)~0x1000)))
159 
160 /* berserk monsters will only switch targets when their target dies and then choose the
161 	geometerically closest monster.  what sets this bit is still unclear.  */
162 #define MONSTER_IS_BERSERK(m) ((m)->flags&(uint16)0x0400)
163 #define SET_MONSTER_BERSERK_STATUS(m,v) ((void)((v)?((m)->flags|=(uint16)0x0400):((m)->flags&=(uint16)~0x0400)))
164 
165 #define MONSTER_IS_IDLE(m) ((m)->flags&(uint16)0x0800)
166 #define SET_MONSTER_IDLE_STATUS(m,v) ((void)((v)?((m)->flags|=(uint16)0x0800):((m)->flags&=(uint16)~0x0800)))
167 
168 /* this flag is set if our current target has inflicted damage on us (because if he hasn�t, we�ll
169 	probably go after somebody else if they hit us first) */
170 #define TARGET_HAS_DONE_DAMAGE(m) ((m)->flags&(uint16)0x0200)
171 #define CLEAR_TARGET_DAMAGE_FLAG(m) ((m)->flags&=(uint16)~0x0200)
172 #define SET_TARGET_DAMAGE_FLAG(m) ((m)->flags|=(uint16)0x0200)
173 
174 #define SET_MONSTER_HAS_BEEN_ACTIVATED(m) ((m)->flags&=(uint16)~_monster_has_never_been_activated)
175 
176 #define MONSTER_IS_BLIND(m) ((m)->flags&(uint16)_monster_is_blind)
177 #define MONSTER_IS_DEAF(m) ((m)->flags&(uint16)_monster_is_deaf)
178 #define MONSTER_TELEPORTS_OUT_WHEN_DEACTIVATED(m) ((m)->flags&(uint16)_monster_teleports_out_when_deactivated)
179 
180 #define MONSTER_IS_DYING(m) ((m)->action==_monster_is_dying_hard||(m)->action==_monster_is_dying_soft||(m)->action==_monster_is_dying_flaming)
181 #define MONSTER_IS_ATTACKING(m) ((m)->action==_monster_is_attacking_close||(m)->action==_monster_is_attacking_far)
182 #define MONSTER_IS_TELEPORTING(m) ((m)->action==_monster_is_teleporting)
183 enum /* monster actions */
184 {
185 	_monster_is_stationary,
186 	_monster_is_waiting_to_attack_again,
187 	_monster_is_moving,
188 	_monster_is_attacking_close, /* melee */
189 	_monster_is_attacking_far, /* ranged */
190 	_monster_is_being_hit,
191 	_monster_is_dying_hard,
192 	_monster_is_dying_soft,
193 	_monster_is_dying_flaming,
194 	_monster_is_teleporting, // transparent
195 	_monster_is_teleporting_in,
196 	_monster_is_teleporting_out,
197 	NUMBER_OF_MONSTER_ACTIONS
198 };
199 
200 #define MONSTER_IS_LOCKED(m) ((m)->mode==_monster_locked||(m)->mode==_monster_losing_lock)
201 #define MONSTER_HAS_VALID_TARGET(m) (MONSTER_IS_ACTIVE(m)&&MONSTER_IS_LOCKED(m))
202 enum /* monster modes */
203 {
204 	_monster_locked,
205 	_monster_losing_lock,
206 	_monster_lost_lock,
207 	_monster_unlocked,
208 	_monster_running,
209 	NUMBER_OF_MONSTER_MODES
210 };
211 
212 enum /* monster flags */
213 {
214 	_monster_was_promoted= 0x1,
215 	_monster_was_demoted= 0x2,
216 	_monster_has_never_been_activated= 0x4,
217 	_monster_is_blind= 0x8,
218 	_monster_is_deaf= 0x10,
219 	_monster_teleports_out_when_deactivated= 0x20
220 };
221 
222 struct monster_data /* 64 bytes */
223 {
224 	short type;
225 	short vitality; /* if ==NONE, will be properly initialized when the monster is first activated */
226 	uint16 flags; /* [slot_used.1] [need_path.1] [recovering_from_hit.1] [active.1] [idle.1] [berserk.1] [target_damage.1] [unused.6] [never_activated.1] [demoted.1] [promoted.1] */
227 
228 	short path; /* NONE is no path (the need path bit should be set in this case) */
229 	world_distance path_segment_length; /* distance until we�re through with this segment of the path */
230 	world_distance desired_height;
231 
232 	short mode, action;
233 	short target_index; /* a monster_index */
234 	world_distance external_velocity; /* per tick, in the direction -facing, only updated during hit/death animations */
235 	world_distance vertical_velocity; /* per tick, is rarely positive; absorbed immediately on contact with ground */
236 	short ticks_since_attack, attack_repetitions;
237 	short changes_until_lock_lost; /* number of times more the target can change polygons until _losing_lock becomes _lost_lock */
238 
239 	world_distance elevation; /* valid when attacking; z-component of projectile vector */
240 
241 	short object_index;
242 
243 	int32 ticks_since_last_activation;
244 
245 	short activation_bias;
246 
247 	short goal_polygon_index; // used instead of NONE when generating random paths
248 
249 	// copied from monster�s object every tick but updated with height
250 	world_point3d sound_location;
251 	short sound_polygon_index;
252 
253 	short random_desired_height;
254 
255 	short unused[7];
256 };
257 const int SIZEOF_monster_data = 64;
258 
259 const int SIZEOF_monster_definition = 156;
260 
261 /* ---------- globals */
262 
263 // Turned the list of active monsters into a variable array
264 
265 extern vector<monster_data> MonsterList;
266 #define monsters (MonsterList.data())
267 
268 // extern struct monster_data *monsters;
269 
270 /* ---------- prototypes/MONSTERS.C */
271 
272 void initialize_monsters(void);
273 void initialize_monsters_for_new_level(void); /* when a map is loaded */
274 
275 void move_monsters(void); /* assumes �t==1 tick */
276 
277 short new_monster(struct object_location *location, short monster_code);
278 void remove_monster(short monster_index);
279 
280 void activate_monster(short monster_index);
281 void deactivate_monster(short monster_index);
282 short find_closest_appropriate_target(short aggressor_index, bool full_circle);
283 
284 void mark_monster_collections(short type, bool loading);
285 void load_monster_sounds(short monster_type);
286 
287 void monster_moved(short target_index, short old_polygon_index);
288 short legal_monster_move(short monster_index, angle facing, world_point3d *new_location);
289 short legal_player_move(short monster_index, world_point3d *new_location, world_distance *object_floor);
290 
291 //ML: Revealed these function for Pfhortran
292 void change_monster_target(short monster_index, short target_index);
293 struct monster_definition *get_monster_definition_external(const short type);
294 
295 
296 // LP change: made these settable from the resource fork
297 // and used a growable list for the indices
298 #define LOCAL_INTERSECTING_MONSTER_BUFFER_SIZE (get_dynamic_limit(_dynamic_limit_local_collision))
299 #define GLOBAL_INTERSECTING_MONSTER_BUFFER_SIZE (get_dynamic_limit(_dynamic_limit_global_collision))
300 bool possible_intersecting_monsters(vector<short> *IntersectedObjectsPtr, unsigned maximum_object_count, short polygon_index, bool include_scenery);
301 #define monsters_nearby(polygon_index) possible_intersecting_monsters(0, 0, (polygon_index), false)
302 
303 void get_monster_dimensions(short monster_index, world_distance *radius, world_distance *height);
304 
305 void activate_nearby_monsters(short target_index, short caller_index, short flags, int32 max_range = -1);
306 
307 void damage_monsters_in_radius(short primary_target_index, short aggressor_index, short aggressor_type,
308 	world_point3d *epicenter, short epicenter_polygon_index, world_distance radius, struct damage_definition *damage, short projectile_index);
309 void damage_monster(short monster_index, short aggressor_index, short aggressor_type, world_point3d *epicenter, struct damage_definition *damage, short projectile_index);
310 
311 monster_data *get_monster_data(
312 	short monster_index);
313 
314 bool bump_monster(short aggressor_index, short monster_index);
315 
316 bool legal_polygon_height_change(short polygon_index, world_distance new_floor_height, world_distance new_ceiling_height, struct damage_definition *damage);
317 void adjust_monster_for_polygon_height_change(short monster_index, short polygon_index, world_distance new_floor_height, world_distance new_ceiling_height);
318 void accelerate_monster(short monster_index, angle direction, angle elevation, world_distance velocity);
319 
320 void monster_died(short target_index);
321 
322 short monster_placement_index(short monster_type);
323 short placement_index_to_monster_type(short placement_index);
324 void try_to_add_random_monster(short monster_type, bool activate);
325 
326 short get_monster_impact_effect(short monster_index);
327 short get_monster_melee_impact_effect(short monster_index);
328 
329 bool live_aliens_on_map(void);
330 
331 // LP: will set player view attributes when trying to shoot a guided projectile.
332 void SetPlayerViewAttribs(int16 half_visual_arc, int16 half_vertical_visual_arc,
333 	world_distance visual_range, world_distance dark_visual_range);
334 
335 
336 // LP: to pack and unpack this data;
337 // these do not make the definitions visible to the outside world
338 
339 uint8 *unpack_monster_data(uint8 *Stream, monster_data *Objects, size_t Count);
340 uint8 *pack_monster_data(uint8 *Stream, monster_data *Objects, size_t Count);
341 uint8 *unpack_monster_definition(uint8 *Stream, size_t Count);
342 uint8 *pack_monster_definition(uint8 *Stream, size_t Count);
343 uint8* unpack_m1_monster_definition(uint8* Stream, size_t Count);
344 void init_monster_definitions();
345 
346 class InfoTree;
347 void parse_mml_damage_kicks(const InfoTree& root);
348 void reset_mml_damage_kicks();
349 void parse_mml_monsters(const InfoTree& root);
350 void reset_mml_monsters();
351 
352 #endif
353