1. We have added a Gift Upgrades feature that allows you to gift an account upgrade to another member, just in time for the holiday season. You can see the gift option when going to the Account Upgrades screen, or on any user profile screen.
    Dismiss Notice

Civ5Map File Format

Discussion in 'Civ5 - Modding Tutorials & Reference' started by MouseyPounds, Apr 10, 2011.

  1. MouseyPounds

    MouseyPounds Prince

    Joined:
    Nov 8, 2010
    Messages:
    417
    Location:
    Maryland, USA
    What follows is a partially-complete outline of the Civ5Map file format. Most of the heavy-lifting on this was done by dannythefool for his Civ5 Replay reader. While trying to update that script for the latest patch, I did some further investigating and decided to post this reference. My interest is mostly in the map itself, so information on the scenario data is almost entirely missing from the current version of this guide.

    Civ5Map File Format

    Map Header

    byte -- Type/version indicator. See Notes below.
    int -- Map Width
    int -- Map Height
    byte -- Possibly number of players for scenario.
    int -- Unknown; seems to be a world wrap indicator (1 if wrap, 0 if no wrap)
    int -- Length of Terrain type list
    int -- Length of 1st Feature type list
    int -- Length of 2nd Feature type list
    int -- Length of Resource type list
    int -- Unknown
    int -- Length of Map Name string
    int -- Length of Description string
    string[] -- Terrain type list
    string[] -- 1st Feature type list
    string[] -- 2nd Feature type list
    string[] -- Resource type list
    string -- Map Name string
    string -- Description string
    int -- Length of String3 (only present in version xB or later)
    string -- String3 (only present in version xB or later)

    Map Data
    Map data is just a list of plots, where a plot is an array of 8 bytes. It starts at plot (0,0), continues along the x-axis until the row is done, then moves on to (0,1), etc. So a useful way to read it is to loop the y values from 0 to Height-1 and inside that loop the x values from 0 to Width-1; then you can simply read the next 8 bytes to get the info for plot (x,y) and do whatever you need to with it.

    A plot array looks like this:
    byte 0 -- Terrain type ID (index into list of Terrain types read from header)
    byte 1 -- Resource type ID; 0xFF if none
    byte 2 -- 1st Feature type ID; 0xFF if none
    byte 3 -- River indicator (non-zero if tile borders a river; actual value probably indicates direction)
    byte 4 -- Elevation (0 = Flat, 1 = Hill, 2 = Mountain)
    byte 5 -- Unknown (possibly related to continent art style)
    byte 6 -- 2nd Feature type ID; 0xFF if none
    byte 7 -- Unknown

    Scenario Header and Data
    If there is any scenario data present, it will appear after the map. I haven't really needed to use this part of the file, so info here is more sparse.

    84 unknown bytes
    int -- Length of Improvement type list
    int -- Length of Unit type list
    int -- Length of Tech type list
    int -- Length of Policy type list
    int -- Length of Building type list
    int -- Length of Promotion type list
    20 unknown bytes
    string[] -- Improvement type list
    string[] -- Unit type list
    string[] -- Tech type list
    string[] -- Policy type list
    string[] -- Building type list
    string[] -- Promotion type list

    That's about where I lose track of things. The next section seems to relate to player data but from here on I just didn't have the time or interest to try and work out what everything is in this part of the file.

    Notes:
    • The first byte (which I call a type/version indicator) seems to have a high nybble of 0 if the map is just a bare terrain map and a high nybble of 8 if the map also contains scenario information -- i.e. cities, units, etc. The low nybble was xA for older maps (prior to the December patch) and is xB for maps exported from the current game (patch 1.0.1.221).
    • All integers are 4-byte little Endian; I generally treat them all as signed.
    • All strings are null-terminated.
    • The "type lists" are blocks of known size which contain several null-terminated strings. For example, if I use a period to represent the null byte, the Terrain type list might look like this:
      Code:
      TERRAIN_GRASS.TERRAIN_PLAINS.TERRAIN_DESERT.TERRAIN_TUNDRA.TERRAIN_SNOW.TERRAIN_COAST.TERRAIN_OCEAN.
      These blocks can be read en masse and then split on the nulls into an array of type names.
    • The int/string combination for String3 was apparently added for version xB maps as it is not present in any version xA maps that I've looked at.
    • Plots only seem to have 1 of the 2 feature types present. For exported maps, if a plot has a "normal" feature (forest, jungle, flood plain) it'll be the first feature; if instead it has a Natural Wonder feature, it'll be the second feature.
     
  2. TomasGudm

    TomasGudm Chieftain

    Joined:
    Mar 1, 2012
    Messages:
    8
    I am using this reference in my project and it is very helpful. I just wanted to add to this what I have found out about

    int -- Unknown; seems to be a world wrap indicator (1 if wrap, 0 if no wrap)

    Actually I think this is a bitmask for misc. settings. In integer values this is what it refers to:

    first bit : World wrap on/off
    second bit : Randomize resources
    third bit : Randomize goodies

    So 7 is all on, 0 is all of and 5 is goodies and world wrap and so on...

    Edit 1: Figured out also that byte 5 is actually continent setting. Civ5 WorldBuilder has settings that allow you to set a continent. These are the values :

    // tile_buffer[5] unknown probably continents
    // 0 = nothing
    // 1 Americas
    // 2 Asia
    // 3 Africa
    // 4 Europe

    But when I painted a map (using default values for four corners generation), it appeared upside down. That is first all was Asia, which gave me a value 2 for the whole map except oceans and coasts. Then I changed one corner to America and one to Europe. Those were the top corners, but in my output I had bottom corners reflect the change. So I'm thinking that the map actually starts at the width-1, height-1 and ends up at 0,0. It shouldn't be hard to flip those, just thought you should know. My project will at least definitely have a working Civ5Map reader and Civ5Map writer if anyone wants a copy when I'm finished.
     
  3. cst_zf

    cst_zf Chieftain

    Joined:
    Nov 30, 2019
    Messages:
    4
    Gender:
    Male
    Something new:
    1. Version can be xC in the latest version of WorldBuilder.

    2. Mod Data Part
    in front of
    there is a part storing Mod Data, which seems like some opcode. So I cannot guess how to count the length of this part.
    And Unknown field is also related with this.
    3. After Building Type List, there is a part contains some scenario game options. but not simply separated by nil, but with a one-byte-long length in front of each string.

    4. Map Width and Map Height is UInt32, from decompiling the world builder.

    5. There are some xFF after all the data. I get two situation of its length, Width*Height*2 or Width*Height*8.
     
  4. cst_zf

    cst_zf Chieftain

    Joined:
    Nov 30, 2019
    Messages:
    4
    Gender:
    Male
    Does any one know how the river indicator is computed? I find the lowest 3 bits means three directions(left down, right down and right). but the higher bits may also be set. I cannot guess the rule.
     
  5. cst_zf

    cst_zf Chieftain

    Joined:
    Nov 30, 2019
    Messages:
    4
    Gender:
    Male
    I got it!
    The int field Unknown is the length of ModData Part.
    my summary:
     
    Last edited: Dec 1, 2019
  6. cst_zf

    cst_zf Chieftain

    Joined:
    Nov 30, 2019
    Messages:
    4
    Gender:
    Male
    Further Advance from decompiling world builder:
    Byte 3 of MapData -- Flag, Bit Masked Byte, the high 5 bits is something, the low 3 bits is river indicator.
    Byte 5 of MapData -- FeatureB, which is natural wonder
    Byte 7 of MapData -- Resource Amount
     
  7. PiR

    PiR Prince Supporter

    Joined:
    Jan 25, 2012
    Messages:
    589
    Gender:
    Male
    Thanks!! I'm using the last version available on the repo, very useful!!
     

Share This Page