1 RMS.LoadLibrary("rmgen");
3 let random_terrain = randomizeBiome([g_BiomeSavanna]);
5 const tMainTerrain = rBiomeT1();
6 const tForestFloor1 = rBiomeT2();
7 const tForestFloor2 = rBiomeT3();
8 const tCliff = rBiomeT4();
9 const tTier1Terrain = rBiomeT5();
10 const tTier2Terrain = rBiomeT6();
11 const tTier3Terrain = rBiomeT7();
12 const tRoad = rBiomeT10();
13 const tRoadWild = rBiomeT11();
14 const tTier4Terrain = rBiomeT12();
15 const tShore = rBiomeT14();
16 const tWater = rBiomeT15();
17 let tHill = rBiomeT8();
18 let tDirt = rBiomeT9();
20 if (random_terrain == g_BiomeTemperate)
22 tDirt = ["medit_shrubs_a", "grass_field"];
23 tHill = ["grass_field", "peat_temp"];
27 const oTree1 = rBiomeE1();
28 const oTree2 = rBiomeE2();
29 const oTree3 = rBiomeE3();
30 const oTree4 = rBiomeE4();
31 const oTree5 = rBiomeE5();
32 const oFruitBush = rBiomeE6();
33 const oMainHuntableAnimal = rBiomeE8();
34 const oFish = rBiomeE9();
35 const oSecondaryHuntableAnimal = rBiomeE10();
36 const oStoneLarge = rBiomeE11();
37 const oMetalLarge = rBiomeE13();
40 const aGrass = rBiomeA1();
41 const aGrassShort = rBiomeA2();
42 const aRockLarge = rBiomeA5();
43 const aRockMedium = rBiomeA6();
44 const aBushMedium = rBiomeA7();
45 const aBushSmall = rBiomeA8();
47 const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2];
48 const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1];
50 log("Initializing map...");
53 const radius = scaleByMapSize(15, 25);
55 const shoreRadius = 6;
56 const numPlayers = getNumPlayers();
57 const mapSize = getMapSize();
58 const mapArea = mapSize * mapSize;
59 const centerOfMap = mapSize / 2;
61 // Create tile classes
62 let clPlayer = createTileClass();
63 let clHill = createTileClass();
64 let clMountain = createTileClass();
65 let clForest = createTileClass();
66 let clWater = createTileClass();
67 let clDirt = createTileClass();
68 let clRock = createTileClass();
69 let clMetal = createTileClass();
70 let clFood = createTileClass();
71 let clBaseResource = createTileClass();
73 for (let ix = 0; ix < mapSize; ++ix)
74 for (let iz = 0; iz < mapSize; ++iz)
75 placeTerrain(ix, iz, tWater);
77 // Randomize player order
79 for (let i = 0; i < numPlayers; ++i)
81 playerIDs = sortPlayers(playerIDs);
88 let startAngle = randFloat(0, TWO_PI);
89 for (let i = 0; i < numPlayers; ++i)
91 playerAngle[i] = startAngle + i * TWO_PI/numPlayers;
92 playerX[i] = 0.5 + 0.38 * cos(playerAngle[i]);
93 playerZ[i] = 0.5 + 0.38 * sin(playerAngle[i]);
96 let fx = fractionToTiles(0.5);
97 let fz = fractionToTiles(0.5);
102 let placer = new ClumpPlacer(mapArea * 1, 1, 1, 1, ix, iz);
103 let terrainPainter = new LayeredPainter(
104 [tWater, tWater, tShore], // terrains
107 let elevationPainter = new SmoothElevationPainter(
108 ELEVATION_SET, // type
109 getMapBaseHeight(), // elevation
112 createArea(placer, [terrainPainter, elevationPainter, paintClass(clWater)], avoidClasses(clPlayer, 5));
114 for (let i = 0; i < numPlayers; ++i)
116 let id = playerIDs[i];
117 log("Creating base for player " + id + "...");
119 // Get the x and z in tiles
120 let fx = fractionToTiles(playerX[i]);
121 let fz = fractionToTiles(playerZ[i]);
125 let hillSize = PI * radius * radius * 2;
128 let placer = new ClumpPlacer(hillSize, 0.80, 0.1, 10, ix, iz);
129 let terrainPainter = new LayeredPainter(
130 [tShore, tMainTerrain], // terrains
131 [shoreRadius] // widths
133 let elevationPainter = new SmoothElevationPainter(
134 ELEVATION_SET, // type
135 elevation, // elevation
136 shoreRadius // blend radius
138 createArea(placer, [terrainPainter, elevationPainter, paintClass(clHill)], null);
140 // Mark a small area around the player's starting coördinates with the clPlayer class
141 addToClass(ix, iz, clPlayer);
142 addToClass(ix + 5, iz, clPlayer);
143 addToClass(ix, iz + 5, clPlayer);
144 addToClass(ix - 5, iz, clPlayer);
145 addToClass(ix, iz - 5, clPlayer);
147 placeCivDefaultEntities(fx, fz, id, { "iberWall": false });
149 // Create the city patch
150 let cityRadius = radius/3;
151 placer = new ClumpPlacer(PI * cityRadius * cityRadius, 0.6, 0.3, 10, ix, iz);
152 let painter = new LayeredPainter([tRoadWild, tRoad], [1]);
153 createArea(placer, painter, null);
155 placeDefaultChicken(fx, fz, clBaseResource);
157 // Create berry bushes
158 let bbAngle = randFloat(0, TWO_PI);
160 let bbX = round(fx + bbDist * cos(bbAngle));
161 let bbZ = round(fz + bbDist * sin(bbAngle));
162 let group = new SimpleGroup(
163 [new SimpleObject(oFruitBush, 5, 5, 0, 3)],
164 true, clBaseResource, bbX, bbZ
166 createObjectGroup(group, 0);
169 let mAngle = bbAngle;
170 while (abs(mAngle - bbAngle) < PI/3)
171 mAngle = randFloat(0, TWO_PI);
174 let mX = round(fx + mDist * cos(mAngle));
175 let mZ = round(fz + mDist * sin(mAngle));
176 group = new SimpleGroup(
177 [new SimpleObject(oMetalLarge, 1, 1, 0, 0)],
178 true, clBaseResource, mX, mZ
180 createObjectGroup(group, 0);
182 // Create stone mines
183 mAngle += randFloat(PI/8, PI/4);
184 mX = round(fx + mDist * cos(mAngle));
185 mZ = round(fz + mDist * sin(mAngle));
186 group = new SimpleGroup(
187 [new SimpleObject(oStoneLarge, 1, 1, 0, 2)],
188 true, clBaseResource, mX, mZ
190 createObjectGroup(group, 0);
192 // Create starting trees, should avoid mines and bushes
196 for (let x = 0; x < tries; ++x)
198 let tAngle = randFloat(0, TWO_PI);
199 let tX = round(fx + tDist * cos(tAngle));
200 let tZ = round(fz + tDist * sin(tAngle));
201 group = new SimpleGroup(
202 [new SimpleObject(oTree2, num, num, 0, 7)],
203 true, clBaseResource, tX, tZ
205 if (createObjectGroup(group, 0, avoidClasses(clBaseResource, 5)))
209 // Create grass tufts
210 num = (PI * radius * radius) / 250;
211 for (let j = 0; j < num; ++j)
213 let gAngle = randFloat(0, TWO_PI);
214 let gDist = radius - (5 + randInt(7));
215 let gX = round(fx + gDist * cos(gAngle));
216 let gZ = round(fz + gDist * sin(gAngle));
217 group = new SimpleGroup(
218 [new SimpleObject(aGrassShort, 2, 5, 0, 1, -PI/8, PI/8)],
219 false, clBaseResource, gX, gZ
221 createObjectGroup(group, 0);
227 // Create central island
228 placer = new ChainPlacer(floor(scaleByMapSize(6, 6)), floor(scaleByMapSize(10, 15)), floor(scaleByMapSize(200, 300)), 1, centerOfMap, centerOfMap, 0, [floor(mapSize * 0.01)]);
229 terrainPainter = new LayeredPainter(
230 [tShore, tMainTerrain], // terrains
231 [shoreRadius, 100] // widths
233 elevationPainter = new SmoothElevationPainter(
234 ELEVATION_SET, // type
235 elevation, // elevation
236 shoreRadius // blend radius
238 createArea(placer, [terrainPainter, elevationPainter, paintClass(clHill)], avoidClasses(clPlayer, 40));
240 let randMountains = 20 + randInt(15);
241 for (let m = 0; m < randMountains; ++m)
243 let randX = randInt(mapSize);
244 let randY = randInt(mapSize);
245 let placer = new ChainPlacer(floor(scaleByMapSize(7, 7)), floor(scaleByMapSize(15, 15)), floor(scaleByMapSize(15, 20)), 1, randX, randY, 0, [floor(mapSize * 0.01)]);
246 let elevRand = 6 + randInt(15);
247 let terrainPainter = new LayeredPainter(
248 [tDirt, tHill], // terrains
249 [floor(elevRand / 3), 40] // widths
251 let elevationPainter = new SmoothElevationPainter(
252 ELEVATION_SET, // type
253 elevRand, // elevation
254 floor(elevRand / 3) // blend radius
256 createArea(placer, [terrainPainter, elevationPainter, paintClass(clHill)], [avoidClasses(clBaseResource, 2, clPlayer, 40), stayClasses(clHill, 6)]);
259 randMountains = 8 + randInt(10);
260 for (let m = 0; m < randMountains; ++m)
262 let randX = randInt(mapSize);
263 let randY = randInt(mapSize);
264 let placer = new ChainPlacer(floor(scaleByMapSize(5, 5)), floor(scaleByMapSize(8, 8)), floor(scaleByMapSize(15, 20)), 1, randX, randY, 0, [floor(mapSize * 0.01)]);
265 let elevRand = 15 + randInt(15);
266 let terrainPainter = new LayeredPainter(
267 [tCliff, tForestFloor2], // terrains
268 [floor(elevRand / 3), 40] // widths
270 let elevationPainter = new SmoothElevationPainter(
271 ELEVATION_MODIFY, // type
272 elevRand, // elevation
273 floor(elevRand / 3) // blend radius
275 createArea(placer, [terrainPainter, elevationPainter, paintClass(clMountain)], [avoidClasses(clBaseResource, 2, clPlayer, 40), stayClasses(clHill, 6)]);
278 // Create center bounty
279 let group = new SimpleGroup(
280 [new SimpleObject(oMetalLarge, 3, 6, 25, floor(mapSize * 0.25))],
281 true, clBaseResource, centerOfMap, centerOfMap
283 createObjectGroup(group, 0, [avoidClasses(clBaseResource, 20, clPlayer, 40, clMountain, 4), stayClasses(clHill, 10)]);
284 group = new SimpleGroup(
285 [new SimpleObject(oStoneLarge, 3, 6, 25, floor(mapSize * 0.25))],
286 true, clBaseResource, centerOfMap, centerOfMap
288 createObjectGroup(group, 0, [avoidClasses(clBaseResource, 20, clPlayer, 40, clMountain, 4), stayClasses(clHill, 10)]);
289 group = new SimpleGroup(
290 [new SimpleObject(oMainHuntableAnimal, floor(6 * numPlayers), floor(6 * numPlayers), 2, floor(mapSize * 0.1))],
291 true, clBaseResource, centerOfMap, centerOfMap
293 createObjectGroup(group, 0, [avoidClasses(clBaseResource, 2, clMountain, 4, clPlayer, 40, clWater, 2), stayClasses(clHill, 10)]);
295 log("Creating fish...");
296 group = new SimpleGroup(
297 [new SimpleObject(oFish, 2, 3, 0, 2)],
300 createObjectGroups(group, 0,
301 avoidClasses(clHill, 10, clFood, 20),
306 [tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2],
307 [avoidClasses(clPlayer, 25, clForest, 10, clBaseResource, 3, clMetal, 3, clRock, 3, clMountain, 2), stayClasses(clHill, 6)],
313 log("Creating straggeler trees...");
314 let types = [oTree1, oTree2, oTree4, oTree3];
315 createStragglerTrees(types, [avoidClasses(clBaseResource, 2, clMetal, 3, clRock, 3, clMountain, 2, clPlayer, 25), stayClasses(clHill, 6)]);
319 log("Creating dirt patches...");
320 let sizes = [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)];
321 let numb = random_terrain == g_BiomeSavanna ? 3 : 1;
323 for (let i = 0; i < sizes.length; ++i)
325 placer = new ChainPlacer(1, floor(scaleByMapSize(3, 5)), sizes[i], 0.5);
326 let painter = new LayeredPainter(
327 [[tMainTerrain, tTier1Terrain], [tTier1Terrain, tTier2Terrain], [tTier2Terrain, tTier3Terrain]], // terrains
332 [painter, paintClass(clDirt)],
333 avoidClasses(clForest, 0, clMountain, 0, clDirt, 5, clPlayer, 10),
334 numb * scaleByMapSize(15, 45)
338 log("Painting shorelines...");
339 paintTerrainBasedOnHeight(1, 2, 0, tMainTerrain);
340 paintTerrainBasedOnHeight(getMapBaseHeight(), 1, 3, tTier1Terrain);
342 log("Creating grass patches...");
343 sizes = [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)];
344 for (let i = 0; i < sizes.length; ++i)
346 placer = new ChainPlacer(1, floor(scaleByMapSize(3, 5)), sizes[i], 0.5);
347 let painter = new TerrainPainter(tTier4Terrain);
351 avoidClasses(clForest, 0, clMountain, 0, clDirt, 5, clPlayer, 10),
352 numb * scaleByMapSize(15, 45)
356 log("Creating food...");
359 [new SimpleObject(oMainHuntableAnimal, 5, 7, 0, 4)],
360 [new SimpleObject(oSecondaryHuntableAnimal, 2, 3, 0, 2)]
362 [3 * numPlayers, 3 * numPlayers],
363 [avoidClasses(clForest, 0, clPlayer, 20, clMountain, 1, clFood, 4, clRock, 4, clMetal, 4), stayClasses(clHill, 2)]
370 [new SimpleObject(oFruitBush, 5, 7, 0, 4)]
373 [avoidClasses(clForest, 0, clPlayer, 15, clMountain, 1, clFood, 4, clRock, 4, clMetal, 4), stayClasses(clHill, 2)]
378 log("Creating more straggeler trees...");
379 createStragglerTrees(types, avoidClasses(clWater, 5, clForest, 7, clMountain, 1, clPlayer, 30, clMetal, 3, clRock, 3));
381 log("Creating decoration...");
382 let planetm = random_terrain == g_BiomeTropic ? 8 : 1;
386 [new SimpleObject(aRockMedium, 1, 3, 0, 1)],
387 [new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)],
388 [new SimpleObject(aGrassShort, 2, 15, 0, 1, -PI/8, PI/8)],
389 [new SimpleObject(aGrass, 2, 10, 0, 1.8, -PI/8, PI/8), new SimpleObject(aGrassShort, 3, 10, 1.2, 2.5, -PI/8, PI/8)],
390 [new SimpleObject(aBushMedium, 1, 5, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)]
393 scaleByMapSize(16, 262),
394 scaleByMapSize(8, 131),
395 planetm * scaleByMapSize(13, 200),
396 planetm * scaleByMapSize(13, 200),
397 planetm * scaleByMapSize(13, 200)
399 avoidClasses(clForest, 2, clPlayer, 20, clMountain, 5, clFood, 1, clBaseResource, 2)
402 log("Creating water forests...");
404 [tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2],
405 avoidClasses(clPlayer, 30, clHill, 10, clFood, 5),
411 log("Creating grass tufts...");
412 let num = (PI * radius * radius) / 250;
413 for (let j = 0; j < num; ++j)
415 let gAngle = randFloat(0, TWO_PI);
416 let gDist = radius - (5 + randInt(7));
417 let gX = round(fx + gDist * cos(gAngle));
418 let gZ = round(fz + gDist * sin(gAngle));
419 group = new SimpleGroup(
420 [new SimpleObject(aGrassShort, 2, 5, 0, 1, -PI / 8, PI / 8)],
421 false, clBaseResource, gX, gZ
423 createObjectGroup(group, 0, [avoidClasses(clMountain, 2, clPlayer, 2, clDirt, 0), stayClasses(clHill, 8)]);
426 log("Creating small grass tufts...");
427 group = new SimpleGroup(
428 [new SimpleObject(aGrassShort, 1, 2, 0, 1, -PI / 8, PI / 8)]
430 createObjectGroups(group, 0,
431 [avoidClasses(clMountain, 2, clPlayer, 2, clDirt, 0), stayClasses(clHill, 8)],
432 planetm * scaleByMapSize(13, 200)
435 setSkySet(shuffleArray(["cloudless", "cumulus", "overcast"])[0]);
436 setWaterMurkiness(0.4);