=============================================================================== Universal Doom Map Format Specification v1.0 - 05/28/08 Written by James "Quasar" Haley - haleyjd@hotmail.com Defined with input from: CodeImp esselfortium Graf Zahl Kaiser SlayeR SoM et al. Copyright (c) 2008 James Haley. Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. =============================================================================== ======================================= I. Grammar / Syntax ======================================= translation_unit := global_expr_list global_expr_list := global_expr global_expr_list global_expr := block | assignment_expr block := identifier '{' expr_list '}' expr_list := assignment_expr expr_list assignment_expr := identifier '=' value ';' | nil identifier := [A-Za-z0-9_]+ value := integer | float | quoted_string | keyword integer := [+-]?[1-9]+[0-9]* | 0[0-9]+ | 0x[0-9A-Fa-f]+ float := [+-]?[0-9]+'.'[0-9]*([eE][+-]?[0-9]+)? quoted_string := "([^"\\]*(\\.[^"\\]*)*)" keyword := [^{}();"'\n\t ]+ Global assignments and named/indexed global blocks are the only top-level entities supported. Whitespace is strictly ignored. Comments are supported as C-style single and multi-line comments: // single line comment /* multi line comment */ Multi-line comments may not be nested. Implementing editors are not required (but are allowed) to maintain syntactic comments when rewriting UDMF map lumps. These comments are provided chiefly for hand-writing and debugging purposes. Blocks begin with a keyword identifier. An example of a minimally-defined entity follows: linedef { id = 1; } Compliant parsers will ignore all unknown keywords in global assignments, block-level assignments, and block headers. Compliant parsers should attempt to preserve as much of such information as is possible by using a flexible mapping such as hashing. Identifiers and keywords are to be treated as case insensitive. A field which specifies "boolean" semantics shall accept keyword value "true" to mean that the field is asserted, and keyword value "false" to mean that the field is unasserted. Keyword values can only be defined in this specification, and not by implementing ports. Use quoted strings instead. Fields which do not appear in a block take on their default value. This allows minimal specification. Note that the default values specified by UDMF are not necessarily the default values which editors may wish to apply to those fields during the creation of new entities during editing. Such editing defaults are not part of this specification. ======================================= II. Implementation Semantics ======================================= ------------------------------------ II.A : Storage and Retrieval of Data ------------------------------------ Block-defined entities are written and read in top-to-bottom order. For example, the following linedefs can be assigned in order to a contiguous block of memory serving as the implementing port's lines array: linedef { id = 1; } linedef { id = 2; } linedef { id = 3; } linedef { id = 4; } Data types: For purposes of internal storage: --------------------------------- Integers should be considered signed with a range of at least 32 bits. Floating-point numbers should be considered double precision. Strings have no reasonable length limitations. Hard Data Type Limits --------------------- No limits on number of definitions are defined as part of this specification, but implementors may face the need to impose such limitations due to restrictions on the amount of memory available, or the amount that can be allocated through a single pointer on the host machine or in a private heap implementation. In the event that a map exceeds such an internal engine limitation, an implementing port or editor should not continue to attempt loading the map, as doing so could destabilize the program. ----------------------------------- II.B : Storage Within Archive Files ----------------------------------- UDMF maps shall be layed out within the archive directory as follows: (HEADER) TEXTMAP ... ENDMAP (HEADER) = Any lump name from 1 to 8 characters. Serves as the name of the map. TEXTMAP = Single UDMF lump containing all data for the map. ... = Blockmap, reject, BSP tree, and port-specific lumps, if any. The format and presence of these resources are not defined by UDMF. ENDMAP = Required closing lump. Implementing editors and source ports may distinguish a UDMF map from a traditional binary map by testing the name of the first directory entry following the map header. Implementing resource editors will be capable of keeping all lumps for the map, even non-standard ones, together by properly scanning for the ENDMAP entry. Non-implementing resource editors will not recognize the sequence of lumps as a map, and may thus be less likely to interfere with the order or presence of the lumps. Use of non-implementing resource editors to manipulate UDMF-map-containing WAD files is not recommended, however. -------------------------------- II.C : Implementation Dependence -------------------------------- A port's list of supported non-standard fields must be provided to implementing editors, where they can be provided to the end user as controls, as options in a dropbox, or through the ability to input any arbitrary "identifier = value;" pair in a text box. Every UDMF map should contain as the first statement in the file the "namespace" identifier statement, which declares the source port implementation relative to which this map is to be interpreted. Example: namespace = "ZDoom"; Implementing source ports may ignore this information, or they may use it to perform automatic runtime translation of maps they would otherwise be unable to support. Implementing source ports should publicly document the value of the "namespace" variable they intend to identify with when establishing support for UDMF, and avoid conflicts with existing implementations at all costs. The following namespaces are considered reserved for compatibility purposes: Doom Heretic Hexen Strife The use of one of these namespaces indicates that all line specials, sector specials, thing types, and if applicable, thing specials contained in the UDMF map conform to the "vanilla" types for the respective gamemode (with an exception for Doom) and are therefore 100% compatible with all UDMF implementors which support the specified gamemode. An exception is made for the "Doom" translation type. It is considered to represent the final fork of the v1.9 Doom engine, and therefore it includes all line types added in DOOM II. It is also additionally considered to include all specials defined in the BOOM and MBF source ports. Implementors who support BOOM linedef types can handle these in the normal manner; ports which do not support them should zero or otherwise ignore the offending specials. Documentation of the precise meanings of these standardized namespaces will be provided in separate documents. This feature is provided in order to facilitate a universal and lossless conversion of all existing Doom-engine-game maps to and from UDMF format, independent of any implementing ports' specific namespaces. ======================================= III. Standardized Fields ======================================= The UDMF v1.0 specification considers the following fields standard. They must be recognized by all implementing ports and editors (support for the features they signify is not necessarily required, such as for ports which do not implement Hexen support - all fields unknown to a given port should be ignored and not treated as an error). linedef { id = ; // ID of line. Interpreted as tag or scripting id. // Default = -1. *** see below. v1 = ; // Index of first vertex. No valid default. v2 = ; // Index of second vertex. No valid default. // All flags default to false. blocking = ; // true = line blocks things. blockmonsters = ; // true = line blocks monsters. twosided = ; // true = line is 2S. dontpegtop = ; // true = upper texture unpegged. dontpegbottom = ; // true = lower texture unpegged. secret = ; // true = drawn as 1S on map. blocksound = ; // true = blocks sound. dontdraw = ; // true = line never drawn on map. mapped = ; // true = always appears on map. // BOOM passuse flag not supported in Strife/Heretic/Hexen namespaces. passuse = ; // true = passes use action. // Strife specific flags. Support for other games is not defined by // default and these flags should be ignored when reading maps not for // the Strife namespace or maps for a port which supports these flags. translucent = ; // true = line is a Strife translucent line. jumpover = ; // true = line is a Strife railing. blockfloaters = ; // true = line is a Strife float-blocker. // Note: SPAC flags should be set false in Doom/Heretic/Strife // namespace maps. Specials in those games do not support this // mechanism and instead imply activation parameters through the // special number. All flags default to false. playercross = ; // true = player can cross. playeruse = ; // true = player can use. monstercross = ; // true = monster can cross. monsteruse = ; // true = monster can use. impact = ; // true = projectile can activate. playerpush = ; // true = player can push. monsterpush = ; // true = monster can push. missilecross = ; // true = projectile can cross. repeatspecial = ; // true = repeatable special. special = ; // Special. Default = 0. arg0 = ; // Argument 0. Default = 0. arg1 = ; // Argument 1. Default = 0. arg2 = ; // Argument 2. Default = 0. arg3 = ; // Argument 3. Default = 0. arg4 = ; // Argument 4. Default = 0. sidefront = ; // Sidedef 1 index. No valid default. sideback = ; // Sidedef 2 index. Default = -1. comment = ; // A comment. Implementors should attach no special // semantic meaning to this field. } sidedef { offsetx = ; // X Offset. Default = 0. offsety = ; // Y Offset. Default = 0. texturetop = ; // Upper texture. Default = "-". texturebottom = ; // Lower texture. Default = "-". texturemiddle = ; // Middle texture. Default = "-". sector = ; // Sector index. No valid default. comment = ; // A comment. Implementors should attach no special // semantic meaning to this field. } vertex { x = ; // X coordinate. No valid default. y = ; // Y coordinate. No valid default. } sector { heightfloor = ; // Floor height. Default = 0. heightceiling = ; // Ceiling height. Default = 0. texturefloor = ; // Floor flat. No valid default. textureceiling = ; // Ceiling flat. No valid default. lightlevel = ; // Light level. Default = 160. special = ; // Sector special. Default = 0. id = ; // Sector tag/id. Default = 0. comment = ; // A comment. Implementors should attach no special // semantic meaning to this field. } thing { id = ; // Thing ID. Default = 0. x = ; // X coordinate. No valid default. y = ; // Y coordinate. No valid default. height = ; // Z height relative to floor. Default = 0. // (Relative to ceiling for SPAWNCEILING items). angle = ; // Map angle of thing in degrees. Default = 0 (East). type = ; // DoomedNum. No valid default. // All flags default to false. skill1 = ; // true = in skill 1. skill2 = ; // true = in skill 2. skill3 = ; // true = in skill 3. skill4 = ; // true = in skill 4. skill5 = ; // true = in skill 5. ambush = ; // true = thing is deaf. single = ; // true = in SP mode. dm = ; // true = in DM mode. coop = ; // true = in Coop. // MBF friend flag not supported in Strife/Heretic/Hexen namespaces. friend = ; // true = MBF friend. // Hexen flags; not supported in Doom/Strife/Heretic namespaces. dormant = ; // true = dormant thing. class1 = ; // true = Present for pclass 1. class2 = ; // true = Present for pclass 2. class3 = ; // true = Present for pclass 3. // Strife specific flags. Support for other games is not defined by // default and these flags should be ignored when reading maps not for // the Strife namespace or maps for a port which supports these flags. standing = ; // true = Strife NPC flag. strifeally = ; // true = Strife ally flag. translucent = ; // true = Strife translucency flag. invisible = ; // true = Strife invisibility flag. // Note: suggested editor defaults for all skill, gamemode, and player // class flags is true rather than the UDMF default of false. // Thing special semantics are only defined for the Hexen namespace or // ports which implement this feature in their own namespace. special = ; // Scripting special. Default = 0; arg0 = ; // Argument 0. Default = 0. arg1 = ; // Argument 1. Default = 0. arg2 = ; // Argument 2. Default = 0. arg3 = ; // Argument 3. Default = 0. arg4 = ; // Argument 4. Default = 0. comment = ; // A comment. Implementors should attach no special // semantic meaning to this field. } *** Tag / ID Behavior for Map Conversion: Unlike traditional Doom maps UDMF makes a clear distinction between a line's ID and the parameter which identifies the object the line's special is supposed to affect. The id will be used to identify this line, and arg0 will be used to identify the line or sector that this line is to affect or otherwise reference, i.e. it is effectively a parameter to the line's special. Boom used the linedef's tag for both due to lack of other options so in order to ensure compatibility any map converter converting maps for the Doom/Heretic/Strife namespaces must store the linedef's tag field as both the id and as arg0 in each line. The default value of the id field under these namespaces is defined as 0 rather than -1. Since UDMF provides a line id field, the Hexen line special #121 (Line_SetIdentification) is obsolete. When converting maps to UDMF under Hexen namespace, special 121 should be written as zero, and the arg0 of the binary linedef should be written as the id field of the UDMF line. The arg0 value of the UDMF line should also then be set to zero. =============================================================================== EOF ===============================================================================