1 RMS.LoadLibrary("rmgen");
2 RMS.LoadLibrary("rmbiome");
6 const tMainTerrain = g_Terrains.mainTerrain;
7 const tForestFloor1 = g_Terrains.forestFloor1;
8 const tForestFloor2 = g_Terrains.forestFloor2;
9 const tCliff = g_Terrains.cliff;
10 const tTier1Terrain = g_Terrains.tier1Terrain;
11 const tTier2Terrain = g_Terrains.tier2Terrain;
12 const tTier3Terrain = g_Terrains.tier3Terrain;
13 const tHill = g_Terrains.mainTerrain;
14 const tRoad = g_Terrains.road;
15 const tRoadWild = g_Terrains.roadWild;
16 const tTier4Terrain = g_Terrains.tier4Terrain;
17 const tWater = g_Terrains.water;
19 const oTree1 = g_Gaia.tree1;
20 const oTree2 = g_Gaia.tree2;
21 const oTree3 = g_Gaia.tree3;
22 const oTree4 = g_Gaia.tree4;
23 const oTree5 = g_Gaia.tree5;
24 const oFruitBush = g_Gaia.fruitBush;
25 const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal;
26 const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal;
27 const oStoneLarge = g_Gaia.stoneLarge;
28 const oStoneSmall = g_Gaia.stoneSmall;
29 const oMetalLarge = g_Gaia.metalLarge;
31 const aGrass = g_Decoratives.grass;
32 const aGrassShort = g_Decoratives.grassShort;
33 const aRockLarge = g_Decoratives.rockLarge;
34 const aRockMedium = g_Decoratives.rockMedium;
35 const aBushMedium = g_Decoratives.bushMedium;
36 const aBushSmall = g_Decoratives.bushSmall;
38 const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2];
39 const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1];
43 const numPlayers = getNumPlayers();
44 const mapSize = getMapSize();
46 var clPlayer = createTileClass();
47 var clHill = createTileClass();
48 var clForest = createTileClass();
49 var clDirt = createTileClass();
50 var clRock = createTileClass();
51 var clMetal = createTileClass();
52 var clFood = createTileClass();
53 var clBaseResource = createTileClass();
54 var clLand = createTileClass();
56 const playerIslandRadius = scaleByMapSize(15, 30);
57 const islandHeight = 20;
59 const islandBetweenPlayerAndCenterDist = 0.16;
60 const islandBetweenPlayerAndCenterRadius = 0.81;
61 const centralIslandRadius = 0.36;
63 var [playerIDs, playerX, playerZ, playerAngle, startAngle] = radialPlayerPlacement();
70 function initIsConnected()
72 for (let m = 0; m < numIslands; ++m)
75 for (let n = 0; n < numIslands; ++n)
76 isConnected[m][n] = 0;
80 function createIsland(islandID, size, tileClass)
82 let hillSize = Math.PI * Math.pow(playerIslandRadius, 2) * size;
84 new ClumpPlacer(hillSize, 0.95, 0.6, 10, islandX[islandID], islandZ[islandID]),
86 new LayeredPainter([tCliff, tHill], [2]),
87 new SmoothElevationPainter(ELEVATION_SET, islandHeight, 2),
94 function createIslandAtRadialLocation(playerID, islandID, playerIDOffset, distFromCenter, islandRadius)
96 let angle = startAngle + (playerID * 2 + playerIDOffset) * Math.PI / numPlayers;
97 islandX[islandID] = Math.round(fractionToTiles(0.5 + distFromCenter * Math.cos(angle)));
98 islandZ[islandID] = Math.round(fractionToTiles(0.5 + distFromCenter * Math.sin(angle)));
99 createIsland(islandID, islandRadius, clLand);
102 function createSnowflakeSearockWithCenter(sizeID)
104 let [tertiaryIslandDist, tertiaryIslandRadius, islandBetweenPlayersDist, islandBetweenPlayersRadius] = islandSizes[sizeID];
106 let islandID_center = 4 * numPlayers;
107 numIslands = islandID_center + 1;
110 log("Creating central island...");
111 islandX[islandID_center] = fractionToTiles(0.5);
112 islandZ[islandID_center] = fractionToTiles(0.5);
113 createIsland(islandID_center, centralIslandRadius, clLand);
115 for (let playerID = 0; playerID < numPlayers; ++playerID)
117 let playerID_neighbor = playerID + 1 < numPlayers ? playerID + 1 : 0;
119 let islandID_player = playerID;
120 let islandID_playerNeighbor = playerID_neighbor;
121 let islandID_betweenPlayers = playerID + numPlayers;
122 let islandID_betweenPlayerAndCenter = playerID + 2 * numPlayers;
123 let islandID_betweenPlayerAndCenterNeighbor = playerID_neighbor + 2 * numPlayers;
124 let islandID_tertiary = playerID + 3 * numPlayers;
126 log("Creating island between the player and their neighbor...");
127 isConnected[islandID_betweenPlayers][islandID_player] = 1;
128 isConnected[islandID_betweenPlayers][islandID_playerNeighbor] = 1;
129 createIslandAtRadialLocation(playerID, islandID_betweenPlayers, 1, islandBetweenPlayersDist, islandBetweenPlayersRadius);
131 log("Creating an island between the player and the center...");
132 isConnected[islandID_betweenPlayerAndCenter][islandID_player] = 1;
133 isConnected[islandID_betweenPlayerAndCenter][islandID_center] = 1;
134 isConnected[islandID_betweenPlayerAndCenter][islandID_betweenPlayerAndCenterNeighbor] = 1;
135 createIslandAtRadialLocation(playerID, islandID_betweenPlayerAndCenter, 0, islandBetweenPlayerAndCenterDist, islandBetweenPlayerAndCenterRadius);
137 log("Creating tertiary island, at the map border...");
138 isConnected[islandID_tertiary][islandID_betweenPlayers] = 1;
139 createIslandAtRadialLocation(playerID, islandID_tertiary, 1, tertiaryIslandDist, tertiaryIslandRadius);
144 * Creates one island in front of every player and connects it with the neighbors.
146 function createSnowflakeSearockWithoutCenter()
148 numIslands = 2 * numPlayers;
151 for (let playerID = 0; playerID < numPlayers; ++playerID)
153 let playerID_neighbor = playerID + 1 < numPlayers ? playerID + 1 : 0;
155 let islandID_player = playerID;
156 let islandID_playerNeighbor = playerID_neighbor;
157 let islandID_inFrontOfPlayer = playerID + numPlayers;
158 let islandID_inFrontOfPlayerNeighbor = playerID_neighbor + numPlayers;
160 isConnected[islandID_player][islandID_playerNeighbor] = 1;
161 isConnected[islandID_player][islandID_inFrontOfPlayer] = 1;
162 isConnected[islandID_inFrontOfPlayer][islandID_inFrontOfPlayerNeighbor] = 1;
164 createIslandAtRadialLocation(playerID, islandID_inFrontOfPlayer, 0, islandBetweenPlayerAndCenterDist, islandBetweenPlayerAndCenterRadius);
168 function createSnowflakeSearockTiny()
170 numIslands = numPlayers + 1;
173 let islandID_center = numPlayers;
175 log("Creating central island...");
176 islandX[islandID_center] = fractionToTiles(0.5);
177 islandZ[islandID_center] = fractionToTiles(0.5);
178 createIsland(numPlayers, 1, clLand);
180 for (let playerID = 0; playerID < numPlayers; ++playerID)
182 let islandID_player = playerID;
183 isConnected[islandID_player][islandID_center] = 1;
189 const islandSizes = {
190 "medium": [0.41, 0.49, 0.26, 1],
191 "large1": [0.41, 0.49, 0.24, 1],
192 "large2": [0.41, 0.36, 0.28, 0.81]
197 createSnowflakeSearockTiny();
199 else if (mapSize <= 192)
201 createSnowflakeSearockWithoutCenter();
203 else if (mapSize <= 256)
206 createSnowflakeSearockWithCenter("medium");
208 createSnowflakeSearockWithoutCenter();
210 else if (mapSize <= 320)
213 createSnowflakeSearockWithCenter("medium");
215 createSnowflakeSearockWithoutCenter();
218 createSnowflakeSearockWithCenter(numPlayers < 6 ? "large1" : "large2");
220 for (var i = 0; i < numPlayers; ++i)
222 var id = playerIDs[i];
223 log("Creating base for player " + id + "...");
225 // get the x and z in tiles
226 var fx = fractionToTiles(playerX[i]);
227 var fz = fractionToTiles(playerZ[i]);
234 let hillSize = createIsland(i, 1, clPlayer);
236 // create the city patch
237 var cityRadius = playerIslandRadius/3;
238 var placer = new ClumpPlacer(PI*cityRadius*cityRadius, 0.6, 0.3, 10, ix, iz);
239 var painter = new LayeredPainter([tRoadWild, tRoad], [1]);
240 createArea(placer, painter, null);
242 placeCivDefaultEntities(fx, fz, id, { 'iberWall': 'towers' });
244 placeDefaultChicken(fx, fz, clBaseResource);
246 // create berry bushes
247 var bbAngle = randFloat(0, TWO_PI);
249 var bbX = round(fx + bbDist * cos(bbAngle));
250 var bbZ = round(fz + bbDist * sin(bbAngle));
251 var group = new SimpleGroup(
252 [new SimpleObject(oFruitBush, 5,5, 0,3)],
253 true, clBaseResource, bbX, bbZ
255 createObjectGroup(group, 0);
258 var mAngle = bbAngle;
259 while(abs(mAngle - bbAngle) < PI/3)
260 mAngle = randFloat(0, TWO_PI);
262 var mDist = playerIslandRadius - 4;
263 var mX = round(fx + mDist * cos(mAngle));
264 var mZ = round(fz + mDist * sin(mAngle));
265 group = new SimpleGroup(
266 [new SimpleObject(oMetalLarge, 1,1, 0,0)],
267 true, clBaseResource, mX, mZ
269 createObjectGroup(group, 0);
271 // create stone mines
272 mAngle += randFloat(PI/8, PI/4);
273 mX = round(fx + mDist * cos(mAngle));
274 mZ = round(fz + mDist * sin(mAngle));
275 group = new SimpleGroup(
276 [new SimpleObject(oStoneLarge, 1,1, 0,2)],
277 true, clBaseResource, mX, mZ
279 createObjectGroup(group, 0);
281 // create starting trees
282 var num = floor(hillSize / 60);
283 var tAngle = randFloat(-PI/3, 4*PI/3);
285 var tX = round(fx + tDist * cos(tAngle));
286 var tZ = round(fz + tDist * sin(tAngle));
287 group = new SimpleGroup(
288 [new SimpleObject(oTree1, num, num, 0,4)],
289 false, clBaseResource, tX, tZ
291 createObjectGroup(group, 0, [avoidClasses(clBaseResource,2), stayClasses(clPlayer, 3)]);
293 placeDefaultDecoratives(fx, fz, aGrassShort, clBaseResource, playerIslandRadius);
297 log("Creating connectors...");
298 for (let ix = 0; ix < mapSize; ++ix)
299 for (let iz = 0; iz < mapSize; ++iz)
300 for (let m = 0; m < numIslands; ++m)
301 for (let n = 0; n < numIslands; ++n)
303 if (isConnected[m][n] != 1)
306 let islandDistX = islandX[n] - islandX[m];
307 let islandDistZ = islandZ[m] - islandZ[n];
309 let d1 = islandDistX * (iz - islandZ[m]) + islandDistZ * (ix - islandX[m]);
310 let d2 = Math.square(islandDistX) + Math.square(islandDistZ);
312 let dis = Math.abs(d1) / Math.sqrt(d2);
313 let z = iz - islandDistX * d1 / d2;
315 if (dis >= 5 || z < Math.min(islandZ[m], islandZ[n]) || z > Math.max(islandZ[m], islandZ[n]))
318 addToClass(ix, iz, clLand);
326 height = islandHeight;
327 tileClass = dis < 2 ? tHill : tCliff;
331 height = islandHeight + 10 * f;
335 if (getHeight(ix, iz) < height)
337 placeTerrain(ix, iz, tileClass);
338 setHeight(ix, iz, height);
342 if (currentBiome() == "savanna")
345 var MAX_TREES = 1250;
348 else if (currentBiome() == "tropic")
350 var MIN_TREES = 1000;
351 var MAX_TREES = 6000;
357 var MAX_TREES = 3000;
361 var totalTrees = scaleByMapSize(MIN_TREES, MAX_TREES);
362 var numForest = totalTrees * P_FOREST;
363 var numStragglers = totalTrees * (1.0 - P_FOREST);
365 log("Creating forests...");
367 [[tForestFloor2, tMainTerrain, pForest1], [tForestFloor2, pForest1]],
368 [[tForestFloor1, tMainTerrain, pForest2], [tForestFloor1, pForest2]]
371 var size = numForest / (scaleByMapSize(2, 8) * numPlayers) * (currentBiome() == "savanna" ? 2 : 1);
372 var num = floor(size / types.length);
373 for (let type of types)
375 new ClumpPlacer(numForest / num, 0.1, 0.1, 1),
377 new LayeredPainter(type, [2]),
380 [avoidClasses(clPlayer, 6, clForest, 10, clHill, 0), stayClasses(clLand, 4)],
384 log("Creating stone mines...");
385 group = new SimpleGroup([new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], true, clRock);
386 createObjectGroupsDeprecated(group, 0,
387 [avoidClasses(clForest, 1, clPlayer, 10, clRock, 10, clHill, 1), stayClasses(clLand, 5)],
388 5*scaleByMapSize(4,16), 100
391 log("Creating small stone quarries...");
392 group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock);
393 createObjectGroupsDeprecated(group, 0,
394 [avoidClasses(clForest, 1, clPlayer, 10, clRock, 10, clHill, 1), stayClasses(clLand, 5)],
395 5*scaleByMapSize(4,16), 100
398 log("Creating metal mines...");
399 group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4)], true, clMetal);
400 createObjectGroupsDeprecated(group, 0,
401 [avoidClasses(clForest, 1, clPlayer, 10, clMetal, 10, clRock, 5, clHill, 1), stayClasses(clLand, 5)],
402 5*scaleByMapSize(4,16), 100
406 log("Creating dirt patches...");
407 for (let size of [scaleByMapSize(3, 48), scaleByMapSize(5, 84), scaleByMapSize(8, 128)])
409 new ClumpPlacer(size, 0.3, 0.06, 0.5),
411 new LayeredPainter([[tMainTerrain, tTier1Terrain],[tTier1Terrain, tTier2Terrain], [tTier2Terrain, tTier3Terrain]], [1, 1]),
414 [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), stayClasses(clLand, 5)],
415 scaleByMapSize(15, 45));
417 log("Creating grass patches...");
418 for (let size of [scaleByMapSize(2, 32), scaleByMapSize(3, 48), scaleByMapSize(5, 80)])
420 new ClumpPlacer(size, 0.3, 0.06, 0.5),
421 new TerrainPainter(tTier4Terrain),
422 [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), stayClasses(clLand, 5)],
423 scaleByMapSize(15, 45));
425 log("Creating small decorative rocks...");
426 group = new SimpleGroup(
427 [new SimpleObject(aRockMedium, 1,3, 0,1)],
430 createObjectGroupsDeprecated(
432 [avoidClasses(clForest, 0, clPlayer, 0, clHill, 0), stayClasses(clLand, 4)],
433 scaleByMapSize(16, 262), 50
436 log("Creating large decorative rocks...");
437 group = new SimpleGroup(
438 [new SimpleObject(aRockLarge, 1,2, 0,1), new SimpleObject(aRockMedium, 1,3, 0,2)],
441 createObjectGroupsDeprecated(
443 [avoidClasses(clForest, 0, clPlayer, 0, clHill, 0), stayClasses(clLand, 4)],
444 scaleByMapSize(8, 131), 50
449 log("Creating deer...");
450 group = new SimpleGroup(
451 [new SimpleObject(oMainHuntableAnimal, 5,7, 0,4)],
454 createObjectGroupsDeprecated(group, 0,
455 [avoidClasses(clForest, 0, clPlayer, 10, clHill, 1, clFood, 20), stayClasses(clLand, 4)],
461 log("Creating sheep...");
462 group = new SimpleGroup(
463 [new SimpleObject(oSecondaryHuntableAnimal, 2,3, 0,2)],
466 createObjectGroupsDeprecated(group, 0,
467 [avoidClasses(clForest, 0, clPlayer, 10, clHill, 1, clFood, 20), stayClasses(clLand, 4)],
471 log("Creating fruits...");
472 group = new SimpleGroup(
473 [new SimpleObject(oFruitBush, 5,7, 0,4)],
476 createObjectGroupsDeprecated(group, 0,
477 [avoidClasses(clForest, 0, clPlayer, 10, clHill, 1, clFood, 20), stayClasses(clLand, 4)],
482 log("Creating straggler trees...");
483 var types = [oTree1, oTree2, oTree4, oTree3];
484 var num = floor(numStragglers / types.length);
485 for (let type of types)
486 createObjectGroupsDeprecated(
487 new SimpleGroup([new SimpleObject(type, 1, 1, 0, 3)], true, clForest),
489 [avoidClasses(clForest, 1, clHill, 1, clPlayer, 9, clMetal, 6, clRock, 6), stayClasses(clLand, 4)],
493 if (currentBiome() == "tropic")
496 log("Creating small grass tufts...");
497 group = new SimpleGroup(
498 [new SimpleObject(aGrassShort, 1,2, 0,1, -PI/8,PI/8)]
500 createObjectGroupsDeprecated(group, 0,
501 [avoidClasses(clHill, 2, clPlayer, 2, clDirt, 0), stayClasses(clLand, 4)],
502 planetm * scaleByMapSize(13, 200)
507 log("Creating large grass tufts...");
508 group = new SimpleGroup(
509 [new SimpleObject(aGrass, 2,4, 0,1.8, -PI/8,PI/8), new SimpleObject(aGrassShort, 3,6, 1.2,2.5, -PI/8,PI/8)]
511 createObjectGroupsDeprecated(group, 0,
512 [avoidClasses(clHill, 2, clPlayer, 2, clDirt, 1, clForest, 0), stayClasses(clLand, 4)],
513 planetm * scaleByMapSize(13, 200)
517 log("Creating bushes...");
518 group = new SimpleGroup(
519 [new SimpleObject(aBushMedium, 1,2, 0,2), new SimpleObject(aBushSmall, 2,4, 0,2)]
521 createObjectGroupsDeprecated(group, 0,
522 [avoidClasses(clHill, 1, clPlayer, 1, clDirt, 1), stayClasses(clLand, 4)],
523 planetm * scaleByMapSize(13, 200), 50
526 setSkySet(pickRandom(["cirrus", "cumulus", "sunny"]));
527 setSunRotation(randFloat(0, TWO_PI));
528 setSunElevation(randFloat(PI/ 5, PI / 3));