Overview
Generated Maps are collections of data that define various aspects of the Age of Empires IV random terrain generator, allowing you to create a general map layout that will be different each time it is loaded.
When working on generated maps, there are five key concepts that are useful to understand.
This guide covers what these concepts are, what they affect, and how to work with them when building a Generated Map. Each are detailed below and explained throughout the guide.
Key Concepts
Terrain Table is a virtual LUA table that holds all the necessary info to generate the map, including terrain and player locations. You can use this table to place special terrain types that deposit resources in specific squares. A set of resources placed on a terrain type is called a local distribution.
Player Starts are encoded into the Terrain Table, and specify where player town centres are located on the map when it generates.
Balanced Resource Settings are what you will use to place the majority of the resources on the map, outside of resources that are placed directly with special terrain squares. These resources take player location into account and place resources in relation to where opponents are.
Distributions are lists of objects that are placed via a terrain type or a global list.
Terrain Types are the data that we fill each square of the Terrain Table with. They contain data that controls the terrain height and whether a local distribution is attached to the terrain.
Terrain Table
In each Generated Map, you will find a table called the terrainLayoutResult.
This table holds all the necessary map information that gets passed to the terrain generator.
Imagine the terrainLayoutResult as a square grid. If you are familiar with the Terrain Layout Tool for Crafted Maps, what you are seeing there is a visual representation of the terrainLayoutResult table. Each square of the table can hold various kinds of information, which when combined together creates your map.
Each square of the grid can contain the following information:
- A terrain type (necessary)
- A player index (optional)
Terrain types are entered into the table with the following format:
terrainLayoutResult[row][col].terrainType = tt_plains
In the above example, "row" and "col" are your X and Y coordinates on your grid, and "tt_plains" is the basic flat ground terrain used for open plains.
A player index indicates where specific players are set to start on the map. Normally, a player index is coupled with a terrain type that has starting resources attached, so that players spawn with their Town Centre and the standard ring of resources around them.
Placing a player on the map looks like the example below:
terrainLayoutResult[playerRow][playerCol].terrainType = tt_player_start_classic_plains
terrainLayoutResult[playerRow][playerCol].playerIndex = 1
These two lines will place player 1 at the specified row and column, with a terrain square that spawns the standard set of starting resources around the player's town centre.
Player Starts
A Player Start acts as a player spawn location, with the playerIndex corresponding to the order in which players appear in the lobby screen.
Note: In code, the playerIndex count starts at 0. For a 2 player map, the playerIndexes must be 0 and 1.
When a Player Start is added to a terrain square, the centre of that square will get a marker placed there that hooks into the running Game Mode script to place starting objects. This is normally a Town Centre, several villagers, a scout, and can be extended through the Game Mode script.
As Player Starts are separate from local distributions, you can create a Player Start without any local resources, or use a different set of local resources by spawning a different terrain type on the same square as your player index.
Player Start Functions
There are several built-in library functions that place player starts for you. Each of these player start functions require the use of several parameters, which includes the following:
- PlacePlayerStarts - The most basic version of the function. Will place players throughout the map while respecting impasse and minimum distances. Can place players closer to the centre of a map.
- PlacePlayerStartsRing - The standard player spawn function used across most open maps. Places players in a ring around the map, with parameters to avoid placing players right in the corners, near impasse, or near the centre of the map. If you imagine a donut overlaying the map, you can specify the thickness of the donut and the size of the centre hole, and players will be placed within those constraints.
- PlacePlayerStartsTogetherRing - A slight modification of the PlacePlayerStartsRing function, designed to ensure that multi-team games spawn teammates close together (e.g. in a 2v2v2v2). This function is used on the Confluence map to place teammates in the same quadrant as their allies.
- PlacePlayerStartsDivided - A spawn function that places players in 2 opposing straight lines, either horizontally or vertically. This is only used for placing 2 teams, and is useful for maps that have some sort of dividing geography down the centre, such as Mountain Pass, Mongolian Heights, and Nagari.
Refer to the generated map template for a more detailed explanation on exactly how to use these functions and their parameters.
All of the above functions can take in parameters like a list of terrain types to avoid, as well as player spawn distances and team distances to try to adhere to. They use a recursive style of execution, where if the function cannot fit players onto the map with the selected minimum player distance and terrain types to avoid, it will shrink the distances between players and try again. Use these functions to ensure that players are placed away from things like mountains and lakes, to ensure that map geography is not broken by player start locations.
We also normally place a radius of flat buffer terrain around players, in order to give them some build space for their initial cities. You can turn this on and off, although for gameplay reasons, we suggest you use the buffer (many maps have a buffer radius of 2 tiles)
Balanced Resource Settings
Assuring a map's resources are balanced is essential to the playability of a Generated Map.
There are several important things to know about distributing a map's resources evenly.
Setting and Tuning Balanced Resources Per Map
In the Attribute Editor, the map_gen\map_gen_layout data provides the ability to set and tune how the Balanced Resource system distributes our important resources on a per-map basis.
For example, if you want one of your maps to spawn a larger than normal amount of gold that is accessible to each player, you have the ability to create that on a single map without affecting the tuning or balance of other skirmish maps.
This tuning data is found under selectable_map_sizes, which allows you to control how many resources spawn on a per-size basis.
Opening this data tab will present you with a list of sizes. The data is arranged this way to allow you to place different amounts of resources per size, per map.
This gives you significant flexibility at the cost of having a large volume of data overhead.
For each size on this map, you can see a number of options that affect resource spawning.
Under the distribution_balancing heading you will see an expandable list, where each entry acts as an override for a specific resource's default settings.
These settings are based on the map_gen_size defaults, as shown in the example below
When you include one of these resource entries in the list inside your map layout, you are signaling that you want to spawn something other than the defaults.
For example, when manually placing sacred sites with your LUA script, you want to create an override entry in your map's list of balanced resources where you set the contested_base_spawn_count to 0 to not spawn extra sacred sites on the map over what you are already placing via script.
Distributions Balancing
Distribution_balancing is where all the resource tuning of gold, stone and other important resources happens. For each type of resource, there are several options:
- Accessible_spawns govern resources placed for each player within an area of accessibility. A value of 1.0 is close to a player, while 0.1 is near the edge of their accessible zone.
You can look at a player's access map in the debug imagery, which will resemble the image below, where the access distance is determined by the player_resource_access_distance variable. The accessible_range_min/max values determine the areas where the accessible resources are placed, for example, setting a min/max to 0.8/1.0 places the resource only in the bright white areas. - Avoid_any_spawn_distance will attempt to place this type of resource at least this many meters away from other resources. If not enough space is found, this distance will decrease as a fallback option to attempt to ensure your resource is placed.
- Avoid_same_spawn_distance will attempt to spread out each individual instance of this resource type from itself only. This is useful for spreading out things like sacred sites, which you want to be spread apart for balance and good gameplay.
- Contested_additional_spawns_per_player scales how many of each contested resource is placed based on the players in the match. This can be a decimal number, so for example, you can spawn an extra 2 gold deposits in a 4 player game by setting this value to 0.5.
- Contested_base_spawn_count is the standard number of this resource you would like to place. This value is for the map, not each player, so a value of 3 will place 3 of the resource on the map.
- Contested_excludes_starting_land_mass is useful for island maps, where you don't want this resource to be placed on players' starting islands. Setting this to true will result in only neutral islands being available for spawning.
- Contested_range_min/max works similarly to the accessible version, except these values control the placement of the contested resources using the contested map. A 0.45-0.55 contested range will distribute resources in as contentious a location as possible, which results in resources being placed exactly half way between players, and the closer you get to 0.0, the further that resources can get towards players.
- Spawn_priority determines the order of placement for all balanced resources. Standard Age of Empires IV tends to place win condition objects like sacred sites higher than things like stone or gold deposits, for example.
Additional Variables
There are an additional number of variables that set size-related settings, detailed below.
- Contested_range is how wide the contested area of the map will be.
- Distribution_balancing_list contains the list of resources that are distributed by the balanced resource system. You have the ability to add more resources to this list through the Attribute Editor under map_gen\distribution\distribution_balancing_list
- Player_start_influence_distance determines how far from the players' start positions resources need to be in order to be placed.
- Solo_play_contested_area_start/end are the values used create the contested map in games where only a single player loads in (ie: sandbox mode). This allows the full map's resources to be spawned in without the need for competing access maps to create the contested areas.
Additional Biome Settings
For each map, special settings are specified that affect the map differently depending on the chosen biome.
Age of Empires IV doesn't currently set anything that will affect gameplay, but it can set extra decorative distributions on certain map or biome combinations.
To do this, right-click the selectable_biomes data entry and add a new selectable_biome data point. This will expose the settings detailed below.
- Additional_distributions is a slot where you can specify a global distribution that will be spawned only in the current biome. This allows you to have differing quantities of trees, rocks, and other globally-distributed objects on a per-biome basis. This can be left null with no consequence. You can use any global distribution here, although there are specific sets of distributions available for each biome under map_gen\distribution\global_distributions\additional
- Atmosphere overrides the atmosphere data present in the map_gen_biome. This adjusts the lighting settings that will be used in the map and allows you to use an atmosphere on this specific map layout / biome combination, creating things such as a foggy maps where it would otherwise be bright and sunny. Atmosphere files are found under scenarios\atmosphere
- Biome sets which biome you wish this data to affect. Biomes are found in the Attribute Editor under map_gen\map_gen_biome
Distributions
Distribution is the method used for placing objects procedurally during map generation.
Everything that exists on the map when you start a skirmish game is placed with the distribution systems, such as trees, rocks, resource deposits, or neutral settlements. To better understand the distribution system, it helps to know how objects are categorized and how these categories differ from one another.
To manipulate Distribution systems, is first important to understand the concept of global vs local distributions, as well as region vs cell placement.
Global vs Local
At a high level, the distinction between global/local and region/cell distributions can be thought of in terms of food delivery services. Our global distribution system acts like everywhere that a pizza chain can deliver to in a given city - it's map-wide. Local distributions are like looking at where a single physical restaurant delivers to, within a radius around the store.
The image below shows a global distribution.
The image below shows a local distribution.
Regions vs Cells
Regions and cells can be thought of as how your food comes packaged. Imagine if you ordered a dozen bagels.
If the bagels came in multiple boxes (bigger than an individual bagel), this would be similar to our region placement - each box can contain a number of individual bagels. In this case, you can't have multiple boxes occupying the same space, since the dimensions of the box would create a buffer space which other boxes can't occupy.
However, if you were instead given 12 small plates, each containing a single bagel, this is similar to cell placement, with each object being places as its own individual object, taking up minimal space, with no buffer that blocks placement of adjacent objects.
Maps in Age of Empires IV are created on top of a 1m cellular grid, so a cellular object takes up a single grid cell.
The image below shows the cell grid overlay turned on, showing the 1m grid.
The image below shows a sample of several regions.
The image below shows several cellular objects.
The image below shows a region distribution of berry bushes.
The image below shows cellularly placed rocks. The red dots denote each object.
Global vs Local Distribution
It is easiest to think of Global Distribution as a map-wide scattering of whatever object is being placed.
An object's global distribution has associated data that controls where that item can spawn on the map, as well as quantity settings that control how many can spawn across the whole map. A common example would be individual trees, which are generally distributed throughout a map in high numbers in a random pattern.
A Local Distribution, on the other hand, is generally a much smaller number of objects that are distributed radially around a specific point on the map.
Local distributions are attached to certain terrain types that are placed on the map grid via the LUA scripts.
For example, Age of Empires IV has a "gold bounty" terrain type that, when placed on the map grid, spawns a gold deposit in a small radius around the centre of that grid square. Local distributions are used to (1) generate each player's starting resources (player start terrain contains local distribution for starting resources), and (2) generate resources on maps when they are needed in specific places.
Local distributions have associated data that control how many objects are placed, the radius of the distribution area, and where the local objects are allowed to be placed. For example, how many trees there are, the the distribution of those trees, and preventing those trees from being placed in water.
Region vs Cell Distribution
Regions and Cells refer to how objects are placed, rather than where on the overall map.
Objects can be placed either as one of the two areas:
- Region - a radial area that can be occupied by one or more of the objects being placed and which blocks other regions
- Cell - the object occupies a single 1m cell
Both Regions and Cells can be set up as global or local distributions. You may use global regions for things like forests, global cells for things like cliffside rocks, local regions for a player's starting gold, and local cells for things like sheep.
Any object can be set up to spawn either as a region or cell. Be sure to remember the context around what each of these options mean when choosing how to set up your data. Objects spawned as Regions have guaranteed space between them, while objects spawned as Cells can be close enough to overlap.
Both are useful in different situations, but each also has potential drawbacks, such as gold deposits being poor candidates for Cell spawning as you don't want two or more deposits physically overlapping and it is important for players to have room to build mining camps next to them.
It's also worth noting that each object spawned as a region or cell can be spawned using a group spawn, which will create a number of objects in a radius with a user-specified density. This is how we create our various types of forests and ensure that the trees are spaced exactly as far apart as we want.
Distribution Passes
During map generation, object placement occurs in several distinct "passes" in order to ensure that the most important objects are given spatial priority. Objects with less gameplay importance are spawned later in the process, as it matters less if there is no more room to place them.
Distribution passes occur in four distinct phases, detailed below.
Pass #1: Local Distributions
Local distributions such as starting resources are spawned first, as they are the highest priority objects on the map in terms of game fairness and balance.
This ensures that maps such as French Pass with its non-starting gold spawns in a central valley play as intended without elements like forests or decorative rocks blocking these vital resources.
The image below shows an example of a local starting resource distribution for a typical 4 player skirmish map. Each circle represents a different region, roughly colour-coded to the type of resource it represents (green for trees, yellow for gold, grey for stone, purple for berries, white for sheep).
Pass #2: Balanced Distributions
Balanced resource distributions are prioritized next, as these are next in terms of gameplay priority.
This includes all on-map gold, stone, settlements, and religious objects. This method of distribution uses the ideas of "Contested" vs "Accessible" areas of a map to ensure that there are (1) resources the players feel they can safely colonize and harvest, and (2) resources further out in the field to fight over.
The image below shows the areas of the map that are contested between the lower-left and upper-left player.
Pass #3: Global Biome Distributions
Depending on the map, each biome may have a separate set of global distributions set to spawn.
Because this is a more specific set of data, this biome distribution takes a higher priority than the generic global distribution set outside the biome settings on the map. This ensures that any biome-specific objects you want on your map will be spawned before the generic global objects.
In all other ways, these distributions function exactly like other global distributions.
The image below shows a sample Global Biome Distribution spawned on an instance of Boulder Bay.
Pass #4: Global Distributions
Global distributions go last, due to the fact that most of the global distribution lists are comprised of our map "dressing", such as non-essential rocks, bushes, and other environment objects.
Trees are included here as well, due to their sheer quantity and relative unimportance to player strategy (individual trees as not as important as gold or stone, for example).
The image below shows all local and global regions spawned on a map.
Terrain Types
A Terrain Type is a wrapper for data that gets used to generate a part of a map.
Each Terrain Type can be characterized by: (1) what it does to terrain elevation, and (2) if it spawns something via a local distribution.
The Terrain Table is built mostly out of different Terrain Types, with each type corresponding to one "square" of terrain.
Most of these are self explanatory, such as tt_mountains being used to create mountains. Others, such as tt_settlement_plains, are used specifically to spawn a Trade Post on flat ground, while others, like tt_player_start_classic_plains, sets a local distribution full of the standard starting resources.
In this terrain type example, there are a number of things to note:
- Global distribution blocking radius - this will control if an area around the centre of this terrain square is blocked from placing anything from the map's global distribution, including things such as forests, bushes, animals, and whatever else may be in your global distribution.
- Is lake source - if set to true, will attempt to spawn water if there is a concave shape of the terrain within the square.
- Local distribution priority - this will let you control the ordering of local distributions. A higher number will help ensure that this local distribution spawns earlier.
- Local distributions - this is a list of objects or resources that this terrain type will spawn, with a radius from the centre of this square.
- Min cliff height - this will let this square form a cliff if adjacent squares are above or below this square's height threshold.
- Terrain height params - this is what sets the terrain behavior of this terrain type.
- Higher amplitude will mean higher deviation from the base height, and is used for things like mountains.
- A positive direction bias (above 0) will mean that any variation in height from the base will tend up, making hills and mountains. A negative bias will form valleys.
- Shift variance will determine how much the height can deviate from the base height. Rolling hills and mountains will want a potentially higher variance.
- Height over width is the base height of the terrain. Higher values will give hills, lower values will give valleys, without factoring in any variance or amplitude.