1 #ifndef __MAP_H
2 #define __MAP_H
3 
4 /*
5 MAP.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 Sunday, August 15, 1993 12:11:35 PM
25 
26 Feb 10, 2000 (Loren Petrich):
27 	Added dynamic-limits setting of MAXIMUM_OBJECTS_PER_MAP
28 
29 Jul 1, 2000 (Loren Petrich):
30 	Made all the accessors inline
31 
32 [Loren Petrich: notes moved here]
33 MAP_ACCESSORS.C
34 Friday, June 3, 1994 12:10:10 PM
35 
36 Thursday, June 16, 1994 7:32:13 PM
37 	if DEBUG is defined, this file is empty.
38 
39 Jul 1, 2000 (Loren Petrich):
40 	moved all its contens out to map.h
41 [End moved notes]
42 
43 Aug 29, 2000 (Loren Petrich):
44 	Created packing and unpacking functions for all the
45 		externally-accessible data types defined here
46 
47 Nov 19, 2000 (Loren Petrich):
48 	Added XML support for texture-loading control
49 
50  June 14, 2003 (Woody Zenfell):
51 	New functions for manipulating polygons' object lists (in support of prediction).
52 	New return type for update_world(), since now we might need rerendering even if
53 		no real ticks have elapsed (we may have predicted ahead further).
54 */
55 
56 #include "csmacros.h"
57 #include "world.h"
58 #include "dynamic_limits.h"
59 
60 #include <vector>
61 
62 using std::vector;
63 
64 /* ---------- constants */
65 
66 #define TICKS_PER_SECOND 30
67 #define TICKS_PER_MINUTE (60*TICKS_PER_SECOND)
68 
69 #define MAP_INDEX_BUFFER_SIZE 8192
70 #define MINIMUM_SEPARATION_FROM_WALL (WORLD_ONE/4)
71 #define MINIMUM_SEPARATION_FROM_PROJECTILE ((3*WORLD_ONE)/4)
72 
73 #define TELEPORTING_DURATION (2*TELEPORTING_MIDPOINT)
74 #define TELEPORTING_MIDPOINT (TICKS_PER_SECOND/2)
75 
76 /* These arrays are the absolute limits, and are used only by the small memory allocating */
77 /*  arrays.  */
78 #define MAXIMUM_LEVELS_PER_MAP (128)
79 
80 #define LEVEL_NAME_LENGTH (64+2)
81 
82 /* ---------- shape descriptors */
83 
84 #include "shape_descriptors.h"
85 
86 /* ---------- damage */
87 
88 enum /* damage types */
89 {
90 	_damage_explosion,
91 	_damage_electrical_staff,
92 	_damage_projectile,
93 	_damage_absorbed,
94 	_damage_flame,
95 	_damage_hound_claws,
96 	_damage_alien_projectile,
97 	_damage_hulk_slap,
98 	_damage_compiler_bolt,
99 	_damage_fusion_bolt,
100 	_damage_hunter_bolt,
101 	_damage_fist,
102 	_damage_teleporter,
103 	_damage_defender,
104 	_damage_yeti_claws,
105 	_damage_yeti_projectile,
106 	_damage_crushing,
107 	_damage_lava,
108 	_damage_suffocation,
109 	_damage_goo,
110 	_damage_energy_drain,
111 	_damage_oxygen_drain,
112 	_damage_hummer_bolt,
113 	_damage_shotgun_projectile,
114 	NUMBER_OF_DAMAGE_TYPES
115 };
116 
117 enum /* damage flags */
118 {
119 	_alien_damage= 0x1 /* will be decreased at lower difficulty levels */
120 };
121 
122 struct damage_definition
123 {
124 	int16 type, flags;
125 
126 	int16 base, random;
127 	_fixed scale;
128 };
129 const int SIZEOF_damage_definition = 12;
130 
131 /* ---------- saved objects (initial map locations, etc.) */
132 
133 // #define MAXIMUM_SAVED_OBJECTS 384
134 
135 enum /* map object types */
136 {
137 	_saved_monster,	/* .index is monster type */
138 	_saved_object,	/* .index is scenery type */
139 	_saved_item,	/* .index is item type */
140 	_saved_player,	/* .index is team bitfield */
141 	_saved_goal,	/* .index is goal number */
142 	_saved_sound_source /* .index is source type, .facing is sound volume */
143 };
144 
145 enum /* map object flags */
146 {
147 	_map_object_is_invisible= 0x0001, /* initially invisible */
148 	_map_object_is_platform_sound= 0x0001,
149 	_map_object_hanging_from_ceiling= 0x0002, /* used for calculating absolute .z coordinate */
150 	_map_object_is_blind= 0x0004, /* monster cannot activate by sight */
151 	_map_object_is_deaf= 0x0008, /* monster cannot activate by sound */
152 	_map_object_floats= 0x0010, /* used by sound sources caused by media */
153 	_map_object_is_network_only= 0x0020 /* for items only */
154 
155 	// top four bits is activation bias for monsters
156 };
157 
158 #define DECODE_ACTIVATION_BIAS(f) ((f)>>12)
159 #define ENCODE_ACTIVATION_BIAS(b) ((b)<<12)
160 
161 struct map_object /* 16 bytes */
162 {
163 	int16 type; /* _saved_monster, _saved_object, _saved_item, ... */
164 	int16 index;
165 	int16 facing;
166 	int16 polygon_index;
167 	world_point3d location; // .z is a delta
168 
169 	uint16 flags;
170 };
171 const int SIZEOF_map_object = 16;
172 
173 // Due to misalignments, these have different sizes
174 typedef world_point2d saved_map_pt;
175 typedef struct line_data saved_line;
176 typedef struct polygon_data saved_poly;
177 typedef struct map_annotation saved_annotation;
178 typedef struct map_object saved_object;
179 typedef struct static_data saved_map_data;
180 
181 /* ---------- map loading/new game structures */
182 
183 enum { /* entry point types- this is per map level (int32). */
184 	_single_player_entry_point= 0x01,
185 	_multiplayer_cooperative_entry_point= 0x02,
186 	_multiplayer_carnage_entry_point= 0x04,
187 	_kill_the_man_with_the_ball_entry_point = 0x08, // was _capture_the_flag_entry_point, even though Bungie used it for KTMWTB
188 	_king_of_hill_entry_point= 0x10,
189 	_defense_entry_point= 0x20,
190 	_rugby_entry_point= 0x40,
191 	_capture_the_flag_entry_point = 0x80
192 };
193 
194 struct entry_point
195 {
196 	int16 level_number;
197 	char level_name[64+2];
198 };
199 
200 #define MAXIMUM_PLAYER_START_NAME_LENGTH 32
201 
202 struct player_start_data
203 {
204 	int16 team;
205 	int16 identifier; /* [weapon_switch_flag.1] [UNUSED.1] [identifier.14] */
206 	int16 color;
207 	char name[MAXIMUM_PLAYER_START_NAME_LENGTH+1]; /* PLAYER_NAME_LENGTH+1 */
208 };
209 
210 enum {
211 	_player_start_doesnt_auto_switch_weapons_flag= 0x8000
212 };
213 
214 const uint16 player_start_identifier_mask = (1<<14) - 1;
215 
216 int16 player_identifier_value(int16 identifier);
217 int16 player_start_identifier_value(const player_start_data * const p);
218 bool player_identifier_doesnt_auto_switch_weapons(int16 identifier);
219 bool player_start_doesnt_auto_switch_Weapons(const player_start_data * const p);
220 void set_player_start_doesnt_auto_switch_weapons_status(player_start_data * const p, bool v);
221 
222 /* inline definitions for relevant player_start_data flags */
player_identifier_value(int16 identifier)223 inline int16 player_identifier_value(int16 identifier)
224 { return identifier & player_start_identifier_mask; }
225 
player_start_identifier_value(const player_start_data * const p)226 inline int16 player_start_identifier_value(const player_start_data * const p)
227 { return (p)->identifier & player_start_identifier_mask; }
228 
player_identifier_doesnt_auto_switch_weapons(int16 identifier)229 inline bool player_identifier_doesnt_auto_switch_weapons(int16 identifier)
230 { return TEST_FLAG(identifier, _player_start_doesnt_auto_switch_weapons_flag); }
231 
player_start_doesnt_auto_switch_Weapons(const player_start_data * const p)232 inline bool player_start_doesnt_auto_switch_Weapons(const player_start_data * const p)
233 { return TEST_FLAG(p->identifier, _player_start_doesnt_auto_switch_weapons_flag); }
234 
set_player_start_doesnt_auto_switch_weapons_status(player_start_data * const p,bool v)235 inline void set_player_start_doesnt_auto_switch_weapons_status(player_start_data * const p, bool v)
236 {	SET_FLAG(p->identifier, _player_start_doesnt_auto_switch_weapons_flag, v); }
237 /* end - inline definitions for relevant player_start_data flags */
238 
239 struct directory_data {
240 	int16 mission_flags;
241 	int16 environment_flags;
242 	int32 entry_point_flags;
243 	char level_name[LEVEL_NAME_LENGTH];
244 };
245 const int SIZEOF_directory_data = 74;
246 
247 /* ---------- map annotations */
248 
249 // #define MAXIMUM_ANNOTATIONS_PER_MAP 20
250 #define MAXIMUM_ANNOTATION_TEXT_LENGTH 64
251 
252 struct map_annotation
253 {
254 	int16 type; /* turns into color, font, size, style, etc... */
255 
256 	world_point2d location; /* where to draw this (lower left) */
257 	int16 polygon_index; /* only displayed if this polygon is in the automap */
258 
259 	char text[MAXIMUM_ANNOTATION_TEXT_LENGTH];
260 };
261 const int SIZEOF_map_annotation = 72;
262 
263 struct map_annotation *get_next_map_annotation(int16 *count);
264 
265 /* ---------- ambient sound images */
266 
267 // #define MAXIMUM_AMBIENT_SOUND_IMAGES_PER_MAP 64
268 
269 // non-directional ambient component
270 struct ambient_sound_image_data // 16 bytes
271 {
272 	uint16 flags;
273 
274 	int16 sound_index;
275 	int16 volume;
276 
277 	int16 unused[5];
278 };
279 const int SIZEOF_ambient_sound_image_data = 16;
280 
281 /* ---------- random sound images */
282 
283 // #define MAXIMUM_RANDOM_SOUND_IMAGES_PER_MAP 64
284 
285 enum // sound image flags
286 {
287 	_sound_image_is_non_directional= 0x0001 // ignore direction
288 };
289 
290 // possibly directional random sound effects
291 struct random_sound_image_data // 32 bytes
292 {
293 	uint16 flags;
294 
295 	int16 sound_index;
296 
297 	int16 volume, delta_volume;
298 	int16 period, delta_period;
299 	angle direction, delta_direction;
300 	_fixed pitch, delta_pitch;
301 
302 	// only used at run-time; initialize to NONE
303 	int16 phase;
304 
305 	int16 unused[3];
306 };
307 const int SIZEOF_random_sound_image_data = 32;
308 
309 /* ---------- object structure */
310 // LP change: made this settable from the resource fork
311 #define MAXIMUM_OBJECTS_PER_MAP (get_dynamic_limit(_dynamic_limit_objects))
312 
313 /* SLOT_IS_USED(), SLOT_IS_FREE(), MARK_SLOT_AS_FREE(), MARK_SLOT_AS_USED() macros are also used
314 	for monsters, effects and projectiles */
315 #define SLOT_IS_USED(o) ((o)->flags&(uint16)0x8000)
316 #define SLOT_IS_FREE(o) (!SLOT_IS_USED(o))
317 #define MARK_SLOT_AS_FREE(o) ((o)->flags&=(uint16)~0x8000)
318 #define MARK_SLOT_AS_USED(o) ((o)->flags|=(uint16)0x8000)
319 
320 #define OBJECT_WAS_RENDERED(o) ((o)->flags&(uint16)0x4000)
321 #define SET_OBJECT_RENDERED_FLAG(o) ((o)->flags|=(uint16)0x4000)
322 #define CLEAR_OBJECT_RENDERED_FLAG(o) ((o)->flags&=(uint16)~0x4000)
323 
324 /* this field is only valid after transmogrify_object_shape is called; in terms of our pipeline, that
325 	means that it�s only valid if OBJECT_WAS_RENDERED returns true *and* was cleared before
326 	the last call to render_scene() ... this means that if OBJECT_WAS_RENDERED returns false,
327 	the monster and projectile managers will probably call transmogrif_object_shape themselves.
328 	for reasons beyond this scope of this comment to explain, the keyframe cannot be frame zero!
329 	also, when any of the flags below are set, the phase of the .sequence field can be examined
330 	to determine exactly how many ticks the last frame took to animate (that is, .sequence.phase
331 	is not reset until the next loop). */
332 #define OBJECT_WAS_ANIMATED(o) ((o)->flags&(uint16)_obj_animated)
333 #define GET_OBJECT_ANIMATION_FLAGS(o) ((o)->flags&(uint16)0x3c00)
334 #define SET_OBJECT_ANIMATION_FLAGS(o,n) { (o)->flags&= (uint16)~0x3c00; (o)->flags|= (n); }
335 enum /* object was animated flags */
336 {
337 	_obj_not_animated= 0x0000, /* nothing happened */
338 	_obj_animated= 0x2000, /* a new frame was reached */
339 	_obj_keyframe_started= 0x1000, /* the key-frame was reached */
340 	_obj_last_frame_animated= 0x0800, /* sequence complete, returning to first frame */
341 	_obj_transfer_mode_finished= 0x0400 /* transfer mode phase is about to loop */
342 };
343 
344 #define GET_OBJECT_SCALE_FLAGS(o) (((o)->flags)&OBJECT_SCALE_FLAGS_MASK)
345 enum /* object scale flags */
346 {
347 	_object_is_enlarged= 0x0200,
348 	_object_is_tiny= 0x0100,
349 
350 	OBJECT_SCALE_FLAGS_MASK= _object_is_enlarged|_object_is_tiny
351 };
352 
353 #define OBJECT_IS_MEDIA_EFFECT(o) ((o)->flags&128)
354 #define SET_OBJECT_IS_MEDIA_EFFECT(o) ((o)->flags|= 128)
355 
356 /* ignored by renderer if INVISIBLE */
357 #define OBJECT_IS_INVISIBLE(o) ((o)->flags&(uint16)32)
358 #define OBJECT_IS_VISIBLE(o) (!OBJECT_IS_INVISIBLE(o))
359 #define SET_OBJECT_INVISIBILITY(o,v) ((void)((v)?((o)->flags|=(uint16)32):((o)->flags&=(uint16)~32)))
360 
361 /* call get_object_dimensions(object_index, &radius, &height) for SOLID objects to get their dimensions */
362 #define OBJECT_IS_SOLID(o) ((o)->flags&(uint16)16)
363 #define SET_OBJECT_SOLIDITY(o,v) ((void)((v)?((o)->flags|=(uint16)16):((o)->flags&=(uint16)~16)))
364 
365 #define GET_OBJECT_STATUS(o) ((o)->flags&(uint16)8)
366 #define SET_OBJECT_STATUS(o,v) ((v)?((o)->flags|=(uint16)8):((o)->flags&=(uint16)~8))
367 #define TOGGLE_OBJECT_STATUS(o) ((o)->flags^=(uint16)8)
368 
369 #define GET_OBJECT_OWNER(o) ((o)->flags&(uint16)7)
370 #define SET_OBJECT_OWNER(o,n) { assert((n)>=0&&(n)<=7); (o)->flags&= (uint16)~7; (o)->flags|= (n); }
371 enum /* object owners (8) */
372 {
373 	_object_is_normal, /* normal */
374 	_object_is_scenery, /* impassable scenery */
375 	_object_is_monster, /* monster index in .permutation */
376 	_object_is_projectile, /* active projectile index in .permutation */
377 	_object_is_effect, /* explosion or something; index in .permutation */
378 	_object_is_item, /* .permutation is item type */
379 	_object_is_device, /* status given by bit in flags field, device type in .permutation */
380 	_object_is_garbage /* will be removed by garbage collection algorithms */
381 };
382 
383 /* because of sign problems, we must rip out the values before we modify them; frame is
384 	in [0,16), phase is in [0,4096) ... this is for shape animations */
385 #define GET_SEQUENCE_FRAME(s) ((s)>>12)
386 #define GET_SEQUENCE_PHASE(s) ((s)&4095)
387 #define BUILD_SEQUENCE(f,p) (((f)<<12)|(p))
388 
389 enum /* object transfer modes (high-level) */
390 {
391 	_xfer_normal,
392 	_xfer_fade_out_to_black, /* reduce ambient light until black, then tint-fade out */
393 	_xfer_invisibility,
394 	_xfer_subtle_invisibility,
395 	_xfer_pulsate, /* only valid for polygons */
396 	_xfer_wobble, /* only valid for polygons */
397 	_xfer_fast_wobble, /* only valid for polygons */
398 	_xfer_static,
399 	_xfer_50percent_static,
400 	_xfer_landscape,
401 	_xfer_smear, /* repeat pixel(0,0) of texture everywhere */
402 	_xfer_fade_out_static,
403 	_xfer_pulsating_static,
404 	_xfer_fold_in, /* appear */
405 	_xfer_fold_out, /* disappear */
406 	_xfer_horizontal_slide,
407 	_xfer_fast_horizontal_slide,
408 	_xfer_vertical_slide,
409 	_xfer_fast_vertical_slide,
410 	_xfer_wander,
411 	_xfer_fast_wander,
412 	_xfer_big_landscape,
413 	NUMBER_OF_TRANSFER_MODES
414 };
415 
416 struct object_location
417 {
418 	struct world_point3d p;
419 	int16 polygon_index;
420 
421 	angle yaw, pitch;
422 
423 	uint16 flags;
424 };
425 
426 struct object_data /* 32 bytes */
427 {
428 	/* these fields are in the order of a world_location3d structure, but are missing the pitch
429 		and velocity fields */
430 	world_point3d location;
431 	int16 polygon;
432 
433 	angle facing;
434 
435 	/* this is not really a shape descriptor: (and this is the only place in the game where you
436 		find this pseudo-shape_descriptor type) the collection is valid, as usual, but the
437 		shape index is an index into the animated shape array for that collection. */
438 	shape_descriptor shape;
439 
440 	uint16 sequence; /* for shape animation */
441 	uint16 flags; /* [used_slot.1] [rendered.1] [animated.4] [unused.4] [invisible.1] [solid.1] [status.1] [owner.3] */
442 	int16 transfer_mode, transfer_period; /* if NONE take from shape data */
443 	int16 transfer_phase; /* for transfer mode animations */
444 	int16 permutation; /* usually index into owner array */
445 
446 	int16 next_object; /* or NONE */
447 	int16 parasitic_object; /* or NONE */
448 
449 	/* used when playing sounds */
450 	_fixed sound_pitch;
451 };
452 const int SIZEOF_object_data = 32;
453 
454 /* ------------ endpoint definition */
455 
456 #define ENDPOINT_IS_SOLID(e) ((e)->flags&1)
457 #define SET_ENDPOINT_SOLIDITY(e,s) ((s)?((e)->flags|=1):((e)->flags&=~(uint16)1))
458 
459 #define ENDPOINT_IS_TRANSPARENT(e) ((e)->flags&4)
460 #define SET_ENDPOINT_TRANSPARENCY(e,s) ((s)?((e)->flags|=4):((e)->flags&=~(uint16)4))
461 
462 /* false if all polygons sharing this endpoint have the same height */
463 #define ENDPOINT_IS_ELEVATION(e) ((e)->flags&2)
464 #define SET_ENDPOINT_ELEVATION(e,s) ((s)?((e)->flags|=2):((e)->flags&=~(uint16)2))
465 
466 struct endpoint_data /* 16 bytes */
467 {
468 	uint16 flags;
469 	world_distance highest_adjacent_floor_height, lowest_adjacent_ceiling_height;
470 
471 	world_point2d vertex;
472 	world_point2d transformed;
473 
474 	int16 supporting_polygon_index;
475 };
476 const int SIZEOF_endpoint_data = 16;
477 
478 // For loading plain points:
479 const int SIZEOF_world_point2d = 4;
480 
481 /* ------------ line definition */
482 
483 #define SOLID_LINE_BIT 0x4000
484 #define TRANSPARENT_LINE_BIT 0x2000
485 #define LANDSCAPE_LINE_BIT 0x1000
486 #define ELEVATION_LINE_BIT 0x800
487 #define VARIABLE_ELEVATION_LINE_BIT 0x400
488 #define LINE_HAS_TRANSPARENT_SIDE_BIT 0x200
489 
490 #define SET_LINE_SOLIDITY(l,v) ((v)?((l)->flags|=(uint16)SOLID_LINE_BIT):((l)->flags&=(uint16)~SOLID_LINE_BIT))
491 #define LINE_IS_SOLID(l) ((l)->flags&SOLID_LINE_BIT)
492 
493 #define SET_LINE_TRANSPARENCY(l,v) ((v)?((l)->flags|=(uint16)TRANSPARENT_LINE_BIT):((l)->flags&=(uint16)~TRANSPARENT_LINE_BIT))
494 #define LINE_IS_TRANSPARENT(l) ((l)->flags&TRANSPARENT_LINE_BIT)
495 
496 #define SET_LINE_LANDSCAPE_STATUS(l,v) ((v)?((l)->flags|=(uint16)LANDSCAPE_LINE_BIT):((l)->flags&=(uint16)~LANDSCAPE_LINE_BIT))
497 #define LINE_IS_LANDSCAPED(l) ((l)->flags&LANDSCAPE_LINE_BIT)
498 
499 #define SET_LINE_ELEVATION(l,v) ((v)?((l)->flags|=(uint16)ELEVATION_LINE_BIT):((l)->flags&=(uint16)~ELEVATION_LINE_BIT))
500 #define LINE_IS_ELEVATION(l) ((l)->flags&ELEVATION_LINE_BIT)
501 
502 #define SET_LINE_VARIABLE_ELEVATION(l,v) ((v)?((l)->flags|=(uint16)VARIABLE_ELEVATION_LINE_BIT):((l)->flags&=(uint16)~VARIABLE_ELEVATION_LINE_BIT))
503 #define LINE_IS_VARIABLE_ELEVATION(l) ((l)->flags&VARIABLE_ELEVATION_LINE_BIT)
504 
505 #define SET_LINE_HAS_TRANSPARENT_SIDE(l,v) ((v)?((l)->flags|=(uint16)LINE_HAS_TRANSPARENT_SIDE_BIT):((l)->flags&=(uint16)~LINE_HAS_TRANSPARENT_SIDE_BIT))
506 #define LINE_HAS_TRANSPARENT_SIDE(l) ((l)->flags&LINE_HAS_TRANSPARENT_SIDE_BIT)
507 
508 struct line_data /* 32 bytes */
509 {
510 	int16 endpoint_indexes[2];
511 	uint16 flags; /* no permutation field */
512 
513 	world_distance length;
514 	world_distance highest_adjacent_floor, lowest_adjacent_ceiling;
515 
516 	/* the side definition facing the clockwise polygon which references this side, and the side
517 		definition facing the counterclockwise polygon (can be NONE) */
518 	int16 clockwise_polygon_side_index, counterclockwise_polygon_side_index;
519 
520 	/* a line can be owned by a clockwise polygon, a counterclockwise polygon, or both (but never
521 		two of the same) (can be NONE) */
522 	int16 clockwise_polygon_owner, counterclockwise_polygon_owner;
523 
524 	int16 unused[6];
525 };
526 const int SIZEOF_line_data = 32;
527 
528 /* --------------- side definition */
529 
530 enum /* side flags */
531 {
532 	_control_panel_status= 0x0001,
533 	_side_is_control_panel= 0x0002,
534 	_side_is_repair_switch= 0x0004, // must be toggled to exit level
535 	_side_is_destructive_switch= 0x0008, // uses an item
536 	_side_is_lighted_switch= 0x0010, // switch must be lighted to use
537 	_side_switch_can_be_destroyed= 0x0020, // projectile hits toggle and destroy this switch
538 	_side_switch_can_only_be_hit_by_projectiles= 0x0040,
539 	_side_item_is_optional= 0x0080, // in Marathon, switches still work without items
540 
541 	_editor_dirty_bit= 0x4000 // used by the editor...
542 };
543 
544 enum /* control panel side types */
545 {
546 	_panel_is_oxygen_refuel,
547 	_panel_is_shield_refuel,
548 	_panel_is_double_shield_refuel,
549 	_panel_is_triple_shield_refuel,
550 	_panel_is_light_switch, // light index in .permutation
551 	_panel_is_platform_switch, // platform index in .permutation
552 	_panel_is_tag_switch, // tag in .permutation (NONE is tagless)
553 	_panel_is_pattern_buffer,
554 	_panel_is_computer_terminal,
555 	NUMBER_OF_CONTROL_PANELS
556 };
557 
558 #define SIDE_IS_CONTROL_PANEL(s) ((s)->flags & _side_is_control_panel)
559 #define SET_SIDE_CONTROL_PANEL(s, t) ((void)((t) ? (s->flags |= (uint16) _side_is_control_panel) : (s->flags &= (uint16)~_side_is_control_panel)))
560 
561 #define GET_CONTROL_PANEL_STATUS(s) (((s)->flags & _control_panel_status) != 0)
562 #define SET_CONTROL_PANEL_STATUS(s, t) ((t) ? (s->flags |= (uint16) _control_panel_status) : (s->flags &= (uint16)~_control_panel_status))
563 #define TOGGLE_CONTROL_PANEL_STATUS(s) ((s)->flags ^= _control_panel_status)
564 
565 #define SIDE_IS_REPAIR_SWITCH(s) ((s)->flags & _side_is_repair_switch)
566 #define SET_SIDE_IS_REPAIR_SWITCH(s, t) ((t) ? (s->flags |= (uint16) _side_is_repair_switch) : (s->flags &= (uint16)~_side_is_repair_switch))
567 
568 /* Flags used by Vulcan */
569 #define SIDE_IS_DIRTY(s) ((s)->flags&_editor_dirty_bit)
570 #define SET_SIDE_IS_DIRTY(s, t) ((t)?(s->flags|=(uint16)_editor_dirty_bit):(s->flags&=(uint16)~_editor_dirty_bit))
571 
572 enum /* side types (largely redundant; most of this could be guessed for examining adjacent polygons) */
573 {
574 	_full_side, /* primary texture is mapped floor-to-ceiling */
575 	_high_side, /* primary texture is mapped on a panel coming down from the ceiling (implies 2 adjacent polygons) */
576 	_low_side, /* primary texture is mapped on a panel coming up from the floor (implies 2 adjacent polygons) */
577 	_composite_side, /* primary texture is mapped floor-to-ceiling, secondary texture is mapped into it (i.e., control panel) */
578 	_split_side /* primary texture is mapped onto a panel coming down from the ceiling, secondary
579 		texture is mapped on a panel coming up from the floor */
580 };
581 
582 struct side_texture_definition
583 {
584 	world_distance x0, y0;
585 	shape_descriptor texture;
586 };
587 
588 struct side_exclusion_zone
589 {
590 	world_point2d e0, e1, e2, e3;
591 };
592 
593 struct side_data /* size platform-dependant */
594 {
595 	int16 type;
596 	uint16 flags;
597 
598 	struct side_texture_definition primary_texture;
599 	struct side_texture_definition secondary_texture;
600 	struct side_texture_definition transparent_texture; /* not drawn if .texture==NONE */
601 
602 	/* all sides have the potential of being impassable; the exclusion zone is the area near
603 		the side which cannot be walked through */
604 	struct side_exclusion_zone exclusion_zone;
605 
606 	int16 control_panel_type; /* Only valid if side->flags & _side_is_control_panel */
607 	int16 control_panel_permutation; /* platform index, light source index, etc... */
608 
609 	int16 primary_transfer_mode; /* These should be in the side_texture_definition.. */
610 	int16 secondary_transfer_mode;
611 	int16 transparent_transfer_mode;
612 
613 	int16 polygon_index, line_index;
614 
615 	int16 primary_lightsource_index;
616 	int16 secondary_lightsource_index;
617 	int16 transparent_lightsource_index;
618 
619 	int32 ambient_delta;
620 
621 	int16 unused[1];
622 };
623 const int SIZEOF_side_data = 64;
624 
625 /* ----------- polygon definition */
626 
627 #define MAXIMUM_VERTICES_PER_POLYGON 8
628 
629 // LP/AlexJLS change: added Marathon 1 polygon damage and glue stuff
630 enum /* polygon types */
631 {
632 	_polygon_is_normal,
633 	_polygon_is_item_impassable,
634 	_polygon_is_monster_impassable,
635 	_polygon_is_hill, /* for king-of-the-hill */
636 	_polygon_is_base, /* for capture the flag, rugby, etc. (team in .permutation) */
637 	_polygon_is_platform, /* platform index in .permutation */
638 	_polygon_is_light_on_trigger, /* lightsource index in .permutation */
639 	_polygon_is_platform_on_trigger, /* polygon index in .permutation */
640 	_polygon_is_light_off_trigger, /* lightsource index in .permutation */
641 	_polygon_is_platform_off_trigger, /* polygon index in .permutation */
642 	_polygon_is_teleporter, /* .permutation is polygon_index of destination */
643 	_polygon_is_zone_border,
644 	_polygon_is_goal,
645 	_polygon_is_visible_monster_trigger,
646 	_polygon_is_invisible_monster_trigger,
647 	_polygon_is_dual_monster_trigger,
648 	_polygon_is_item_trigger, /* activates all items in this zone */
649 	_polygon_must_be_explored,
650 	_polygon_is_automatic_exit, /* if success conditions are met, causes automatic transport too next level */
651 	_polygon_is_minor_ouch,
652 	_polygon_is_major_ouch,
653 	_polygon_is_glue,
654 	_polygon_is_glue_trigger,
655 	_polygon_is_superglue
656 };
657 
658 #define POLYGON_IS_DETACHED_BIT 0x4000
659 #define POLYGON_IS_DETACHED(p) ((p)->flags&POLYGON_IS_DETACHED_BIT)
660 #define SET_POLYGON_DETACHED_STATE(p, v) ((v)?((p)->flags|=POLYGON_IS_DETACHED_BIT):((p)->flags&=~POLYGON_IS_DETACHED_BIT))
661 
662 struct horizontal_surface_data /* should be in polygon structure */
663 {
664 	world_distance height;
665 	int16 lightsource_index;
666 	shape_descriptor texture;
667 	int16 transfer_mode, transfer_mode_data;
668 
669 	world_point2d origin;
670 };
671 
672 struct polygon_data /* 128 bytes */
673 {
674 	int16 type;
675 	uint16 flags;
676 	int16 permutation;
677 
678 	uint16 vertex_count;
679 	int16 endpoint_indexes[MAXIMUM_VERTICES_PER_POLYGON]; /* clockwise */
680 	int16 line_indexes[MAXIMUM_VERTICES_PER_POLYGON];
681 
682 	shape_descriptor floor_texture, ceiling_texture;
683 	world_distance floor_height, ceiling_height;
684 	int16 floor_lightsource_index, ceiling_lightsource_index;
685 
686 	int32 area; /* in world_distance^2 units */
687 
688 	int16 first_object;
689 
690 	/* precalculated impassability information; each polygon has a list of lines and points
691 		that anything big (i.e., monsters but not projectiles) inside it must check against when
692 		ending a move inside it. */
693 	int16 first_exclusion_zone_index;
694 	int16 line_exclusion_zone_count;
695 	int16 point_exclusion_zone_count;
696 
697 	int16 floor_transfer_mode;
698 	int16 ceiling_transfer_mode;
699 
700 	int16 adjacent_polygon_indexes[MAXIMUM_VERTICES_PER_POLYGON];
701 
702 	/* a list of polygons within WORLD_ONE of us */
703 	int16 first_neighbor_index;
704 	int16 neighbor_count;
705 
706 	world_point2d center;
707 
708 	int16 side_indexes[MAXIMUM_VERTICES_PER_POLYGON];
709 
710 	world_point2d floor_origin, ceiling_origin;
711 
712 	int16 media_index;
713 	int16 media_lightsource_index;
714 
715 	/* NONE terminated list of _saved_sound_source indexes which must be checked while a
716 		listener is inside this polygon (can be none) */
717 	int16 sound_source_indexes;
718 
719 	// either can be NONE
720 	int16 ambient_sound_image_index;
721 	int16 random_sound_image_index;
722 
723 	int16 unused[1];
724 };
725 const int SIZEOF_polygon_data = 128;
726 
727 /* ----------- static light definition */
728 
729 struct saved_lighting_function_specification /* 7*2 == 14 bytes */
730 {
731 	int16 function;
732 
733 	int16 period, delta_period;
734 	uint16 intensity_hi, intensity_lo, delta_intensity_hi, delta_intensity_lo;
735 };
736 
737 struct saved_static_light_data /* 8*2 + 6*14 == 100 bytes */
738 {
739 	int16 type;
740 	uint16 flags;
741 
742 	int16 phase; // initializer, so lights may start out-of-phase with each other
743 
744 	struct saved_lighting_function_specification primary_active, secondary_active, becoming_active;
745 	struct saved_lighting_function_specification primary_inactive, secondary_inactive, becoming_inactive;
746 
747 	int16 tag;
748 
749 	int16 unused[4];
750 };
751 const int SIZEOF_saved_static_light_data = 100;
752 
753 /* ---------- random placement data structures.. */
754 
755 enum /* game difficulty levels */
756 {
757 	_wuss_level,
758 	_easy_level,
759 	_normal_level,
760 	_major_damage_level,
761 	_total_carnage_level,
762 	NUMBER_OF_GAME_DIFFICULTY_LEVELS
763 };
764 
765 
766 enum /* for difficulty level names (moved here so it is in a common header file) */
767 {
768 	kDifficultyLevelsStringSetID	= 145
769 };
770 
771 /* ---------- new object frequency structures. */
772 
773 #define MAXIMUM_OBJECT_TYPES 64
774 
775 enum // flags for object_frequency_definition
776 {
777 	_reappears_in_random_location= 0x0001
778 };
779 
780 struct object_frequency_definition
781 {
782 	uint16 flags;
783 
784 	int16 initial_count;   // number that initially appear. can be greater than maximum_count
785 	int16 minimum_count;   // this number of objects will be maintained.
786 	int16 maximum_count;   // can�t exceed this, except at the beginning of the level.
787 
788 	int16 random_count;    // maximum random occurences of the object
789 	uint16 random_chance;    // in (0, 65535]
790 };
791 const int SIZEOF_object_frequency_definition = 12;
792 
793 /* ---------- map */
794 
795 enum /* mission flags */
796 {
797 	_mission_none= 0x0000,
798 	_mission_extermination= 0x0001,
799 	_mission_exploration= 0x0002,
800 	_mission_retrieval= 0x0004,
801 	_mission_repair= 0x0008,
802 	_mission_rescue= 0x0010,
803 	_mission_exploration_m1= 0x0020,
804 	_mission_rescue_m1= 0x0040,
805 	_mission_repair_m1= 0x0080
806 };
807 
808 enum /* environment flags */
809 {
810 	_environment_normal= 0x0000,
811 	_environment_vacuum= 0x0001, // prevents certain weapons from working, player uses oxygen
812 	_environment_magnetic= 0x0002, // motion sensor works poorly
813 	_environment_rebellion= 0x0004, // makes clients fight pfhor
814 	_environment_low_gravity= 0x0008, // low gravity
815 	_environment_glue_m1= 0x0010, // handle glue polygons like Marathon 1
816 	_environment_ouch_m1= 0x0020, // the floor is lava
817 	_environment_rebellion_m1= 0x0040,  // use Marathon 1 rebellion (don't strip items/health)
818 	_environment_song_index_m1 = 0x0080, // play music
819 	_environment_terminals_stop_time = 0x0100, // solo only
820 	_environment_activation_ranges = 0x0200, // Marathon 1 monster activation limits
821 	_environment_m1_weapons = 0x0400,    // multiple weapon pickups on TC; low gravity grenades
822 
823 	_environment_network= 0x2000,	// these two pseudo-environments are used to prevent items
824 	_environment_single_player= 0x4000 // from arriving in the items.c code.
825 };
826 
827 /* current map number is in player->map */
828 struct static_data
829 {
830 	int16 environment_code;
831 
832 	int16 physics_model;
833 	int16 song_index;
834 	int16 mission_flags;
835 	int16 environment_flags;
836 
837 	bool ball_in_play; // true if there's a ball in play
838 	bool unused1;
839 	int16 unused[3];
840 
841 	char level_name[LEVEL_NAME_LENGTH];
842 	uint32 entry_point_flags;
843 };
844 const unsigned int SIZEOF_static_data = 88;
845 
846 enum /* game options.. */
847 {
848 	_multiplayer_game= 0x0001, /* multi or single? */
849 	_ammo_replenishes= 0x0002, /* Does or doesn't */
850 	_weapons_replenish= 0x0004, /* Weapons replenish? */
851 	_specials_replenish= 0x0008, /* Invisibility, Ammo? */
852 	_monsters_replenish= 0x0010, /* Monsters are lazarus.. */
853 	_motion_sensor_does_not_work= 0x00020, /* Motion sensor works */
854 	_overhead_map_is_omniscient=  0x0040, /* Only show teammates on overhead map */
855 	_burn_items_on_death= 0x0080, /* When you die, you lose everything but the initial crap.. */
856 	_live_network_stats= 0x0100,
857 	_game_has_kill_limit= 0x0200,  /* Game ends when the kill limit is reached. */
858 	_force_unique_teams= 0x0400, /* every player must have a unique team */
859 	_dying_is_penalized= 0x0800, /* time penalty for dying */
860 	_suicide_is_penalized= 0x1000, /* time penalty for killing yourselves */
861 	_overhead_map_shows_items= 0x2000,
862 	_overhead_map_shows_monsters= 0x4000,
863 	_overhead_map_shows_projectiles= 0x8000
864 };
865 
866 enum /* cheat flags */
867   {
868     _allow_crosshair = 0x0001,
869     _allow_tunnel_vision = 0x0002,
870     _allow_behindview = 0x0004,
871     _disable_carnage_messages = 0x0008,
872     _disable_saving_level = 0x0010,
873     _allow_overlay_map = 0x0020
874   };
875 
876 enum // specifies how the user completed the level. saved in dynamic_data
877 {
878 	_level_unfinished,
879 	_level_finished,
880 	_level_failed
881 };
882 
883 /* Game types! */
884 enum {
885 	_game_of_kill_monsters,		// single player & combative use this
886 	_game_of_cooperative_play,	// multiple players, working together
887 	_game_of_capture_the_flag,	// A team game.
888 	_game_of_king_of_the_hill,
889 	_game_of_kill_man_with_ball,
890 	_game_of_defense,
891 	_game_of_rugby,
892 	_game_of_tag,
893 	_game_of_custom,
894 	NUMBER_OF_GAME_TYPES
895 };
896 
897 #define GET_GAME_TYPE() (dynamic_world->game_information.game_type)
898 #define GET_GAME_OPTIONS() (dynamic_world->game_information.game_options)
899 #define GET_GAME_PARAMETER(x) (dynamic_world->game_information.parameters[(x)])
900 
901 /*
902 	Single player game:
903 		game_type= _game_of_kill_monsters;
904 		game_options= 0
905 */
906 
907 struct game_data
908 {
909 	/* Used for the net game, decrement each tick.  Used for the */
910 	/*  single player game-> set to INT32_MAX, and decremented over time, so */
911 	/*  that you know how long it took you to solve the game. */
912 	int32 game_time_remaining;
913 	int16 game_type; /* One of previous enum's */
914 	int16 game_options;
915         int16 cheat_flags;
916 	int16 kill_limit;
917 	int16 initial_random_seed;
918 	int16 difficulty_level;
919 	int16 parameters[2]; /* Use these later. for now memset to 0 */
920 };
921 
922 struct dynamic_data
923 {
924 	/* ticks since the beginning of the game */
925 	int32 tick_count;
926 
927 	/* the real seed is static in WORLD.C; must call set_random_seed() */
928 	uint16 random_seed;
929 
930 	/* This is stored in the dynamic_data so that it is valid across */
931 	/* saves. */
932 	struct game_data game_information;
933 
934 	int16 player_count;
935 	int16 speaking_player_index;
936 
937 	int16 unused;
938 	int16 platform_count;
939 	int16 endpoint_count;
940 	int16 line_count;
941 	int16 side_count;
942 	int16 polygon_count;
943 	int16 lightsource_count;
944 	int16 map_index_count;
945 	int16 ambient_sound_image_count, random_sound_image_count;
946 
947 	/* statistically unlikely to be valid */
948 	int16 object_count;
949 	int16 monster_count;
950 	int16 projectile_count;
951 	int16 effect_count;
952 	int16 light_count;
953 
954 	int16 default_annotation_count;
955 	int16 personal_annotation_count;
956 
957 	int16 initial_objects_count;
958 
959 	int16 garbage_object_count;
960 
961 	/* used by move_monsters() to decide who gets to generate paths, etc. */
962 	int16 last_monster_index_to_get_time, last_monster_index_to_build_path;
963 
964 	/* variables used by new_monster() to adjust for different difficulty levels */
965 	int16 new_monster_mangler_cookie, new_monster_vanishing_cookie;
966 
967 	/* number of civilians killed by players; periodically decremented */
968 	int16 civilians_killed_by_players;
969 
970 	/* used by the item placement stuff */
971 	int16 random_monsters_left[MAXIMUM_OBJECT_TYPES];
972 	int16 current_monster_count[MAXIMUM_OBJECT_TYPES];
973 	int16 random_items_left[MAXIMUM_OBJECT_TYPES];
974 	int16 current_item_count[MAXIMUM_OBJECT_TYPES];
975 
976 	int16 current_level_number;   // what level the user is currently exploring.
977 
978 	int16 current_civilian_causalties, current_civilian_count;
979 	int16 total_civilian_causalties, total_civilian_count;
980 
981 	world_point2d game_beacon;
982 	int16 game_player_index;
983 };
984 const unsigned int SIZEOF_dynamic_data = 604;
985 
986 /* ---------- map globals */
987 
988 // Turned some of these lists into variable arrays;
989 // took over their maximum numbers as how many of them
990 
991 extern struct static_data *static_world;
992 extern struct dynamic_data *dynamic_world;
993 
994 extern vector<object_data> ObjectList;
995 #define objects (ObjectList.data())
996 
997 // extern struct object_data *objects;
998 
999 extern vector<endpoint_data> EndpointList;
1000 #define map_endpoints (EndpointList.data())
1001 #define MAXIMUM_ENDPOINTS_PER_MAP (EndpointList.size())
1002 
1003 extern vector<line_data> LineList;
1004 #define map_lines (LineList.data())
1005 #define MAXIMUM_LINES_PER_MAP (LineList.size())
1006 
1007 extern vector<side_data> SideList;
1008 #define map_sides (SideList.data())
1009 #define MAXIMUM_SIDES_PER_MAP (SideList.size())
1010 
1011 extern vector<polygon_data> PolygonList;
1012 #define map_polygons (PolygonList.data())
1013 #define MAXIMUM_POLYGONS_PER_MAP (PolygonList.size())
1014 
1015 // extern struct polygon_data *map_polygons;
1016 // extern struct side_data *map_sides;
1017 // extern struct line_data *map_lines;
1018 // extern struct endpoint_data *map_endpoints;
1019 
1020 extern vector<ambient_sound_image_data> AmbientSoundImageList;
1021 #define MAXIMUM_AMBIENT_SOUND_IMAGES_PER_MAP (AmbientSoundImageList.size())
1022 #define ambient_sound_images (AmbientSoundImageList.data())
1023 
1024 extern vector<random_sound_image_data> RandomSoundImageList;
1025 #define MAXIMUM_RANDOM_SOUND_IMAGES_PER_MAP (RandomSoundImageList.size())
1026 #define random_sound_images (RandomSoundImageList.data())
1027 
1028 // extern struct ambient_sound_image_data *ambient_sound_images;
1029 // extern struct random_sound_image_data *random_sound_images;
1030 
1031 extern vector<int16> MapIndexList;
1032 #define map_indexes (MapIndexList.data())
1033 
1034 // extern int16 *map_indexes;
1035 
1036 extern vector<uint8> AutomapLineList;
1037 #define automap_lines (AutomapLineList.data())
1038 
1039 extern vector<uint8> AutomapPolygonList;
1040 #define automap_polygons (AutomapPolygonList.data())
1041 
1042 // extern byte *automap_lines;
1043 // extern byte *automap_polygons;
1044 
1045 extern vector<map_annotation> MapAnnotationList;
1046 #define MAXIMUM_ANNOTATIONS_PER_MAP (MapAnnotationList.size())
1047 #define map_annotations (MapAnnotationList.data())
1048 
1049 extern vector<map_object> SavedObjectList;
1050 #define MAXIMUM_SAVED_OBJECTS (SavedObjectList.size())
1051 #define saved_objects (SavedObjectList.data())
1052 
1053 // extern struct map_annotation *map_annotations;
1054 // extern struct map_object *saved_objects;
1055 
1056 extern bool game_is_networked; /* true if this is a network game */
1057 
1058 #define ADD_LINE_TO_AUTOMAP(i) (automap_lines[(i)>>3] |= (byte) 1<<((i)&0x07))
1059 #define CLEAR_LINE_FROM_AUTOMAP(i) (automap_lines[(i)>>3] &= ~((byte) 1<<((i&0x07))))
1060 #define LINE_IS_IN_AUTOMAP(i) ((automap_lines[(i)>>3]&((byte)1<<((i)&0x07)))?(true):(false))
1061 
1062 #define ADD_POLYGON_TO_AUTOMAP(i) (automap_polygons[(i)>>3] |= (byte) 1<<((i)&0x07))
1063 #define CLEAR_POLYGON_FROM_AUTOMAP(i) (automap_polygons[(i)>>3] &= ~((byte) 1<<((i&0x07))))
1064 #define POLYGON_IS_IN_AUTOMAP(i) ((automap_polygons[(i)>>3]&((byte)1<<((i)&0x07)))?(true):(false))
1065 
1066 // Whether or not Marathon 2/oo landscapes had been loaded (switch off for Marathon 1 compatibility)
1067 extern bool LandscapesLoaded;
1068 
1069 // The index number of the first texture loaded (should be the main wall texture);
1070 // needed for infravision fog when landscapes are switched off
1071 extern short LoadedWallTexture;
1072 
1073 /* ---------- prototypes/MARATHON.C */
1074 
1075 void initialize_marathon(void);
1076 
1077 void leaving_map(void);
1078 // LP: added whether a savegame is being restored (skip Pfhortran init if that's the case)
1079 bool entering_map(bool restoring_saved);
1080 
1081 // ZZZ: now returns <whether anything changed, real-mode elapsed time>
1082 // (used to return only the latter)
1083 std::pair<bool, int16> update_world(void);
1084 
1085 // ZZZ: these really don't go here, but they live in marathon2.cpp where update_world() lives.....
1086 void reset_intermediate_action_queues();
1087 void set_prediction_wanted(bool inPrediction);
1088 
1089 /* Called to activate lights, platforms, etc. (original polygon may be NONE) */
1090 void changed_polygon(short original_polygon_index, short new_polygon_index, short player_index);
1091 
1092 short calculate_damage(struct damage_definition *damage);
1093 void cause_polygon_damage(short polygon_index, short monster_index);
1094 
1095 short calculate_level_completion_state(void);
1096 
1097 /* ---------- prototypes/MAP.C */
1098 
1099 void allocate_map_memory(void);
1100 void initialize_map_for_new_game(void);
1101 void initialize_map_for_new_level(void);
1102 
1103 void mark_environment_collections(short environment_code, bool loading);
1104 void mark_map_collections(bool loading);
1105 bool collection_in_environment(short collection_code, short environment_code);
1106 
1107 bool valid_point2d(world_point2d *p);
1108 bool valid_point3d(world_point3d *p);
1109 
1110 void reconnect_map_object_list(void);
1111 short new_map_object2d(world_point2d *location, short polygon_index, shape_descriptor shape, angle facing);
1112 short new_map_object3d(world_point3d *location, short polygon_index, shape_descriptor shape, angle facing);
1113 short new_map_object(struct object_location *location, shape_descriptor shape);
1114 short attach_parasitic_object(short host_index, shape_descriptor shape, angle facing);
1115 void remove_parasitic_object(short host_index);
1116 bool translate_map_object(short object_index, world_point3d *new_location, short new_polygon_index);
1117 short find_new_object_polygon(world_point2d *parent_location, world_point2d *child_location, short parent_polygon_index);
1118 void remove_map_object(short index);
1119 
1120 
1121 // ZZZ additions in support of prediction:
1122 // removes the object at object_index from the polygon with index in object's 'polygon' field
1123 extern void remove_object_from_polygon_object_list(short object_index);
1124 extern void remove_object_from_polygon_object_list(short object_index, short polygon_index);
1125 
1126 // schedules object at object_index for later insertion into a polygon object list.  it'll be inserted
1127 // before the object with index index_to_precede (which had better be in the list or be scheduled for insertion
1128 // by the time perform_deferred_polygon_object_list_manipulations() is called, else A1 will assert).
1129 extern void deferred_add_object_to_polygon_object_list(short object_index, short index_to_precede);
1130 
1131 // actually does the insertions scheduled by deferred_add_object_to_polygon_object_list().  uses the polygon
1132 // index each scheduled object has _when this function is called_, not whatever polygon index it had when
1133 // deferred_add_object_to_polygon_object_list() was called!
1134 extern void perform_deferred_polygon_object_list_manipulations();
1135 
1136 
1137 
1138 struct shape_and_transfer_mode
1139 {
1140 	/* extended shape descriptor */
1141 	short collection_code, low_level_shape_index;
1142 
1143 	short transfer_mode;
1144 	_fixed transfer_phase; /* [0,FIXED_ONE] */
1145 
1146 	// Needed for animated models: which frame in an individual sequence (0, 1, 2, ...)
1147 	short Frame, NextFrame;
1148 
1149 	// Needed for animated models: which tick in a frame, and total ticks per frame
1150 	short Phase, Ticks;
1151 };
1152 
1153 void get_object_shape_and_transfer_mode(world_point3d *camera_location, short object_index, struct shape_and_transfer_mode *data);
1154 void set_object_shape_and_transfer_mode(short object_index, shape_descriptor shape, short transfer_mode);
1155 void animate_object(short object_index); /* assumes �t==1 tick */
1156 bool randomize_object_sequence(short object_index, shape_descriptor shape);
1157 
1158 void play_object_sound(short object_index, short sound_code);
1159 void play_polygon_sound(short polygon_index, short sound_code);
1160 void _play_side_sound(short side_index, short sound_code, _fixed pitch);
1161 void play_world_sound(short polygon_index, world_point3d *origin, short sound_code);
1162 
1163 #define play_side_sound(side_index, sound_code) _play_side_sound(side_index, sound_code, FIXED_ONE)
1164 
1165 void handle_random_sound_image(void);
1166 
1167 void initialize_map_for_new_player(void);
1168 void generate_map(short level);
1169 
1170 short world_point_to_polygon_index(world_point2d *location);
1171 short clockwise_endpoint_in_line(short polygon_index, short line_index, short index);
1172 
1173 short find_adjacent_polygon(short polygon_index, short line_index);
1174 short find_flooding_polygon(short polygon_index);
1175 short find_adjacent_side(short polygon_index, short line_index);
1176 short find_shared_line(short polygon_index1, short polygon_index2);
1177 bool line_is_landscaped(short polygon_index, short line_index, world_distance z);
1178 short find_line_crossed_leaving_polygon(short polygon_index, world_point2d *p0, world_point2d *p1);
1179 bool point_in_polygon(short polygon_index, world_point2d *p);
1180 void find_center_of_polygon(short polygon_index, world_point2d *center);
1181 
1182 int32 point_to_line_segment_distance_squared(world_point2d *p, world_point2d *a, world_point2d *b);
1183 int32 point_to_line_distance_squared(world_point2d *p, world_point2d *a, world_point2d *b);
1184 
1185 _fixed closest_point_on_line(world_point2d *e0, world_point2d *e1, world_point2d *p, world_point2d *closest_point);
1186 void closest_point_on_circle(world_point2d *c, world_distance radius, world_point2d *p, world_point2d *closest_point);
1187 
1188 _fixed find_line_intersection(world_point2d *e0, world_point2d *e1, world_point3d *p0,
1189 	world_point3d *p1, world_point3d *intersection);
1190 _fixed find_floor_or_ceiling_intersection(world_distance h, world_point3d *p0, world_point3d *p1, world_point3d *intersection);
1191 
1192 void ray_to_line_segment(world_point2d *p0, world_point2d *p1, angle theta, world_distance d);
1193 
1194 void push_out_line(world_point2d *e0, world_point2d *e1, world_distance d, world_distance line_length);
1195 bool keep_line_segment_out_of_walls(short polygon_index, world_point3d *p0,
1196 	world_point3d *p1, world_distance maximum_delta_height, world_distance height, world_distance *adjusted_floor_height,
1197 	world_distance *adjusted_ceiling_height, short *supporting_polygon_index);
1198 
1199 _fixed get_object_light_intensity(short object_index);
1200 
1201 bool line_has_variable_height(short line_index);
1202 
1203 void recalculate_map_counts(void);
1204 
1205 bool change_polygon_height(short polygon_index, world_distance new_floor_height,
1206 	world_distance new_ceiling_height, struct damage_definition *damage);
1207 
1208 bool line_is_obstructed(short polygon_index1, world_point2d *p1, short polygon_index2, world_point2d *p2);
1209 bool point_is_player_visible(short max_players, short polygon_index, world_point2d *p, int32 *distance);
1210 bool point_is_monster_visible(short polygon_index, world_point2d *p, int32 *distance);
1211 
1212 void turn_object_to_shit(short garbage_object_index);
1213 
1214 void random_point_on_circle(world_point3d *center, short center_polygon_index,
1215 	world_distance radius, world_point3d *random_point, short *random_polygon_index);
1216 
1217 void calculate_line_midpoint(short line_index, world_point3d *midpoint);
1218 
1219 void *get_map_structure_chunk(long chunk_size);
1220 void reallocate_map_structure_memory(long size);
1221 
1222 /* ---------- prototypes/MAP_ACCESSORS.C */
1223 
1224 // LP changed: previously inline; now de-inlined for less code bulk
1225 // When the index is out of range,
1226 // the geometry ones make failed asserts,
1227 // while the sound ones return null pointers.
1228 
1229 object_data *get_object_data(
1230 	const short object_index);
1231 
1232 polygon_data *get_polygon_data(
1233 	const short polygon_index);
1234 
1235 line_data *get_line_data(
1236 	const short line_index);
1237 
1238 side_data *get_side_data(
1239 	const short side_index);
1240 
1241 endpoint_data *get_endpoint_data(
1242 	const short endpoint_index);
1243 
1244 short *get_map_indexes(
1245 	const short index,
1246 	const short count);
1247 
1248 ambient_sound_image_data *get_ambient_sound_image_data(
1249 	const short ambient_sound_image_index);
1250 
1251 random_sound_image_data *get_random_sound_image_data(
1252 	const short random_sound_image_index);
1253 
1254 /* ---------- prototypes/MAP_CONSTRUCTORS.C */
1255 
1256 short new_map_endpoint(world_point2d *where);
1257 short duplicate_map_endpoint(short old_endpoint_index);
1258 short new_map_line(short a, short b, short poly_a, short poly_b, short side_a, short side_b);
1259 short duplicate_map_line(short old_line_index);
1260 short new_map_polygon(short *line_indexes, short line_count, short floor_height,
1261 	short ceiling_height, short floor_texture, short ceiling_texture, short lightsource_index);
1262 void recalculate_side_type(short side_index);
1263 short new_side(short polygon_index, short line_index);
1264 
1265 void precalculate_map_indexes(void);
1266 
1267 void touch_polygon(short polygon_index);
1268 void recalculate_redundant_polygon_data(short polygon_index);
1269 void recalculate_redundant_endpoint_data(short endpoint_index);
1270 void recalculate_redundant_line_data(short line_index);
1271 void recalculate_redundant_side_data(short side_index, short line_index);
1272 
1273 void calculate_endpoint_polygon_owners(short endpoint_index, short *first_index, short *index_count);
1274 void calculate_endpoint_line_owners(short endpoint_index, short *first_index, short *index_count);
1275 
1276 void guess_side_lightsource_indexes(short side_index);
1277 
1278 void set_map_index_buffer_size(long length);
1279 
1280 // LP: routines for packing and unpacking the data from streams of bytes
1281 
1282 uint8 *unpack_endpoint_data(uint8 *Stream, endpoint_data* Objects, size_t Count);
1283 uint8 *pack_endpoint_data(uint8 *Stream, endpoint_data* Objects, size_t Count);
1284 uint8 *unpack_line_data(uint8 *Stream, line_data* Objects, size_t Count);
1285 uint8 *pack_line_data(uint8 *Stream, line_data* Objects, size_t Count);
1286 uint8 *unpack_side_data(uint8 *Stream, side_data* Objects, size_t Count);
1287 uint8 *pack_side_data(uint8 *Stream, side_data* Objects, size_t Count);
1288 uint8 *unpack_polygon_data(uint8 *Stream, polygon_data* Objects, size_t Count);
1289 uint8 *pack_polygon_data(uint8 *Stream, polygon_data* Objects, size_t Count);
1290 
1291 uint8 *unpack_map_annotation(uint8 *Stream, map_annotation* Objects, size_t Count);
1292 uint8 *pack_map_annotation(uint8 *Stream, map_annotation* Objects, size_t Count);
1293 uint8 *unpack_map_object(uint8 *Stream, map_object* Objects, size_t Count);
1294 uint8 *pack_map_object(uint8 *Stream, map_object* Objects, size_t Count);
1295 uint8 *unpack_object_frequency_definition(uint8 *Stream, object_frequency_definition* Objects, size_t Count);
1296 uint8 *pack_object_frequency_definition(uint8 *Stream, object_frequency_definition* Objects, size_t Count);
1297 uint8 *unpack_static_data(uint8 *Stream, static_data* Objects, size_t Count);
1298 uint8 *pack_static_data(uint8 *Stream, static_data* Objects, size_t Count);
1299 
1300 uint8 *unpack_ambient_sound_image_data(uint8 *Stream, ambient_sound_image_data* Objects, size_t Count);
1301 uint8 *pack_ambient_sound_image_data(uint8 *Stream, ambient_sound_image_data* Objects, size_t Count);
1302 uint8 *unpack_random_sound_image_data(uint8 *Stream, random_sound_image_data* Objects, size_t Count);
1303 uint8 *pack_random_sound_image_data(uint8 *Stream, random_sound_image_data* Objects, size_t Count);
1304 
1305 uint8 *unpack_dynamic_data(uint8 *Stream, dynamic_data* Objects, size_t Count);
1306 uint8 *pack_dynamic_data(uint8 *Stream, dynamic_data* Objects, size_t Count);
1307 uint8 *unpack_object_data(uint8 *Stream, object_data* Objects, size_t Count);
1308 uint8 *pack_object_data(uint8 *Stream, object_data* Objects, size_t Count);
1309 
1310 uint8 *unpack_damage_definition(uint8 *Stream, damage_definition* Objects, size_t Count);
1311 uint8 *pack_damage_definition(uint8 *Stream, damage_definition* Objects, size_t Count);
1312 
1313 /*
1314 	map_indexes, automap_lines, and automap_polygons do not have any special
1315 	packing and unpacking routines, because the packing/unpacking of map_indexes is
1316 	relatively simple, and because the automap lines and polygons need no such processing.
1317 */
1318 
1319 /* ---------- prototypes/PLACEMENT.C */
1320 
1321 // LP: this one does unpacking also
1322 void load_placement_data(uint8 *_monsters, uint8 *_items);
1323 struct object_frequency_definition *get_placement_info(void);
1324 void place_initial_objects(void);
1325 void recreate_objects(void);
1326 void object_was_just_added(short object_class, short object_type);
1327 void object_was_just_destroyed(short object_class, short object_type);
1328 short get_random_player_starting_location_and_facing(short max_player_index, short team, struct object_location *location);
1329 
1330 void mark_all_monster_collections(bool loading);
1331 void load_all_monster_sounds(void);
1332 
1333 /* ---------- prototypes/GAME_DIALOGS.C */
1334 
1335 /* --------- prototypes/LIGHTSOURCE.C */
1336 
1337 void update_lightsources(void);
1338 short new_lightsource_from_old(short old_source);
1339 void entered_polygon(short index);
1340 void left_polygon(short index);
1341 /* Only send _light_turning_on, _light_turning_off, _light_toggle */
1342 void change_light_state(size_t lightsource_index, short state);
1343 
1344 /* ---------- prototypes/DEVICES.C */
1345 
1346 void mark_control_panel_shapes(bool load);
1347 void initialize_control_panels_for_level(void);
1348 void update_control_panels(void);
1349 
1350 bool control_panel_in_environment(short control_panel_type, short environment_code);
1351 
1352 void change_device_state(short device_index, bool active);
1353 short new_device(world_point2d *location, short initial_polygon_index,
1354 	short type, short extra_data, bool active);
1355 void update_action_key(short player_index, bool triggered);
1356 
1357 bool untoggled_repair_switches_on_level(bool only_last_switch = false);
1358 
1359 void assume_correct_switch_position(short switch_type, short permutation, bool new_state);
1360 
1361 void try_and_toggle_control_panel(short polygon_index, short line_index, short projectile_index);
1362 
1363 bool line_side_has_control_panel(short line_index, short polygon_index, short *side_index_with_panel);
1364 
1365 /* ---------- prototypes/GAME_WAD.C */
1366 
1367 struct map_identifier {
1368 	uint32 scenario_checksum;
1369 	short level_index;
1370 };
1371 
1372 void set_to_default_map(void);
1373 
1374 /* Return true if it finds the file, and it sets the mapfile to that file. */
1375 /* Otherwise it returns false, meaning that we need have the file sent to us. */
1376 bool use_map_file(uint32 checksum);
1377 bool load_level_from_map(short level_index);
1378 uint32 get_current_map_checksum(void);
1379 bool select_map_to_use(void);
1380 
1381 /* Call with location of NULL to get the number of start locations for a */
1382 /* given team or player */
1383 short get_player_starting_location_and_facing(short team, short index,
1384 	struct object_location *location);
1385 
1386 void pause_game(void);
1387 void resume_game(void);
1388 
1389 bool get_indexed_entry_point(struct entry_point *entry_point, short *index, int32 type);
1390 bool get_entry_points(vector<entry_point> &vec, int32 type);
1391 
1392 bool new_game(short number_of_players, bool network,
1393 	struct game_data *game_information,
1394 	struct player_start_data *player_start_information,
1395 	struct entry_point *entry_point);
1396 bool goto_level(struct entry_point *entry, bool new_game, short number_of_players);
1397 
1398 class InfoTree;
1399 void parse_mml_texture_loading(const InfoTree& root);
1400 void reset_mml_texture_loading();
1401 
1402 #endif
1403