2 * Heightmap image source:
3 * Imagery by Jesse Allen, NASA's Earth Observatory,
4 * using data from the General Bathymetric Chart of the Oceans (GEBCO)
5 * produced by the British Oceanographic Data Centre.
6 * https://visibleearth.nasa.gov/view.php?id=73934
8 * Licensing: Public Domain, https://visibleearth.nasa.gov/useterms.php
10 * The heightmap image is reproduced using:
11 * wget https://eoimages.gsfc.nasa.gov/images/imagerecords/73000/73934/gebco_08_rev_elev_{A,B,C,D}{1..2}_grey_geo.tif
12 * gdal_merge.py -o world.tif gebco_08_rev_elev_{A,B,C,D}{1..2}_grey_geo.tif
13 * lat=46; lon=14; width=58;
14 * gdal_translate -projwin $((lon-width/2)) $((lat+width/2)) $((lon+width/2)) $((lat-width/2)) world.tif mediterranean.tif
15 * convert mediterranean.tif -resize 512 -contrast-stretch 0 mediterranean.png
16 * No further changes should be applied to the image to keep it easily interchangeable.
19 Engine.LoadLibrary("rmgen");
20 Engine.LoadLibrary("rmgen-common");
21 Engine.LoadLibrary("rmgen2");
22 Engine.LoadLibrary("rmbiome");
24 TILE_CENTERED_HEIGHT_MAP = true;
26 const tWater = "medit_sand_wet";
27 const tSnowedRocks = ["alpine_cliff_b", "alpine_cliff_snow"];
28 setBiome("generic/mediterranean");
30 const heightScale = num => num * g_MapSettings.Size / 320;
32 const heightSeaGround = heightScale(-6);
33 const heightWaterLevel = heightScale(0);
34 const heightShoreline = heightScale(0.5);
35 const heightSnow = heightScale(10);
37 var g_Map = new RandomMap(heightWaterLevel, g_Terrains.mainTerrain);
38 var mapSize = g_Map.getSize();
39 var mapCenter = g_Map.getCenter();
40 var mapBounds = g_Map.getBounds();
42 g_Map.LoadHeightmapImage("mediterranean.png", 0, 40);
43 Engine.SetProgress(15);
45 initTileClasses(["autumn", "desert", "medit", "polar", "steppe", "temp", "shoreline", "africa", "northern_europe", "southern_europe", "western_europe", "eastern_europe"]);
47 var northernTopLeft = new Vector2D(fractionToTiles(0.3), fractionToTiles(0.7));
48 var westernTopLeft = new Vector2D(fractionToTiles(0.7), fractionToTiles(0.47));
49 var africaTop = fractionToTiles(0.33);
53 "tileClass": g_TileClasses.northern_europe,
54 "position1": new Vector2D(northernTopLeft.x, mapBounds.top),
55 "position2": new Vector2D(mapBounds.right, northernTopLeft.y),
56 "biome": "generic/snowy",
57 "constraint": new NullConstraint()
60 "tileClass": g_TileClasses.western_europe,
61 "position1": new Vector2D(mapBounds.left, mapBounds.top),
62 "position2": westernTopLeft,
63 "biome": "generic/temperate",
64 "constraint": avoidClasses(g_TileClasses.northern_europe, 0)
67 "tileClass": g_TileClasses.eastern_europe,
68 "position1": new Vector2D(westernTopLeft.x, mapBounds.top),
69 "position2": new Vector2D(mapBounds.right, westernTopLeft.y),
70 "biome": "generic/autumn",
71 "constraint": avoidClasses(g_TileClasses.northern_europe, 0)
74 "tileClass": g_TileClasses.southern_europe,
75 "position1": new Vector2D(mapBounds.left, africaTop),
76 "position2": new Vector2D(mapBounds.right, westernTopLeft.y),
77 "biome": "generic/mediterranean",
78 "constraint": new NullConstraint()
81 "tileClass": g_TileClasses.africa,
82 "position1": new Vector2D(mapBounds.left, africaTop),
83 "position2": new Vector2D(mapBounds.right, mapBounds.bottom),
84 "biome": "generic/desert",
85 "constraint": new NullConstraint()
89 g_Map.log("Lowering sea ground");
91 new MapBoundsPlacer(),
92 new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 2),
93 new HeightConstraint(-Infinity, heightWaterLevel));
94 Engine.SetProgress(20);
96 g_Map.log("Smoothing heightmap");
98 new MapBoundsPlacer(),
99 new SmoothingPainter(1, scaleByMapSize(0.3, 0.8), 1));
100 Engine.SetProgress(25);
102 g_Map.log("Marking water");
104 new MapBoundsPlacer(),
105 new TileClassPainter(g_TileClasses.water),
106 new HeightConstraint(-Infinity, heightWaterLevel));
107 Engine.SetProgress(30);
109 g_Map.log("Marking land");
111 new DiskPlacer(fractionToTiles(0.5), mapCenter),
112 new TileClassPainter(g_TileClasses.land),
113 avoidClasses(g_TileClasses.water, 0));
114 Engine.SetProgress(35);
116 g_Map.log("Marking climate zones");
117 for (let zone of climateZones)
119 setBiome(zone.biome);
121 new RectPlacer(zone.position1, zone.position2, Infinity),
122 new TileClassPainter(zone.tileClass),
126 new RectPlacer(zone.position1, zone.position2, Infinity),
127 new TerrainPainter(g_Terrains.mainTerrain),
129 new HeightConstraint(heightWaterLevel, Infinity),
133 Engine.SetProgress(40);
135 g_Map.log("Fuzzing biome borders");
136 for (let zone of climateZones)
138 setBiome(zone.biome);
140 createLayeredPatches(
141 [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)],
143 [g_Terrains.mainTerrain, g_Terrains.tier1Terrain],
144 [g_Terrains.tier1Terrain, g_Terrains.tier2Terrain],
145 [g_Terrains.tier2Terrain, g_Terrains.tier3Terrain]
150 g_TileClasses.forest, 2,
151 g_TileClasses.water, 2,
152 g_TileClasses.mountain, 2,
153 g_TileClasses.dirt, 5,
154 g_TileClasses.player, 8),
155 borderClasses(zone.tileClass, 3, 3),
157 scaleByMapSize(20, 60),
160 Engine.SetProgress(45);
164 g_Map.log("Finding player positions");
166 let [playerIDs, playerPosition] = playerPlacementRandom(
169 avoidClasses(g_TileClasses.mountain, 5),
170 stayClasses(g_TileClasses.land, scaleByMapSize(8, 25))
173 g_Map.log("Flatten the initial CC area and placing playerbases...");
174 for (let i = 0; i < getNumPlayers(); ++i)
176 g_Map.logger.printDuration();
177 setBiome(climateZones.find(zone => zone.tileClass.has(playerPosition[i])).biome);
180 new ClumpPlacer(diskArea(defaultPlayerBaseRadius() * 0.8), 0.95, 0.6, Infinity, playerPosition[i]),
181 new SmoothElevationPainter(ELEVATION_SET, g_Map.getHeight(playerPosition[i]), 6));
183 createBase(playerIDs[i], playerPosition[i], mapSize >= 384);
186 Engine.SetProgress(50);
188 for (let zone of climateZones)
190 setBiome(zone.biome);
192 g_Map.log("Painting shoreline");
194 new MapBoundsPlacer(),
196 new TerrainPainter(g_Terrains.shore),
197 new TileClassPainter(g_TileClasses.shoreline)
200 stayClasses(zone.tileClass, 0),
201 new HeightConstraint(-Infinity, heightShoreline)
204 g_Map.log("Painting cliffs");
206 new MapBoundsPlacer(),
208 new TerrainPainter(g_Terrains.cliff),
209 new TileClassPainter(g_TileClasses.mountain),
212 stayClasses(zone.tileClass, 0),
213 avoidClasses(g_TileClasses.water, 2),
214 new SlopeConstraint(2, Infinity)
217 g_Map.log("Placing resources");
222 g_TileClasses.berries, 5,
223 g_TileClasses.forest, 3,
224 g_TileClasses.mountain, 2,
225 g_TileClasses.player, 30,
226 g_TileClasses.rock, 10,
227 g_TileClasses.metal, 25,
228 g_TileClasses.water, 4
230 "stay": [zone.tileClass, 0],
238 g_TileClasses.berries, 5,
239 g_TileClasses.forest, 3,
240 g_TileClasses.mountain, 2,
241 g_TileClasses.player, 30,
242 g_TileClasses.rock, 10,
243 g_TileClasses.metal, 25,
244 g_TileClasses.water, 4
246 "stay": [zone.tileClass, 0],
254 g_TileClasses.berries, 3,
255 g_TileClasses.forest, 15,
256 g_TileClasses.metal, 3,
257 g_TileClasses.mountain, 2,
258 g_TileClasses.player, 12,
259 g_TileClasses.rock, 2,
260 g_TileClasses.water, 2
262 "stay": [zone.tileClass, 0],
265 "amounts": ["normal"]
268 "func": addSmallMetal,
270 g_TileClasses.berries, 5,
271 g_TileClasses.forest, 3,
272 g_TileClasses.mountain, 2,
273 g_TileClasses.player, 30,
274 g_TileClasses.rock, 10,
275 g_TileClasses.metal, 15,
276 g_TileClasses.water, 4
278 "stay": [zone.tileClass, 0],
281 "amounts": ["few", "normal", "many"]
286 g_TileClasses.berries, 30,
287 g_TileClasses.forest, 2,
288 g_TileClasses.metal, 4,
289 g_TileClasses.mountain, 2,
290 g_TileClasses.player, 20,
291 g_TileClasses.rock, 4,
292 g_TileClasses.water, 2
294 "stay": [zone.tileClass, 0],
302 g_TileClasses.animals, 10,
303 g_TileClasses.forest, 1,
304 g_TileClasses.metal, 2,
305 g_TileClasses.mountain, 1,
306 g_TileClasses.player, 15,
307 g_TileClasses.rock, 2,
308 g_TileClasses.water, 3
310 "stay": [zone.tileClass, 0],
318 g_TileClasses.animals, 10,
319 g_TileClasses.forest, 1,
320 g_TileClasses.metal, 2,
321 g_TileClasses.mountain, 1,
322 g_TileClasses.player, 15,
323 g_TileClasses.rock, 2,
324 g_TileClasses.water, 1
326 "stay": [zone.tileClass, 0],
332 "func": addStragglerTrees,
334 g_TileClasses.berries, 5,
335 g_TileClasses.forest, 5,
336 g_TileClasses.metal, 2,
337 g_TileClasses.mountain, 1,
338 g_TileClasses.player, 12,
339 g_TileClasses.rock, 2,
340 g_TileClasses.water, 3
342 "stay": [zone.tileClass, 0],
348 "func": addLayeredPatches,
350 g_TileClasses.dirt, 5,
351 g_TileClasses.forest, 2,
352 g_TileClasses.mountain, 2,
353 g_TileClasses.player, 12,
354 g_TileClasses.water, 3
356 "stay": [zone.tileClass, 0],
362 "func": addDecoration,
364 g_TileClasses.forest, 2,
365 g_TileClasses.mountain, 2,
366 g_TileClasses.player, 12,
367 g_TileClasses.water, 4
369 "stay": [zone.tileClass, 0],
372 "amounts": ["normal"]
376 Engine.SetProgress(60);
378 g_Map.log("Painting water");
380 new MapBoundsPlacer(),
381 new TerrainPainter(tWater),
382 new HeightConstraint(-Infinity, heightWaterLevel));
384 g_Map.log("Painting snow on mountains");
386 new MapBoundsPlacer(),
387 new TerrainPainter(tSnowedRocks),
389 new HeightConstraint(heightSnow, Infinity),
391 g_TileClasses.africa, 0,
392 g_TileClasses.southern_europe, 0,
393 g_TileClasses.player, 6)
396 Engine.SetProgress(70);
398 g_Map.log("Placing fish...");
399 g_Gaia.fish = "gaia/fauna_fish";
404 g_TileClasses.fish, 10,
406 "stay": [g_TileClasses.water, 4],
408 "mixes": ["similar"],
412 Engine.SetProgress(85);
414 g_Map.log("Placing whale...");
415 g_Gaia.fish = "gaia/fauna_whale_fin";
420 g_TileClasses.fish, 2,
421 g_TileClasses.desert, 50,
422 g_TileClasses.steppe, 50
424 "stay": [g_TileClasses.water, 7],
427 "amounts": ["scarce"]
430 Engine.SetProgress(95);
433 g_Map.createTileClass(),
435 stayClasses(g_TileClasses.land, 5),
437 g_TileClasses.forest, 2,
438 g_TileClasses.rock, 4,
439 g_TileClasses.metal, 4,
440 g_TileClasses.berries, 2,
441 g_TileClasses.animals, 2,
442 g_TileClasses.mountain, 2)
445 setWindAngle(-0.589049);
446 setWaterTint(0.556863, 0.615686, 0.643137);
447 setWaterColor(0.494118, 0.639216, 0.713726);
449 setWaterMurkiness(0.87);
450 setWaterType("ocean");
452 setTerrainAmbientColor(0.72, 0.72, 0.82);
454 setSunColor(0.733, 0.746, 0.574);
455 setSunRotation(Math.PI * 0.95);
456 setSunElevation(Math.PI / 6);
458 setSkySet("cumulus");
461 setFogColor(0.69, 0.616, 0.541);
465 setPPSaturation(0.42);