1 const TERRAIN_SEPARATOR = "|";
2 const SEA_LEVEL = 20.0;
3 const HEIGHT_UNITS_PER_METRE = 92;
6 * Number of impassable, unexplorable tiles at the map border.
8 const MAP_BORDER_WIDTH = 3;
10 const g_DamageTypes = new DamageTypes();
13 * Constants needed for heightmap_manipulation.js
15 const MAX_HEIGHT_RANGE = 0xFFFF / HEIGHT_UNITS_PER_METRE; // Engine limit, Roughly 700 meters
16 const MIN_HEIGHT = - SEA_LEVEL;
19 * Length of one tile of the terrain grid in metres.
20 * Useful to transform footprint sizes of templates to the coordinate system used by getMapSize.
22 const TERRAIN_TILE_SIZE = Engine.GetTerrainTileSize();
24 const MAX_HEIGHT = MAX_HEIGHT_RANGE - SEA_LEVEL;
27 * Default angle for buildings.
29 const BUILDING_ORIENTATION = -1/4 * Math.PI;
31 const g_CivData = deepfreeze(loadCivFiles(false));
34 * Sets whether setHeight operates on the center of a tile or on the vertices.
36 var TILE_CENTERED_HEIGHT_MAP = false;
38 function fractionToTiles(f)
40 return g_MapSettings.Size * f;
43 function tilesToFraction(t)
45 return t / g_MapSettings.Size;
48 function scaleByMapSize(min, max, minMapSize = 128, maxMapSize = 512)
50 return min + (max - min) * (g_MapSettings.Size - minMapSize) / (maxMapSize - minMapSize);
53 function randomPositionOnTile(tilePosition)
55 return Vector2D.add(tilePosition, new Vector2D(randFloat(0, 1), randFloat(0, 1)));
59 * Retries the given function with those arguments as often as specified.
61 function retryPlacing(placeFunc, retryFactor, amount, getResult, behaveDeprecated = false)
63 let maxFail = amount * retryFactor;
69 while (good < amount && bad <= maxFail)
71 let result = placeFunc();
73 if (result !== undefined || behaveDeprecated)
82 return getResult ? results : good;
85 // TODO this is a hack to simulate the old behaviour of those functions
86 // until all old maps are changed to use the correct version of these functions
87 function createObjectGroupsDeprecated(group, player, constraint, amount, retryFactor = 10)
89 return createObjectGroups(group, player, constraint, amount, retryFactor, true);
92 function createObjectGroupsByAreasDeprecated(group, player, constraint, amount, retryFactor, areas)
94 return createObjectGroupsByAreas(group, player, constraint, amount, retryFactor, areas, true);
98 * Attempts to place the given number of areas in random places of the map.
99 * Returns actually placed areas.
101 function createAreas(centeredPlacer, painter, constraint, amount, retryFactor = 10)
103 let placeFunc = function() {
104 centeredPlacer.setCenterPosition(g_Map.randomCoordinate(false));
105 return createArea(centeredPlacer, painter, constraint);
108 return retryPlacing(placeFunc, retryFactor, amount, true, false);
112 * Attempts to place the given number of areas in random places of the given areas.
113 * Returns actually placed areas.
115 function createAreasInAreas(centeredPlacer, painter, constraint, amount, retryFactor, areas)
117 let placeFunc = function() {
118 centeredPlacer.setCenterPosition(pickRandom(pickRandom(areas).points));
119 return createArea(centeredPlacer, painter, constraint);
122 return retryPlacing(placeFunc, retryFactor, amount, true, false);
126 * Attempts to place the given number of groups in random places of the map.
127 * Returns the number of actually placed groups.
129 function createObjectGroups(group, player, constraint, amount, retryFactor = 10, behaveDeprecated = false)
131 let placeFunc = function() {
132 group.setCenterPosition(g_Map.randomCoordinate(true));
133 return createObjectGroup(group, player, constraint);
136 return retryPlacing(placeFunc, retryFactor, amount, false, behaveDeprecated);
140 * Attempts to place the given number of groups in random places of the given areas.
141 * Returns the number of actually placed groups.
143 function createObjectGroupsByAreas(group, player, constraint, amount, retryFactor, areas, behaveDeprecated = false)
145 let placeFunc = function() {
146 group.setCenterPosition(pickRandom(pickRandom(areas).points));
147 return createObjectGroup(group, player, constraint);
150 return retryPlacing(placeFunc, retryFactor, amount, false, behaveDeprecated);
153 function createTerrain(terrain)
155 return typeof terrain == "string" ?
156 new SimpleTerrain(...terrain.split(TERRAIN_SEPARATOR)) :
157 new RandomTerrain(terrain.map(t => createTerrain(t)));
161 * Constructs a new Area shaped by the Placer meeting the Constraints and calls the Painters there.
162 * Supports both Centered and Non-Centered Placers.
164 function createArea(placer, painters, constraints)
166 let points = placer.place(new AndConstraint(constraints));
170 let area = g_Map.createArea(points);
172 new MultiPainter(painters).paint(area);
178 * @param mode is one of the HeightPlacer constants determining whether to exclude the min/max elevation.
180 function paintTerrainBasedOnHeight(minHeight, maxHeight, mode, terrain)
183 new HeightPlacer(mode, minHeight, maxHeight),
184 new TerrainPainter(terrain));
187 function paintTileClassBasedOnHeight(minHeight, maxHeight, mode, tileClass)
190 new HeightPlacer(mode, minHeight, maxHeight),
191 new TileClassPainter(tileClass));
194 function unPaintTileClassBasedOnHeight(minHeight, maxHeight, mode, tileClass)
197 new HeightPlacer(mode, minHeight, maxHeight),
198 new TileClassUnPainter(tileClass));
202 * Places the Entities of the given Group if they meet the Constraints
203 * and sets the given player as the owner.
205 function createObjectGroup(group, player, constraints)
207 return group.place(player, new AndConstraint(constraints));
211 * Create an avoid constraint for the given classes by the given distances
213 function avoidClasses(/*class1, dist1, class2, dist2, etc*/)
216 for (let i = 0; i < arguments.length/2; ++i)
217 ar.push(new AvoidTileClassConstraint(arguments[2*i], arguments[2*i+1]));
219 // Return single constraint
223 return new AndConstraint(ar);
227 * Create a stay constraint for the given classes by the given distances
229 function stayClasses(/*class1, dist1, class2, dist2, etc*/)
232 for (let i = 0; i < arguments.length/2; ++i)
233 ar.push(new StayInTileClassConstraint(arguments[2*i], arguments[2*i+1]));
235 // Return single constraint
239 return new AndConstraint(ar);
243 * Create a border constraint for the given classes by the given distances
245 function borderClasses(/*class1, idist1, odist1, class2, idist2, odist2, etc*/)
248 for (let i = 0; i < arguments.length/3; ++i)
249 ar.push(new BorderTileClassConstraint(arguments[3*i], arguments[3*i+1], arguments[3*i+2]));
251 // Return single constraint
255 return new AndConstraint(ar);
258 function convertHeightmap1Dto2D(heightmap)
261 let hmSize = Math.sqrt(heightmap.length);
262 for (let x = 0; x < hmSize; ++x)
264 result[x] = new Float32Array(hmSize);
265 for (let y = 0; y < hmSize; ++y)
266 result[x][y] = heightmap[y * hmSize + x];