Map

A map is a file that Soldat uses to recognize a level (e.g., ctf_B2b.PMS). These maps, with the .PMS filetype extension, can be generated with Map makers. In versions 1.05b and earlier, the extension .PMP was used.

General Components
Maps consist of polygons, scenery, colliders, waypoints (for bots), spawnpoints, and bonuses.

Properties
Maps also contain properties, which include weather, footstep sound, jet fuel, and background color.

Types
There are many types of maps in Soldat. In order to differentiate what gametypes a map supports, their filenames are prefixed with a 3 letter code, followed by an underscore, then the name of the map, as follows:
 * Normal maps (for Deathmatch, Pointmatch, Teammatch and Rambomatch. No prefix is used for these maps.)
 * Capture the Flag maps (Uses the prefix ctf_)
 * Infiltration maps (Uses the prefix inf_)
 * Hold the Flag maps (Uses the prefix htf_)
 * Climbing maps (Uses the prefix kz_ ctf_kz_ ctf_ and many more)
 * Race maps (Uses the prefix ctf_rce_ or ctf_)
 * Various maps (Either use the prefix var_ or none at all)
 * Dodgeball Maps (Either use the prefix DB_ or none at all)
 * Trenchwars Maps (Either tw_ or ctf_tw_ prefix)

File Structure
Here is the physical structure of the map file. The text below, saved in a file, is usable in Hex Workshop 4.23 to view the components of the map. With a small amount of work, it is possible to convert it to working C++ code or, with a little more work, to convert it to another language. /* Soldat PMS file format structure defenition file for Hex Workshop by: Chrisgbk

//#include "standard-types.hsl" // All the standard deftypes (shown below for clarity)

typedef         char    CHAR ; typedef signed  __int8  BYTE ; typedef         BYTE    byte ; typedef unsigned __int8 UBYTE ; typedef         UBYTE   ubyte ; typedef unsigned __int16 WORD ; typedef         WORD    word ; typedef unsigned __int16 USHORT ; typedef         USHORT  ushort ; typedef         short   SHORT ; typedef unsigned __int32 DWORD ; typedef         DWORD   dword ; typedef         long    LONG ; typedef unsigned __int32 ULONG ; typedef         ULONG   ulong ; typedef signed  __int64 QUAD ; typedef         QUAD    quad ; typedef unsigned __int64 UQUAD ; typedef         UQUAD   uquad ; typedef         float   FLOAT ; typedef         double  DOUBLE ;


 * 1) pragma maxarray(10000) // default max array size is 128(to protect from corrupt data), need this
 * 2) pragma byteorder(little_endian) // Intel

// note: since #pragma pack(4) isnt supported by hex workshop, I had to pad everything manually // it may be wise to do it this way, even if your compiler supposrt this pragma, due to uncertanties over how a given compiler will allign the members of the data structures.
 * 1) pragma enumsize(1) // 1 byte
 * 2) pragma pack(1)

typedef enum TRUEFALSE { FALSE = 0, TRUE } BOOL; // just... yeah


 * 1) pragma hide // don't make these structs visible in Hex Workshop

typedef enum POLYTYPE { ptNORMAL = 0, ptONLY_BULLETS_COLLIDE, ptONLY_PLAYERS_COLLIDE, ptNO_COLLIDE, ptICE, ptDEADLY, ptBLOODY_DEADLY, ptHURTS, ptREGENERATES, ptLAVA, ptALPHABULLETS, ptALPHAPLAYERS, ptBRAVOBULLETS, ptBRAVOPLAYERS, ptCHARLIEBULLETS, ptCHARLIEPLAYERS, ptDELTABULLETS, ptDELTAPLAYERS, ptBOUNCY, ptEXPLOSIVE, ptHURTFLAGGERS, ptFLAGGERCOLLIDES, ptNONFLAGGERCOLLIDES, ptFLAGCOLLIDES } PMS_POLYTYPE;

typedef enum DRAWBEHIND { dbBEHIND_ALL = 0, dbBEHIND_MAP, dbBEHIND_NONE } PMS_DRAWBEHIND;

typedef enum SPECIALACTIONS { saNONE = 0, saSTOP_AND_CAMP, saWAIT_1_SECOND, saWAIT_5_SECONDS, saWAIT_10_SECONDS, saWAIT_15_SECONDS, saWAIT_20_SECONDS } PMS_SPECIALACTIONS;

typedef enum WEATHERTYPE { wtNONE = 0, wtRAIN, wtSANDSTORM, wtSNOW } PMS_WEATHERTYPE;

typedef enum STEPSTYPE { stHARD_GROUND = 0, stSOFT_GROUND, stNONE } PMS_STEPSTYPE;


 * 1) pragma enumsize(4) // 4 byte

typedef enum SPAWNTEAM { stGENERAL = 0, stALPHA, stBRAVO, stCHARLIE, stDELTA, stALPHA_FLAG, stBRAVO_FLAG, stGRENADES, stMEDKITS, stCLUSTERS, stVEST, stFLAMER, stBERSERKER, stPREDATOR, stYELLOW_FLAG, stRAMBO_BOW, stSTAT_GUN } PMS_SPAWNTEAM;

typedef struct tagPMS_VECTOR { FLOAT x;	FLOAT y;	FLOAT z; } PMS_VECTOR;

typedef struct tagPMS_COLOR { UBYTE blue; UBYTE green; UBYTE red; UBYTE alpha; } PMS_COLOR;

typedef struct tagPMS_HEADER { LONG version; } PMS_HEADER;

typedef struct tagPMS_OPTIONS { UBYTE nameLen; CHAR name[nameLen]; CHAR nameFiller[38-nameLen]; UBYTE texLen; CHAR texture[texLen]; CHAR textureFiller[24 - texLen]; PMS_COLOR bgColorTop; PMS_COLOR bgColorBottom; LONG jetAmount; UBYTE grenades; UBYTE medikits; PMS_WEATHERTYPE weather; PMS_STEPSTYPE steps; LONG randID; } PMS_OPTIONS;

typedef struct tagPMS_VERTEX { FLOAT x;	FLOAT y;	FLOAT z;	FLOAT rhw; PMS_COLOR color; FLOAT tu; FLOAT tv; } PMS_VERTEX;

typedef struct tagPMS_POLYGON { PMS_VERTEX vetex[3]; PMS_VECTOR perpendicular[3]; PMS_POLYTYPE polyType; } PMS_POLYGON;

typedef struct tagPMS_SECTOR { WORD polyCount; WORD polys[polyCount]; } PMS_SECTOR;

typedef struct tagPMS_PROP { BOOL active; UBYTE filler1; WORD style; LONG width; LONG height; FLOAT x;	FLOAT y;	FLOAT rotation; FLOAT scaleX; FLOAT scaleY; UBYTE alpha; UBYTE filler2[3]; PMS_COLOR color; PMS_DRAWBEHIND level; UBYTE filler3[3]; } PMS_PROP; /* found out that these are already defined ^_^

typedef struct tagDOSTIME { WORD second : 5; WORD minute : 6; WORD hour   : 5; } DOSTIME;

typedef struct tagDOSDATE { WORD day : 5; WORD month : 4; WORD year   : 7; } DOSDATE; typedef struct tagPMS_TIMESTAMP { DOSTIME time; DOSDATE date; } PMS_TIMESTAMP;

typedef struct tagPMS_SCENERY { UBYTE nameLen; CHAR name[nameLen]; CHAR nameFiller[50-nameLen]; PMS_TIMESTAMP timestamp; } PMS_SCENERY;

typedef struct tagPMS_COLLIDER { BOOL active; UBYTE filler[3]; FLOAT x;	FLOAT y;	FLOAT radius; } PMS_COLLIDER;

typedef struct tagPMS_SPAWNPOINT { BOOL active; UBYTE filler[3]; LONG x;	LONG y;	PMS_SPAWNTEAM team; } PMS_SPAWNPOINT;

typedef struct tagPMS_WAYPOINT { BOOL active; UBYTE filler1[3]; LONG id; LONG x;	LONG y;	BOOL left; BOOL right; BOOL up; BOOL down; BOOL jet; UBYTE path; PMS_SPECIALACTIONS specialAction; UBYTE c2; UBYTE c3; UBYTE filler2[3]; LONG numConnections; LONG connections[20]; } PMS_WAYPOINT;


 * 1) pragma show

struct PMS_FILE { PMS_HEADER header; PMS_OPTIONS options; LONG polygonCount; PMS_POLYGON polygon[polygonCount]; LONG sectorDivision; LONG numSectors; //PMS_SECTOR sector[(numSectors*2)+1][(numSectors*2)+1]; // unlike VB/Delphi, can't define the lower bound; only the length. -25 to 25 is the same as 0 to 50, or length of 51 ((2*25)+1) PMS_SECTOR sector[((numSectors*2)+1)*((numSectors*2)+1)]; // same as above, but as a single flat array. Use whatever you feel most comfortable with. LONG propCount; PMS_PROP prop[propCount]; LONG sceneryCount; PMS_SCENERY scenery[sceneryCount]; LONG colliderCount; PMS_COLLIDER collider[colliderCount]; LONG spawnpointCount; PMS_SPAWNPOINT spawnpoint[spawnpointCount]; LONG waypointCount; PMS_WAYPOINT waypoint[waypointCount]; };