Difference between revisions of "Map format"

From VCMI Project Wiki
Jump to: navigation, search
(Root entry)
(Logical event conditions)
 
(79 intermediate revisions by the same user not shown)
Line 9: Line 9:
 
** Map objects, possibly split by level as well
 
** Map objects, possibly split by level as well
 
== Base format ==
 
== Base format ==
 
+
* zip archive, file extension .vmap
* zip archive
 
 
* contains header.json
 
* contains header.json
 
* header.json contains Json object
 
* header.json contains Json object
Line 16: Line 15:
 
* everything else may be changed in future
 
* everything else may be changed in future
 
* this page describes format version 1
 
* this page describes format version 1
 +
 +
== Extensions ==
 +
* Possible future major verions of map format are out of scope in this document
 +
* All minor versions shall be backward and forward compatible
 +
* Allowed modifications:
 +
*# adding new attributes of any type
 +
*# deprecating old attributes
 +
* New attributes get version suffix (f.e. "field_3" where 3 is minor version introduced this field)
 +
** "_x" suffix indicates draft for next format revision
 +
* Engine discards attributes with higher version
 +
* Map editor preserve attributes with higher version disallowing modification
 +
*# {{todo}} handle situation with deprecated (actually replaced) attribute edit
  
 
==Map header==
 
==Map header==
 
===Root entry===
 
===Root entry===
 +
* engine {{wip}}
 +
* editor {{wip}}
 +
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
  
Line 52: Line 66:
  
 
// Map difficulty. Represented as percentage?
 
// Map difficulty. Represented as percentage?
"difficulty" : 100,
+
"difficulty" : 100, //or enum EASY, NORMAL, HARD, EXPERT, IMPOSSIBLE
  
 
// Maximum level that hero can reach on this map. Optional, default is 199 (internal engine limitation)
 
// Maximum level that hero can reach on this map. Optional, default is 199 (internal engine limitation)
"levelLimit" : 20,
+
"heroLevelLimit" : 20,
  
 
// Information on players placed on map, see below
 
// Information on players placed on map, see below
Line 62: Line 76:
 
   //...
 
   //...
 
  },
 
  },
 +
 +
"teams":[<team settings format>],
  
 
// list of allowed/banned heroes, abilities, spells.  "allOf" aka "required" part of condition as treated as "allowed" and not recommended to use
 
// list of allowed/banned heroes, abilities, spells.  "allOf" aka "required" part of condition as treated as "allowed" and not recommended to use
Line 72: Line 88:
 
"allowedSpells" : {<Logical id condition>},
 
"allowedSpells" : {<Logical id condition>},
  
 +
"allowedArtifacts" : {<Logical id condition>},
  
 
// Text for victory conditions on map selection screen.
 
// Text for victory conditions on map selection screen.
Line 84: Line 101:
  
 
// list of triggered events that denote computer-readable victory/defeat conditions
 
// list of triggered events that denote computer-readable victory/defeat conditions
"triggeredEvents" : { <list of triggered events, see below> }
+
"triggeredEvents" : { <list of triggered events, see below> },
 +
 
 +
"rumors":[
 +
{
 +
"name": "rumor name",
 +
"text": "rumor text",
 +
}
 +
//...
 +
],
 +
 
 +
"predefinedHeroes":{
 +
"hero_id":{<Hero definition format>}
 +
//...
 +
}
 +
 
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
===Level header format===
 
===Level header format===
 +
* engine {{done}} only 2 level max, same size
 +
* editor {{done}}
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
 
"surface" :
 
"surface" :
Line 104: Line 137:
  
 
===Player information format===
 
===Player information format===
 +
* engine {{wip}}
 +
* editor {{wip}}
  
 
'''Player color names'''
 
'''Player color names'''
Line 111: Line 146:
 
"red" :
 
"red" :
 
{
 
{
//TODO
+
//
 +
"allowedFactions":{<Logical id condition>},
 +
 
 +
"randomFaction": true,//if true player can not chose faction
 +
 
 +
"canPlay": "PlayerOnly", //PlayerOrAI(default), PlayerOnly, AIOnly
 +
 
 +
//all heroes owned by player
 +
"heroes":{//todo
 +
"hero_1":{
 +
"type":"knight",
 +
"name":"King Arthur"
 +
},
 +
"hero_7":{
 +
"type":"" //empty type means random town
 +
}
 +
//...
 +
},
 +
"mainHero": "hero_1",
 +
 
 +
"mainTown":{
 +
"type": "rampart", //???
 +
"x":123,
 +
"y":31,
 +
"l":0,
 +
"generateHero": false
 +
}
 
}
 
}
 +
</syntaxhighlight>
 +
 +
=== Team settings format ===
 +
* engine {{done}}
 +
* editor {{done}}
 +
 +
<syntaxhighlight lang="javascript">
 +
[
 +
["red", "tan"],
 +
["blue", "purple", "green"]
 +
]
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
===Triggered events format===
 
===Triggered events format===
 +
* editor {{done}}
 +
* engine {{done}}
 +
 +
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
 
// Unique identifier of an event
 
// Unique identifier of an event
Line 140: Line 216:
 
}
 
}
 
</syntaxhighlight>
 
</syntaxhighlight>
===Logical id conditions===
+
 
 +
=== Logical id condition ===
 +
* engine {{done}}
 +
* editor {{done}}
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
 
"condition"
 
"condition"
Line 159: Line 238:
  
 
===Logical event conditions===
 
===Logical event conditions===
 +
* engine {{wip}}
 +
* editor {{todo}}
 +
 
Logical conditions for map events use same base system as buidings but with different base element. See [[List of all event conditions]] for possible elements for these expressions.
 
Logical conditions for map events use same base system as buidings but with different base element. See [[List of all event conditions]] for possible elements for these expressions.
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
Line 166: Line 248:
 
     "allOf",
 
     "allOf",
 
     // 1) Have 100'000 gold
 
     // 1) Have 100'000 gold
     [ "haveResources", { "type" : "resource.gold", "value" : 100000 }],
+
     [ "have_0", { "type" : "resource.gold", "value" : 100000 }],
 +
 
 
     // 2) 60 days have not passed since game start (aka time expires loss condition)
 
     // 2) 60 days have not passed since game start (aka time expires loss condition)
 
     [
 
     [
Line 175: Line 258:
 
     [
 
     [
 
       "anyOf"
 
       "anyOf"
       [ "control", { "position" : [ 1, 4,0], "type" : "object.town" } ],
+
      //by map position and (optional) object type/suptype
       [ "control", { "position" : [10,25,0], "type" : "object.town" } ]
+
       [ "have_0", { "position" : [ 1, 4, 0], "type" : "object.town"} ],
    ]
+
      //by instance id
 +
       [ "have_0", { "object": "town_9" } ]
 +
    ],
 +
 
 +
    [ "have_0", { "object" : "hero_42"}]
 
]
 
]
 
</syntaxhighlight>
 
</syntaxhighlight>
  
==Terrain==
+
== Hero definition format ==
 +
* editor {{done}}
 +
* engine {{todo}}
 +
 
 +
<syntaxhighlight lang="javascript">
 +
{
 +
 
 +
"artifacts" : {
 +
"backpack" : [
 +
],
 +
"feet" : "",
 +
"head" : "",
 +
"leftHand" : "",
 +
"leftRing" : "",
 +
"mach1" : "",
 +
"mach2" : "",
 +
"mach3" : "",
 +
"mach4" : "",
 +
"misc1" : "",
 +
"misc2" : "",
 +
"misc3" : "",
 +
"misc4" : "",
 +
"misc5" : "",
 +
"neck" : "",
 +
"rightHand" : "",
 +
"rightRing" : "",
 +
"shoulders" : "",
 +
"spellbook" : "",
 +
"torso" : ""
 +
},
 +
"biography" : "",
 +
"experience" : 0,
 +
 +
"name" : "My hero",
 +
 
 +
 +
//optional, icon index (from "Portraits[Large|Small].json" ) or another hero id, default from "type"
 +
"portrait" : "hota.cove.zilare",
 +
 +
//optional default inherited from configuration
 +
"primarySkills" : {
 +
"attack" : 0,
 +
"defence" : 2,
 +
"knowledge" : 0,
 +
"spellpower" : 3
 +
},
 +
 +
"secondarySkills" : {
 +
"leadership" : "basic"//"advanced", "expert"
 +
//...
 +
},
 +
 
 +
//optional, default if not set
 +
"female" : true,//false
 +
"spellBook" : [
 +
"fortune"
 +
//...
 +
],
 +
//default all players
 +
"availableFor":["red","tan"]
 +
}
 +
</syntaxhighlight>
 +
 
 +
== Terrain ==
 +
* engine {{done}}
 +
* editor {{done}}
 +
 
 
Represented as Json 2d vector (row, column), each tile is encoded string in order to keep map as small as possible. Encoding map using full Json format is not an option due to loading speed.  
 
Represented as Json 2d vector (row, column), each tile is encoded string in order to keep map as small as possible. Encoding map using full Json format is not an option due to loading speed.  
 
Terrain of each map level is stored in %levelId%_terrain.json
 
Terrain of each map level is stored in %levelId%_terrain.json
Line 187: Line 340:
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
 
[
 
[
   [ "dt10", "dt13pc3", "dt12" ],
+
   [ "dt37_pc14|", "sn50_pc9|", "dt12_" ],
   [ "wt26", "wt03pc3", "dt12" ],
+
   [ "wt26_", "wt03_pc3_", "dt12_" ],
   [ "wt64", "wt34pc3", "dt12rw4" ]
+
   [ "wt64_", "wt34_pc3_", "dt12_rw4+" ]
 
]
 
]
 
</syntaxhighlight>
 
</syntaxhighlight>
 
Format of each individual tile is:
 
Format of each individual tile is:
 
<pre>
 
<pre>
[terrain code][terrain index]
+
[terrain code][terrain index][flip]
[P][path type][path index]
+
[P][path type][path index][flip]
[R][river type][river index]
+
[R][river type][river index][flip]
[F][flags as uint8]
+
 
 +
</pre>
 +
 
 +
flip codes:
 +
 
 +
<pre>
 +
_ no rotation
 +
- left-right flip
 +
| top-bottom flip
 +
+ both directions
 
</pre>
 
</pre>
 +
 
First part is obligatory 2-letter code of terrain (e.g. dt for Dirt) and index of frame in animation file for this tile. Second part is optional description of path present on tile (e.g. cobblestone road will be encoded as "pc" - path cobblestone) with frame index similar to terrain. Third optional part describes rivers on this tile (e.g. normal river will be encoded as "rw" - river water), following frame index.
 
First part is obligatory 2-letter code of terrain (e.g. dt for Dirt) and index of frame in animation file for this tile. Second part is optional description of path present on tile (e.g. cobblestone road will be encoded as "pc" - path cobblestone) with frame index similar to terrain. Third optional part describes rivers on this tile (e.g. normal river will be encoded as "rw" - river water), following frame index.
 
"Flags" used if not 0 contains rotation for terrain, path & river.
 
"Flags" used if not 0 contains rotation for terrain, path & river.
Line 228: Line 391:
  
 
==Objects==
 
==Objects==
 +
* engine {{done}}
 +
* editor {{done}}
 +
 +
See also: [[Object instance format]]
 
"objects.json"
 
"objects.json"
  
 
<syntaxhighlight lang="javascript">
 
<syntaxhighlight lang="javascript">
[
 
 
{
 
{
 +
"town_375":{
 +
 
//appearance selected by engine if not present
 
//appearance selected by engine if not present
  
 
"template":{<object template format>}
 
"template":{<object template format>}
"type":"objecttype",
+
"type":"town",
"subtype":"someMod:objectSubtype",
+
"subtype":"hota.cove:cove",
  
 
"options" : {
 
"options" : {
 
//object type specific
 
//object type specific
 +
//object instance format
 
},
 
},
  
 +
"pos_x" : [x,y,l], //TODO: alternate coordinates
 
"x" : 10,"y" : 6, "l": 0 //coordinates
 
"x" : 10,"y" : 6, "l": 0 //coordinates
 +
 +
//future extension for scripts
 +
"mod_myMod_x":
 +
{
 +
//<myMod specific options>
 +
},
 +
"mod_anotherMod_x":
 +
{
 +
//<myMod specific options>
 +
},
 +
//future extension for object mixins
 +
"mix_identifier1_x":
 +
{
 +
//mixin type specific
 +
},
 +
"mix_identifier2_x":
 +
{
 +
//mixin type specific
 +
}
 
},
 
},
[...]
+
//...
],
+
}
 +
</syntaxhighlight>
  
</syntaxhighlight>
+
* instance identifier has format <object type w\o mod id> "_" <unique number>.
  
 
== Technical details ==
 
== Technical details ==

Latest revision as of 15:11, 16 January 2017

This article is a proposal of new map format editor / random map genrator of modded VCMI.

Basic ideas

  • Map uses Json format
  • Complete map is a zip archive.
  • Archive contains map split in several sections with predefined names
    • Header, corresponds to H3M header structure. Separate file is needed mostly to allow fast loading of map headers in pregame map selection
    • Terrain, each level in separate file
    • Map objects, possibly split by level as well

Base format

  • zip archive, file extension .vmap
  • contains header.json
  • header.json contains Json object
  • header object contains formatVersion field
  • everything else may be changed in future
  • this page describes format version 1

Extensions

  • Possible future major verions of map format are out of scope in this document
  • All minor versions shall be backward and forward compatible
  • Allowed modifications:
    1. adding new attributes of any type
    2. deprecating old attributes
  • New attributes get version suffix (f.e. "field_3" where 3 is minor version introduced this field)
    • "_x" suffix indicates draft for next format revision
  • Engine discards attributes with higher version
  • Map editor preserve attributes with higher version disallowing modification
    1. [Todo] handle situation with deprecated (actually replaced) attribute edit

Map header

Root entry

  • engine [WiP]
  • editor [WiP]
//version of format itself. This field will be always present.
"versionMajor" : 1,

//maps with same version and different revisions are backward compatible (todo: forward compatibility)
"versionMinor": 0,


//list of mods required to run this map
//todo: use mod versions
//all "required" mods must be loaded to play this map (f.e. mod with faction used in map)
//if any of "banned" mods are enabled map cant be loaded (f.e. known conflict with map`s scrpited mechanics)
//"allowed" mods are not required, just information that these mods are tested with this map

//map objects can only include/use objects from "required" mods.
//map scripts may also use "allowed" mods (assumed that they check presence of particular mod)

"mods" : {<Logical id condition>},

// Lists map levels and their size and depth
"mapLevels" : {
    "surface" : {<Level header format>},
    "underground" : {<Level header format>}
},

// Human-readable name of the map
"name" : "Test map",

// Human-readable description of the map
"description" : "Long description of completely useless testing map",

// Map difficulty. Represented as percentage?
"difficulty" : 100, //or enum EASY, NORMAL, HARD, EXPERT, IMPOSSIBLE

// Maximum level that hero can reach on this map. Optional, default is 199 (internal engine limitation)
"heroLevelLimit" : 20,

// Information on players placed on map, see below
"players" : { 
  "color":{<player information format>} 
  //...
 },

"teams":[<team settings format>],

// list of allowed/banned heroes, abilities, spells.  "allOf" aka "required" part of condition as treated as "allowed" and not recommended to use
"allowedHeroes" : {<Logical id condition>},


"allowedAbilities" : {<Logical id condition>},


"allowedSpells" : {<Logical id condition>},

"allowedArtifacts" : {<Logical id condition>},

// Text for victory conditions on map selection screen.
"victoryString" : "Defeat all enemies or find artifact",
// Icon, indicates index of frame in SCNRVICT.DEF file
"victoryIconIndex" : 12,

// Text for defeat conditions on map selection screen.
"defeatString" : "Lose your capital Steadwick or your hero Roland",
// Icon, indicates index of frame in SCNRLOSS.DEF file
"defeatIconIndex" : 1,

// list of triggered events that denote computer-readable victory/defeat conditions
"triggeredEvents" : { <list of triggered events, see below> },

"rumors":[
{
"name": "rumor name",
"text": "rumor text",
}
//...
],

"predefinedHeroes":{
"hero_id":{<Hero definition format>}
//...
}

Level header format

  • engine [Done] only 2 level max, same size
  • editor [Done]
"surface" :
{

	//mandatory; level height in tiles
	"height": 72,

	//mandatory; level width in tiles
	"width": 72,

	//mandatory, unique; coordinate of this level
	"index": 0, //0=surface, 1 underground.
}

Player information format

  • engine [WiP]
  • editor [WiP]

Player color names red, blue, tan, green, orange, purple, teal, pink

"red" :
{
	//
	"allowedFactions":{<Logical id condition>},

	"randomFaction": true,//if true player can not chose faction

	"canPlay": "PlayerOnly", //PlayerOrAI(default), PlayerOnly, AIOnly

	//all heroes owned by player
	"heroes":{//todo
		"hero_1":{
			"type":"knight", 
			"name":"King Arthur"
		},
		"hero_7":{
			"type":"" //empty type means random town
		}
		//...
	},
	"mainHero": "hero_1",

	"mainTown":{
		"type": "rampart", //???
		"x":123,
		"y":31,
		"l":0,
		"generateHero": false
	}
}

Team settings format

  • engine [Done]
  • editor [Done]
[
["red", "tan"],
["blue", "purple", "green"]
]

Triggered events format

  • editor [Done]
  • engine [Done]


// Unique identifier of an event
"findTheBlade" :
{
	// Logical condition for this event to trigger, see below
	"condition" : [ "logical expression code" ],

	// TODO: Long description of this event/quest, will be displayed in quest window
	"description" : "Find ancient artifact, Armageddon's Blade to claim victory!",

	// Message that will be displayed to player that have triggered this event
	"message" : "You have found Armageddon's Blade. You won!",

	// Effect caused by this event, right now only win/loss effects are supported
	"effect" :
	{
		// Type of effect, can be either "victory" or "defeat"
		"type" : "victory",

		// Message that will be send to the rest of players to explain what happened
		"messageToSend" : "Enemy found AB. All is lost!"
	}
}

Logical id condition

  • engine [Done]
  • editor [Done]
"condition"
{
    //these ids are allowed, default defined by handler
    "anyOf":
    [ "id1", "id2" ],

    //these ids are required, default none. automatically added to allowed
    "allOf":
    [ "id3", "id4" ],

    //these ids are banned, default none, has priority over allowed and required.
    "noneOf":
    [ "id4", "id5" ],
}

Logical event conditions

  • engine [WiP]
  • editor [Todo]

Logical conditions for map events use same base system as buidings but with different base element. See List of all event conditions for possible elements for these expressions.

"condition"
[
    // To fulfill, all of below must be true
    "allOf",
    // 1) Have 100'000 gold
    [ "have_0", { "type" : "resource.gold", "value" : 100000 }],

    // 2) 60 days have not passed since game start (aka time expires loss condition)
    [
      "noneOf",
      [ "daysPassed", { "value" : 60 } ]
    ],
    // 3) Player must control at least one of towns at positions specified below
    [
      "anyOf"
      //by map position and (optional) object type/suptype
      [ "have_0", { "position" : [ 1, 4, 0], "type" : "object.town"} ],
      //by instance id
      [ "have_0", { "object": "town_9" } ]
    ],

    [ "have_0", { "object" : "hero_42"}]
]

Hero definition format

  • editor [Done]
  • engine [Todo]
{

	"artifacts" : {
		"backpack" : [
		],
		"feet" : "",
		"head" : "",
		"leftHand" : "",
		"leftRing" : "",
		"mach1" : "",
		"mach2" : "",
		"mach3" : "",
		"mach4" : "",
		"misc1" : "",
		"misc2" : "",
		"misc3" : "",
		"misc4" : "",
		"misc5" : "",
		"neck" : "",
		"rightHand" : "",
		"rightRing" : "",
		"shoulders" : "",
		"spellbook" : "",
		"torso" : ""
	},
	"biography" : "",
	"experience" : 0,
	
	"name" : "My hero",

		
	//optional, icon index (from "Portraits[Large|Small].json" ) or another hero id, default from "type"
	"portrait" : "hota.cove.zilare", 
			
	//optional default inherited from configuration
	"primarySkills" : {
		"attack" : 0,
		"defence" : 2,
		"knowledge" : 0,
		"spellpower" : 3
	},
			
	"secondarySkills" : {
		"leadership" : "basic"//"advanced", "expert"
		//...
	},

	//optional, default if not set
	"female" : true,//false
	"spellBook" : [
		"fortune"
		//...
	],
	//default all players
	"availableFor":["red","tan"]
}

Terrain

  • engine [Done]
  • editor [Done]

Represented as Json 2d vector (row, column), each tile is encoded string in order to keep map as small as possible. Encoding map using full Json format is not an option due to loading speed. Terrain of each map level is stored in %levelId%_terrain.json

[
  [ "dt37_pc14|", "sn50_pc9|", "dt12_" ],
  [ "wt26_", "wt03_pc3_", "dt12_" ],
  [ "wt64_", "wt34_pc3_", "dt12_rw4+" ]
]

Format of each individual tile is:

[terrain code][terrain index][flip]
[P][path type][path index][flip]
[R][river type][river index][flip]

flip codes:

_ no rotation
- left-right flip
| top-bottom flip
+ both directions

First part is obligatory 2-letter code of terrain (e.g. dt for Dirt) and index of frame in animation file for this tile. Second part is optional description of path present on tile (e.g. cobblestone road will be encoded as "pc" - path cobblestone) with frame index similar to terrain. Third optional part describes rivers on this tile (e.g. normal river will be encoded as "rw" - river water), following frame index. "Flags" used if not 0 contains rotation for terrain, path & river.

Terrain codes

  • DIRT - dt
  • SAND - sa
  • GRASS - gr
  • SNOW - sn
  • SWAMP - sw
  • ROUGH - rg
  • SUBTER. - sb
  • LAVA - lv
  • WATER - wt
  • ROCK - rc

Road codes

  • dirt - pd
  • grazvel - pg
  • cobblestone - pc

River codes

  • water - rw
  • icy - ri
  • moddy - rm
  • lava - rl

Objects

  • engine [Done]
  • editor [Done]

See also: Object instance format "objects.json"

{
"town_375":{

	//appearance selected by engine if not present

	"template":{<object template format>}
	"type":"town",
	"subtype":"hota.cove:cove",

	"options" : {
		//object type specific
		//object instance format
	},

	"pos_x" : [x,y,l], //TODO: alternate coordinates
	"x" : 10,"y" : 6, "l": 0 //coordinates

	//future extension for scripts
	"mod_myMod_x":
	{
		//<myMod specific options>
	},
	"mod_anotherMod_x":
	{
		//<myMod specific options>
	},
	//future extension for object mixins
	"mix_identifier1_x":
	{
	//mixin type specific
	},
	"mix_identifier2_x":
	{
	//mixin type specific
	}
},
//...
}
  • instance identifier has format <object type w\o mod id> "_" <unique number>.

Technical details

Object identification

  • Regardless of mod from which map came from, map considered to be part of "core" mod. So all string ids except ones from core are namespaced with mod name.


Modding related articles

Main articles
Modding changelog Modding guidelines How to create a town mod Mod Handler


Formats
Mod file Format
Town Format Creature Format Hero Classes Format
Artifact Format Animation Format Hero Format
Bonus Format Object Format Spell Format


Work-in-progress formats
Building bonuses Map format
Bonus Type Format Random map template


Outdated pages
Mod system proposal