Move getMapCenter and getMapBounds to the RandomMap object, refs #4964.
[0ad.git] / binaries / data / mods / public / maps / random / island_stronghold.js
blobe831d0db6b93496ef4dfb787b1ab40a29bf790ad
1 Engine.LoadLibrary("rmgen");
2 Engine.LoadLibrary("rmgen2");
3 Engine.LoadLibrary("rmbiome");
4 Engine.LoadLibrary("heightmap");
6 const g_InitialMineDistance = 14;
7 const g_InitialTrees = 50;
9 setSelectedBiome();
11 const tMainTerrain = g_Terrains.mainTerrain;
12 const tForestFloor1 = g_Terrains.forestFloor1;
13 const tForestFloor2 = g_Terrains.forestFloor2;
14 const tCliff = g_Terrains.cliff;
15 const tTier1Terrain = g_Terrains.tier1Terrain;
16 const tTier2Terrain = g_Terrains.tier2Terrain;
17 const tTier3Terrain = g_Terrains.tier3Terrain;
18 const tHill = g_Terrains.hill;
19 const tTier4Terrain = g_Terrains.tier4Terrain;
20 const tShore = g_Terrains.shore;
21 const tWater = g_Terrains.water;
23 const oTree1 = g_Gaia.tree1;
24 const oTree2 = g_Gaia.tree2;
25 const oTree3 = g_Gaia.tree3;
26 const oTree4 = g_Gaia.tree4;
27 const oTree5 = g_Gaia.tree5;
28 const oFruitBush = g_Gaia.fruitBush;
29 const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal;
30 const oFish = g_Gaia.fish;
31 const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal;
32 const oStoneLarge = g_Gaia.stoneLarge;
33 const oStoneSmall = g_Gaia.stoneSmall;
34 const oMetalLarge = g_Gaia.metalLarge;
35 const oWhale = "gaia/fauna_whale_humpback";
36 const oShipwreck = "other/special_treasure_shipwreck";
37 const oShipDebris = "other/special_treasure_shipwreck_debris";
38 const oObelisk = "other/obelisk";
40 const aGrass = g_Decoratives.grass;
41 const aGrassShort = g_Decoratives.grassShort;
42 const aRockLarge = g_Decoratives.rockLarge;
43 const aRockMedium = g_Decoratives.rockMedium;
45 const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2];
46 const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1];
48 const heightSeaGround = -10;
49 const heightLand = 3;
50 const heightHill = 18;
52 var g_Map = new RandomMap(heightSeaGround, tWater);
54 const numPlayers = getNumPlayers();
55 const mapSize = getMapSize();
56 const mapCenter = g_Map.getCenter();
58 const clPlayer = createTileClass();
59 const clHill = createTileClass();
60 const clForest = createTileClass();
61 const clDirt = createTileClass();
62 const clRock = createTileClass();
63 const clMetal = createTileClass();
64 const clFood = createTileClass();
65 const clBaseResource = createTileClass();
66 const clLand = createTileClass();
68 var startAngle = randomAngle();
70 var teams = getTeamsArray();
71 var numTeams = teams.filter(team => team).length;
72 var teamPosition = distributePointsOnCircle(numTeams, startAngle, fractionToTiles(0.3), mapCenter)[0];
73 var teamRadius = fractionToTiles(0.05);
75 var teamNo = 0;
76 for (let i = 0; i < teams.length; ++i)
78         if (!teams[i] || isNomad())
79                 continue;
81         ++teamNo;
83         let [playerPosition, playerAngle] = distributePointsOnCircle(teams[i].length, startAngle + 2 * Math.PI / teams[i].length, teamRadius, teamPosition[i]);
84         playerPosition.forEach(position => position.round());
86         log("Creating island and starting entities for team " + i);
87         for (let p = 0; p < teams[i].length; ++p)
88         {
89                 addCivicCenterAreaToClass(playerPosition[p], clPlayer);
91                 createArea(
92                         new ChainPlacer(2, Math.floor(scaleByMapSize(5, 11)), Math.floor(scaleByMapSize(60, 250)), 1, playerPosition[p], 0, [Math.floor(fractionToTiles(0.01))]),
93                         [
94                                 new LayeredPainter([tMainTerrain, tMainTerrain, tMainTerrain], [1, 6]),
95                                 new SmoothElevationPainter(ELEVATION_SET, heightLand, 6),
96                                 paintClass(clLand)
97                         ]);
99                 placeCivDefaultStartingEntities(playerPosition[p], teams[i][p], false);
100         }
102         let mineAngle = randFloat(-1, 1) * Math.PI / teams[i].length;
103         let mines = [
104                 { "template": oMetalLarge, "angle": mineAngle },
105                 { "template": oStoneLarge, "angle": mineAngle + Math.PI / 4 }
106         ];
108         log("Create starting resources for team " + i);
109         for (let p = 0; p < teams[i].length; ++p)
110                 for (let mine of mines)
111                 {
112                         let position = Vector2D.add(playerPosition[p], new Vector2D(g_InitialMineDistance, 0).rotate(-playerAngle[p] - mine.angle));
113                         createObjectGroup(
114                                 new SimpleGroup([new SimpleObject(mine.template, 1, 1, 0, 4)], true, clBaseResource, position.x, position.y),
115                                 0,
116                                 [avoidClasses(clBaseResource, 4, clPlayer, 4), stayClasses(clLand, 5)]);
117                 }
119         log("Place initial trees for team " + i);
120         for (let p = 0; p < teams[i].length; ++p)
121         {
122                 let tries = 10;
123                 for (let x = 0; x < tries; ++x)
124                 {
125                         let tAngle = playerAngle[p] + randFloat(-1, 1) * 2 * Math.PI / teams[i].length;
126                         let treePosition = Vector2D.add(playerPosition[p], new Vector2D(16, 0).rotate(-tAngle)).round();
127                         let group = new SimpleGroup(
128                                 [new SimpleObject(oTree2, g_InitialTrees, g_InitialTrees, 0, 7)],
129                                 true, clBaseResource, treePosition.x, treePosition.y
130                         );
131                         if (createObjectGroup(group, 0, [avoidClasses(clBaseResource, 4, clPlayer, 4), stayClasses(clLand, 4)]))
132                                 break;
133                 }
134         }
136         for (let p = 0; p < teams[i].length; ++p)
137                 placePlayerBaseBerries({
138                         "template": oFruitBush,
139                         "playerID": teams[i][p],
140                         "playerPosition": playerPosition[p],
141                         "BaseResourceClass": clBaseResource,
142                         "baseResourceConstraint": new AndConstraint([avoidClasses(clPlayer, 4), stayClasses(clLand, 5)])
143                 });
145         for (let p = 0; p < teams[i].length; ++p)
146                 placePlayerBaseChicken({
147                         "playerID": teams[i][p],
148                         "playerPosition": playerPosition[p],
149                         "BaseResourceClass": clBaseResource,
150                         "baseResourceConstraint": new AndConstraint([avoidClasses(clPlayer, 4), stayClasses(clLand, 5)])
151                 });
153         log("Creating huntable animals for team " + i + "...");
154         for (let p = 0; p < teams[i].length; ++p)
155         {
156                 let group = new SimpleGroup(
157                         [new SimpleObject(oMainHuntableAnimal, 2 * numPlayers / numTeams, 2 * numPlayers / numTeams, 0, Math.floor(fractionToTiles(0.2)))],
158                         true, clBaseResource, teamPosition[i].x, teamPosition[i].y
159                 );
160                 createObjectGroup(group, 0, [avoidClasses(clBaseResource, 2, clPlayer, 10), stayClasses(clLand, 5)]);
162                 group = new SimpleGroup(
163                         [new SimpleObject(oSecondaryHuntableAnimal, 4 * numPlayers / numTeams, 4 * numPlayers / numTeams, 0, Math.floor(fractionToTiles(0.2)))],
164                         true, clBaseResource, teamPosition[i].x, teamPosition[i].y
165                 );
166                 createObjectGroup(group, 0, [avoidClasses(clBaseResource, 2, clPlayer, 10), stayClasses(clLand, 5)]);
167         }
170 Engine.SetProgress(40);
172 log("Creating big islands...");
173 createAreas(
174         new ChainPlacer(
175                 Math.floor(scaleByMapSize(4, 8) * (isNomad() ? 2 : 1)),
176                 Math.floor(scaleByMapSize(8, 16) * (isNomad() ? 2 : 1)),
177                 Math.floor(scaleByMapSize(25, 60)),
178                 0.07,
179                 undefined,
180                 scaleByMapSize(30, 70)),
181         [
182                 new LayeredPainter([tMainTerrain, tMainTerrain], [2]),
183                 new SmoothElevationPainter(ELEVATION_SET, heightLand, 6),
184                 paintClass(clLand)
185         ],
186         avoidClasses(clLand, 3, clPlayer, 3),
187         scaleByMapSize(4, 14) * (isNomad() ? 2 : 1),
188         1);
190 log("Creating small islands...");
191 createAreas(
192         new ChainPlacer(Math.floor(scaleByMapSize(4, 7)), Math.floor(scaleByMapSize(7, 10)), Math.floor(scaleByMapSize(16, 40)), 0.07, undefined, scaleByMapSize(22, 40)),
193         [
194                 new LayeredPainter([tMainTerrain, tMainTerrain], [2]),
195                 new SmoothElevationPainter(ELEVATION_SET, heightLand, 6),
196                 paintClass(clLand)
197         ],
198         avoidClasses(clLand, 3, clPlayer, 3),
199         scaleByMapSize(6, 55),
200         1);
202 Engine.SetProgress(70);
204 log("Smoothing heightmap...");
205 for (let i = 0; i < 5; ++i)
206         globalSmoothHeightmap();
208 // repaint clLand to compensate for smoothing
209 unPaintTileClassBasedOnHeight(-10, 10, 3, clLand);
210 paintTileClassBasedOnHeight(0, 5, 3, clLand);
212 Engine.SetProgress(85);
214 createBumps(avoidClasses(clPlayer, 20));
216 createMines(
218         [new SimpleObject(oMetalLarge, 1, 1, 3, (numPlayers * 2) + 1)]
220 [avoidClasses(clForest, 1, clPlayer, 40, clRock, 20), stayClasses(clLand, 4)],
221 clMetal
224 createMines(
226         [new SimpleObject(oStoneLarge, 1, 1, 3, (numPlayers * 2) + 1)], [new SimpleObject(oStoneSmall, 2, 2, 2, (numPlayers * 2) + 1)]
228 [avoidClasses(clForest, 1, clPlayer, 40, clMetal, 20), stayClasses(clLand, 4)],
229 clRock
232 var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(1));
233 createForests(
234  [tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2],
235  [avoidClasses(clPlayer, 10, clForest, 20, clBaseResource, 5, clRock, 6, clMetal, 6), stayClasses(clLand, 3)],
236  clForest,
237  forestTrees);
239 log("Creating hills...");
240 createAreas(
241         new ChainPlacer(1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(16, 40)), 0.5),
242         [
243                 new LayeredPainter([tCliff, tHill], [2]),
244                 new SmoothElevationPainter(ELEVATION_SET, heightHill, 2),
245                 paintClass(clHill)
246         ],
247         [avoidClasses(clBaseResource, 20, clHill, 15, clRock, 6, clMetal, 6), stayClasses(clLand, 0)],
248         scaleByMapSize(4, 13)
251 for (let i = 0; i < 3; ++i)
252         globalSmoothHeightmap();
254 createStragglerTrees(
255         [oTree1, oTree2, oTree4, oTree3],
256         [
257                 avoidClasses(clForest, 10, clPlayer, 20, clMetal, 6, clRock, 6, clHill, 1),
258                 stayClasses(clLand, 4)
259         ],
260         clForest,
261         stragglerTrees);
263 createFood(
264         [
265                 [new SimpleObject(oMainHuntableAnimal, 5, 7, 0, 4)],
266                 [new SimpleObject(oSecondaryHuntableAnimal, 2, 3, 0, 2)]
267         ],
268         [3 * numPlayers, 3 * numPlayers],
269         [avoidClasses(clForest, 0, clPlayer, 20, clHill, 1, clRock, 6, clMetal, 6), stayClasses(clLand, 2)],
270         clFood);
272 createFood(
273         [
274                 [new SimpleObject(oFruitBush, 5, 7, 0, 4)]
275         ],
276         [3 * numPlayers],
277         [avoidClasses(clForest, 0, clPlayer, 15, clHill, 1, clFood, 4, clRock, 6, clMetal, 6), stayClasses(clLand, 2)],
278         clFood);
280 if (currentBiome() == "desert")
282         log("Creating obelisks");
283         let group = new SimpleGroup(
284                 [new SimpleObject(oObelisk, 1, 1, 0, 1)],
285                 true
286         );
287         createObjectGroupsDeprecated(
288                 group, 0,
289                 [avoidClasses(clBaseResource, 0, clHill, 0, clRock, 0, clMetal, 0, clFood, 0), stayClasses(clLand, 1)],
290                 scaleByMapSize(3, 8), 1000
291         );
294 log("Creating dirt patches...");
295 let numb = currentBiome() == "savanna" ? 3 : 1;
296 for (let size of [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)])
297         createAreas(
298                 new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5),
299                 [
300                         new LayeredPainter([[tMainTerrain, tTier1Terrain], [tTier1Terrain, tTier2Terrain], [tTier2Terrain, tTier3Terrain]], [1, 1]),
301                         paintClass(clDirt)
302                 ],
303                 [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 0), stayClasses(clLand, 4)],
304                 numb*scaleByMapSize(15, 45));
306 log("Creating grass patches...");
307 for (let size of [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)])
308         createAreas(
309                 new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5),
310                 new TerrainPainter(tTier4Terrain),
311                 [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 0), stayClasses(clLand, 4)],
312                 numb * scaleByMapSize(15, 45));
314 log("Creating small decorative rocks...");
315 let group = new SimpleGroup(
316         [new SimpleObject(aRockMedium, 1, 3, 0, 1)],
317         true
319 createObjectGroupsDeprecated(
320         group, 0,
321         [avoidClasses(clForest, 0, clHill, 0), stayClasses(clLand, 2)],
322         scaleByMapSize(16, 262), 50
325 log("Creating large decorative rocks...");
326 group = new SimpleGroup(
327         [new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)],
328         true
330 createObjectGroupsDeprecated(
331         group, 0,
332         [avoidClasses(clForest, 0, clHill, 0), stayClasses(clLand, 2)],
333         scaleByMapSize(8, 131), 50
336 log("Creating fish...");
337 group = new SimpleGroup(
338         [new SimpleObject(oFish, 2, 3, 0, 2)],
339         true, clFood
341 createObjectGroupsDeprecated(group, 0,
342         avoidClasses(clLand, 4, clFood, 20),
343         25 * numPlayers, 60
346 log("Creating Whales...");
347 group = new SimpleGroup(
348         [new SimpleObject(oWhale, 1, 1, 0, 3)],
349         true, clFood
351 createObjectGroupsDeprecated(group, 0,
352         [avoidClasses(clLand, 4),avoidClasses(clFood, 8)],
353         scaleByMapSize(5, 20), 100
356 log("Creating shipwrecks...");
357 group = new SimpleGroup(
358         [new SimpleObject(oShipwreck, 1, 1, 0, 1)],
359         true, clFood
361 createObjectGroupsDeprecated(group, 0,
362         [avoidClasses(clLand, 4),avoidClasses(clFood, 8)],
363         scaleByMapSize(12, 16), 100
366 log("Creating shipwreck debris...");
367 group = new SimpleGroup(
368         [new SimpleObject(oShipDebris, 1, 1, 0, 1)],
369         true, clFood
371 createObjectGroupsDeprecated(group, 0,
372         [avoidClasses(clLand, 4),avoidClasses(clFood, 8)],
373         scaleByMapSize(10, 20), 100
376 log("Creating small grass tufts...");
377 let planetm = currentBiome() == "tropic" ? 8 : 1;
378 group = new SimpleGroup(
379         [new SimpleObject(aGrassShort, 1, 2, 0, 1, -Math.PI / 8, Math.PI / 8)]
381 createObjectGroupsDeprecated(group, 0,
382         [avoidClasses(clHill, 2, clPlayer, 2, clDirt, 0), stayClasses(clLand, 3)],
383         planetm * scaleByMapSize(13, 200)
386 Engine.SetProgress(95);
388 log("Creating large grass tufts...");
389 group = new SimpleGroup(
390         [new SimpleObject(aGrass, 2, 4, 0, 1.8, -Math.PI / 8, Math.PI / 8), new SimpleObject(aGrassShort, 3, 6, 1.2,2.5, -Math.PI / 8, Math.PI / 8)]
392 createObjectGroupsDeprecated(group, 0,
393         [avoidClasses(clHill, 2, clPlayer, 2, clDirt, 1, clForest, 0), stayClasses(clLand, 5)],
394         planetm * scaleByMapSize(13, 200)
397 paintTerrainBasedOnHeight(1, 2, 0, tShore);
398 paintTerrainBasedOnHeight(heightSeaGround, 1, 3, tWater);
400 placePlayersNomad(clPlayer, [stayClasses(clLand, 4), avoidClasses(clHill, 2, clForest, 1, clMetal, 4, clRock, 4, clFood, 2)]);
402 setSkySet(pickRandom(["cloudless", "cumulus", "overcast"]));
403 setSunRotation(randomAngle());
404 setSunElevation(randFloat(1/5, 1/3) * Math.PI);
405 setWaterWaviness(2);
407 Engine.SetProgress(100);
409 g_Map.ExportMap();