Map

From AlephWiki

Jump to: navigation, search

Marathon 2 Map File Format

Return to History

WARNING: This is the majority of the stuff that I think will be useful to those intrepid souls writing Marathon 2 extensions. The data contained herein is correct as far as I can tell. I have also included a program that dumps the files out so you can see the internal structures, as well as the offsets. Use this to verify that your output is correct. If you wish to make addendums, please do so at the end of this document and leave this warning intact. Thanks, and good luck!

-Ryan rdm4@acpub.duke.edu

/* WAD.H Thursday, June 30, 1994 10:55:20 PM

Sunday, July 3, 1994 5:51:47 PM I wonder if I should include an element size in the entry_header structure...

Tuesday, December 13, 1994 4:10:48 PM Included element size in the entry_header for the directory size. The directory is application_specific_directory_data_size+sizeof(struct directory_entry).

  • /
  1. define CURRENT_WADFILE_VERSION (2)
  1. define MAXIMUM_DIRECTORY_ENTRIES_PER_FILE 64
  2. define MAXIMUM_WADFILE_NAME_LENGTH 64
  3. define MAXIMUM_UNION_WADFILES 16
  4. define MAXIMUM_OPEN_WADFILES 3

/* ------------- typedefs */ typedef unsigned long WadDataType;

/* ------------- file structures */ struct wad_header { /* 128 bytes */ short version; /* Used internally */ short data_version; /* Used by the data.. */ char file_name[MAXIMUM_WADFILE_NAME_LENGTH]; unsigned long checksum; long directory_offset; short wad_count; short application_specific_directory_data_size; short entry_header_size; short directory_entry_base_size; unsigned long parent_checksum; /* If non-zero, this is the checksum of our parent, and we are simply modifications! */ short unused[20]; };

struct directory_entry { /* 10 bytes */ long offset_to_start; /* From start of file */ long length; /* Of total level */ short index; /* For inplace modification of the wadfile! */ };

struct entry_header { /* 16 bytes */ WadDataType tag; long next_offset; /* From current file location-> ie directory_entry.offset_to_start+next_offset */ long length; /* Of entry */ long offset; /* Offset for inplace expansion of data */

/* Data follows */ };


/* TAGS.H Sunday, July 3, 1994 5:33:15 PM

This is a list of all of the tags used by code that uses the wad file format. One tag, KEY_TAG, has special meaning, and KEY_TAG_SIZE must be set to the size of an index entry. Each wad can only have one index entry. You can get the index entry from a wad, or from all of the wads in the file easily.

Marathon uses the KEY_TAG as the name of the level.

  • /
  1. define MAXIMUM_LEVEL_NAME_SIZE 64

/* OSTypes.. */

  1. define APPLICATION_CREATOR '52.4'
  2. define SHAPES_FILE_TYPE 'shp2'
  3. define SOUNDS_FILE_TYPE 'snd2'
  4. define FILM_FILE_TYPE 'fil2'
  1. define SCENARIO_FILE_TYPE 'sce2' /* This is a wad file.. */
  2. define SAVE_GAME_TYPE 'sga2' /* This is a wad file.. */
  3. define PHYSICS_FILE_TYPE 'phy2' /* This is a wad file.. */
  4. define PATCH_FILE_TYPE 'pat2' /* This is a wad file.. */

/* Other tags- */

  1. define POINT_TAG 'PNTS'
  2. define LINE_TAG 'LINS'
  3. define SIDE_TAG 'SIDS'
  4. define POLYGON_TAG 'POLY'
  5. define LIGHTSOURCE_TAG 'LITE'
  6. define ANNOTATION_TAG 'NOTE'
  7. define OBJECT_TAG 'OBJS'
  8. define GUARDPATH_TAG 'pŒth'
  9. define MAP_INFO_TAG 'Minf'
  10. define ITEM_PLACEMENT_STRUCTURE_TAG 'plac'
  11. define DOOR_EXTRA_DATA_TAG 'door'
  12. define PLATFORM_STATIC_DATA_TAG 'plat'
  13. define ENDPOINT_DATA_TAG 'EPNT'
  14. define MEDIA_TAG 'medi'
  15. define AMBIENT_SOUND_TAG 'ambi'
  16. define RANDOM_SOUND_TAG 'bonk'
  17. define TERMINAL_DATA_TAG 'term'

/* Save/Load game tags. */

  1. define PLAYER_STRUCTURE_TAG 'plyr'
  2. define DYNAMIC_STRUCTURE_TAG 'dwol'
  3. define OBJECT_STRUCTURE_TAG 'mobj'
  4. define MAP_INDEXES_TAG 'iidx'
  5. define AUTOMAP_LINES 'alin'
  6. define AUTOMAP_POLYGONS 'apol'
  7. define MONSTERS_STRUCTURE_TAG 'mOns'
  8. define EFFECTS_STRUCTURE_TAG 'fx '
  9. define PROJECTILES_STRUCTURE_TAG 'bang'
  10. define PLATFORM_STRUCTURE_TAG 'PLAT'
  11. define WEAPON_STATE_TAG 'weap'
  12. define TERMINAL_STATE_TAG 'cint'

/* Physics model tags */

  1. define MONSTER_PHYSICS_TAG 'MNpx'
  2. define EFFECTS_PHYSICS_TAG 'FXpx'
  3. define PROJECTILE_PHYSICS_TAG 'PRpx'
  4. define PHYSICS_PHYSICS_TAG 'PXpx'
  5. define WEAPONS_PHYSICS_TAG 'WPpx'

/* Application Specific directory structure...

This data is copied from the map info data. It is stored separetely for faster access.

  • /

struct directory_data { short mission_flags; short environment_flags; long entry_point_flags; char level_name[LEVEL_NAME_LENGTH]; };

enum { /* entry point types- this is per map level (long). */ _single_player_entry_point= 0x01, _multiplayer_cooperative_entry_point= 0x02, _multiplayer_carnage_entry_point= 0x04, _capture_the_flag_entry_point= 0x08, _king_of_hill_entry_point= 0x10 };

enum /* mission flags */ { _mission_none= 0x0000, _mission_extermination= 0x0001, _mission_exploration= 0x0002, _mission_retrieval= 0x0004, _mission_repair= 0x0008, _mission_rescue= 0x0010 };

enum /* environment flags */ { _environment_normal= 0x0000, _environment_vacuum= 0x0001, // prevents certain weapons from working, player uses oxygen _environment_magnetic= 0x0002, // motion sensor works poorly _environment_rebellion= 0x0004, // makes clients fight pfhor _environment_low_gravity= 0x0008, // low gravity

_environment_network= 0x2000, // these two pseudo-environments are used to prevent items _environment_single_player= 0x4000 // from arriving in the items.c code. };


/* ----------------------------- Map tags ----------------- */

  1. define POINT_TAG 'PNTS'

An array of: struct world_point2d { short x, y; };

  1. define LINE_TAG 'LINS'

/* ------------ line definition */

  1. define SOLID_LINE_BIT 0x4000
  2. define TRANSPARENT_LINE_BIT 0x2000
  3. define LANDSCAPE_LINE_BIT 0x1000
  4. define ELEVATION_LINE_BIT 0x800
  5. define VARIABLE_ELEVATION_LINE_BIT 0x400
  6. define LINE_HAS_TRANSPARENT_SIDE_BIT 0x200
  1. define SET_LINE_SOLIDITY(l,v) ((v)?((l)->flags_=(word)SOLID_LINE_BIT):((l)->flags&=(word)~SOLID_LINE_BIT))
  2. define LINE_IS_SOLID(l) ((l)->flags&SOLID_LINE_BIT)
  1. define SET_LINE_TRANSPARENCY(l,v) ((v)?((l)->flags_=(word)TRANSPARENT_LINE_BIT):((l)->flags&=(word)~TRANSPARENT_LINE_BIT))
  2. define LINE_IS_TRANSPARENT(l) ((l)->flags&TRANSPARENT_LINE_BIT)
  1. define SET_LINE_LANDSCAPE_STATUS(l,v) ((v)?((l)->flags_=(word)LANDSCAPE_LINE_BIT):((l)->flags&=(word)~LANDSCAPE_LINE_BIT))
  2. define LINE_IS_LANDSCAPED(l) ((l)->flags&LANDSCAPE_LINE_BIT)
  1. define SET_LINE_ELEVATION(l,v) ((v)?((l)->flags_=(word)ELEVATION_LINE_BIT):((l)->flags&=(word)~ELEVATION_LINE_BIT))
  2. define LINE_IS_ELEVATION(l) ((l)->flags&ELEVATION_LINE_BIT)
  1. define SET_LINE_VARIABLE_ELEVATION(l,v) ((v)?((l)->flags_=(word)VARIABLE_ELEVATION_LINE_BIT):((l)->flags&=(word)~VARIABLE_ELEVATION_LINE_BIT))
  2. define LINE_IS_VARIABLE_ELEVATION(l) ((l)->flags&VARIABLE_ELEVATION_LINE_BIT)
  1. define SET_LINE_HAS_TRANSPARENT_SIDE(l,v) ((v)?((l)->flags_=(word)LINE_HAS_TRANSPARENT_SIDE_BIT):((l)->flags&=(word)~LINE_HAS_TRANSPARENT_SIDE_BIT))
  2. define LINE_HAS_TRANSPARENT_SIDE(l) ((l)->flags&LINE_HAS_TRANSPARENT_SIDE_BIT)

struct line_data /* 32 bytes */ { short endpoint_indexes[2]; word flags; /* no permutation field */

world_distance length; world_distance highest_adjacent_floor, lowest_adjacent_ceiling;

/* the side definition facing the clockwise polygon which references this side, and the side definition facing the counterclockwise polygon (can be NONE) */ short clockwise_polygon_side_index, counterclockwise_polygon_side_index;

/* a line can be owned by a clockwise polygon, a counterclockwise polygon, or both (but never two of the same) (can be NONE) */ short clockwise_polygon_owner, counterclockwise_polygon_owner;

short unused[6]; };


  1. define SIDE_TAG 'SIDS'

enum /* side flags */ { _control_panel_status= 0x0001, _side_is_control_panel= 0x0002, _side_is_repair_switch= 0x0004, // must be toggled to exit level _side_is_destructive_switch= 0x0008, // uses an item _side_is_lighted_switch= 0x0010, // switch must be lighted to use _side_switch_can_be_destroyed= 0x0020, // projectile hits toggle and destroy this switch _side_switch_can_only_be_hit_by_projectiles= 0x0040,

_editor_dirty_bit= 0x4000 // used by the editor... };

enum /* control panel side types */ { _panel_is_oxygen_refuel, _panel_is_shield_refuel, _panel_is_double_shield_refuel, _panel_is_triple_shield_refuel, _panel_is_light_switch, // light index in .permutation _panel_is_platform_switch, // platform index in .permutation _panel_is_tag_switch, // tag in .permutation (NONE is tagless) _panel_is_pattern_buffer, _panel_is_computer_terminal, NUMBER_OF_CONTROL_PANELS };

  1. define SIDE_IS_CONTROL_PANEL(s) ((s)->flags & _side_is_control_panel)
  2. define SET_SIDE_CONTROL_PANEL(s, t) ((t) ? (s->flags _= (word) _side_is_control_panel) : (s->flags &= (word)~_side_is_control_panel))
  1. define GET_CONTROL_PANEL_STATUS(s) ((s)->flags & _control_panel_status)
  2. define SET_CONTROL_PANEL_STATUS(s, t) ((t) ? (s->flags _= (word) _control_panel_status) : (s->flags &= (word)~_control_panel_status))
  3. define TOGGLE_CONTROL_PANEL_STATUS(s) ((s)->flags ^= _control_panel_status)
  1. define SIDE_IS_REPAIR_SWITCH(s) ((s)->flags & _side_is_repair_switch)
  2. define SET_SIDE_IS_REPAIR_SWITCH(s, t) ((t) ? (s->flags _= (word) _side_is_repair_switch) : (s->flags &= (word)~_side_is_repair_switch))

/* Flags used by Vulcan */

  1. define SIDE_IS_DIRTY(s) ((s)->flags&_editor_dirty_bit)
  2. define SET_SIDE_IS_DIRTY(s, t) ((t)?(s->flags_=(word)_editor_dirty_bit):(s->flags&=(word)~_editor_dirty_bit))

enum /* side types (largely redundant; most of this could be guessed for examining adjacent polygons) */ { _full_side, /* primary texture is mapped floor-to-ceiling */ _high_side, /* primary texture is mapped on a panel coming down from the ceiling (implies 2 adjacent polygons) */ _low_side, /* primary texture is mapped on a panel coming up from the floor (implies 2 adjacent polygons) */ _composite_side, /* primary texture is mapped floor-to-ceiling, secondary texture is mapped into it (i.e., control panel) */ _split_side /* primary texture is mapped onto a panel coming down from the ceiling, secondary texture is mapped on a panel coming up from the floor */ };

struct side_texture_definition { world_distance x0, y0; shape_descriptor texture; };

struct side_exclusion_zone { world_point2d e0, e1, e2, e3; };

struct side_data /* 64 bytes */ { short type; word flags;

struct side_texture_definition primary_texture; struct side_texture_definition secondary_texture; struct side_texture_definition transparent_texture; /* not drawn if .texture==NONE */

/* all sides have the potential of being impassable; the exclusion zone is the area near the side which cannot be walked through */ struct side_exclusion_zone exclusion_zone;

short control_panel_type; /* Only valid if side->flags & _side_is_control_panel */ short control_panel_permutation; /* platform index, light source index, etc... */

short primary_transfer_mode; /* These should be in the side_texture_definition.. */ short secondary_transfer_mode; short transparent_transfer_mode;

short polygon_index, line_index;

short primary_lightsource_index; short secondary_lightsource_index; short transparent_lightsource_index;

fixed ambient_delta;

short unused[1]; };

  1. define POLYGON_TAG 'POLY'
  1. define MAXIMUM_VERTICES_PER_POLYGON 8

enum /* polygon types */ { _polygon_is_normal, _polygon_is_item_impassable, _polygon_is_monster_impassable, _polygon_is_hill, /* for king-of-the-hill */ _polygon_is_base, /* for capture the flag, rugby, etc. (team in .permutation) */ _polygon_is_platform, /* platform index in .permutation */ _polygon_is_light_on_trigger, /* lightsource index in .permutation */ _polygon_is_platform_on_trigger, /* polygon index in .permutation */ _polygon_is_light_off_trigger, /* lightsource index in .permutation */ _polygon_is_platform_off_trigger, /* polygon index in .permutation */ _polygon_is_teleporter, /* .permutation is polygon_index of destination */ _polygon_is_zone_border, _polygon_is_goal, _polygon_is_visible_monster_trigger, _polygon_is_invisible_monster_trigger, _polygon_is_dual_monster_trigger, _polygon_is_item_trigger, /* activates all items in this zone */ _polygon_must_be_explored, _polygon_is_automatic_exit /* if success conditions are met, causes automatic transport too next level */ };

  1. define POLYGON_IS_DETACHED_BIT 0x4000
  2. define POLYGON_IS_DETACHED(p) ((p)->flags&POLYGON_IS_DETACHED_BIT)
  3. define SET_POLYGON_DETACHED_STATE(p, v) ((v)?((p)->flags_=POLYGON_IS_DETACHED_BIT):((p)->flags&=~POLYGON_IS_DETACHED_BIT))

struct polygon_data /* 128 bytes */ { short type; word flags; short permutation;

short vertex_count; short endpoint_indexes[MAXIMUM_VERTICES_PER_POLYGON]; /* clockwise */ short line_indexes[MAXIMUM_VERTICES_PER_POLYGON];

shape_descriptor floor_texture, ceiling_texture; world_distance floor_height, ceiling_height; short floor_lightsource_index, ceiling_lightsource_index;

long area; /* in world_distance^2 units */

short first_object;

/* precalculated impassability information; each polygon has a list of lines and points that anything big (i.e., monsters but not projectiles) inside it must check against when ending a move inside it. */ short first_exclusion_zone_index; short line_exclusion_zone_count; short point_exclusion_zone_count;

short floor_transfer_mode; short ceiling_transfer_mode;

short adjacent_polygon_indexes[MAXIMUM_VERTICES_PER_POLYGON];

/* a list of polygons within WORLD_ONE of us */ short first_neighbor_index; short neighbor_count;

world_point2d center;

short side_indexes[MAXIMUM_VERTICES_PER_POLYGON];

world_point2d floor_origin, ceiling_origin;

short media_index; short media_lightsource_index;

/* NONE terminated list of _saved_sound_source indexes which must be checked while a listener is inside this polygon (can be none) */ short sound_source_indexes;

// either can be NONE short ambient_sound_image_index; short random_sound_image_index;

short unused[1]; };


  1. define LIGHTSOURCE_TAG 'LITE'

/* ---------- constants */

  1. define MAXIMUM_LIGHTS_PER_MAP 64

enum /* default light types */ { _normal_light, _strobe_light, _media_light, NUMBER_OF_LIGHT_TYPES };

enum /* states */ { _light_becoming_active, _light_primary_active, _light_secondary_active, _light_becoming_inactive, _light_primary_inactive, _light_secondary_inactive };

/* ---------- static light data */

enum /* lighting functions */ { _constant_lighting_function, // maintain final intensity for period _linear_lighting_function, // linear transition between initial and final intensity over period _smooth_lighting_function, // sine transition between initial and final intensity over period _flicker_lighting_function, // intensity in [smooth_intensity(t),final_intensity] NUMBER_OF_LIGHTING_FUNCTIONS };

/* as intensities, transition functions are given the primary periods of the active and inactive state, plus the intensity at the time of transition */ struct lighting_function_specification /* 7*2 == 14 bytes */ { short function;

short period, delta_period; fixed intensity, delta_intensity; };

enum /* static flags */ { _light_is_initially_active, _light_has_slaved_intensities, _light_is_stateless, NUMBER_OF_STATIC_LIGHT_FLAGS /* <=16 */ };

  1. define LIGHT_IS_INITIALLY_ACTIVE(s) TEST_FLAG16((s)->flags, _light_is_initially_active)
  2. define LIGHT_IS_STATELESS(s) TEST_FLAG16((s)->flags, _light_is_stateless)
  1. define SET_LIGHT_IS_INITIALLY_ACTIVE(s, v) SET_FLAG16((s)->flags, _light_is_initially_active, (v))
  2. define SET_LIGHT_IS_STATELESS(s, v) SET_FLAG16((s)->flags, _light_is_stateless, (v))

struct static_light_data /* 8*2 + 6*14 == 100 bytes */ { short type; word flags;

short phase; // initializer, so lights may start out-of-phase with each other

struct lighting_function_specification primary_active, secondary_active, becoming_active; struct lighting_function_specification primary_inactive, secondary_inactive, becoming_inactive;

short tag;

short unused[4]; };

/* ---------- dynamic light data */

struct light_data /* 14*2 + 100 == 128 bytes */ { word flags; short state;

// result of lighting function fixed intensity;

// data recalculated each function changed; passed to lighting_function each update short phase, period; fixed initial_intensity, final_intensity;

short unused[4];

struct static_light_data static_data; };


  1. define ANNOTATION_TAG 'NOTE'
  1. define MAXIMUM_ANNOTATIONS_PER_MAP 20
  2. define MAXIMUM_ANNOTATION_TEXT_LENGTH 64

struct map_annotation { short type; /* turns into color, font, size, style, etc... */

world_point2d location; /* where to draw this (lower left) */ short polygon_index; /* only displayed if this polygon is in the automap */

char text[MAXIMUM_ANNOTATION_TEXT_LENGTH]; };


  1. define OBJECT_TAG 'OBJS'
  1. define MAXIMUM_SAVED_OBJECTS 384

enum /* map object types */ { _saved_monster, /* .index is monster type */ _saved_object, /* .index is scenery type */ _saved_item, /* .index is item type */ _saved_player, /* .index is team bitfield */ _saved_goal, /* .index is goal number */ _saved_sound_source /* .index is source type, .facing is sound volume */ };

enum /* map object flags */ { _map_object_is_invisible= 0x0001, /* initially invisible */ _map_object_is_platform_sound= 0x0001, _map_object_hanging_from_ceiling= 0x0002, /* used for calculating absolute .z coordinate */ _map_object_is_blind= 0x0004, /* monster cannot activate by sight */ _map_object_is_deaf= 0x0008, /* monster cannot activate by sound */ _map_object_floats= 0x0010, /* used by sound sources caused by media */ _map_object_is_network_only= 0x0020 /* for items only */

// top four bits is activation bias for monsters };

  1. define DECODE_ACTIVATION_BIAS(f) ((f)>>12)
  2. define ENCODE_ACTIVATION_BIAS(b) ((b)<<12)

struct map_object /* 16 bytes */ { short type; /* _saved_monster, _saved_object, _saved_item, ... */ short index; short facing; short polygon_index; world_point3d location; // .z is a delta

word flags; };

  1. define MAP_INFO_TAG 'Minf'

struct static_data { short environment_code;

short physics_model; short song_index; short mission_flags; short environment_flags;

short unused[4];

char level_name[LEVEL_NAME_LENGTH]; long entry_point_flags; };

  1. define ITEM_PLACEMENT_STRUCTURE_TAG 'plac'

/* ---------- new object frequency structures. */

  1. define MAXIMUM_OBJECT_TYPES 64

enum // flags for object_frequency_definition { _reappears_in_random_location= 0x0001 };

struct object_frequency_definition { word flags;

short initial_count; // number that initially appear. can be greater than maximum_count short minimum_count; // this number of objects will be maintained. short maximum_count; // canÕt exceed this, except at the beginning of the level.

short random_count; // maximum random occurences of the object word random_chance; // in (0, 65535] };


  1. define PLATFORM_STATIC_DATA_TAG 'plat'
  1. define MAXIMUM_PLATFORMS_PER_MAP 64

enum /* platform types */ { _platform_is_spht_door, _platform_is_spht_split_door, _platform_is_locked_spht_door, _platform_is_spht_platform, _platform_is_noisy_spht_platform, _platform_is_heavy_spht_door, _platform_is_pfhor_door, _platform_is_heavy_spht_platform, _platform_is_pfhor_platform,

NUMBER_OF_PLATFORM_TYPES };

enum /* platform speeds */ { _very_slow_platform= WORLD_ONE/(4*TICKS_PER_SECOND), _slow_platform= WORLD_ONE/(2*TICKS_PER_SECOND), _fast_platform= 2*_slow_platform, _very_fast_platform= 3*_slow_platform, _blindingly_fast_platform= 4*_slow_platform };

enum /* platform delays */ { _no_delay_platform= 0, /* use carefully; difficult to reincarnate on */ _short_delay_platform= TICKS_PER_SECOND, _long_delay_platform= 2*TICKS_PER_SECOND, _very_long_delay_platform= 4*TICKS_PER_SECOND, _extremely_long_delay_platform= 8*TICKS_PER_SECOND };

enum /* static platform flags */ { _platform_is_initially_active, /* otherwise inactive */ _platform_is_initially_extended, /* high for floor platforms, low for ceiling platforms, closed for two-way platforms */ _platform_deactivates_at_each_level, /* this platform will deactivate each time it reaches a discrete level */ _platform_deactivates_at_initial_level, /* this platform will deactivate upon returning to its original position */ _platform_activates_adjacent_platforms_when_deactivating, /* when deactivating, this platform activates adjacent platforms */ _platform_extends_floor_to_ceiling, /* i.e., there is no empty space when the platform is fully extended */ _platform_comes_from_floor, /* platform rises from floor */ _platform_comes_from_ceiling, /* platform lowers from ceiling */ _platform_causes_damage, /* when obstructed by monsters, this platform causes damage */ _platform_does_not_activate_parent, /* does not reactive itÕs parent (i.e., that platform which activated it) */ _platform_activates_only_once, /* cannot be activated a second time */ _platform_activates_light, /* activates floor and ceiling lightsources while activating */ _platform_deactivates_light, /* deactivates floor and ceiling lightsources while deactivating */ _platform_is_player_controllable, /* i.e., door: players can use action key to change the state and/or direction of this platform */ _platform_is_monster_controllable, /* i.e., door: monsters can expect to be able to move this platform even if inactive */ _platform_reverses_direction_when_obstructed, _platform_cannot_be_externally_deactivated, /* when active, can only be deactivated by itself */ _platform_uses_native_polygon_heights, /* complicated interpretation; uses native polygon heights during automatic min,max calculation */ _platform_delays_before_activation, /* whether or not the platform begins with the maximum delay before moving */ _platform_activates_adjacent_platforms_when_activating, _platform_deactivates_adjacent_platforms_when_activating, _platform_deactivates_adjacent_platforms_when_deactivating, _platform_contracts_slower, _platform_activates_adjacent_platforms_at_each_level, _platform_is_locked, _platform_is_secret, _platform_is_door, NUMBER_OF_STATIC_PLATFORM_FLAGS /* <=32 */ };

struct static_platform_data { short type; short speed, delay; world_distance maximum_height, minimum_height; /* if NONE then calculated in some reasonable way */

unsigned long static_flags;

short polygon_index;

short tag;

short unused[7]; };


  1. define ENDPOINT_DATA_TAG 'EPNT'

Don't worry about this one, because Marathon2 will calculate it for you.

  1. define MEDIA_TAG 'medi'
  1. define MAXIMUM_MEDIAS_PER_MAP 16

enum /* media types */ { _media_water, _media_lava, _media_goo, _media_sewage, NUMBER_OF_MEDIA_TYPES };

enum /* media flags */ { _media_sound_obstructed_by_floor, // this media makes no sound when under the floor

NUMBER_OF_MEDIA_FLAGS /* <= 16 */ };

  1. define MEDIA_SOUND_OBSTRUCTED_BY_FLOOR(m) TEST_FLAG16((m)->flags, _media_sound_obstructed_by_floor)
  1. define SET_MEDIA_SOUND_OBSTRUCTED_BY_FLOOR(m, v) SET_FLAG16((m)->flags, _media_sound_obstructed_by_floor, (v))

enum /* media detonation types */ { _small_media_detonation_effect, _medium_media_detonation_effect, _large_media_detonation_effect, _large_media_emergence_effect, NUMBER_OF_MEDIA_DETONATION_TYPES };

enum /* media sounds */ { _media_snd_feet_entering, _media_snd_feet_leaving, _media_snd_head_entering, _media_snd_head_leaving, _media_snd_splashing, _media_snd_ambient_over, _media_snd_ambient_under, _media_snd_platform_entering, _media_snd_platform_leaving,

NUMBER_OF_MEDIA_SOUNDS };

/* ---------- structures */

struct media_data /* 32 bytes */ { short type; word flags;

/* this light is not used as a real light; instead, the intensity of this light is used to determine the height of the media: height= low + (high-low)*intensity ... this sounds gross, but it makes media heights as flexible as light intensities; clearly discontinuous light functions (e.g., strobes) should not be used */ short light_index;

/* this is the maximum external velocity due to current; acceleration is 1/32nd of this */ angle current_direction; world_distance current_magnitude;

world_distance low, high;

world_point2d origin; world_distance height;

fixed minimum_light_intensity; shape_descriptor texture; short transfer_mode;

short unused[2]; };


  1. define AMBIENT_SOUND_TAG 'ambi'
  1. define MAXIMUM_AMBIENT_SOUND_IMAGES_PER_MAP 64

// non-directional ambient component struct ambient_sound_image_data // 16 bytes { word flags;

short sound_index; short volume;

short unused[5]; };

  1. define RANDOM_SOUND_TAG 'bonk'
  1. define MAXIMUM_RANDOM_SOUND_IMAGES_PER_MAP 64

enum // sound image flags { _sound_image_is_non_directional= 0x0001 // ignore direction };

// possibly directional random sound effects struct random_sound_image_data // 32 bytes { word flags;

short sound_index;

short volume, delta_volume; short period, delta_period; angle direction, delta_direction; fixed pitch, delta_pitch;

// only used at run-time; initialize to NONE short phase;

short unused[3]; };

  1. define TERMINAL_DATA_TAG 'term'

/* Preprocessed format: static: long total_length; short grouping_count; short font_changes_count; short total_text_length; dynamic: struct terminal_groupings groups[grouping_count]; struct text_face_data[font_changes_count]; char text;

  • /

/* ------------ structures */ struct static_preprocessed_terminal_data { short total_length; short flags; short lines_per_page; /* Added for internationalization/sync problems */ short grouping_count; short font_changes_count; };

struct terminal_groupings { short flags; /* varies.. */ short type; /* _information_text, _checkpoint_text, _briefing_text, _movie, _sound_bite, _soundtrack */ short permutation; /* checkpoint id for chkpt, level id for _briefing, movie id for movie, sound id for sound, soundtrack id for soundtrack */ short start_index; short length; short maximum_line_count; };

struct text_face_data { short index; short face; short color; };

/* ----------------------------- Physics model tags ----------------- */

  1. define MONSTER_PHYSICS_TAG 'MNpx'

/* MONSTER_DEFINITIONS.H Monday, May 30, 1994 9:04:01 PM

  • /

/* ---------- macros */

  1. define TYPE_IS_NEUTRAL(definition,type) (!((definition->friends_definition->enemies)&monster_definitions[type].class))
  2. define TYPE_IS_ENEMY(definition,type) (definition->enemies&monster_definitions[type].class)
  3. define TYPE_IS_FRIEND(definition,type) (definition->friends&monster_definitions[type].class)

/* ---------- constants */

enum /* monster classes */ { _class_player_bit, _class_human_civilian_bit, _class_madd_bit, _class_possessed_hummer_bit,

_class_defender_bit,

_class_fighter_bit, _class_trooper_bit, _class_hunter_bit, _class_enforcer_bit, _class_juggernaut_bit, _class_hummer_bit,

_class_compiler_bit, _class_cyborg_bit, _class_assimilated_civilian_bit,

_class_tick_bit, _class_yeti_bit,

_class_player= 1<<_class_player_bit, _class_human_civilian= 1<<_class_human_civilian_bit, _class_madd= 1<<_class_madd_bit, _class_possessed_hummer= 1<<_class_possessed_hummer_bit, _class_human= _class_player__class_human_civilian__class_madd__class_possessed_hummer,

_class_defender= 1<<_class_defender_bit,

_class_fighter= 1<<_class_fighter_bit, _class_trooper= 1<<_class_trooper_bit, _class_hunter= 1<<_class_hunter_bit, _class_enforcer= 1<<_class_enforcer_bit, _class_juggernaut= 1<<_class_juggernaut_bit, _class_pfhor= _class_fighter__class_trooper__class_hunter__class_enforcer__class_juggernaut,

_class_compiler= 1<<_class_compiler_bit, _class_cyborg= 1<<_class_cyborg_bit, _class_assimilated_civilian= 1<<_class_assimilated_civilian_bit, _class_hummer= 1<<_class_hummer_bit, _class_client= _class_compiler__class_assimilated_civilian__class_cyborg__class_hummer,

_class_tick= 1<<_class_tick_bit, _class_yeti= 1<<_class_yeti_bit, _class_native= _class_tick__class_yeti,

_class_hostile_alien= _class_pfhor__class_client, _class_neutral_alien= _class_native };

enum /* intelligence: maximum polygon switches before losing lock */ { _intelligence_low= 2, _intelligence_average= 3, _intelligence_high= 8 };

enum /* door retry masks */ { _slow_door_retry_mask= 63, _normal_door_retry_mask= 31, _fast_door_retry_mask= 15, _vidmaster_door_retry_mask= 3 };

enum /* flags */ { _monster_is_omniscent= 0x1, /* ignores line-of-sight during find_closest_appropriate_target() */ _monster_flys= 0x2, _monster_is_alien= 0x4, /* moves slower on slower levels, etc. */ _monster_major= 0x8, /* type -1 is minor */ _monster_minor= 0x10, /* type +1 is major */ _monster_cannot_be_dropped= 0x20, /* low levels cannot skip this monster */ _monster_floats= 0x40, /* exclusive from flys; forces the monster to take +¶h gradually */ _monster_cannot_attack= 0x80, /* monster has no weapons and cannot attack (runs constantly to safety) */ _monster_uses_sniper_ledges= 0x100, /* sit on ledges and hurl shit at the player (ranged attack monsters only) */ _monster_is_invisible= 0x200, /* this monster uses _xfer_invisibility */ _monster_is_subtly_invisible= 0x400, /* this monster uses _xfer_subtle_invisibility */ _monster_is_kamakazi= 0x800, /* monster does shrapnel damage and will suicide if close enough to target */ _monster_is_berserker= 0x1000, /* below 1/4 vitality this monster goes berserk */ _monster_is_enlarged= 0x2000, /* monster is 1.25 times normal height */ _monster_has_delayed_hard_death= 0x4000, /* always dies soft, then switches to hard */ _monster_fires_symmetrically= 0x8000, /* fires at ±dy, simultaneously */ _monster_has_nuclear_hard_death= 0x10000, /* playerÕs screen whites out and slowly recovers */ _monster_cant_fire_backwards= 0x20000, /* monster canÕt turn more than 135¡ to fire */ _monster_can_die_in_flames= 0x40000, /* uses humanoid flaming body shape */ _monster_waits_with_clear_shot= 0x80000, /* will sit and fire (slowly) if we have a clear shot */ _monster_is_tiny= 0x100000, /* 0.25-size normal height */ _monster_attacks_immediately= 0x200000, /* monster will try an attack immediately */ _monster_is_not_afraid_of_water= 0x400000, _monster_is_not_afraid_of_sewage= 0x800000, _monster_is_not_afraid_of_lava= 0x1000000, _monster_is_not_afraid_of_goo= 0x2000000, _monster_can_teleport_under_media= 0x4000000, _monster_chooses_weapons_randomly= 0x8000000 /* monsters unable to open doors have door retry masks of NONE */ /* monsters unable to switch levels have min,max ledge deltas of 0 */ /* monsters unstopped by bullets have hit frames of NONE */ };

enum /* monster speeds (world_distance per tick); also used for projectiles */ { _speed_slow= WORLD_ONE/120, _speed_medium= WORLD_ONE/80, _speed_almost_fast= WORLD_ONE/70, _speed_fast= WORLD_ONE/40, _speed_superfast1= WORLD_ONE/30, _speed_superfast2= WORLD_ONE/28, _speed_superfast3= WORLD_ONE/26, _speed_superfast4= WORLD_ONE/24, _speed_superfast5= WORLD_ONE/22, _speed_blinding= WORLD_ONE/20, _speed_insane= WORLD_ONE/10 };

  1. define NORMAL_MONSTER_GRAVITY (WORLD_ONE/120)
  2. define NORMAL_MONSTER_TERMINAL_VELOCITY (WORLD_ONE/14)

/* ---------- monster definition structures */

struct attack_definition { short type; short repetitions; angle error; /* ±error is added to the firing angle */ world_distance range; /* beyond which we cannot attack */ short attack_shape; /* attack occurs when keyframe is displayed */

world_distance dx, dy, dz; /* +dy is right, +dx is out, +dz is up */ };

struct monster_definition /* <128 bytes */ { short collection;

short vitality; unsigned long immunities, weaknesses; unsigned long flags;

long class; /* our class */ long friends, enemies; /* bit fields of what classes we consider friendly and what types we donÕt like */

fixed sound_pitch; short activation_sound, friendly_activation_sound, clear_sound; short kill_sound, apology_sound, friendly_fire_sound; short flaming_sound; /* the scream we play when we go down in flames */ short random_sound, random_sound_mask; /* if moving and locked play this sound if we get time and our mask comes up */

short carrying_item_type; /* an item type we might drop if we donÕt explode */

world_distance radius, height; world_distance preferred_hover_height; world_distance minimum_ledge_delta, maximum_ledge_delta; fixed external_velocity_scale; short impact_effect, melee_impact_effect, contrail_effect;

short half_visual_arc, half_vertical_visual_arc; world_distance visual_range, dark_visual_range; short intelligence; short speed, gravity, terminal_velocity; short door_retry_mask; short shrapnel_radius; /* no shrapnel if NONE */ struct damage_definition shrapnel_damage;

shape_descriptor hit_shapes; shape_descriptor hard_dying_shape, soft_dying_shape; /* minus dead frame */ shape_descriptor hard_dead_shapes, soft_dead_shapes; /* NONE for vanishing */ shape_descriptor stationary_shape, moving_shape; shape_descriptor teleport_in_shape, teleport_out_shape;

/* which type of attack the monster actually uses is determined at attack time; typically melee attacks will occur twice as often as ranged attacks because the monster will be stopped (and stationary monsters attack twice as often as moving ones) */ short attack_frequency; struct attack_definition melee_attack; struct attack_definition ranged_attack; };

  1. define EFFECTS_PHYSICS_TAG 'FXpx'

enum /* flags */ { _end_when_animation_loops= 0x0001, _end_when_transfer_animation_loops= 0x0002, _sound_only= 0x0004, /* play the animationÕs initial sound and nothing else */ _make_twin_visible= 0x0008, _media_effect= 0x0010 };

/* ---------- structures */

struct effect_definition { short collection, shape;

fixed sound_pitch;

word flags; short delay, delay_sound; };


  1. define PROJECTILE_PHYSICS_TAG 'PRpx'


  1. define PHYSICS_PHYSICS_TAG 'PXpx'

/* ---------- constants */

enum /* projectile flags */ { _guided= 0x0001, _stop_when_animation_loops= 0x0002, _persistent= 0x0004, /* does stops doing damage and stops moving against a target, but doesn't vanish */ _alien_projectile= 0x0008, /* does less damage and moves slower on lower levels */ _affected_by_gravity= 0x0010, _no_horizontal_error= 0x0020, _no_vertical_error= 0x0040, _can_toggle_control_panels= 0x0080, _positive_vertical_error= 0x0100, _melee_projectile= 0x0200, /* can use a monsterÕs custom melee detonation */ _persistent_and_virulent= 0x0400, /* keeps moving and doing damage after a successful hit */ _usually_pass_transparent_side= 0x0800, _sometimes_pass_transparent_side= 0x1000, _doubly_affected_by_gravity= 0x2000, _rebounds_from_floor= 0x4000, /* unless v.z<kvzMIN */ _penetrates_media= 0x8000, /* huh uh huh ... i said penetrate */ _becomes_item_on_detonation= 0x10000, /* item type in .permutation field of projectile */ _bleeding_projectile= 0x20000, /* can use a monsterÕs custom bleeding detonation */ _horizontal_wander= 0x40000, /* random horizontal error perpendicular to direction of movement */ _vertical_wander= 0x80000, /* random vertical movement perpendicular to direction of movement */ _affected_by_half_gravity= 0x100000 };

/* ---------- structures */

struct projectile_definition { short collection, shape; /* collection can be NONE (invisible) */ short detonation_effect, media_detonation_effect; short contrail_effect, ticks_between_contrails, maximum_contrails; /* maximum of NONE is infinite */ short media_projectile_promotion;

world_distance radius; /* can be zero and will still hit */ world_distance area_of_effect; /* one target if ==0 */ struct damage_definition damage;

unsigned long flags;

world_distance speed; world_distance maximum_range;

fixed sound_pitch; short flyby_sound, rebound_sound; };


  1. define WEAPONS_PHYSICS_TAG 'WPpx'

enum /* weapon classes */ { _melee_class, /* normal weapon, no ammunition, both triggers do the same thing */ _normal_class, /* normal weapon, one ammunition type, both triggers do the same thing */ _dual_function_class, /* normal weapon, one ammunition type, trigger does something different */ _twofisted_pistol_class, /* two can be held at once (differnet triggers), same ammunition */ _multipurpose_class /* two weapons in one (assault rifle, grenade launcher), two different ammunition types with two separate triggers; secondary ammunition is discrete (i.e., it is never loaded explicitly but appears in the weapon) */ };

enum /* weapon flags */ { _no_flags= 0x0, _weapon_is_automatic= 0x01, _weapon_disappears_after_use= 0x02, _weapon_plays_instant_shell_casing_sound= 0x04, _weapon_overloads= 0x08, _weapon_has_random_ammo_on_pickup= 0x10, _powerup_is_temporary= 0x20, _weapon_reloads_in_one_hand= 0x40, _weapon_fires_out_of_phase= 0x80, _weapon_fires_under_media= 0x100, _weapon_triggers_share_ammo= 0x200, _weapon_secondary_has_angular_flipping= 0x400 };

enum { _weapon_in_hand_collection= 1, _fist_idle= 0, _fist_punching, _pistol_idle, _pistol_firing, _pistol_reloading, _shotgun_idle, _shotgun_firing, _shotgun_reloading, _assault_rifle_idle, _assault_rifle_firing, _assault_rifle_reloading, _fusion_idle, _fusion_firing, _missile_launcher_idle, _missile_launcher_firing, _flamethrower_idle, _flamethrower_transit, _flamethrower_firing, _assault_rifle_shell_casing, _pistol_shell_casing, _fusion_charged, _alien_weapon_idle, _alien_weapon_firing };

/* ---------- shell casings */

enum // shell casing types { _shell_casing_assault_rifle, _shell_casing_pistol, _shell_casing_pistol_left, _shell_casing_pistol_right,

NUMBER_OF_SHELL_CASING_TYPES };

struct shell_casing_definition { short collection, shape;

fixed x0, y0; fixed vx0, vy0; fixed dvx, dvy; };

struct trigger_definition { short rounds_per_magazine; short ammunition_type; short ticks_per_round; short recovery_ticks; short charging_ticks; world_distance recoil_magnitude; short firing_sound; short click_sound; short charging_sound; short shell_casing_sound; short reloading_sound; short charged_sound; short projectile_type; short theta_error; short dx, dz; short shell_casing_type; short burst_count; };

struct weapon_definition { short item_type; short powerup_type; short weapon_class; short flags;

fixed firing_light_intensity; short firing_intensity_decay_ticks;

/* weapon will come up to FIXED_ONE when fired; idle_height±bob_amplitude should be in the range [0,FIXED_ONE] */ fixed idle_height, bob_amplitude, kick_height, reload_height; fixed idle_width, horizontal_amplitude;

/* each weapon has three basic animations: idle, firing and reloading. sounds and frames are pulled from the shape collection. for automatic weapons the firing animation loops until the trigger is released or the gun is empty and the gun begins rising as soon as the trigger is depressed and is not lowered until the firing animation stops. for single shot weapons the animation loops once; the weapon is raised and lowered as soon as the firing animation terminates */ short collection; short idle_shape, firing_shape, reloading_shape; short unused; short charging_shape, charged_shape;

/* How long does it take to ready the weapon? */ /* load_rounds_tick is the point which you actually load them. */ short ready_ticks, await_reload_ticks, loading_ticks, finish_loading_ticks, powerup_ticks;

struct trigger_definition weapons_by_trigger[NUMBER_OF_TRIGGERS]; };

/* ----------------------------- Save/Load game tags ----------------- */ /* These tags are only present in a save game, and won't be detailed in this document...... */

  1. define PLAYER_STRUCTURE_TAG 'plyr'
  2. define DYNAMIC_STRUCTURE_TAG 'dwol'
  3. define OBJECT_STRUCTURE_TAG 'mobj'
  4. define MAP_INDEXES_TAG 'iidx'
  5. define AUTOMAP_LINES 'alin'
  6. define AUTOMAP_POLYGONS 'apol'
  7. define MONSTERS_STRUCTURE_TAG 'mOns'
  8. define EFFECTS_STRUCTURE_TAG 'fx '
  9. define PROJECTILES_STRUCTURE_TAG 'bang'
  10. define PLATFORM_STRUCTURE_TAG 'PLAT'
  11. define WEAPON_STATE_TAG 'weap'
  12. define TERMINAL_STATE_TAG 'cint'


typedef unsigned short word; typedef unsigned char byte; typedef byte boolean;

/* ---------- fixed math */

  1. define FIXED_FRACTIONAL_BITS 16
  2. define FIXED_ONE ((fixed)(1<<FIXED_FRACTIONAL_BITS))
  3. define FIXED_ONE_HALF ((fixed)(1<<(FIXED_FRACTIONAL_BITS-1)))
  1. define FIXED_TO_FLOAT(f) (((double)(f))/FIXED_ONE)
  2. define FLOAT_TO_FIXED(f) ((fixed)((f)*FIXED_ONE))
  1. define INTEGER_TO_FIXED(s) (((fixed)(s))<<FIXED_FRACTIONAL_BITS)
  2. define FIXED_INTEGERAL_PART(f) ((short)((f)>>FIXED_FRACTIONAL_BITS))
  3. define FIXED_FRACTIONAL_PART(f) (((fixed)(f))&(FIXED_ONE-1))

typedef long fixed;


  1. define WORLD_FRACTIONAL_BITS 10
  2. define WORLD_ONE ((world_distance)(1<<WORLD_FRACTIONAL_BITS))

typedef short angle; /* 0-512 */ typedef short world_distance;

enum /* damage types */ { _damage_explosion, _damage_electrical_staff, _damage_projectile, _damage_absorbed, _damage_flame, _damage_hound_claws, _damage_alien_projectile, _damage_hulk_slap, _damage_compiler_bolt, _damage_fusion_bolt, _damage_hunter_bolt, _damage_fist, _damage_teleporter, _damage_defender, _damage_yeti_claws, _damage_yeti_projectile, _damage_crushing, _damage_lava, _damage_suffocation, _damage_goo, _damage_energy_drain, _damage_oxygen_drain, _damage_hummer_bolt, _damage_shotgun_projectile };

enum /* damage flags */ { _alien_damage= 0x1 /* will be decreased at lower difficulty levels */ };

struct damage_definition { short type, flags;

short base, random; fixed scale; };


/* Physics structure */

enum /* models */ { _model_game_walking, _model_game_running, NUMBER_OF_PHYSICS_MODELS };

/* ---------- structures */

struct physics_constants { fixed maximum_forward_velocity, maximum_backward_velocity, maximum_perpendicular_velocity; fixed acceleration, deceleration, airborne_deceleration; /* forward, backward and perpendicular */ fixed gravitational_acceleration, climbing_acceleration, terminal_velocity; fixed external_deceleration;

fixed angular_acceleration, angular_deceleration, maximum_angular_velocity, angular_recentering_velocity; fixed fast_angular_velocity, fast_angular_maximum; /* for head movements */ fixed maximum_elevation; /* positive and negative */ fixed external_angular_deceleration;

/* step_length is distance between adjacent nodes in the actorÕs phase */ fixed step_delta, step_amplitude; fixed radius, height, dead_height, camera_height, splash_height;

fixed half_camera_separation; };


More questions and answers: > 2) LINS chunk: What does transparent_line_bit, landscape, elevation, > variable elevation mena? Do I need to set these in the lines flags and if > so, under what conditions?

Landscape tells that the line has a landscape texture on it. I think it is anacrhonistic, though I am not sure.

Transparent means that it has a transparent texture on it, and the graphics engine should treat it as though the wall wasn't there.

Not sure what elevation means, and can't look it up right now.

Variable elevation is the lines surrounding platforms, I am pretty sure.

> 3) I need the EPNT for reading in Bungie levels. I am using the one from > M1, and it is working.

Yeah, that should work.

> 4) SIDEs chunk: what is ambient delta? And what ranges can it be set to?

Ambient delta is for lightsources. We don't actually use it anywhere, (it was an early idea), but it effectively tints the wall based on the lightsources intensity + delta intensity.

> 5) OBJS chunk: the z co-ord = delta? Huh? or is this really the z-cord?

Depends on the flags. It depends on the _map_object_hanging_from_ceiling= 0x0002, /* used for calculating absolute .z coordinate */ flag.

> 6) In general, what are the tags fields for?

Tags are a way of making one switch or platform active multiple lights, platforms, etc.

> 7) The TERM chunk needs better explaning, perhaps an example?

This is the terminal texts for Marathon 2. It is a compiled format, something useful for you on this. Alternatively I might just release our Terminal Editor, which is what we used to generate these.

> 8) Any general info on putting this all together in a working map that can > not be easily deduced?

Should be just like before... ;)

1) The 'PLAT' type is not documented. The 'plat' type is. The map that came with M2 uses the 'PLAT' type. Can I get the info for this type?

PLAT is the dynamic version of plat. The structure is: struct platform_data /* 128 bytes */ { short type; unsigned long static_flags; short speed, delay; world_distance minimum_floor_height, maximum_floor_height; world_distance minimum_ceiling_height, maximum_ceiling_height;

short polygon_index; word dynamic_flags; world_distance floor_height, ceiling_height; short ticks_until_restart; /* if weÕre not moving but are active, this is our delay until we move again */

struct endpoint_owner_data endpoint_owners[MAXIMUM_VERTICES_PER_POLYGON];

short parent_platform_index; /* the platform_index which activated us, if any */

short tag;

short unused[22]; };


You shouldn't have to worry about this though- if you save properly formatted plat resources, marathon2 will convert them to PLAT on saving and loading.

2) The various types of control panels are not listed. Only the first 8 types. The Map that came with M2 uses types that go much higher. Can I get a list of these types?

enum // control panel sounds { _activating_sound, _deactivating_sound, _unusuable_sound,

NUMBER_OF_CONTROL_PANEL_SOUNDS };

struct control_panel_definition { short class; word flags;

short collection; short active_shape, inactive_shape;

short sounds[NUMBER_OF_CONTROL_PANEL_SOUNDS]; fixed sound_frequency;

short item; };

/* ---------- globals */

  1. define NUMBER_OF_CONTROL_PANEL_DEFINITIONS (sizeof(control_panel_definitions)/sizeof(struct control_panel_definition))

static struct control_panel_definition control_panel_definitions[]= { // _collection_walls1 {_panel_is_oxygen_refuel, 0, _collection_walls1, 2, 3, {_snd_oxygen_refuel, NONE, NONE}, FIXED_ONE, NONE}, {_panel_is_shield_refuel, 0, _collection_walls1, 2, 3, {_snd_energy_refuel, NONE, NONE}, FIXED_ONE, NONE}, {_panel_is_double_shield_refuel, 0, _collection_walls1, 2, 3, {_snd_energy_refuel, NONE, NONE}, FIXED_ONE+FIXED_ONE/8, NONE}, {_panel_is_tag_switch, 0, _collection_walls1, 0, 1, {_snd_chip_insertion, NONE, NONE}, FIXED_ONE, _i_uplink_chip}, {_panel_is_light_switch, 0, _collection_walls1, 0, 1, {_snd_switch_on, _snd_switch_off, _snd_cant_toggle_switch}, FIXED_ONE, NONE}, {_panel_is_platform_switch, 0, _collection_walls1, 0, 1, {_snd_switch_on, _snd_switch_off, _snd_cant_toggle_switch}, FIXED_ONE, NONE}, {_panel_is_tag_switch, 0, _collection_walls1, 0, 1, {_snd_switch_on, _snd_switch_off, _snd_cant_toggle_switch}, FIXED_ONE, NONE}, {_panel_is_pattern_buffer, 0, _collection_walls1, 4, 4, {_snd_pattern_buffer, NONE, NONE}, FIXED_ONE, NONE}, {_panel_is_computer_terminal, 0, _collection_walls1, 4, 4, {NONE, NONE, NONE}, FIXED_ONE, NONE}, {_panel_is_tag_switch, 0, _collection_walls1, 1, 0, {_snd_destroy_control_panel, NONE, NONE}, FIXED_ONE, NONE},

// _collection_walls2 {_panel_is_shield_refuel, 0, _collection_walls2, 2, 3, {_snd_energy_refuel, NONE, NONE}, FIXED_ONE, NONE}, {_panel_is_double_shield_refuel, 0, _collection_walls2, 2, 3, {_snd_energy_refuel, NONE, NONE}, FIXED_ONE+FIXED_ONE/8, NONE}, {_panel_is_triple_shield_refuel, 0, _collection_walls2, 2, 3, {_snd_energy_refuel, NONE, NONE}, FIXED_ONE+FIXED_ONE/4, NONE}, {_panel_is_light_switch, 0, _collection_walls2, 0, 1, {_snd_switch_on, _snd_switch_off, _snd_cant_toggle_switch}, FIXED_ONE, NONE}, {_panel_is_platform_switch, 0, _collection_walls2, 0, 1, {_snd_switch_on, _snd_switch_off, _snd_cant_toggle_switch}, FIXED_ONE, NONE}, {_panel_is_tag_switch, 0, _collection_walls2, 0, 1, {_snd_switch_on, _snd_switch_off, _snd_cant_toggle_switch}, FIXED_ONE, NONE}, {_panel_is_pattern_buffer, 0, _collection_walls2, 4, 4, {_snd_pattern_buffer, NONE, NONE}, FIXED_ONE, NONE}, {_panel_is_computer_terminal, 0, _collection_walls2, 4, 4, {NONE, NONE, NONE}, FIXED_ONE, NONE}, {_panel_is_oxygen_refuel, 0, _collection_walls2, 2, 3, {_snd_oxygen_refuel, NONE, NONE}, FIXED_ONE, NONE}, {_panel_is_tag_switch, 0, _collection_walls2, 0, 1, {_snd_chip_insertion, NONE, NONE}, FIXED_ONE, _i_uplink_chip}, {_panel_is_tag_switch, 0, _collection_walls2, 1, 0, {_snd_destroy_control_panel, NONE, NONE}, FIXED_ONE, NONE},

// _collection_walls3 {_panel_is_shield_refuel, 0, _collection_walls3, 2, 3, {_snd_energy_refuel, NONE, NONE}, FIXED_ONE, NONE}, {_panel_is_double_shield_refuel, 0, _collection_walls3, 2, 3, {_snd_energy_refuel, NONE, NONE}, FIXED_ONE+FIXED_ONE/8, NONE}, {_panel_is_triple_shield_refuel, 0, _collection_walls3, 2, 3, {_snd_energy_refuel, NONE, NONE}, FIXED_ONE+FIXED_ONE/4, NONE}, {_panel_is_light_switch, 0, _collection_walls3, 0, 1, {_snd_switch_on, _snd_switch_off, _snd_cant_toggle_switch}, FIXED_ONE, NONE}, {_panel_is_platform_switch, 0, _collection_walls3, 0, 1, {_snd_switch_on, _snd_switch_off, _snd_cant_toggle_switch}, FIXED_ONE, NONE}, {_panel_is_tag_switch, 0, _collection_walls3, 0, 1, {_snd_switch_on, _snd_switch_off, _snd_cant_toggle_switch}, FIXED_ONE, NONE}, {_panel_is_pattern_buffer, 0, _collection_walls3, 4, 4, {_snd_pattern_buffer, NONE, NONE}, FIXED_ONE, NONE}, {_panel_is_computer_terminal, 0, _collection_walls3, 4, 4, {NONE, NONE, NONE}, FIXED_ONE, NONE}, {_panel_is_oxygen_refuel, 0, _collection_walls3, 2, 3, {_snd_oxygen_refuel, NONE, NONE}, FIXED_ONE, NONE}, {_panel_is_tag_switch, 0, _collection_walls3, 0, 1, {_snd_chip_insertion, NONE, NONE}, FIXED_ONE, _i_uplink_chip}, {_panel_is_tag_switch, 0, _collection_walls3, 1, 0, {_snd_destroy_control_panel, NONE, NONE}, FIXED_ONE, NONE},

// _collection_walls4 {_panel_is_shield_refuel, 0, _collection_walls5, 2, 3, {_snd_energy_refuel, NONE, NONE}, FIXED_ONE, NONE}, {_panel_is_double_shield_refuel, 0, _collection_walls5, 2, 3, {_snd_energy_refuel, NONE, NONE}, FIXED_ONE+FIXED_ONE/8, NONE}, {_panel_is_triple_shield_refuel, 0, _collection_walls5, 2, 3, {_snd_energy_refuel, NONE, NONE}, FIXED_ONE+FIXED_ONE/4, NONE}, {_panel_is_light_switch, 0, _collection_walls5, 0, 1, {_snd_pfhor_switch_on, _snd_pfhor_switch_off, _snd_cant_toggle_switch}, FIXED_ONE, NONE}, {_panel_is_platform_switch, 0, _collection_walls5, 0, 1, {_snd_pfhor_switch_on, _snd_pfhor_switch_off, _snd_cant_toggle_switch}, FIXED_ONE, NONE}, {_panel_is_tag_switch, 0, _collection_walls5, 0, 1, {_snd_pfhor_switch_on, _snd_pfhor_switch_off, _snd_cant_toggle_switch}, FIXED_ONE, NONE}, {_panel_is_pattern_buffer, 0, _collection_walls5, 4, 4, {_snd_pattern_buffer, NONE, NONE}, FIXED_ONE, NONE}, {_panel_is_computer_terminal, 0, _collection_walls5, 4, 4, {NONE, NONE, NONE}, FIXED_ONE, NONE}, {_panel_is_oxygen_refuel, 0, _collection_walls5, 2, 3, {_snd_oxygen_refuel, NONE, NONE}, FIXED_ONE, NONE}, {_panel_is_tag_switch, 0, _collection_walls5, 0, 1, {_snd_chip_insertion, NONE, NONE}, FIXED_ONE, _i_uplink_chip}, {_panel_is_tag_switch, 0, _collection_walls5, 1, 0, {_snd_destroy_control_panel, NONE, NONE}, FIXED_ONE, NONE}, };

3) Is there a list of the various object types? I can create a list by placing all possible objects, and playing the map, but if there is a list it would be easier.

_saved_monster, /* .index is monster type */

enum /* monster types */ { _monster_marine, _monster_tick_energy, _monster_tick_oxygen, _monster_tick_kamakazi, _monster_compiler_minor, _monster_compiler_major, _monster_compiler_minor_invisible, _monster_compiler_major_invisible, _monster_fighter_minor, _monster_fighter_major, _monster_fighter_minor_projectile, _monster_fighter_major_projectile, _civilian_crew, _civilian_science, _civilian_security, _civilian_assimilated, _monster_hummer_minor, // slow hummer _monster_hummer_major, // fast hummer _monster_hummer_big_minor, // big hummer _monster_hummer_big_major, // angry hummer _monster_hummer_possessed, // hummer from durandal _monster_cyborg_minor, _monster_cyborg_major, _monster_cyborg_flame_minor, _monster_cyborg_flame_major, _monster_enforcer_minor, _monster_enforcer_major, _monster_hunter_minor, _monster_hunter_major, _monster_trooper_minor, _monster_trooper_major, _monster_mother_of_all_cyborgs, _monster_mother_of_all_hunters, _monster_sewage_yeti, _monster_water_yeti, _monster_lava_yeti, _monster_defender_minor, _monster_defender_major, _monster_juggernaut_minor, _monster_juggernaut_major, _monster_tiny_fighter, _monster_tiny_bob, _monster_tiny_yeti, NUMBER_OF_MONSTER_TYPES };

_saved_object, /* .index is scenery type */

struct scenery_definition { word flags; shape_descriptor shape;

world_distance radius, height;

short destroyed_effect; shape_descriptor destroyed_shape; };

struct scenery_definition scenery_definitions[]= { // lava {0, BUILD_DESCRIPTOR(_collection_scenery2, 3)}, // light dirt {0, BUILD_DESCRIPTOR(_collection_scenery2, 4)}, // dark dirt {0, BUILD_DESCRIPTOR(_collection_scenery2, 5)}, // bones {0, BUILD_DESCRIPTOR(_collection_scenery2, 6)}, // bone {0, BUILD_DESCRIPTOR(_collection_scenery2, 7)}, // ribs {0, BUILD_DESCRIPTOR(_collection_scenery2, 8)}, // skull {_scenery_is_solid__scenery_can_be_destroyed, BUILD_DESCRIPTOR(_collection_scenery2, 9), WORLD_ONE/8, -WORLD_ONE/8, _effect_lava_lamp_breaking, BUILD_DESCRIPTOR(_collection_scenery2, 19)}, // hanging light {_scenery_is_solid__scenery_can_be_destroyed, BUILD_DESCRIPTOR(_collection_scenery2, 10), WORLD_ONE/8, -WORLD_ONE/8, _effect_lava_lamp_breaking, BUILD_DESCRIPTOR(_collection_scenery2, 20)}, // hanging light {_scenery_is_solid, BUILD_DESCRIPTOR(_collection_scenery2, 12), WORLD_ONE/8, WORLD_ONE_HALF}, // small cylinder {_scenery_is_solid, BUILD_DESCRIPTOR(_collection_scenery2, 13), WORLD_ONE_FOURTH, WORLD_ONE_HALF}, // large cylinder {_scenery_is_solid, BUILD_DESCRIPTOR(_collection_scenery2, 14), WORLD_ONE_FOURTH, WORLD_ONE_HALF}, // block {_scenery_is_solid, BUILD_DESCRIPTOR(_collection_scenery2, 15), WORLD_ONE_FOURTH, WORLD_ONE_HALF}, // block {_scenery_is_solid, BUILD_DESCRIPTOR(_collection_scenery2, 16), WORLD_ONE_FOURTH, WORLD_ONE_HALF}, // block

// water {0, BUILD_DESCRIPTOR(_collection_scenery1, 4)}, // pistol clip {_scenery_is_solid__scenery_can_be_destroyed, BUILD_DESCRIPTOR(_collection_scenery1, 5), WORLD_ONE/6, -WORLD_ONE/8, _effect_water_lamp_breaking, BUILD_DESCRIPTOR(_collection_scenery1, 6)}, // short light {_scenery_is_solid__scenery_can_be_destroyed, BUILD_DESCRIPTOR(_collection_scenery1, 7), WORLD_ONE/8, -WORLD_ONE/8, _effect_water_lamp_breaking, BUILD_DESCRIPTOR(_collection_scenery1, 8)}, // long light {_scenery_is_solid__scenery_can_be_destroyed, BUILD_DESCRIPTOR(_collection_scenery1, 9), WORLD_ONE/4, -WORLD_ONE/6, _effect_grenade_explosion, BUILD_DESCRIPTOR(_collection_scenery1, 23)}, // siren {0, BUILD_DESCRIPTOR(_collection_scenery1, 10)}, // rocks {0, BUILD_DESCRIPTOR(_collection_scenery1, 21)}, // blood drops {_scenery_is_animated, BUILD_DESCRIPTOR(_collection_scenery1, 11)}, // water thing {0, BUILD_DESCRIPTOR(_collection_scenery1, 12)}, // gun {0, BUILD_DESCRIPTOR(_collection_scenery1, 13)}, // bob remains {0, BUILD_DESCRIPTOR(_collection_scenery1, 14)}, // puddles {0, BUILD_DESCRIPTOR(_collection_scenery1, 15)}, // big puddles {_scenery_is_solid, BUILD_DESCRIPTOR(_collection_scenery1, 16), WORLD_ONE_FOURTH, WORLD_ONE_HALF}, // security monitor {_scenery_is_solid, BUILD_DESCRIPTOR(_collection_scenery1, 17), WORLD_ONE_FOURTH, WORLD_ONE_HALF}, // alien supply can {_scenery_is_animated, BUILD_DESCRIPTOR(_collection_scenery1, 18)}, // machine {0, BUILD_DESCRIPTOR(_collection_scenery1, 20)}, // fighterÕs staff

// sewage {_scenery_is_solid__scenery_can_be_destroyed, BUILD_DESCRIPTOR(_collection_scenery3, 5), WORLD_ONE/6, -WORLD_ONE/8, _effect_sewage_lamp_breaking, BUILD_DESCRIPTOR(_collection_scenery3, 6)}, // stubby green light {_scenery_is_solid__scenery_can_be_destroyed, BUILD_DESCRIPTOR(_collection_scenery3, 7), WORLD_ONE/6, -WORLD_ONE/8, _effect_sewage_lamp_breaking, BUILD_DESCRIPTOR(_collection_scenery3, 8)}, // long green light {0, BUILD_DESCRIPTOR(_collection_scenery3, 4)}, // junk {0, BUILD_DESCRIPTOR(_collection_scenery3, 9)}, // big antenna {0, BUILD_DESCRIPTOR(_collection_scenery3, 10)}, // big antenna {_scenery_is_solid, BUILD_DESCRIPTOR(_collection_scenery3, 11), WORLD_ONE_FOURTH, WORLD_ONE_HALF}, // alien supply can {0, BUILD_DESCRIPTOR(_collection_scenery3, 13)}, // bones {0, BUILD_DESCRIPTOR(_collection_scenery3, 17)}, // big bones {0, BUILD_DESCRIPTOR(_collection_scenery3, 12)}, // pfhor pieces {0, BUILD_DESCRIPTOR(_collection_scenery3, 14)}, // bob pieces {0, BUILD_DESCRIPTOR(_collection_scenery3, 15)}, // bob blood

// alien {_scenery_is_solid__scenery_can_be_destroyed, BUILD_DESCRIPTOR(_collection_scenery5, 4), WORLD_ONE/6, -WORLD_ONE/8, _effect_alien_lamp_breaking, BUILD_DESCRIPTOR(_collection_scenery5, 5)}, // green light {_scenery_is_solid__scenery_can_be_destroyed, BUILD_DESCRIPTOR(_collection_scenery5, 14), WORLD_ONE/6, -WORLD_ONE/8, _effect_alien_lamp_breaking, BUILD_DESCRIPTOR(_collection_scenery5, 15)}, // small alien light {_scenery_is_solid__scenery_can_be_destroyed, BUILD_DESCRIPTOR(_collection_scenery5, 16), WORLD_ONE/6, -WORLD_ONE/8, _effect_alien_lamp_breaking, BUILD_DESCRIPTOR(_collection_scenery5, 17)}, // alien ceiling rod light {0, BUILD_DESCRIPTOR(_collection_scenery5, 6)}, // bulbous yellow alien object {0, BUILD_DESCRIPTOR(_collection_scenery5, 7)}, // square grey organic object {0, BUILD_DESCRIPTOR(_collection_scenery5, 9)}, // pfhor skeleton {0, BUILD_DESCRIPTOR(_collection_scenery5, 10)}, // pfhor mask {0, BUILD_DESCRIPTOR(_collection_scenery5, 11)}, // green stuff {0, BUILD_DESCRIPTOR(_collection_scenery5, 12)}, // hunter shield {0, BUILD_DESCRIPTOR(_collection_scenery5, 13)}, // bones {0, BUILD_DESCRIPTOR(_collection_scenery5, 18)}, // alien sludge };

_saved_item, /* .index is item type */ enum /* item types */ { _i_knife, _i_magnum, _i_magnum_magazine, _i_plasma_pistol, _i_plasma_magazine, _i_assault_rifle, _i_assault_rifle_magazine, _i_assault_grenade_magazine, _i_missile_launcher, _i_missile_launcher_magazine, _i_invisibility_powerup, _i_invincibility_powerup, _i_infravision_powerup, _i_alien_shotgun, _i_alien_shotgun_magazine, _i_flamethrower, _i_flamethrower_canister, _i_extravision_powerup, _i_oxygen_powerup, _i_energy_powerup, _i_double_energy_powerup, _i_triple_energy_powerup, _i_shotgun, _i_shotgun_magazine, _i_spht_door_key, _i_uplink_chip,

BALL_ITEM_BASE, _i_light_blue_ball= BALL_ITEM_BASE, _i_red_ball, _i_violet_ball, _i_yellow_ball, _i_brown_ball, _i_orange_ball, _i_blue_ball, _i_green_ball,

NUMBER_OF_DEFINED_ITEMS };

_saved_player, /* .index is team bitfield */ enum /* team colors */ { _violet_team, _red_team, _tan_team, _light_blue_team, _yellow_team, _brown_team, _blue_team, _green_team, NUMBER_OF_TEAM_COLORS };

_saved_goal, /* .index is goal number */ _saved_sound_source /* .index is source type, .facing is sound volume */


4) I have been able to make maps, but Marathon won't play them, the screen fades out and thats it. The map dump utility does not report any errors. Can I send you a small, one poly map for analysis?

Obviously I can't check every map, but if any of you want to send me a small one, I can run it through the debug version of Marathon2 and find out where it asserts. It will probably take me some time to get to that, though.

<tt>

Personal tools