Merge 'remotes/trunk'
[0ad.git] / binaries / data / mods / public / maps / random / ngorongoro.js
blobd6ad1667f9785dfd2f884a33fdb9e1de55d88dd2
1 /**
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
7  *
8  * Licensing: Public Domain, https://visibleearth.nasa.gov/useterms.php
9  *
10  * The heightmap image is reproduced using:
11  * wget https://eoimages.gsfc.nasa.gov/images/imagerecords/73000/73934/gebco_08_rev_elev_C2_grey_geo.tif
12  * lat=-3.177437; lon=35.574687; width=0.7
13  * lat1=$(bc <<< ";scale=5;$lat-$width/2"); lon1=$(bc <<< ";scale=5;$lon+$width/2"); lat2=$(bc <<< ";scale=5;$lat+$width/2"); lon2=$(bc <<< ";scale=5;$lon-$width/2")
14  * gdal_translate -projwin $lon2 $lat2 $lon1 $lat1 gebco_08_rev_elev_C2_grey_geo.tif ngorongoro.tif
15  * convert ngorongoro.tif -resize 512 -contrast-stretch 0 ngorongoro.png
16  * No further changes should be applied to the image to keep it easily interchangeable.
17  */
19 Engine.LoadLibrary("rmgen");
20 Engine.LoadLibrary("rmgen-common");
21 Engine.LoadLibrary("rmgen2");
22 Engine.LoadLibrary("rmbiome");
24 function* GenerateMap()
26         setBiome("generic/savanna");
28         g_Terrains.roadWild = "savanna_riparian_dry";
29         g_Terrains.road = "road2";
31         g_Gaia.metalLarge = "gaia/ore/savanna_large";
32         g_Gaia.metalSmall = "gaia/ore/tropical_small";
33         g_Gaia.fish = "gaia/fish/tilapia";
34         g_Gaia.tree1 = "gaia/tree/baobab";
35         g_Gaia.tree2 = "gaia/tree/baobab";
36         g_Gaia.tree3 = "gaia/tree/baobab";
37         g_Gaia.tree4 = "gaia/tree/baobab";
38         g_Gaia.tree5 = "gaia/tree/baobab";
40         g_Decoratives.grass = "actor|props/flora/grass_savanna.xml";
41         g_Decoratives.grassShort = "actor|props/flora/grass_soft_dry_tuft_a.xml";
42         g_Decoratives.rockLarge = "actor|geology/stone_savanna_med.xml";
43         g_Decoratives.rockMedium = "actor|geology/stone_savanna_med.xml";
44         g_Decoratives.bushMedium = "actor|props/flora/bush_desert_dry_a.xml";
45         g_Decoratives.bushSmall = "actor|props/flora/bush_dry_a.xml";
47         const heightScale = num => num * mapSettings.Size / 320;
49         const heightHighlands = heightScale(45);
50         const heightEden = heightScale(60);
51         const heightMax = 150;
53         function setBiomeLowlands()
54         {
55                 g_Gaia.mainHuntableAnimal = "gaia/fauna_giraffe";
56                 g_Gaia.secondaryHuntableAnimal = "gaia/fauna_zebra";
58                 g_Terrains.mainTerrain = "savanna_riparian_bank";
59                 g_Terrains.forestFloor1 = "savanna_dirt_rocks_b";
60                 g_Terrains.forestFloor2 = "savanna_dirt_rocks_c";
61                 g_Terrains.tier1Terrain = "savanna_dirt_rocks_a";
62                 g_Terrains.tier2Terrain = "savanna_grass_a";
63                 g_Terrains.tier3Terrain = "savanna_grass_b";
64                 g_Terrains.tier4Terrain = "savanna_forest_floor_a";
65         }
67         function setBiomeHighlands()
68         {
70                 g_Gaia.mainHuntableAnimal = "gaia/fauna_lioness";
71                 g_Gaia.secondaryHuntableAnimal = "gaia/fauna_lion";
73                 g_Terrains.mainTerrain = "savanna_grass_a_wetseason";
74                 g_Terrains.forestFloor1 = "savanna_grass_a";
75                 g_Terrains.forestFloor2 = "savanna_grass_b";
76                 g_Terrains.tier1Terrain = "savanna_grass_a_wetseason";
77                 g_Terrains.tier2Terrain = "savanna_grass_b_wetseason";
78                 g_Terrains.tier3Terrain = "savanna_shrubs_a_wetseason";
79                 g_Terrains.tier4Terrain = "savanna_shrubs_b";
80         }
82         function setBiomeEden()
83         {
84                 g_Gaia.mainHuntableAnimal = "gaia/fauna_rhinoceros_white";
85                 g_Gaia.secondaryHuntableAnimal = "gaia/fauna_elephant_african_bush";
86         }
88         globalThis.g_Map = new RandomMap(0, g_Terrains.mainTerrain);
89         const mapCenter = g_Map.getCenter();
91         initTileClasses(["eden", "highlands"]);
93         g_Map.LoadHeightmapImage("ngorongoro.png", 0, heightMax);
94         yield 15;
96         g_Map.log("Smoothing heightmap");
97         createArea(
98                 new MapBoundsPlacer(),
99                 new SmoothingPainter(1, scaleByMapSize(0.1, 0.5), 1));
100         yield 25;
102         g_Map.log("Marking land");
103         createArea(
104                 new MapBoundsPlacer(),
105                 new TileClassPainter(g_TileClasses.land));
106         yield 40;
108         g_Map.log("Marking eden");
109         createArea(
110                 new DiskPlacer(fractionToTiles(0.14), mapCenter),
111                 new TileClassPainter(g_TileClasses.eden),
112                 new HeightConstraint(-Infinity, heightEden));
113         yield 45;
115         g_Map.log("Marking highlands");
116         createArea(
117                 new MapBoundsPlacer(),
118                 new TileClassPainter(g_TileClasses.highlands),
119                 [
120                         new HeightConstraint(heightHighlands, Infinity),
121                         avoidClasses(g_TileClasses.eden, 0)
122                 ]);
123         yield 50;
125         g_Map.log("Painting cliffs");
126         createArea(
127                 new MapBoundsPlacer(),
128                 [
129                         new TerrainPainter(g_Terrains.cliff),
130                         new TileClassPainter(g_TileClasses.mountain),
131                 ],
132                 new SlopeConstraint(2, Infinity));
133         yield 55;
135         if (!isNomad())
136         {
137                 g_Map.log("Placing players");
138                 const [playerIDs, playerPosition] = createBases(
139                         ...playerPlacementRandom(
140                                 sortAllPlayers(),
141                                 [
142                                         avoidClasses(
143                                                 g_TileClasses.mountain, 5,
144                                                 g_TileClasses.highlands, 5,
145                                                 g_TileClasses.eden, 5),
146                                         stayClasses(g_TileClasses.land, defaultPlayerBaseRadius())
147                                 ]),
148                         true);
150                 g_Map.log("Flatten the initial CC area");
151                 for (const position of playerPosition)
152                         createArea(
153                                 new ClumpPlacer(diskArea(defaultPlayerBaseRadius() * 0.8), 0.95, 0.6, Infinity,
154                                         position),
155                                 new SmoothElevationPainter(ELEVATION_SET, g_Map.getHeight(position), 6));
156         }
158         g_Map.log("Render lowlands");
159         setBiomeLowlands();
160         addElements([
161                 {
162                         "func": addLayeredPatches,
163                         "avoid": [
164                                 g_TileClasses.dirt, 5,
165                                 g_TileClasses.forest, 2,
166                                 g_TileClasses.mountain, 2,
167                                 g_TileClasses.player, 12,
168                                 g_TileClasses.eden, 2,
169                                 g_TileClasses.highlands, 2
170                         ],
171                         "sizes": ["normal"],
172                         "mixes": ["normal"],
173                         "amounts": ["many"]
174                 },
175                 {
176                         "func": addDecoration,
177                         "avoid": [
178                                 g_TileClasses.forest, 2,
179                                 g_TileClasses.mountain, 2,
180                                 g_TileClasses.player, 12,
181                                 g_TileClasses.eden, 2,
182                                 g_TileClasses.highlands, 2
183                         ],
184                         "sizes": ["normal"],
185                         "mixes": ["normal"],
186                         "amounts": ["many"]
187                 }
188         ]);
190         addElements(shuffleArray([
191                 {
192                         "func": addSmallMetal,
193                         "avoid": [
194                                 g_TileClasses.berries, 5,
195                                 g_TileClasses.forest, 3,
196                                 g_TileClasses.mountain, 6,
197                                 g_TileClasses.player, 30,
198                                 g_TileClasses.rock, 20,
199                                 g_TileClasses.metal, 10,
200                                 g_TileClasses.eden, 2,
201                                 g_TileClasses.highlands, 2
203                         ],
204                         "sizes": ["normal"],
205                         "mixes": ["same"],
206                         "amounts": ["few"]
207                 },
208                 {
209                         "func": addStone,
210                         "avoid": [
211                                 g_TileClasses.berries, 5,
212                                 g_TileClasses.forest, 3,
213                                 g_TileClasses.mountain, 6,
214                                 g_TileClasses.player, 30,
215                                 g_TileClasses.rock, 20,
216                                 g_TileClasses.metal, 10,
217                                 g_TileClasses.eden, 2,
218                                 g_TileClasses.highlands, 2
219                         ],
220                         "sizes": ["normal"],
221                         "mixes": ["same"],
222                         "amounts": ["scarce"]
223                 },
224                 {
225                         "func": addForests,
226                         "avoid": [
227                                 g_TileClasses.berries, 5,
228                                 g_TileClasses.forest, 8,
229                                 g_TileClasses.metal, 3,
230                                 g_TileClasses.mountain, 6,
231                                 g_TileClasses.player, 20,
232                                 g_TileClasses.rock, 3,
233                                 g_TileClasses.eden, 2,
234                                 g_TileClasses.highlands, 2
235                         ],
236                         "sizes": ["normal"],
237                         "mixes": ["similar"],
238                         "amounts": ["normal"]
239                 }
240         ]));
242         addElements(shuffleArray([
243                 {
244                         "func": addAnimals,
245                         "avoid": [
246                                 g_TileClasses.animals, 20,
247                                 g_TileClasses.forest, 2,
248                                 g_TileClasses.metal, 2,
249                                 g_TileClasses.mountain, 6,
250                                 g_TileClasses.player, 20,
251                                 g_TileClasses.rock, 2,
252                                 g_TileClasses.eden, 2,
253                                 g_TileClasses.highlands, 2
254                         ],
255                         "sizes": ["big"],
256                         "mixes": ["similar"],
257                         "amounts": ["many"]
258                 },
259                 {
260                         "func": addAnimals,
261                         "avoid": [
262                                 g_TileClasses.animals, 20,
263                                 g_TileClasses.forest, 2,
264                                 g_TileClasses.metal, 2,
265                                 g_TileClasses.mountain, 6,
266                                 g_TileClasses.player, 20,
267                                 g_TileClasses.rock, 2,
268                                 g_TileClasses.eden, 2,
269                                 g_TileClasses.highlands, 2
270                         ],
271                         "sizes": ["normal"],
272                         "mixes": ["unique"],
273                         "amounts": ["many"]
274                 },
275                 {
276                         "func": addStragglerTrees,
277                         "avoid": [
278                                 g_TileClasses.berries, 5,
279                                 g_TileClasses.forest, 4,
280                                 g_TileClasses.metal, 2,
281                                 g_TileClasses.mountain, 6,
282                                 g_TileClasses.player, 12,
283                                 g_TileClasses.rock, 2,
284                                 g_TileClasses.eden, 2,
285                                 g_TileClasses.highlands, 2
286                         ],
287                         "sizes": ["big"],
288                         "mixes": ["same"],
289                         "amounts": ["many"]
290                 }
291         ]));
292         yield 60;
294         g_Map.log("Render highlands");
295         setBiomeHighlands();
296         addElements([
297                 {
298                         "func": addLayeredPatches,
299                         "avoid": [
300                                 g_TileClasses.forest, 2,
301                                 g_TileClasses.mountain, 2,
302                                 g_TileClasses.player, 12
303                         ],
304                         "stay": [g_TileClasses.highlands, 2],
305                         "sizes": ["normal"],
306                         "mixes": ["normal"],
307                         "amounts": ["many"]
308                 },
309                 {
310                         "func": addDecoration,
311                         "avoid": [
312                                 g_TileClasses.forest, 2,
313                                 g_TileClasses.mountain, 2,
314                                 g_TileClasses.player, 12
315                         ],
316                         "stay": [g_TileClasses.highlands, 2],
317                         "sizes": ["normal"],
318                         "mixes": ["normal"],
319                         "amounts": ["many"]
320                 }
321         ]);
323         addElements(shuffleArray([
324                 {
325                         "func": addSmallMetal,
326                         "avoid": [
327                                 g_TileClasses.berries, 5,
328                                 g_TileClasses.forest, 3,
329                                 g_TileClasses.mountain, 3,
330                                 g_TileClasses.player, 30,
331                                 g_TileClasses.rock, 10,
332                                 g_TileClasses.metal, 20
333                         ],
334                         "stay": [g_TileClasses.highlands, 2],
335                         "sizes": ["normal"],
336                         "mixes": ["same"],
337                         "amounts": ["many"]
338                 },
339                 {
340                         "func": addStone,
341                         "avoid": [
342                                 g_TileClasses.berries, 5,
343                                 g_TileClasses.forest, 3,
344                                 g_TileClasses.mountain, 3,
345                                 g_TileClasses.player, 30,
346                                 g_TileClasses.rock, 20,
347                                 g_TileClasses.metal, 10
348                         ],
349                         "stay": [g_TileClasses.highlands, 2],
350                         "sizes": ["normal"],
351                         "mixes": ["same"],
352                         "amounts": ["many"]
353                 },
354                 {
355                         "func": addForests,
356                         "avoid": [
357                                 g_TileClasses.berries, 5,
358                                 g_TileClasses.forest, 8,
359                                 g_TileClasses.metal, 3,
360                                 g_TileClasses.mountain, 3,
361                                 g_TileClasses.player, 20,
362                                 g_TileClasses.rock, 3
363                         ],
364                         "stay": [g_TileClasses.highlands, 2],
365                         "sizes": ["huge"],
366                         "mixes": ["similar"],
367                         "amounts": ["many"]
368                 }
369         ]));
371         addElements(shuffleArray([
372                 {
373                         "func": addAnimals,
374                         "avoid": [
375                                 g_TileClasses.animals, 20,
376                                 g_TileClasses.forest, 2,
377                                 g_TileClasses.metal, 2,
378                                 g_TileClasses.mountain, 3,
379                                 g_TileClasses.player, 20,
380                                 g_TileClasses.rock, 2
381                         ],
382                         "stay": [g_TileClasses.highlands, 2],
383                         "sizes": ["huge"],
384                         "mixes": ["same"],
385                         "amounts": ["many"]
386                 },
387                 {
388                         "func": addStragglerTrees,
389                         "avoid": [
390                                 g_TileClasses.berries, 5,
391                                 g_TileClasses.forest, 2,
392                                 g_TileClasses.metal, 2,
393                                 g_TileClasses.mountain, 3,
394                                 g_TileClasses.player, 12,
395                                 g_TileClasses.rock, 2
396                         ],
397                         "stay": [g_TileClasses.highlands, 2],
398                         "sizes": ["huge"],
399                         "mixes": ["same"],
400                         "amounts": ["many"]
401                 }
402         ]));
403         yield 70;
405         g_Map.log("Render eden");
406         setBiomeEden();
407         addElements([
408                 {
409                         "func": addLayeredPatches,
410                         "avoid": [
411                                 g_TileClasses.dirt, 5,
412                                 g_TileClasses.forest, 2,
413                                 g_TileClasses.mountain, 2,
414                                 g_TileClasses.player, 12
415                         ],
416                         "stay": [g_TileClasses.eden, 2],
417                         "sizes": ["normal"],
418                         "mixes": ["normal"],
419                         "amounts": ["many"]
420                 },
421                 {
422                         "func": addDecoration,
423                         "avoid": [
424                                 g_TileClasses.forest, 2,
425                                 g_TileClasses.mountain, 2,
426                                 g_TileClasses.player, 12
427                         ],
428                         "stay": [g_TileClasses.eden, 2],
429                         "sizes": ["normal"],
430                         "mixes": ["normal"],
431                         "amounts": ["many"]
432                 }
433         ]);
435         addElements(shuffleArray([
436                 {
437                         "func": addMetal,
438                         "avoid": [
439                                 g_TileClasses.berries, 5,
440                                 g_TileClasses.forest, 3,
441                                 g_TileClasses.mountain, 2,
442                                 g_TileClasses.player, 20,
443                                 g_TileClasses.rock, 3,
444                                 g_TileClasses.metal, 3
445                         ],
446                         "stay": [g_TileClasses.eden, 2],
447                         "sizes": ["normal"],
448                         "mixes": ["same"],
449                         "amounts": ["tons"]
450                 },
451                 {
452                         "func": addMetal,
453                         "avoid": [
454                                 g_TileClasses.berries, 5,
455                                 g_TileClasses.forest, 3,
456                                 g_TileClasses.mountain, 2,
457                                 g_TileClasses.player, 20,
458                                 g_TileClasses.rock, 3,
459                                 g_TileClasses.metal, 3
460                         ],
461                         "stay": [g_TileClasses.eden, 2],
462                         "sizes": ["normal"],
463                         "mixes": ["same"],
464                         "amounts": ["tons"]
465                 },
466                 {
467                         "func": addSmallMetal,
468                         "avoid": [
469                                 g_TileClasses.berries, 5,
470                                 g_TileClasses.forest, 3,
471                                 g_TileClasses.mountain, 2,
472                                 g_TileClasses.player, 20,
473                                 g_TileClasses.rock, 3,
474                                 g_TileClasses.metal, 3
475                         ],
476                         "stay": [g_TileClasses.eden, 2],
477                         "sizes": ["normal"],
478                         "mixes": ["same"],
479                         "amounts": ["tons"]
480                 },
481                 {
482                         "func": addStone,
483                         "avoid": [
484                                 g_TileClasses.berries, 5,
485                                 g_TileClasses.forest, 3,
486                                 g_TileClasses.mountain, 2,
487                                 g_TileClasses.player, 30,
488                                 g_TileClasses.rock, 3,
489                                 g_TileClasses.metal, 3
490                         ],
491                         "stay": [g_TileClasses.eden, 2],
492                         "sizes": ["normal"],
493                         "mixes": ["same"],
494                         "amounts": ["few"]
495                 },
496                 {
497                         "func": addForests,
498                         "avoid": [
499                                 g_TileClasses.berries, 5,
500                                 g_TileClasses.forest, 8,
501                                 g_TileClasses.metal, 3,
502                                 g_TileClasses.mountain, 8,
503                                 g_TileClasses.player, 20,
504                                 g_TileClasses.rock, 3
505                         ],
506                         "stay": [g_TileClasses.eden, 2],
507                         "sizes": ["huge"],
508                         "mixes": ["similar"],
509                         "amounts": ["scarce"]
510                 }
511         ]));
513         addElements(shuffleArray([
514                 {
515                         "func": addAnimals,
516                         "avoid": [
517                                 g_TileClasses.animals, 2,
518                                 g_TileClasses.forest, 2,
519                                 g_TileClasses.metal, 2,
520                                 g_TileClasses.mountain, 3,
521                                 g_TileClasses.player, 20,
522                                 g_TileClasses.rock, 2
523                         ],
524                         "stay": [g_TileClasses.eden, 2],
525                         "sizes": ["normal"],
526                         "mixes": ["same"],
527                         "amounts": ["many"]
528                 },
529                 {
530                         "func": addStragglerTrees,
531                         "avoid": [
532                                 g_TileClasses.berries, 5,
533                                 g_TileClasses.forest, 2,
534                                 g_TileClasses.metal, 2,
535                                 g_TileClasses.mountain, 8,
536                                 g_TileClasses.player, 12,
537                                 g_TileClasses.rock, 2
538                         ],
539                         "stay": [g_TileClasses.eden, 2],
540                         "sizes": ["huge"],
541                         "mixes": ["same"],
542                         "amounts": ["scarce"]
543                 }
544         ]));
545         yield 80;
547         placePlayersNomad(
548                 g_Map.createTileClass(),
549                 [
550                         stayClasses(g_TileClasses.land, 5),
551                         avoidClasses(
552                                 g_TileClasses.forest, 2,
553                                 g_TileClasses.rock, 4,
554                                 g_TileClasses.metal, 4,
555                                 g_TileClasses.berries, 2,
556                                 g_TileClasses.animals, 2,
557                                 g_TileClasses.mountain, 2)
558                 ]);
560         setAmbientColor(0.521, 0.475, 0.322);
562         setSunColor(0.733, 0.746, 0.574);
563         setSunRotation(Math.PI);
564         setSunElevation(1/2);
566         setFogFactor(0);
567         setFogThickness(0);
568         setFogColor(0.69, 0.616, 0.541);
570         setPPEffect("hdr");
571         setPPContrast(0.67);
572         setPPSaturation(0.42);
573         setPPBloom(0.23);
575         return g_Map;