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