1 #ifndef __PLATFORMS_H 2 #define __PLATFORMS_H 3 4 /* 5 PLATFORMS.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 Friday, July 15, 1994 3:42:39 PM 25 26 Saturday, October 29, 1994 2:42:22 AM (Jason) 27 razed. 28 29 May 18, 2000 (Loren Petrich): 30 Added XML-parser support 31 */ 32 33 #include "map.h" 34 35 /* ---------- constants */ 36 37 // #define MAXIMUM_PLATFORMS_PER_MAP 64 38 39 enum /* platform types */ 40 { 41 _platform_is_spht_door, 42 _platform_is_spht_split_door, 43 _platform_is_locked_spht_door, 44 _platform_is_spht_platform, 45 _platform_is_noisy_spht_platform, 46 _platform_is_heavy_spht_door, 47 _platform_is_pfhor_door, 48 _platform_is_heavy_spht_platform, 49 _platform_is_pfhor_platform, 50 51 NUMBER_OF_PLATFORM_TYPES 52 }; 53 54 enum /* platform speeds */ 55 { 56 _very_slow_platform= WORLD_ONE/(4*TICKS_PER_SECOND), 57 _slow_platform= WORLD_ONE/(2*TICKS_PER_SECOND), 58 _fast_platform= 2*_slow_platform, 59 _very_fast_platform= 3*_slow_platform, 60 _blindingly_fast_platform= 4*_slow_platform 61 }; 62 63 enum /* platform delays */ 64 { 65 _no_delay_platform= 0, /* use carefully; difficult to reincarnate on */ 66 _short_delay_platform= TICKS_PER_SECOND, 67 _long_delay_platform= 2*TICKS_PER_SECOND, 68 _very_long_delay_platform= 4*TICKS_PER_SECOND, 69 _extremely_long_delay_platform= 8*TICKS_PER_SECOND 70 }; 71 72 enum /* static platform flags */ 73 { 74 _platform_is_initially_active, /* otherwise inactive */ 75 _platform_is_initially_extended, /* high for floor platforms, low for ceiling platforms, closed for two-way platforms */ 76 _platform_deactivates_at_each_level, /* this platform will deactivate each time it reaches a discrete level */ 77 _platform_deactivates_at_initial_level, /* this platform will deactivate upon returning to its original position */ 78 _platform_activates_adjacent_platforms_when_deactivating, /* when deactivating, this platform activates adjacent platforms */ 79 _platform_extends_floor_to_ceiling, /* i.e., there is no empty space when the platform is fully extended */ 80 _platform_comes_from_floor, /* platform rises from floor */ 81 _platform_comes_from_ceiling, /* platform lowers from ceiling */ 82 _platform_causes_damage, /* when obstructed by monsters, this platform causes damage */ 83 _platform_does_not_activate_parent, /* does not reactive it�s parent (i.e., that platform which activated it) */ 84 _platform_activates_only_once, /* cannot be activated a second time */ 85 _platform_activates_light, /* activates floor and ceiling lightsources while activating */ 86 _platform_deactivates_light, /* deactivates floor and ceiling lightsources while deactivating */ 87 _platform_is_player_controllable, /* i.e., door: players can use action key to change the state and/or direction of this platform */ 88 _platform_is_monster_controllable, /* i.e., door: monsters can expect to be able to move this platform even if inactive */ 89 _platform_reverses_direction_when_obstructed, 90 _platform_cannot_be_externally_deactivated, /* when active, can only be deactivated by itself */ 91 _platform_uses_native_polygon_heights, /* complicated interpretation; uses native polygon heights during automatic min,max calculation */ 92 _platform_delays_before_activation, /* whether or not the platform begins with the maximum delay before moving */ 93 _platform_activates_adjacent_platforms_when_activating, 94 _platform_deactivates_adjacent_platforms_when_activating, 95 _platform_deactivates_adjacent_platforms_when_deactivating, 96 _platform_contracts_slower, 97 _platform_activates_adjacent_platforms_at_each_level, 98 _platform_is_locked, 99 _platform_is_secret, 100 _platform_is_door, 101 _platform_floods_m1, 102 NUMBER_OF_STATIC_PLATFORM_FLAGS /* <=32 */ 103 }; 104 105 #define PLATFORM_IS_INITIALLY_ACTIVE(p) TEST_FLAG32((p)->static_flags, _platform_is_initially_active) 106 #define PLATFORM_IS_INITIALLY_EXTENDED(p) TEST_FLAG32((p)->static_flags, _platform_is_initially_extended) 107 #define PLATFORM_IS_INITIALLY_CONTRACTED(p) (!PLATFORM_IS_INITIALLY_EXTENDED(p)) 108 #define PLATFORM_EXTENDS_FLOOR_TO_CEILING(p) TEST_FLAG32((p)->static_flags, _platform_extends_floor_to_ceiling) 109 #define PLATFORM_COMES_FROM_FLOOR(p) TEST_FLAG32((p)->static_flags, _platform_comes_from_floor) 110 #define PLATFORM_COMES_FROM_CEILING(p) TEST_FLAG32((p)->static_flags, _platform_comes_from_ceiling) 111 #define PLATFORM_GOES_BOTH_WAYS(p) (PLATFORM_COMES_FROM_FLOOR(p)&&PLATFORM_COMES_FROM_CEILING(p)) 112 #define PLATFORM_CAUSES_DAMAGE(p) TEST_FLAG32((p)->static_flags, _platform_causes_damage) 113 #define PLATFORM_REVERSES_DIRECTION_WHEN_OBSTRUCTED(p) TEST_FLAG32((p)->static_flags, _platform_reverses_direction_when_obstructed) 114 #define PLATFORM_ACTIVATES_ONLY_ONCE(p) TEST_FLAG32((p)->static_flags, _platform_activates_only_once) 115 #define PLATFORM_ACTIVATES_ADJACENT_PLATFORMS_WHEN_DEACTIVATING(p) TEST_FLAG32((p)->static_flags, _platform_activates_adjacent_platforms_when_deactivating) 116 #define PLATFORM_ACTIVATES_LIGHT(p) TEST_FLAG32((p)->static_flags, _platform_activates_light) 117 #define PLATFORM_DEACTIVATES_LIGHT(p) TEST_FLAG32((p)->static_flags, _platform_deactivates_light) 118 #define PLATFORM_DEACTIVATES_AT_EACH_LEVEL(p) TEST_FLAG32((p)->static_flags, _platform_deactivates_at_each_level) 119 #define PLATFORM_DEACTIVATES_AT_INITIAL_LEVEL(p) TEST_FLAG32((p)->static_flags, _platform_deactivates_at_initial_level) 120 #define PLATFORM_DOES_NOT_ACTIVATE_PARENT(p) TEST_FLAG32((p)->static_flags, _platform_does_not_activate_parent) 121 #define PLATFORM_IS_PLAYER_CONTROLLABLE(p) TEST_FLAG32((p)->static_flags, _platform_is_player_controllable) 122 #define PLATFORM_IS_MONSTER_CONTROLLABLE(p) TEST_FLAG32((p)->static_flags, _platform_is_monster_controllable) 123 #define PLATFORM_CANNOT_BE_EXTERNALLY_DEACTIVATED(p) TEST_FLAG32((p)->static_flags, _platform_cannot_be_externally_deactivated) 124 #define PLATFORM_USES_NATIVE_POLYGON_HEIGHTS(p) TEST_FLAG32((p)->static_flags, _platform_uses_native_polygon_heights) 125 #define PLATFORM_DELAYS_BEFORE_ACTIVATION(p) TEST_FLAG32((p)->static_flags, _platform_delays_before_activation) 126 #define PLATFORM_ACTIVATES_ADJACENT_PLATFORMS_WHEN_ACTIVATING(p) TEST_FLAG32((p)->static_flags, _platform_activates_adjacent_platforms_when_activating) 127 #define PLATFORM_DEACTIVATES_ADJACENT_PLATFORMS_WHEN_ACTIVATING(p) TEST_FLAG32((p)->static_flags, _platform_deactivates_adjacent_platforms_when_activating) 128 #define PLATFORM_DEACTIVATES_ADJACENT_PLATFORMS_WHEN_DEACTIVATING(p) TEST_FLAG32((p)->static_flags, _platform_deactivates_adjacent_platforms_when_deactivating) 129 #define PLATFORM_CONTRACTS_SLOWER(p) TEST_FLAG32((p)->static_flags, _platform_contracts_slower) 130 #define PLATFORM_ACTIVATES_ADJACENT_PLATFORMS_AT_EACH_LEVEL(p) TEST_FLAG32((p)->static_flags, _platform_activates_adjacent_platforms_at_each_level) 131 #define PLATFORM_IS_LOCKED(p) TEST_FLAG32((p)->static_flags, _platform_is_locked) 132 #define PLATFORM_IS_SECRET(p) TEST_FLAG32((p)->static_flags, _platform_is_secret) 133 #define PLATFORM_IS_DOOR(p) TEST_FLAG32((p)->static_flags, _platform_is_door) 134 #define PLATFORM_FLOODS_M1(p) TEST_FLAG32((p)->static_flags, _platform_floods_m1) 135 136 #define SET_PLATFORM_IS_INITIALLY_ACTIVE(p, v) SET_FLAG32((p)->static_flags, _platform_is_initially_active, (v)) 137 #define SET_PLATFORM_IS_INITIALLY_EXTENDED(p, v) SET_FLAG32((p)->static_flags, _platform_is_initially_extended, (v)) 138 #define SET_PLATFORM_EXTENDS_FLOOR_TO_CEILING(p, v) SET_FLAG32((p)->static_flags, _platform_extends_floor_to_ceiling, (v)) 139 #define SET_PLATFORM_COMES_FROM_FLOOR(p, v) SET_FLAG32((p)->static_flags, _platform_comes_from_floor, (v)) 140 #define SET_PLATFORM_COMES_FROM_CEILING(p, v) SET_FLAG32((p)->static_flags, _platform_comes_from_ceiling, (v)) 141 #define SET_PLATFORM_CAUSES_DAMAGE(p, v) SET_FLAG32((p)->static_flags, _platform_causes_damage, (v)) 142 #define SET_PLATFORM_REVERSES_DIRECTION_WHEN_OBSTRUCTED(p, v) SET_FLAG32((p)->static_flags, _platform_reverses_direction_when_obstructed, (v)) 143 #define SET_PLATFORM_ACTIVATES_ONLY_ONCE(p, v) SET_FLAG32((p)->static_flags, _platform_activates_only_once, (v)) 144 #define SET_PLATFORM_ACTIVATES_ADJACENT_PLATFORMS_WHEN_DEACTIVATING(p, v) SET_FLAG32((p)->static_flags, _platform_activates_adjacent_platforms_when_deactivating, (v)) 145 #define SET_PLATFORM_ACTIVATES_LIGHT(p, v) SET_FLAG32((p)->static_flags, _platform_activates_light, (v)) 146 #define SET_PLATFORM_DEACTIVATES_LIGHT(p, v) SET_FLAG32((p)->static_flags, _platform_deactivates_light, (v)) 147 #define SET_PLATFORM_DEACTIVATES_AT_EACH_LEVEL(p, v) SET_FLAG32((p)->static_flags, _platform_deactivates_at_each_level, (v)) 148 #define SET_PLATFORM_DEACTIVATES_AT_INITIAL_LEVEL(p, v) SET_FLAG32((p)->static_flags, _platform_deactivates_at_initial_level, (v)) 149 #define SET_PLATFORM_DOES_NOT_ACTIVATE_PARENT(p, v) SET_FLAG32((p)->static_flags, _platform_does_not_activate_parent, (v)) 150 #define SET_PLATFORM_IS_PLAYER_CONTROLLABLE(p, v) SET_FLAG32((p)->static_flags, _platform_is_player_controllable, (v)) 151 #define SET_PLATFORM_IS_MONSTER_CONTROLLABLE(p, v) SET_FLAG32((p)->static_flags, _platform_is_monster_controllable, (v)) 152 #define SET_PLATFORM_CANNOT_BE_EXTERNALLY_DEACTIVATED(p, v) SET_FLAG32((p)->static_flags, _platform_cannot_be_externally_deactivated, (v)) 153 #define SET_PLATFORM_USES_NATIVE_POLYGON_HEIGHTS(p, v) SET_FLAG32((p)->static_flags, _platform_uses_native_polygon_heights, (v)) 154 #define SET_PLATFORM_DELAYS_BEFORE_ACTIVATION(p, v) SET_FLAG32((p)->static_flags, _platform_delays_before_activation, (v)) 155 #define SET_PLATFORM_ACTIVATES_ADJACENT_PLATFORMS_WHEN_ACTIVATING(p, v) SET_FLAG32((p)->static_flags, _platform_activates_adjacent_platforms_when_activating, (v)) 156 #define SET_PLATFORM_DEACTIVATES_ADJACENT_PLATFORMS_WHEN_ACTIVATING(p, v) SET_FLAG32((p)->static_flags, _platform_deactivates_adjacent_platforms_when_activating, (v)) 157 #define SET_PLATFORM_DEACTIVATES_ADJACENT_PLATFORMS_WHEN_DEACTIVATING(p, v) SET_FLAG32((p)->static_flags, _platform_deactivates_adjacent_platforms_when_deactivating, (v)) 158 #define SET_PLATFORM_CONTRACTS_SLOWER(p, v) SET_FLAG32((p)->static_flags, _platform_contracts_slower, (v)) 159 #define SET_PLATFORM_ACTIVATES_ADJACENT_PLATFORMS_AT_EACH_LEVEL(p, v) SET_FLAG32((p)->static_flags, _platform_activates_adjacent_platforms_at_each_level, (v)) 160 #define SET_PLATFORM_IS_LOCKED(p, v) SET_FLAG32((p)->static_flags, _platform_is_locked, (v)) 161 #define SET_PLATFORM_IS_SECRET(p, v) SET_FLAG32((p)->static_flags, _platform_is_secret, (v)) 162 #define SET_PLATFORM_IS_DOOR(p, v) SET_FLAG32((p)->static_flags, _platform_is_door, (v)) 163 #define SET_PLATFORM_FLOODS_M1(p, v) SET_FLAG32((p)->static_flags, _platform_floods_m1, (v)) 164 165 enum /* dynamic platform flags */ 166 { 167 _platform_is_active, /* otherwise inactive */ 168 _platform_is_extending, /* otherwise contracting; could be waiting between levels */ 169 _platform_is_moving, /* otherwise at rest (waiting between levels) */ 170 _platform_has_been_activated, /* in case we can only be activated once */ 171 _platform_was_moving, /* the platform moved unobstructed last tick */ 172 _platform_is_fully_extended, 173 _platform_is_fully_contracted, 174 _platform_was_just_activated_or_deactivated, 175 _platform_floor_below_media, 176 _platform_ceiling_below_media, 177 NUMBER_OF_DYNAMIC_PLATFORM_FLAGS /* <=16 */ 178 }; 179 180 #define PLATFORM_IS_ACTIVE(p) TEST_FLAG16((p)->dynamic_flags, _platform_is_active) 181 #define PLATFORM_IS_EXTENDING(p) TEST_FLAG16((p)->dynamic_flags, _platform_is_extending) 182 #define PLATFORM_IS_CONTRACTING(p) (!PLATFORM_IS_EXTENDING(p)) 183 #define PLATFORM_IS_MOVING(p) TEST_FLAG16((p)->dynamic_flags, _platform_is_moving) 184 #define PLATFORM_HAS_BEEN_ACTIVATED(p) TEST_FLAG16((p)->dynamic_flags, _platform_has_been_activated) 185 #define PLATFORM_WAS_MOVING(p) TEST_FLAG16((p)->dynamic_flags, _platform_was_moving) 186 #define PLATFORM_IS_FULLY_EXTENDED(p) TEST_FLAG16((p)->dynamic_flags, _platform_is_fully_extended) 187 #define PLATFORM_IS_FULLY_CONTRACTED(p) TEST_FLAG16((p)->dynamic_flags, _platform_is_fully_contracted) 188 #define PLATFORM_WAS_JUST_ACTIVATED_OR_DEACTIVATED(p) TEST_FLAG16((p)->dynamic_flags, _platform_was_just_activated_or_deactivated) 189 #define PLATFORM_FLOOR_BELOW_MEDIA(p) TEST_FLAG16((p)->dynamic_flags, _platform_floor_below_media) 190 #define PLATFORM_CEILING_BELOW_MEDIA(p) TEST_FLAG16((p)->dynamic_flags, _platform_ceiling_below_media) 191 192 #define SET_PLATFORM_IS_ACTIVE(p, v) SET_FLAG16((p)->dynamic_flags, _platform_is_active, (v)) 193 #define SET_PLATFORM_IS_EXTENDING(p) SET_FLAG16((p)->dynamic_flags, _platform_is_extending, true) 194 #define SET_PLATFORM_IS_CONTRACTING(p) SET_FLAG16((p)->dynamic_flags, _platform_is_extending, false) 195 #define SET_PLATFORM_IS_MOVING(p, v) SET_FLAG16((p)->dynamic_flags, _platform_is_moving, (v)) 196 #define SET_PLATFORM_HAS_BEEN_ACTIVATED(p) SET_FLAG16((p)->dynamic_flags, _platform_has_been_activated, true) 197 #define SET_PLATFORM_WAS_MOVING(p) SET_FLAG16((p)->dynamic_flags, _platform_was_moving, true) 198 #define SET_PLATFORM_WAS_BLOCKED(p) SET_FLAG16((p)->dynamic_flags, _platform_was_moving, false) 199 #define SET_PLATFORM_IS_FULLY_EXTENDED(p) SET_FLAG16((p)->dynamic_flags, _platform_is_fully_extended, true) 200 #define SET_PLATFORM_IS_FULLY_CONTRACTED(p) SET_FLAG16((p)->dynamic_flags, _platform_is_fully_contracted, true) 201 #define CLEAR_PLATFORM_POSITIONING_FLAGS(p) SET_FLAG16((p)->dynamic_flags, _platform_is_fully_contracted, false), SET_FLAG16((p)->dynamic_flags, _platform_is_fully_extended, false) 202 #define SET_PLATFORM_WAS_JUST_ACTIVATED_OR_DEACTIVATED(p) SET_FLAG16((p)->dynamic_flags, _platform_was_just_activated_or_deactivated, true) 203 #define CLEAR_PLATFORM_WAS_JUST_ACTIVATED_OR_DEACTIVATED(p) SET_FLAG16((p)->dynamic_flags, _platform_was_just_activated_or_deactivated, false) 204 #define SET_PLATFORM_FLOOR_BELOW_MEDIA(p, v) SET_FLAG16((p)->dynamic_flags, _platform_floor_below_media, v) 205 #define SET_PLATFORM_CEILING_BELOW_MEDIA(p, v) SET_FLAG16((p)->dynamic_flags, _platform_ceiling_below_media, v) 206 207 // using "fully contracted" is close enough to act like Marathon... I hope 208 #define PLATFORM_IS_FLOODED(p) (PLATFORM_FLOODS_M1(p) && PLATFORM_IS_FULLY_CONTRACTED(p)) 209 210 struct endpoint_owner_data 211 { 212 int16 first_polygon_index, polygon_index_count; 213 int16 first_line_index, line_index_count; 214 }; 215 216 struct static_platform_data /* size platform-dependant */ 217 { 218 int16 type; 219 int16 speed, delay; 220 world_distance maximum_height, minimum_height; /* if NONE then calculated in some reasonable way */ 221 222 uint32 static_flags; 223 224 int16 polygon_index; 225 226 int16 tag; 227 228 int16 unused[7]; 229 }; 230 const int SIZEOF_static_platform_data = 32; 231 232 struct platform_data /* 140 bytes */ 233 { 234 int16 type; 235 uint32 static_flags; 236 int16 speed, delay; 237 world_distance minimum_floor_height, maximum_floor_height; 238 world_distance minimum_ceiling_height, maximum_ceiling_height; 239 240 int16 polygon_index; 241 242 uint16 dynamic_flags; 243 world_distance floor_height, ceiling_height; 244 int16 ticks_until_restart; /* if we�re not moving but are active, this is our delay until we move again */ 245 246 struct endpoint_owner_data endpoint_owners[MAXIMUM_VERTICES_PER_POLYGON]; 247 248 int16 parent_platform_index; /* the platform_index which activated us, if any */ 249 250 int16 tag; 251 252 int16 unused[22]; 253 }; 254 const int SIZEOF_platform_data = 140; 255 256 /* --------- globals */ 257 258 // Turned the list of platforms into a variable array; 259 // took over their maximum number as how many of them 260 261 extern vector<platform_data> PlatformList; 262 #define platforms (PlatformList.data()) 263 #define MAXIMUM_PLATFORMS_PER_MAP (PlatformList.size()) 264 265 // extern struct platform_data *platforms; 266 267 /* --------- prototypes/PLATFORMS.C */ 268 269 short new_platform(struct static_platform_data *data, short polygon_index, short version); 270 struct static_platform_data *get_defaults_for_platform_type(short type); 271 272 void update_platforms(void); 273 274 void platform_was_entered(short platform_index, bool player); 275 276 bool try_and_change_platform_state(short platform_index, bool state); 277 bool try_and_change_tagged_platform_states(short tag, bool state); 278 279 enum /* return values from monster_can_enter_platform() and monster_can_leave_platform() */ 280 { 281 _platform_will_never_be_accessable, 282 _platform_will_be_accessable, 283 _platform_might_be_accessable, 284 _platform_is_accessable, 285 286 _exit_will_never_be_accessable, 287 _exit_will_be_accessable, 288 _exit_might_be_accessable, 289 _exit_is_accessable 290 }; 291 short monster_can_enter_platform(short platform_index, short source_polygon_index, world_distance height, world_distance minimum_ledge_delta, world_distance maximum_ledge_delta); 292 short monster_can_leave_platform(short platform_index, short destination_polygon_index, world_distance height, world_distance minimum_ledge_delta, world_distance maximum_ledge_delta); 293 294 bool platform_is_on(short platform_index); 295 296 void adjust_platform_for_media(short platform_index, bool initialize); 297 void adjust_platform_endpoint_and_line_heights(short platform_index); 298 299 void player_touch_platform_state(short player_index, short platform_index); 300 bool platform_is_legal_player_target(short platform_index); 301 302 bool platform_is_at_initial_state(short platform_index); 303 304 short get_platform_moving_sound(short platform_index); 305 306 platform_data *get_platform_data( 307 short platform_index); 308 309 // LP: to pack and unpack this data; 310 // these do not make the definitions visible to the outside world 311 312 uint8 *unpack_static_platform_data(uint8 *Stream, static_platform_data *Objects, size_t Count); 313 uint8 *pack_static_platform_data(uint8 *Stream, static_platform_data *Objects, size_t Count); 314 uint8 *unpack_platform_data(uint8 *Stream, platform_data *Objects, size_t Count); 315 uint8 *pack_platform_data(uint8 *Stream, platform_data *Objects, size_t Count); 316 317 class InfoTree; 318 void parse_mml_platforms(const InfoTree& root); 319 void reset_mml_platforms(); 320 321 #endif 322