1 RMS.LoadLibrary("rmgen");
3 var tGrass = ["medit_grass_field", "medit_grass_field_b", "temp_grass_c"];
4 var tDune = ["medit_grass_field_brown"];
5 var tBigDune = ["medit_grass_field_brown"];
6 var tGrassPForest = "forestfloor_dirty";
7 var tForestFloor = "medit_grass_shrubs";
8 var tGrassA = ["desert_dirt_persia_1", "desert_dirt_persia_2"];
10 var tLushGrass = ["medit_grass_field","medit_grass_field_a"];
12 var tSteepCliffs = ["temp_cliff_b", "temp_cliff_a"];
13 var tCliffs = ["temp_cliff_b", "medit_cliff_italia", "medit_cliff_italia_grass"];
14 var tHill = ["medit_cliff_italia_grass","medit_cliff_italia_grass", "medit_grass_field", "medit_grass_field", "temp_grass"];
15 var tMountain = ["medit_cliff_italia_grass","medit_cliff_italia"];
16 var tMountainTop = ["medit_cliff_italia"];
18 var tDirt = ["medit_dirt", "medit_dirt_b"];
19 var tRoad = ["medit_city_tile","medit_rocks_grass","medit_grass_field_b"];
20 var tRoadWild = ["medit_rocks_grass","medit_grass_field_b"];
21 var tGrassPatch = "medit_dirt_b";
23 var tShoreBlend = ["medit_sand_wet","medit_rocks_wet"];
24 var tShore = ["medit_rocks","medit_sand","medit_sand"];
25 var tSandTransition = ["medit_sand","medit_rocks_grass","medit_rocks_grass","medit_rocks_grass"];
26 var tVeryDeepWater = ["medit_sea_depths","medit_sea_coral_deep"];
27 var tDeepWater = ["medit_sea_coral_deep","tropic_ocean_coral"];
28 var tCreekWater = "medit_sea_coral_plants";
31 var ePine = "gaia/flora_tree_aleppo_pine";
32 var ePalmTall = "gaia/flora_tree_cretan_date_palm_tall";
33 var eFanPalm = "gaia/flora_tree_medit_fan_palm";
34 var eCypress = "gaia/flora_tree_cypress";
35 var eApple = "gaia/flora_tree_apple";
36 var eBush = "gaia/flora_bush_berry";
37 var eFish = "gaia/fauna_fish";
38 var ePig = "gaia/fauna_pig";
39 var eStoneMine = "gaia/geology_stonemine_medit_quarry";
40 var eMetalMine = "gaia/geology_metal_mediterranean_slabs";
43 var aFlower1 = "actor|props/flora/decals_flowers_daisies.xml";
44 var aWaterFlower = "actor|props/flora/water_lillies.xml";
45 var aReedsA = "actor|props/flora/reeds_pond_lush_a.xml";
46 var aReedsB = "actor|props/flora/reeds_pond_lush_b.xml";
47 var aRock = "actor|geology/stone_granite_med.xml";
48 var aLargeRock = "actor|geology/stone_granite_large.xml";
49 var aBushA = "actor|props/flora/bush_medit_sm_lush.xml";
50 var aBushB = "actor|props/flora/bush_medit_me_lush.xml";
51 var aPlantA = "actor|props/flora/plant_medit_artichoke.xml";
52 var aPlantB = "actor|props/flora/grass_tufts_a.xml";
53 var aPlantC = "actor|props/flora/grass_soft_tuft_a.xml";
54 var aShorePlantA = "actor|props/flora/reeds_beach.xml";
55 var aShorePlantB = "actor|props/flora/grass_temp_field_brown.xml";
57 var aStandingStone = "actor|props/special/eyecandy/standing_stones.xml";
59 var tForestNicae = [tForestFloor + TERRAIN_SEPARATOR + ePine,tForestFloor + TERRAIN_SEPARATOR + ePine,tForestFloor + TERRAIN_SEPARATOR + ePine,tForestFloor + TERRAIN_SEPARATOR + ePine,tForestFloor + TERRAIN_SEPARATOR + eFanPalm, tForestFloor + TERRAIN_SEPARATOR + ePalmTall, tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor];
60 var tForestNicaeLight = [tForestFloor + TERRAIN_SEPARATOR + ePine,tForestFloor + TERRAIN_SEPARATOR + ePine,tForestFloor + TERRAIN_SEPARATOR + eFanPalm, tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor];
61 var tForestNicaeScarce = [tForestFloor + TERRAIN_SEPARATOR + ePine,tForestFloor + TERRAIN_SEPARATOR + ePine,tForestFloor + TERRAIN_SEPARATOR + eFanPalm, tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor,tForestFloor];
63 log("Initializing map...");
67 var numPlayers = getNumPlayers();
68 var mapSize = getMapSize();
69 var mapArea = mapSize*mapSize;
71 // create tile classes
72 var clCorsica = createTileClass();
73 var clSardinia = createTileClass();
74 var clCreek = createTileClass();
76 var clWater = createTileClass();
78 var clCliffs = createTileClass();
79 var clForest = createTileClass();
80 var clPeak = createTileClass();
82 var clShore = createTileClass();
83 var clPathToShore = createTileClass();
84 var clPlayer = createTileClass();
85 var clBaseResource = createTileClass();
86 var clPassage = createTileClass();
87 var clHill = createTileClass();
88 var clWater = createTileClass();
89 var clDirt = createTileClass();
90 var clRock = createTileClass();
91 var clMetal = createTileClass();
92 var clFood = createTileClass();
93 var clSettlement = createTileClass();
94 var clDune = createTileClass();
96 // on every pixel of the map, set wet sand
97 for (var ix = 0; ix < mapSize; ix++)
99 for (var iz = 0; iz < mapSize; iz++)
101 var x = ix / (mapSize + 1.0);
102 var z = iz / (mapSize + 1.0);
103 placeTerrain(ix, iz, tVeryDeepWater);
104 //addToClass(ix,iz,clWater);
108 // let's decide if we swap
109 var swap = Math.round(Math.random()); // should return about 50/50 a 0 or a 1
110 // let's create Corsica
111 log("Creating Corsica");
112 var CorsicaX = fractionToTiles(0.99);
113 var CorsicaZ = fractionToTiles(0.9);
115 CorsicaX = fractionToTiles(0.01);
117 // Okay so the thing here is that we'll make a sort of jagged circle. To achieve this, I'll make a few islands
118 // that will basically be put together
119 // first, let's make a big round island in the corner.
120 // okay so actually subdivided cleverly to make it work and give jagedness with the multiple islands
121 var llx = round(CorsicaX);
122 var llz = round(CorsicaZ);
123 // okay so the circle reaches close to a third of the map
124 var placer = new ClumpPlacer(fractionToSize(0.3)*1.8, 1.0, 0.5, 10, llx, llz);
125 var terrainPainter = new LayeredPainter([tCliffs, tGrass], [2] );
126 var elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 5,0);
127 createArea(placer, [terrainPainter, paintClass(clCorsica), elevationPainter], null);
128 var nbSubIsland = 5; // actually 5+1
129 for (var i = 0; i <= nbSubIsland; i++)
131 // radius is "sqrt(this.size / PI)"... so in my case it's "sqrt(fractionofSize(0.33)*2.0/PI), about 0.64, sqrt-ed
133 // only from π to 3π/2
134 var angle = (i * (-PI/(nbSubIsland*2)) + PI);
137 var llx = round (CorsicaX + sqrt(fractionToSize(0.3)*0.55)*sin(angle));
138 var llz = round (CorsicaZ + sqrt(fractionToSize(0.3)*0.55)*cos(angle));
139 var placer = new ClumpPlacer(fractionToSize(0.05)/2, 0.6, 0.03, 10, llx, llz);
140 var terrainPainter = new LayeredPainter([tCliffs, tGrass], [2] );
141 var elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 5,1);
142 createArea(placer, [terrainPainter, paintClass(clCorsica), elevationPainter], null);
146 log("Creating Sardinia");
147 var SardiniaX = fractionToTiles(0.01);
148 var SardiniaZ = fractionToTiles(0.1);
150 SardiniaX = fractionToTiles(0.99);
152 var llx = round(SardiniaX);
153 var llz = round(SardiniaZ);
154 // okay so the circle reaches close to a third of the map
155 var placer = new ClumpPlacer(fractionToSize(0.3)*1.8, 1.0, 0.5, 10, llx, llz);
156 var terrainPainter = new LayeredPainter([tCliffs, tGrass], [2] );
157 var elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 5,0);
158 createArea(placer, [terrainPainter, paintClass(clSardinia), elevationPainter], null);
159 // same as Corsica on the other side
160 for (var i = 0; i <= nbSubIsland; i++)
162 var angle = (i * (-PI/(nbSubIsland*2)));
165 var llx = round (SardiniaX + sqrt(fractionToSize(0.3)*0.55)*sin(angle));
166 var llz = round (SardiniaZ + sqrt(fractionToSize(0.3)*0.55)*cos(angle));
167 var placer = new ClumpPlacer(fractionToSize(0.05)/2, 0.6, 0.03, 10, llx, llz);
168 var terrainPainter = new LayeredPainter([tCliffs, tGrass], [2] );
169 var elevationPainter = new SmoothElevationPainter(ELEVATION_SET, 5,1);
170 createArea(placer, [terrainPainter, paintClass(clSardinia), elevationPainter], null);
173 log("Creating Creeks");
175 // okay so now let's make some cleverly designed creeks: this creates a very jagged relief, looks good
176 var nbCreeks = scaleByMapSize(6,15);
178 var islandX = [SardiniaX,CorsicaX];
179 var islandZ = [SardiniaZ,CorsicaZ];
181 for (var island = 0; island <= 1; island++)
182 for (var i = 0; i <= nbCreeks; i++)
184 var radius = fractionToTiles( (Math.random()/17) + 0.49);
185 var angle = PI*island + i*(PI/(nbCreeks*2));
188 fx = radius * cos(angle);
189 fz = radius * sin(angle);
190 fx = round(islandX[island] + fx);
191 fz = round(islandZ[island] + fz);
192 var size = scaleByMapSize(75,100);
193 if (Math.random() > 0.5)
194 size = Math.random() * 40 + 10;
196 size += Math.random() * 20;
197 var placer = new ClumpPlacer(size, 0.4, 0.01, 10, fx,fz);
198 var terrainPainter = new TerrainPainter(tSteepCliffs);
199 var elevationPainter = new SmoothElevationPainter(ELEVATION_SET, -5,0); // base height is -10
200 createArea(placer, [terrainPainter, paintClass(clCreek), elevationPainter], null);
203 var nbBeaches = scaleByMapSize(2,5);
204 for (var island = 0; island <= 1; island++)
206 for (var i = 0; i <= nbBeaches; i++)
208 var smallRadius = fractionToTiles( 0.45);
209 var bigRadius = fractionToTiles( 0.57);
210 var angle = PI*island + i*(PI/(nbBeaches*2.5)) + PI/(nbBeaches*6) + randFloat(-PI/(nbBeaches*7),PI/(nbBeaches*7));
213 var startX = smallRadius * cos(angle);
214 var startZ = smallRadius * sin(angle);
215 startX = round(islandX[island] + startX);
216 startZ = round(islandZ[island] + startZ);
218 var endX = bigRadius * cos(angle);
219 var endZ = bigRadius * sin(angle);
220 endX = round(islandX[island] + endX);
221 endZ = round(islandZ[island] + endZ);
223 var placer = new ClumpPlacer(130, 0.7, 0.8, 10, round((startX+endX*3)/4),round((startZ+endZ*3)/4));
224 var elevationPainter = new SmoothElevationPainter(ELEVATION_SET, -1,5); // base height is -10
225 createArea(placer, [elevationPainter], null);
227 straightPassageMaker(startX, startZ,endX,endZ, 25, 18, 4,clShore,null);
231 log("Creating Main Relief");
232 // Let's make it generally cliffy
233 placer = new ClumpPlacer(fractionToSize(0.3)*1.8, 1.0, 0.2, 4,round((CorsicaX * 5 + fractionToTiles(0.5)) / 6.0),round(fractionToTiles(0.8)));
234 elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 30,fractionToTiles(0.45));
235 createArea( placer, [elevationPainter], null);
236 placer = new ClumpPlacer(fractionToSize(0.3)*1.8, 1.0, 0.2, 4,round((SardiniaX * 5 + fractionToTiles(0.5)) / 6.0),round(fractionToTiles(0.2)));
237 elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 30,fractionToTiles(0.45));
238 createArea( placer, [elevationPainter], null);
240 log("Creating players");
242 // randomize player order
244 for (var i = 0; i < numPlayers; i++)
248 playerIDs = sortPlayers(playerIDs);
251 var playerX = new Array(numPlayers);
252 var playerZ = new Array(numPlayers);
253 var playerAngle = new Array(numPlayers);
256 var formerTeam = getPlayerTeam(0);
259 for (var o = 0; o < numPlayers; o++)
261 if (getPlayerTeam(o) === formerTeam && formerTeam !== -1)
268 } else if (getPlayerTeam(o) !== -1){
278 // okay now the less crowded:
279 if (onCorsica.length > onSardinia.length)
284 formerTeam = getPlayerTeam(o);
286 // le'ts place the players in a circle around the island.
287 for (var i = 0;i < onCorsica.length; i++)
289 var angle = (i * (PI/(onCorsica.length*2)) + PI + PI/(4*onCorsica.length));
292 playerAngle[onCorsica[i]] = angle;
293 playerX[onCorsica[i]] = round( CorsicaX + fractionToTiles(0.36*cos(angle)));
294 playerZ[onCorsica[i]] = round( fractionToTiles(1 + 0.36*sin(angle)));
296 for (var i = 0;i < onSardinia.length; i++)
298 var angle = (i * (PI/(onSardinia.length*2)) + PI/(4*onSardinia.length));
301 playerAngle[onSardinia[i]] = angle;
302 playerX[onSardinia[i]] = round( SardiniaX + fractionToTiles(0.36*cos(angle)));
303 playerZ[onSardinia[i]] = round( fractionToTiles(0 + 0.36*sin(angle)));
306 var placer = undefined;
307 var fx = 0; var fz = 0;
308 var ix =0; var iz = 0;
309 for (var i = 0; i < numPlayers; i++)
311 var id = playerIDs[i];
312 log("Creating base for player " + id + "...");
317 // get the x and z in tiles
322 // let's create a nice platform
323 var placer = new ClumpPlacer(PI*radius*radius, 0.95, 0.3, 10, fx,fz);
324 var PlayerArea = createArea(placer, [paintClass(clPlayer)], null);
326 // create the city patch
327 var cityRadius = radius/4;
328 placer = new ClumpPlacer(PI*cityRadius*cityRadius, 0.8, 0.3, 10, fx, fz);
329 var painter = new LayeredPainter([tRoadWild,tRoad],[1]);
330 var elevationPainter = new SmoothElevationPainter(ELEVATION_SET, getHeight(fx,fz),10);
331 createArea(placer, [painter,paintClass(clSettlement),elevationPainter], null);
333 // create starting units
334 placeCivDefaultEntities(fx, fz, id, { 'iberWall': false });
336 placeDefaultChicken(fx, fz, clBaseResource);
338 // create berry bushes
339 var bbAngle = randFloat(0, TWO_PI);
341 var bbX = round(fx + bbDist * cos(bbAngle));
342 var bbZ = round(fz + bbDist * sin(bbAngle));
343 var group = new SimpleGroup(
344 [new SimpleObject(eBush, 5,5, 1,2)],
345 true, clBaseResource, bbX, bbZ
347 createObjectGroup(group, 0);
350 // this makes sure it's created on the same level as the player.
351 var mAngle = randFloat(playerAngle[i] + PI/2,playerAngle[i] + PI/3);
353 var mX = round(fx + mDist * cos(mAngle));
354 var mZ = round(fz + mDist * sin(mAngle));
355 group = new SimpleGroup(
356 [new SimpleObject(eMetalMine, 1,1, 0,0),new SimpleObject(aBushB, 1,1, 2,2), new SimpleObject(aBushA, 0,2, 1,3), new SimpleObject(ePine, 0,1, 3,3)], true, clBaseResource, mX, mZ );
357 createObjectGroup(group, 0);
358 // create stone mines
359 mAngle += randFloat(PI/8, PI/5);
360 mX = round(fx + mDist * cos(mAngle));
361 mZ = round(fz + mDist * sin(mAngle));
362 group = new SimpleGroup(
363 [new SimpleObject(eStoneMine, 1,1, 0,2),new SimpleObject(aBushB, 1,1, 2,2), new SimpleObject(aBushA, 0,2, 1,3), new SimpleObject(ePine, 0,1, 3,3)], true, clBaseResource, mX, mZ );
364 createObjectGroup(group, 0);
366 group = new SimpleGroup([new SimpleObject(ePine, 1,3, 1,4),new SimpleObject(ePalmTall, 0,1, 1,4),new SimpleObject(eFanPalm, 0,1, 0,2)], true, clForest);
367 createObjectGroups(group, 0, [avoidClasses(clBaseResource,3, clSettlement,0), stayClasses(clPlayer,1)], 150, 1000);
371 log ("making plateaux");
372 // Corsica and Sardinia
374 var SardX = round((SardiniaX*5 + fractionToTiles(0.5))/6.0);
375 var SardZ = round(fractionToTiles(0.1));
376 var CorsX = round((CorsicaX*5 + fractionToTiles(0.5))/6.0);
377 var CorsZ = round(fractionToTiles(0.9));
378 // first level plateaux, puts the player higher
379 placer = new ClumpPlacer(fractionToSize(0.18)*1.8, 0.95, 0.02, 4,CorsX,CorsZ);
380 elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 9,1);
381 createArea( placer, [elevationPainter], null);
382 placer = new ClumpPlacer(fractionToSize(0.18)*1.8, 0.95, 0.02, 4,SardX,SardZ);
383 elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 9,1);
384 createArea( placer, [elevationPainter], null);
385 // second level plateaux, top of the hill
388 placer = new ClumpPlacer(fractionToSize(0.1), 0.98, 0.04, 4,CorsX,CorsZ);
389 terrainPainter = new LayeredPainter([tCliffs, tGrass], [2] );
390 elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 8,1);
391 createArea( placer, [terrainPainter,elevationPainter], null);
392 placer = new ClumpPlacer(fractionToSize(0.1), 0.98, 0.04, 4,SardX,SardZ);
393 terrainPainter = new LayeredPainter([tCliffs, tGrass], [2] );
394 elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 8,1);
395 createArea( placer, [terrainPainter,elevationPainter], null);
397 log ("creating passages towards the island");
400 var nb = scaleByMapSize(1,4);
401 for (var i = 0; i < nb; i++) {
402 var radius = sqrt(fractionToSize(0.1)/PI);
403 var angle = PI + i*(PI/(2*nb)) + PI/(4*nb);
406 var x1 = round(CorsX + (radius+5)*cos(angle));
407 var y1 = round(CorsZ + (radius+5)*sin(angle));
408 var x2 = round(CorsX + (radius-4)*cos(angle));
409 var y2 = round(CorsZ + (radius-4)*sin(angle));
410 straightPassageMaker(x1, y1, x2, y2, 1, 6, 2, clPassage, tGrass);
412 for (var i = 0; i < nb; i++) {
413 var radius = sqrt(fractionToSize(0.1)/PI)+ 2;
414 var angle = i*(PI/(2*nb)) + PI/(4*nb);
417 var x1 = round(SardX + (radius+5)*cos(angle));
418 var y1 = round(SardZ + (radius+5)*sin(angle));
419 var x2 = round(SardX + (radius-4)*cos(angle));
420 var y2 = round(SardZ + (radius-4)*sin(angle));
421 straightPassageMaker(x1, y1, x2, y2, 1, 6, 2, clPassage, tGrass);
424 for (var i = 0; i <= 3; i++) {
425 var radius = sqrt(fractionToSize(0.18)*1.8/PI) + 2;
426 var angle = PI + i*(PI/7) + PI/9;
429 var x1 = round(CorsX + (radius+7)*cos(angle));
430 var y1 = round(CorsZ + (radius+7)*sin(angle));
431 var x2 = round(CorsX + (radius-5)*cos(angle));
432 var y2 = round(CorsZ + (radius-5)*sin(angle));
433 straightPassageMaker(x1, y1, x2, y2, 4, 10, 3, clPassage, tGrass);
435 for (var i = 0; i <= 3; i++) {
436 var radius = sqrt(fractionToSize(0.18)*1.8/PI)+ 2;
437 var angle = i*(PI/7) + PI/9;
440 var x1 = round(SardX + (radius+7)*cos(angle));
441 var y1 = round(SardZ + (radius+7)*sin(angle));
442 var x2 = round(SardX + (radius-5)*cos(angle));
443 var y2 = round(SardZ + (radius-5)*sin(angle));
444 straightPassageMaker(x1, y1, x2, y2, 4, 10, 3, clPassage, tGrass);
448 log ("creating bumps");
449 placer = new ClumpPlacer(70, 0.6, 0.1, 4);
450 elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, 2,3);
451 createAreas( placer, [elevationPainter], [avoidClasses(clPlayer,2,clPassage, 2), stayClasses(clCorsica,2)],scaleByMapSize(20,100), 5 );
452 createAreas( placer, [elevationPainter], [avoidClasses(clPlayer,2,clPassage, 2), stayClasses(clSardinia,2)],scaleByMapSize(20,100), 5 );
454 log ("creating anti bumps");
455 placer = new ClumpPlacer(120, 0.3, 0.1, 4);
456 elevationPainter = new SmoothElevationPainter(ELEVATION_MODIFY, -5,6);
457 createAreas( placer, [elevationPainter], [avoidClasses(clPlayer,2,clPassage, 2,clCorsica,2,clSardinia,2)],scaleByMapSize(20,100), 5 );
461 var terrTop = createTerrain(tMountainTop);
462 var terrMount = createTerrain(tMountain);
463 var terrHill = createTerrain(tHill);
464 var terrCliff = createTerrain(tCliffs);
465 var terrSteepCliff = createTerrain(tSteepCliffs);
466 var terrGrass = createTerrain(tGrass);
468 var terrShallow = createTerrain(tCreekWater);
469 var terrDeep = createTerrain(tDeepWater);
470 var terrDark = createTerrain(tVeryDeepWater);
471 var terrSand = createTerrain(tShore);
472 var terrWetSand = createTerrain(tShoreBlend);
473 var terrSandTransition = createTerrain(tSandTransition);
474 // first pass: who's water?
475 for (var sandx = 0; sandx < mapSize; sandx++)
476 for (var sandz = 0; sandz < mapSize; sandz++)
477 if (getHeight(sandx,sandz) < 0)
478 addToClass(sandx,sandz,clWater);
480 // second pass: who's not water
481 for (var sandx = 0; sandx < mapSize; sandx++) {
482 for (var sandz = 0; sandz < mapSize; sandz++) {
483 if (getTileClass(clSettlement).countMembersInRadius(sandx,sandz,2) === 0)
485 var height = getHeight(sandx,sandz);
486 var heightDiff = getHeightDiff(sandx,sandz);
487 if (height >= 0.5 && height < 1.5 /*&& getTileClass(clWater).countMembersInRadius(sandx,sandz,3) > 0 */ && getTileClass(clShore).countMembersInRadius(sandx,sandz,2) > 0)
489 terrSandTransition.place(sandx,sandz);
490 } else if (height >= 1 && getTileClass(clWater).countMembersInRadius(sandx,sandz,3) == 0)
492 // paint hills or cliffs depending on terrain elevation difference
493 if (height > 17 && getTileClass(clPassage).countMembersInRadius(sandx,sandz,2) == 0)
496 terrHill.place(sandx,sandz);
497 else if(heightDiff < 10)
498 terrMount.place(sandx,sandz);
500 terrGrass.place(sandx,sandz);
502 if (height > 25 && heightDiff >= 10 && getTileClass(clPassage).countMembersInRadius(sandx,sandz,2) == 0) {
503 terrSteepCliff.place(sandx,sandz);
504 addToClass(sandx,sandz,clCliffs);
505 } else if(heightDiff >= 10 && getTileClass(clPassage).countMembersInRadius(sandx,sandz,2) == 0) {
506 terrCliff.place(sandx,sandz);
507 addToClass(sandx,sandz,clCliffs);
510 if (height >= 0 && heightDiff >= 9) {
511 terrCliff.place(sandx,sandz);
512 addToClass(sandx,sandz,clCliffs);
513 } else if (height >= -0.75 && height < 1.5 && heightDiff < 9) {
514 terrSand.place(sandx,sandz);
515 } else if (height >= -3 && height < -0.75 && heightDiff < 9) {
516 terrWetSand.place(sandx,sandz);
517 } else if (height >= -6 && height < -3 && heightDiff < 9) {
518 terrShallow.place(sandx,sandz);
519 } else if (height > -10 && height < -6 && heightDiff < 6) {
520 terrDeep.place(sandx,sandz);
522 if (heightDiff >= 9) {
523 terrCliff.place(sandx,sandz);
524 addToClass(sandx,sandz,clCliffs);
533 log("Creating stone mines...");
534 // create large stone quarries
535 group = new SimpleGroup([new SimpleObject(eStoneMine, 1,1, 0,0),new SimpleObject(aBushB, 1,1, 2,2), new SimpleObject(aBushA, 0,2, 1,3)], true, clBaseResource);
536 createObjectGroups(group, 0,[stayClasses(clCorsica, 1),avoidClasses(clWater, 3, clPlayer,2 , clBaseResource, 2,clCliffs,1)], scaleByMapSize(6,25), 1000 );
537 createObjectGroups(group, 0,[stayClasses(clSardinia, 1),avoidClasses(clWater, 3, clPlayer,2 , clBaseResource, 2,clCliffs,1)], scaleByMapSize(6,25), 1000 );
539 log("Creating metal mines...");
540 // create large metal quarries
541 group = new SimpleGroup([new SimpleObject(eMetalMine, 1,1, 0,0),new SimpleObject(aBushB, 1,1, 2,2), new SimpleObject(aBushA, 0,2, 1,3)], true, clBaseResource);
542 createObjectGroups(group, 0,[avoidClasses(clWater, 3, clPlayer,2 , clBaseResource, 2,clCliffs,1),stayClasses(clCorsica, 1)], scaleByMapSize(6,25), 1000 );
543 createObjectGroups(group, 0,[avoidClasses(clWater, 3, clPlayer,2 , clBaseResource, 2,clCliffs,1),stayClasses(clSardinia, 1)], scaleByMapSize(6,25), 1000 );
545 log("Creating grass patches...");
546 placer = new ClumpPlacer(20, 0.3, 0.06, 0.5);
547 painter = new TerrainPainter(tLushGrass);
548 createAreas( placer, [painter,paintClass(clForest)], avoidClasses(clWater, 1,clPlayer, 0,clBaseResource, 3,clCliffs,1), scaleByMapSize(10, 40) );
550 log ("creating forests");
551 var TreeGroup = new SimpleGroup([new SimpleObject(ePine, 3,6, 1,3),new SimpleObject(ePalmTall, 1,3, 1,3),new SimpleObject(eFanPalm, 0,2, 0,2),new SimpleObject(eApple, 0,1, 1,2)], true, clForest);
552 createObjectGroups(TreeGroup, 0, [avoidClasses(clWater, 1, clForest, 0,clPlayer, 0,clBaseResource, 2,clCliffs,2), stayClasses(clCorsica, 3)], scaleByMapSize(350,2500), 100 );
553 createObjectGroups(TreeGroup, 0, [avoidClasses(clWater, 1, clForest, 0,clPlayer, 0,clBaseResource, 2,clCliffs,2), stayClasses(clSardinia, 3)], scaleByMapSize(350,2500), 100 );
558 // create small decorative rocks
559 log("Creating small decorative rocks...");
560 group = new SimpleGroup( [new SimpleObject(aRock, 1,3, 0,1),new SimpleObject(aStandingStone, 0,2, 0,3)], true );
561 createObjectGroups( group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 0,clBaseResource, 0, clPassage, 2),
562 scaleByMapSize(16, 262), 50
566 // create large decorative rocks
567 log("Creating large decorative rocks...");
568 group = new SimpleGroup( [new SimpleObject(aLargeRock, 1,2, 0,1), new SimpleObject(aRock, 1,3, 0,2)], true
570 createObjectGroups( group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 0,clBaseResource, 0, clPassage, 2),
571 scaleByMapSize(8, 131), 50
573 createObjectGroups( group, 0, borderClasses(clWater, 5,10), scaleByMapSize(100,800), 500);
575 // create decorative grass
576 log("Creating beautification...");
577 group = new SimpleGroup( [new SimpleObject(aPlantA, 3,7, 0,3),new SimpleObject(aPlantB, 3,6, 0,3),new SimpleObject(aPlantC, 1,4, 0,4)], true );
578 createObjectGroups( group, 0, avoidClasses(clWater, 0,clBaseResource, 0, clShore,3), scaleByMapSize(100, 600), 50 );
579 group = new SimpleGroup( [new SimpleObject(aPlantB, 5,20, 0,5),new SimpleObject(aPlantC, 4,10, 0,4)], true );
580 createObjectGroups( group, 0, avoidClasses(clWater, 0,clBaseResource, 0, clShore,3), scaleByMapSize(100, 600), 50 );
584 log("Creating animals...");
585 group = new SimpleGroup( [new SimpleObject(ePig, 2,4, 0,3)] );
586 createObjectGroups( group, 0, avoidClasses(clWater, 3,clBaseResource, 0), scaleByMapSize(20, 100), 50 );
588 group = new SimpleGroup( [new SimpleObject(eFish, 1,2, 0,3)] );
589 createObjectGroups( group, 0, [avoidClasses(clCreek,3,clShore,3),stayClasses(clWater, 3)], scaleByMapSize(50, 150), 100 );
594 if (randFloat(0,1) > 0.5)
595 setSkySet("cumulus");
598 setSunColor(0.8,0.66,0.48);
599 setSunElevation(0.828932);
601 setSunRotation(6.3*PI/8);
603 setSunRotation(2.3*PI/8);
604 setTerrainAmbientColor(0.564706,0.543726,0.419608);
605 setUnitsAmbientColor(0.53,0.55,0.45);
606 setWaterColor(0.2,0.294,0.49);
607 setWaterTint(0.208, 0.659, 0.925);
608 setWaterMurkiness(0.72);
609 setWaterWaviness(2.0);
610 setWaterType("ocean");
617 // this function will go from point [x1,z1] to point [x2,z2], while following a curve of width (starting-center-starting)
618 // it can smooth on the side depending on "smooth", which is the distance of the smooth. Tileclass and Terrain set a tileclass/terrain
619 // it effectively can create a smooth path from point [x1,z1] to point [x2,z2], ie Canyon, whatever.
620 // note: NOT efficient for large distances: I'm widely oversampling
621 function straightPassageMaker(x1, z1, x2, z2, startWidth, centerWidth, smooth, tileclass, terrain)
623 var mapSize = g_Map.size;
624 var stepNB = sqrt((x2-x1)*(x2-x1) + (z2-z1)*(z2-z1)) + 2;
626 var startHeight = getHeight(x1,z1);
627 var finishHeight = getHeight(x2,z2);
628 for (var step = 0; step <= stepNB; step+=0.5)
630 var ix = ((stepNB-step)*x1 + x2*step) / stepNB;
631 var iz = ((stepNB-step)*z1 + z2*step) / stepNB;
632 // 5 at star/end, and 0 at the center
633 var width = (abs(step - stepNB/2.0) *startWidth + (stepNB/2 - abs(step - stepNB/2.0)) * centerWidth ) / (stepNB/2);
634 var oldDirection = [x2-x1, z2-z1];
635 // let's get the perpendicular direction
636 var direction = [ -oldDirection[1],oldDirection[0] ];
637 if (abs(direction[0]) > abs(direction[1]))
639 direction[1] = direction[1] / abs(direction[0]);
640 if (direction[0] > 0)
645 direction[0] = direction[0] / abs(direction[1]);
646 if (direction[1] > 0)
651 for (var po = -Math.floor(width/2.0); po <= Math.floor(width/2.0); po+=0.5)
653 var rx = po*direction[0];
654 var rz = po*direction[1];
656 var relativeWidth = abs(po / Math.floor(width/2));
657 var targetHeight = ((stepNB-step)*startHeight + finishHeight*step) / stepNB;
658 if (round(ix + rx) < mapSize && round(iz + rz) < mapSize && round(ix + rx) >= 0 && round(iz + rz) >= 0)
660 // smoothing the sides
661 if ( abs(abs(po) - abs(Math.floor(width/2.0))) < smooth)
663 var localHeight = getHeight(round(ix + rx), round(iz + rz));
664 var localPart = smooth - abs(abs(po) - abs(Math.floor(width/2.0)));
665 var targetHeight = (localHeight * localPart + targetHeight * (1/localPart) )/ (localPart + 1/localPart);
668 g_Map.setHeight(round(ix + rx), round(iz + rz), targetHeight);
669 if (tileclass !== null)
670 addToClass(round(ix + rx), round(iz + rz), tileclass);
671 if (terrain !== null)
672 placeTerrain(round(ix + rx), round(iz + rz), terrain);
677 // no need for preliminary rounding
678 function getHeightDiff(x1, z1)
680 var height = getHeight(round(x1),round(z1));
682 if (z1 + 1 < mapSize)
683 diff += abs(getHeight(round(x1),round(z1+1)) - height);
684 if (x1 + 1 < mapSize && z1 + 1 < mapSize)
685 diff += abs(getHeight(round(x1+1),round(z1+1)) - height);
686 if (x1 + 1 < mapSize)
687 diff += abs(getHeight(round(x1+1),round(z1)) - height);
688 if (x1 + 1 < mapSize && z1 - 1 >= 0)
689 diff += abs(getHeight(round(x1+1),round(z1-1)) - height);
691 diff += abs(getHeight(round(x1),round(z1-1)) - height);
692 if (x1 - 1 >= 0 && z1 - 1 >= 0)
693 diff += abs(getHeight(round(x1-1),round(z1-1)) - height);
695 diff += abs(getHeight(round(x1-1),round(z1)) - height);
696 if (x1 - 1 >= 0 && z1 + 1 < mapSize)
697 diff += abs(getHeight(round(x1-1),round(z1+1)) - height);
700 function hasTextureInRadius(x1, z1,radius, textureName)
702 for (var xx = x1-radius;xx <= x1 + radius; xx++)
703 for (var zz = z1-radius;zz <= z1 + radius; zz++)
704 if (xx !== x1 || zz !== z1)
705 if (xx >= 0 && xx < mapSize)
706 if (zz >= 0 && zz < mapSize)
708 if (typeof(textureName) != "number")
710 for (var i in textureName)
711 if ( g_Map.getTexture(xx,zz) == textureName[i])
714 if ( g_Map.getTexture(xx,zz) == textureName)