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