Index: ps/trunk/binaries/data/mods/public/maps/random/guadalquivir_river.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/guadalquivir_river.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/guadalquivir_river.js (revision 26381) @@ -1,290 +1,290 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); const tGrass = ["medit_grass_field_a", "medit_grass_field_b"]; const tForestFloorC = "medit_plants_dirt"; const tForestFloorP = "medit_grass_shrubs"; const tGrassA = "medit_grass_field_b"; const tGrassB = "medit_grass_field_brown"; const tGrassC = "medit_grass_field_dry"; const tRoad = "medit_city_tile"; const tRoadWild = "medit_city_tile"; const tGrassPatch = "medit_grass_shrubs"; const tShore = "sand_grass_25"; const tWater = "medit_sand_wet"; const oPoplar = "gaia/tree/poplar"; const oApple = "gaia/fruit/apple"; const oCarob = "gaia/tree/carob"; const oBerryBush = "gaia/fruit/berry_01"; const oDeer = "gaia/fauna_deer"; const oFish = "gaia/fish/generic"; const oSheep = "gaia/fauna_sheep"; const oStoneLarge = "gaia/rock/mediterranean_large"; const oStoneSmall = "gaia/rock/mediterranean_small"; const oMetalLarge = "gaia/ore/mediterranean_large"; const aGrass = "actor|props/flora/grass_soft_large_tall.xml"; const aGrassShort = "actor|props/flora/grass_soft_large.xml"; const aReeds = "actor|props/flora/reeds_pond_lush_a.xml"; const aLillies = "actor|props/flora/water_lillies.xml"; const aRockLarge = "actor|geology/stone_granite_large.xml"; const aRockMedium = "actor|geology/stone_granite_med.xml"; const aBushMedium = "actor|props/flora/bush_medit_me.xml"; const aBushSmall = "actor|props/flora/bush_medit_sm.xml"; const pForestP = [tForestFloorP + TERRAIN_SEPARATOR + oPoplar, tForestFloorP]; const pForestC = [tForestFloorC + TERRAIN_SEPARATOR + oCarob, tForestFloorC]; var heightSeaGround = -3; var heightShallow = -1.5; var heightShore = 2; var heightLand = 3; var g_Map = new RandomMap(heightSeaGround, tWater); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); const mapBounds = g_Map.getBounds(); var clPlayer = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clLand = g_Map.createTileClass(); var clRiver = g_Map.createTileClass(); var clShallow = g_Map.createTileClass(); g_Map.log("Create the continent body"); var startAngle = randomAngle(); var continentCenter = new Vector2D(fractionToTiles(0.5), fractionToTiles(0.7)).rotateAround(startAngle, mapCenter).round(); createArea( new ChainPlacer( 2, Math.floor(scaleByMapSize(5, 12)), Math.floor(scaleByMapSize(60, 700)), Infinity, continentCenter, 0, [Math.floor(fractionToTiles(0.49))]), [ new TerrainPainter(tGrass), new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), new TileClassPainter(clLand) ]); var playerIDs = sortAllPlayers(); var playerPosition = playerPlacementArcs( playerIDs, continentCenter, fractionToTiles(0.35), -startAngle - 0.5 * Math.PI, 0, 0.65 * Math.PI); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "Walls": false, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oPoplar, "count": 2 }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(20); paintRiver({ "parallel": true, "constraint": stayClasses(clLand, 0), "start": new Vector2D(mapCenter.x, mapBounds.top).rotateAround(startAngle, mapCenter), "end": new Vector2D(mapCenter.x, mapBounds.bottom).rotateAround(startAngle, mapCenter), "width": fractionToTiles(0.07), "fadeDist": scaleByMapSize(3, 12), "deviation": 1, "heightRiverbed": heightSeaGround, "heightLand": heightShore, "meanderShort": 12, "meanderLong": 0, "waterFunc": (position, height, z) => { clRiver.add(position); createTerrain(tWater).place(position); if (height < heightShallow && ( z > 0.3 && z < 0.4 || z > 0.5 && z < 0.6 || z > 0.7 && z < 0.8)) { g_Map.setHeight(position, heightShallow); clShallow.add(position); } } }); paintTerrainBasedOnHeight(1, 3, 0, tShore); paintTerrainBasedOnHeight(-8, 1, 2, tWater); createBumps([avoidClasses(clPlayer, 20, clRiver, 1), stayClasses(clLand, 3)]); var [forestTrees, stragglerTrees] = getTreeCounts(500, 3000, 0.7); createForests( [tGrass, tForestFloorP, tForestFloorC, pForestC, pForestP], [avoidClasses(clPlayer, 20, clForest, 17, clRiver, 1), stayClasses(clLand, 7)], clForest, forestTrees); Engine.SetProgress(50); g_Map.log("Creating dirt patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [[tGrass,tGrassA],[tGrassA,tGrassB], [tGrassB,tGrassC]], [1,1], [avoidClasses(clForest, 0, clDirt, 3, clPlayer, 8, clRiver, 1), stayClasses(clLand, 7)], scaleByMapSize(15, 45), clDirt); g_Map.log("Creating grass patches"); createPatches( [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)], tGrassPatch, [avoidClasses(clForest, 0, clDirt, 3, clPlayer, 8, clRiver, 1), stayClasses(clLand, 7)], scaleByMapSize(15, 45), clDirt); Engine.SetProgress(55); g_Map.log("Creating stone mines"); createMines( [ [new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], [avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clRiver, 1), stayClasses(clLand, 5)], clRock); g_Map.log("Creating metal mines"); createMines( [ [new SimpleObject(oMetalLarge, 1,1, 0,4)] ], [avoidClasses(clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clRiver, 1), stayClasses(clLand, 5)], clMetal ); Engine.SetProgress(65); createDecoration( [ [new SimpleObject(aRockMedium, 1, 3, 0, 1)], [new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)], [new SimpleObject(aGrassShort, 1, 2, 0, 1)], [new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3, 6, 1.2, 2.5)], [new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)] ], [ scaleByMapAreaAbsolute(16), scaleByMapAreaAbsolute(8), scaleByMapAreaAbsolute(13), scaleByMapAreaAbsolute(13), scaleByMapAreaAbsolute(13) ], [avoidClasses(clPlayer, 1, clDirt, 1, clRiver, 1), stayClasses(clLand, 6)]); g_Map.log("Create water decoration in the shallow parts"); createDecoration( [ [new SimpleObject(aReeds, 1, 3, 0, 1)], [new SimpleObject(aLillies, 1, 2, 0, 1)] ], [ scaleByMapAreaAbsolute(800), scaleByMapAreaAbsolute(800) ], stayClasses(clShallow, 0)); Engine.SetProgress(70); createFood( [ [new SimpleObject(oDeer, 5, 7, 0, 4)], [new SimpleObject(oSheep, 2, 3, 0, 2)] ], [ 3 * numPlayers, 3 * numPlayers ], [avoidClasses(clForest, 0, clPlayer, 20, clFood, 20, clRiver, 1), stayClasses(clLand, 3)], clFood); createFood( [ [new SimpleObject(oBerryBush, 5, 7, 0, 4)] ], [ randIntInclusive(1, 4) * numPlayers + 2 ], [avoidClasses(clForest, 0, clPlayer, 20, clFood, 10, clRiver, 1), stayClasses(clLand, 3)], clFood); createFood( [ [new SimpleObject(oFish, 2, 3, 0, 2)] ], [ 25 * numPlayers ], avoidClasses(clLand, 2, clRiver, 1), clFood); Engine.SetProgress(85); createStragglerTrees( [oPoplar, oCarob, oApple], [avoidClasses(clForest, 1, clPlayer, 9, clMetal, 6, clRock, 6, clRiver, 1), stayClasses(clLand, 7)], clForest, stragglerTrees); placePlayersNomad( clPlayer, new AndConstraint([ stayClasses(clLand, 4), avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clFood, 2)])); setSkySet("cumulus"); setWaterColor(0.2,0.312,0.522); setWaterTint(0.1,0.1,0.8); setWaterWaviness(4.0); setWaterType("lake"); setWaterMurkiness(0.73); setFogFactor(0.3); setFogThickness(0.25); setPPEffect("hdr"); setPPContrast(0.62); setPPSaturation(0.51); setPPBloom(0.12); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/lake.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/lake.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/lake.js (revision 26381) @@ -1,252 +1,252 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); setSelectedBiome(); const tMainTerrain = g_Terrains.mainTerrain; const tForestFloor1 = g_Terrains.forestFloor1; const tForestFloor2 = g_Terrains.forestFloor2; const tCliff = g_Terrains.cliff; const tTier1Terrain = g_Terrains.tier1Terrain; const tTier2Terrain = g_Terrains.tier2Terrain; const tTier3Terrain = g_Terrains.tier3Terrain; const tHill = g_Terrains.hill; const tRoad = g_Terrains.road; const tRoadWild = g_Terrains.roadWild; const tTier4Terrain = g_Terrains.tier4Terrain; const tShore = g_Terrains.shore; const tWater = g_Terrains.water; const oTree1 = g_Gaia.tree1; const oTree2 = g_Gaia.tree2; const oTree3 = g_Gaia.tree3; const oTree4 = g_Gaia.tree4; const oTree5 = g_Gaia.tree5; const oFruitBush = g_Gaia.fruitBush; const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal; const oFish = g_Gaia.fish; const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal; const oStoneLarge = g_Gaia.stoneLarge; const oStoneSmall = g_Gaia.stoneSmall; const oMetalLarge = g_Gaia.metalLarge; const oMetalSmall = g_Gaia.metalSmall; const aGrass = g_Decoratives.grass; const aGrassShort = g_Decoratives.grassShort; const aRockLarge = g_Decoratives.rockLarge; const aRockMedium = g_Decoratives.rockMedium; const aBushMedium = g_Decoratives.bushMedium; const aBushSmall = g_Decoratives.bushSmall; const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2]; const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1]; const heightSeaGround = -3; const heightLand = 3; var g_Map = new RandomMap(heightLand, tMainTerrain); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); g_Map.log("Preventing water in player territory"); for (let i = 0; i < numPlayers; ++i) addCivicCenterAreaToClass(playerPosition[i], clPlayer); g_Map.log("Creating the lake..."); createArea( new ChainPlacer( 2, Math.floor(scaleByMapSize(5, 16)), Math.floor(scaleByMapSize(35, 200)), Infinity, mapCenter, 0, [Math.floor(fractionToTiles(0.2))]), [ new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4), new TileClassPainter(clWater) ], avoidClasses(clPlayer, 20)); g_Map.log("Creating more shore jaggedness"); createAreas( new ChainPlacer(2, Math.floor(scaleByMapSize(4, 6)), 3, Infinity), [ new LayeredPainter([tCliff, tHill], [2]), new TileClassUnPainter(clWater) ], borderClasses(clWater, 4, 7), scaleByMapSize(12, 130) * 2, 150); paintTerrainBasedOnHeight(2.4, 3.4, 3, tMainTerrain); paintTerrainBasedOnHeight(1, 2.4, 0, tShore); paintTerrainBasedOnHeight(-8, 1, 2, tWater); paintTileClassBasedOnHeight(-6, 0, 1, clWater); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], // PlayerTileClass marked above "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oFruitBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oTree1, "count": 5 }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(20); createBumps(avoidClasses(clWater, 2, clPlayer, 20)); if (randBool()) createHills([tMainTerrain, tCliff, tHill], avoidClasses(clPlayer, 20, clHill, 15, clWater, 2), clHill, scaleByMapSize(1, 4) * numPlayers); else createMountains(tCliff, avoidClasses(clPlayer, 20, clHill, 15, clWater, 2), clHill, scaleByMapSize(1, 4) * numPlayers); const [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(1)); createDefaultForests( [tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2], avoidClasses(clPlayer, 20, clForest, 17, clHill, 0, clWater, 2), clForest, forestTrees); Engine.SetProgress(50); g_Map.log("Creating dirt patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [[tMainTerrain,tTier1Terrain],[tTier1Terrain,tTier2Terrain], [tTier2Terrain,tTier3Terrain]], [1,1], avoidClasses(clWater, 3, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45), clDirt); g_Map.log("Creating grass patches"); createPatches( [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)], tTier4Terrain, avoidClasses(clWater, 3, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(55); g_Map.log("Creating metal mines"); createBalancedMetalMines( oMetalSmall, oMetalLarge, clMetal, avoidClasses(clWater, 3, clForest, 1, clPlayer, scaleByMapSize(20, 35), clHill, 1) ); g_Map.log("Creating stone mines"); createBalancedStoneMines( oStoneSmall, oStoneLarge, clRock, avoidClasses(clWater, 3, clForest, 1, clPlayer, scaleByMapSize(20, 35), clHill, 1, clMetal, 10) ); Engine.SetProgress(65); var planetm = 1; if (currentBiome() == "generic/india") planetm = 8; createDecoration( [ [new SimpleObject(aRockMedium, 1, 3, 0, 1)], [new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)], [new SimpleObject(aGrassShort, 1, 2, 0, 1)], [new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3, 6, 1.2, 2.5)], [new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)] ], [ scaleByMapAreaAbsolute(16), scaleByMapAreaAbsolute(8), planetm * scaleByMapAreaAbsolute(13), planetm * scaleByMapAreaAbsolute(13), planetm * scaleByMapAreaAbsolute(13) ], avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0)); Engine.SetProgress(70); createFood( [ [new SimpleObject(oMainHuntableAnimal, 5, 7, 0, 4)], [new SimpleObject(oSecondaryHuntableAnimal, 2, 3, 0, 2)] ], [ 3 * numPlayers, 3 * numPlayers ], avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 20), clFood); createFood( [ [new SimpleObject(oFruitBush, 5, 7, 0, 4)] ], [ 3 * numPlayers ], avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 10), clFood); createFood( [ [new SimpleObject(oFish, 2, 3, 0, 2)] ], [ 25 * numPlayers ], [avoidClasses(clFood, 20), stayClasses(clWater, 6)], clFood); Engine.SetProgress(85); createStragglerTrees( [oTree1, oTree2, oTree4, oTree3], avoidClasses(clWater, 5, clForest, 7, clHill, 1, clPlayer, 12, clMetal, 6, clRock, 6), clForest, stragglerTrees); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clHill, 2, clForest, 1, clMetal, 4, clRock, 4, clFood, 2)); setWaterWaviness(4.0); setWaterType("lake"); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/lower_nubia.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/lower_nubia.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/lower_nubia.js (revision 26381) @@ -1,419 +1,419 @@ /** * Heightmap image source: * Imagery by Jesse Allen, NASA's Earth Observatory, * using data from the General Bathymetric Chart of the Oceans (GEBCO) * produced by the British Oceanographic Data Centre. * https://visibleearth.nasa.gov/view.php?id=73934 * https://visibleearth.nasa.gov/view.php?id=74393 * Licensing: Public Domain, https://visibleearth.nasa.gov/useterms.php * * Since the elevation does not correlate with water distribution in lower_nubia, * this map additionally uses composite photography to paint the water correctly. * * To reproduce the heightmaps, first set the coordinates: * lat=23.25; lon=31.75; width=6; * 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") * * The land heightmap image is reproduced using: * wget https://eoimages.gsfc.nasa.gov/images/imagerecords/73000/73934/gebco_08_rev_elev_C1_grey_geo.tif * gdal_translate -projwin $lon2 $lat2 $lon1 $lat1 gebco_08_rev_elev_C1_grey_geo.tif lower_nubia.tif * convert lower_nubia.tif -resize 512 -contrast-stretch 0 lower_nubia_heightmap.png * convert lower_nubia_heightmap.png -threshold 25% lower_nubia_land_threshold.png * * The watermap image is reproduced using: * wget https://eoimages.gsfc.nasa.gov/images/imagerecords/74000/74393/world.topo.200407.3x21600x21600.C1.jpg * gdal_translate -a_srs EPSG:4326 -a_ullr 0 90 90 0 world.topo.200407.3x21600x21600.C1.jpg world.topo.200407.3x21600x21600.C1.jpg.tif * gdal_translate -projwin $lon2 $lat2 $lon1 $lat1 world.topo.200407.3x21600x21600.C1.jpg.tif lower_nubia_water.tif * convert lower_nubia_water.tif -set colorspace Gray -resize 512 -separate -average -threshold 51% lower_nubia_water_threshold.png * * No further changes should be applied to the images to keep them easily interchangeable. */ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); TILE_CENTERED_HEIGHT_MAP = true; const tSand = "desert_sand_dunes_100"; const tPlateau = ["savanna_dirt_a", "savanna_dirt_b"]; const tNilePlants = "desert_plants_a"; const tCliffUpper = ["medit_cliff_italia", "medit_cliff_italia", "medit_cliff_italia_grass"]; const tRoad = "savanna_tile_a"; const tWater = "desert_sand_wet"; const oAcacia = "gaia/tree/acacia"; const oTreeDead = "gaia/tree/dead"; const oBushBadlands = "gaia/tree/bush_badlands"; const oBerryBush = "gaia/fruit/berry_05"; const oPalms = [ "gaia/tree/cretan_date_palm_tall", "gaia/tree/cretan_date_palm_short", "gaia/tree/palm_tropic", "gaia/tree/date_palm", "gaia/tree/senegal_date_palm", "gaia/tree/medit_fan_palm" ]; const oStoneLarge = "gaia/rock/savanna_large"; const oStoneSmall = "gaia/rock/desert_small"; const oMetalLarge = "gaia/ore/savanna_large"; const oMetalSmall = "gaia/ore/desert_small"; const oWoodTreasure = "gaia/treasure/wood"; const oGazelle = "gaia/fauna_gazelle"; const oElephant = "gaia/fauna_elephant_african_bush"; const oElephantInfant = "gaia/fauna_elephant_african_infant"; const oLion = "gaia/fauna_lion"; const oLioness = "gaia/fauna_lioness"; const oHawk = "birds/buzzard"; const oPyramid = "structures/kush/pyramid_large"; const aRock = actorTemplate("geology/stone_savanna_med"); const aBushes = [ "props/flora/bush_dry_a", "props/flora/bush_medit_la_dry", "props/flora/bush_medit_me_dry", "props/flora/bush_medit_sm", "props/flora/bush_medit_sm_dry", "props/flora/bush_tempe_me_dry", "props/flora/grass_soft_dry_large_tall", "props/flora/grass_soft_dry_small_tall" ].map(actorTemplate); const heightScale = num => num * g_MapSettings.Size / 320; const heightSeaGround = heightScale(-3); const heightWaterLevel = heightScale(0); const heightNileForests = heightScale(15); const heightPlateau2 = heightScale(38); const minHeight = -3; const maxHeight = 150; const g_Map = new RandomMap(0, tSand); const mapCenter = g_Map.getCenter(); const mapBounds = g_Map.getBounds(); const clWater = g_Map.createTileClass(); const clCliff = g_Map.createTileClass(); const clPlayer = g_Map.createTileClass(); const clBaseResource = g_Map.createTileClass(); const clForest = g_Map.createTileClass(); const clRock = g_Map.createTileClass(); const clMetal = g_Map.createTileClass(); const clFood = g_Map.createTileClass(); const clPyramid = g_Map.createTileClass(); const clPassage = g_Map.createTileClass(); g_Map.log("Loading heightmaps"); const heightmapLand = convertHeightmap1Dto2D(Engine.LoadHeightmapImage("maps/random/lower_nubia_heightmap.png")); const heightmapLandThreshold = convertHeightmap1Dto2D(Engine.LoadHeightmapImage("maps/random/lower_nubia_land_threshold.png")); const heightmapWaterThreshold = convertHeightmap1Dto2D(Engine.LoadHeightmapImage("maps/random/lower_nubia_water_threshold.png")); Engine.SetProgress(3); g_Map.log("Composing heightmap"); var heightmapCombined = []; for (let x = 0; x < heightmapLand.length; ++x) { heightmapCombined[x] = new Float32Array(heightmapLand.length); for (let y = 0; y < heightmapLand.length; ++y) // Reduce ahistorical Lake Nasser and lakes in the valleys west of the Nile. // The heightmap does not correlate with water distribution in this arid climate at all. heightmapCombined[x][y] = heightmapLandThreshold[x][y] || heightmapWaterThreshold[x][y] ? heightmapLand[x][y] : minHeight; } Engine.SetProgress(6); g_Map.log("Applying heightmap"); createArea( new MapBoundsPlacer(), new HeightmapPainter(heightmapCombined, minHeight, maxHeight)); Engine.SetProgress(9); g_Map.log("Lowering sea ground"); createArea( new MapBoundsPlacer(), [ new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 3), new TileClassPainter(clWater) ], new HeightConstraint(-Infinity, heightSeaGround)); Engine.SetProgress(15); g_Map.log("Creating Nile passages"); const riverAngle = Math.PI * 3 / 4; for (let i = 0; i < scaleByMapSize(8, 15); ++i) { let x = fractionToTiles(randFloat(0, 1)); createArea( new PathPlacer( new Vector2D(x, mapBounds.bottom).rotateAround(riverAngle, mapCenter), new Vector2D(x, mapBounds.top).rotateAround(riverAngle, mapCenter), scaleByMapSize(5, 7), 0.2, 5, 0.2, 0, Infinity), [ new ElevationBlendingPainter(heightNileForests, 0.5), new SmoothingPainter(2, 1, 2), new TileClassPainter(clPassage) ], [ new NearTileClassConstraint(clWater, 4), avoidClasses(clPassage, scaleByMapSize(15, 25)) ]); } Engine.SetProgress(18); g_Map.log("Smoothing heightmap"); createArea( new MapBoundsPlacer(), new SmoothingPainter(1, scaleByMapSize(0.5, 1), 1)); Engine.SetProgress(22); g_Map.log("Marking water"); createArea( new MapBoundsPlacer(), new TileClassPainter(clWater), new HeightConstraint(-Infinity, heightSeaGround)); Engine.SetProgress(28); g_Map.log("Marking cliffs"); createArea( new MapBoundsPlacer(), new TileClassPainter(clCliff), new SlopeConstraint(2, Infinity)); Engine.SetProgress(32); g_Map.log("Painting water and shoreline"); createArea( new MapBoundsPlacer(), new TerrainPainter(tWater), new HeightConstraint(-Infinity, heightWaterLevel)); Engine.SetProgress(35); g_Map.log("Painting plateau"); createArea( new MapBoundsPlacer(), new TerrainPainter(tPlateau), new HeightConstraint(heightPlateau2, Infinity)); Engine.SetProgress(38); var playerIDs = []; var playerPosition = []; if (!isNomad()) { g_Map.log("Finding player locations"); [playerIDs, playerPosition] = playerPlacementRandom(sortAllPlayers(), avoidClasses(clWater, scaleByMapSize(8, 12), clCliff, scaleByMapSize(8, 12))); g_Map.log("Flatten the initial CC area"); for (let position of playerPosition) createArea( new ClumpPlacer(diskArea(defaultPlayerBaseRadius() * 0.8), 0.95, 0.6, Infinity, position), new SmoothElevationPainter(ELEVATION_SET, g_Map.getHeight(position), 6)); } Engine.SetProgress(43); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "baseResourceConstraint": avoidClasses(clCliff, 0, clWater, 0), "CityPatch": { "outerTerrain": tRoad, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { "template": oGazelle, "distance": 18, "minGroupDistance": 2, "maxGroupDistance": 4, "minGroupCount": 2, "maxGroupCount": 3 }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oAcacia, "count": scaleByMapSize(3, 12), "minDistGroup": 2, "maxDistGroup": 6, "minDist": 15, "maxDist": 16 }, "Treasures": { "types": [ { "template": oWoodTreasure, "count": 14 } ] }, "Decoratives": { "template": pickRandom(aBushes) } }); Engine.SetProgress(50); g_Map.log("Painting lower cliffs"); createArea( new MapBoundsPlacer(), new TerrainPainter(tNilePlants), [ new SlopeConstraint(2, Infinity), new NearTileClassConstraint(clWater, 2) ]); Engine.SetProgress(55); g_Map.log("Painting upper cliffs"); createArea( new MapBoundsPlacer(), new TerrainPainter(tCliffUpper), [ avoidClasses(clWater, 2), new SlopeConstraint(2, Infinity) ]); Engine.SetProgress(60); g_Map.log("Creating stone mines"); createMines( [ [new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], [new SimpleObject(oStoneSmall, 3, 6, 1, 3, 0, 2 * Math.PI, 1)] ], avoidClasses(clWater, 4, clCliff, 4, clPlayer, 20, clRock, 10), clRock, scaleByMapSize(10, 30)); Engine.SetProgress(63); g_Map.log("Creating metal mines"); createMines( [ [new SimpleObject(oMetalSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oMetalLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], [new SimpleObject(oMetalSmall, 3, 6, 1, 3, 0, 2 * Math.PI, 1)] ], avoidClasses(clWater, 4, clCliff, 4, clPlayer, 20, clMetal, 10, clRock, 5), clMetal, scaleByMapSize(10, 30)); Engine.SetProgress(67); g_Map.log("Creating pyramid"); createObjectGroups( new SimpleGroup([new SimpleObject(oPyramid, 1, 1, 1, 1)], true, clPyramid), 0, [new NearTileClassConstraint(clWater, 10), avoidClasses(clWater, 6, clCliff, 6, clPlayer, 40, clMetal, 6, clRock, 6)], 1, 500); Engine.SetProgress(70); g_Map.log("Creating trees near the Nile"); createObjectGroups( new SimpleGroup([new RandomObject(oPalms, 1, 2, 1, 1)], true, clForest), 0, [ new NearTileClassConstraint(clWater, scaleByMapSize(1, 8)), new HeightConstraint(heightNileForests, Infinity), avoidClasses(clWater, 0, clCliff, 0, clForest, 1, clPlayer, 12, clBaseResource, 5, clMetal, 4, clRock, 4, clPyramid, 6) ], scaleByMapSize(100, 1000), 200); Engine.SetProgress(73); const avoidCollisions = avoidClasses(clPlayer, 12, clBaseResource, 5, clWater, 1, clForest, 1, clRock, 4, clMetal, 4, clFood, 6, clCliff, 0, clPyramid, 6); g_Map.log("Creating straggler trees and bushes"); var stragglerTreeObjects = [ [new SimpleObject(oAcacia, 1, 1, 0, 0), new SimpleObject(oBushBadlands, 0, 1, 2, 2)], [new SimpleObject(oTreeDead, 1, 1, 0, 0), new SimpleObject(oBushBadlands, 0, 1, 2, 2)] ]; for (let objects of stragglerTreeObjects) createObjectGroups( new SimpleGroup(objects, true, clForest), 0, [avoidCollisions, avoidClasses(clWater, 10, clForest, 4)], scaleByMapSize(10, 180), 10); Engine.SetProgress(77); g_Map.log("Creating gazelles"); createObjectGroups( new SimpleGroup([new SimpleObject(oGazelle, 5, 7, 2, 4)], true, clFood), 0, avoidCollisions, scaleByMapSize(2, 10), 50); Engine.SetProgress(80); if (!isNomad()) { g_Map.log("Creating lions"); createObjectGroups( new SimpleGroup([new SimpleObject(oLion, 1, 2, 2, 4), new SimpleObject(oLioness, 2, 3, 2, 4)], true, clFood), 0, avoidCollisions, scaleByMapSize(2, 10), 50); } Engine.SetProgress(83); g_Map.log("Creating elephants"); createObjectGroups( new SimpleGroup([new SimpleObject(oElephant, 2, 3, 2, 4), new SimpleObject(oElephantInfant, 2, 3, 2, 4)], true, clFood), 0, avoidCollisions, scaleByMapSize(2, 10), 50); Engine.SetProgress(86); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 2, clRock, 4, clMetal, 4, clFood, 2, clCliff, 2, clPyramid, 6)); Engine.SetProgress(90); g_Map.log("Creating hawk"); for (let i = 0; i < scaleByMapSize(0, 2); ++i) g_Map.placeEntityAnywhere(oHawk, 0, mapCenter, randomAngle()); Engine.SetProgress(91); createDecoration( aBushes.map(bush => [new SimpleObject(bush, 0, 3, 2, 4)]), aBushes.map(bush => scaleByMapSize(100, 800) * randIntInclusive(1, 3)), [ new NearTileClassConstraint(clWater, 2), new HeightConstraint(heightWaterLevel, Infinity), avoidClasses(clForest, 0) ]); Engine.SetProgress(92); createDecoration( [[new SimpleObject(aRock, 0, 4, 2, 4)]], [[scaleByMapSize(100, 600)]], avoidClasses(clWater, 0)); Engine.SetProgress(95); setWindAngle(-0.43); setWaterTint(0.161, 0.286, 0.353); setWaterColor(0.129, 0.176, 0.259); setWaterWaviness(8); setWaterMurkiness(0.87); setWaterType("lake"); setAmbientColor(0.58, 0.443, 0.353); setSunColor(0.733, 0.746, 0.574); setSunRotation(Math.PI * 1.1); setSunElevation(Math.PI / 7); setFogFactor(0); setFogThickness(0); setFogColor(0.69, 0.616, 0.541); setPPEffect("hdr"); setPPContrast(0.67); setPPSaturation(0.42); setPPBloom(0.23); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/neareastern_badlands.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/neareastern_badlands.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/neareastern_badlands.js (revision 26381) @@ -1,358 +1,358 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); if (g_MapSettings.Biome) setSelectedBiome(); else setBiome("generic/sahara"); const tPrimary = g_Terrains.mainTerrain; const tCity = g_Terrains.roadWild; const tCityPlaza = g_Terrains.road; const tSand = g_Terrains.tier3Terrain; const tDunes = g_Terrains.tier4Terrain; const tFineSand = g_Terrains.tier2Terrain; const tCliff = g_Terrains.cliff; const tDirt = g_Terrains.dirt; const tForestFloor = "desert_forestfloor_palms"; const tGrass = g_Terrains.forestFloor2; const tGrassSand25 = g_Terrains.shoreBlend; const tShore = g_Terrains.shore; const tWaterDeep = g_Terrains.water; const oBerryBush = "gaia/fruit/grapes"; const oCamel = "gaia/fauna_camel"; const oFish = g_Gaia.fish; const oGazelle = "gaia/fauna_gazelle"; const oGiraffe = "gaia/fauna_giraffe"; const oGoat = "gaia/fauna_goat"; const oWildebeest = "gaia/fauna_wildebeest"; const oStoneLarge = g_Gaia.stoneLarge; const oStoneSmall = g_Gaia.stoneSmall; const oMetalLarge = g_Gaia.metalLarge; const oMetalSmall = g_Gaia.metalSmall; const oOasisTree = "gaia/tree/senegal_date_palm"; const oDatePalm = g_Gaia.tree1; const oSDatePalm = g_Gaia.tree2; const aBush1 = g_Decoratives.bushMedium; const aBush2 = "actor|props/flora/bush_desert_dry_a.xml"; const aBush3 = g_Decoratives.bushSmall; const aBush4 = "actor|props/flora/plant_desert_a.xml"; const aBushes = [aBush1, aBush2, aBush3, aBush4]; const aDecorativeRock = g_Decoratives.rockMedium; const pForest = [tForestFloor + TERRAIN_SEPARATOR + oDatePalm, tForestFloor + TERRAIN_SEPARATOR + oSDatePalm, tForestFloor]; const pForestOasis = [tGrass + TERRAIN_SEPARATOR + oOasisTree, tGrass + TERRAIN_SEPARATOR + oDatePalm, tGrass]; const heightLand = 10; const heightOffsetOasis = -11; const heightOffsetHill1 = 16; const heightOffsetHill2 = 16; const heightOffsetHill3 = 16; const heightOffsetBump = 2; var g_Map = new RandomMap(heightLand, tPrimary); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); var clPlayer = g_Map.createTileClass(); var clHill1 = g_Map.createTileClass(); var clOasis = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clPatch = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var oasisRadius = scaleByMapSize(14, 40); var [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); if (!isNomad()) for (let i = 0; i < numPlayers; ++i) createArea( new ClumpPlacer(diskArea(defaultPlayerBaseRadius()), 0.9, 0.5, Infinity, playerPosition[i]), new TileClassPainter(clPlayer)); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tCity, "innerTerrain": tCityPlaza, "width": 3, "radius": 10 }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oDatePalm } // No decoratives }); Engine.SetProgress(10); g_Map.log("Creating dune patches"); createAreas( new ClumpPlacer(scaleByMapSize(40, 150), 0.2, 0.1, 0), [ new TerrainPainter(tDunes), new TileClassPainter(clPatch) ], avoidClasses(clPatch, 2, clPlayer, 0), scaleByMapSize(5, 20)); Engine.SetProgress(15); g_Map.log("Creating sand patches"); createAreas( new ClumpPlacer(scaleByMapSize(25, 100), 0.2, 0.1, 0), [ new TerrainPainter([tSand, tFineSand]), new TileClassPainter(clPatch) ], avoidClasses(clPatch, 2, clPlayer, 0), scaleByMapSize(15, 50)); Engine.SetProgress(20); g_Map.log("Creating dirt patches"); createAreas( new ClumpPlacer(scaleByMapSize(25, 100), 0.2, 0.1, 0), [ new TerrainPainter([tDirt]), new TileClassPainter(clPatch) ], avoidClasses(clPatch, 2, clPlayer, 0), scaleByMapSize(15, 50)); Engine.SetProgress(25); g_Map.log("Creating oasis"); createArea( new ClumpPlacer(diskArea(oasisRadius), 0.6, 0.15, 0, mapCenter), [ new LayeredPainter([[tSand, pForest], [tGrassSand25, pForestOasis], tGrassSand25, tShore, tWaterDeep], [2, 3, 1, 1]), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetOasis, 8), new TileClassPainter(clOasis) ]); Engine.SetProgress(30); g_Map.log("Creating oasis wildlife"); var num = Math.round(Math.PI * oasisRadius / 8); var constraint = new AndConstraint([borderClasses(clOasis, 0, 3), avoidClasses(clOasis, 0)]); for (var i = 0; i < num; ++i) { let animalPosition; let r = 0; let angle = 2 * Math.PI / num * i; do { // Work outward until constraint met animalPosition = Vector2D.add(mapCenter, new Vector2D(r, 0).rotate(-angle)).round(); ++r; } while (!constraint.allows(animalPosition) && r < mapSize / 2); createObjectGroup( new RandomGroup( [ new SimpleObject(oGiraffe, 2, 4, 0, 3), new SimpleObject(oWildebeest, 3,5, 0,3), new SimpleObject(oGazelle, 5,7, 0,3) ], true, clFood, animalPosition), 0); } g_Map.log("Creating oasis fish"); constraint = new AndConstraint([borderClasses(clOasis, 15, 0), avoidClasses(clFood, 5)]); num = Math.round(Math.PI * oasisRadius / 16); for (var i = 0; i < num; ++i) { let fishPosition; var r = 0; var angle = 2 * Math.PI / num * i; do { // Work outward until constraint met fishPosition = Vector2D.add(mapCenter, new Vector2D(r, 0).rotate(-angle)); ++r; } while (!constraint.allows(fishPosition) && r < mapSize / 2); createObjectGroup(new SimpleGroup([new SimpleObject(oFish, 1, 1, 0, 1)], true, clFood, fishPosition), 0); } Engine.SetProgress(35); g_Map.log("Creating level 1 hills"); var hillAreas = createAreas( new ClumpPlacer(scaleByMapSize(50,300), 0.25, 0.1, 0.5), [ new LayeredPainter([tCliff, tSand], [1]), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetHill1, 1), new TileClassPainter(clHill1) ], avoidClasses(clOasis, 3, clPlayer, 0, clHill1, 10), scaleByMapSize(10,20), 100 ); Engine.SetProgress(40); g_Map.log("Creating small level 1 hills"); hillAreas = hillAreas.concat( createAreas( new ClumpPlacer(scaleByMapSize(25,150), 0.25, 0.1, 0.5), [ new LayeredPainter([tCliff, tSand], [1]), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetHill2, 1), new TileClassPainter(clHill1) ], avoidClasses(clOasis, 3, clPlayer, 0, clHill1, 3), scaleByMapSize(15,25), 100)); Engine.SetProgress(45); g_Map.log("Creating decorative rocks"); createObjectGroupsByAreasDeprecated( new SimpleGroup( [new RandomObject([aDecorativeRock, aBush2, aBush3], 3, 8, 0, 2)], true), 0, borderClasses(clHill1, 0, 3), scaleByMapSize(40,200), 50, hillAreas); Engine.SetProgress(50); g_Map.log("Creating level 2 hills"); createAreasInAreas( new ClumpPlacer(scaleByMapSize(25, 150), 0.25, 0.1, 0), [ new LayeredPainter([tCliff, tSand], [1]), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetHill2, 1) ], [stayClasses(clHill1, 0)], scaleByMapSize(15, 25), 50, hillAreas); Engine.SetProgress(55); g_Map.log("Creating level 3 hills"); createAreas( new ClumpPlacer(scaleByMapSize(12, 75), 0.25, 0.1, 0), [ new LayeredPainter([tCliff, tSand], [1]), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetHill3, 1) ], [stayClasses(clHill1, 0)], scaleByMapSize(15,25), 50 ); Engine.SetProgress(60); g_Map.log("Creating bumps"); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 0), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), avoidClasses(clOasis, 0, clPlayer, 0, clHill1, 2), scaleByMapSize(100, 200) ); Engine.SetProgress(65); g_Map.log("Creating forests"); var [forestTrees, stragglerTrees] = getTreeCounts(500, 2500, 0.5); var num = g_DefaultNumberOfForests; createAreas( new ClumpPlacer(forestTrees / num, 0.15, 0.1, 0.5), [ new TerrainPainter([tSand, pForest]), new TileClassPainter(clForest) ], avoidClasses(clPlayer, 1, clOasis, 10, clForest, 10, clHill1, 1), num, 50); Engine.SetProgress(70); g_Map.log("Creating metal mines"); createBalancedMetalMines( oMetalSmall, oMetalLarge, clMetal, avoidClasses(clOasis, 2, clForest, 0, clPlayer, scaleByMapSize(15, 25), clHill1, 1) ); g_Map.log("Creating stone mines"); createBalancedStoneMines( oStoneSmall, oStoneLarge, clRock, avoidClasses(clOasis, 2, clForest, 0, clPlayer, scaleByMapSize(15, 25), clHill1, 1, clMetal, 10) ); Engine.SetProgress(80); g_Map.log("Creating gazelles"); let group = new SimpleGroup([new SimpleObject(oGazelle, 5,7, 0,4)], true, clFood); createObjectGroupsDeprecated(group, 0, avoidClasses(clOasis, 1, clForest, 0, clPlayer, 5, clHill1, 1, clFood, 10), scaleByMapSize(5,20), 50 ); g_Map.log("Creating goats"); group = new SimpleGroup([new SimpleObject(oGoat, 2,4, 0,3)], true, clFood); createObjectGroupsDeprecated(group, 0, avoidClasses(clOasis, 1, clForest, 0, clPlayer, 5, clHill1, 1, clFood, 10), scaleByMapSize(5,20), 50 ); g_Map.log("Creating camels"); group = new SimpleGroup([new SimpleObject(oCamel, 2,4, 0,2)], true, clFood); createObjectGroupsDeprecated(group, 0, avoidClasses(clOasis, 1, clForest, 0, clPlayer, 5, clHill1, 1, clFood, 10), scaleByMapSize(5,20), 50 ); Engine.SetProgress(85); createStragglerTrees( [oDatePalm, oSDatePalm], avoidClasses(clOasis, 1, clForest, 0, clHill1, 1, clPlayer, 4, clMetal, 6, clRock, 6), clForest, stragglerTrees); Engine.SetProgress(90); g_Map.log("Creating bushes"); group = new SimpleGroup([new RandomObject(aBushes, 2,3, 0,2)]); createObjectGroupsDeprecated(group, 0, avoidClasses(clOasis, 1, clHill1, 1, clPlayer, 0, clForest, 0), scaleByMapSize(16, 262) ); g_Map.log("Creating more decorative rocks"); group = new SimpleGroup([new SimpleObject(aDecorativeRock, 1,2, 0,2)]); createObjectGroupsDeprecated(group, 0, avoidClasses(clOasis, 1, clHill1, 1, clPlayer, 0, clForest, 0), scaleByMapSize(16, 262) ); placePlayersNomad(clPlayer, avoidClasses(clOasis, 4, clForest, 1, clMetal, 4, clRock, 4, clHill1, 4, clFood, 2)); setWaterWaviness(1.0); setWaterType("clap"); setWaterHeight(20); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/phoenician_levant.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/phoenician_levant.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/phoenician_levant.js (revision 26381) @@ -1,332 +1,332 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); //TILE_CENTERED_HEIGHT_MAP = true; const tCity = "medit_city_pavement"; const tCityPlaza = "medit_city_pavement"; const tHill = ["medit_dirt", "medit_dirt_b", "medit_dirt_c", "medit_rocks_grass", "medit_rocks_grass"]; const tMainDirt = "medit_dirt"; const tCliff = "medit_cliff_aegean"; const tForestFloor = "medit_rocks_shrubs"; const tGrass = "medit_rocks_grass"; const tRocksShrubs = "medit_rocks_shrubs"; const tRocksGrass = "medit_rocks_grass"; const tDirt = "medit_dirt_b"; const tDirtB = "medit_dirt_c"; const tShore = "medit_sand"; const tWater = "medit_sand_wet"; const oGrapeBush = "gaia/fruit/grapes"; const oDeer = "gaia/fauna_deer"; const oFish = "gaia/fish/generic"; const oSheep = "gaia/fauna_sheep"; const oGoat = "gaia/fauna_goat"; const oStoneLarge = "gaia/rock/mediterranean_large"; const oStoneSmall = "gaia/rock/mediterranean_small"; const oMetalLarge = "gaia/ore/mediterranean_large"; const oDatePalm = "gaia/tree/cretan_date_palm_short"; const oSDatePalm = "gaia/tree/cretan_date_palm_tall"; const oCarob = "gaia/tree/carob"; const oFanPalm = "gaia/tree/medit_fan_palm"; const oPoplar = "gaia/tree/poplar_lombardy"; const oCypress = "gaia/tree/cypress"; const aBush1 = "actor|props/flora/bush_medit_sm.xml"; const aBush2 = "actor|props/flora/bush_medit_me.xml"; const aBush3 = "actor|props/flora/bush_medit_la.xml"; const aBush4 = "actor|props/flora/bush_medit_me.xml"; const aDecorativeRock = "actor|geology/stone_granite_med.xml"; const pForest = [tForestFloor + TERRAIN_SEPARATOR + oDatePalm, tForestFloor + TERRAIN_SEPARATOR + oSDatePalm, tForestFloor + TERRAIN_SEPARATOR + oCarob, tForestFloor, tForestFloor]; const heightSeaGround = -3; const heightShore = -1.5; const heightLand = 1; const heightIsland = 6; const heightHill = 15; const heightOffsetBump = 2; var g_Map = new RandomMap(heightLand, tHill); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); const mapBounds = g_Map.getBounds(); var clPlayer = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clGrass = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clIsland = g_Map.createTileClass(); var startAngle = randIntInclusive(0, 3) * Math.PI / 2; placePlayerBases({ "PlayerPlacement": [ sortAllPlayers(), playerPlacementLine(Math.PI / 2, new Vector2D(fractionToTiles(0.76), mapCenter.y), fractionToTiles(0.2)).map(pos => pos.rotateAround(startAngle, mapCenter)) ], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tCityPlaza, "innerTerrain": tCity }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oGrapeBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oCarob, "count": 2 }, "Decoratives": { "template": aBush1 } }); Engine.SetProgress(30); paintRiver({ "parallel": true, "start": new Vector2D(mapBounds.left, mapBounds.top).rotateAround(startAngle, mapCenter), "end": new Vector2D(mapBounds.left, mapBounds.bottom).rotateAround(startAngle, mapCenter), "width": mapSize, "fadeDist": scaleByMapSize(6, 25), "deviation": 0, "heightRiverbed": heightSeaGround, "heightLand": heightLand, "meanderShort": 20, "meanderLong": 0 }); Engine.SetProgress(40); paintTileClassBasedOnHeight(-Infinity, heightLand, Elevation_ExcludeMin_ExcludeMax, clWater); paintTerrainBasedOnHeight(-Infinity, heightShore, Elevation_ExcludeMin_ExcludeMax, tWater); paintTerrainBasedOnHeight(heightShore, heightLand, Elevation_ExcludeMin_ExcludeMax, tShore); g_Map.log("Creating bumps"); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, Infinity), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), avoidClasses(clWater, 2, clPlayer, 20), scaleByMapSize(100, 200)); g_Map.log("Creating hills"); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(16, 40)), 0.5), [ new LayeredPainter([tCliff, tHill], [2]), new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), new TileClassPainter(clHill) ], avoidClasses(clPlayer, 20, clForest, 1, clHill, 15, clWater, 0), scaleByMapSize(1, 4) * numPlayers * 3); g_Map.log("Creating forests"); var [forestTrees, stragglerTrees] = getTreeCounts(500, 2500, 0.5); var num = scaleByMapSize(10,42); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), forestTrees / (num * Math.floor(scaleByMapSize(2, 5))), 0.5), [ new TerrainPainter([tForestFloor, pForest]), new TileClassPainter(clForest) ], avoidClasses(clPlayer, 20, clForest, 10, clWater, 1, clHill, 1, clBaseResource, 3), num, 50); Engine.SetProgress(50); g_Map.log("Creating grass patches"); for (let size of [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)]) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5), [ new LayeredPainter( [[tGrass, tRocksShrubs], [tRocksShrubs, tRocksGrass], [tRocksGrass, tGrass]], [1, 1]), new TileClassPainter(clDirt) ], avoidClasses(clForest, 0, clGrass, 5, clPlayer, 10, clWater, 4, clDirt, 5, clHill, 1), scaleByMapSize(15, 45)); Engine.SetProgress(55); g_Map.log("Creating dirt patches"); for (let size of [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)]) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5), [ new LayeredPainter( [[tDirt, tDirtB], [tDirt, tMainDirt], [tDirtB, tMainDirt]], [1, 1]), new TileClassPainter(clDirt) ], avoidClasses(clForest, 0, clDirt, 5, clPlayer, 10, clWater, 4, clGrass, 5, clHill, 1), scaleByMapSize(15, 45)); Engine.SetProgress(60); g_Map.log("Creating cyprus"); createAreas( new ClumpPlacer(diskArea(fractionToTiles(0.08)), 0.2, 0.1, 0.01), [ new LayeredPainter([tShore, tHill], [12]), new SmoothElevationPainter(ELEVATION_SET, heightIsland, 8), new TileClassPainter(clIsland), new TileClassUnPainter(clWater) ], [stayClasses (clWater, 8)], 1, 100); g_Map.log("Creating cyprus mines"); var mines = [ new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], true, clRock), new SimpleGroup([new SimpleObject(oMetalLarge, 1, 1, 0, 4)], true, clMetal), new SimpleGroup([new SimpleObject(oStoneSmall, 2, 5, 1, 3)], true, clRock) ]; for (let mine of mines) createObjectGroups( mine, 0, [ stayClasses(clIsland, 9), avoidClasses(clForest, 1, clRock, 8, clMetal, 8) ], scaleByMapSize(4, 16)); g_Map.log("Creating stone mines"); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clWater, 3, clHill, 1), scaleByMapSize(4,16), 100 ); g_Map.log("Creating small stone quarries"); group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clWater, 3, clHill, 1), scaleByMapSize(4,16), 100 ); g_Map.log("Creating metal mines"); group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4)], true, clMetal); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clWater, 3, clHill, 1), scaleByMapSize(4,16), 100 ); Engine.SetProgress(65); g_Map.log("Creating small decorative rocks"); group = new SimpleGroup( [new SimpleObject(aDecorativeRock, 1,3, 0,1)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clWater, 1, clForest, 0, clPlayer, 0, clHill, 1), scaleByMapSize(16, 262), 50 ); g_Map.log("Creating shrubs"); group = new SimpleGroup( [new SimpleObject(aBush2, 1,2, 0,1), new SimpleObject(aBush1, 1,3, 0,2), new SimpleObject(aBush4, 1,2, 0,1), new SimpleObject(aBush3, 1,3, 0,2)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clWater, 3, clPlayer, 0, clHill, 1), scaleByMapSize(40, 360), 50 ); Engine.SetProgress(70); g_Map.log("Creating fish"); group = new SimpleGroup([new SimpleObject(oFish, 1,3, 2,6)], true, clFood); createObjectGroupsDeprecated(group, 0, [avoidClasses(clIsland, 2, clFood, 10), stayClasses(clWater, 5)], 3*scaleByMapSize(5,20), 50 ); g_Map.log("Creating sheeps"); group = new SimpleGroup([new SimpleObject(oSheep, 5,7, 0,4)], true, clFood); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 7, clWater, 3, clFood, 10, clHill, 1), scaleByMapSize(5,20), 50 ); g_Map.log("Creating goats"); group = new SimpleGroup([new SimpleObject(oGoat, 2,4, 0,3)], true, clFood); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 7, clWater, 3, clFood, 10, clHill, 1), scaleByMapSize(5,20), 50 ); g_Map.log("Creating deers"); group = new SimpleGroup([new SimpleObject(oDeer, 2,4, 0,2)], true, clFood); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 7, clWater, 3, clFood, 10, clHill, 1), scaleByMapSize(5,20), 50 ); g_Map.log("Creating grape bushes"); group = new SimpleGroup( [new SimpleObject(oGrapeBush, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 0, clPlayer, 15, clHill, 1, clFood, 7), randIntInclusive(1, 4) * numPlayers + 2, 50 ); Engine.SetProgress(90); var stragglerTreeConfig = [ [1, avoidClasses(clForest, 0, clWater, 4, clPlayer, 8, clMetal, 6, clHill, 1)], [3, [stayClasses(clIsland, 9), avoidClasses(clRock, 4, clMetal, 4)]] ]; for (let [amount, constraint] of stragglerTreeConfig) createStragglerTrees( [oDatePalm, oSDatePalm, oCarob, oFanPalm, oPoplar, oCypress], constraint, clForest, amount * stragglerTrees); setSkySet("sunny"); setSunColor(0.917, 0.828, 0.734); setWaterColor(0.263,0.314,0.631); setWaterTint(0.133, 0.725,0.855); setWaterWaviness(2.0); setWaterType("ocean"); setWaterMurkiness(0.8); setAmbientColor(0.447059, 0.509804, 0.54902); setSunElevation(0.671884); setSunRotation(-0.582913); setFogFactor(0.2); setFogThickness(0.15); setFogColor(0.8, 0.7, 0.6); setPPEffect("hdr"); setPPContrast(0.53); setPPSaturation(0.47); setPPBloom(0.52); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/hellas.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/hellas.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/hellas.js (revision 26381) @@ -1,559 +1,559 @@ /** * Heightmap image source: * Imagery by Jesse Allen, NASA's Earth Observatory, * using data from the General Bathymetric Chart of the Oceans (GEBCO) * produced by the British Oceanographic Data Centre. * https://visibleearth.nasa.gov/view.php?id=73934 * * Licensing: Public Domain, https://visibleearth.nasa.gov/useterms.php * * The heightmap image is reproduced using: * wget https://eoimages.gsfc.nasa.gov/images/imagerecords/73000/73934/gebco_08_rev_elev_C1_grey_geo.tif * lat=37; lon=23; width=7; # including crete * gdal_translate -projwin $((lon-width/2)) $((lat+width/2)) $((lon+width/2)) $((lat-width/2)) gebco_08_rev_elev_C1_grey_geo.tif hellas.tif * convert hellas.tif -contrast-stretch 0 hellas.png * No further changes should be applied to the image to keep it easily interchangeable. */ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); TILE_CENTERED_HEIGHT_MAP = true; var mapStyles = [ // mainland { "minMapSize": 0, "enabled": randBool(0.15), "landRatio": [0.95, 1] }, // lots of water { "minMapSize": 384, "enabled": randBool(1/4), "landRatio": [0.3, 0.5] }, // few water { "minMapSize": 192, "enabled": true, "landRatio": [0.65, 0.9] } ]; const heightmapHellas = convertHeightmap1Dto2D(Engine.LoadHeightmapImage("maps/random/hellas.png")); const biomes = Engine.ReadJSONFile("maps/random/hellas_biomes.json"); const heightScale = num => num * g_MapSettings.Size / 320; const heightSeaGround = heightScale(-6); const heightReedsMin = heightScale(-2); const heightReedsMax = heightScale(-0.5); const heightShoreline = heightScale(1); const heightLowlands = heightScale(30); const heightHighlands = heightScale(60); const heightmapMin = 0; const heightmapMax = 100; var g_Map = new RandomMap(0, biomes.lowlands.terrains.main); var mapSize = g_Map.getSize(); var mapCenter = g_Map.getCenter(); var numPlayers = getNumPlayers(); var clWater; var clCliffs; var clPlayer = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clDock = g_Map.createTileClass(); var constraintLowlands = new HeightConstraint(heightShoreline, heightLowlands); var constraintHighlands = new HeightConstraint(heightLowlands, heightHighlands); var constraintMountains = new HeightConstraint(heightHighlands, Infinity); var [minLandRatio, maxLandRatio] = mapStyles.filter(mapStyle => mapSize >= mapStyle.minMapSize).sort((a, b) => a.enabled - b.enabled).pop().landRatio; var [minCliffRatio, maxCliffRatio] = [maxLandRatio < 0.75 ? 0 : 0.08, 0.18]; var playerIDs = sortAllPlayers(); var playerPosition; // Pick a random subset of the heightmap that meets the mapStyle and has space for all players var subAreaSize; var subAreaTopLeft; while (true) { subAreaSize = Math.floor(randFloat(0.01, 0.2) * heightmapHellas.length); subAreaTopLeft = new Vector2D(randFloat(0, 1), randFloat(0, 1)).mult(heightmapHellas.length - subAreaSize).floor(); let heightmap = extractHeightmap(heightmapHellas, subAreaTopLeft, subAreaSize); let heightmapPainter = new HeightmapPainter(heightmap, heightmapMin, heightmapMax); // Quick area test let points = new DiskPlacer(heightmap.length / 2 - MAP_BORDER_WIDTH, new Vector2D(1, 1).mult(heightmap.length / 2)).place(new NullConstraint()); let landArea = 0; for (let point of points) if (heightmapPainter.scaleHeight(heightmap[point.x][point.y]) > heightShoreline) ++landArea; let landRatio = landArea / points.length; g_Map.log("Chosen heightmap at " + uneval(subAreaTopLeft) + " of size " + subAreaSize + ", land-ratio: " + landRatio.toFixed(3)); if (landRatio < minLandRatio || landRatio > maxLandRatio) continue; g_Map.log("Copying heightmap"); createArea( new MapBoundsPlacer(), heightmapPainter); g_Map.log("Measuring land area"); let passableLandArea = createArea( new DiskPlacer(fractionToTiles(0.5), mapCenter), undefined, new HeightConstraint(heightShoreline, Infinity)); if (!passableLandArea) continue; landRatio = passableLandArea.getPoints().length / diskArea(fractionToTiles(0.5)); g_Map.log("Land ratio: " + landRatio.toFixed(3)); if (landRatio < minLandRatio || landRatio > maxLandRatio) continue; g_Map.log("Lowering sea ground"); clWater = g_Map.createTileClass(); createArea( new MapBoundsPlacer(), [ new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 5), new TileClassPainter(clWater) ], new HeightConstraint(-Infinity, heightShoreline)); let cliffsRatio; while (true) { createArea( new DiskPlacer(fractionToTiles(0.5) - MAP_BORDER_WIDTH, mapCenter), new SmoothingPainter(1, 0.5, 1)); Engine.SetProgress(25); clCliffs = g_Map.createTileClass(); // Marking cliffs let cliffsArea = createArea( new MapBoundsPlacer(), new TileClassPainter(clCliffs), [ avoidClasses(clWater, 2), new SlopeConstraint(2, Infinity) ]); cliffsRatio = cliffsArea.getPoints().length / Math.square(g_Map.getSize()); g_Map.log("Smoothing heightmap, cliff ratio: " + cliffsRatio.toFixed(3)); if (cliffsRatio < maxCliffRatio) break; } if (cliffsRatio < minCliffRatio) { g_Map.log("Too few cliffs: " + cliffsRatio); continue; } if (isNomad()) break; g_Map.log("Finding player locations"); let players = playerPlacementRandom( playerIDs, avoidClasses( clCliffs, scaleByMapSize(6, 15), clWater, scaleByMapSize(10, 20))); if (players) { [playerIDs, playerPosition] = players; break; } g_Map.log("Too few player locations, starting over"); } Engine.SetProgress(35); if (!isNomad()) { g_Map.log("Flattening initial CC area"); let playerRadius = defaultPlayerBaseRadius() * 0.8; for (let position of playerPosition) createArea( new ClumpPlacer(diskArea(playerRadius), 0.95, 0.6, Infinity, position), new SmoothElevationPainter(ELEVATION_SET, g_Map.getHeight(position), playerRadius / 2)); Engine.SetProgress(38); } g_Map.log("Painting lowlands"); createArea( new MapBoundsPlacer(), new TerrainPainter(biomes.lowlands.terrains.main), constraintLowlands); Engine.SetProgress(40); g_Map.log("Painting highlands"); createArea( new MapBoundsPlacer(), new TerrainPainter(biomes.highlands.terrains.main), constraintHighlands); Engine.SetProgress(45); g_Map.log("Painting mountains"); createArea( new MapBoundsPlacer(), new TerrainPainter(biomes.common.terrains.cliffs), [ avoidClasses(clWater, 2), constraintMountains ]); Engine.SetProgress(48); g_Map.log("Painting water and shoreline"); createArea( new MapBoundsPlacer(), new TerrainPainter(biomes.water.terrains.main), new HeightConstraint(-Infinity, heightShoreline)); Engine.SetProgress(50); g_Map.log("Painting cliffs"); createArea( new MapBoundsPlacer(), new TerrainPainter(biomes.common.terrains.cliffs), [ avoidClasses(clWater, 2), new SlopeConstraint(2, Infinity) ]); Engine.SetProgress(55); for (let i = 0; i < numPlayers; ++i) { if (isNomad()) break; let localBiome = constraintHighlands.allows(playerPosition[i]) ? biomes.highlands : biomes.lowlands; placePlayerBase({ "playerID": playerIDs[i], "playerPosition": playerPosition[i], "PlayerTileClass": clPlayer, "Walls": "towers", "BaseResourceClass": clBaseResource, "baseResourceConstraint": avoidClasses(clPlayer, 4, clWater, 1, clCliffs, 1), "CityPatch": { "outerTerrain": biomes.common.terrains.roadWild, "innerTerrain": biomes.common.terrains.road }, - "Chicken": { + "StartingAnimal": { "template": localBiome.gaia.fauna.startingAnimal, "groupCount": 1, "minGroupCount": 4, "maxGroupCount": 4 }, "Berries": { "template": localBiome.gaia.flora.fruitBush, "minCount": 3, "maxCount": 3 }, "Mines": { "types": [ { "template": biomes.common.gaia.mines.metalLarge }, { "template": biomes.common.gaia.mines.stoneLarge } ], "minAngle": Math.PI / 2, "maxAngle": Math.PI }, "Trees": { "template": pickRandom(localBiome.gaia.flora.trees), "count": 15 } // No decoratives }); } Engine.SetProgress(60); g_Map.log("Placing docks"); placeDocks( biomes.shoreline.gaia.dock, 0, scaleByMapSize(1, 2) * 100, clWater, clDock, heightReedsMax, heightShoreline, [avoidClasses(clDock, 50), new StaticConstraint(avoidClasses(clPlayer, 30, clCliffs, 8))], 0, 50); Engine.SetProgress(65); let [forestTrees, stragglerTrees] = getTreeCounts(600, 4000, 0.7); let biomeTreeRatioHighlands = 0.4; for (let biome of ["lowlands", "highlands"]) createForests( [ biomes[biome].terrains.main, biomes[biome].terrains.forestFloors[0], biomes[biome].terrains.forestFloors[1], biomes[biome].terrains.forests[0], biomes[biome].terrains.forests[1] ], [ biome == "highlands" ? constraintHighlands : constraintLowlands, avoidClasses(clPlayer, 20, clForest, 18, clCliffs, 1, clWater, 2) ], clForest, forestTrees * (biome == "highlands" ? biomeTreeRatioHighlands : 1 - biomeTreeRatioHighlands)); Engine.SetProgress(70); g_Map.log("Creating stone mines"); var minesStone = [ [new SimpleObject(biomes.common.gaia.mines.stoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], [new SimpleObject(biomes.common.gaia.mines.stoneSmall, 2, 3, 1, 3, 0, 2 * Math.PI, 1)] ]; for (let mine of minesStone) createObjectGroups( new SimpleGroup(mine, true, clRock), 0, [avoidClasses(clForest, 1, clPlayer, 20, clRock, 18, clCliffs, 2, clWater, 2, clDock, 6)], scaleByMapSize(2, 12), 50); Engine.SetProgress(75); g_Map.log("Creating metal mines"); var minesMetal = [ [new SimpleObject(biomes.common.gaia.mines.metalLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], [new SimpleObject(biomes.common.gaia.mines.metalSmall, 2, 3, 1, 3, 0, 2 * Math.PI, 1)] ]; for (let mine of minesMetal) createObjectGroups( new SimpleGroup(mine, true, clMetal), 0, [avoidClasses(clForest, 1, clPlayer, 20, clRock, 8, clMetal, 18, clCliffs, 2, clWater, 2, clDock, 6)], scaleByMapSize(2, 12), 50); Engine.SetProgress(80); for (let biome of ["lowlands", "highlands"]) createStragglerTrees( biomes[biome].gaia.flora.trees, [ biome == "highlands" ? constraintHighlands : constraintLowlands, avoidClasses(clForest, 8, clCliffs, 1, clPlayer, 12, clMetal, 6, clRock, 6, clCliffs, 2, clWater, 2, clDock, 6) ], clForest, stragglerTrees * (biome == "highlands" ? biomeTreeRatioHighlands * 4 : 1 - biomeTreeRatioHighlands)); Engine.SetProgress(85); createFood( [ [new SimpleObject(biomes.highlands.gaia.fauna.horse, 3, 5, 0, 4)], [new SimpleObject(biomes.highlands.gaia.fauna.pony, 2, 3, 0, 4)], [new SimpleObject(biomes.highlands.gaia.flora.fruitBush, 5, 7, 0, 4)] ], [ scaleByMapSize(2, 16), scaleByMapSize(2, 12), scaleByMapSize(2, 20) ], [ avoidClasses(clForest, 0, clPlayer, 20, clFood, 16, clCliffs, 2, clWater, 2, clRock, 4, clMetal, 4, clDock, 6), constraintHighlands ], clFood); Engine.SetProgress(90); createFood( [ [new SimpleObject(biomes.lowlands.gaia.fauna.sheep, 2, 3, 0, 2)], [new SimpleObject(biomes.lowlands.gaia.fauna.rabbit, 2, 3, 0, 2)], [new SimpleObject(biomes.lowlands.gaia.flora.fruitBush, 5, 7, 0, 4)] ], [ scaleByMapSize(2, 16), scaleByMapSize(2, 12), scaleByMapSize(1, 20) ], [ avoidClasses(clForest, 0, clPlayer, 20, clFood, 16, clCliffs, 2, clWater, 2, clRock, 4, clMetal, 4, clDock, 6), constraintLowlands ], clFood); Engine.SetProgress(93); createFood( [ [new SimpleObject(biomes.highlands.gaia.fauna.goat, 3, 5, 0, 4)] ], [ 3 * numPlayers ], [ avoidClasses(clForest, 1, clPlayer, 20, clFood, 20, clCliffs, 1, clRock, 4, clMetal, 4, clDock, 6), constraintMountains ], clFood); g_Map.log("Creating hawk"); for (let i = 0; i < scaleByMapSize(0, 2); ++i) g_Map.placeEntityAnywhere(biomes.highlands.gaia.fauna.hawk, 0, mapCenter, randomAngle()); g_Map.log("Creating fish"); createObjectGroups( new SimpleGroup([new SimpleObject(biomes.water.gaia.fauna.fish, 1, 1, 0, 3)], true, clFood), 0, [stayClasses(clWater, 8), avoidClasses(clFood, 8, clDock, 6)], scaleByMapSize(15, 50), 100); Engine.SetProgress(95); g_Map.log("Creating grass patches"); for (let biome of ["lowlands", "highlands"]) for (let patch of biomes[biome].terrains.patches) createPatches( [scaleByMapSize(3, 7), scaleByMapSize(5, 15)], patch, [ biome == "highlands" ? constraintHighlands : constraintLowlands, avoidClasses(clForest, 0, clDirt, 5, clPlayer, 12, clCliffs, 2, clWater, 2), ], scaleByMapSize(15, 45) / biomes[biome].terrains.patches.length, clDirt); Engine.SetProgress(96); for (let biome of ["lowlands", "highlands"]) { createDecoration( [ [new SimpleObject(actorTemplate(biomes[biome].actors.mushroom), 1, 4, 1, 2)], [ new SimpleObject(actorTemplate(biomes.common.actors.grass), 2, 4, 0, 1.8), new SimpleObject(actorTemplate(biomes.common.actors.grassShort), 3,6, 1.2, 2.5) ], [ new SimpleObject(actorTemplate(biomes.common.actors.bushMedium), 1, 2, 0, 2), new SimpleObject(actorTemplate(biomes.common.actors.bushSmall), 2, 4, 0, 2) ] ], [ scaleByMapAreaAbsolute(20), scaleByMapAreaAbsolute(13), scaleByMapAreaAbsolute(13), scaleByMapAreaAbsolute(13) ], [ biome == "highlands" ? constraintHighlands : constraintLowlands, avoidClasses(clCliffs, 1, clPlayer, 15, clForest, 1, clRock, 4, clMetal, 4), ]); createDecoration( [ biomes[biome].actors.stones.map(template => new SimpleObject(actorTemplate(template), 1, 3, 0, 1)) ], [ biomes[biome].actors.stones.map(template => scaleByMapAreaAbsolute(2) * randIntInclusive(1, 3)) ], [ biome == "highlands" ? constraintHighlands : constraintLowlands, avoidClasses(clWater, 4, clPlayer, 15, clForest, 1, clRock, 4, clMetal, 4), ]); } Engine.SetProgress(98); g_Map.log("Creating temple"); createObjectGroups( new SimpleGroup([new SimpleObject(biomes.highlands.gaia.athen.temple, 1, 1, 0, 0)], true), 0, [ avoidClasses(clCliffs, 4, clWater, 4, clPlayer, 40, clForest, 4, clRock, 4, clMetal, 4), constraintHighlands ], 1, 200); g_Map.log("Creating statues"); createObjectGroups( new SimpleGroup([new SimpleObject(actorTemplate(biomes.lowlands.actors.athen.statue), 1, 1, 0, 0)], true), 0, [ avoidClasses(clCliffs, 2, clWater, 4, clPlayer, 30, clForest, 1, clRock, 8, clMetal, 8, clDock, 6), constraintLowlands ], scaleByMapSize(1, 2), 50); g_Map.log("Creating campfire"); createObjectGroups( new SimpleGroup([new SimpleObject(actorTemplate(biomes.common.actors.campfire), 1, 1, 0, 0)], true), 0, [avoidClasses(clCliffs, 2, clWater, 4, clPlayer, 30, clForest, 1, clRock, 8, clMetal, 8, clDock, 6)], scaleByMapSize(0, 2), 50); g_Map.log("Creating oxybeles"); createObjectGroups( new SimpleGroup([new SimpleObject(biomes.highlands.gaia.athen.oxybeles, 1, 1, 0, 0)], true), 0, [ avoidClasses(clCliffs, 2, clPlayer, 30, clForest, 1, clRock, 4, clMetal, 4), constraintHighlands ], scaleByMapSize(0, 2), 100); g_Map.log("Creating handcart"); createObjectGroups( new SimpleGroup([new SimpleObject(actorTemplate(biomes.highlands.actors.handcart), 1, 1, 0, 0)], true), 0, [ avoidClasses(clCliffs, 1, clPlayer, 15, clForest, 1, clRock, 4, clMetal, 4), constraintHighlands ], scaleByMapSize(1, 4), 50); g_Map.log("Creating water log"); createObjectGroups( new SimpleGroup([new SimpleObject(actorTemplate(biomes.water.actors.waterlog), 1, 1, 0, 0)], true), 0, [stayClasses(clWater, 4)], scaleByMapSize(1, 2), 10); g_Map.log("Creating reeds"); createObjectGroups( new SimpleGroup( [ new SimpleObject(actorTemplate(biomes.shoreline.actors.reeds), 5, 12, 1, 4), new SimpleObject(actorTemplate(biomes.shoreline.actors.lillies), 1, 2, 1, 5) ], false, clDirt), 0, new HeightConstraint(heightReedsMin, heightReedsMax), scaleByMapSize(10, 25), 20); placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clFood, 2, clCliffs, 2, clWater, 15)); Engine.SetProgress(99); setWaterColor(0.024, 0.212, 0.024); setWaterTint(0.133, 0.725, 0.855); setWaterMurkiness(0.8); setWaterWaviness(3); setFogFactor(0); setPPEffect("hdr"); setPPSaturation(0.51); setPPContrast(0.62); setPPBloom(0.12); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/india.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/india.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/india.js (revision 26381) @@ -1,271 +1,271 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); const tGrass1 = "savanna_grass_a"; const tDirt1 = "savanna_dirt_a"; const tDirt4 = "savanna_dirt_b"; const tCityTiles = "savanna_tile_a_dirt_red"; const tShore = "savanna_riparian_bank"; const tWater = "savanna_riparian_wet"; const oTree = "gaia/tree/palm_tropic"; const oBerryBush = "gaia/fruit/berry_01"; const oRabbit = "gaia/fauna_rabbit"; const oTiger = "gaia/fauna_tiger"; const oCrocodile = "gaia/fauna_crocodile_nile"; const oFish = "gaia/fish/generic"; const oElephant = "gaia/fauna_elephant_asian"; const oElephantInfant = "gaia/fauna_elephant_asian_infant"; const oBoar = "gaia/fauna_boar"; const oStoneSmall = "gaia/rock/savanna_small"; const oMetalLarge = "gaia/ore/savanna_large"; const aBush = "actor|props/flora/bush_medit_sm_dry.xml"; const aRock = "actor|geology/stone_savanna_med.xml"; const heightSeaGround = -3; const heightLand = 1; const heightShore = 3; const heightOffsetBump = 2; var g_Map = new RandomMap(heightLand, tGrass1); var numPlayers = getNumPlayers(); var mapSize = g_Map.getSize(); var mapCenter = g_Map.getCenter(); var clPlayer = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, // No city patch - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "type": "stone_formation", "template": oStoneSmall, "terrain": tDirt1 } ] }, "Trees": { "template": oTree, "count": scaleByMapSize(3, 7), "minDist": 13, "maxDist": 15, "minDistGroup": 4, "maxDistGroup": 6 } // No decoratives }); Engine.SetProgress(20); g_Map.log("Creating bumps"); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.5, 0.08, Infinity), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), avoidClasses(clPlayer, 13), scaleByMapSize(300, 800) ); g_Map.log("Creating the half dried-up lake"); createArea( new ChainPlacer( 2, Math.floor(scaleByMapSize(2, 16)), Math.floor(scaleByMapSize(35, 200)), Infinity, mapCenter, 0, [Math.floor(scaleByMapSize(15, 40))]), [ new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4), new TileClassPainter(clWater) ], avoidClasses(clPlayer, 2)); g_Map.log("Creating more shore jaggedness"); createAreas( new ChainPlacer(2, Math.floor(scaleByMapSize(4, 6)), 3, Infinity), [ new SmoothElevationPainter(ELEVATION_SET, heightShore, 4), new TileClassUnPainter(clWater) ], borderClasses(clWater, 4, 7), scaleByMapSize(12, 130) * 2, 150 ); paintTerrainBasedOnHeight(2.4, 3.4, 3, tGrass1); paintTerrainBasedOnHeight(1, 2.4, 0, tShore); paintTerrainBasedOnHeight(-8, 1, 2, tWater); paintTileClassBasedOnHeight(-6, 0, 1, clWater); Engine.SetProgress(55); g_Map.log("Creating stone mines"); for (let i = 0; i < scaleByMapSize(12, 30); ++i) { let position = new Vector2D(randIntInclusive(1, mapSize - 1), randIntInclusive(1, mapSize - 1)); if (avoidClasses(clPlayer, 30, clRock, 25, clWater, 10).allows(position)) { createStoneMineFormation(position, oStoneSmall, tDirt4); clRock.add(position); } } g_Map.log("Creating metal mines"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oMetalLarge, 1, 1, 0, 4)], true, clMetal), 0, avoidClasses(clPlayer, 20, clMetal, 10, clRock, 8, clWater, 4), scaleByMapSize(2, 12), 100 ); Engine.SetProgress(65); g_Map.log("Creating small decorative rocks"); createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject(aRock, 1, 3, 0, 3)], true ), 0, avoidClasses(clPlayer, 7, clWater, 1), scaleByMapSize(200, 1200), 1 ); Engine.SetProgress(70); g_Map.log("Creating boar"); createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject(oBoar, 1, 2, 0, 4)], true, clFood ), 0, avoidClasses(clWater, 1, clPlayer, 20, clFood, 11), scaleByMapSize(4, 12), 50 ); g_Map.log("Creating tigers"); createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject(oTiger, 2, 2, 0, 4)], true, clFood ), 0, avoidClasses(clWater, 1, clPlayer, 20, clFood, 11), scaleByMapSize(4, 12), 50 ); g_Map.log("Creating crocodiles"); createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject(oCrocodile, 2, 4, 0, 4)], true, clFood ), 0, stayClasses(clWater, 1), scaleByMapSize(4, 12), 50 ); g_Map.log("Creating elephants"); createObjectGroupsDeprecated( new SimpleGroup( [ new SimpleObject(oElephant, 2, 4, 0, 4), new SimpleObject(oElephantInfant, 1, 2, 0, 4) ], true, clFood ), 0, avoidClasses(clWater, 1, clPlayer, 20, clFood, 11), scaleByMapSize(4, 12), 50 ); g_Map.log("Creating rabbits"); createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject(oRabbit, 5, 6, 0, 4)], true, clFood ), 0, avoidClasses(clWater, 1, clPlayer, 20, clFood, 11), scaleByMapSize(4, 12), 50 ); createFood( [ [new SimpleObject(oFish, 2, 3, 0, 2)] ], [ 25 * numPlayers ], [avoidClasses(clFood, 20), stayClasses(clWater, 2)], clFood); g_Map.log("Creating berry bush"); createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject(oBerryBush, 5, 7, 0, 4)], true, clFood ), 0, avoidClasses(clWater, 3, clPlayer, 20, clFood, 12, clRock, 4, clMetal, 4), randIntInclusive(1, 4) * numPlayers + 2, 50 ); Engine.SetProgress(85); g_Map.log("Creating trees"); createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject(oTree, 1, 7, 0, 3)], true, clForest ), 0, avoidClasses(clForest, 1, clPlayer, 20, clMetal, 4, clRock, 4, clWater, 1), scaleByMapSize(70, 500) ); g_Map.log("Creating large grass tufts"); createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject(aBush, 2, 4, 0, 1.8, -Math.PI/8, Math.PI/8)] ), 0, avoidClasses(clWater, 3, clPlayer, 2, clForest, 0), scaleByMapSize(100, 1200) ); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clFood, 2)); setSunColor(0.87451, 0.847059, 0.647059); setWaterColor(0.741176, 0.592157, 0.27451); setWaterTint(0.741176, 0.592157, 0.27451); setWaterWaviness(2.0); setWaterType("clap"); setWaterMurkiness(0.835938); setAmbientColor(0.57, 0.58, 0.55); setFogFactor(0.25); setFogThickness(0.15); setFogColor(0.847059, 0.737255, 0.482353); setPPEffect("hdr"); setPPContrast(0.57031); setPPBloom(0.34); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/islands.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/islands.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/islands.js (revision 26381) @@ -1,365 +1,365 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); TILE_CENTERED_HEIGHT_MAP = true; setSelectedBiome(); const tMainTerrain = g_Terrains.mainTerrain; const tForestFloor1 = g_Terrains.forestFloor1; const tForestFloor2 = g_Terrains.forestFloor2; const tCliff = g_Terrains.cliff; const tTier1Terrain = g_Terrains.tier1Terrain; const tTier2Terrain = g_Terrains.tier2Terrain; const tTier3Terrain = g_Terrains.tier3Terrain; const tHill = g_Terrains.hill; const tRoad = g_Terrains.road; const tRoadWild = g_Terrains.roadWild; const tTier4Terrain = g_Terrains.tier4Terrain; const tShore = g_Terrains.shore; const tWater = g_Terrains.water; const oTree1 = g_Gaia.tree1; const oTree2 = g_Gaia.tree2; const oTree3 = g_Gaia.tree3; const oTree4 = g_Gaia.tree4; const oTree5 = g_Gaia.tree5; const oFruitBush = g_Gaia.fruitBush; const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal; const oFish = g_Gaia.fish; const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal; const oStoneLarge = g_Gaia.stoneLarge; const oStoneSmall = g_Gaia.stoneSmall; const oMetalLarge = g_Gaia.metalLarge; const oWoodTreasure = "gaia/treasure/wood"; const oDock = "skirmish/structures/default_dock"; const aGrass = g_Decoratives.grass; const aGrassShort = g_Decoratives.grassShort; const aRockLarge = g_Decoratives.rockLarge; const aRockMedium = g_Decoratives.rockMedium; const aBushMedium = g_Decoratives.bushMedium; const aBushSmall = g_Decoratives.bushSmall; const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2]; const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1]; const heightSeaGround = -5; const heightLand = 3; const heightOffsetBump = 2; const heightHill = 18; var g_Map = new RandomMap(heightSeaGround, tWater); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clLand = g_Map.createTileClass(); var playerIslandRadius = scaleByMapSize(20, 29); var [playerIDs, playerPosition, playerAngle] = playerPlacementCircle(fractionToTiles(0.35)); if (!isNomad()) { g_Map.log("Creating player islands and docks"); for (let i = 0; i < numPlayers; i++) { createArea( new ClumpPlacer(diskArea(playerIslandRadius), 0.8, 0.1, Infinity, playerPosition[i]), [ new LayeredPainter([tMainTerrain , tMainTerrain, tMainTerrain], [1, 6]), new SmoothElevationPainter(ELEVATION_SET, heightLand, 6), new TileClassPainter(clLand), new TileClassPainter(clPlayer) ]); let dockLocation = findLocationInDirectionBasedOnHeight(playerPosition[i], mapCenter, -3 , heightLand - 0.5, heightLand); g_Map.placeEntityPassable(oDock, playerIDs[i], dockLocation, playerAngle[i] + Math.PI); } } g_Map.log("Creating big islands"); createAreas( new ChainPlacer( Math.floor(scaleByMapSize(4, 8)), Math.floor(scaleByMapSize(8, 14)), Math.floor(scaleByMapSize(25, 60)), 0.07), [ new TerrainPainter(tMainTerrain), new SmoothElevationPainter(ELEVATION_SET, heightLand, 6), new TileClassPainter(clLand) ], avoidClasses(clLand, scaleByMapSize(8, 12)), scaleByMapSize(4, 14)); g_Map.log("Creating small islands"); createAreas( new ChainPlacer( Math.floor(scaleByMapSize(4, 7)), Math.floor(scaleByMapSize(7, 10)), Math.floor(scaleByMapSize(16, 40)), 0.07), [ new TerrainPainter(tMainTerrain), new SmoothElevationPainter(ELEVATION_SET, heightLand, 6), new TileClassPainter(clLand) ], avoidClasses(clLand, scaleByMapSize(8, 12)), scaleByMapSize(6, 54)); paintTerrainBasedOnHeight(1, 3, 0, tShore); paintTerrainBasedOnHeight(-8, 1, 2, tWater); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], // PlayerTileClass marked above "BaseResourceClass": clBaseResource, "Walls": "towers", "CityPatch": { "radius": playerIslandRadius / 3, "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oFruitBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Treasures": { "types": [ { "template": oWoodTreasure, "count": 14 } ] }, "Trees": { "template": oTree1, "count": 5 }, "Decoratives": { "template": aGrassShort } }); g_Map.log("Creating bumps"); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, Infinity), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), [avoidClasses(clPlayer, 0), stayClasses(clLand, 3)], scaleByMapSize(20, 100)); g_Map.log("Creating hills"); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(16, 40)), 0.5), [ new LayeredPainter([tCliff, tHill], [2]), new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), new TileClassPainter(clHill) ], [avoidClasses(clPlayer, 2, clHill, 15), stayClasses(clLand, 0)], scaleByMapSize(4, 13)); g_Map.log("Creating forests"); var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(1)); var types = [ [[tForestFloor2, tMainTerrain, pForest1], [tForestFloor2, pForest1]], [[tForestFloor1, tMainTerrain, pForest2], [tForestFloor1, pForest2]] ]; if (currentBiome() != "generic/savanna") { var size = forestTrees / (scaleByMapSize(3,6) * numPlayers); var num = Math.floor(size / types.length); for (let type of types) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), forestTrees / (num * Math.floor(scaleByMapSize(2, 5))), 0.5), [ new LayeredPainter(type, [2]), new TileClassPainter(clForest) ], [avoidClasses(clPlayer, 0, clForest, 10, clHill, 0), stayClasses(clLand, 6)], num); } Engine.SetProgress(50); g_Map.log("Creating dirt patches"); var numberOfPatches = scaleByMapSize(15, 45) * (currentBiome() == "generic/savanna" ? 3 : 1); for (let size of [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)]) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5), [ new LayeredPainter([[tMainTerrain, tTier1Terrain], [tTier1Terrain, tTier2Terrain], [tTier2Terrain, tTier3Terrain]], [1, 1]), new TileClassPainter(clDirt) ], [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 0), stayClasses(clLand, 6)], numberOfPatches); g_Map.log("Creating grass patches"); for (let size of [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)]) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5), new TerrainPainter(tTier4Terrain), [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 0), stayClasses(clLand, 6)], numberOfPatches); Engine.SetProgress(55); g_Map.log("Creating stone mines"); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 1, clPlayer, 0, clRock, 10, clHill, 1), stayClasses(clLand, 5)], scaleByMapSize(4,16), 100 ); g_Map.log("Creating small stone quarries"); group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 1, clPlayer, 0, clRock, 10, clHill, 1), stayClasses(clLand, 5)], scaleByMapSize(4,16), 100 ); g_Map.log("Creating metal mines"); group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4)], true, clMetal); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 1, clPlayer, 0, clMetal, 10, clRock, 5, clHill, 1), stayClasses(clLand, 5)], scaleByMapSize(4,16), 100 ); Engine.SetProgress(65); g_Map.log("Creating small decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockMedium, 1,3, 0,1)], true ); createObjectGroupsDeprecated( group, 0, [avoidClasses(clForest, 0, clPlayer, 0, clHill, 0), stayClasses(clLand, 5)], scaleByMapSize(16, 262), 50 ); g_Map.log("Creating large decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockLarge, 1,2, 0,1), new SimpleObject(aRockMedium, 1,3, 0,2)], true ); createObjectGroupsDeprecated( group, 0, [avoidClasses(clForest, 0, clPlayer, 0, clHill, 0), stayClasses(clLand, 5)], scaleByMapSize(8, 131), 50 ); Engine.SetProgress(70); g_Map.log("Creating deer"); group = new SimpleGroup( [new SimpleObject(oMainHuntableAnimal, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 0, clPlayer, 0, clHill, 1, clFood, 20), stayClasses(clLand, 5)], 3 * numPlayers, 50 ); Engine.SetProgress(75); g_Map.log("Creating sheep"); group = new SimpleGroup( [new SimpleObject(oSecondaryHuntableAnimal, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 0, clPlayer, 0, clHill, 1, clFood, 20), stayClasses(clLand, 5)], 3 * numPlayers, 50 ); g_Map.log("Creating fruit bush"); group = new SimpleGroup( [new SimpleObject(oFruitBush, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 0, clPlayer, 8, clHill, 1, clFood, 20), stayClasses(clLand, 5)], randIntInclusive(1, 4) * numPlayers + 2, 50 ); g_Map.log("Creating fish"); group = new SimpleGroup( [new SimpleObject(oFish, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clLand, 4, clForest, 2, clPlayer, 2, clHill, 2, clFood, 20), 25 * numPlayers, 60 ); Engine.SetProgress(85); createStragglerTrees( [oTree1, oTree2, oTree4, oTree3], [avoidClasses(clForest, 1, clHill, 1, clPlayer, 0, clMetal, 6, clRock, 6), stayClasses(clLand, 6)], clForest, stragglerTrees); var planetm = 1; if (currentBiome() == "generic/india") planetm = 8; g_Map.log("Creating small grass tufts"); group = new SimpleGroup( [new SimpleObject(aGrassShort, 1,2, 0,1, -Math.PI / 8, Math.PI / 8)] ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clHill, 2, clPlayer, 2, clDirt, 0), stayClasses(clLand, 6)], planetm * scaleByMapSize(13, 200) ); Engine.SetProgress(90); g_Map.log("Creating large grass tufts"); group = new SimpleGroup( [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)] ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clHill, 2, clPlayer, 2, clDirt, 1, clForest, 0), stayClasses(clLand, 5)], planetm * scaleByMapSize(13, 200) ); Engine.SetProgress(95); g_Map.log("Creating bushes"); group = new SimpleGroup( [new SimpleObject(aBushMedium, 1,2, 0,2), new SimpleObject(aBushSmall, 2,4, 0,2)] ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clHill, 1, clPlayer, 1, clDirt, 1), stayClasses(clLand, 6)], planetm * scaleByMapSize(13, 200), 50 ); placePlayersNomad(clPlayer, [stayClasses(clLand, 4), avoidClasses(clHill, 2, clForest, 1, clMetal, 4, clRock, 4, clFood, 2)]); setSkySet(pickRandom(["cirrus", "cumulus", "sunny"])); setSunRotation(randomAngle()); setSunElevation(randFloat(1/5, 1/3) * Math.PI); setWaterWaviness(2); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/kerala.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/kerala.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/kerala.js (revision 26381) @@ -1,345 +1,345 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); const tGrass = ["tropic_grass_c", "tropic_grass_c", "tropic_grass_c", "tropic_grass_c", "tropic_grass_plants", "tropic_plants", "tropic_plants_b"]; const tGrassA = "tropic_plants_c"; const tGrassB = "tropic_plants_c"; const tGrassC = "tropic_grass_c"; const tForestFloor = "tropic_grass_plants"; const tCliff = ["tropic_cliff_a", "tropic_cliff_a", "tropic_cliff_a", "tropic_cliff_a_plants"]; const tPlants = "tropic_plants"; const tRoad = "tropic_citytile_a"; const tRoadWild = "tropic_citytile_plants"; const tShoreBlend = "tropic_beach_dry_plants"; const tShore = "tropic_beach_dry"; const tWater = "tropic_beach_wet"; const oTree = "gaia/tree/toona"; const oPalm = "gaia/tree/palm_tropic"; const oStoneLarge = "gaia/rock/tropical_large"; const oStoneSmall = "gaia/rock/tropical_small"; const oMetalLarge = "gaia/ore/tropical_large"; const oFish = "gaia/fish/generic"; const oDeer = "gaia/fauna_deer"; const oSheep = "gaia/fauna_tiger"; const oBush = "gaia/fruit/berry_01"; const aRockLarge = "actor|geology/stone_granite_large.xml"; const aRockMedium = "actor|geology/stone_granite_med.xml"; const aBush1 = "actor|props/flora/plant_tropic_a.xml"; const aBush2 = "actor|props/flora/plant_lg.xml"; const aBush3 = "actor|props/flora/plant_tropic_large.xml"; const pForestD = [tForestFloor + TERRAIN_SEPARATOR + oTree, tForestFloor]; const pForestP = [tForestFloor + TERRAIN_SEPARATOR + oPalm, tForestFloor]; const heightSeaGround = -5; const heightLand = 3; const heightHill = 25; var g_Map = new RandomMap(heightLand, tGrass); const numPlayers = getNumPlayers(); const mapCenter = g_Map.getCenter(); const mapBounds = g_Map.getBounds(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var waterPosition = fractionToTiles(0.31); var playerPosition = fractionToTiles(0.55); var mountainPosition = fractionToTiles(0.69); var startAngle = randomAngle(); placePlayerBases({ "PlayerPlacement": [ sortAllPlayers(), playerPlacementLine(0, new Vector2D(mapCenter.x, playerPosition), fractionToTiles(0.2)).map(pos => pos.rotateAround(startAngle, mapCenter)) ], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oTree, "count": scaleByMapSize(12, 30), "minDist": 12, "maxDist": 14, "minDistGroup": 1, "maxDistGroup": 3 } // No decoratives }); Engine.SetProgress(15); paintRiver({ "parallel": true, "start": new Vector2D(mapBounds.left, mapBounds.top).rotateAround(startAngle - Math.PI / 2, mapCenter), "end": new Vector2D(mapBounds.left, mapBounds.bottom).rotateAround(startAngle - Math.PI / 2, mapCenter), "width": 2 * waterPosition, "fadeDist": 8, "deviation": 0, "heightRiverbed": heightSeaGround, "heightLand": heightLand, "meanderShort": 20, "meanderLong": 0, "waterFunc": (position, height, riverFraction) => { clWater.add(position); } }); g_Map.log("Marking mountain area"); var areaMountains = createArea( new ConvexPolygonPlacer( [ new Vector2D(mountainPosition, mapBounds.top), new Vector2D(mountainPosition, mapBounds.bottom), new Vector2D(mapBounds.right, mapBounds.top), new Vector2D(mapBounds.right, mapBounds.bottom) ].map(pos => pos.rotateAround(startAngle - Math.PI / 2, mapCenter)), Infinity)); g_Map.log("Creating shores"); for (let i = 0; i < scaleByMapSize(20, 120); ++i) { let position = new Vector2D(fractionToTiles(randFloat(0.28, 0.34)), fractionToTiles(randFloat(0.1, 0.9))).rotateAround(startAngle - Math.PI / 2, mapCenter).round(); createArea( new ChainPlacer(1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(16, 30)), Infinity, position), [ new LayeredPainter([tGrass, tGrass], [2]), new SmoothElevationPainter(ELEVATION_SET, heightLand, 3), new TileClassUnPainter(clWater) ]); } paintTerrainBasedOnHeight(-6, 1, 1, tWater); paintTerrainBasedOnHeight(1, 2.8, 1, tShoreBlend); paintTerrainBasedOnHeight(0, 1, 1, tShore); paintTileClassBasedOnHeight(-6, 0.5, 1, clWater); Engine.SetProgress(45); g_Map.log("Creating hills"); createAreasInAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(16, 40)), 0.1), [ new LayeredPainter([tCliff, tGrass], [3]), new SmoothElevationPainter(ELEVATION_SET, heightHill, 3), new TileClassPainter(clHill) ], avoidClasses(clPlayer, 20, clHill, 5, clWater, 2, clBaseResource, 2), scaleByMapSize(5, 100), 3, [areaMountains]); g_Map.log("Creating forests"); var [forestTrees, stragglerTrees] = getTreeCounts(1000, 6000, 0.7); var types = [ [[tGrass, tGrass, tGrass, tGrass, pForestD], [tGrass, tGrass, tGrass, pForestD]], [[tGrass, tGrass, tGrass, tGrass, pForestP], [tGrass, tGrass, tGrass, pForestP]] ]; var size = forestTrees / (scaleByMapSize(3,6) * numPlayers); var num = Math.floor(size / types.length); for (let type of types) createAreas( new ChainPlacer( 1, Math.floor(scaleByMapSize(3, 5)), forestTrees / (num * Math.floor(scaleByMapSize(2, 4))), 0.5), [ new LayeredPainter(type, [2]), new TileClassPainter(clForest) ], avoidClasses(clPlayer, 20, clForest, 10, clHill, 0, clWater, 8), num); Engine.SetProgress(70); g_Map.log("Creating grass patches"); for (let size of [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)]) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5), [ new LayeredPainter([tGrassC, tGrassA, tGrassB], [2, 1]), new TileClassPainter(clDirt) ], avoidClasses(clWater, 8, clForest, 0, clHill, 0, clPlayer, 12, clDirt, 16), scaleByMapSize(20, 80)); for (let size of [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)]) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5), [ new TerrainPainter(tPlants), new TileClassPainter(clDirt) ], avoidClasses(clWater, 8, clForest, 0, clHill, 0, clPlayer, 12, clDirt, 16), scaleByMapSize(20, 80)); g_Map.log("Creating stone mines"); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), scaleByMapSize(4,16), 100 ); g_Map.log("Creating small stone quarries"); group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), scaleByMapSize(4,16), 100 ); g_Map.log("Creating metal mines"); group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4)], true, clMetal); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 1), scaleByMapSize(4,16), 100 ); g_Map.log("Creating small decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockMedium, 1,3, 0,1)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0), 3*scaleByMapSize(16, 262), 50 ); g_Map.log("Creating large decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockLarge, 1,2, 0,1), new SimpleObject(aRockMedium, 1,3, 0,2)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0), 3*scaleByMapSize(8, 131), 50 ); g_Map.log("Creating small grass tufts"); group = new SimpleGroup( [new SimpleObject(aBush1, 1,2, 0,1, -Math.PI / 8, Math.PI / 8)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 2, clHill, 2, clPlayer, 2, clDirt, 0), 8 * scaleByMapSize(13, 200) ); Engine.SetProgress(90); g_Map.log("Creating large grass tufts"); group = new SimpleGroup( [new SimpleObject(aBush2, 2,4, 0,1.8, -Math.PI / 8, Math.PI / 8), new SimpleObject(aBush1, 3,6, 1.2,2.5, -Math.PI / 8, Math.PI / 8)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clHill, 2, clPlayer, 2, clDirt, 1, clForest, 0), 8 * scaleByMapSize(13, 200) ); Engine.SetProgress(95); g_Map.log("Creating bushes"); group = new SimpleGroup( [new SimpleObject(aBush3, 1,2, 0,2), new SimpleObject(aBush2, 2,4, 0,2)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 1, clHill, 1, clPlayer, 1, clDirt, 1), 8 * scaleByMapSize(13, 200), 50 ); Engine.SetProgress(96); createStragglerTrees( [oTree, oPalm], avoidClasses(clWater, 5, clForest, 1, clHill, 1, clPlayer, 12, clMetal, 6, clRock, 6), clForest, stragglerTrees); g_Map.log("Creating deer"); group = new SimpleGroup( [new SimpleObject(oDeer, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 0, clPlayer, 10, clHill, 1, clFood, 20), 3 * numPlayers, 50 ); Engine.SetProgress(97); g_Map.log("Creating berry bush"); group = new SimpleGroup( [new SimpleObject(oBush, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 6, clForest, 0, clPlayer, 20, clHill, 1, clFood, 10), randIntInclusive(1, 4) * numPlayers + 2, 50 ); g_Map.log("Creating sheep"); group = new SimpleGroup( [new SimpleObject(oSheep, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 0, clPlayer, 22, clHill, 1, clFood, 20), 3 * numPlayers, 50 ); g_Map.log("Creating fish"); group = new SimpleGroup( [new SimpleObject(oFish, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clFood, 20), stayClasses(clWater, 6)], 25 * numPlayers, 60 ); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clHill, 2, clForest, 1, clMetal, 4, clRock, 4, clFood, 2)); setSunColor(0.6, 0.6, 0.6); setSunElevation(Math.PI / 3); setWaterColor(0.524,0.734,0.839); setWaterTint(0.369,0.765,0.745); setWaterWaviness(1.0); setWaterType("ocean"); setWaterMurkiness(0.35); setFogFactor(0.4); setFogThickness(0.2); setPPEffect("hdr"); setPPContrast(0.7); setPPSaturation(0.65); setPPBloom(0.6); setSkySet("cirrus"); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/lorraine_plain.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/lorraine_plain.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/lorraine_plain.js (revision 26381) @@ -1,322 +1,322 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); const tPrimary = "temp_grass_long"; const tGrass = ["temp_grass", "temp_grass", "temp_grass_d"]; const tGrassPForest = "temp_plants_bog"; const tGrassDForest = "temp_plants_bog"; const tGrassA = "temp_grass_plants"; const tGrassB = "temp_plants_bog"; const tGrassC = "temp_mud_a"; const tRoad = "temp_road"; const tRoadWild = "temp_road_overgrown"; const tGrassPatchBlend = "temp_grass_long_b"; const tGrassPatch = ["temp_grass_d", "temp_grass_clovers"]; const tShore = "temp_plants_bog"; const tWater = "temp_mud_a"; const oBeech = "gaia/tree/euro_beech"; const oOak = "gaia/tree/oak"; const oBerryBush = "gaia/fruit/berry_01"; const oDeer = "gaia/fauna_deer"; const oRabbit = "gaia/fauna_rabbit"; const oStoneLarge = "gaia/rock/temperate_large"; const oStoneSmall = "gaia/rock/temperate_small"; const oMetalLarge = "gaia/ore/temperate_large"; const aGrass = "actor|props/flora/grass_soft_small_tall.xml"; const aGrassShort = "actor|props/flora/grass_soft_large.xml"; const aRockLarge = "actor|geology/stone_granite_med.xml"; const aRockMedium = "actor|geology/stone_granite_med.xml"; const aReeds = "actor|props/flora/reeds_pond_lush_a.xml"; const aLillies = "actor|props/flora/water_lillies.xml"; const aBushMedium = "actor|props/flora/bush_medit_me.xml"; const aBushSmall = "actor|props/flora/bush_medit_sm.xml"; const pForestB = [tGrassDForest + TERRAIN_SEPARATOR + oBeech, tGrassDForest]; const pForestO = [tGrassPForest + TERRAIN_SEPARATOR + oOak, tGrassPForest]; const pForestR = [tGrassDForest + TERRAIN_SEPARATOR + oBeech, tGrassDForest, tGrassDForest + TERRAIN_SEPARATOR + oOak, tGrassDForest, tGrassDForest, tGrassDForest]; const heightSeaGround = -4; const heightShallows = -2; const heightLand = 3; const heightOffsetBump = 2; var g_Map = new RandomMap(heightLand, tPrimary); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); const mapBounds = g_Map.getBounds(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clShallow = g_Map.createTileClass(); var shallowWidth = scaleByMapSize(8, 12); var startAngle = randomAngle(); placePlayerBases({ "PlayerPlacement": playerPlacementRiver(startAngle + Math.PI / 2, fractionToTiles(0.5)), // PlayerTileClass marked below "BaseResourceClass": clBaseResource, "Walls": "towers", "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad, "painters": [ new TileClassPainter(clPlayer) ] }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oOak, "count": 3 }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(20); var riverPositions = [ new Vector2D(mapBounds.left + 1, mapCenter.y), new Vector2D(mapBounds.right - 1, mapCenter.y) ].map(v => v.rotateAround(startAngle, mapCenter)); g_Map.log("Creating the main river"); createArea( new PathPlacer(riverPositions[0], riverPositions[1], scaleByMapSize(10, 20), 0.5, scaleByMapSize(0.5, 2), 0.1, 0.01), new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4), avoidClasses(clPlayer, 4)); Engine.SetProgress(25); g_Map.log("Creating small puddles at the map border to ensure players being separated"); for (let riverPosition of riverPositions) createArea( new ClumpPlacer(diskArea(scaleByMapSize(5, 10)), 0.95, 0.6, Infinity, riverPosition), new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 2), avoidClasses(clPlayer, 8)); Engine.SetProgress(30); g_Map.log("Creating the shallows of the main river"); for (let i = 0; i <= randIntInclusive(3, scaleByMapSize(4, 6)); ++i) { let location = fractionToTiles(randFloat(0.15, 0.85)); createPassage({ "start": new Vector2D(location, mapBounds.top).rotateAround(startAngle, mapCenter), "end": new Vector2D(location, mapBounds.bottom).rotateAround(startAngle, mapCenter), "startWidth": shallowWidth, "endWidth": shallowWidth, "smoothWidth": 2, "startHeight": heightShallows, "endHeight": heightShallows, "constraints": new HeightConstraint(-Infinity, heightShallows), "tileClass": clShallow }); } Engine.SetProgress(35); createTributaryRivers( startAngle, randIntInclusive(9, scaleByMapSize(13, 21)), scaleByMapSize(10, 20), heightSeaGround, [-6, -1.5], Math.PI / 5, clWater, clShallow, avoidClasses(clPlayer, 3, clBaseResource, 4)); Engine.SetProgress(40); paintTerrainBasedOnHeight(-5, 1, 1, tWater); paintTerrainBasedOnHeight(1, 2, 1, pForestR); paintTileClassBasedOnHeight(-6, 0.5, 1, clWater); Engine.SetProgress(50); g_Map.log("Creating bumps"); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, Infinity), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), avoidClasses(clWater, 2, clPlayer, 15), scaleByMapSize(100, 200) ); Engine.SetProgress(55); var [forestTrees, stragglerTrees] = getTreeCounts(500, 2500, 0.7); createForests( [tGrass, tGrassDForest, tGrassPForest, pForestB, pForestO], avoidClasses(clPlayer, 15, clWater, 3, clForest, 16, clHill, 1), clForest, forestTrees); Engine.SetProgress(70); g_Map.log("Creating dirt patches"); for (let size of [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)]) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5), [ new LayeredPainter([[tGrass,tGrassA], tGrassB, [tGrassB,tGrassC]], [1, 1]), new TileClassPainter(clDirt) ], avoidClasses(clWater, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 6), scaleByMapSize(15, 45) ); g_Map.log("Creating grass patches"); for (let size of [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)]) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5), new LayeredPainter([tGrassPatchBlend, tGrassPatch], [1]), avoidClasses(clWater, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 6), scaleByMapSize(15, 45) ); Engine.SetProgress(80); g_Map.log("Creating stone mines"); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clWater, 0, clForest, 1, clPlayer, 15, clRock, 10, clHill, 1)], scaleByMapSize(4,16), 100 ); g_Map.log("Creating small stone quarries"); group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clWater, 0, clForest, 1, clPlayer, 15, clRock, 10, clHill, 1)], scaleByMapSize(4,16), 100 ); g_Map.log("Creating metal mines"); group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4)], true, clMetal); createObjectGroupsDeprecated(group, 0, [avoidClasses(clWater, 0, clForest, 1, clPlayer, 15, clMetal, 10, clRock, 5, clHill, 1)], scaleByMapSize(4,16), 100 ); Engine.SetProgress(86); g_Map.log("Creating small decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockMedium, 1,3, 0,1)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0), scaleByMapSize(16, 262), 50 ); g_Map.log("Creating large decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockLarge, 1,2, 0,1), new SimpleObject(aRockMedium, 1,3, 0,2)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0), scaleByMapSize(8, 131), 50 ); g_Map.log("Creating deer"); group = new SimpleGroup( [new SimpleObject(oDeer, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 15, clHill, 1, clFood, 20), 3 * numPlayers, 50 ); g_Map.log("Creating rabbits"); group = new SimpleGroup( [new SimpleObject(oRabbit, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 15, clHill, 1, clFood, 20), 3 * numPlayers, 50 ); g_Map.log("Creating berry bush"); group = new SimpleGroup( [new SimpleObject(oBerryBush, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 0, clPlayer, 15, clHill, 1, clFood, 10), randIntInclusive(1, 4) * numPlayers + 2, 50 ); createStragglerTrees( [oOak, oBeech], avoidClasses(clWater, 1, clForest, 7, clHill, 1, clPlayer, 5, clMetal, 6, clRock, 6), clForest, stragglerTrees); g_Map.log("Creating small grass tufts"); group = new SimpleGroup( [new SimpleObject(aGrassShort, 1,2, 0,1, -Math.PI / 8, Math.PI / 8)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 2, clHill, 2, clPlayer, 2, clDirt, 0), scaleByMapSize(13, 200) ); g_Map.log("Creating large grass tufts"); group = new SimpleGroup( [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)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clHill, 2, clPlayer, 2, clDirt, 1, clForest, 0), scaleByMapSize(13, 200) ); g_Map.log("Creating bushes"); group = new SimpleGroup( [new SimpleObject(aBushMedium, 1,2, 0,2), new SimpleObject(aBushSmall, 2,4, 0,2)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 1, clHill, 1, clPlayer, 1, clDirt, 1), scaleByMapSize(13, 200), 50 ); g_Map.log("Creating shallow flora"); group = new SimpleGroup( [new SimpleObject(aLillies, 1,2, 0,2), new SimpleObject(aReeds, 2,4, 0,2)] ); createObjectGroupsDeprecated(group, 0, stayClasses(clShallow, 1), 60 * scaleByMapSize(13, 200), 80 ); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); setSkySet("cirrus"); setWaterColor(0.1,0.212,0.422); setWaterTint(0.3,0.1,0.949); setWaterWaviness(3.0); setWaterType("lake"); setWaterMurkiness(0.80); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/migration.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/migration.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/migration.js (revision 26381) @@ -1,373 +1,373 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); setSelectedBiome(); const tMainTerrain = g_Terrains.mainTerrain; const tForestFloor1 = g_Terrains.forestFloor1; const tForestFloor2 = g_Terrains.forestFloor2; const tCliff = g_Terrains.cliff; const tTier1Terrain = g_Terrains.tier1Terrain; const tTier2Terrain = g_Terrains.tier2Terrain; const tTier3Terrain = g_Terrains.tier3Terrain; const tHill = g_Terrains.hill; const tRoad = g_Terrains.road; const tRoadWild = g_Terrains.roadWild; const tTier4Terrain = g_Terrains.tier4Terrain; const tShore = g_Terrains.shore; const tWater = g_Terrains.water; const oTree1 = g_Gaia.tree1; const oTree2 = g_Gaia.tree2; const oTree3 = g_Gaia.tree3; const oTree4 = g_Gaia.tree4; const oTree5 = g_Gaia.tree5; const oFruitBush = g_Gaia.fruitBush; const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal; const oFish = g_Gaia.fish; const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal; const oStoneLarge = g_Gaia.stoneLarge; const oStoneSmall = g_Gaia.stoneSmall; const oMetalLarge = g_Gaia.metalLarge; const oWoodTreasure = "gaia/treasure/wood"; const oDock = "skirmish/structures/default_dock"; const aGrass = g_Decoratives.grass; const aGrassShort = g_Decoratives.grassShort; const aRockLarge = g_Decoratives.rockLarge; const aRockMedium = g_Decoratives.rockMedium; const aBushMedium = g_Decoratives.bushMedium; const aBushSmall = g_Decoratives.bushSmall; const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2]; const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1]; const heightSeaGround = -5; const heightLand = 3; const heightHill = 18; const heightOffsetBump = 2; var g_Map = new RandomMap(heightSeaGround, tWater); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clLand = g_Map.createTileClass(); var clIsland = g_Map.createTileClass(); var startAngle = randomAngle(); var playerIDs = sortAllPlayers(); var [playerPosition, playerAngle] = playerPlacementCustomAngle( fractionToTiles(0.35), mapCenter, i => startAngle - Math.PI * (i + 1) / (numPlayers + 1)); g_Map.log("Creating player islands and docks"); for (let i = 0; i < numPlayers; ++i) { createArea( new ClumpPlacer(diskArea(defaultPlayerBaseRadius()), 0.8, 0.1, Infinity, playerPosition[i]), [ new LayeredPainter([tWater, tShore, tMainTerrain], [1, 4]), new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), new TileClassPainter(clIsland), new TileClassPainter(isNomad() ? clLand : clPlayer) ]); if (isNomad()) continue; let dockLocation = findLocationInDirectionBasedOnHeight(playerPosition[i], mapCenter, -3 , 2.6, 3); g_Map.placeEntityPassable(oDock, playerIDs[i], dockLocation, playerAngle[i] + Math.PI); } Engine.SetProgress(10); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "Walls": false, // No city patch - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oFruitBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Treasures": { "types": [ { "template": oWoodTreasure, "count": 14 } ] }, "Trees": { "template": oTree1, "count": scaleByMapSize(12, 30) }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(15); g_Map.log("Create the continent body"); var continentPosition = Vector2D.add(mapCenter, new Vector2D(0, fractionToTiles(0.38)).rotate(-startAngle)).round(); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.4)), 0.8, 0.08, Infinity, continentPosition), [ new LayeredPainter([tWater, tShore, tMainTerrain], [4, 2]), new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), new TileClassPainter(clLand) ], avoidClasses(clIsland, 8)); Engine.SetProgress(20); g_Map.log("Creating shore jaggedness"); createAreas( new ClumpPlacer(scaleByMapSize(15, 80), 0.2, 0.1, Infinity), [ new LayeredPainter([tMainTerrain, tMainTerrain], [2]), new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), new TileClassPainter(clLand) ], [ borderClasses(clLand, 6, 3), avoidClasses(clIsland, 8) ], scaleByMapSize(2, 15) * 20, 150); paintTerrainBasedOnHeight(1, 3, 0, tShore); paintTerrainBasedOnHeight(-8, 1, 2, tWater); Engine.SetProgress(25); g_Map.log("Creating bumps"); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, Infinity), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), [avoidClasses(clIsland, 10), stayClasses(clLand, 3)], scaleByMapSize(100, 200) ); Engine.SetProgress(30); g_Map.log("Creating hills"); createAreas( new ClumpPlacer(scaleByMapSize(20, 150), 0.2, 0.1, Infinity), [ new LayeredPainter([tCliff, tHill], [2]), new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), new TileClassPainter(clHill) ], [avoidClasses(clIsland, 10, clHill, 15), stayClasses(clLand, 7)], scaleByMapSize(1, 4) * numPlayers ); Engine.SetProgress(34); g_Map.log("Creating forests"); var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(1)); var types = [ [[tForestFloor2, tMainTerrain, pForest1], [tForestFloor2, pForest1]], [[tForestFloor1, tMainTerrain, pForest2], [tForestFloor1, pForest2]] ]; var size = forestTrees / (scaleByMapSize(2,8) * numPlayers) * (currentBiome() == "generic/savanna" ? 2 : 1); var num = Math.floor(size / types.length); for (let type of types) createAreas( new ClumpPlacer(forestTrees / num, 0.1, 0.1, Infinity), [ new LayeredPainter(type, [2]), new TileClassPainter(clForest) ], [avoidClasses(clPlayer, 6, clForest, 10, clHill, 0), stayClasses(clLand, 7)], num); Engine.SetProgress(38); g_Map.log("Creating dirt patches"); for (let size of [scaleByMapSize(3, 48), scaleByMapSize(5, 84), scaleByMapSize(8, 128)]) createAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), [ new LayeredPainter( [[tMainTerrain, tTier1Terrain], [tTier1Terrain, tTier2Terrain], [tTier2Terrain, tTier3Terrain]], [1, 1]), new TileClassPainter(clDirt) ], [ avoidClasses( clForest, 0, clHill, 0, clDirt, 5, clIsland, 0), stayClasses(clLand, 7) ], scaleByMapSize(15, 45)); Engine.SetProgress(42); g_Map.log("Creating grass patches"); for (let size of [scaleByMapSize(2, 32), scaleByMapSize(3, 48), scaleByMapSize(5, 80)]) createAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), new TerrainPainter(tTier4Terrain), [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clIsland, 0), stayClasses(clLand, 7)], scaleByMapSize(15, 45)); Engine.SetProgress(46); g_Map.log("Creating stone mines"); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 1, clPlayer, 10, clRock, 10, clHill, 1), stayClasses(clLand, 7)], scaleByMapSize(4,16), 100 ); Engine.SetProgress(50); g_Map.log("Creating small stone quarries"); group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 1, clPlayer, 10, clRock, 10, clHill, 1), stayClasses(clLand, 7)], scaleByMapSize(4,16), 100 ); Engine.SetProgress(54); g_Map.log("Creating metal mines"); group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4)], true, clMetal); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 1, clPlayer, 10, clMetal, 10, clRock, 5, clHill, 1), stayClasses(clLand, 7)], scaleByMapSize(4,16), 100 ); Engine.SetProgress(58); g_Map.log("Creating small decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockMedium, 1,3, 0,1)], true ); createObjectGroupsDeprecated( group, 0, [avoidClasses(clForest, 0, clPlayer, 0, clHill, 0), stayClasses(clLand, 6)], scaleByMapSize(16, 262), 50 ); Engine.SetProgress(62); g_Map.log("Creating large decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockLarge, 1,2, 0,1), new SimpleObject(aRockMedium, 1,3, 0,2)], true ); createObjectGroupsDeprecated( group, 0, [avoidClasses(clForest, 0, clPlayer, 0, clHill, 0), stayClasses(clLand, 6)], scaleByMapSize(8, 131), 50 ); Engine.SetProgress(66); g_Map.log("Creating deer"); group = new SimpleGroup( [new SimpleObject(oMainHuntableAnimal, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 0, clPlayer, 10, clHill, 1, clFood, 20), stayClasses(clLand, 7)], 3 * numPlayers, 50 ); Engine.SetProgress(70); g_Map.log("Creating sheep"); group = new SimpleGroup( [new SimpleObject(oSecondaryHuntableAnimal, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 0, clPlayer, 10, clHill, 1, clFood, 20), stayClasses(clLand, 7)], 3 * numPlayers, 50 ); Engine.SetProgress(74); g_Map.log("Creating fruit bush"); group = new SimpleGroup( [new SimpleObject(oFruitBush, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 0, clPlayer, 8, clHill, 1, clFood, 20), stayClasses(clLand, 7)], randIntInclusive(1, 4) * numPlayers + 2, 50 ); Engine.SetProgress(78); g_Map.log("Creating fish"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oFish, 2,3, 0,2)], true, clFood), 0, avoidClasses(clLand, 2, clPlayer, 2, clHill, 0, clFood, 20), 25 * numPlayers, 60 ); Engine.SetProgress(82); createStragglerTrees( [oTree1, oTree2, oTree4, oTree3], [avoidClasses(clForest, 1, clHill, 1, clPlayer, 9, clMetal, 6, clRock, 6), stayClasses(clLand, 9)], clForest, stragglerTrees); Engine.SetProgress(86); var planetm = currentBiome() == "generic/india" ? 8 : 1; g_Map.log("Creating small grass tufts"); group = new SimpleGroup( [new SimpleObject(aGrassShort, 1,2, 0,1, -Math.PI / 8, Math.PI / 8)] ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clHill, 2, clPlayer, 2, clDirt, 0), stayClasses(clLand, 6)], planetm * scaleByMapSize(13, 200) ); Engine.SetProgress(90); g_Map.log("Creating large grass tufts"); group = new SimpleGroup( [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)] ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clHill, 2, clPlayer, 2, clDirt, 1, clForest, 0), stayClasses(clLand, 6)], planetm * scaleByMapSize(13, 200) ); Engine.SetProgress(94); g_Map.log("Creating bushes"); group = new SimpleGroup( [new SimpleObject(aBushMedium, 1,2, 0,2), new SimpleObject(aBushSmall, 2,4, 0,2)] ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clHill, 1, clPlayer, 1, clDirt, 1), stayClasses(clLand, 6)], planetm * scaleByMapSize(13, 200), 50 ); Engine.SetProgress(98); setSkySet(pickRandom(["cirrus", "cumulus", "sunny"])); setSunRotation(randomAngle()); setSunElevation(randFloat(1/5, 1/3) * Math.PI); setWaterWaviness(2); placePlayersNomad(clPlayer, [stayClasses(clIsland, 4), avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)]); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/persian_highlands.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/persian_highlands.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/persian_highlands.js (revision 26381) @@ -1,323 +1,323 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); if (g_MapSettings.Biome) setSelectedBiome(); else // TODO: Replace ugly default for atlas by a dropdown setBiome("persian_highlands/summer"); const tDirtMain = g_Terrains.mainTerrain; const tCity = g_Terrains.road; const tCliff = g_Terrains.cliff; const tLakebed1 = g_Terrains.lakebed1; const tLakebed2 = g_Terrains.lakebed2; const tForestFloor = g_Terrains.forestFloor1; const tRocky = g_Terrains.tier1Terrain; const tRocks = g_Terrains.tier2Terrain; const tGrass = g_Terrains.tier3Terrain; const oOak = g_Gaia.tree1; const oGrapesBush = g_Gaia.fruitBush; const oCamel = g_Gaia.mainHuntableAnimal; const oSheep = g_Gaia.secondaryHuntableAnimal; const oGoat = g_Gaia.thirdHuntableAnimal; const oStoneLarge = g_Gaia.stoneLarge; const oStoneSmall = g_Gaia.stoneSmall; const oMetalLarge = g_Gaia.metalLarge; const aDecorativeRock = g_Decoratives.rockMedium; const aBush1 = g_Decoratives.bush1; const aBush2 = g_Decoratives.bush2; const aBush3 = g_Decoratives.bush3; const aBush4 = g_Decoratives.bush4; const aBushes = [aBush1, aBush2, aBush3, aBush4]; const pForestO = [tForestFloor + TERRAIN_SEPARATOR + oOak, tForestFloor + TERRAIN_SEPARATOR + oOak, tForestFloor, tDirtMain, tDirtMain]; const heightLand = 10; const heightOffsetValley = -10; var g_Map = new RandomMap(heightLand, tDirtMain); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clPatch = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clCP = g_Map.createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tCity, "innerTerrain": tCity, "painters": [ new TileClassPainter(clPlayer) ] }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oGrapesBush, }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ], "groupElements": shuffleArray(aBushes).map(t => new SimpleObject(t, 1, 1, 3, 4)) }, "Trees": { "template": oOak, "count": 3 } // No decoratives }); Engine.SetProgress(10); g_Map.log("Creating rock patches"); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 6)), Math.floor(scaleByMapSize(20, 45)), 0), [ new TerrainPainter(tRocky), new TileClassPainter(clPatch) ], avoidClasses(clPatch, 2, clPlayer, 0), scaleByMapSize(5, 20)); Engine.SetProgress(15); g_Map.log("Creating secondary rock patches"); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), Math.floor(scaleByMapSize(15, 40)), 0), [ new TerrainPainter([tRocky, tRocks]), new TileClassPainter(clPatch) ], avoidClasses(clPatch, 2, clPlayer, 4), scaleByMapSize(15, 50)); Engine.SetProgress(20); g_Map.log("Creating dirt patches"); createAreas( new ChainPlacer( 1, Math.floor(scaleByMapSize(3, 5)), Math.floor(scaleByMapSize(15, 40)), 0), [ new TerrainPainter([tGrass]), new TileClassPainter(clPatch) ], avoidClasses(clPatch, 2, clPlayer, 4), scaleByMapSize(15, 50)); Engine.SetProgress(25); g_Map.log("Creating centeral plateau"); createArea( new ChainPlacer( 2, Math.floor(scaleByMapSize(5, 13)), Math.floor(scaleByMapSize(35, 200)), Infinity, mapCenter, 0, [Math.floor(scaleByMapSize(18, 68))]), [ new LayeredPainter([tLakebed2, tLakebed1], [6]), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetValley, 8), new TileClassPainter(clCP) ], avoidClasses(clPlayer, 18)); Engine.SetProgress(30); g_Map.log("Creating hills"); for (let i = 0; i < scaleByMapSize(20, 80); ++i) createMountain( Math.floor(scaleByMapSize(40, 60)), Math.floor(scaleByMapSize(3, 4)), Math.floor(scaleByMapSize(6, 12)), Math.floor(scaleByMapSize(4, 10)), avoidClasses(clPlayer, 7, clCP, 5, clHill, Math.floor(scaleByMapSize(18, 25))), randIntExclusive(0, mapSize), randIntExclusive(0, mapSize), tCliff, clHill, 14); Engine.SetProgress(35); g_Map.log("Creating forests"); var [forestTrees, stragglerTrees] = getTreeCounts(500, 2500, 0.7); var types = [ [[tDirtMain, tForestFloor, pForestO], [tForestFloor, pForestO]], [[tDirtMain, tForestFloor, pForestO], [tForestFloor, pForestO]] ]; var size = forestTrees / (scaleByMapSize(3,6) * numPlayers); var num = Math.floor(size / types.length); for (let type of types) createAreas( new ChainPlacer( Math.floor(scaleByMapSize(1, 2)), Math.floor(scaleByMapSize(2, 5)), Math.floor(size / Math.floor(scaleByMapSize(8, 3))), Infinity), [ new LayeredPainter(type, [2]), new TileClassPainter(clForest) ], avoidClasses( clPlayer, 6, clForest, 10, clHill, 1, clCP, 1), num); Engine.SetProgress(50); g_Map.log("Creating stone mines"); createObjectGroupsDeprecated( new SimpleGroup( [ new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4), new RandomObject(aBushes, 2, 4, 0, 2) ], true, clRock), 0, [avoidClasses(clForest, 1, clPlayer, 10, clRock, 10, clHill, 1, clCP, 1)], scaleByMapSize(2,8), 100); g_Map.log("Creating small stone quarries"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oStoneSmall, 2, 5, 1, 3), new RandomObject(aBushes, 2, 4, 0, 2)], true, clRock), 0, [avoidClasses(clForest, 1, clPlayer, 10, clRock, 10, clHill, 1, clCP, 1)], scaleByMapSize(2, 8), 100); g_Map.log("Creating metal mines"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oMetalLarge, 1, 1, 0, 4), new RandomObject(aBushes, 2, 4, 0, 2)], true, clMetal), 0, [avoidClasses(clForest, 1, clPlayer, 10, clMetal, 10, clRock, 5, clHill, 1, clCP, 1)], scaleByMapSize(2,8), 100); g_Map.log("Creating centeral stone mines"); createObjectGroupsDeprecated( new SimpleGroup( [ new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4), new RandomObject(aBushes, 2,4, 0,2) ], true, clRock), 0, stayClasses(clCP, 6), 5*scaleByMapSize(5, 30), 50); g_Map.log("Creating small stone quarries"); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 2, 5, 1, 3), new RandomObject(aBushes, 2, 4, 0, 2)], true, clRock); createObjectGroupsDeprecated(group, 0, stayClasses(clCP, 6), 5*scaleByMapSize(5,30), 50 ); g_Map.log("Creating centeral metal mines"); group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4), new RandomObject(aBushes, 2,4, 0,2)], true, clMetal); createObjectGroupsDeprecated(group, 0, stayClasses(clCP, 6), 5*scaleByMapSize(5,30), 50 ); Engine.SetProgress(60); g_Map.log("Creating small decorative rocks"); group = new SimpleGroup( [new SimpleObject(aDecorativeRock, 1,3, 0,1)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clForest, 0, clPlayer, 0, clHill, 0), scaleByMapSize(16, 262), 50 ); Engine.SetProgress(65); g_Map.log("Creating bushes"); group = new SimpleGroup( [new SimpleObject(aBush2, 1,2, 0,1), new SimpleObject(aBush1, 1,3, 0,2)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clForest, 0, clPlayer, 0, clHill, 0), scaleByMapSize(8, 131), 50 ); Engine.SetProgress(70); g_Map.log("Creating goat"); group = new SimpleGroup( [new SimpleObject(oGoat, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 1, clHill, 1, clFood, 20, clCP, 2), 3 * numPlayers, 50 ); g_Map.log("Creating sheep"); group = new SimpleGroup( [new SimpleObject(oSheep, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 1, clHill, 1, clFood, 20, clCP, 2), 3 * numPlayers, 50 ); g_Map.log("Creating grape bush"); group = new SimpleGroup( [new SimpleObject(oGrapesBush, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 20, clHill, 1, clFood, 10, clCP, 2), randIntInclusive(1, 4) * numPlayers + 2, 50 ); g_Map.log("Creating camels"); group = new SimpleGroup( [new SimpleObject(oCamel, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, stayClasses(clCP, 2), 3 * numPlayers, 50 ); Engine.SetProgress(90); createStragglerTrees( [oOak], avoidClasses(clForest, 1, clHill, 1, clPlayer, 1, clBaseResource, 6, clMetal, 6, clRock, 6, clCP, 2), clForest, stragglerTrees); placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/aegean_sea.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/aegean_sea.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/aegean_sea.js (revision 26381) @@ -1,310 +1,310 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); TILE_CENTERED_HEIGHT_MAP = true; const tCity = "medit_city_pavement"; const tCityPlaza = "medit_city_pavement"; const tHill = ["medit_grass_shrubs", "medit_rocks_grass_shrubs", "medit_rocks_shrubs", "medit_rocks_grass", "medit_shrubs"]; const tMainDirt = "medit_dirt"; const tCliff = "medit_cliff_aegean"; const tForestFloor = "medit_grass_shrubs"; const tGrass = "medit_grass_field"; const tGrassSand50 = "medit_grass_field_a"; const tGrassSand25 = "medit_grass_field_b"; const tDirt = "medit_dirt_b"; const tDirt2 = "medit_rocks_grass"; const tDirt3 = "medit_rocks_shrubs"; const tDirtCracks = "medit_dirt_c"; const tShoreUpper = "medit_sand"; const tShoreLower = "medit_sand_wet"; const tCoralsUpper = "medit_sea_coral_plants"; const tCoralsLower = "medit_sea_coral_deep"; const tSeaDepths = "medit_sea_depths"; const oBerryBush = "gaia/fruit/berry_01"; const oDeer = "gaia/fauna_deer"; const oFish = "gaia/fish/generic"; const oSheep = "gaia/fauna_sheep"; const oGoat = "gaia/fauna_goat"; const oStoneLarge = "gaia/rock/mediterranean_large"; const oStoneSmall = "gaia/rock/mediterranean_small"; const oMetalLarge = "gaia/ore/mediterranean_large"; const oDatePalm = "gaia/tree/cretan_date_palm_short"; const oSDatePalm = "gaia/tree/cretan_date_palm_tall"; const oCarob = "gaia/tree/carob"; const oFanPalm = "gaia/tree/medit_fan_palm"; const oPoplar = "gaia/tree/poplar_lombardy"; const oCypress = "gaia/tree/cypress"; const aBush1 = "actor|props/flora/bush_medit_sm.xml"; const aBush2 = "actor|props/flora/bush_medit_me.xml"; const aBush3 = "actor|props/flora/bush_medit_la.xml"; const aBush4 = "actor|props/flora/bush_medit_me.xml"; const aDecorativeRock = "actor|geology/stone_granite_med.xml"; const pForest = [tForestFloor, tForestFloor + TERRAIN_SEPARATOR + oCarob, tForestFloor + TERRAIN_SEPARATOR + oDatePalm, tForestFloor + TERRAIN_SEPARATOR + oSDatePalm, tForestFloor]; const heightSeaGround = -3; const heightSeaBump = -2.5; const heightCorralsLower = -2; const heightCorralsUpper = -1.5; const heightShore = 1; const heightLand = 2; const heightIsland = 6; var g_Map = new RandomMap(heightShore, tHill); const numPlayers = getNumPlayers(); const mapCenter = g_Map.getCenter(); const mapBounds = g_Map.getBounds(); var clPlayer = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clGrass = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clIsland = g_Map.createTileClass(); var startAngle = randomAngle(); placePlayerBases({ "PlayerPlacement": playerPlacementRiver(startAngle , fractionToTiles(0.6)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tCityPlaza, "innerTerrain": tCity }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oCarob, "count": 2 }, "Decoratives": { "template": aBush1 } }); Engine.SetProgress(30); paintRiver({ "parallel": false, "start": new Vector2D(mapCenter.x, mapBounds.top).rotateAround(startAngle, mapCenter), "end": new Vector2D(mapCenter.x, mapBounds.bottom).rotateAround(startAngle, mapCenter), "width": fractionToTiles(0.35), "fadeDist": scaleByMapSize(6, 25), "deviation": 0, "heightRiverbed": heightSeaGround, "heightLand": heightLand, "meanderShort": 20, "meanderLong": 0 }); paintTileClassBasedOnHeight(-Infinity, 0.7, Elevation_ExcludeMin_ExcludeMax, clWater); paintTerrainBasedOnHeight(-Infinity, heightShore, Elevation_ExcludeMin_ExcludeMax, tShoreLower); paintTerrainBasedOnHeight(heightShore, heightLand, Elevation_ExcludeMin_ExcludeMax, tShoreUpper); Engine.SetProgress(40); createBumps(avoidClasses(clWater, 2, clPlayer, 20)); var [forestTrees, stragglerTrees] = getTreeCounts(500, 3000, 0.7); createForests( [tForestFloor, tForestFloor, tForestFloor, pForest, pForest], avoidClasses(clPlayer, 20, clForest, 17, clWater, 2, clBaseResource, 3), clForest, forestTrees); Engine.SetProgress(50); if (randBool()) createHills([tGrass, tCliff, tHill], avoidClasses(clPlayer, 20, clForest, 1, clHill, 15, clWater, 3), clHill, scaleByMapSize(3, 15)); else createMountains(tCliff, avoidClasses(clPlayer, 20, clForest, 1, clHill, 15, clWater, 3), clHill, scaleByMapSize(3, 15)); g_Map.log("Creating grass patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [[tGrass,tGrassSand50],[tGrassSand50,tGrassSand25], [tGrassSand25,tGrass]], [1,1], avoidClasses(clForest, 0, clGrass, 2, clPlayer, 10, clWater, 2, clDirt, 2, clHill, 1), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(55); g_Map.log("Creating dirt patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [tDirt3, tDirt2,[tDirt,tMainDirt], [tDirtCracks,tMainDirt]], [1,1,1], avoidClasses(clForest, 0, clDirt, 2, clPlayer, 10, clWater, 2, clGrass, 2, clHill, 1), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(60); g_Map.log("Creating undersea bumps"); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(16, 40)), 0.5), new SmoothElevationPainter(ELEVATION_SET, heightSeaBump, 3), stayClasses(clWater, 6), scaleByMapSize(10, 50)); g_Map.log("Creating islands"); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(30, 80)), 0.5), [ new LayeredPainter([tShoreLower, tShoreUpper, tHill], [2 ,1]), new SmoothElevationPainter(ELEVATION_SET, heightIsland, 4), new TileClassPainter(clIsland) ], [avoidClasses(clPlayer, 8, clForest, 1, clIsland, 15), stayClasses (clWater, 6)], scaleByMapSize(1, 4) * numPlayers ); paintTerrainBasedOnHeight(-Infinity, heightSeaGround, Elevation_IncludeMin_IncludeMax, tSeaDepths); paintTerrainBasedOnHeight(heightSeaGround, heightCorralsLower, Elevation_ExcludeMin_IncludeMax, tCoralsLower); paintTerrainBasedOnHeight(heightCorralsLower, heightCorralsUpper, Elevation_ExcludeMin_IncludeMax, tCoralsUpper); g_Map.log("Creating island stone mines"); createMines( [ [new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], stayClasses(clIsland, 4), clRock); g_Map.log("Creating island metal mines"); createMines( [ [new SimpleObject(oMetalLarge, 1,1, 0,4)] ], stayClasses(clIsland, 4), clMetal ); g_Map.log("Creating stone mines"); createMines( [ [new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clWater, 1, clHill, 1), clRock); g_Map.log("Creating metal mines"); createMines( [ [new SimpleObject(oMetalLarge, 1,1, 0,4)] ], avoidClasses(clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clWater, 1, clHill, 1), clMetal ); Engine.SetProgress(65); createDecoration( [ [ new SimpleObject(aDecorativeRock, 1, 3, 0, 1) ], [ new SimpleObject(aBush2, 1, 2, 0, 1), new SimpleObject(aBush1, 1, 3, 0, 2), new SimpleObject(aBush4, 1, 2, 0, 1), new SimpleObject(aBush3, 1, 3, 0, 2) ] ], [ scaleByMapAreaAbsolute(16), scaleByMapSize(40, 360) ], avoidClasses(clWater, 2, clForest, 0, clPlayer, 0, clHill, 1)); Engine.SetProgress(70); createFood( [ [new SimpleObject(oFish, 2, 3, 0, 2)] ], [ 3 * scaleByMapSize(5, 20) ], [avoidClasses(clIsland, 2, clFood, 10), stayClasses(clWater, 5)], clFood); createFood( [ [new SimpleObject(oSheep, 5, 7, 0, 4)], [new SimpleObject(oGoat, 2, 4, 0, 3)], [new SimpleObject(oDeer, 2, 4, 0, 2)] ], [ scaleByMapSize(5, 20), scaleByMapSize(5, 20), scaleByMapSize(5, 20) ], avoidClasses(clForest, 0, clPlayer, 8, clBaseResource, 4, clWater, 1, clFood, 10, clHill, 1), clFood); createFood( [ [new SimpleObject(oBerryBush, 5, 7, 0, 4)] ], [ 3 * numPlayers ], avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 10), clFood); Engine.SetProgress(90); var types = [oDatePalm, oSDatePalm, oCarob, oFanPalm, oPoplar, oCypress]; createStragglerTrees( types, avoidClasses(clForest, 1, clWater, 2, clPlayer, 12, clMetal, 6, clHill, 1), clForest, stragglerTrees); createStragglerTrees( types, stayClasses(clIsland, 4), clForest, stragglerTrees * 10); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clIsland, 10, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); setSkySet("cumulus"); setSunColor(0.866667, 0.776471, 0.486275); setWaterColor(0, 0.501961, 1); setWaterTint(0.501961, 1, 1); setWaterWaviness(4.0); setWaterType("ocean"); setWaterMurkiness(0.49); setFogFactor(0.3); setFogThickness(0.25); setPPEffect("hdr"); setPPContrast(0.62); setPPSaturation(0.51); setPPBloom(0.12); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/african_plains.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/african_plains.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/african_plains.js (revision 26381) @@ -1,307 +1,307 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); if (g_MapSettings.Biome) setSelectedBiome(); else setBiome("generic/savanna"); // Pick some biome defaults and overload a few settings. var tPrimary = g_Terrains.mainTerrain; var tForestFloor = g_Terrains.forestFloor1; var tCliff = ["savanna_cliff_a", "savanna_cliff_a_red", "savanna_cliff_b", "savanna_cliff_b_red"]; var tSecondary = g_Terrains.tier4Terrain; var tGrassShrubs = g_Terrains.tier1Terrain; var tDirt = g_Terrains.dirt; var tDirt2 = "savanna_dirt_a_red"; var tDirt3 = g_Terrains.dirt; var tDirt4 = g_Terrains.hill; var tCitytiles = "savanna_tile_a"; var tShore = g_Terrains.shore; var tWater = g_Terrains.water; var oBaobab = g_Gaia.tree1; var oPalm = g_Gaia.tree2; var oPalm2 = g_Gaia.tree3; var oBerryBush = "gaia/fruit/berry_01"; var oWildebeest = "gaia/fauna_wildebeest"; var oZebra = "gaia/fauna_zebra"; var oRhino = "gaia/fauna_rhinoceros_white"; var oLion = "gaia/fauna_lion"; var oLioness = "gaia/fauna_lioness"; var oHawk = "birds/buzzard"; var oGiraffe = "gaia/fauna_giraffe"; var oGiraffe2 = "gaia/fauna_giraffe_infant"; var oGazelle = "gaia/fauna_gazelle"; var oElephant = "gaia/fauna_elephant_african_bush"; var oElephant2 = "gaia/fauna_elephant_african_infant"; var oCrocodile = "gaia/fauna_crocodile_nile"; var oFish = g_Gaia.fish; var oStoneLarge = g_Gaia.stoneLarge; var oStoneSmall = g_Gaia.stoneSmall; var oMetalLarge = g_Gaia.metalLarge; var oMetalSmall = g_Gaia.metalSmall; var aBush = g_Decoratives.bushMedium; var aRock = g_Decoratives.rockMedium; const pForest = [tForestFloor + TERRAIN_SEPARATOR + oPalm, tForestFloor + TERRAIN_SEPARATOR + oPalm2, tForestFloor]; var heightSeaGround = -5; var heightLand = 2; var heightCliff = 3; var g_Map = new RandomMap(heightLand, tPrimary); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tPrimary, "innerTerrain": tCitytiles }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "type": "stone_formation", "template": oStoneSmall, "terrain": tDirt4 } ] }, "Trees": { "template": oBaobab, "count": scaleByMapSize(3, 12), "minDistGroup": 2, "maxDistGroup": 6, "minDist": 15, "maxDist": 16 } // No decoratives }); Engine.SetProgress(20); // The specificity of this map is a bunch of watering holes & hills making it somewhat cluttered. const nbHills = scaleByMapSize(6, 16); const nbWateringHoles = scaleByMapSize(4, 10); { g_Map.log("Creating hills"); createHills([tDirt2, tCliff, tGrassShrubs], avoidClasses(clPlayer, 30, clHill, 15), clHill, nbHills); Engine.SetProgress(30); g_Map.log("Creating water holes"); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), Math.floor(scaleByMapSize(60, 100)), Infinity), [ new LayeredPainter([tShore, tWater], [1]), new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 7), new TileClassPainter(clWater) ], avoidClasses(clPlayer, 22, clWater, 8, clHill, 2), nbWateringHoles); Engine.SetProgress(45); paintTerrainBasedOnHeight(heightCliff, Infinity, 0, tCliff); } createBumps(avoidClasses(clWater, 2, clPlayer, 20)); g_Map.log("Creating forests"); createDefaultForests( [tPrimary, pForest, tForestFloor, pForest, pForest], avoidClasses(clPlayer, 20, clForest, 15, clHill, 0, clWater, 2), clForest, scaleByMapSize(500, 3000)); Engine.SetProgress(50); g_Map.log("Creating dirt patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [[tDirt, tDirt3], [tDirt2, tDirt4]], [2], avoidClasses(clWater, 3, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(55); g_Map.log("Creating shrubs"); createPatches( [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)], tGrassShrubs, avoidClasses(clWater, 3, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(60); g_Map.log("Creating grass patches"); createPatches( [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)], tSecondary, avoidClasses(clWater, 3, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(65); g_Map.log("Creating metal mines"); createBalancedMetalMines( oMetalSmall, oMetalLarge, clMetal, avoidClasses(clWater, 4, clForest, 1, clPlayer, scaleByMapSize(20, 35), clHill, 1) ); g_Map.log("Creating stone mines"); createBalancedStoneMines( oStoneSmall, oStoneLarge, clRock, avoidClasses(clWater, 4, clForest, 1, clPlayer, scaleByMapSize(20, 35), clHill, 1, clMetal, 10) ); Engine.SetProgress(70); createDecoration( [ [new SimpleObject(aBush, 1,3, 0,1)], [new SimpleObject(aRock, 1,2, 0,1)] ], [ scaleByMapAreaAbsolute(8), scaleByMapAreaAbsolute(8) ], avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0)); Engine.SetProgress(75); // Roaming animals { var placeRoaming = function(name, objs) { g_Map.log("Creating roaming " + name); const group = new SimpleGroup(objs, true, clFood); createObjectGroups(group, 0, avoidClasses(clWater, 3, clPlayer, 20, clFood, 11, clHill, 4), scaleByMapSize(3, 9), 50 ); }; placeRoaming("giraffes", [new SimpleObject(oGiraffe, 2, 4, 0, 4), new SimpleObject(oGiraffe2, 0, 2, 0, 4)]); placeRoaming("elephants", [new SimpleObject(oElephant, 2, 4, 0, 4), new SimpleObject(oElephant2, 0, 2, 0, 4)]); placeRoaming("lions", [new SimpleObject(oLion, 0, 1, 0, 4), new SimpleObject(oLioness, 2, 3, 0, 4)]); // Other roaming animals createFood( [ [new SimpleObject(oHawk, 1, 1, 0, 3)], [new SimpleObject(oGazelle, 3, 5, 0, 3)], [new SimpleObject(oZebra, 3, 5, 0, 3)], [new SimpleObject(oWildebeest, 4, 6, 0, 3)], [new SimpleObject(oRhino, 1, 1, 0, 3)] ], [ 3 * numPlayers, 3 * numPlayers, 3 * numPlayers, 3 * numPlayers, 3 * numPlayers, ], avoidClasses(clFood, 20, clWater, 5, clHill, 2, clPlayer, 16), clFood); } // Animals that hang around watering holes { // TODO: these have a high retry factor because our mapgen constraint logic is bad. var placeWateringHoleAnimals = function(name, objs, numberOfGroups) { g_Map.log("Creating " + name + " around watering holes"); const group = new SimpleGroup(objs, true, clFood); createObjectGroups(group, 0, borderClasses(clWater, 6, 3), numberOfGroups, 50 ); }; placeWateringHoleAnimals( "crocodiles", [new SimpleObject(oCrocodile, 2, 3, 0, 3)], nbWateringHoles * 0.8 ); placeWateringHoleAnimals( "zebras", [new SimpleObject(oZebra, 2, 5, 0, 3)], nbWateringHoles ); placeWateringHoleAnimals( "gazelles", [new SimpleObject(oGazelle, 2, 5, 0, 3)], nbWateringHoles ); } g_Map.log("Creating other food sources"); createFood( [ [new SimpleObject(oBerryBush, 5, 7, 0, 4)] ], [ randIntInclusive(1, 4) * numPlayers + 2 ], avoidClasses(clWater, 3, clForest, 2, clPlayer, 20, clHill, 3, clFood, 10), clFood); createFood( [ [new SimpleObject(oFish, 2, 3, 0, 2)] ], [ 15 * numPlayers ], [avoidClasses(clFood, 20), stayClasses(clWater, 6)], clFood); Engine.SetProgress(85); g_Map.log("Creating straggler baobabs"); const group = new SimpleGroup([new SimpleObject(oBaobab, 1, 3, 0, 3)], true, clForest); createObjectGroups( group, 0, avoidClasses(clWater, 0, clForest, 2, clHill, 3, clPlayer, 12, clMetal, 4, clRock, 4), scaleByMapSize(15, 75) ); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); // Adjust some biome settings; setSkySet("sunny"); setWaterType("clap"); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/alpine_lakes.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/alpine_lakes.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/alpine_lakes.js (revision 26381) @@ -1,269 +1,269 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); if (randBool()) { RandomMapLogger.prototype.printDirectly("Setting late spring biome.\n"); setFogThickness(0.26); setFogFactor(0.4); setPPEffect("hdr"); setPPSaturation(0.48); setPPContrast(0.53); setPPBloom(0.12); var tPrimary = ["alpine_dirt_grass_50"]; var tForestFloor = "alpine_forrestfloor"; var tCliff = ["alpine_cliff_a", "alpine_cliff_b", "alpine_cliff_c"]; var tSecondary = "alpine_grass_rocky"; var tHalfSnow = ["alpine_grass_snow_50", "alpine_dirt_snow"]; var tSnowLimited = ["alpine_snow_rocky"]; var tDirt = "alpine_dirt"; var tRoad = "new_alpine_citytile"; var tRoadWild = "new_alpine_citytile"; var tShore = "alpine_shore_rocks_grass_50"; var tWater = "alpine_shore_rocks"; var oPine = "gaia/tree/pine"; var oBerryBush = "gaia/fruit/berry_01"; var oDeer = "gaia/fauna_deer"; var oFish = "gaia/fish/generic"; var oRabbit = "gaia/fauna_rabbit"; var oStoneLarge = "gaia/rock/alpine_large"; var oStoneSmall = "gaia/rock/alpine_small"; var oMetalLarge = "gaia/ore/alpine_large"; var aGrass = "actor|props/flora/grass_soft_small_tall.xml"; var aGrassShort = "actor|props/flora/grass_soft_large.xml"; var aRockLarge = "actor|geology/stone_granite_med.xml"; var aRockMedium = "actor|geology/stone_granite_med.xml"; var aBushMedium = "actor|props/flora/bush_medit_me.xml"; var aBushSmall = "actor|props/flora/bush_medit_sm.xml"; } else { RandomMapLogger.prototype.printDirectly("Setting winter spring biome.\n"); setFogFactor(0.35); setFogThickness(0.19); setPPSaturation(0.37); setPPEffect("hdr"); var tPrimary = ["alpine_snow_a", "alpine_snow_b"]; var tForestFloor = "alpine_forrestfloor_snow"; var tCliff = ["alpine_cliff_snow"]; var tSecondary = "alpine_grass_snow_50"; var tHalfSnow = ["alpine_grass_snow_50", "alpine_dirt_snow"]; var tSnowLimited = ["alpine_snow_a", "alpine_snow_b"]; var tDirt = "alpine_dirt"; var tRoad = "new_alpine_citytile"; var tRoadWild = "new_alpine_citytile"; var tShore = "alpine_shore_rocks_icy"; var tWater = "alpine_shore_rocks"; var oPine = "gaia/tree/pine_w"; var oBerryBush = "gaia/fruit/berry_01"; var oDeer = "gaia/fauna_deer"; var oFish = "gaia/fish/generic"; var oRabbit = "gaia/fauna_rabbit"; var oStoneLarge = "gaia/rock/alpine_large"; var oStoneSmall = "gaia/rock/alpine_small"; var oMetalLarge = "gaia/ore/alpine_large"; var aGrass = "actor|props/flora/grass_soft_dry_small_tall.xml"; var aGrassShort = "actor|props/flora/grass_soft_dry_large.xml"; var aRockLarge = "actor|geology/stone_granite_med.xml"; var aRockMedium = "actor|geology/stone_granite_med.xml"; var aBushMedium = "actor|props/flora/bush_medit_me_dry.xml"; var aBushSmall = "actor|props/flora/bush_medit_sm_dry.xml"; } const pForest = [tForestFloor + TERRAIN_SEPARATOR + oPine, tForestFloor]; var heightSeaGround = -5; var heightLand = 3; var g_Map = new RandomMap(heightLand, tPrimary); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oPine, "count": scaleByMapSize(3, 12) }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(20); createMountains(tCliff, avoidClasses(clPlayer, 20, clHill, 8), clHill, scaleByMapSize(10, 40) * numPlayers, Math.floor(scaleByMapSize(40, 60)), Math.floor(scaleByMapSize(4, 5)), Math.floor(scaleByMapSize(7, 15)), Math.floor(scaleByMapSize(5, 15))); Engine.SetProgress(30); g_Map.log("Creating lakes"); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(4, 8)), Math.floor(scaleByMapSize(40, 180)), 0.7), [ new LayeredPainter([tShore, tWater], [1]), new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 5), new TileClassPainter(clWater) ], avoidClasses(clPlayer, 20, clWater, 8), scaleByMapSize(5, 16), 1); paintTerrainBasedOnHeight(3, Math.floor(scaleByMapSize(20, 40)), 0, tCliff); paintTerrainBasedOnHeight(Math.floor(scaleByMapSize(20, 40)), 100, 3, tSnowLimited); createBumps(avoidClasses(clWater, 2, clPlayer, 20)); var [forestTrees, stragglerTrees] = getTreeCounts(500, 3000, 0.7); createForests( [tPrimary, tForestFloor, tForestFloor, pForest, pForest], avoidClasses(clPlayer, 20, clForest, 17, clHill, 0, clWater, 2), clForest, forestTrees); Engine.SetProgress(60); g_Map.log("Creating dirt patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [[tDirt,tHalfSnow], [tHalfSnow,tSnowLimited]], [2], avoidClasses(clWater, 3, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45), clDirt); g_Map.log("Creating grass patches"); createPatches( [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)], tSecondary, avoidClasses(clWater, 3, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(65); g_Map.log("Creating stone mines"); createMines( [ [new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), clRock); g_Map.log("Creating metal mines"); createMines( [ [new SimpleObject(oMetalLarge, 1,1, 0,4)] ], avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 1), clMetal ); Engine.SetProgress(70); createDecoration( [ [new SimpleObject(aRockMedium, 1, 3, 0, 1)], [new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)], [new SimpleObject(aGrassShort, 1, 2, 0, 1)], [new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3, 6, 1.2, 2.5)], [new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)] ], [ scaleByMapAreaAbsolute(16), scaleByMapAreaAbsolute(8), scaleByMapAreaAbsolute(13), scaleByMapAreaAbsolute(13), scaleByMapAreaAbsolute(13) ], avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0)); Engine.SetProgress(75); createFood( [ [new SimpleObject(oDeer, 5, 7, 0, 4)], [new SimpleObject(oRabbit, 2, 3, 0, 2)] ], [ 3 * numPlayers, 3 * numPlayers ], avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 20), clFood); createFood( [ [new SimpleObject(oBerryBush, 5, 7, 0, 4)] ], [ randIntInclusive(1, 4) * numPlayers + 2 ], avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 10), clFood); createFood( [ [new SimpleObject(oFish, 2, 3, 0, 2)] ], [ 15 * numPlayers ], [avoidClasses(clFood, 20), stayClasses(clWater, 6)], clFood); Engine.SetProgress(85); createStragglerTrees( [oPine], avoidClasses(clWater, 5, clForest, 3, clHill, 1, clPlayer, 12, clMetal, 6, clRock, 6), clForest, stragglerTrees); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); setSkySet(pickRandom(["cirrus", "cumulus", "sunny"])); setSunRotation(randomAngle()); setSunElevation(Math.PI * randFloat(1/5, 1/3)); setWaterColor(0.0, 0.047, 0.286); // dark majestic blue setWaterTint(0.471, 0.776, 0.863); // light blue setWaterMurkiness(0.82); setWaterWaviness(3.0); setWaterType("clap"); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/alpine_valley.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/alpine_valley.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/alpine_valley.js (revision 26381) @@ -1,544 +1,544 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); TILE_CENTERED_HEIGHT_MAP = true; /** * This class creates random mountainranges without enclosing any area completely. * * To determine their location, a graph is created where each vertex is a possible starting or * ending location of a mountainrange and each edge a possible mountainrange. * * That graph starts nearly complete (i.e almost every vertex is connected to most other vertices). * After a random edge was chosen and placed as a mountainrange, * all edges that intersect, that leave a too small gap to another mountainrange or that are connected to * too many other mountainranges are removed from the graph. * This is repeated until all edges were removed. */ function MountainRangeBuilder(args) { /** * These parameters paint the mountainranges after their location was determined. */ this.pathplacer = args.pathplacer; this.painters = args.painters; this.constraint = args.constraint; this.mountainWidth = args.mountainWidth; /** * Minimum geometric distance between two mountains that don't end in one place (disjoint edges). */ this.minDistance = args.mountainWidth + args.passageWidth; /** * Array of Vector2D locations where a mountainrange can start or end. */ this.vertices = args.points; /** * Number of mountainranges starting or ending at the given point. */ this.vertexDegree = this.vertices.map(p => 0); /** * Highest number of mountainranges that can meet in one point (maximum degree of each vertex). */ this.maxDegree = args.maxDegree; /** * Each possible edge is an array containing two vertex indices. * The algorithm adds possible edges consecutively and removes subsequently invalid edges. */ this.possibleEdges = []; this.InitPossibleEdges(); /** * A two-dimensional array of booleans that are true if the two corresponding vertices may be connected by a new edge (mountainrange). * It is initialized with some points that should never be connected and updated with every placed edge. * The purpose is to rule out any cycles in the graph, i.e. prevent any territory enclosed by mountainranges. */ this.verticesConnectable = []; this.InitConnectable(); /** * Currently iterated item of possibleEdges that is either used as a mountainrange or removed from the possibleEdges. */ this.index = undefined; /** * These variables hold the indices of the two points of that edge and the location of them as a Vector2D. */ this.currentEdge = undefined; this.currentEdgeStart = undefined; this.currentEdgeEnd = undefined; } MountainRangeBuilder.prototype.InitPossibleEdges = function() { for (let i = 0; i < this.vertices.length; ++i) for (let j = numPlayers; j < this.vertices.length; ++j) if (j > i) this.possibleEdges.push([i, j]); }; MountainRangeBuilder.prototype.InitConnectable = function() { for (let i = 0; i < this.vertices.length; ++i) { this.verticesConnectable[i] = []; for (let j = 0; j < this.vertices.length; ++j) this.verticesConnectable[i][j] = i >= numPlayers || j >= numPlayers || i == j || i != j - 1 && i != j + 1; } }; MountainRangeBuilder.prototype.SetConnectable = function(isConnectable) { this.verticesConnectable[this.currentEdge[0]][this.currentEdge[1]] = isConnectable; this.verticesConnectable[this.currentEdge[1]][this.currentEdge[0]] = isConnectable; }; MountainRangeBuilder.prototype.UpdateCurrentEdge = function() { this.currentEdge = this.possibleEdges[this.index]; this.currentEdgeStart = this.vertices[this.currentEdge[0]]; this.currentEdgeEnd = this.vertices[this.currentEdge[1]]; }; /** * Remove all edges that are too close to the current mountainrange or intersect. */ MountainRangeBuilder.prototype.RemoveInvalidEdges = function() { for (let i = 0; i < this.possibleEdges.length; ++i) { this.UpdateCurrentEdge(); let comparedEdge = this.possibleEdges[i]; let comparedEdgeStart = this.vertices[comparedEdge[0]]; let comparedEdgeEnd = this.vertices[comparedEdge[1]]; let edge0Equal = this.currentEdgeStart == comparedEdgeStart; let edge1Equal = this.currentEdgeStart == comparedEdgeEnd; let edge2Equal = this.currentEdgeEnd == comparedEdgeEnd; let edge3Equal = this.currentEdgeEnd == comparedEdgeStart; if (!edge0Equal && !edge2Equal && !edge1Equal && !edge3Equal && testLineIntersection(this.currentEdgeStart, this.currentEdgeEnd, comparedEdgeStart, comparedEdgeEnd, this.minDistance) || ( edge0Equal && !edge2Equal || !edge1Equal && edge3Equal) && distanceOfPointFromLine(this.currentEdgeStart, this.currentEdgeEnd, comparedEdgeEnd) < this.minDistance || (!edge0Equal && edge2Equal || edge1Equal && !edge3Equal) && distanceOfPointFromLine(this.currentEdgeStart, this.currentEdgeEnd, comparedEdgeStart) < this.minDistance) { this.possibleEdges.splice(i, 1); --i; if (this.index > i) --this.index; } } }; /** * Tests using depth-first-search if the graph according to pointsConnectable contains a cycle, * i.e. if adding the currentEdge would result in an area enclosed by mountainranges. */ MountainRangeBuilder.prototype.HasCycles = function() { let tree = []; let backtree = []; let pointQueue = [this.currentEdge[0]]; while (pointQueue.length) { let selectedPoint = pointQueue.shift(); if (tree.indexOf(selectedPoint) == -1) { tree.push(selectedPoint); backtree.push(-1); } for (let i = 0; i < this.vertices.length; ++i) { if (this.verticesConnectable[selectedPoint][i] || i == backtree[tree.lastIndexOf(selectedPoint)]) continue; // If the current point was encountered already, then a cycle was identified. if (tree.indexOf(i) != -1) return true; // Otherwise visit this point next pointQueue.unshift(i); tree.push(i); backtree.push(selectedPoint); } } return false; }; MountainRangeBuilder.prototype.PaintCurrentEdge = function() { this.pathplacer.start = this.currentEdgeStart; this.pathplacer.end = this.currentEdgeEnd; this.pathplacer.width = this.mountainWidth; // Creating mountainrange if (!createArea(this.pathplacer, this.painters, this.constraint)) return false; // Creating circular mountains at both ends of that mountainrange for (let point of [this.currentEdgeStart, this.currentEdgeEnd]) createArea( new ClumpPlacer(diskArea(this.mountainWidth / 2), 0.95, 0.6, Infinity, point), this.painters, this.constraint); return true; }; /** * This is the only function meant to be publicly accessible. */ MountainRangeBuilder.prototype.CreateMountainRanges = function() { g_Map.log("Creating mountainrange with " + this.possibleEdges.length + " possible edges"); let max = this.possibleEdges.length; while (this.possibleEdges.length) { Engine.SetProgress(35 - 15 * this.possibleEdges.length / max); this.index = randIntExclusive(0, this.possibleEdges.length); this.UpdateCurrentEdge(); this.SetConnectable(false); if (this.vertexDegree[this.currentEdge[0]] < this.maxDegree && this.vertexDegree[this.currentEdge[1]] < this.maxDegree && !this.HasCycles() && this.PaintCurrentEdge()) { ++this.vertexDegree[this.currentEdge[0]]; ++this.vertexDegree[this.currentEdge[1]]; this.RemoveInvalidEdges(); } else this.SetConnectable(true); this.possibleEdges.splice(this.index, 1); } }; if (randBool()) { RandomMapLogger.prototype.printDirectly("Setting late spring biome.\n"); var tPrimary = ["alpine_dirt_grass_50"]; var tForestFloor = "alpine_forrestfloor"; var tCliff = ["alpine_cliff_a", "alpine_cliff_b", "alpine_cliff_c"]; var tSecondary = "alpine_grass_rocky"; var tHalfSnow = ["alpine_grass_snow_50", "alpine_dirt_snow"]; var tSnowLimited = ["alpine_snow_rocky"]; var tDirt = "alpine_dirt"; var tRoad = "new_alpine_citytile"; var tRoadWild = "new_alpine_citytile"; var oPine = "gaia/tree/pine"; var oBerryBush = "gaia/fruit/berry_01"; var oDeer = "gaia/fauna_deer"; var oRabbit = "gaia/fauna_rabbit"; var oStoneLarge = "gaia/rock/alpine_large"; var oStoneSmall = "gaia/rock/alpine_small"; var oMetalLarge = "gaia/ore/alpine_large"; var aGrass = "actor|props/flora/grass_soft_small_tall.xml"; var aGrassShort = "actor|props/flora/grass_soft_large.xml"; var aRockLarge = "actor|geology/stone_granite_med.xml"; var aRockMedium = "actor|geology/stone_granite_med.xml"; var aBushMedium = "actor|props/flora/bush_medit_me.xml"; var aBushSmall = "actor|props/flora/bush_medit_sm.xml"; } else { RandomMapLogger.prototype.printDirectly("Setting winter biome.\n"); var tPrimary = ["alpine_snow_a", "alpine_snow_b"]; var tForestFloor = "alpine_forrestfloor_snow"; var tCliff = ["alpine_cliff_snow"]; var tSecondary = "alpine_grass_snow_50"; var tHalfSnow = ["alpine_grass_snow_50", "alpine_dirt_snow"]; var tSnowLimited = ["alpine_snow_a", "alpine_snow_b"]; var tDirt = "alpine_dirt"; var tRoad = "new_alpine_citytile"; var tRoadWild = "new_alpine_citytile"; var oPine = "gaia/tree/pine_w"; var oBerryBush = "gaia/fruit/berry_01"; var oDeer = "gaia/fauna_deer"; var oRabbit = "gaia/fauna_rabbit"; var oStoneLarge = "gaia/rock/alpine_large"; var oStoneSmall = "gaia/rock/alpine_small"; var oMetalLarge = "gaia/ore/alpine_large"; var aGrass = "actor|props/flora/grass_soft_dry_small_tall.xml"; var aGrassShort = "actor|props/flora/grass_soft_dry_large.xml"; var aRockLarge = "actor|geology/stone_granite_med.xml"; var aRockMedium = "actor|geology/stone_granite_med.xml"; var aBushMedium = "actor|props/flora/bush_medit_me_dry.xml"; var aBushSmall = "actor|props/flora/bush_medit_sm_dry.xml"; } var heightLand = 3; var heightOffsetBump = 2; var snowlineHeight = 29; var heightMountain = 30; const pForest = [tForestFloor + TERRAIN_SEPARATOR + oPine, tForestFloor]; var g_Map = new RandomMap(heightLand, tPrimary); const numPlayers = getNumPlayers(); const mapCenter = g_Map.getCenter(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var [playerIDs, playerPosition, playerAngle, startAngle] = playerPlacementCircle(fractionToTiles(0.35)); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oPine }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(20); new MountainRangeBuilder({ "pathplacer": new PathPlacer(undefined, undefined, undefined, 0.4, scaleByMapSize(3, 12), 0.1, 0.1, 0.1), "painters":[ new LayeredPainter([tCliff, tPrimary], [3]), new SmoothElevationPainter(ELEVATION_SET, heightMountain, 2), new TileClassPainter(clHill) ], "constraint": avoidClasses(clPlayer, 20), "passageWidth": scaleByMapSize(10, 15), "mountainWidth": scaleByMapSize(9, 15), "maxDegree": 3, "points": [ // Four points near each player ...distributePointsOnCircle(numPlayers, startAngle + Math.PI / numPlayers, fractionToTiles(0.49), mapCenter)[0], ...distributePointsOnCircle(numPlayers, startAngle + Math.PI / numPlayers * 1.4, fractionToTiles(0.34), mapCenter)[0], ...distributePointsOnCircle(numPlayers, startAngle + Math.PI / numPlayers * 0.6, fractionToTiles(0.34), mapCenter)[0], ...distributePointsOnCircle(numPlayers, startAngle + Math.PI / numPlayers, fractionToTiles(0.18), mapCenter)[0], mapCenter ] }).CreateMountainRanges(); Engine.SetProgress(35); paintTerrainBasedOnHeight(heightLand + 0.1, snowlineHeight, 0, tCliff); paintTerrainBasedOnHeight(snowlineHeight, heightMountain, 3, tSnowLimited); g_Map.log("Creating bumps"); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, Infinity), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), avoidClasses(clPlayer, 10), scaleByMapSize(100, 200)); Engine.SetProgress(40); g_Map.log("Creating hills"); createAreas( new ClumpPlacer(scaleByMapSize(40, 150), 0.2, 0.1, Infinity), [ new LayeredPainter([tCliff, tSnowLimited], [2]), new SmoothElevationPainter(ELEVATION_SET, heightMountain, 2), new TileClassPainter(clHill) ], avoidClasses(clPlayer, 20, clHill, 14), scaleByMapSize(10, 80) * numPlayers ); Engine.SetProgress(50); g_Map.log("Creating forests"); var [forestTrees, stragglerTrees] = getTreeCounts(500, 3000, 0.7); var types = [ [[tForestFloor, tPrimary, pForest], [tForestFloor, pForest]] ]; var size = forestTrees / (scaleByMapSize(2,8) * numPlayers); var num = Math.floor(size / types.length); for (let type of types) createAreas( new ClumpPlacer(forestTrees / num, 0.1, 0.1, Infinity), [ new LayeredPainter(type, [2]), new TileClassPainter(clForest) ], avoidClasses(clPlayer, 12, clForest, 10, clHill, 0), num); Engine.SetProgress(60); g_Map.log("Creating dirt patches"); for (let size of [scaleByMapSize(3, 48), scaleByMapSize(5, 84), scaleByMapSize(8, 128)]) createAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), [ new LayeredPainter([[tDirt, tHalfSnow], [tHalfSnow, tSnowLimited]], [2]), new TileClassPainter(clDirt) ], avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45)); g_Map.log("Creating grass patches"); for (let size of [scaleByMapSize(2, 32), scaleByMapSize(3, 48), scaleByMapSize(5, 80)]) createAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), new TerrainPainter(tSecondary), avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45)); Engine.SetProgress(65); g_Map.log("Creating stone mines"); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), scaleByMapSize(4,16), 100 ); g_Map.log("Creating small stone mines"); group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), scaleByMapSize(4,16), 100 ); g_Map.log("Creating metal mines"); group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4)], true, clMetal); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 1), scaleByMapSize(4,16), 100 ); Engine.SetProgress(70); g_Map.log("Creating small decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockMedium, 1,3, 0,1)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clForest, 0, clPlayer, 0, clHill, 0), scaleByMapSize(16, 262), 50 ); g_Map.log("Creating large decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockLarge, 1,2, 0,1), new SimpleObject(aRockMedium, 1,3, 0,2)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clForest, 0, clPlayer, 0, clHill, 0), scaleByMapSize(8, 131), 50 ); Engine.SetProgress(75); g_Map.log("Creating deer"); group = new SimpleGroup( [new SimpleObject(oDeer, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 10, clHill, 1, clFood, 20), 3 * numPlayers, 50 ); g_Map.log("Creating berry bush"); group = new SimpleGroup( [new SimpleObject(oBerryBush, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 20, clHill, 1, clFood, 10), randIntInclusive(1, 4) * numPlayers + 2, 50 ); g_Map.log("Creating rabbit"); group = new SimpleGroup( [new SimpleObject(oRabbit, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 10, clHill, 1, clFood, 20), 3 * numPlayers, 50 ); Engine.SetProgress(85); createStragglerTrees( [oPine], avoidClasses(clForest, 1, clHill, 1, clPlayer, 12, clMetal, 6, clRock, 6), clForest, stragglerTrees); g_Map.log("Creating small grass tufts"); var planetm = 1; group = new SimpleGroup( [new SimpleObject(aGrassShort, 1,2, 0,1, -Math.PI / 8, Math.PI / 8)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clHill, 2, clPlayer, 2, clDirt, 0), planetm * scaleByMapSize(13, 200) ); Engine.SetProgress(90); g_Map.log("Creating large grass tufts"); group = new SimpleGroup( [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)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clHill, 2, clPlayer, 2, clDirt, 1, clForest, 0), planetm * scaleByMapSize(13, 200) ); Engine.SetProgress(95); g_Map.log("Creating bushes"); group = new SimpleGroup( [new SimpleObject(aBushMedium, 1,2, 0,2), new SimpleObject(aBushSmall, 2,4, 0,2)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clHill, 1, clPlayer, 1, clDirt, 1), planetm * scaleByMapSize(13, 200), 50 ); placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); setSkySet(pickRandom(["cirrus", "cumulus", "sunny"])); setSunRotation(randomAngle()); setSunElevation(Math.PI * randFloat(1/5, 1/3)); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/anatolian_plateau.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/anatolian_plateau.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/anatolian_plateau.js (revision 26381) @@ -1,249 +1,251 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); const tPrimary = ["steppe_grass_a", "steppe_grass_c", "steppe_grass_d"]; const tGrass = ["steppe_grass_a", "steppe_grass_b", "steppe_grass_c", "steppe_grass_d"]; const tForestFloor = "steppe_grass_c"; const tGrassA = "steppe_grass_b"; const tGrassB = "steppe_grass_c"; const tGrassC = ["steppe_grass_b", "steppe_grass_c", "steppe_grass_d"]; const tGrassD = "steppe_grass_a"; const tDirt = ["steppe_dirt_a", "steppe_dirt_b"]; const tRoad = "road_stones"; const tRoadWild = "road_stones"; const oPoplar = "gaia/tree/poplar_lombardy"; const oBush = "gaia/tree/bush_temperate"; const oBerryBush = "gaia/fruit/berry_01"; const oRabbit = "gaia/fauna_rabbit"; +const oAnimal = "gaia/fauna_sheep"; const oSheep = "gaia/fauna_sheep"; const oStoneLarge = "gaia/rock/mediterranean_large"; const oStoneSmall = "gaia/rock/mediterranean_small"; const oMetalLarge = "gaia/ore/mediterranean_large"; const aGrass = "actor|props/flora/grass_soft_small_tall.xml"; const aGrassShort = "actor|props/flora/grass_soft_large.xml"; const aRockLarge = "actor|geology/stone_granite_med.xml"; const aRockMedium = "actor|geology/stone_granite_med.xml"; const aBushMedium = "actor|props/flora/bush_medit_me.xml"; const aBushSmall = "actor|props/flora/bush_medit_sm.xml"; const pForest = [tForestFloor + TERRAIN_SEPARATOR + oPoplar, tForestFloor]; var heightLand = 1; var heightOffsetBump = 2; var g_Map = new RandomMap(heightLand, tPrimary); var numPlayers = getNumPlayers(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { + "template": oAnimal }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oPoplar }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(20); g_Map.log("Creating bumps"); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(2, 5)), 0.5), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), avoidClasses(clPlayer, 13), scaleByMapSize(300, 800)); g_Map.log("Creating forests"); var [forestTrees, stragglerTrees] = getTreeCounts(220, 1000, 0.65); var types = [[[tForestFloor, tGrass, pForest], [tForestFloor, pForest]]]; var size = forestTrees / (scaleByMapSize(2,8) * numPlayers); var num = 4 * Math.floor(size / types.length); for (let type of types) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(2, 3)), 4, Infinity), [ new LayeredPainter(type, [2]), new TileClassPainter(clForest) ], avoidClasses(clPlayer, 13, clForest, 20, clHill, 1), num); Engine.SetProgress(50); g_Map.log("Creating grass patches"); createLayeredPatches( [scaleByMapSize(5, 48), scaleByMapSize(6, 84), scaleByMapSize(8, 128)], [[tGrass,tGrassA,tGrassC],[tGrass,tGrassA,tGrassC], [tGrass,tGrassA,tGrassC]], [1,1], avoidClasses(clForest, 0, clHill, 0, clDirt, 2, clPlayer, 10), scaleByMapSize(50, 70), clDirt); g_Map.log("Creating dirt patches"); createLayeredPatches( [scaleByMapSize(5, 32), scaleByMapSize(6, 48), scaleByMapSize(7, 80)], [tGrassD ,tDirt], [1], avoidClasses(clForest, 0, clHill, 0, clDirt, 2, clPlayer, 10), scaleByMapSize(50, 90), clDirt); Engine.SetProgress(55); g_Map.log("Creating big patches"); createLayeredPatches( [scaleByMapSize(10, 60), scaleByMapSize(15, 90), scaleByMapSize(20, 120)], [tGrassB ,tGrassA], [1], avoidClasses(clHill, 0, clPlayer, 8), scaleByMapSize(30, 90), clDirt); Engine.SetProgress(60); g_Map.log("Creating stone mines"); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), scaleByMapSize(1,4), 100 ); g_Map.log("Creating small stone quarries"); group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), scaleByMapSize(1,4), 100 ); g_Map.log("Creating metal mines"); group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4)], true, clMetal); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 1), scaleByMapSize(2,8), 100 ); Engine.SetProgress(65); g_Map.log("Creating small decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockMedium, 1,3, 0,1)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clForest, 0, clPlayer, 10, clHill, 0), scaleByMapSize(16, 262), 50 ); g_Map.log("Creating large decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockLarge, 1,2, 0,1), new SimpleObject(aRockMedium, 1,3, 0,2)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clForest, 0, clPlayer, 10, clHill, 0), scaleByMapSize(8, 131), 50 ); Engine.SetProgress(70); g_Map.log("Creating rabbits"); group = new SimpleGroup( [new SimpleObject(oRabbit, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 10, clHill, 1, clFood, 20), 6 * numPlayers, 50 ); g_Map.log("Creating berry bush"); group = new SimpleGroup( [new SimpleObject(oBerryBush, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 20, clHill, 1, clFood, 20), randIntInclusive(1, 4) * numPlayers + 2, 50 ); Engine.SetProgress(75); g_Map.log("Creating sheep"); group = new SimpleGroup( [new SimpleObject(oSheep, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 10, clHill, 1, clFood, 20), 3 * numPlayers, 50 ); Engine.SetProgress(85); createStragglerTrees( [oBush, oPoplar], avoidClasses(clForest, 1, clHill, 1, clPlayer, 13, clMetal, 6, clRock, 6), clForest, stragglerTrees); g_Map.log("Creating large grass tufts"); group = new SimpleGroup( [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)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clHill, 2, clPlayer, 10, clDirt, 1, clForest, 0), scaleByMapSize(13, 200) ); Engine.SetProgress(95); g_Map.log("Creating bushes"); group = new SimpleGroup( [new SimpleObject(aBushMedium, 1,2, 0,2), new SimpleObject(aBushSmall, 2,4, 0,2)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clHill, 1, clPlayer, 1, clDirt, 1), scaleByMapSize(13, 200), 50 ); placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); setFogThickness(0.1); setFogFactor(0.2); setPPEffect("hdr"); setPPSaturation(0.45); setPPContrast(0.62); setPPBloom(0.2); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/archipelago.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/archipelago.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/archipelago.js (revision 26381) @@ -1,277 +1,277 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); TILE_CENTERED_HEIGHT_MAP = true; setSelectedBiome(); const biomeTweaks = Engine.ReadJSONFile("maps/random/archipelago_biome_tweaks.json"); const tMainTerrain = g_Terrains.mainTerrain; const tForestFloor1 = g_Terrains.forestFloor1; const tForestFloor2 = g_Terrains.forestFloor2; const tCliff = g_Terrains.cliff; const tTier1Terrain = g_Terrains.tier1Terrain; const tTier2Terrain = g_Terrains.tier2Terrain; const tTier3Terrain = g_Terrains.tier3Terrain; const tHill = g_Terrains.hill; const tTier4Terrain = g_Terrains.dirt; const tRoad = g_Terrains.road; const tRoadWild = g_Terrains.roadWild; const tShore = g_Terrains.shore; const tWater = g_Terrains.water; const oTree1 = g_Gaia.tree1; const oTree2 = g_Gaia.tree2; const oTree3 = g_Gaia.tree3; const oTree4 = g_Gaia.tree4; const oTree5 = g_Gaia.tree5; const oFruitBush = g_Gaia.fruitBush; const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal; const oFish = g_Gaia.fish; const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal; const oStoneLarge = g_Gaia.stoneLarge; const oStoneSmall = g_Gaia.stoneSmall; const oMetalLarge = g_Gaia.metalLarge; const oWoodTreasure = "gaia/treasure/wood"; const aGrass = g_Decoratives.grass; const aGrassShort = g_Decoratives.grassShort; const aRockLarge = g_Decoratives.rockLarge; const aRockMedium = g_Decoratives.rockMedium; const aBushMedium = g_Decoratives.bushMedium; const aBushSmall = g_Decoratives.bushSmall; const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2]; const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1]; var heightSeaGround = -5; var heightLand = 3; var heightShore = 1; var g_Map = new RandomMap(heightSeaGround, tWater); const numPlayers = getNumPlayers(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clLand = g_Map.createTileClass(); var islandRadius = scaleByMapSize(22, 31); var [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); g_Map.log("Creating player islands"); for (let i = 0; i < numPlayers; ++i) createArea( new ChainPlacer( 2, Math.floor(scaleByMapSize(5, 10)), Math.floor(scaleByMapSize(25, 60)), Infinity, playerPosition[i], 0, [Math.floor(islandRadius)]), [ new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), new TileClassPainter(clLand) ]); g_Map.log("Creating random islands"); createAreas( new ChainPlacer( Math.floor(scaleByMapSize(4, 8)), Math.floor(scaleByMapSize(8, 14)), Math.floor(scaleByMapSize(25, 60)), 0.07, undefined, scaleByMapSize(30, 70)), [ new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), new TileClassPainter(clLand) ], null, scaleByMapSize(1, 5) * randIntInclusive(5, 10)); paintTerrainBasedOnHeight(heightLand - 0.6, heightLand + 0.4, 3, tMainTerrain); paintTerrainBasedOnHeight(heightShore, heightLand, 0, tShore); paintTerrainBasedOnHeight(heightSeaGround, heightShore, 2, tWater); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], // PlayerTileClass marked below "BaseResourceClass": clBaseResource, "Walls": "towers", "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad, "radius": islandRadius / 3, "painters": [ new TileClassPainter(clPlayer) ] }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oFruitBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Treasures": { "types": [ { "template": oWoodTreasure, "count": 14 } ] }, "Trees": { "template": oTree1, "count": scaleByMapSize(15, 30) }, "Decoratives": { "template": aGrassShort, } }); createBumps([avoidClasses(clPlayer, 10), stayClasses(clLand, 5)]); if (randBool()) createHills([tMainTerrain, tCliff, tHill], [avoidClasses(clPlayer, 2, clHill, 15), stayClasses(clLand, 0)], clHill, scaleByMapSize(1, 4) * numPlayers); else createMountains(tCliff, [avoidClasses(clPlayer, 2, clHill, 15), stayClasses(clLand, 0)], clHill, scaleByMapSize(1, 4) * numPlayers); // adjust biomes (especially wood) const biomeSpecifics = biomeTweaks[currentBiome()] || biomeTweaks.baseline; var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(biomeSpecifics.treeAmount)); createForests( [tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2], [avoidClasses(clPlayer, biomeSpecifics.forestPlayerSpacing, clForest, biomeSpecifics.forestForestSpacing, clHill, 0), stayClasses(clLand, 3)], clForest, forestTrees ); Engine.SetProgress(50); g_Map.log("Creating dirt patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [[tMainTerrain, tTier1Terrain], [tTier1Terrain, tTier2Terrain], [tTier2Terrain, tTier3Terrain]], [1, 1], [avoidClasses(clForest, 0, clHill, 0, clDirt, 3, clPlayer, 12), stayClasses(clLand, 7)], scaleByMapSize(15, 45), clDirt ); g_Map.log("Creating grass patches"); createPatches( [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)], tTier4Terrain, [avoidClasses(clForest, 0, clHill, 0, clDirt, 3, clPlayer, 12), stayClasses(clLand, 7)], scaleByMapSize(15, 45), clDirt ); Engine.SetProgress(55); g_Map.log("Creating stone mines"); createMines( [ [new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4)], [new SimpleObject(oStoneSmall, 2, 5, 1, 3)] ], [avoidClasses(clForest, 1, clPlayer, 7, clRock, 10, clHill, 1), stayClasses(clLand, 6)], clRock ); g_Map.log("Creating metal mines"); createMines( [[new SimpleObject(oMetalLarge, 1, 1, 0, 4)]], [avoidClasses(clForest, 1, clPlayer, 7, clMetal, 10, clRock, 5, clHill, 1), stayClasses(clLand, 6)], clMetal ); Engine.SetProgress(65); var planetm = currentBiome() == "generic/india" ? 8 : 1; createDecoration( [ [new SimpleObject(aRockMedium, 1, 3, 0, 1)], [new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)], [new SimpleObject(aGrassShort, 1, 2, 0, 1)], [new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3, 6, 1.2, 2.5)], [new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)] ], [ scaleByMapAreaAbsolute(16), scaleByMapAreaAbsolute(8), planetm * scaleByMapAreaAbsolute(13), planetm * scaleByMapAreaAbsolute(13), planetm * scaleByMapAreaAbsolute(13) ], [avoidClasses(clForest, 0, clPlayer, 0, clHill, 0), stayClasses(clLand, 5)]); Engine.SetProgress(70); createFood( [ [new SimpleObject(oMainHuntableAnimal, 5, 7, 0, 4)], [new SimpleObject(oSecondaryHuntableAnimal, 2, 3, 0, 2)] ], [ 3 * numPlayers, 3 * numPlayers ], [avoidClasses(clForest, 0, clPlayer, 1, clHill, 1, clFood, 20), stayClasses(clLand, 3)], clFood); Engine.SetProgress(75); createFood( [ [new SimpleObject(oFruitBush, 5, 7, 0, 4)] ], [ 3 * numPlayers ], [avoidClasses(clForest, 0, clPlayer, 1, clHill, 1, clFood, 10), stayClasses(clLand, 3)], clFood); Engine.SetProgress(80); createFood( [ [new SimpleObject(oFish, 2, 3, 0, 2)] ], [ 25 * numPlayers ], avoidClasses(clLand, 3, clPlayer, 2, clFood, 20), clFood); Engine.SetProgress(85); createStragglerTrees( [oTree1, oTree2, oTree4, oTree3], [avoidClasses(clForest, 7, clHill, 1, clPlayer, 3, clMetal, 6, clRock, 6), stayClasses(clLand, 7)], clForest, stragglerTrees); placePlayersNomad( clPlayer, new AndConstraint([ stayClasses(clLand, 4), avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)])); setWaterWaviness(4.0); setWaterType("ocean"); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/arctic_summer.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/arctic_summer.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/arctic_summer.js (revision 26381) @@ -1,323 +1,323 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); setFogThickness(0.46); setFogFactor(0.5); setPPEffect("hdr"); setPPSaturation(0.48); setPPContrast(0.53); setPPBloom(0.12); var tPrimary = ["alpine_grass_rocky"]; var tForestFloor = "alpine_grass"; var tCliff = ["polar_cliff_a", "polar_cliff_b", "polar_cliff_snow"]; var tSecondary = "alpine_grass"; var tHalfSnow = ["polar_grass_snow", "ice_dirt"]; var tSnowLimited = ["polar_snow_rocks", "polar_ice"]; var tDirt = "ice_dirt"; var tShore = "alpine_shore_rocks"; var tWater = "polar_ice_b"; var tHill = "polar_ice_cracked"; var oBush = "gaia/tree/bush_badlands"; var oBush2 = "gaia/tree/bush_temperate"; var oBerryBush = "gaia/fruit/berry_01"; var oRabbit = "gaia/fauna_rabbit"; var oMuskox = "gaia/fauna_muskox"; var oDeer = "gaia/fauna_deer"; var oWolf = "gaia/fauna_wolf"; var oWhaleFin = "gaia/fauna_whale_fin"; var oWhaleHumpback = "gaia/fauna_whale_humpback"; var oFish = "gaia/fish/generic"; var oStoneLarge = "gaia/rock/alpine_large"; var oStoneSmall = "gaia/rock/alpine_small"; var oMetalLarge = "gaia/ore/alpine_large"; var oWoodTreasure = "gaia/treasure/wood"; var aRockLarge = "actor|geology/stone_granite_med.xml"; var aRockMedium = "actor|geology/stone_granite_med.xml"; const pForest = [tForestFloor + TERRAIN_SEPARATOR + oBush, tForestFloor + TERRAIN_SEPARATOR + oBush2, tForestFloor]; var heightSeaGround = -5; var heightLand = 2; var g_Map = new RandomMap(heightLand, tPrimary); const numPlayers = getNumPlayers(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tPrimary, "innerTerrain": tSecondary }, - "Chicken": { + "StartingAnimal": { "template": oRabbit }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Treasures": { "types": [ { "template": oWoodTreasure, "count": 10 } ] }, "Trees": { "template": oBush, "count": 20, "maxDistGroup": 3 } // No decoratives }); Engine.SetProgress(20); createHills( [tPrimary, tCliff, tHill], avoidClasses( clPlayer, 35, clForest, 20, clHill, 50, clWater, 2), clHill, scaleByMapSize(1, 240)); Engine.SetProgress(30); g_Map.log("Creating lakes"); createAreas( new ChainPlacer( 1, Math.floor(scaleByMapSize(4, 8)), Math.floor(scaleByMapSize(40, 180)), Infinity), [ new LayeredPainter([tShore, tWater], [1]), new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 5), new TileClassPainter(clWater) ], avoidClasses(clPlayer, 15), scaleByMapSize(1, 20)); Engine.SetProgress(45); createBumps(avoidClasses(clPlayer, 6, clWater, 2), scaleByMapSize(30, 300), 1, 8, 4, 0, 3); paintTerrainBasedOnHeight(4, 15, 0, tCliff); paintTerrainBasedOnHeight(15, 100, 3, tSnowLimited); var [forestTrees, stragglerTrees] = getTreeCounts(500, 3000, 0.7); createForests( [tSecondary, tForestFloor, tForestFloor, pForest, pForest], avoidClasses( clPlayer, 20, clForest, 14, clHill, 20, clWater, 2), clForest, forestTrees); Engine.SetProgress(60); g_Map.log("Creating dirt patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [[tDirt,tHalfSnow], [tHalfSnow,tSnowLimited]], [2], avoidClasses( clWater, 3, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45), clDirt); g_Map.log("Creating shrubs"); createPatches( [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)], tSecondary, avoidClasses( clWater, 3, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45), clDirt); g_Map.log("Creating grass patches"); createPatches( [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)], tSecondary, avoidClasses( clWater, 3, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(65); g_Map.log("Creating stone mines"); createMines( [ [new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], [new SimpleObject(oStoneSmall, 2, 5, 1, 3)] ], avoidClasses( clWater, 3, clForest, 1, clPlayer, 20, clRock, 18, clHill, 1), clRock); g_Map.log("Creating metal mines"); createMines( [ [new SimpleObject(oMetalLarge, 1, 1, 0, 4)] ], avoidClasses( clWater, 3, clForest, 1, clPlayer, 20, clMetal, 18, clRock, 5, clHill, 1), clMetal); Engine.SetProgress(70); createDecoration( [ [ new SimpleObject(aRockMedium, 1, 3, 0, 1) ], [ new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 1) ] ], [ scaleByMapAreaAbsolute(16), scaleByMapAreaAbsolute(8), ], avoidClasses( clWater, 0, clForest, 0, clPlayer, 0, clHill, 0)); Engine.SetProgress(75); createFood( [ [new SimpleObject(oWolf, 3, 5, 0, 3)], [new SimpleObject(oRabbit, 6, 8, 0, 6)], [new SimpleObject(oDeer, 3, 4, 0, 3)], [new SimpleObject(oMuskox, 3, 4, 0, 3)] ], [ 3 * numPlayers, 3 * numPlayers, 3 * numPlayers, 3 * numPlayers ], avoidClasses( clFood, 20, clHill, 5, clWater, 5), clFood); createFood( [ [new SimpleObject(oWhaleFin, 1, 1, 0, 3)], [new SimpleObject(oWhaleHumpback, 1, 1, 0, 3)] ], [ 3 * numPlayers, 3 * numPlayers ], [ avoidClasses(clFood, 20), stayClasses(clWater, 6) ], clFood); createFood( [ [new SimpleObject(oBerryBush, 5, 7, 0, 4)] ], [ randIntInclusive(1, 4) * numPlayers + 2 ], avoidClasses( clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 10), clFood); createFood( [ [new SimpleObject(oFish, 2, 3, 0, 2)] ], [ 15 * numPlayers ], [ avoidClasses(clFood, 20), stayClasses(clWater, 6) ], clFood); Engine.SetProgress(85); createStragglerTrees( [oBush, oBush2], avoidClasses( clWater, 5, clForest, 3, clHill, 1, clPlayer, 12, clMetal, 4, clRock, 4), clForest, stragglerTrees); placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clWater, 4, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); setSkySet("sunset 1"); setSunRotation(randomAngle()); setSunColor(0.8, 0.7, 0.6); setAmbientColor(0.6, 0.5, 0.6); setSunElevation(Math.PI * randFloat(1/12, 1/7)); setWaterColor(0, 0.047, 0.286); setWaterTint(0.462, 0.756, 0.866); setWaterMurkiness(0.92); setWaterWaviness(1); setWaterType("clap"); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/ardennes_forest.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/ardennes_forest.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/ardennes_forest.js (revision 26381) @@ -1,462 +1,462 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); setBiome("generic/temperate"); const tPrimary = ["steppe_grass_03", "steppe_grass_03", "alpine_cliff_c", "temperate_grass_mud_01"]; const tGrass = ["steppe_grass_04", "steppe_grass_04", "aegean_grass_dirt_03"]; const tPineForestFloor = "steppe_grass_03"; const tForestFloor = [tPineForestFloor, tPineForestFloor, "temperate_grass_mud_01"]; const tCliff = ["alpine_cliff_c", "alpine_cliff_c", "temperate_cliff_01"]; const tCity = ["new_alpine_citytile", "new_alpine_grass_dirt_a"]; const tGrassPatch = ["alpine_grass_d"]; const oBoar = "gaia/fauna_boar"; const oDeer = "gaia/fauna_deer"; const oBear = "gaia/fauna_bear_brown"; const oPig = "gaia/fauna_pig"; const oBerryBush = "gaia/fruit/berry_01"; const oMetalSmall = "gaia/ore/alpine_small"; const oMetalLarge = "gaia/ore/temperate_large"; const oStoneSmall = "gaia/rock/alpine_small"; const oStoneLarge = "gaia/rock/temperate_large"; const oOak = "gaia/tree/oak"; const oOakLarge = "gaia/tree/oak_large"; const oPine = "gaia/tree/pine"; const oAleppoPine = "gaia/tree/fir"; const aTreeA = "actor|flora/trees/oak.xml"; const aTreeB = "actor|flora/trees/oak_large.xml"; const aTreeC = "actor|flora/trees/pine.xml"; const aTreeD = "actor|flora/trees/fir_tree.xml"; const aTrees = [aTreeA, aTreeB, aTreeC, aTreeD]; const aGrassLarge = "actor|props/flora/grass_soft_large.xml"; const aWoodLarge = "actor|props/special/eyecandy/wood_pile_1_b.xml"; const aWoodA = "actor|props/special/eyecandy/wood_sm_pile_a.xml"; const aWoodB = "actor|props/special/eyecandy/wood_sm_pile_b.xml"; const aBarrel = "actor|props/special/eyecandy/barrel_a.xml"; const aWheel = "actor|props/special/eyecandy/wheel_laying.xml"; const aCeltHomestead = "actor|structures/celts/homestead.xml"; const aCeltHouse = "actor|structures/celts/house.xml"; const aCeltLongHouse = "actor|structures/celts/longhouse.xml"; var pForest = [ tPineForestFloor+TERRAIN_SEPARATOR+oOak, tForestFloor, tPineForestFloor+TERRAIN_SEPARATOR+oPine, tForestFloor, tPineForestFloor+TERRAIN_SEPARATOR+oAleppoPine, tForestFloor, tForestFloor ]; const heightRavineValley = 2; const heightLand = 30; const heightRavineHill = 40; const heightHill = 50; const heightOffsetRavine = 10; var g_Map = new RandomMap(heightHill, tPrimary); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clForestJoin = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clHillDeco = g_Map.createTileClass(); var clExplorable = g_Map.createTileClass(); g_Map.log("Creating the central dip"); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.44)), 0.94, 0.05, 0.1, mapCenter), [ new LayeredPainter([tCliff, tGrass], [3]), new SmoothElevationPainter(ELEVATION_SET, heightLand, 3) ]); Engine.SetProgress(5); g_Map.log("Finding hills"); var noise0 = new Noise2D(20); for (var ix = 0; ix < mapSize; ix++) for (var iz = 0; iz < mapSize; iz++) { let position = new Vector2D(ix, iz); let h = g_Map.getHeight(position); if (h > heightRavineHill) { clHill.add(position); // Add hill noise var x = ix / (mapSize + 1.0); var z = iz / (mapSize + 1.0); var n = (noise0.get(x, z) - 0.5) * heightRavineHill; g_Map.setHeight(position, h + n); } } var [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.3)); function distanceToPlayers(x, z) { var r = 10000; for (var i = 0; i < numPlayers; i++) { var dx = x - tilesToFraction(playerPosition[i].x); var dz = z - tilesToFraction(playerPosition[i].y); r = Math.min(r, Math.square(dx) + Math.square(dz)); } return Math.sqrt(r); } function playerNearness(x, z) { var d = fractionToTiles(distanceToPlayers(x,z)); if (d < 13) return 0; if (d < 19) return (d-13)/(19-13); return 1; } Engine.SetProgress(10); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "BaseResourceClass": clBaseResource, // Playerclass marked below "CityPatch": { "outerTerrain": tCity, "innerTerrain": tCity, "radius": scaleByMapSize(5, 6), "smoothness": 0.05 }, - "Chicken": { + "StartingAnimal": { "template": oPig }, "Berries": { "template": oBerryBush, "minCount": 3, "maxCount": 3 }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ], "distance": 16 }, "Trees": { "template": oOak, "count": 2 } // No decoratives }); g_Map.log("Marking player territory"); for (let i = 0; i < numPlayers; ++i) createArea( new ClumpPlacer(250, 0.95, 0.3, 0.1, playerPosition[i]), new TileClassPainter(clPlayer)); Engine.SetProgress(30); g_Map.log("Creating hills"); for (let size of [scaleByMapSize(50, 800), scaleByMapSize(50, 400), scaleByMapSize(10, 30), scaleByMapSize(10, 30)]) { let mountains = createAreas( new ClumpPlacer(size, 0.1, 0.2, 0.1), [ new LayeredPainter([tCliff, [tForestFloor, tForestFloor, tCliff]], [2]), new SmoothElevationPainter(ELEVATION_SET, heightHill, size < 50 ? 2 : 4), new TileClassPainter(clHill) ], avoidClasses(clPlayer, 8, clBaseResource, 2, clHill, 5), scaleByMapSize(1, 4)); if (size > 100 && mountains.length) createAreasInAreas( new ClumpPlacer(size * 0.3, 0.94, 0.05, 0.1), [ new LayeredPainter([tCliff, tForestFloor], [2]), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetRavine, 3) ], stayClasses(clHill, 4), mountains.length * 2, 20, mountains); let ravine = createAreas( new ClumpPlacer(size, 0.1, 0.2, 0.1), [ new LayeredPainter([tCliff, tForestFloor], [2]), new SmoothElevationPainter(ELEVATION_SET, heightRavineValley, 2), new TileClassPainter(clHill) ], avoidClasses(clPlayer, 6, clBaseResource, 2, clHill, 5), scaleByMapSize(1, 3)); if (size > 150 && ravine.length) { g_Map.log("Placing huts in ravines"); createObjectGroupsByAreasDeprecated( new RandomGroup( [ new SimpleObject(aCeltHouse, 0, 1, 4, 5), new SimpleObject(aCeltLongHouse, 1, 1, 4, 5) ], true, clHillDeco), 0, [avoidClasses(clHillDeco, 3), stayClasses(clHill, 3)], ravine.length * 5, 20, ravine); createObjectGroupsByAreasDeprecated( new RandomGroup([new SimpleObject(aCeltHomestead, 1, 1, 1, 1)], true, clHillDeco), 0, [avoidClasses(clHillDeco, 5), stayClasses(clHill, 4)], ravine.length * 2, 100, ravine); // Place noise createAreasInAreas( new ClumpPlacer(size * 0.3, 0.94, 0.05, 0.1), [ new LayeredPainter([tCliff, tForestFloor], [2]), new SmoothElevationPainter(ELEVATION_SET, heightRavineValley, 2) ], [avoidClasses(clHillDeco, 2), stayClasses(clHill, 0)], ravine.length * 2, 20, ravine); createAreasInAreas( new ClumpPlacer(size * 0.1, 0.3, 0.05, 0.1), [ new LayeredPainter([tCliff, tForestFloor], [2]), new SmoothElevationPainter(ELEVATION_SET, heightRavineHill, 2), new TileClassPainter(clHill) ], [avoidClasses(clHillDeco, 2), borderClasses(clHill, 15, 1)], ravine.length * 2, 50, ravine); } } Engine.SetProgress(50); for (var ix = 0; ix < mapSize; ix++) for (var iz = 0; iz < mapSize; iz++) { let position = new Vector2D(ix, iz); let h = g_Map.getHeight(position); if (h > 35 && randBool(0.1) || h < 15 && randBool(0.05) && clHillDeco.countMembersInRadius(position, 1) == 0) g_Map.placeEntityAnywhere( pickRandom(aTrees), 0, randomPositionOnTile(position), randomAngle()); } var explorableArea = createArea( new MapBoundsPlacer(), undefined, [ new HeightConstraint(15, 45), avoidClasses(clPlayer, 1) ]); new TileClassPainter(clExplorable).paint(explorableArea); Engine.SetProgress(55); // Add some general noise - after placing height dependant trees for (var ix = 0; ix < mapSize; ix++) { var x = ix / (mapSize + 1.0); for (var iz = 0; iz < mapSize; iz++) { let position = new Vector2D(ix, iz); var z = iz / (mapSize + 1.0); var h = g_Map.getHeight(position); var pn = playerNearness(x,z); var n = (noise0.get(x,z) - 0.5) * 10; g_Map.setHeight(position, h + (n * pn)); } } Engine.SetProgress(60); g_Map.log("Creating forests"); var [forestTrees, stragglerTrees] = getTreeCounts(1300, 8000, 0.8); var [forestTreesJoin, forestTrees] = getTreeCounts(forestTrees, forestTrees, 0.25); var num = forestTrees / scaleByMapSize(20, 70); createAreasInAreas( new ClumpPlacer(forestTrees / num, 0.1, 0.1, Infinity), [ new TerrainPainter(pForest), new TileClassPainter(clForest) ], avoidClasses(clPlayer, 5, clBaseResource, 4, clForest, 5, clHill, 4), num, 100, [explorableArea] ); var num = forestTreesJoin / (scaleByMapSize(4, 6) * numPlayers); createAreasInAreas( new ClumpPlacer(forestTreesJoin / num, 0.1, 0.1, Infinity), [ new TerrainPainter(pForest), new TileClassPainter(clForest), new TileClassPainter(clForestJoin) ], [avoidClasses(clPlayer, 5, clBaseResource, 4, clForestJoin, 5, clHill, 4), borderClasses(clForest, 1, 4)], num, 100, [explorableArea] ); Engine.SetProgress(70); g_Map.log("Creating grass patches"); for (let size of [scaleByMapSize(3, 48), scaleByMapSize(5, 84), scaleByMapSize(8, 128)]) createAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), new TerrainPainter([tGrass, tGrassPatch]), avoidClasses(clForest, 0, clHill, 2, clPlayer, 5), scaleByMapSize(15, 45)); g_Map.log("Creating chopped forest patches"); for (let size of [scaleByMapSize(20, 120)]) createAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), new TerrainPainter(tForestFloor), avoidClasses(clForest, 1, clHill, 2, clPlayer, 5), scaleByMapSize(4, 12)); Engine.SetProgress(75); g_Map.log("Creating metal mines"); createBalancedMetalMines( oMetalSmall, oMetalLarge, clMetal, [stayClasses(clExplorable, 1), avoidClasses(clForest, 0, clPlayer, scaleByMapSize(15, 25), clHill, 1)] ); g_Map.log("Creating stone mines"); createBalancedStoneMines( oStoneSmall, oStoneLarge, clRock, [stayClasses(clExplorable, 1), avoidClasses(clForest, 0, clPlayer, scaleByMapSize(15, 25), clHill, 1, clMetal, 10)] ); Engine.SetProgress(80); g_Map.log("Creating wildlife"); let group = new SimpleGroup( [new SimpleObject(oDeer, 5,7, 0,4)], true, clFood ); createObjectGroupsByAreasDeprecated(group, 0, avoidClasses(clHill, 4, clForest, 0, clPlayer, 0, clBaseResource, 20), 3 * numPlayers, 100, [explorableArea] ); group = new SimpleGroup( [new SimpleObject(oBoar, 2,3, 0,5)], true, clFood ); createObjectGroupsByAreasDeprecated(group, 0, avoidClasses(clHill, 4, clForest, 0, clPlayer, 0, clBaseResource, 15), numPlayers, 50, [explorableArea] ); group = new SimpleGroup( [new SimpleObject(oBear, 1,1, 0,4)], false, clFood ); createObjectGroupsByAreasDeprecated(group, 0, avoidClasses(clHill, 4, clForest, 0, clPlayer, 20), scaleByMapSize(3, 12), 200, [explorableArea] ); Engine.SetProgress(85); g_Map.log("Creating berry bush"); group = new SimpleGroup( [new SimpleObject(oBerryBush, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 20, clHill, 4, clFood, 20), randIntInclusive(3, 12) * numPlayers + 2, 50 ); g_Map.log("Creating decorative props"); group = new SimpleGroup( [ new SimpleObject(aWoodA, 1,2, 0,1), new SimpleObject(aWoodB, 1,3, 0,1), new SimpleObject(aWheel, 0,2, 0,1), new SimpleObject(aWoodLarge, 0,1, 0,1), new SimpleObject(aBarrel, 0,2, 0,1) ], true ); createObjectGroupsByAreasDeprecated( group, 0, avoidClasses(clForest, 0), scaleByMapSize(5, 50), 50, [explorableArea] ); Engine.SetProgress(90); g_Map.log("Creating straggler trees"); var types = [oOak, oOakLarge, oPine, oAleppoPine]; var num = Math.floor(stragglerTrees / types.length); for (let type of types) createObjectGroupsByAreasDeprecated( new SimpleGroup([new SimpleObject(type, 1, 1, 0, 3)], true, clForest), 0, avoidClasses(clForest, 4, clHill, 5, clPlayer, 10, clBaseResource, 2, clMetal, 5, clRock, 5), num, 20, [explorableArea]); Engine.SetProgress(95); g_Map.log("Creating grass tufts"); group = new SimpleGroup( [new SimpleObject(aGrassLarge, 1,2, 0,1, -Math.PI / 8, Math.PI / 8)] ); createObjectGroupsByAreasDeprecated(group, 0, avoidClasses(clHill, 2, clPlayer, 2), scaleByMapSize(50, 300), 20, [explorableArea] ); placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/atlas_mountains.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/atlas_mountains.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/atlas_mountains.js (revision 26381) @@ -1,224 +1,224 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); const tPrimary = ["medit_rocks_grass", "medit_rocks_grass", "medit_rocks_grass", "medit_rocks_grass", "medit_rocks_grass_shrubs", "medit_rocks_shrubs"]; const tGrass = ["medit_rocks_grass_shrubs", "medit_rocks_shrubs"]; const tForestFloor = "medit_grass_field_dry"; const tCliff = "medit_cliff_italia"; const tGrassDirt = "medit_rocks_grass"; const tDirt = "medit_dirt"; const tRoad = "medit_city_tile"; const tRoadWild = "medit_city_tile"; const tGrass2 = "medit_rocks_grass_shrubs"; const tGrassPatch = "medit_grass_wild"; const oCarob = "gaia/tree/carob"; const oAleppoPine = "gaia/tree/aleppo_pine"; const oBerryBush = "gaia/fruit/berry_01"; const oDeer = "gaia/fauna_deer"; const oSheep = "gaia/fauna_sheep"; const oStoneLarge = "gaia/rock/mediterranean_large"; const oStoneSmall = "gaia/rock/mediterranean_small"; const oMetalLarge = "gaia/ore/mediterranean_large"; const oWoodTreasure = "gaia/treasure/wood"; const oFoodTreasure = "gaia/treasure/food_bin"; const aGrass = "actor|props/flora/grass_soft_large_tall.xml"; const aGrassShort = "actor|props/flora/grass_soft_large.xml"; const aRockLarge = "actor|geology/stone_granite_large.xml"; const aRockMedium = "actor|geology/stone_granite_med.xml"; const aBushMedium = "actor|props/flora/bush_medit_me.xml"; const aBushSmall = "actor|props/flora/bush_medit_sm.xml"; const aCarob = "actor|flora/trees/carob.xml"; const aAleppoPine = "actor|flora/trees/aleppo_pine.xml"; const pForest1 = [tForestFloor + TERRAIN_SEPARATOR + oCarob, tForestFloor]; const pForest2 = [tForestFloor + TERRAIN_SEPARATOR + oAleppoPine, tForestFloor]; const heightLand = 3; var g_Map = new RandomMap(heightLand, tPrimary); const numPlayers = getNumPlayers(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clTreasure = g_Map.createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oCarob, "count": scaleByMapSize(2, 8) }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(10); createBumps(avoidClasses(clPlayer, 9)); createMountains(tCliff, avoidClasses(clPlayer, 20, clHill, 8), clHill, scaleByMapSize(20, 120)); Engine.SetProgress(25); var [forestTrees, stragglerTrees] = getTreeCounts(500, 3000, 0.7); createForests( [tGrass, tForestFloor, tForestFloor, pForest1, pForest2], avoidClasses(clPlayer, 20, clForest, 14, clHill, 1), clForest, forestTrees); Engine.SetProgress(40); g_Map.log("Creating dirt patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [tGrassDirt,tDirt], [2], avoidClasses(clForest, 0, clHill, 0, clDirt, 3, clPlayer, 10), scaleByMapSize(15, 45), clDirt); g_Map.log("Creating grass patches"); createLayeredPatches( [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)], [tGrass2,tGrassPatch], [1], avoidClasses(clForest, 0, clHill, 0, clDirt, 3, clPlayer, 10), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(50); g_Map.log("Creating stone mines"); createMines( [ [new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], avoidClasses(clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 2), clRock); g_Map.log("Creating metal mines"); createMines( [ [new SimpleObject(oMetalLarge, 1,1, 0,4)] ], avoidClasses(clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 2), clMetal ); Engine.SetProgress(60); createDecoration( [ [new SimpleObject(aRockMedium, 1, 3, 0, 1)], [new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)], [new SimpleObject(aGrassShort, 1, 2, 0, 1)], [new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3, 6, 1.2, 2.5)], [new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)] ], [ scaleByMapAreaAbsolute(16), scaleByMapAreaAbsolute(8), scaleByMapAreaAbsolute(13), scaleByMapAreaAbsolute(13), scaleByMapAreaAbsolute(13) ], avoidClasses(clForest, 0, clPlayer, 0, clHill, 0)); Engine.SetProgress(75); createFood( [ [new SimpleObject(oSheep, 5, 7, 0, 4)], [new SimpleObject(oDeer, 2, 3, 0, 2)] ], [ 3 * numPlayers, 3 * numPlayers ], avoidClasses(clForest, 0, clPlayer, 20, clHill, 1, clFood, 20), clFood); createFood( [ [new SimpleObject(oBerryBush, 5, 7, 0, 4)] ], [ randIntInclusive(3, 12) * numPlayers + 2 ], avoidClasses(clForest, 0, clPlayer, 20, clHill, 1, clFood, 10), clFood); g_Map.log("Creating food treasures"); var group = new SimpleGroup( [new SimpleObject(oFoodTreasure, 2,3, 0,2)], true, clTreasure ); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 18, clHill, 1, clFood, 5), 3 * numPlayers, 50 ); g_Map.log("Creating food treasures"); group = new SimpleGroup( [new SimpleObject(oWoodTreasure, 2,3, 0,2)], true, clTreasure ); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 18, clHill, 1), 3 * numPlayers, 50 ); Engine.SetProgress(80); createStragglerTrees( [oCarob, oAleppoPine], avoidClasses(clForest, 1, clHill, 1, clPlayer, 10, clMetal, 6, clRock, 6, clTreasure, 4), clForest, stragglerTrees); createStragglerTrees( [aCarob, aAleppoPine], stayClasses(clHill, 2), clForest, stragglerTrees / 5); placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); setFogFactor(0.2); setFogThickness(0.14); setPPEffect("hdr"); setPPContrast(0.45); setPPSaturation(0.56); setPPBloom(0.1); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/botswanan_haven.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/botswanan_haven.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/botswanan_haven.js (revision 26381) @@ -1,398 +1,398 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); const tGrassA = "savanna_shrubs_a_wetseason"; const tGrassB = "savanna_shrubs_a"; const tCliff = "savanna_cliff_a"; const tHill = "savanna_grass_a_wetseason"; const tMud = "savanna_mud_a"; const tShoreBlend = "savanna_grass_b_wetseason"; const tShore = "savanna_riparian_wet"; const tWater = "savanna_mud_a"; const tCityTile = "savanna_tile_a"; const oBush = "gaia/tree/bush_temperate"; const oBaobab = "gaia/tree/baobab"; const oToona = "gaia/tree/toona"; const oBerryBush = "gaia/fruit/berry_01"; const oGazelle = "gaia/fauna_gazelle"; const oZebra = "gaia/fauna_zebra"; const oWildebeest = "gaia/fauna_wildebeest"; const oLion = "gaia/fauna_lion"; const oRhino = "gaia/fauna_rhinoceros_white"; const oCrocodile = "gaia/fauna_crocodile_nile"; const oElephant = "gaia/fauna_elephant_north_african"; const oElephantInfant = "gaia/fauna_elephant_african_infant"; const oLioness = "gaia/fauna_lioness"; const oRabbit = "gaia/fauna_rabbit"; const oStoneLarge = "gaia/rock/temperate_large"; const oStoneSmall = "gaia/rock/savanna_small"; const oMetalLarge = "gaia/ore/savanna_large"; const aGrass = "actor|props/flora/grass_field_lush_tall.xml"; const aGrass2 = "actor|props/flora/grass_tropic_field_tall.xml"; const aGrassShort = "actor|props/flora/grass_soft_large.xml"; const aRockLarge = "actor|geology/stone_granite_med.xml"; const aRockMedium = "actor|geology/stone_granite_med.xml"; const aReeds = "actor|props/flora/reeds_pond_lush_a.xml"; const aReeds2 = "actor|props/flora/reeds_pond_lush_b.xml"; const aLillies = "actor|props/flora/water_lillies.xml"; const aBushMedium = "actor|props/flora/bush_tropic_b.xml"; const aBushSmall = "actor|props/flora/bush_tropic_a.xml"; const aShrub = "actor|props/flora/shrub_tropic_plant_flower.xml"; const aFlower = "actor|props/flora/flower_bright.xml"; const aPalm = "actor|props/flora/shrub_fanpalm.xml"; const heightMarsh = -2; const heightLand = 3; const heightHill = 15; const heightOffsetBump1 = 2; const heightOffsetBump2 = 1; var g_Map = new RandomMap(heightLand, tShoreBlend); const numPlayers = getNumPlayers(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tCityTile, "innerTerrain": tCityTile }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oBaobab }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(15); g_Map.log("Creating bumps"); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.6, 0.1, Infinity), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump1, 2), avoidClasses(clPlayer, 13), scaleByMapSize(300, 800)); g_Map.log("Creating hills"); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(16, 40)), 0.5), [ new LayeredPainter([tCliff, tHill], [2]), new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), new TileClassPainter(clHill) ], avoidClasses(clPlayer, 20, clHill, 15, clWater, 0), scaleByMapSize(1, 4) * numPlayers * 3); g_Map.log("Creating marshes"); for (let i = 0; i < 2; ++i) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(6, 12)), Math.floor(scaleByMapSize(15, 60)), 0.8), [ new LayeredPainter([tShoreBlend, tShore, tWater], [1, 1]), new SmoothElevationPainter(ELEVATION_SET, heightMarsh, 3), new TileClassPainter(clWater) ], avoidClasses(clPlayer, 25, clWater, Math.round(scaleByMapSize(7, 16) * randFloat(0.8, 1.35))), scaleByMapSize(4, 20)); g_Map.log("Creating reeds"); createObjectGroupsDeprecated( new SimpleGroup( [ new SimpleObject(aReeds, 20, 40, 0, 4), new SimpleObject(aReeds2, 20, 40, 0, 4), new SimpleObject(aLillies, 10, 30, 0, 4) ], true), 0, stayClasses(clWater, 1), scaleByMapSize(400, 1000), 100); Engine.SetProgress(40); g_Map.log("Creating bumps"); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, Infinity), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump2, 2), stayClasses(clWater, 2), scaleByMapSize(50, 100)); g_Map.log("Creating mud patches"); for (let size of [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)]) createAreas( new ChainPlacer(2, Math.floor(scaleByMapSize(3, 6)), size, Infinity), [ new LayeredPainter([tGrassA, tGrassB, tMud], [1, 1]), new TileClassPainter(clDirt) ], avoidClasses(clWater, 1, clHill, 0, clDirt, 5, clPlayer, 8), scaleByMapSize(15, 45)); Engine.SetProgress(50); g_Map.log("Creating stone mines"); createObjectGroupsDeprecated( new SimpleGroup( [ new SimpleObject(oStoneSmall, 0, 2, 0, 4), new SimpleObject(oStoneLarge, 1, 1, 0, 4) ], true, clRock), 0, [avoidClasses(clWater, 0, clPlayer, 20, clRock, 10, clHill, 1)], scaleByMapSize(4, 16), 100); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oStoneSmall, 2, 5, 1, 3)], true, clRock), 0, [avoidClasses(clWater, 0, clPlayer, 20, clRock, 10, clHill, 1)], scaleByMapSize(4, 16), 100); g_Map.log("Creating metal mines"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oMetalLarge, 1, 1, 0, 4)], true, clMetal), 0, [avoidClasses(clWater, 0, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 1)], scaleByMapSize(4, 16), 100); Engine.SetProgress(60); g_Map.log("Creating small decorative rocks"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(aRockMedium, 1, 3, 0, 1)], true), 0, avoidClasses(clPlayer, 1), scaleByMapSize(16, 262), 50); Engine.SetProgress(65); g_Map.log("Creating large decorative rocks"); createObjectGroupsDeprecated( new SimpleGroup( [ new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2) ], true), 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0), scaleByMapSize(8, 131), 50); Engine.SetProgress(70); g_Map.log("Creating lions"); createObjectGroupsDeprecated( new SimpleGroup( [ new SimpleObject(oLion, 0, 1, 0, 4), new SimpleObject(oLioness, 2, 3, 0, 4) ], true, clFood), 0, avoidClasses(clWater, 1, clPlayer, 20, clFood, 11, clHill, 1), scaleByMapSize(4, 12), 50); g_Map.log("Creating zebras"); createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject(oZebra, 4, 6, 0, 4)], true, clFood), 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clHill, 1, clFood, 13), 3 * numPlayers, 50); g_Map.log("Creating wildebeest"); createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject(oWildebeest, 2, 4, 0, 4)], true, clFood), 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clHill, 1, clFood, 13), 3 * numPlayers, 50); g_Map.log("Creating crocodiles"); createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject(oCrocodile, 2, 3, 0, 4)], true, clFood), 0, [avoidClasses(clForest, 0, clPlayer, 20, clHill, 1, clFood, 13), stayClasses(clWater, 3)], 5 * numPlayers, 200); g_Map.log("Creating gazelles"); createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject(oGazelle, 4, 6, 0, 4)], true, clFood), 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clHill, 1, clFood, 13), 3 * numPlayers, 50); Engine.SetProgress(75); g_Map.log("Creating rabbits"); createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject(oRabbit, 6, 8, 0, 2)], true, clFood), 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clHill, 1, clFood, 13), 6 * numPlayers, 50); g_Map.log("Creating rhinos"); createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject(oRhino, 1, 1, 0, 2)], true, clFood), 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clHill, 1, clFood, 13), 3 * numPlayers, 50); g_Map.log("Creating elephants"); createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject(oElephant, 2, 3, 0, 4), new SimpleObject(oElephantInfant, 1, 1, 0, 4)], true, clFood), 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clHill, 1, clFood, 13), 3 * numPlayers, 50); g_Map.log("Creating berry bushes"); createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject(oBerryBush, 5, 7, 0, 4)], true, clFood), 0, avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 10), randIntInclusive(1, 4) * numPlayers + 2, 50); Engine.SetProgress(80); createStragglerTrees( [oToona, oBaobab, oBush, oBush], avoidClasses(clForest, 1, clWater, 1, clHill, 1, clPlayer, 13, clMetal, 4, clRock, 4), clForest, scaleByMapSize(60, 500)); Engine.SetProgress(85); g_Map.log("Creating small grass tufts"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(aGrassShort, 1, 2, 0, 1, -Math.PI / 8, Math.PI / 8)]), 0, avoidClasses(clWater, 2, clPlayer, 13, clDirt, 0), scaleByMapSize(13, 200)); Engine.SetProgress(90); g_Map.log("Creating large grass tufts"); createObjectGroupsDeprecated( new SimpleGroup([ 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) ]), 0, avoidClasses(clWater, 3, clPlayer, 13, clDirt, 1, clForest, 0), scaleByMapSize(13, 200)); Engine.SetProgress(95); g_Map.log("Creating bushes"); createObjectGroupsDeprecated( new SimpleGroup( [ new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2) ]), 0, avoidClasses(clWater, 1, clPlayer, 13, clDirt, 1), scaleByMapSize(13, 200), 50); g_Map.log("Creating flowering shrubs"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(aShrub, 1, 1, 0, 2)]), 0, avoidClasses(clWater, 1, clPlayer, 13, clDirt, 1), scaleByMapSize(13, 200), 50); g_Map.log("Creating decorative palms"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(aPalm, 1, 3, 0, 2)]), 0, avoidClasses(clWater, 2, clPlayer, 12, clDirt, 1), scaleByMapSize(13, 200), 50); g_Map.log("Creating shrubs,flowers and other decorations"); createObjectGroupsDeprecated( new SimpleGroup( [ new SimpleObject(aFlower, 0, 6, 0, 2), new SimpleObject(aGrass2, 2, 5, 0, 2) ]), 0, avoidClasses(clWater, 1, clHill, 1, clPlayer, 13, clDirt, 1), scaleByMapSize(13, 200), 50); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); setSkySet("cirrus"); setWaterColor(0.553, 0.635, 0.345); setWaterTint(0.161, 0.514, 0.635); setWaterMurkiness(0.8); setWaterWaviness(1.0); setWaterType("clap"); setFogThickness(0.25); setFogFactor(0.6); setPPEffect("hdr"); setPPSaturation(0.44); setPPBloom(0.3); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/cantabrian_highlands.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/cantabrian_highlands.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/cantabrian_highlands.js (revision 26381) @@ -1,279 +1,279 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); setSelectedBiome(); const tPrimary = g_Terrains.mainTerrain; const tGrass = [g_Terrains.tier1Terrain, g_Terrains.tier2Terrain]; const tGrassPForest = g_Terrains.forestFloor1; const tGrassDForest = g_Terrains.forestFloor2; const tGrassA = g_Terrains.tier2Terrain; const tGrassB = g_Terrains.tier3Terrain; const tGrassC = g_Terrains.tier4Terrain; const tHill = g_Terrains.hill; const tCliff = g_Terrains.cliff; const tRoad = g_Terrains.road; const tRoadWild = g_Terrains.roadWild; const tGrassPatchBlend = g_Terrains.tier2Terrain; const tGrassPatch = g_Terrains.tier1Terrain; const tShoreBlend = g_Terrains.shoreBlend; const tShore = g_Terrains.shore; const tWater = g_Terrains.water; const oOak = g_Gaia.tree1; const oOakLarge = g_Gaia.tree2; const oApple = g_Gaia.tree3; const oPine = g_Gaia.tree4; const oAleppoPine = g_Gaia.tree5; const oBerryBush = g_Gaia.fruitBush; const oDeer = g_Gaia.mainHuntableAnimal; const oFish = g_Gaia.fish; const oSheep = g_Gaia.secondaryHuntableAnimal; const oStoneLarge = g_Gaia.stoneLarge; const oStoneSmall = g_Gaia.stoneSmall; const oMetalLarge = g_Gaia.metalLarge; const oMetalSmall = g_Gaia.metalSmall; const aGrass = g_Decoratives.grass; const aGrassShort = g_Decoratives.grassShort; const aReeds = g_Decoratives.reeds; const aLillies = g_Decoratives.lillies; const aRockLarge = g_Decoratives.rockLarge; const aRockMedium = g_Decoratives.rockMedium; const aBushMedium = g_Decoratives.bushMedium; const aBushSmall = g_Decoratives.bushSmall; const pForestD = [tGrassDForest + TERRAIN_SEPARATOR + oOak, tGrassDForest + TERRAIN_SEPARATOR + oOakLarge, tGrassDForest]; const pForestP = [tGrassPForest + TERRAIN_SEPARATOR + oPine, tGrassPForest + TERRAIN_SEPARATOR + oAleppoPine, tGrassPForest]; const heightSeaGround = -7; const heightLand = 3; const heightHill = 20; var g_Map = new RandomMap(heightLand, tPrimary); var numPlayers = getNumPlayers(); var mapSize = g_Map.getSize(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var playerHillRadius = defaultPlayerBaseRadius() / (isNomad() ? 1.5 : 1); var [playerIDs, playerPosition, playerAngle] = playerPlacementCircle(fractionToTiles(0.35)); g_Map.log("Creating player hills and ramps"); for (let i = 0; i < numPlayers; ++i) { createArea( new ClumpPlacer(diskArea(playerHillRadius), 0.95, 0.6, Infinity, playerPosition[i]), [ new LayeredPainter([tCliff, tHill], [2]), new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), new TileClassPainter(clPlayer) ]); let angle = playerAngle[i] + Math.PI * (1 + randFloat(-1, 1) / 8); createPassage({ "start": Vector2D.add(playerPosition[i], new Vector2D(playerHillRadius + 15, 0).rotate(-angle)), "end": Vector2D.add(playerPosition[i], new Vector2D(playerHillRadius - 3, 0).rotate(-angle)), "startWidth": 10, "endWidth": 10, "smoothWidth": 2, "tileClass": clPlayer, "terrain": tHill, "edgeTerrain": tCliff }); } placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "Walls": false, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oOak, "count": 2 }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(10); g_Map.log("Creating lakes"); var numLakes = Math.round(scaleByMapSize(1,4) * numPlayers); var waterAreas = createAreas( new ClumpPlacer(scaleByMapSize(100, 250), 0.8, 0.1, Infinity), [ new LayeredPainter([tShoreBlend, tShore, tWater], [1, 1]), new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 6), new TileClassPainter(clWater) ], avoidClasses(clPlayer, 2, clWater, 20), numLakes ); Engine.SetProgress(15); g_Map.log("Creating reeds"); var group = new SimpleGroup( [new SimpleObject(aReeds, 5,10, 0,4), new SimpleObject(aLillies, 0,1, 0,4)], true ); createObjectGroupsByAreas(group, 0, [borderClasses(clWater, 3, 0), stayClasses(clWater, 1)], numLakes, 100, waterAreas ); Engine.SetProgress(20); g_Map.log("Creating fish"); createObjectGroupsByAreas( new SimpleGroup( [new SimpleObject(oFish, 1,1, 0,1)], true, clFood ), 0, [stayClasses(clWater, 4), avoidClasses(clFood, 8)], numLakes / 4, 50, waterAreas ); Engine.SetProgress(25); createBumps(avoidClasses(clWater, 2, clPlayer, 0)); Engine.SetProgress(30); createHills([tCliff, tCliff, tHill], avoidClasses(clPlayer, 2, clWater, 5, clHill, 15), clHill, scaleByMapSize(1, 4) * numPlayers); Engine.SetProgress(35); var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(1)); createDefaultForests( [tGrass, tGrassDForest, tGrassPForest, pForestP, pForestD], avoidClasses(clPlayer, 1, clWater, 3, clForest, 17, clHill, 1), clForest, forestTrees); Engine.SetProgress(40); g_Map.log("Creating dirt patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [[tGrass,tGrassA],[tGrassA,tGrassB], [tGrassB,tGrassC]], [1,1], avoidClasses(clWater, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 0), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(45); g_Map.log("Creating grass patches"); createLayeredPatches( [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)], [tGrassPatchBlend, tGrassPatch], [1], avoidClasses(clWater, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 0), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(50); g_Map.log("Creating metal mines"); createBalancedMetalMines( oMetalSmall, oMetalLarge, clMetal, avoidClasses(clWater, 0, clForest, 0, clPlayer, scaleByMapSize(15, 25), clHill, 1) ); g_Map.log("Creating stone mines"); createBalancedStoneMines( oStoneSmall, oStoneLarge, clRock, avoidClasses(clWater, 0, clForest, 0, clPlayer, scaleByMapSize(15, 25), clHill, 1, clMetal, 10) ); Engine.SetProgress(60); createDecoration( [ [new SimpleObject(aRockMedium, 1, 3, 0, 1)], [new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)], [new SimpleObject(aGrassShort, 1, 2, 0, 1)], [new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3, 6, 1.2, 2.5)], [new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)] ], [ scaleByMapAreaAbsolute(16), scaleByMapAreaAbsolute(8), scaleByMapAreaAbsolute(13), scaleByMapAreaAbsolute(13), scaleByMapAreaAbsolute(13) ], avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0)); Engine.SetProgress(70); createFood( [ [new SimpleObject(oSheep, 2, 3, 0, 2)], [new SimpleObject(oDeer, 5, 7, 0, 4)] ], [ 3 * numPlayers, 3 * numPlayers ], avoidClasses(clWater, 0, clForest, 0, clPlayer, 1, clHill, 1, clFood, 20), clFood); Engine.SetProgress(80); createFood( [ [new SimpleObject(oBerryBush, 5, 7, 0, 4)] ], [ randIntInclusive(1, 4) * numPlayers + 2 ], avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 10), clFood); Engine.SetProgress(85); createStragglerTrees( [oOak, oOakLarge, oPine, oApple], avoidClasses(clWater, 1, clForest, 1, clHill, 1, clPlayer, 1, clMetal, 6, clRock, 6), clForest, stragglerTrees); Engine.SetProgress(90); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); setSkySet("cirrus"); setWaterColor(0.447, 0.412, 0.322); // muddy brown setWaterTint(0.447, 0.412, 0.322); setWaterMurkiness(1.0); setWaterWaviness(3.0); setWaterType("lake"); setFogThickness(0.25); setFogFactor(0.4); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/canyon.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/canyon.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/canyon.js (revision 26381) @@ -1,352 +1,352 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); setSelectedBiome(); const tMainTerrain = g_Terrains.mainTerrain; const tForestFloor1 = g_Terrains.forestFloor1; const tForestFloor2 = g_Terrains.forestFloor2; const tCliff = g_Terrains.cliff; const tTier1Terrain = g_Terrains.tier1Terrain; const tTier2Terrain = g_Terrains.tier2Terrain; const tTier3Terrain = g_Terrains.tier3Terrain; const tHill = g_Terrains.hill; const tRoad = g_Terrains.road; const tRoadWild = g_Terrains.roadWild; const tTier4Terrain = g_Terrains.tier4Terrain; const oTree1 = g_Gaia.tree1; const oTree2 = g_Gaia.tree2; const oTree3 = g_Gaia.tree3; const oTree4 = g_Gaia.tree4; const oTree5 = g_Gaia.tree5; const oFruitBush = g_Gaia.fruitBush; const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal; const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal; const oStoneLarge = g_Gaia.stoneLarge; const oStoneSmall = g_Gaia.stoneSmall; const oMetalLarge = g_Gaia.metalLarge; const oWoodTreasure = "gaia/treasure/wood"; const oFoodTreasure = "gaia/treasure/food_bin"; const aGrass = g_Decoratives.grass; const aGrassShort = g_Decoratives.grassShort; const aRockLarge = g_Decoratives.rockLarge; const aRockMedium = g_Decoratives.rockMedium; const aBushMedium = g_Decoratives.bushMedium; const aBushSmall = g_Decoratives.bushSmall; const aTree = g_Decoratives.tree; const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2]; const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1]; const heightLand = 3; const heightHill = 30; var g_Map = new RandomMap(heightHill, tMainTerrain); var numPlayers = getNumPlayers(); var mapSize = g_Map.getSize(); var mapCenter = g_Map.getCenter(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clHill2 = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clLand = g_Map.createTileClass(); var playerCanyonRadius = scaleByMapSize(18, 32); var [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); g_Map.log("Reserving space for the players, their initial forests and some less space therein without trees"); for (let i = 0; i < numPlayers; ++i) for (let j = 1; j <= 2; ++j) createArea( new ClumpPlacer(diskArea(playerCanyonRadius / j), 0.65, 0.1, Infinity, playerPosition[i]), [ new TerrainPainter(tMainTerrain), new SmoothElevationPainter(ELEVATION_SET, heightLand, 2), new TileClassPainter(j == 1 || isNomad() ? clLand : clPlayer) ]); g_Map.log("Creating center area"); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.16)), 0.7, 0.1, Infinity, mapCenter), [ new TerrainPainter(tMainTerrain), new SmoothElevationPainter(ELEVATION_SET, heightLand, 3), new TileClassPainter(clLand) ]); createArea( new ClumpPlacer(150, 0.6, 0.3, Infinity, mapCenter), new TileClassPainter(clHill)); g_Map.log("Creating hills"); for (let i = 0; i < scaleByMapSize(9, 16); ++i) createArea( new PathPlacer( new Vector2D(randIntExclusive(1, mapSize), randIntExclusive(1, mapSize)), new Vector2D(randIntExclusive(1, mapSize), randIntExclusive(1, mapSize)), scaleByMapSize(11, 16), 0.4, 3 * scaleByMapSize(1, 4), 0.1, 0), [ new SmoothElevationPainter(ELEVATION_SET, heightHill, 3), new TileClassPainter(clHill2) ], avoidClasses(clPlayer, 6, clHill2, 3, clHill, 2)); for (let g = 0; g < scaleByMapSize(5, 30); ++g) { let position = new Vector2D(randIntInclusive(1, mapSize - 1), randIntInclusive(1, mapSize - 1)); let newarea = createArea( new ClumpPlacer(diskArea(fractionToTiles(0.06)), 0.7, 0.1, Infinity, position), [ new TerrainPainter(tMainTerrain), new SmoothElevationPainter(ELEVATION_SET, heightLand, 3), new TileClassPainter(clLand) ], avoidClasses(clLand, 6)); if (newarea !== null) { var distances = []; var d1 = 9999; var d2 = 9999; var p1 = -1; var p2 = 0; for (let i = 0; i < numPlayers; ++i) distances.push(position.distanceTo(playerPosition[i])); for (let a = 0; a < numPlayers; ++a) { if (d1 >= distances[a]) { d2 = d1; d1 = distances[a]; p2 = p1; p1 = a; } else if (d2 >= distances[a]) { d2 = distances[a]; p2 = a; } } for (let playerID of [p1, p2]) if (playerPosition[playerID]) createArea( new PathPlacer(position, playerPosition[playerID], scaleByMapSize(11, 17), 0.4, scaleByMapSize(3, 12), 0.1, 0.1), [ new TerrainPainter(tMainTerrain), new SmoothElevationPainter(ELEVATION_SET, heightLand, 3), new TileClassPainter(clLand) ]); } } g_Map.log("Creating paths from players to neighbor and center"); for (let i = 0; i < numPlayers; ++i) { let neighbor = i + 1 < numPlayers ? i + 1 : 0; for (let position of [playerPosition[neighbor], mapCenter]) createArea( new PathPlacer( playerPosition[i], position, scaleByMapSize(8, 13), 0.4, 3 * scaleByMapSize(1, 4), 0.1, 0), [ new LayeredPainter([tRoadWild, tRoad], [1]), new SmoothElevationPainter(ELEVATION_SET, heightLand, 2), new TileClassPainter(clLand), new TileClassPainter(clHill) ]); } g_Map.log("Painting center place"); createArea( new ClumpPlacer(150, 0.6, 0.3, Infinity, mapCenter), new TerrainPainter(tRoad)); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], // PlayerTileClass already marked above "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoad, "innerTerrain": tRoad, "radius": playerCanyonRadius / 3 }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oFruitBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ], "distance": 11 }, "Trees": { "template": oTree1 }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(20); paintTerrainBasedOnHeight(3.1, 29, 0, tCliff); paintTileClassBasedOnHeight(3.1, 32, 0, clHill2); createBumps([avoidClasses(clPlayer, 2), stayClasses(clLand, 2)]); createHills([tCliff, tCliff, tHill], [avoidClasses(clPlayer, 2, clHill, 8, clHill2, 8), stayClasses(clLand, 5)], clHill, scaleByMapSize(10, 40)); // create hills outside the canyon createHills([tCliff, tCliff, tMainTerrain], avoidClasses(clLand, 1, clHill, 1), clHill, scaleByMapSize(20, 150), undefined, undefined, undefined, undefined, 40); var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(1)); createForests( [tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2], [avoidClasses(clPlayer, 1, clForest, 15, clHill, 1, clHill2, 0), stayClasses(clLand, 4)], clForest, forestTrees); Engine.SetProgress(50); g_Map.log("Creating dirt patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [[tMainTerrain,tTier1Terrain],[tTier1Terrain,tTier2Terrain], [tTier2Terrain,tTier3Terrain]], [1,1], [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 4, clHill2, 0), stayClasses(clLand, 3)], scaleByMapSize(15, 45), clDirt); g_Map.log("Creating grass patches"); createPatches( [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)], tTier4Terrain, [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 4, clHill2, 0), stayClasses(clLand, 3)], scaleByMapSize(15, 45), clDirt); g_Map.log("Creating stone mines"); createMines( [ [new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], [avoidClasses(clForest, 1, clPlayer, 3, clRock, 10, clHill, 1, clHill2, 1), stayClasses(clLand, 2)], clRock); g_Map.log("Creating metal mines"); createMines( [ [new SimpleObject(oMetalLarge, 1,1, 0,4)] ], [avoidClasses(clForest, 1, clPlayer, 3, clMetal, 10, clRock, 5, clHill, 1, clHill2, 1), stayClasses(clLand, 2)], clMetal ); Engine.SetProgress(65); var planetm = 1; if (currentBiome() == "generic/india") planetm = 8; createDecoration( [ [new SimpleObject(aRockMedium, 1, 3, 0, 1)], [new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)], [new SimpleObject(aGrassShort, 1, 2, 0, 1)], [new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3, 6, 1.2, 2.5)], [new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)] ], [ 3 * scaleByMapAreaAbsolute(16), 3 * scaleByMapAreaAbsolute(8), planetm * scaleByMapAreaAbsolute(13), planetm * scaleByMapAreaAbsolute(13), planetm * scaleByMapAreaAbsolute(13) ], avoidClasses(clForest, 0, clPlayer, 0, clHill, 0)); g_Map.log("Creating actor trees"); var group = new SimpleGroup( [new SimpleObject(aTree, 1,1, 0,1)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clLand, 5), scaleByMapSize(200, 800), 50 ); Engine.SetProgress(70); createFood( [ [new SimpleObject(oMainHuntableAnimal, 5, 7, 0, 4)], [new SimpleObject(oSecondaryHuntableAnimal, 2, 3, 0, 2)] ], [ 3 * numPlayers, 3 * numPlayers ], [avoidClasses(clForest, 0, clPlayer, 4, clHill, 1, clFood, 20, clHill2, 1), stayClasses(clLand, 3)], clFood); createFood( [ [new SimpleObject(oFruitBush, 5, 7, 0, 4)] ], [ 3 * numPlayers ], [avoidClasses(clForest, 0, clPlayer, 4, clHill, 1, clFood, 10, clHill2, 1), stayClasses(clLand, 3)], clFood); Engine.SetProgress(85); createStragglerTrees( [oTree1, oTree2, oTree4, oTree3], [avoidClasses(clForest, 1, clHill, 1, clPlayer, 9, clMetal, 6, clRock, 6, clHill2, 1), stayClasses(clLand, 3)], clForest, stragglerTrees); g_Map.log("Creating treasures"); for (let i = 0; i < randIntInclusive(3, 8); ++i) for (let template of [oFoodTreasure, oWoodTreasure]) g_Map.placeEntityPassable( template, 0, Vector2D.add(mapCenter, new Vector2D(randFloat(0, 7), 0).rotate(randomAngle())), randomAngle()); placePlayersNomad( clPlayer, [stayClasses(clLand, 4), avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clHill2, 4, clFood, 2)]); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/continent.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/continent.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/continent.js (revision 26381) @@ -1,256 +1,256 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); setSelectedBiome(); const tMainTerrain = g_Terrains.mainTerrain; const tForestFloor1 = g_Terrains.forestFloor1; const tForestFloor2 = g_Terrains.forestFloor2; const tCliff = g_Terrains.cliff; const tTier1Terrain = g_Terrains.tier1Terrain; const tTier2Terrain = g_Terrains.tier2Terrain; const tTier3Terrain = g_Terrains.tier3Terrain; const tHill = g_Terrains.hill; const tRoad = g_Terrains.road; const tRoadWild = g_Terrains.roadWild; const tTier4Terrain = g_Terrains.tier4Terrain; const tShore = g_Terrains.shore; const tWater = g_Terrains.water; const oTree1 = g_Gaia.tree1; const oTree2 = g_Gaia.tree2; const oTree3 = g_Gaia.tree3; const oTree4 = g_Gaia.tree4; const oTree5 = g_Gaia.tree5; const oFruitBush = g_Gaia.fruitBush; const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal; const oFish = g_Gaia.fish; const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal; const oStoneLarge = g_Gaia.stoneLarge; const oStoneSmall = g_Gaia.stoneSmall; const oMetalLarge = g_Gaia.metalLarge; const oMetalSmall = g_Gaia.metalSmall; const aGrass = g_Decoratives.grass; const aGrassShort = g_Decoratives.grassShort; const aRockLarge = g_Decoratives.rockLarge; const aRockMedium = g_Decoratives.rockMedium; const aBushMedium = g_Decoratives.bushMedium; const aBushSmall = g_Decoratives.bushSmall; const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2]; const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1]; const heightSeaGround = -5; const heightLand = 3; var g_Map = new RandomMap(heightSeaGround, tWater); var numPlayers = getNumPlayers(); var mapSize = g_Map.getSize(); var mapCenter = g_Map.getCenter(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clLand = g_Map.createTileClass(); g_Map.log("Creating continent"); createArea( new ChainPlacer( 2, Math.floor(scaleByMapSize(5, 12)), Math.floor(scaleByMapSize(60, 700)), Infinity, mapCenter, 0, [Math.floor(fractionToTiles(0.33))]), [ new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), new TileClassPainter(clLand) ]); var [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.25)); g_Map.log("Ensuring initial player land"); for (let i = 0; i < numPlayers; ++i) createArea( new ChainPlacer( 2, Math.floor(scaleByMapSize(5, 9)), Math.floor(scaleByMapSize(5, 20)), Infinity, playerPosition[i], 0, [Math.floor(scaleByMapSize(23, 50))]), [ new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), new TileClassPainter(clLand) ]); Engine.SetProgress(20); paintTerrainBasedOnHeight(3, 4, 3, tMainTerrain); paintTerrainBasedOnHeight(1, 3, 0, tShore); paintTerrainBasedOnHeight(-8, 1, 2, tWater); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oFruitBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oTree1, "count": 2 }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(30); createBumps([avoidClasses(clPlayer, 10), stayClasses(clLand, 5)]); if (randBool()) createHills([tMainTerrain, tCliff, tHill], [avoidClasses(clPlayer, 20, clHill, 15, clBaseResource, 3), stayClasses(clLand, 5)], clHill, scaleByMapSize(1, 4) * numPlayers); else createMountains(tCliff, [avoidClasses(clPlayer, 20, clHill, 15, clBaseResource, 3), stayClasses(clLand, 5)], clHill, scaleByMapSize(1, 4) * numPlayers); var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(1)); createDefaultForests( [tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2], [avoidClasses(clPlayer, 20, clForest, 17, clHill, 0, clBaseResource,2), stayClasses(clLand, 4)], clForest, forestTrees); Engine.SetProgress(50); g_Map.log("Creating dirt patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [[tMainTerrain,tTier1Terrain],[tTier1Terrain,tTier2Terrain], [tTier2Terrain,tTier3Terrain]], [1,1], [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), stayClasses(clLand, 5)], scaleByMapSize(15, 45), clDirt); g_Map.log("Creating grass patches"); createPatches( [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)], tTier4Terrain, [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), stayClasses(clLand, 5)], scaleByMapSize(15, 45), clDirt); Engine.SetProgress(55); g_Map.log("Creating metal mines"); createBalancedMetalMines( oMetalSmall, oMetalLarge, clMetal, [stayClasses(clLand, 6), avoidClasses(clForest, 1, clPlayer, scaleByMapSize(20, 35), clHill, 1)], ); g_Map.log("Creating stone mines"); createBalancedStoneMines( oStoneSmall, oStoneLarge, clRock, [stayClasses(clLand, 6), avoidClasses(clForest, 1, clPlayer, scaleByMapSize(20, 35), clHill, 1, clMetal, 10)] ); Engine.SetProgress(65); // create decoration var planetm = 1; if (currentBiome() == "generic/india") planetm = 8; createDecoration( [ [new SimpleObject(aRockMedium, 1, 3, 0, 1)], [new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)], [new SimpleObject(aGrassShort, 1, 2, 0, 1)], [new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3, 6, 1.2, 2.5)], [new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)] ], [ scaleByMapAreaAbsolute(16), scaleByMapAreaAbsolute(8), planetm * scaleByMapAreaAbsolute(13), planetm * scaleByMapAreaAbsolute(13), planetm * scaleByMapAreaAbsolute(13) ], [avoidClasses(clForest, 0, clPlayer, 0, clHill, 0), stayClasses(clLand, 5)]); Engine.SetProgress(70); createFood( [ [new SimpleObject(oMainHuntableAnimal, 5, 7, 0, 4)], [new SimpleObject(oSecondaryHuntableAnimal, 2, 3, 0, 2)] ], [ 3 * numPlayers, 3 * numPlayers ], [avoidClasses(clForest, 0, clPlayer, 20, clHill, 1, clFood, 20), stayClasses(clLand, 5)], clFood); createFood( [ [new SimpleObject(oFruitBush, 5, 7, 0, 4)] ], [ 3 * numPlayers ], [avoidClasses(clForest, 0, clPlayer, 20, clHill, 1, clFood, 10), stayClasses(clLand, 5)], clFood); createFood( [ [new SimpleObject(oFish, 2, 3, 0, 2)] ], [ 25 * numPlayers ], avoidClasses(clLand, 2, clFood, 20), clFood); Engine.SetProgress(85); createStragglerTrees( [oTree1, oTree2, oTree4, oTree3], [avoidClasses(clForest, 7, clHill, 1, clPlayer, 9, clMetal, 6, clRock, 6), stayClasses(clLand, 7)], clForest, stragglerTrees); placePlayersNomad( clPlayer, [stayClasses(clLand, 4), avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)]); setWaterWaviness(1.0); setWaterType("ocean"); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/corinthian_isthmus.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/corinthian_isthmus.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/corinthian_isthmus.js (revision 26381) @@ -1,333 +1,333 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); setSelectedBiome(); TILE_CENTERED_HEIGHT_MAP = true; const tCity = g_Terrains.road; const tCityPlaza = g_Terrains.roadWild; const tHill = g_Terrains.hill; const tMainDirt = g_Terrains.dirt; const tCliff = g_Terrains.cliff; const tForestFloor = g_Terrains.forestFloor1; const tGrass = g_Terrains.mainTerrain; const tGrassSand50 = g_Terrains.tier1Terrain; const tGrassSand25 = g_Terrains.tier3Terrain; const tDirt = g_Terrains.dirt; const tDirt2 = g_Terrains.dirt; const tDirt3 = g_Terrains.tier2Terrain; const tDirtCracks = g_Terrains.dirt; const tShore = g_Terrains.shore; const tWater = g_Terrains.water; const oBerryBush = g_Gaia.fruitBush; const oDeer = g_Gaia.mainHuntableAnimal; const oFish = g_Gaia.fish; const oSheep = g_Gaia.secondaryHuntableAnimal; const oGoat = "gaia/fauna_goat"; const oStoneLarge = g_Gaia.stoneLarge; const oStoneSmall = g_Gaia.stoneSmall; const oMetalLarge = g_Gaia.metalLarge; const oMetalSmall = g_Gaia.metalSmall; const oDatePalm = g_Gaia.tree1; const oSDatePalm = g_Gaia.tree2; const oCarob = g_Gaia.tree3; const oFanPalm = g_Gaia.tree4; const oPoplar = g_Gaia.tree5; const oCypress = pickRandom([g_Gaia.tree1, g_Gaia.tree2, g_Gaia.tree3, g_Gaia.tree4, g_Gaia.tree5]); const aBush1 = g_Decoratives.bushSmall; const aBush2 = g_Decoratives.bushMedium; const aBush3 = g_Decoratives.grassShort; const aBush4 = g_Decoratives.tree; const aDecorativeRock = g_Decoratives.rockMedium; const aLillies = g_Decoratives.lillies; const aReeds = g_Decoratives.reeds; const pForest = [ tForestFloor, tForestFloor + TERRAIN_SEPARATOR + oCarob, tForestFloor + TERRAIN_SEPARATOR + oDatePalm, tForestFloor + TERRAIN_SEPARATOR + oSDatePalm, tForestFloor ]; var heightSeaGround = -7; var heightShallow = -0.8; var heightLand = 3; var g_Map = new RandomMap(heightLand, tHill); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); var clPlayer = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clGrass = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clPassageway = g_Map.createTileClass(); var clShallow = g_Map.createTileClass(); g_Map.log("Creating the main river"); var riverAngle = randomAngle(); var riverWidth = scaleByMapSize(20, 90); var riverStart = new Vector2D(mapCenter.x, 0).rotateAround(riverAngle, mapCenter); var riverEnd = new Vector2D(mapCenter.x, mapSize).rotateAround(riverAngle, mapCenter); createArea( new PathPlacer(riverStart, riverEnd, riverWidth, 0.2, scaleByMapSize(0.3, 1), 0.04, 0.01), new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4)); g_Map.log("Creating small puddles at the map border to ensure players being separated"); for (const point of [riverStart, riverEnd]) createArea( new ClumpPlacer(diskArea(riverWidth / 2), 0.95, 0.6, Infinity, point), new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4)); // Paint water so we now where to lay passageway. paintTileClassBasedOnHeight(heightSeaGround - 1, 0.5, 1, clWater); g_Map.log("Creating passage connecting the two riversides"); // Add some leeway to make sure things are connected. const fraction = randFloat(0.38, 0.62); const middlePoint = riverStart.clone().mult(fraction).add(riverEnd.clone().mult(1 - fraction)); let passageStart = new Vector2D(middlePoint.x, middlePoint.y - riverWidth * 1.1).rotateAround(riverAngle, middlePoint); let passageEnd = new Vector2D(middlePoint.x, middlePoint.y + riverWidth * 1.1).rotateAround(riverAngle, middlePoint); passageStart = passageStart.rotateAround(Math.PI / 2, middlePoint); passageEnd = passageEnd.rotateAround(Math.PI / 2, middlePoint); // First create a shallow (walkable) area. const passageWidth = scaleByMapSize(15, 40); createArea( new PathPlacer( passageStart, passageEnd, passageWidth * 2, 0.2, scaleByMapSize(0.2, 0.4), 0.1, 0.01, 100.0), new MultiPainter([ new SmoothElevationPainter(ELEVATION_SET, heightShallow, 3), new TileClassPainter(clShallow)]), new OrConstraint([ stayClasses(clWater, 0), borderClasses(clWater, 0, 3), ]) ); // Then create the proper passageway. createArea( new PathPlacer( passageStart, passageEnd, passageWidth, 0.5, scaleByMapSize(0.2, 0.4), 0.1, 0.01), new MultiPainter([ new SmoothElevationPainter(ELEVATION_SET, heightLand, 3), new TileClassPainter(clPassageway)]) ); paintTerrainBasedOnHeight(heightSeaGround - 1, 1, 1, tWater); paintTerrainBasedOnHeight(1, 2, 1, tShore); paintTerrainBasedOnHeight(2, 5, 1, tGrass); // Reset water class. clWater = g_Map.createTileClass(); paintTileClassBasedOnHeight(heightSeaGround - 1, 0.5, 1, clWater); placePlayerBases({ "PlayerPlacement": playerPlacementRiver(riverAngle, fractionToTiles(0.6)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "Walls": "towers", "CityPatch": { "outerTerrain": tCityPlaza, "innerTerrain": tCity }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneSmall }, { "template": oStoneSmall }, ] }, "Trees": { "template": oCarob, "count": 2 }, "Decoratives": { "template": aBush1 } }); Engine.SetProgress(40); createBumps(avoidClasses(clWater, 2, clPlayer, 20)); const [forestTrees, stragglerTrees] = getTreeCounts(500, 3000, 0.7); createDefaultForests( [tForestFloor, tForestFloor, pForest, pForest, pForest], avoidClasses(clPlayer, 20, clPassageway, 5, clForest, 17, clWater, 2, clBaseResource, 3), clForest, forestTrees); Engine.SetProgress(50); if (randBool()) createHills([tGrass, tCliff, tHill], avoidClasses(clPlayer, 20, clPassageway, 10, clForest, 1, clHill, 15, clWater, 3), clHill, scaleByMapSize(3, 15)); else createMountains(tCliff, avoidClasses(clPlayer, 20, clPassageway, 10, clForest, 1, clHill, 15, clWater, 3), clHill, scaleByMapSize(3, 15)); g_Map.log("Creating grass patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [[tGrass, tGrassSand50], [tGrassSand50, tGrassSand25], [tGrassSand25, tGrass]], [1, 1], avoidClasses(clForest, 0, clGrass, 2, clPlayer, 10, clWater, 2, clDirt, 2, clHill, 1), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(55); g_Map.log("Creating dirt patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [tDirt3, tDirt2, [tDirt, tMainDirt], [tDirtCracks, tMainDirt]], [1, 1, 1], avoidClasses(clForest, 0, clDirt, 2, clPlayer, 10, clWater, 2, clGrass, 2, clHill, 1), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(60); g_Map.log("Creating stone mines in the middle"); createObjectGroups( new SimpleGroup([new SimpleObject(oStoneSmall, 1, 4, 0, 4)], true, clRock), 0, [ avoidClasses(clForest, 4, clPlayer, 15, clRock, 6, clWater, 0, clHill, 4), stayClasses(clPassageway, 2) ], scaleByMapSize(4, 15), 80 ); g_Map.log("Creating metal mines"); createBalancedMetalMines( oMetalSmall, oMetalLarge, clMetal, avoidClasses(clPassageway, 1, clWater, 0, clForest, 0, clPlayer, scaleByMapSize(15, 25), clHill, 1, clRock, 10), 0.9 // less available area -> slightly less metal ); Engine.SetProgress(65); createDecoration( [ [ new SimpleObject(aDecorativeRock, 1, 3, 0, 1) ], [ new SimpleObject(aBush2, 1, 2, 0, 1), new SimpleObject(aBush1, 1, 3, 0, 2), new SimpleObject(aBush4, 1, 2, 0, 1), new SimpleObject(aBush3, 1, 3, 0, 2) ] ], [ scaleByMapAreaAbsolute(16), scaleByMapSize(40, 360) ], avoidClasses(clWater, 2, clForest, 0, clPlayer, 5, clBaseResource, 6, clHill, 1, clRock, 6, clMetal, 6)); Engine.SetProgress(70); createFood( [ [new SimpleObject(oFish, 2, 3, 0, 2)] ], [ 3 * scaleByMapSize(5, 20) ], [avoidClasses(clFood, 8, clShallow, 2), stayClasses(clWater, 4)], clFood); createFood( [ [new SimpleObject(oSheep, 5, 7, 0, 4)], [new SimpleObject(oGoat, 2, 4, 0, 3)], [new SimpleObject(oDeer, 2, 4, 0, 2)] ], [ scaleByMapSize(5, 20), scaleByMapSize(5, 20), scaleByMapSize(5, 20) ], avoidClasses(clForest, 0, clPlayer, 10, clPassageway, 0, clBaseResource, 6, clWater, 1, clFood, 10, clHill, 1, clRock, 6, clMetal, 6), clFood); createFood( [ [new SimpleObject(oBerryBush, 5, 7, 0, 4)] ], [ 3 * numPlayers ], avoidClasses(clWater, 3, clForest, 0, clPassageway, 0, clPlayer, 20, clHill, 1, clFood, 10, clRock, 6, clMetal, 6), clFood); Engine.SetProgress(90); createStragglerTrees( [oDatePalm, oSDatePalm, oCarob, oFanPalm, oPoplar, oCypress], avoidClasses(clForest, 1, clWater, 2, clPlayer, 8, clBaseResource, 6, clMetal, 6, clRock, 6, clHill, 1), clForest, stragglerTrees); g_Map.log("Placing decorations on shallows"); createObjectGroups( new SimpleGroup([ new SimpleObject(aDecorativeRock, 1, 2, 0, 1), new SimpleObject(aReeds, 0, 4, 0, 1), ], true, clRock), 0, [stayClasses(clShallow, 2), avoidClasses(clPassageway, 0)], scaleByMapSize(30, 100), 50 ); createObjectGroups( new SimpleGroup([new SimpleObject(aLillies, 1, 2, 0, 1)], true, clRock), 0, [stayClasses(clShallow, 2), avoidClasses(clPassageway, 0)], scaleByMapSize(6, 36), 50 ); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); setWaterWaviness(2.5); setWaterType("ocean"); setWaterMurkiness(0.49); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/corsica.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/corsica.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/corsica.js (revision 26381) @@ -1,519 +1,519 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); var tGrass = ["medit_grass_field", "medit_grass_field_b", "temp_grass_c"]; var tLushGrass = ["medit_grass_field","medit_grass_field_a"]; var tSteepCliffs = ["temp_cliff_b", "temp_cliff_a"]; var tCliffs = ["temp_cliff_b", "medit_cliff_italia", "medit_cliff_italia_grass"]; var tHill = ["medit_cliff_italia_grass","medit_cliff_italia_grass", "medit_grass_field", "medit_grass_field", "temp_grass"]; var tMountain = ["medit_cliff_italia_grass","medit_cliff_italia"]; var tRoad = ["medit_city_tile","medit_rocks_grass","medit_grass_field_b"]; var tRoadWild = ["medit_rocks_grass","medit_grass_field_b"]; var tShoreBlend = ["medit_sand_wet","medit_rocks_wet"]; var tShore = ["medit_rocks","medit_sand","medit_sand"]; var tSandTransition = ["medit_sand","medit_rocks_grass","medit_rocks_grass","medit_rocks_grass"]; var tVeryDeepWater = ["medit_sea_depths","medit_sea_coral_deep"]; var tDeepWater = ["medit_sea_coral_deep","tropic_ocean_coral"]; var tCreekWater = "medit_sea_coral_plants"; var ePine = "gaia/tree/aleppo_pine"; var ePalmTall = "gaia/tree/cretan_date_palm_tall"; var eFanPalm = "gaia/tree/medit_fan_palm"; var eApple = "gaia/fruit/apple"; var eBush = "gaia/fruit/berry_01"; var eFish = "gaia/fish/generic"; var ePig = "gaia/fauna_pig"; var eStoneMine = "gaia/rock/mediterranean_large"; var eMetalMine = "gaia/ore/mediterranean_large"; var aRock = "actor|geology/stone_granite_med.xml"; var aLargeRock = "actor|geology/stone_granite_large.xml"; var aBushA = "actor|props/flora/bush_medit_sm_lush.xml"; var aBushB = "actor|props/flora/bush_medit_me_lush.xml"; var aPlantA = "actor|props/flora/plant_medit_artichoke.xml"; var aPlantB = "actor|props/flora/grass_tufts_a.xml"; var aPlantC = "actor|props/flora/grass_soft_tuft_a.xml"; var aStandingStone = "actor|props/special/eyecandy/standing_stones.xml"; var heightSeaGround = -8; var heightCreeks = -5; var heightBeaches = -1; var heightMain = 5; var heightOffsetMainRelief = 30; var heightOffsetLevel1 = 9; var heightOffsetLevel2 = 8; var heightOffsetBumps = 2; var heightOffsetAntiBumps = -5; var g_Map = new RandomMap(heightSeaGround, tVeryDeepWater); var numPlayers = getNumPlayers(); var mapSize = g_Map.getSize(); var mapCenter = g_Map.getCenter(); var clIsland = g_Map.createTileClass(); var clCreek = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clCliffs = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clShore = g_Map.createTileClass(); var clPlayer = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clPassage = g_Map.createTileClass(); var clSettlement = g_Map.createTileClass(); var radiusBeach = fractionToTiles(0.57); var radiusCreeks = fractionToTiles(0.52); var radiusIsland = fractionToTiles(0.4); var radiusLevel1 = fractionToTiles(0.35); var radiusPlayer = fractionToTiles(0.25); var radiusLevel2 = fractionToTiles(0.2); var creeksArea = () => randBool() ? randFloat(10, 50) : scaleByMapSize(75, 100) + randFloat(0, 20); var nbCreeks = scaleByMapSize(6, 15); var nbSubIsland = 5; var nbBeaches = scaleByMapSize(2, 5); var nbPassagesLevel1 = scaleByMapSize(4, 8); var nbPassagesLevel2 = scaleByMapSize(2, 4); g_Map.log("Creating Corsica and Sardinia"); var swapAngle = randBool() ? Math.PI / 2 : 0; var islandLocations = [new Vector2D(0.05, 0.05), new Vector2D(0.95, 0.95)].map(v => v.mult(mapSize).rotateAround(-swapAngle, mapCenter)); for (let island = 0; island < 2; ++island) { g_Map.log("Creating island area"); createArea( new ClumpPlacer(diskArea(radiusIsland), 1, 0.5, Infinity, islandLocations[island]), [ new LayeredPainter([tCliffs, tGrass], [2]), new SmoothElevationPainter(ELEVATION_SET, heightMain, 0), new TileClassPainter(clIsland) ]); g_Map.log("Creating subislands"); for (let i = 0; i < nbSubIsland + 1; ++i) { let angle = Math.PI * (island + i / (nbSubIsland * 2)) + swapAngle; let location = Vector2D.add(islandLocations[island], new Vector2D(radiusIsland, 0).rotate(-angle)); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.09)), 0.6, 0.03, Infinity, location), [ new LayeredPainter([tCliffs, tGrass], [2]), new SmoothElevationPainter(ELEVATION_SET, heightMain, 1), new TileClassPainter(clIsland) ]); } g_Map.log("Creating creeks"); for (let i = 0; i < nbCreeks + 1; ++i) { let angle = Math.PI * (island + i * (1 / (nbCreeks * 2))) + swapAngle; let location = Vector2D.add(islandLocations[island], new Vector2D(radiusCreeks, 0).rotate(-angle)); createArea( new ClumpPlacer(creeksArea(), 0.4, 0.01, Infinity, location), [ new TerrainPainter(tSteepCliffs), new SmoothElevationPainter(ELEVATION_SET, heightCreeks, 0), new TileClassPainter(clCreek) ]); } g_Map.log("Creating beaches"); for (let i = 0; i < nbBeaches + 1; ++i) { let angle = Math.PI * (island + (i / (nbBeaches * 2.5)) + 1 / (nbBeaches * 6) + randFloat(-1, 1) / (nbBeaches * 7)) + swapAngle; let start = Vector2D.add(islandLocations[island], new Vector2D(radiusIsland, 0).rotate(-angle)); let end = Vector2D.add(islandLocations[island], new Vector2D(radiusBeach, 0).rotate(-angle)); createArea( new ClumpPlacer(130, 0.7, 0.8, Infinity, Vector2D.add(start, Vector2D.mult(end, 3)).div(4)), new SmoothElevationPainter(ELEVATION_SET, heightBeaches, 5)); createPassage({ "start": start, "end": end, "startWidth": 18, "endWidth": 25, "smoothWidth": 4, "tileClass": clShore }); } g_Map.log("Creating main relief"); createArea( new ClumpPlacer(diskArea(radiusIsland), 1, 0.2, Infinity, islandLocations[island]), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetMainRelief, fractionToTiles(0.45))); g_Map.log("Creating first level plateau"); createArea( new ClumpPlacer(diskArea(radiusLevel1), 0.95, 0.02, Infinity, islandLocations[island]), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetLevel1, 1)); g_Map.log("Creating first level passages"); for (let i = 0; i <= nbPassagesLevel1; ++i) { let angle = Math.PI * (i / 7 + 1 / 9 + island) + swapAngle; createPassage({ "start": Vector2D.add(islandLocations[island], new Vector2D(radiusLevel1 + 10, 0).rotate(-angle)), "end": Vector2D.add(islandLocations[island], new Vector2D(radiusLevel1 - 4, 0).rotate(-angle)), "startWidth": 10, "endWidth": 6, "smoothWidth": 3, "tileClass": clPassage }); } if (mapSize > 150) { g_Map.log("Creating second level plateau"); createArea( new ClumpPlacer(diskArea(radiusLevel2), 0.98, 0.04, Infinity, islandLocations[island]), [ new LayeredPainter([tCliffs, tGrass], [2]), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetLevel2, 1) ]); g_Map.log("Creating second level passages"); for (let i = 0; i < nbPassagesLevel2; ++i) { let angle = Math.PI * (i / (2 * nbPassagesLevel2) + 1 / (4 * nbPassagesLevel2) + island) + swapAngle; createPassage({ "start": Vector2D.add(islandLocations[island], new Vector2D(radiusLevel2 + 3, 0).rotate(-angle)), "end": Vector2D.add(islandLocations[island], new Vector2D(radiusLevel2 - 6, 0).rotate(-angle)), "startWidth": 4, "endWidth": 6, "smoothWidth": 2, "tileClass": clPassage }); } } } Engine.SetProgress(30); g_Map.log("Determining player locations"); var playerIDs = sortAllPlayers(); var playerPosition = []; var playerAngle = []; var p = 0; for (let island = 0; island < 2; ++island) { let playersPerIsland = island == 0 ? Math.ceil(numPlayers / 2) : Math.floor(numPlayers / 2); for (let i = 0; i < playersPerIsland; ++i) { playerAngle[p] = Math.PI * ((i + 0.5) / (2 * playersPerIsland) + island) + swapAngle; playerPosition[p] = Vector2D.add(islandLocations[island], new Vector2D(radiusPlayer).rotate(-playerAngle[p])); addCivicCenterAreaToClass(playerPosition[p], clPlayer); ++p; } } placePlayerBases({ "PlayerPlacement": [sortAllPlayers(), playerPosition], "BaseResourceClass": clBaseResource, "baseResourceConstraint": avoidClasses(clPlayer, 2), "Walls": false, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad, "coherence": 0.8, "radius": 6, "painters": [ new TileClassPainter(clSettlement) ] }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": eBush }, "Mines": { "types": [ { "template": eMetalMine }, { "template": eStoneMine } ] } // Sufficient starting trees around, no decoratives }); Engine.SetProgress(40); g_Map.log("Creating bumps"); createAreas( new ClumpPlacer(70, 0.6, 0.1, Infinity), [new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBumps, 3)], [ stayClasses(clIsland, 2), avoidClasses(clPlayer, 6, clPassage, 2) ], scaleByMapSize(20, 100), 5); g_Map.log("Creating anti bumps"); createAreas( new ClumpPlacer(120, 0.3, 0.1, Infinity), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetAntiBumps, 6), avoidClasses(clPlayer, 6, clPassage, 2, clIsland, 2), scaleByMapSize(20, 100), 5); g_Map.log("Painting water"); paintTileClassBasedOnHeight(-Infinity, 0, Elevation_ExcludeMin_ExcludeMax, clWater); g_Map.log("Painting land"); for (let mapX = 0; mapX < mapSize; ++mapX) for (let mapZ = 0; mapZ < mapSize; ++mapZ) { let position = new Vector2D(mapX, mapZ); let terrain = getCosricaSardiniaTerrain(position); if (!terrain) continue; createTerrain(terrain).place(position); if (terrain == tCliffs || terrain == tSteepCliffs) clCliffs.add(position); } function getCosricaSardiniaTerrain(position) { let isWater = clWater.countMembersInRadius(position, 3); let isShore = clShore.countMembersInRadius(position, 2); let isPassage = clPassage.countMembersInRadius(position, 2); let isSettlement = clSettlement.countMembersInRadius(position, 2); if (isSettlement) return undefined; let height = g_Map.getHeight(position); let slope = g_Map.getSlope(position); if (height >= 0.5 && height < 1.5 && isShore) return tSandTransition; // Paint land cliffs and grass if (height >= 1 && !isWater) { if (isPassage) return tGrass; if (slope >= 1.25) return height > 25 ? tSteepCliffs : tCliffs; if (height < 17) return tGrass; if (slope < 0.625) return tHill; return tMountain; } if (slope >= 1.125) return tCliffs; if (height >= 1.5) return undefined; if (height >= -0.75) return tShore; if (height >= -3) return tShoreBlend; if (height >= -6) return tCreekWater; if (height > -10 && slope < 0.75) return tDeepWater; return undefined; } Engine.SetProgress(65); g_Map.log("Creating mines"); for (let mine of [eMetalMine, eStoneMine]) createObjectGroupsDeprecated( new SimpleGroup( [ new SimpleObject(mine, 1,1, 0,0), new SimpleObject(aBushB, 1,1, 2,2), new SimpleObject(aBushA, 0,2, 1,3) ], true, clBaseResource), 0, [ stayClasses(clIsland, 1), avoidClasses( clWater, 3, clPlayer, 6, clBaseResource, 4, clPassage, 2, clCliffs, 1) ], scaleByMapSize(6, 25), 1000); g_Map.log("Creating grass patches"); createAreas( new ClumpPlacer(20, 0.3, 0.06, 0.5), [ new TerrainPainter(tLushGrass), new TileClassPainter(clForest) ], avoidClasses( clWater, 1, clPlayer, 6, clBaseResource, 3, clCliffs, 1), scaleByMapSize(10, 40)); g_Map.log("Creating forests"); createObjectGroupsDeprecated( 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), 0, [ stayClasses(clIsland, 3), avoidClasses( clWater, 1, clForest, 0, clPlayer, 3, clBaseResource, 4, clPassage, 2, clCliffs, 2) ], scaleByMapSize(350, 2500), 100); Engine.SetProgress(75); g_Map.log("Creating small decorative rocks"); createObjectGroupsDeprecated( new SimpleGroup( [ new SimpleObject(aRock, 1, 3, 0, 1), new SimpleObject(aStandingStone, 0, 2, 0, 3) ], true), 0, avoidClasses( clWater, 0, clForest, 0, clPlayer, 6, clBaseResource, 4, clPassage, 2), scaleByMapSize(16, 262), 50); g_Map.log("Creating large decorative rocks"); var rocksGroup = new SimpleGroup( [ new SimpleObject(aLargeRock, 1, 2, 0, 1), new SimpleObject(aRock, 1, 3, 0, 2) ], true); createObjectGroupsDeprecated( rocksGroup, 0, avoidClasses( clWater, 0, clForest, 0, clPlayer, 6, clBaseResource, 4, clPassage, 2), scaleByMapSize(8, 131), 50); createObjectGroupsDeprecated( rocksGroup, 0, borderClasses(clWater, 5, 10), scaleByMapSize(100, 800), 500); g_Map.log("Creating decorative plants"); var plantGroups = [ new SimpleGroup( [ new SimpleObject(aPlantA, 3, 7, 0, 3), new SimpleObject(aPlantB, 3,6, 0, 3), new SimpleObject(aPlantC, 1,4, 0, 4) ], true), new SimpleGroup( [ new SimpleObject(aPlantB, 5, 20, 0, 5), new SimpleObject(aPlantC, 4,10, 0,4) ], true) ]; for (let group of plantGroups) createObjectGroupsDeprecated( group, 0, avoidClasses( clWater, 0, clBaseResource, 4, clShore, 3), scaleByMapSize(100, 600), 50); Engine.SetProgress(80); g_Map.log("Creating animals"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(ePig, 2,4, 0,3)]), 0, avoidClasses( clWater, 3, clBaseResource, 4, clPlayer, 6), scaleByMapSize(20, 100), 50); g_Map.log("Creating fish"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(eFish, 1,2, 0,3)]), 0, [ stayClasses(clWater, 3), avoidClasses(clCreek, 3, clShore, 3) ], scaleByMapSize(50, 150), 100); Engine.SetProgress(95); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clBaseResource, 4, clCliffs, 4)); setSkySet(pickRandom(["cumulus", "sunny"])); setSunColor(0.8, 0.66, 0.48); setSunElevation(0.828932); setSunRotation((swapAngle ? 0.288 : 0.788) * Math.PI); setAmbientColor(0.564706,0.543726,0.419608); setWaterColor(0.2,0.294,0.49); setWaterTint(0.208, 0.659, 0.925); setWaterMurkiness(0.72); setWaterWaviness(2.0); setWaterType("ocean"); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/cycladic_archipelago.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/cycladic_archipelago.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/cycladic_archipelago.js (revision 26381) @@ -1,364 +1,364 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); const tOceanRockDeep = "medit_sea_coral_deep"; const tOceanCoral = "medit_sea_coral_plants"; const tBeachWet = "medit_sand_wet"; const tBeachDry = "medit_sand"; const tBeach = ["medit_rocks_grass","medit_sand", "medit_rocks_grass_shrubs"]; const tBeachBlend = ["medit_rocks_grass", "medit_rocks_grass_shrubs"]; const tCity = "medit_city_tile"; const tGrassDry = ["medit_grass_field_dry", "medit_grass_field_b"]; const tGrass = ["medit_rocks_grass", "medit_rocks_grass","medit_dirt","medit_rocks_grass_shrubs"]; const tGrassShrubs = "medit_shrubs"; const tCliffShrubs = ["medit_cliff_aegean_shrubs", "medit_cliff_italia_grass","medit_cliff_italia"]; const tCliff = ["medit_cliff_italia", "medit_cliff_italia", "medit_cliff_italia_grass"]; const tForestFloor = "medit_forestfloor_a"; const tWater = "medit_sea_depths"; const oBeech = "gaia/tree/euro_beech"; const oBerryBush = "gaia/fruit/berry_01"; const oCarob = "gaia/tree/carob"; const oCypress1 = "gaia/tree/cypress"; const oCypress2 = "gaia/tree/cypress"; const oLombardyPoplar = "gaia/tree/poplar_lombardy"; const oPalm = "gaia/tree/medit_fan_palm"; const oPine = "gaia/tree/aleppo_pine"; const oDateT = "gaia/tree/cretan_date_palm_tall"; const oDateS = "gaia/tree/cretan_date_palm_short"; const oDeer = "gaia/fauna_deer"; const oFish = "gaia/fish/generic"; const oWhale = "gaia/fauna_whale_humpback"; const oStoneLarge = "gaia/rock/mediterranean_large"; const oStoneSmall = "gaia/rock/mediterranean_small"; const oMetalLarge = "gaia/ore/mediterranean_large"; const oShipwreck = "gaia/treasure/shipwreck"; const oShipDebris = "gaia/treasure/shipwreck_debris"; const aRockLarge = "actor|geology/stone_granite_large.xml"; const aRockMed = "actor|geology/stone_granite_med.xml"; const aRockSmall = "actor|geology/stone_granite_small.xml"; const pPalmForest = [tForestFloor+TERRAIN_SEPARATOR+oPalm, tGrass]; const pPineForest = [tForestFloor+TERRAIN_SEPARATOR+oPine, tGrass]; const pPoplarForest = [tForestFloor+TERRAIN_SEPARATOR+oLombardyPoplar, tGrass]; const pMainForest = [tForestFloor+TERRAIN_SEPARATOR+oCarob, tForestFloor+TERRAIN_SEPARATOR+oBeech, tGrass, tGrass]; const heightSeaGround = -5; const heightLand = 3; const heightHill = 12; const heightOffsetBump = 2; var g_Map = new RandomMap(heightSeaGround, tWater); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); var clCoral = g_Map.createTileClass(); var clPlayer = g_Map.createTileClass(); var clIsland = g_Map.createTileClass(); var clCity = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); //array holding starting islands based on number of players var startingPlaces=[[0],[0,3],[0,2,4],[0,1,3,4],[0,1,2,3,4],[0,1,2,3,4,5]]; var startAngle = randomAngle(); var islandRadius = scaleByMapSize(15, 40); var islandCount = Math.max(6, numPlayers); var islandPosition = distributePointsOnCircle(islandCount, startAngle, fractionToTiles(0.39), mapCenter)[0].map(position => position.round()); var centralIslandRadius = scaleByMapSize(15, 30); var centralIslandCount = Math.floor(scaleByMapSize(1, 4)); var centralIslandPosition = new Array(numPlayers).fill(0).map((v, i) => Vector2D.add(mapCenter, new Vector2D(fractionToTiles(randFloat(0.1, 0.16)), 0).rotate( -startAngle - Math.PI * (i * 2 / centralIslandCount + randFloat(-1, 1) / 8)).round())); var areas = []; var nPlayer = 0; var playerPosition = []; function createCycladicArchipelagoIsland(position, tileClass, radius, coralRadius) { // Deep ocean rocks createArea( new ClumpPlacer(diskArea(radius + coralRadius), 0.7, 0.1, Infinity, position), [ new LayeredPainter([tOceanRockDeep, tOceanCoral], [5]), new TileClassPainter(clCoral) ], avoidClasses(clCoral, 0, clPlayer, 0)); // Island areas.push( createArea( new ClumpPlacer(diskArea(radius), 0.7, 0.1, Infinity, position), [ new LayeredPainter([tOceanCoral, tBeachWet, tBeachDry, tBeach, tBeachBlend, tGrass], [1, 3, 1, 1, 2]), new SmoothElevationPainter(ELEVATION_SET, heightLand, 5), new TileClassPainter(tileClass) ], avoidClasses(clPlayer, 0))); } g_Map.log("Creating player islands"); for (let i = 0; i < islandCount; ++i) { let isPlayerIsland = numPlayers >= 6 || i == startingPlaces[numPlayers - 1][nPlayer]; if (isPlayerIsland) { playerPosition[nPlayer] = islandPosition[i]; ++nPlayer; } createCycladicArchipelagoIsland(islandPosition[i], isPlayerIsland ? clPlayer : clIsland, islandRadius, scaleByMapSize(1, 5)); } g_Map.log("Creating central islands"); for (let position of centralIslandPosition) createCycladicArchipelagoIsland(position, clIsland, centralIslandRadius, 2); placePlayerBases({ "PlayerPlacement": [sortAllPlayers(), playerPosition], // PlayerTileClass is clCity here and painted below "BaseResourceClass": clBaseResource, "Walls": "towers", "CityPatch": { "radius": 6, "outerTerrain": tGrass, "innerTerrain": tCity, "painters": [ new TileClassPainter(clCity) ] }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oPalm, "count": 2 } // No decoratives }); Engine.SetProgress(20); g_Map.log("Creating bumps"); createAreasInAreas( new ClumpPlacer(scaleByMapSize(20, 60), 0.3, 0.06, Infinity), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 3), avoidClasses(clCity, 0), scaleByMapSize(25, 75),15, areas); Engine.SetProgress(34); g_Map.log("Creating hills"); createAreasInAreas( new ClumpPlacer(scaleByMapSize(20, 150), 0.2, 0.1, Infinity), [ new LayeredPainter([tCliff, tCliffShrubs], [2]), new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), new TileClassPainter(clHill) ], avoidClasses(clCity, 15, clHill, 15), scaleByMapSize(5, 30), 15, areas); Engine.SetProgress(38); paintTileClassBasedOnHeight(-Infinity, 0, Elevation_ExcludeMin_ExcludeMax, clWater); g_Map.log("Creating forests"); var forestTypes = [ [[tForestFloor, tGrass, pPalmForest], [tForestFloor, pPalmForest]], [[tForestFloor, tGrass, pPineForest], [tForestFloor, pPineForest]], [[tForestFloor, tGrass, pPoplarForest], [tForestFloor, pPoplarForest]], [[tForestFloor, tGrass, pMainForest], [tForestFloor, pMainForest]] ]; for (let type of forestTypes) createAreasInAreas( new ClumpPlacer(randIntInclusive(6, 17), 0.1, 0.1, Infinity), [ new LayeredPainter(type, [2]), new TileClassPainter(clForest) ], avoidClasses(clCity, 1, clWater, 3, clForest, 3, clHill, 1, clBaseResource, 4), scaleByMapSize(10, 64), 20, areas); Engine.SetProgress(42); g_Map.log("Creating stone mines"); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], true, clRock); createObjectGroupsByAreasDeprecated(group, 0, [avoidClasses(clWater, 1, clForest, 1, clHill, 1, clPlayer, 5, clRock, 6)], scaleByMapSize(4,16), 200, areas ); Engine.SetProgress(46); g_Map.log("Creating small stone mines"); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock); createObjectGroupsByAreasDeprecated(group, 0, [avoidClasses(clWater, 1, clForest, 1, clHill, 1, clPlayer, 5, clRock, 6)], scaleByMapSize(4,16), 200, areas ); Engine.SetProgress(50); g_Map.log("Creating metal mines"); group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4)], true, clMetal); createObjectGroupsByAreasDeprecated(group, 0, [avoidClasses(clWater, 1, clForest, 1, clHill, 1, clPlayer, 5, clMetal, 6, clRock, 6)], scaleByMapSize(4,16), 200, areas ); Engine.SetProgress(54); g_Map.log("Creating shrub patches"); for (let size of [scaleByMapSize(2, 32), scaleByMapSize(3, 48), scaleByMapSize(5, 80)]) createAreasInAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), [ new LayeredPainter([tBeachBlend, tGrassShrubs], [1]), new TileClassPainter(clDirt) ], avoidClasses(clWater, 3, clHill, 0, clDirt, 6, clCity, 0, clBaseResource, 4), scaleByMapSize(4, 16), 20, areas); Engine.SetProgress(58); g_Map.log("Creating grass patches"); for (let size of [scaleByMapSize(2, 32), scaleByMapSize(3, 48), scaleByMapSize(5, 80)]) createAreasInAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), [ new LayeredPainter([tGrassDry], []), new TileClassPainter(clDirt) ], avoidClasses(clWater, 3, clHill, 0, clDirt, 6, clCity, 0, clBaseResource, 4), scaleByMapSize(4, 16), 20, areas); Engine.SetProgress(62); g_Map.log("Creating straggler trees"); for (let tree of [oCarob, oBeech, oLombardyPoplar, oLombardyPoplar, oPine]) createObjectGroupsByAreasDeprecated( new SimpleGroup([new SimpleObject(tree, 1,1, 0,1)], true, clForest), 0, avoidClasses(clWater, 2, clForest, 2, clCity, 3, clBaseResource, 4, clRock, 6, clMetal, 6, clPlayer, 1, clHill, 1), scaleByMapSize(2, 38), 50, areas ); Engine.SetProgress(66); g_Map.log("Create straggler cypresses"); group = new SimpleGroup( [new SimpleObject(oCypress2, 1,3, 0,3), new SimpleObject(oCypress1, 0,2, 0,2)], true ); createObjectGroupsByAreasDeprecated(group, 0, avoidClasses(clWater, 2, clForest, 2, clCity, 3, clBaseResource, 4, clRock, 6, clMetal, 6, clPlayer, 1, clHill, 1), scaleByMapSize(5, 75), 50, areas ); Engine.SetProgress(70); g_Map.log("Create straggler date palms"); group = new SimpleGroup( [new SimpleObject(oDateS, 1,3, 0,3), new SimpleObject(oDateT, 0,2, 0,2)], true ); createObjectGroupsByAreasDeprecated(group, 0, avoidClasses(clWater, 2, clForest, 1, clCity, 0, clBaseResource, 4, clRock, 6, clMetal, 6, clPlayer, 1, clHill, 1), scaleByMapSize(5, 75), 50, areas ); Engine.SetProgress(74); g_Map.log("Creating rocks"); group = new SimpleGroup( [new SimpleObject(aRockSmall, 0,3, 0,2), new SimpleObject(aRockMed, 0,2, 0,2), new SimpleObject(aRockLarge, 0,1, 0,2)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 0, clCity, 0), scaleByMapSize(30, 180), 50 ); Engine.SetProgress(78); g_Map.log("Creating deer"); group = new SimpleGroup( [new SimpleObject(oDeer, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 5, clForest, 1, clHill, 1, clCity, 10, clMetal, 6, clRock, 4, clFood, 8), 3 * numPlayers, 50 ); Engine.SetProgress(82); g_Map.log("Creating berry bushes"); group = new SimpleGroup([new SimpleObject(oBerryBush, 5,7, 0,3)], true, clFood); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 2, clForest, 1, clHill, 1, clCity, 10, clMetal, 6, clRock, 4, clFood, 8), 1.5 * numPlayers, 100 ); Engine.SetProgress(86); g_Map.log("Creating Fish"); group = new SimpleGroup([new SimpleObject(oFish, 1,1, 0,3)], true, clFood); createObjectGroupsDeprecated(group, 0, [stayClasses(clWater,1),avoidClasses(clFood, 8)], scaleByMapSize(40,200), 100 ); Engine.SetProgress(90); g_Map.log("Creating Whales"); group = new SimpleGroup([new SimpleObject(oWhale, 1,1, 0,3)], true, clFood); createObjectGroupsDeprecated(group, 0, [stayClasses(clWater,1),avoidClasses(clFood, 8, clPlayer,4,clIsland,4)], scaleByMapSize(10,40), 100 ); Engine.SetProgress(94); g_Map.log("Creating shipwrecks"); group = new SimpleGroup([new SimpleObject(oShipwreck, 1,1, 0,3)], true, clFood); createObjectGroupsDeprecated(group, 0, [stayClasses(clWater,1),avoidClasses(clFood, 8)], scaleByMapSize(6,16), 100 ); Engine.SetProgress(98); g_Map.log("Creating shipwreck debris"); group = new SimpleGroup([new SimpleObject(oShipDebris, 1,2, 0,4)], true, clFood); createObjectGroupsDeprecated(group, 0, [stayClasses(clWater,1),avoidClasses(clFood, 8)], scaleByMapSize(10,20), 100 ); Engine.SetProgress(99); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clBaseResource, 4, clHill, 4, clMetal, 4, clRock, 4, clFood, 1)); setSkySet("sunny"); setWaterColor(0.2,0.294,0.49); setWaterTint(0.208, 0.659, 0.925); setWaterMurkiness(0.72); setWaterWaviness(3.0); setWaterType("ocean"); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/danubius.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/danubius.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/danubius.js (revision 26381) @@ -1,844 +1,844 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); const day = g_MapSettings.Daytime !== undefined ? g_MapSettings.Daytime == "day" : randBool(2/3); // Spawn ships away from the shoreline, but patrol close to the shoreline const triggerPointShipSpawn = "trigger/trigger_point_A"; const triggerPointShipPatrol = "trigger/trigger_point_B"; const triggerPointShipUnloadLeft = "trigger/trigger_point_C"; const triggerPointShipUnloadRight = "trigger/trigger_point_D"; const triggerPointLandPatrolLeft = "trigger/trigger_point_E"; const triggerPointLandPatrolRight = "trigger/trigger_point_F"; const triggerPointCCAttackerPatrolLeft = "trigger/trigger_point_G"; const triggerPointCCAttackerPatrolRight = "trigger/trigger_point_H"; const triggerPointRiverDirection = "trigger/trigger_point_I"; const tPrimary = ["temp_grass_aut", "temp_grass_plants_aut", "temp_grass_c_aut", "temp_grass_d_aut"]; const tRoad = "steppe_river_rocks"; const tIsland = ["temp_grass_long_b_aut", "temp_grass_plants_aut", "temp_forestfloor_aut"]; const tCliff = "temp_cliff_a"; const tForestFloor = "temp_forestfloor_aut"; const tGrass = "medit_shrubs_golden"; const tGrass2 ="grass_mediterranean_dry_1024test"; const tGrass3 = "medit_grass_field_b"; const tShore = "temp_dirt_gravel_b"; const tWater = "steppe_river_rocks_wet"; const tSeaDepths = "medit_sea_depths"; const oBerryBush = "gaia/fruit/berry_01"; const oDeer = "gaia/fauna_deer"; const oFish = "gaia/fish/generic"; const oSheep = "gaia/fauna_sheep"; const oGoat = "gaia/fauna_goat"; const oWolf = "gaia/fauna_wolf"; const oHawk = "birds/buzzard"; const oRabbit = "gaia/fauna_rabbit"; const oBoar = "gaia/fauna_boar"; const oBear = "gaia/fauna_bear_brown"; const oStoneLarge = "gaia/rock/temperate_large"; const oStoneRuins = "gaia/ruins/standing_stone"; const oMetalLarge = "gaia/ore/mediterranean_large"; const oApple = "gaia/fruit/apple"; const oAcacia = "gaia/tree/acacia"; const oOak = "gaia/tree/oak_aut"; const oOak2 = "gaia/tree/oak_aut_new"; const oOak3 = "gaia/tree/oak_dead"; const oOak4 = "gaia/tree/oak"; const oPopolar = "gaia/tree/poplar_lombardy"; const oBeech = "gaia/tree/euro_beech_aut"; const oBeech2 = "gaia/tree/euro_beech"; const oTreasures = [ "gaia/treasure/food_barrel", "gaia/treasure/food_bin", "gaia/treasure/stone", "gaia/treasure/wood", "gaia/treasure/metal" ]; // Disable capturing on all parts of the village except the // civic center and buildings occurring outside of the village const oCivicCenter = "structures/gaul/civil_centre"; const oTower = "structures/gaul/defense_tower"; const oOutpost = "structures/gaul/outpost"; const oTemple = "uncapturable|structures/gaul/temple"; const oTavern = "uncapturable|structures/gaul/tavern"; const oHouse = "uncapturable|structures/gaul/house"; const oLongHouse = "uncapturable|structures/celt_longhouse"; const oHut = "uncapturable|structures/celt_hut"; const oSentryTower = "uncapturable|structures/gaul/sentry_tower"; const oWatchTower = "uncapturable|structures/palisades_watchtower"; const oPalisadeTallSpikes = "uncapturable|structures/palisades_spikes_tall"; const oPalisadeAngleSpikes = "uncapturable|structures/palisades_spike_angle"; const oPalisadeCurve = "uncapturable|structures/palisades_curve"; const oPalisadeShort = "uncapturable|structures/palisades_short"; const oPalisadeMedium = "uncapturable|structures/palisades_medium"; const oPalisadeLong = "uncapturable|structures/palisades_long"; const oPalisadeGate = "uncapturable|structures/palisades_gate"; const oPalisadePillar = "uncapturable|structures/palisades_tower"; const oFemale = "units/gaul/support_female_citizen"; const oHealer = "units/gaul/support_healer_b"; const oSkirmisher = "units/gaul/infantry_javelineer_b"; const oNakedFanatic = "units/gaul/champion_fanatic"; const aBush1 = "actor|props/flora/bush_tempe_sm.xml"; const aBush2 = "actor|props/flora/bush_tempe_me.xml"; const aBush3 = "actor|props/flora/bush_tempe_la.xml"; const aBush4 = "actor|props/flora/bush_tempe_me.xml"; const aRock1 = "actor|geology/stone_granite_med.xml"; const aRock2 = "actor|geology/stone_granite_boulder.xml"; const aRock3 = "actor|geology/stone_granite_greek_boulder.xml"; const aRock4 = "actor|geology/stonemine_alpine_a.xml"; const aFerns = "actor|props/flora/ferns.xml"; const aBucket = "actor|props/structures/celts/blacksmith_bucket"; const aBarrel = "actor|props/structures/gauls/storehouse_barrel_b"; const aTartan = "actor|props/structures/celts/tartan_a"; const aWheel = "actor|props/special/eyecandy/wheel_laying"; const aWell = "actor|props/special/eyecandy/well_1_b"; const aWoodcord = "actor|props/special/eyecandy/woodcord"; const aWaterLog = "actor|props/flora/water_log.xml"; const aCampfire = "actor|props/special/eyecandy/campfire"; const aBench = "actor|props/special/eyecandy/bench_1"; const aRug = "actor|props/special/eyecandy/rug_stand_iber"; const treeTypes = [oOak, oOak2, oOak3, oOak4, oBeech, oBeech2, oAcacia]; const pForest1 = [ tForestFloor, tForestFloor + TERRAIN_SEPARATOR + oOak, tForestFloor + TERRAIN_SEPARATOR + oOak2, tForestFloor + TERRAIN_SEPARATOR + oOak3, tForestFloor + TERRAIN_SEPARATOR + oOak4, tForestFloor ]; const pForest2 = [ tForestFloor, tForestFloor + TERRAIN_SEPARATOR + oPopolar, tForestFloor + TERRAIN_SEPARATOR + oBeech, tForestFloor + TERRAIN_SEPARATOR + oBeech2, tForestFloor + TERRAIN_SEPARATOR + oAcacia, tForestFloor ]; const smallMapSize = 192; const mediumMapSize = 256; const normalMapSize = 320; // Minimum distance from the map border to ship ungarrison points const ShorelineDistance = 15; const heightSeaGround = -3; const heightShore = 1; const heightLand = 3; const heightPath = 1.5; const heightIsland = 6; var g_Map = new RandomMap(heightLand, tPrimary); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); const mapBounds = g_Map.getBounds(); var clPlayer = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clLand = [g_Map.createTileClass(), g_Map.createTileClass()]; var clPatrolPointSiegeEngine = [g_Map.createTileClass(), g_Map.createTileClass()]; var clPatrolPointSoldier = [g_Map.createTileClass(), g_Map.createTileClass()]; var clShore = [g_Map.createTileClass(), g_Map.createTileClass()]; var clShoreUngarrisonPoint = [g_Map.createTileClass(), g_Map.createTileClass()]; var clShip = g_Map.createTileClass(); var clShipPatrol = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clIsland = g_Map.createTileClass(); var clTreasure = g_Map.createTileClass(); var clWaterLog = g_Map.createTileClass(); var clGauls = g_Map.createTileClass(); var clTower = g_Map.createTileClass(); var clOutpost = g_Map.createTileClass(); var clPath = g_Map.createTileClass(); var clRitualPlace = g_Map.createTileClass(); var startAngle = randomAngle(); var waterWidth = fractionToTiles(0.3); // How many treasures will be placed near the gallic civic centers var gallicCCTreasureCount = randIntInclusive(8, 12); // How many treasures will be placed randomly on the map at most var randomTreasureCount = randIntInclusive(0, scaleByMapSize(0, 2)); var ritualParticipants = [ { "radius": 0.6, "templates": [oFemale], "count": 9, "angle": Math.PI }, { "radius": 0.8, "templates": [oSkirmisher, oHealer, oNakedFanatic], "count": 15, "angle": Math.PI }, { "radius": 1, "templates": [aBench], "count": 10, "angle": Math.PI / 2 }, { "radius": 1.1, "templates": [oGoat], "count": 7, "angle": 0 }, { "radius": 1.2, "templates": [aRug], "count": 8, "angle": Math.PI } ]; g_WallStyles.danubius_village = { "house": { "angle": Math.PI, "length": 0, "indent": 4, "bend": 0, "templateName": oHouse }, "hut": { "angle": Math.PI, "length": 0, "indent": 4, "bend": 0, "templateName": oHut }, "longhouse": { "angle": Math.PI, "length": 0, "indent": 4, "bend": 0, "templateName": oLongHouse }, "tavern": { "angle": Math.PI * 3/2, "length": 0, "indent": 4, "bend": 0, "templateName": oTavern }, "temple": { "angle": Math.PI * 3/2, "length": 0, "indent": 4, "bend": 0, "templateName": oTemple }, "defense_tower": { "angle": Math.PI / 2, "length": 0, "indent": 4, "bend": 0, "templateName": mapSize >= normalMapSize ? (isNomad() ? oSentryTower : oTower) : oWatchTower }, "pillar": readyWallElement(oPalisadePillar), "gate": readyWallElement(oPalisadeGate), "long": readyWallElement(oPalisadeLong), "medium": readyWallElement(oPalisadeMedium), "short": readyWallElement(oPalisadeShort), "cornerIn": readyWallElement(oPalisadeCurve), "overlap": 0.05 }; g_WallStyles.danubius_spikes = { "spikes_tall": readyWallElement(oPalisadeTallSpikes, "gaia"), "spike_single": readyWallElement(oPalisadeAngleSpikes, "gaia"), "overlap": 0 }; var fortressDanubiusVillage = new Fortress( "Geto-Dacian Tribal Confederation", new Array(2).fill([ "gate", "pillar", "hut", "long", "long", "cornerIn", "defense_tower", "long", "temple", "long", "pillar", "house", "long", "short", "pillar", "gate", "pillar", "longhouse", "long", "long", "cornerIn", "defense_tower", "long", "tavern", "long", "pillar" ]).reduce((result, items) => result.concat(items), [])); var palisadeCorner = ["turn_0.25", "spike_single", "turn_0.25"]; var palisadeGate = ["spike_single", "gap_3.6", "spike_single"]; var palisadeWallShort = new Array(3).fill("spikes_tall"); var palisadeWallLong = new Array(5).fill("spikes_tall"); var palisadeSideShort = [...palisadeGate, ...palisadeWallShort, ...palisadeCorner, ...palisadeWallShort]; var palisadeSideLong = [...palisadeGate, ...palisadeWallShort, ...palisadeCorner, ...palisadeWallLong]; var fortressDanubiusSpikes = new Fortress( "Spikes Of The Geto-Dacian Tribal Confederation", [...palisadeSideLong, ...palisadeSideShort, ...palisadeSideLong, ...palisadeSideShort]); // Place a gallic village on small maps and larger var gallicCC = mapSize >= smallMapSize; if (gallicCC) { g_Map.log("Creating gallic villages"); let gaulCityRadius = 12; let gaulCityBorderDistance = mapSize < mediumMapSize ? 10 : 18; // Whether to add a celtic ritual and a path from the gallic city leading to it let addCelticRitual = randBool(0.9); // One village left and right of the river for (let i = 0; i < 2; ++i) { let civicCenterPosition = new Vector2D( i == 0 ? mapBounds.left + gaulCityBorderDistance : mapBounds.right - gaulCityBorderDistance, mapCenter.y).rotateAround(startAngle, mapCenter); if (addCelticRitual) { // Don't position the meeting place at the center of the map let meetingPlacePosition = new Vector2D( i == 0 ? mapBounds.left + waterWidth : mapBounds.right - waterWidth, mapCenter.y + fractionToTiles(randFloat(0.1, 0.4)) * (randBool() ? 1 : -1)).rotateAround(startAngle, mapCenter); // Radius of the meeting place let mRadius = scaleByMapSize(4, 6); // Create a path connecting the gallic city with a meeting place at the shoreline. // To avoid the path going through the palisade wall, start it at the gate, not at the city center. let pathStart = Vector2D.add(civicCenterPosition, new Vector2D(gaulCityRadius * (i == 0 ? 1 : -1), 0).rotate(startAngle)); createArea( new PathPlacer(pathStart, meetingPlacePosition, 4, 0.4, 4, 0.2, 0.05), [ new LayeredPainter([tShore, tRoad], [1]), new SmoothElevationPainter(ELEVATION_SET, heightPath, 4), new TileClassPainter(clPath) ]); // Create the meeting place near the shoreline at the end of the path createArea( new ClumpPlacer(diskArea(mRadius), 0.6, 0.3, Infinity, meetingPlacePosition), [ new TerrainPainter(tShore), new TileClassPainter(clPath), new TileClassPainter(clRitualPlace) ]); g_Map.placeEntityAnywhere(aCampfire, 0, meetingPlacePosition, randomAngle()); for (let participants of ritualParticipants) { let [positions, angles] = distributePointsOnCircle(participants.count, startAngle, participants.radius * mRadius, meetingPlacePosition); for (let j = 0; j < positions.length; ++j) g_Map.placeEntityPassable(pickRandom(participants.templates), 0, positions[j], angles[j] + participants.angle); } } g_Map.placeEntityPassable(oCivicCenter, 0, civicCenterPosition, startAngle + BUILDING_ORIENTATION + Math.PI * 3/2 * i); // Create the city patch createArea( new ClumpPlacer(diskArea(gaulCityRadius), 0.6, 0.3, Infinity, civicCenterPosition), [ new TerrainPainter(tShore), new TileClassPainter(clGauls) ]); // Place walls and buildings placeCustomFortress(civicCenterPosition, fortressDanubiusVillage, "danubius_village", 0, startAngle + Math.PI); placeCustomFortress(civicCenterPosition, fortressDanubiusSpikes, "danubius_spikes", 0, startAngle + Math.PI); // Place treasure, potentially inside buildings for (let j = 0; j < gallicCCTreasureCount; ++j) g_Map.placeEntityPassable( pickRandom(oTreasures), 0, Vector2D.add(civicCenterPosition, new Vector2D(randFloat(-0.8, 0.8) * gaulCityRadius, 0).rotate(randomAngle())), randomAngle()); } } Engine.SetProgress(10); placePlayerBases({ "PlayerPlacement": playerPlacementRiver(startAngle, fractionToTiles(0.6)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "Walls": false, "CityPatch": { "outerTerrain": tShore, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ], "distance": scaleByMapSize(9, 14) }, "Trees": { "template": oOak, "count": 20, "minDist": 10, "maxDist": 14 }, "Decoratives": { "template": aBush1 } }); Engine.SetProgress(20); paintRiver({ "parallel": true, "start": new Vector2D(mapCenter.x, mapBounds.top).rotateAround(startAngle, mapCenter), "end": new Vector2D(mapCenter.x, mapBounds.bottom).rotateAround(startAngle, mapCenter), "width": waterWidth, "fadeDist": scaleByMapSize(6, 25), "deviation": 0, "heightRiverbed": heightSeaGround, "heightLand": heightLand, "meanderShort": 30, "meanderLong": 0, "waterFunc": (position, height, riverFraction) => { let origPos = position.clone().rotateAround(-startAngle, mapCenter); // Distinguish left and right shoreline if (0 < height && height < 1 && origPos.y > ShorelineDistance && origPos.y < mapSize - ShorelineDistance) clShore[origPos.x < mapCenter.x ? 0 : 1].add(position); }, "landFunc": (position, shoreDist1, shoreDist2) => { if (shoreDist1 > 0) clLand[0].add(position); if (shoreDist2 < 0) clLand[1].add(position); } }); Engine.SetProgress(30); paintTileClassBasedOnHeight(-Infinity, 0.7, Elevation_ExcludeMin_ExcludeMax, clWater); var areasLand = [0, 1].map(i => createArea( new MapBoundsPlacer(), undefined, stayClasses(clLand[i], 0))); var areasWater = [createArea( new MapBoundsPlacer(), undefined, new HeightConstraint(-Infinity, heightLand))]; g_Map.log("Creating shores"); paintTerrainBasedOnHeight(-Infinity, heightShore, 0, tWater); paintTerrainBasedOnHeight(heightShore, heightLand, 0, tShore); Engine.SetProgress(35); createBumps(avoidClasses(clPlayer, 6, clWater, 2, clPath, 1, clGauls, 1), scaleByMapSize(30, 300), 1, 8, 4, 0, 3); Engine.SetProgress(40); if (randBool()) createHills( [tCliff, tCliff, tCliff], avoidClasses(clPlayer, 18, clHill, 20, clWater, 2, clGauls, 5, clPath, 1), clHill, scaleByMapSize(3, 15)); else createMountains( tCliff, avoidClasses(clPlayer, 18, clHill, 20, clWater, 2, clGauls, 5, clPath, 1), clHill, scaleByMapSize(3, 15)); Engine.SetProgress(45); var [forestTrees, stragglerTrees] = getTreeCounts(500, 3000, 0.7); createForests( [tForestFloor, tForestFloor, tForestFloor, pForest1, pForest2], avoidClasses(clPlayer, 16, clForest, 17, clWater, 5, clHill, 2, clGauls, 5, clPath, 1), clForest, forestTrees); Engine.SetProgress(50); g_Map.log("Creating grass patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [[tGrass, tGrass2], [tGrass2, tGrass3], [tGrass3, tGrass]], [1, 1], avoidClasses(clForest, 0, clPlayer, 10, clWater, 2, clDirt, 2, clHill, 1, clGauls, 5, clPath, 1), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(55); g_Map.log("Creating islands"); var areaIslands = createAreas( new ChainPlacer(Math.floor(scaleByMapSize(3, 4)), Math.floor(scaleByMapSize(4, 8)), Math.floor(scaleByMapSize(50, 80)), 0.5), [ new LayeredPainter([tWater, tShore, tIsland], [2, 1]), new SmoothElevationPainter(ELEVATION_SET, heightIsland, 4), new TileClassPainter(clIsland) ], [avoidClasses(clIsland, 30), stayClasses(clWater, 10)], scaleByMapSize(1, 4) * numPlayers); Engine.SetProgress(60); createBumps(stayClasses(clIsland, 2), scaleByMapSize(50, 400), 1, 8, 4, 0, 3); g_Map.log("Painting seabed"); paintTerrainBasedOnHeight(-20, -3, 3, tSeaDepths); g_Map.log("Creating island metal mines"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(oMetalLarge, 1, 1, 0, 4)], true, clMetal), 0, [avoidClasses(clMetal, 50, clRock, 10), stayClasses(clIsland, 5)], scaleByMapSize(3, 10), 20, areaIslands); g_Map.log("Creating island stone mines"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(oStoneLarge, 1, 1, 0, 4)], true, clRock), 0, [avoidClasses(clMetal, 10, clRock, 50), stayClasses(clIsland, 5)], scaleByMapSize(3, 10), 20, areaIslands); Engine.SetProgress(65); g_Map.log("Creating island towers"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(oTower, 1, 1, 0, 4)], true, clTower), 0, [avoidClasses(clMetal, 4, clRock, 4, clTower, 20), stayClasses(clIsland, 7)], scaleByMapSize(3, 10), 20, areaIslands); g_Map.log("Creating island outposts"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(oOutpost, 1, 1, 0, 4)], true, clOutpost), 0, [avoidClasses(clMetal, 4, clRock, 4, clTower, 5, clOutpost, 20), stayClasses(clIsland, 7)], scaleByMapSize(3, 10), 20, areaIslands); g_Map.log("Creating metal mines"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(oMetalLarge, 1, 1, 0, 4)], true, clMetal), 0, avoidClasses(clForest, 4, clBaseResource, 20, clMetal, 50, clRock, 20, clWater, 4, clHill, 4, clGauls, 5, clPath, 5), scaleByMapSize(4, 20), 50, areasLand); g_Map.log("Creating stone mines"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(oStoneLarge, 1, 1, 0, 4)], true, clRock), 0, avoidClasses(clForest, 4, clBaseResource, 20, clMetal, 20, clRock, 50, clWater, 4, clHill, 4, clGauls, 5, clPath, 5), scaleByMapSize(4, 20), 50, areasLand); g_Map.log("Creating stone ruins"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(oStoneRuins, 1, 1, 0, 4)], true, clRock), 0, avoidClasses(clForest, 2, clPlayer, 12, clMetal, 6, clRock, 25, clWater, 4, clHill, 4, clGauls, 5, clPath, 1), scaleByMapSize(2, 10), 20, areasLand); Engine.SetProgress(70); g_Map.log("Creating decoratives"); for (let i = 0; i < 2; ++i) createDecoration( [ [new SimpleObject(aRock1, 1, 1, 0, 1)], [new SimpleObject(aRock2, 1, 1, 0, 1)], [new SimpleObject(aRock3, 1, 1, 0, 1)], [new SimpleObject(aRock4, 1, 1, 0, 1)], [new SimpleObject(aBush1, 1, 3, 0, 2)], [new SimpleObject(aBush2, 1, 2, 0, 1)], [new SimpleObject(aBush3, 1, 3, 0, 2)], [new SimpleObject(aBush4, 1, 2, 0, 1)], [new SimpleObject(aFerns, 2, 5, 2, 4)] ], [ scaleByMapAreaAbsolute(5), scaleByMapAreaAbsolute(5), scaleByMapAreaAbsolute(5), scaleByMapAreaAbsolute(5), scaleByMapAreaAbsolute(5), scaleByMapAreaAbsolute(5), scaleByMapAreaAbsolute(5), scaleByMapAreaAbsolute(5), scaleByMapSize(20, 80) ], i == 0 ? avoidClasses(clWater, 4, clForest, 1, clPlayer, 16, clRock, 4, clMetal, 4, clHill, 4, clGauls, 5, clPath, 1) : [stayClasses(clIsland, 4), avoidClasses(clForest, 1, clRock, 4, clMetal, 4)]); Engine.SetProgress(75); g_Map.log("Creating fish"); createFood( [ [new SimpleObject(oFish, 2, 3, 0, 2)] ], [ 20 * scaleByMapSize(5, 20) ], [avoidClasses(clIsland, 2, clFood, 10, clPath, 1), stayClasses(clWater, 5)], clFood); Engine.SetProgress(80); g_Map.log("Creating huntable animals"); createFood( [ [new SimpleObject(oSheep, 5, 5, 0, 4)], [new SimpleObject(oGoat, 5, 5, 0, 4)], [new SimpleObject(oRabbit, 5, 8, 0, 4)], [new SimpleObject(oDeer, 4, 6, 0, 2)], [new SimpleObject(oHawk, 1, 1, 0, 4)] ], [ scaleByMapSize(5, 20), scaleByMapSize(5, 20), scaleByMapSize(5, 20), scaleByMapSize(5, 20), scaleByMapSize(5, 10) ], avoidClasses(clIsland, 2, clFood, 10, clWater, 5, clPlayer, 16, clHill, 2, clGauls, 5, clPath, 1), clFood); g_Map.log("Creating violent animals"); if (!isNomad()) createFood( [ [new SimpleObject(oWolf, 1, 3, 0, 4)], [new SimpleObject(oBoar, 1, 1, 0, 4)], [new SimpleObject(oBear, 1, 1, 0, 4)] ], [ scaleByMapSize(5, 20), scaleByMapSize(5, 20), scaleByMapSize(5, 20) ], avoidClasses(clIsland, 2, clFood, 10, clWater, 5, clPlayer, 24, clHill, 2, clGauls, 5, clPath, 1), clFood); Engine.SetProgress(85); g_Map.log("Creating fruits"); createFood( [ [new SimpleObject(oApple, 3, 5, 4, 7)], [new SimpleObject(oBerryBush, 4, 6, 0, 4)] ], [ scaleByMapSize(5, 20), scaleByMapSize(5, 20) ], avoidClasses(clWater, 5, clForest, 2, clPlayer, 16, clHill, 4, clFood, 10, clMetal, 4, clRock, 4, clGauls, 5, clPath, 1), clFood); Engine.SetProgress(90); createStragglerTrees( treeTypes, avoidClasses(clForest, 2, clWater, 8, clPlayer, 16, clMetal, 4, clRock, 4, clFood, 1, clHill, 2, clGauls, 5, clPath, 5), clForest, stragglerTrees); createStragglerTrees( treeTypes, [stayClasses(clIsland, 4), avoidClasses(clMetal, 4, clRock, 4, clTower, 4, clOutpost, 4)], clForest, stragglerTrees * 7); Engine.SetProgress(95); g_Map.log("Creating animals on islands"); createFood( [ [new SimpleObject(oSheep, 4, 6, 0, 4)], [new SimpleObject(oGoat, 4, 6, 0, 4)], [new SimpleObject(oRabbit, 5, 8, 0, 4)] ], [ 10 * scaleByMapSize(5, 20), 10 * scaleByMapSize(5, 20), 10 * scaleByMapSize(5, 20) ], [avoidClasses(clRock, 4, clMetal, 4, clFood, 3, clForest, 1, clOutpost, 2, clTower, 2), stayClasses(clIsland, 4)], clFood); Engine.SetProgress(98); g_Map.log("Creating treasures"); createObjectGroupsByAreas( new SimpleGroup( [new SimpleObject(pickRandom(oTreasures), 1, 1, 0, 2)], true, clTreasure ), 0, avoidClasses(clForest, 1, clPlayer, 15, clHill, 1, clWater, 5, clFood, 1, clRock, 4, clMetal, 4, clTreasure, 10, clGauls, 5), randomTreasureCount, 50, areasLand); g_Map.log("Creating gallic decoratives"); createDecoration( [ [new SimpleObject(aBucket, 1, 1, 0, 1)], [new SimpleObject(aBarrel, 1, 1, 0, 1)], [new SimpleObject(aTartan, 3, 3, 4, 4, Math.PI/4, Math.PI/2)], [new SimpleObject(aWheel, 2, 4, 1, 2)], [new SimpleObject(aWell, 1, 1, 0, 2)], [new SimpleObject(aWoodcord, 1, 2, 2, 2, Math.PI/2, Math.PI/2)] ], [ scaleByMapSize(2, 10), scaleByMapSize(2, 10), scaleByMapSize(2, 10), scaleByMapSize(2, 10), scaleByMapSize(3, 4), scaleByMapSize(2, 10) ], avoidClasses(clForest, 1, clPlayer, 10, clBaseResource, 5, clHill, 1, clFood, 1, clWater, 5, clRock, 4, clMetal, 4, clGauls, 5, clPath, 1)); g_Map.log("Creating spawn points for ships"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(triggerPointShipSpawn, 1, 1, 0, 0)], true, clShip), 0, [avoidClasses(clShip, 5, clIsland, 4), stayClasses(clWater, 10)], scaleByMapSize(10, 75), 10, areasWater); g_Map.log("Creating patrol points for ships"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(triggerPointShipPatrol, 1, 1, 0, 0)], true, clShipPatrol), 0, [avoidClasses(clShipPatrol, 5, clIsland, 3), stayClasses(clWater, 4)], scaleByMapSize(20, 150), 10, areasWater); g_Map.log("Creating ungarrison points for ships"); for (let i = 0; i < 2; ++i) { let areaShore = [createArea( new MapBoundsPlacer(), undefined, stayClasses(clShore[i], 0))]; createObjectGroupsByAreas( new SimpleGroup( [new SimpleObject( i == 0 ? triggerPointShipUnloadLeft : triggerPointShipUnloadRight, 1, 1, 0, 0)], true, clShoreUngarrisonPoint[i]), 0, avoidClasses(clShoreUngarrisonPoint[i], 4), scaleByMapSize(60, 200), 20, areaShore); } g_Map.log("Creating riverdirection triggerpoint"); g_Map.placeEntityAnywhere(triggerPointRiverDirection, 0, Vector2D.add(mapCenter, new Vector2D(0, 1).rotate(startAngle)), randomAngle()); g_Map.log("Creating patrol points for siege engines"); for (let i = 0; i < 2; ++i) // Patrol points for siege engines createObjectGroupsByAreas( new SimpleGroup( [new SimpleObject( i == 0 ? triggerPointLandPatrolLeft : triggerPointLandPatrolRight, 1, 1, 0, 0)], true, clPatrolPointSiegeEngine[i]), 0, avoidClasses(clWater, 5, clForest, 3, clHill, 3, clFood, 1, clRock, 5, clMetal, 5, clPlayer, 10, clGauls, 5, clPatrolPointSiegeEngine[i], 5), scaleByMapSize(20, 150), 10, [areasLand[i]]); if (gallicCC) { g_Map.log("Creating patrol points for soldiers"); for (let i = 0; i < 2; ++i) createObjectGroupsByAreas( new SimpleGroup( [new SimpleObject( i == 0 ? triggerPointCCAttackerPatrolLeft : triggerPointCCAttackerPatrolRight, 1, 1, 0, 0)], true, clPatrolPointSoldier[i]), 0, // Don't avoid the forest, so that as many places as possible on the border are visited avoidClasses( clWater, 5, clHill, 3, clFood, 1, clRock, 4, clMetal, 4, clPlayer, 15, clGauls, 0, clPatrolPointSoldier[i], 5), scaleByMapSize(20, 150), 20, [areasLand[i]]); } g_Map.log("Creating water logs"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(aWaterLog, 1, 1, 0, 0, startAngle, startAngle)], true, clWaterLog), 0, [avoidClasses(clShip, 3, clIsland, 4), stayClasses(clWater, 4)], scaleByMapSize(1, 4), 10, areasWater); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clMetal, 4, clRock, 4, clIsland, 4, clGauls, 20, clRitualPlace, 20, clForest, 1, clBaseResource, 4, clHill, 4, clFood, 2)); if (day) { g_Map.log("Setting day theme"); setSkySet("cumulus"); setSunColor(0.9, 0.8, 0.5); setFogFactor(0.05); setFogThickness(0.25); setWaterColor(0.317, 0.396, 0.294); setWaterTint(0.439, 0.403, 0.262); setPPContrast(0.62); setPPSaturation(0.51); setPPBloom(0.12); } else { g_Map.log("Setting night theme"); setSkySet("dark"); setSunColor(0.4, 0.9, 1.2); setSunElevation(0.13499); setSunRotation(-2.5); setAmbientColor(0.25, 0.3, 0.45); setFogFactor(0.004); setFogThickness(0.25); setFogColor(0.35, 0.45, 0.5); setWaterColor(0.074, 0.101, 0.090); setWaterTint(0.129, 0.160, 0.137); } setPPEffect("hdr"); setWaterWaviness(2.0); setWaterType("lake"); setWaterMurkiness(0.97); setWaterHeight(21); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/deep_forest.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/deep_forest.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/deep_forest.js (revision 26381) @@ -1,201 +1,201 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); var templateStone = "gaia/rock/temperate_small"; var templateStoneMine = "gaia/rock/temperate_large"; var templateMetalMine = "gaia/ore/temperate_large"; var templateTemple = "gaia/ruins/unfinished_greek_temple"; var terrainPrimary = ["temp_grass", "temp_grass_b", "temp_grass_c", "temp_grass_d", "temp_grass_long_b", "temp_grass_clovers_2", "temp_grass_mossy", "temp_grass_plants"]; var terrainWood = ['temp_grass_mossy|gaia/tree/oak', 'temp_forestfloor_pine|gaia/tree/pine', 'temp_mud_plants|gaia/tree/dead', 'temp_plants_bog|gaia/tree/oak_large', "temp_dirt_gravel_plants|gaia/tree/aleppo_pine", 'temp_forestfloor_autumn|gaia/tree/carob']; var terrainWoodBorder = ['temp_grass_plants|gaia/tree/euro_beech', 'temp_grass_mossy|gaia/tree/poplar', 'temp_grass_mossy|gaia/tree/poplar_lombardy', 'temp_grass_long|gaia/tree/bush_temperate', 'temp_mud_plants|gaia/tree/bush_temperate', 'temp_mud_plants|gaia/tree/bush_badlands', 'temp_grass_long|gaia/fruit/apple', 'temp_grass_clovers|gaia/fruit/berry_01', 'temp_grass_clovers_2|gaia/fruit/grapes', 'temp_grass_plants|gaia/fauna_deer', "temp_grass_long_b|gaia/fauna_rabbit", "temp_grass_plants"]; var terrainBase = ["temp_dirt_gravel", "temp_grass_b"]; var terrainBaseBorder = ["temp_grass_b", "temp_grass_b", "temp_grass", "temp_grass_c", "temp_grass_mossy"]; var terrainBaseCenter = ['temp_dirt_gravel', 'temp_dirt_gravel', 'temp_grass_b']; var terrainPath = ['temp_road', "temp_road_overgrown", 'temp_grass_b']; var terrainHill = ["temp_highlands", "temp_highlands", "temp_highlands", "temp_dirt_gravel_b", "temp_cliff_a"]; var terrainHillBorder = ["temp_highlands", "temp_highlands", "temp_highlands", "temp_dirt_gravel_b", "temp_dirt_gravel_plants", "temp_highlands", "temp_highlands", "temp_highlands", "temp_dirt_gravel_b", "temp_dirt_gravel_plants", "temp_highlands", "temp_highlands", "temp_highlands", "temp_cliff_b", "temp_dirt_gravel_plants", "temp_highlands", "temp_highlands", "temp_highlands", "temp_cliff_b", "temp_dirt_gravel_plants", "temp_highlands|gaia/fauna_goat"]; var heightPath = -2; var heightLand = 0; var heightOffsetRandomPath = 1; var g_Map = new RandomMap(heightLand, terrainPrimary); var mapSize = g_Map.getSize(); var mapRadius = mapSize/2; var mapCenter = g_Map.getCenter(); var clPlayer = g_Map.createTileClass(); var clPath = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var numPlayers = getNumPlayers(); var baseRadius = 20; var minPlayerRadius = Math.min(mapRadius - 1.5 * baseRadius, 5/8 * mapRadius); var maxPlayerRadius = Math.min(mapRadius - baseRadius, 3/4 * mapRadius); var playerPosition = []; var playerAngle = []; var playerAngleStart = randomAngle(); var playerAngleAddAvrg = 2 * Math.PI / numPlayers; var playerAngleMaxOff = playerAngleAddAvrg/4; var radiusEC = Math.max(mapRadius/8, baseRadius/2); var resourceRadius = fractionToTiles(1/3); var resourcePerPlayer = [templateStone, templateMetalMine]; // For large maps there are memory errors with too many trees. A density of 256x192/mapArea works with 0 players. // Around each player there is an area without trees so with more players the max density can increase a bit. var maxTreeDensity = Math.min(256 * (192 + 8 * numPlayers) / Math.square(mapSize), 1); // Has to be tweeked but works ok var bushChance = 1/3; // 1 means 50% chance in deepest wood, 0.5 means 25% chance in deepest wood var playerIDs = sortAllPlayers(); for (var i=0; i < numPlayers; i++) { playerAngle[i] = (playerAngleStart + i * playerAngleAddAvrg + randFloat(0, playerAngleMaxOff)) % (2 * Math.PI); playerPosition[i] = Vector2D.add(mapCenter, new Vector2D(randFloat(minPlayerRadius, maxPlayerRadius), 0).rotate(-playerAngle[i]).round()); } Engine.SetProgress(10); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "BaseResourceClass": clBaseResource, // player class painted below "CityPatch": { "radius": 0.8 * baseRadius, "smoothness": 1/8, "painters": [ new LayeredPainter([terrainBaseBorder, terrainBase, terrainBaseCenter], [baseRadius/4, baseRadius/4]), new TileClassPainter(clPlayer) ] }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": "gaia/fruit/grapes", "minCount": 2, "maxCount": 2, "distance": 12, "minDist": 5, "maxDist": 8 }, "Mines": { "types": [ { "template": templateMetalMine }, { "template": templateStoneMine } ], "minAngle": Math.PI / 2, "maxAngle": Math.PI }, "Trees": { "template": "gaia/tree/oak_large", "count": 2 } }); Engine.SetProgress(30); g_Map.log("Painting paths"); var pathBlending = numPlayers <= 4; for (let i = 0; i < numPlayers + (pathBlending ? 1 : 0); ++i) for (let j = pathBlending ? 0 : i + 1; j < numPlayers + 1; ++j) { let pathStart = i < numPlayers ? playerPosition[i] : mapCenter; let pathEnd = j < numPlayers ? playerPosition[j] : mapCenter; createArea( new RandomPathPlacer(pathStart, pathEnd, 1.25, baseRadius / 2, pathBlending), [ new TerrainPainter(terrainPath), new SmoothElevationPainter(ELEVATION_SET, heightPath, 2, heightOffsetRandomPath), new TileClassPainter(clPath) ], avoidClasses(clBaseResource, 4)); } Engine.SetProgress(50); g_Map.log("Placing expansion resources"); for (let i = 0; i < numPlayers; ++i) for (let rIndex = 0; rIndex < resourcePerPlayer.length; ++rIndex) { let angleDist = numPlayers > 1 ? (playerAngle[(i + 1) % numPlayers] - playerAngle[i] + 2 * Math.PI) % (2 * Math.PI) : 2 * Math.PI; // they are supposed to be in between players on the same radius let angle = playerAngle[i] + angleDist * (rIndex + 1) / (resourcePerPlayer.length + 1); let position = Vector2D.add(mapCenter, new Vector2D(resourceRadius, 0).rotate(-angle)).round(); g_Map.placeEntityPassable(resourcePerPlayer[rIndex], 0, position, randomAngle()); createArea( new ClumpPlacer(40, 1/2, 1/8, Infinity, position), [ new LayeredPainter([terrainHillBorder, terrainHill], [1]), new ElevationPainter(randFloat(1, 2)), new TileClassPainter(clHill) ]); } Engine.SetProgress(60); g_Map.log("Placing temple"); g_Map.placeEntityPassable(templateTemple, 0, mapCenter, randomAngle()); clBaseResource.add(mapCenter); g_Map.log("Creating central mountain"); createArea( new ClumpPlacer(Math.square(radiusEC), 1/2, 1/8, Infinity, mapCenter), [ new LayeredPainter([terrainHillBorder, terrainHill], [radiusEC/4]), new ElevationPainter(randFloat(1, 2)), new TileClassPainter(clHill) ]); // Woods and general height map for (var x = 0; x < mapSize; x++) for (var z = 0; z < mapSize; z++) { let position = new Vector2D(x, z); // The 0.5 is a correction for the entities placed on the center of tiles var radius = mapCenter.distanceTo(Vector2D.add(position, new Vector2D(0.5, 0.5))); var minDistToSL = mapSize; for (var i=0; i < numPlayers; i++) minDistToSL = Math.min(minDistToSL, position.distanceTo(playerPosition[i])); // Woods tile based var tDensFactSL = Math.max(Math.min((minDistToSL - baseRadius) / baseRadius, 1), 0); var tDensFactRad = Math.abs((resourceRadius - radius) / resourceRadius); var tDensFactEC = Math.max(Math.min((radius - radiusEC) / radiusEC, 1), 0); var tDensActual = maxTreeDensity * tDensFactSL * tDensFactRad * tDensFactEC; if (randBool(tDensActual) && g_Map.validTile(position)) { let border = tDensActual < randFloat(0, bushChance * maxTreeDensity); if (avoidClasses(clPath, 1, clHill, border ? 0 : 1).allows(position)) { createTerrain(border ? terrainWoodBorder : terrainWood).place(position); g_Map.setHeight(position, randFloat(0, 1)); clForest.add(position); } } // General height map let hVarMiddleHill = fractionToTiles(1 / 64) * (1 + Math.cos(3/2 * Math.PI * radius / mapRadius)); var hVarHills = 5 * (1 + Math.sin(x / 10) * Math.sin(z / 10)); g_Map.setHeight(position, g_Map.getHeight(position) + hVarMiddleHill + hVarHills + 1); } Engine.SetProgress(95); placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clBaseResource, 4, clHill, 4)); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/dodecanese.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/dodecanese.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/dodecanese.js (revision 26381) @@ -1,430 +1,430 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); TILE_CENTERED_HEIGHT_MAP = true; const tCity = "medit_city_pavement"; const tCityPlaza = "medit_city_pavement"; const tHill = ["medit_grass_shrubs", "medit_rocks_grass_shrubs", "medit_rocks_shrubs", "medit_rocks_grass", "medit_shrubs"]; const tMainDirt = "medit_dirt"; const tCliff = "medit_cliff_aegean"; const tForestFloor = "medit_grass_wild"; const tPrimary = ["medit_grass_shrubs", "medit_grass_wild", "medit_rocks_grass_shrubs", "medit_dirt_b", "medit_plants_dirt", "medit_grass_flowers"]; const tDirt = "medit_dirt_b"; const tDirt2 = "medit_rocks_grass"; const tDirt3 = "medit_rocks_shrubs"; const tDirtCracks = "medit_dirt_c"; const tShoreLower = "medit_sand_wet"; const tShoreUpper = "medit_sand"; const tCoralsLower = "medit_sea_coral_deep"; const tCoralsUpper = "medit_sea_coral_plants"; const tWater = "medit_sea_depths"; const tLavaOuter = "LavaTest06"; const tLavaInner = "LavaTest05"; const oBerryBush = "gaia/fruit/berry_01"; const oDeer = "gaia/fauna_deer"; const oFish = "gaia/fish/generic"; const oSheep = "gaia/fauna_sheep"; const oGoat = "gaia/fauna_goat"; const oRabbit = "gaia/fauna_rabbit"; const oStoneLarge = "gaia/rock/mediterranean_large"; const oStoneSmall = "gaia/rock/mediterranean_small"; const oMetalLarge = "gaia/ore/mediterranean_large"; const oMetalSmall = "gaia/ore/mediterranean_small"; const oDatePalm = "gaia/tree/cretan_date_palm_short"; const oSDatePalm = "gaia/tree/cretan_date_palm_tall"; const oCarob = "gaia/tree/carob"; const oFanPalm = "gaia/tree/medit_fan_palm"; const oPoplar = "gaia/tree/poplar_lombardy"; const oCypress = "gaia/tree/cypress"; const oBush = "gaia/tree/bush_temperate"; const aBush1 = actorTemplate("props/flora/bush_medit_sm"); const aBush2 = actorTemplate("props/flora/bush_medit_me"); const aBush3 = actorTemplate("props/flora/bush_medit_la"); const aBush4 = actorTemplate("props/flora/bush_medit_me"); const aDecorativeRock = actorTemplate("geology/stone_granite_med"); const aBridge = actorTemplate("props/special/eyecandy/bridge_edge_wooden"); const aSmokeBig = actorTemplate("particle/smoke_volcano"); const aSmokeSmall = actorTemplate("particle/smoke_curved"); const pForest1 = [ tForestFloor, tForestFloor + TERRAIN_SEPARATOR + oCarob, tForestFloor + TERRAIN_SEPARATOR + oDatePalm, tForestFloor + TERRAIN_SEPARATOR + oSDatePalm, tForestFloor]; const pForest2 = [ tForestFloor, tForestFloor + TERRAIN_SEPARATOR + oFanPalm, tForestFloor + TERRAIN_SEPARATOR + oPoplar, tForestFloor + TERRAIN_SEPARATOR + oCypress]; const heightSeaGround = -8; const heightCoralsLower = -6; const heightCoralsUpper = -4; const heightSeaBump = -2.5; const heightShoreLower = -2; const heightBridge = -0.5; const heightShoreUpper = 1; const heightLand = 3; const heightOffsetBump = 2; const heightHill = 8; const heightVolano = 25; var g_Map = new RandomMap(heightSeaGround, tWater); var numPlayers = getNumPlayers(); var clIsland = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clPlayer = g_Map.createTileClass(); var clPlayerIsland = g_Map.createTileClass(); var clShore = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clGrass = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clVolcano = g_Map.createTileClass(); var clBridge = g_Map.createTileClass(); const playerIslandRadius = scaleByMapSize(20, 29); const bridgeLength = 16; const maxBridges = scaleByMapSize(2, 12); var [playerIDs, playerPosition] = playerPlacementRandom(sortAllPlayers()); g_Map.log("Creating player islands"); for (let position of playerPosition) createArea( new ChainPlacer(2, 6, scaleByMapSize(15, 50), Infinity, position, 0, [playerIslandRadius]), [ new TerrainPainter(tPrimary), new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), new TileClassPainter(clIsland) ].concat(isNomad() ? [] : [new TileClassPainter(clPlayerIsland)])); Engine.SetProgress(10); g_Map.log("Creating islands"); createAreas( new ChainPlacer(6, Math.floor(scaleByMapSize(8, 10)), Math.floor(scaleByMapSize(10, 35)), 0.2), [ new TerrainPainter(tPrimary), new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), new TileClassPainter(clIsland) ], avoidClasses(clIsland, 6), scaleByMapSize(25, 80)); Engine.SetProgress(20); // Notice that the Constraints become much shorter when avoiding water rather than staying on islands g_Map.log("Marking water"); createArea( new MapBoundsPlacer(), new TileClassPainter(clWater), new HeightConstraint(-Infinity, heightShoreLower)); Engine.SetProgress(30); g_Map.log("Creating undersea bumps"); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(16, 40)), 0.5), new SmoothElevationPainter(ELEVATION_SET, heightSeaBump, 3), avoidClasses(clIsland, 2), scaleByMapSize(10, 50)); Engine.SetProgress(35); g_Map.log("Creating volcano"); var areasVolcano = createAreas( new ClumpPlacer(diskArea(scaleByMapSize(4, 8)), 0.5, 0.5, 0.1), [ new LayeredPainter([tLavaOuter, tLavaInner], [4]), new SmoothElevationPainter(ELEVATION_SET, heightVolano, 6), new TileClassPainter(clVolcano) ], [ new NearTileClassConstraint(clIsland, 8), avoidClasses(clHill, 5, clPlayerIsland, 0), ], 1, 200); createBumps(avoidClasses(clWater, 0, clPlayer, 10, clVolcano, 0)); Engine.SetProgress(40); g_Map.log("Creating large bumps"); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 3), avoidClasses(clWater, 2, clVolcano, 0, clPlayer, 10), scaleByMapSize(20, 200)); Engine.SetProgress(45); g_Map.log("Creating hills"); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(16, 40)), 0.5), [ new LayeredPainter([tCliff, tHill], [2]), new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), new TileClassPainter(clHill) ], avoidClasses(clWater, 1, clPlayer, 12, clVolcano, 0, clHill, 15), scaleByMapSize(4, 13)); Engine.SetProgress(50); g_Map.log("Painting corals"); paintTerrainBasedOnHeight(-Infinity, heightCoralsLower, Elevation_IncludeMin_ExcludeMax, tWater); paintTerrainBasedOnHeight(heightCoralsLower, heightCoralsUpper, Elevation_IncludeMin_ExcludeMax, tCoralsLower); paintTerrainBasedOnHeight(heightCoralsUpper, heightShoreLower, Elevation_IncludeMin_ExcludeMax, tCoralsUpper); g_Map.log("Painting shoreline"); var areaShoreline = createArea( new HeightPlacer(Elevation_IncludeMin_ExcludeMax, heightShoreLower, heightShoreUpper), [ new TerrainPainter(tShoreLower), new TileClassPainter(clShore) ], avoidClasses(clVolcano, 0)); createArea( new HeightPlacer(Elevation_IncludeMin_ExcludeMax, heightShoreUpper, heightLand), new TerrainPainter(tShoreUpper), avoidClasses(clVolcano, 0)); Engine.SetProgress(60); g_Map.log("Creating dirt patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [tDirt3, tDirt2, [tDirt, tMainDirt], [tDirtCracks, tMainDirt]], [1, 1, 1], avoidClasses(clWater, 4, clVolcano, 2, clForest, 1, clDirt, 2, clGrass, 2, clHill, 1), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(65); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "BaseResourceClass": clBaseResource, "PlayerTileClass": clPlayer, "Walls": "towers", "CityPatch": { "radius": playerIslandRadius / 4, "outerTerrain": tCityPlaza, "innerTerrain": tCity }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, // sufficient trees around "Decoratives": { "template": aBush1 } }); Engine.SetProgress(70); g_Map.log("Creating stone mines"); createMines( [ [new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], [new SimpleObject(oStoneSmall, 2, 5, 1, 3)] ], avoidClasses(clWater, 4, clVolcano, 4, clPlayerIsland, 0, clBaseResource, 4, clForest, 3, clMetal, 4, clRock, 4), clRock, scaleByMapSize(4, 16)); Engine.SetProgress(75); g_Map.log("Creating metal mines"); createMines( [ [new SimpleObject(oMetalSmall, 0, 1, 0, 4), new SimpleObject(oMetalLarge, 1, 1, 0, 4)], [new SimpleObject(oMetalSmall, 2, 5, 1, 3)] ], avoidClasses(clWater, 4, clPlayerIsland, 0, clVolcano, 4, clBaseResource, 4, clForest, 3, clMetal, 4, clRock, 4), clMetal, scaleByMapSize(4, 16)); Engine.SetProgress(80); placePlayersNomad(clPlayer, avoidClasses(clWater, 12, clVolcano, 4, clMetal, 4, clRock, 4, clHill, 4)); var [forestTrees, stragglerTrees] = getTreeCounts(800, 4000, 0.7); createForests( [tForestFloor, tForestFloor, tForestFloor, pForest1, pForest2], avoidClasses(clWater, 2, clPlayer, 4, clVolcano, 2, clForest, 1, clBaseResource, 4, clMetal, 4, clRock, 4), clForest, forestTrees, 200); Engine.SetProgress(85); createFood( [ [new SimpleObject(oSheep, 5, 7, 0, 4)], [new SimpleObject(oGoat, 2, 4, 0, 3)], [new SimpleObject(oDeer, 2, 4, 0, 2)], [new SimpleObject(oRabbit, 3, 9, 0, 4)], [new SimpleObject(oBerryBush, 3, 5, 0, 4)] ], [ scaleByMapSize(5, 20), scaleByMapSize(5, 20), scaleByMapSize(5, 20), scaleByMapSize(5, 20), 3 * numPlayers ], avoidClasses(clWater, 1, clPlayer, 15, clVolcano, 4, clBaseResource, 4, clHill, 2, clMetal, 4, clRock, 4), clFood); Engine.SetProgress(87); createFood( [ [new SimpleObject(oFish, 2, 3, 0, 2)] ], [ 3 * numPlayers ], avoidClasses(clIsland, 8, clFood, 10, clVolcano, 4), clFood); createStragglerTrees( [oPoplar, oCypress, oFanPalm, oDatePalm, oSDatePalm], avoidClasses(clWater, 1, clVolcano, 4, clPlayer, 12, clForest, 1, clMetal, 4, clRock, 4), clForest, stragglerTrees, 200); g_Map.log("Creating bushes"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oBush, 3, 5, 0, 4)], true), 0, [avoidClasses(clWater, 1, clVolcano, 4, clPlayer, 5, clForest, 1, clBaseResource, 4, clMetal, 4, clRock, 4)], scaleByMapSize(20, 50)); createDecoration( [ [ new SimpleObject(aDecorativeRock, 1, 3, 0, 1) ], [ new SimpleObject(aBush2, 1, 2, 0, 1), new SimpleObject(aBush1, 1, 3, 0, 2), new SimpleObject(aBush4, 1, 2, 0, 1), new SimpleObject(aBush3, 1, 3, 0, 2) ] ], [ scaleByMapAreaAbsolute(16), scaleByMapSize(40, 360) ], avoidClasses(clWater, 4, clPlayer, 5, clVolcano, 4, clForest, 1, clBaseResource, 4, clRock, 4, clMetal, 4, clHill, 1)); g_Map.log("Creating bridges"); var bridges = 0; for (let bridgeStart of shuffleArray(areaShoreline.getPoints())) { if (new NearTileClassConstraint(clBridge, bridgeLength * 8).allows(bridgeStart)) continue; for (let direction = 0; direction < 4; ++direction) { let bridgeAngle = direction * Math.PI / 2; let bridgeDirection = new Vector2D(1, 0).rotate(bridgeAngle); let areaOffset = new Vector2D(1, 1); let bridgeOffset = new Vector2D(direction % 2 ? 2 : 0, direction % 2 ? 0 : 2); let bridgeCenter1 = Vector2D.add(bridgeStart, Vector2D.mult(bridgeDirection, bridgeLength / 2)); let bridgeCenter2 = Vector2D.add(bridgeCenter1, bridgeOffset); if (avoidClasses(clWater, 0).allows(bridgeCenter1) && avoidClasses(clWater, 0).allows(bridgeCenter2)) continue; let bridgeEnd1 = Vector2D.add(bridgeStart, Vector2D.mult(bridgeDirection, bridgeLength)); let bridgeEnd2 = Vector2D.add(bridgeEnd1, bridgeOffset); if (avoidClasses(clShore, 0).allows(bridgeEnd1) && avoidClasses(clShore, 0).allows(bridgeEnd2)) continue; let bridgePerpendicular = bridgeDirection.perpendicular(); let bridgeP = Vector2D.mult(bridgePerpendicular, bridgeLength / 2).round(); if (avoidClasses(clWater, 0).allows(Vector2D.add(bridgeCenter1, bridgeP)) || avoidClasses(clWater, 0).allows(Vector2D.sub(bridgeCenter2, bridgeP))) continue; ++bridges; // This bridge model is not centered on the horizontal plane, so the angle is messy // TILE_CENTERED_HEIGHT_MAP also influences the outcome of the placement. let bridgeOrientation = direction % 2 ? 0 : Math.PI / 2; bridgeCenter1[direction % 2 ? "y" : "x"] += 0.25; bridgeCenter2[direction % 2 ? "y" : "x"] -= 0.25; g_Map.placeEntityAnywhere(aBridge, 0, bridgeCenter1, bridgeOrientation); g_Map.placeEntityAnywhere(aBridge, 0, bridgeCenter2, bridgeOrientation + Math.PI); createArea( new RectPlacer(Vector2D.sub(bridgeStart, areaOffset), Vector2D.add(bridgeEnd1, areaOffset)), [ new ElevationPainter(heightBridge), new TileClassPainter(clBridge) ]); for (let center of [bridgeStart, bridgeEnd2]) createArea( new DiskPlacer(2, center), new SmoothingPainter(1, 1, 1)); break; } if (bridges >= maxBridges) break; } g_Map.log("Creating smoke"); if (areasVolcano.length) { createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(aSmokeBig, 1, 1, 0, 4)], false), 0, stayClasses(clVolcano, 6), scaleByMapSize(4, 12), 20, areasVolcano); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(aSmokeSmall, 2, 2, 0, 4)], false), 0, stayClasses(clVolcano, 4), scaleByMapSize(4, 12), 20, areasVolcano); } Engine.SetProgress(90); setSkySet("cumulus"); setSunColor(0.87, 0.78, 0.49); setWaterColor(0, 0.501961, 1); setWaterTint(0.5, 1, 1); setWaterWaviness(4.0); setWaterType("ocean"); setWaterMurkiness(0.49); setFogFactor(0.3); setFogThickness(0.25); setPPEffect("hdr"); setPPContrast(0.62); setPPSaturation(0.51); setPPBloom(0.12); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/elephantine.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/elephantine.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/elephantine.js (revision 26381) @@ -1,602 +1,602 @@ /** * Heightmap image source: * OpenStreetMap, available under Open Database Licence, www.openstreetmap.org/copyright * https://download.geofabrik.de/africa.html * * To reproduce the river image: * You need a gdal version that supports osm, see https://www.gdal.org/drv_osm.html * wget https://download.geofabrik.de/africa/egypt-latest.osm.pbf * lon=32.89; lat=24.09175; width=0.025; * 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") * rm elephantine.geojson; ogr2ogr -f GeoJSON elephantine.geojson -clipdst $lon1 $lat1 $lon2 $lat2 egypt-latest.osm.pbf -sql 'select * from multipolygons where natural="water"' * gdal_rasterize -burn 10 -ts 512 512 elephantine.geojson elephantine.tif * convert elephantine.tif -threshold 50% -negate elephantine.png * * No further changes should be applied to the image to keep it easily interchangeable. */ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); TILE_CENTERED_HEIGHT_MAP = true; const tPrimary = ["savanna_dirt_rocks_a_red", "savanna_dirt_a_red", "savanna_dirt_b_red"]; const tDirt = ["new_savanna_dirt_c", "new_savanna_dirt_d", "savanna_dirt_b_red", "savanna_dirt_plants_cracked"]; const tWater = "desert_sand_wet"; const tRoad = "savanna_tile_a_red"; const tRoadIsland = "savanna_tile_a"; const tRoadWildIsland = "savanna_dirt_rocks_a"; const tGrass = ["savanna_shrubs_a_wetseason", "alpine_grass_b_wild", "medit_shrubs_a", "steppe_grass_green_a"]; const tForestFloorLand = "savanna_forestfloor_b_red"; const tForestFloorIsland = pickRandom(tGrass); const oAcacia = "gaia/tree/acacia"; const oPalms = [ "gaia/tree/cretan_date_palm_tall", "gaia/tree/cretan_date_palm_short", "gaia/tree/palm_tropic", "gaia/tree/date_palm", "gaia/tree/senegal_date_palm", "gaia/tree/medit_fan_palm" ]; const oStoneLarge = "gaia/rock/savanna_large"; const oStoneSmall = "gaia/rock/desert_small"; const oMetalLarge = "gaia/ore/savanna_large"; const oMetalSmall = "gaia/ore/desert_small"; const oTreasure = [ "gaia/treasure/food_barrel", "gaia/treasure/food_bin", "gaia/treasure/wood", "gaia/treasure/metal", "gaia/treasure/stone" ]; const oBerryBush = "gaia/fruit/berry_05"; const oGazelle = "gaia/fauna_gazelle"; const oRhino = "gaia/fauna_rhinoceros_white"; const oWarthog = "gaia/fauna_boar"; const oGiraffe = "gaia/fauna_giraffe"; const oGiraffeInfant = "gaia/fauna_giraffe_infant"; const oElephant = "gaia/fauna_elephant_african_bush"; const oElephantInfant = "gaia/fauna_elephant_african_infant"; const oLion = "gaia/fauna_lion"; const oLioness = "gaia/fauna_lioness"; const oCrocodile = "gaia/fauna_crocodile_nile"; const oFish = "gaia/fish/tilapia"; const oHawk = "birds/buzzard"; // The main temple on elephantine was very similar looking (Greco-Roman-Egyptian): const oWonder = "structures/ptol/wonder"; const oTemples = ["structures/kush/temple_amun", "structures/kush/temple"]; const oPyramid = "structures/kush/pyramid_large"; const oTowers = new Array(2).fill("uncapturable|structures/kush/sentry_tower").concat(["uncapturable|structures/kush/defense_tower"]); const oHeroes = Engine.FindTemplates("units/kush/", true).filter(templateName => templateName.startsWith("units/kush/hero_")); const oUnits = Engine.FindTemplates("units/kush/", false).filter(templateName => templateName.startsWith("units/kush/") && oHeroes.every(heroTemplateName => heroTemplateName != templateName) && Engine.GetTemplate(templateName).Identity.VisibleClasses._string.split(" ").some(type => ["Soldier", "Healer", "Female"].indexOf(type) != -1)); const aRock = actorTemplate("geology/stone_savanna_med"); const aStatues = [ "props/structures/kushites/statue_bird", "props/structures/kushites/statue_lion", "props/structures/kushites/statue_ram" ].map(actorTemplate); const aBushesShoreline = [ ...new Array(4).fill("props/flora/ferns"), "props/flora/bush", "props/flora/bush_medit_la", "props/flora/bush_medit_la_lush", "props/flora/bush_medit_me_lush", "props/flora/bush_medit_sm", "props/flora/bush_medit_sm_lush", "props/flora/bush_tempe_la_lush" ].map(actorTemplate); const aBushesIslands = aBushesShoreline.concat(new Array(3).fill(actorTemplate("props/flora/foliagebush"))); const aBushesDesert = [ "props/flora/bush_dry_a", "props/flora/bush_medit_la_dry", "props/flora/bush_medit_me_dry", "props/flora/bush_medit_sm", "props/flora/bush_medit_sm_dry", "props/flora/bush_tempe_me_dry", "props/flora/grass_soft_dry_large_tall", "props/flora/grass_soft_dry_small_tall" ].map(actorTemplate); const pForestPalmsLand = [ tForestFloorLand, ...oPalms.map(tree => tForestFloorLand + TERRAIN_SEPARATOR + tree), tForestFloorLand]; const pForest2Land = [ tForestFloorLand, tForestFloorLand + TERRAIN_SEPARATOR + oAcacia, tForestFloorLand ]; const pForestPalmsIsland = [ tForestFloorIsland, ...oPalms.map(tree => tForestFloorIsland + TERRAIN_SEPARATOR + tree), tForestFloorIsland]; const pForest2Island = [ tForestFloorIsland, tForestFloorIsland + TERRAIN_SEPARATOR + oAcacia, tForestFloorIsland ]; const heightScale = num => num * g_MapSettings.Size / 320; const heightSeaGround = heightScale(-15); const heightWaterLevel = heightScale(0); const heightShore = heightScale(1); const heightOffsetPath = heightScale(-4); const minHeight = -1; const maxHeight = 2; const g_Map = new RandomMap(0, tPrimary); const mapBounds = g_Map.getBounds(); const mapCenter = g_Map.getCenter(); const clWater = g_Map.createTileClass(); const clIsland = g_Map.createTileClass(); const clCliff = g_Map.createTileClass(); const clPlayer = g_Map.createTileClass(); const clBaseResource = g_Map.createTileClass(); const clForest = g_Map.createTileClass(); const clDirt = g_Map.createTileClass(); const clRock = g_Map.createTileClass(); const clMetal = g_Map.createTileClass(); const clFood = g_Map.createTileClass(); const clTemple = g_Map.createTileClass(); const clTower = g_Map.createTileClass(); const clStatue = g_Map.createTileClass(); const clSoldier = g_Map.createTileClass(); const clTreasure = g_Map.createTileClass(); const clPath = g_Map.createTileClass(); const riverAngle = 0.22 * Math.PI; const riverWidthBorder = fractionToTiles(0.27); const riverWidthCenter = fractionToTiles(0.35); const avoidCollisions = avoidClasses( clPlayer, 15, clWater, 1, clForest, 1, clRock, 4, clMetal, 4, clFood, 6, clPath, 1, clTemple, 11, clCliff, 0, clStatue, 2, clSoldier, 3, clTower, 2, clTreasure, 1); g_Map.LoadHeightmapImage("elephantine.png", minHeight, maxHeight); Engine.SetProgress(3); g_Map.log("Lowering sea ground"); createArea( new MapBoundsPlacer(), [ new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4), new TileClassPainter(clWater) ], new HeightConstraint(-Infinity, heightWaterLevel)); Engine.SetProgress(6); g_Map.log("Smoothing heightmap"); createArea( new MapBoundsPlacer(), new SmoothingPainter(1, scaleByMapSize(0.1, 0.5), 1)); Engine.SetProgress(10); g_Map.log("Marking islands"); var areaIsland = createArea( new ConvexPolygonPlacer( [ new Vector2D(mapCenter.x - riverWidthBorder / 2, mapBounds.top), new Vector2D(mapCenter.x - riverWidthBorder / 2, mapBounds.bottom), new Vector2D(mapCenter.x - riverWidthCenter / 2, mapCenter.y), new Vector2D(mapCenter.x + riverWidthCenter / 2, mapCenter.y), new Vector2D(mapCenter.x + riverWidthBorder / 2, mapBounds.top), new Vector2D(mapCenter.x + riverWidthBorder / 2, mapBounds.bottom) ].map(v => v.rotateAround(riverAngle, mapCenter)), Infinity), new TileClassPainter(clIsland), avoidClasses(clPlayer, 0, clWater, 0)); Engine.SetProgress(13); g_Map.log("Painting islands"); createArea( new MapBoundsPlacer(), new TerrainPainter(tGrass), stayClasses(clIsland, 0)); Engine.SetProgress(16); g_Map.log("Painting water and shoreline"); createArea( new MapBoundsPlacer(), new TerrainPainter(tWater), new HeightConstraint(-Infinity, heightShore)); Engine.SetProgress(19); placePlayerBases({ "PlayerPlacement": playerPlacementRiver(riverAngle, fractionToTiles(0.62)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "baseResourceConstraint": avoidClasses(clWater, 4), "Walls": "towers", "CityPatch": { "outerTerrain": tRoad, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oAcacia, "count": 2 }, "Decoratives": { "template": pickRandom(aBushesDesert) } }); Engine.SetProgress(22); g_Map.log("Creating temple"); var groupTemple = createObjectGroupsByAreas( new SimpleGroup([new RandomObject(g_Map.getSize() >= 320 ? [oWonder] : oTemples, 1, 1, 0, 1, riverAngle, riverAngle)], true, clTemple), 0, stayClasses(clIsland, scaleByMapSize(10, 20)), 1, 200, [areaIsland]); Engine.SetProgress(34); g_Map.log("Creating pyramid"); var groupPyramid = createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(oPyramid, 1, 1, 0, 1, riverAngle, riverAngle)], true, clTemple), 0, [stayClasses(clIsland, scaleByMapSize(10, 20)), avoidClasses(clTemple, scaleByMapSize(20, 50)), avoidCollisions], 1, 200, [areaIsland]); Engine.SetProgress(37); g_Map.log("Painting city patches"); var cityCenters = [ groupTemple[0] && groupTemple[0][0] && { "pos": Vector2D.from3D(groupTemple[0][0].position), "radius": 10 }, groupPyramid[0] && groupPyramid[0][0] && { "pos": Vector2D.from3D(groupPyramid[0][0].position), "radius": 6 },].filter(pos => !!pos); var areaCityPatch = cityCenters.map(cityCenter => createArea( new DiskPlacer(cityCenter.radius, cityCenter.pos), new LayeredPainter([tRoadWildIsland, tRoadIsland], [2]), stayClasses(clIsland, 2))); Engine.SetProgress(40); g_Map.log("Painting city path"); if (cityCenters.length == 2) createArea( new PathPlacer(cityCenters[0].pos, cityCenters[1].pos, 4, 0.3, 4, 0.2, 0.05), [ new LayeredPainter([tRoadWildIsland, tRoadIsland], [1]), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetPath, 4), new TileClassPainter(clPath) ]); Engine.SetProgress(42); createBumps(avoidClasses(clPlayer, 10, clWater, 2, clTemple, 10, clPath, 1), scaleByMapSize(10, 500), 1, 8, 4, 0.2, 3); Engine.SetProgress(43); g_Map.log("Marking cliffs"); createArea( new MapBoundsPlacer(), new TileClassPainter(clCliff), [ avoidClasses(clWater, 2), new SlopeConstraint(2, Infinity) ]); Engine.SetProgress(44); g_Map.log("Creating stone mines"); createMines( [ [new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], [new SimpleObject(oStoneSmall, 2, 5, 1, 3, 0, 2 * Math.PI, 1)] ], avoidClasses(clWater, 4, clCliff, 4, clPlayer, 20, clRock, 10, clPath, 1), clRock, scaleByMapSize(6, 24)); Engine.SetProgress(45); g_Map.log("Creating metal mines"); createMines( [ [new SimpleObject(oMetalSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oMetalLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], [new SimpleObject(oMetalSmall, 2, 5, 1, 3, 0, 2 * Math.PI, 1)] ], avoidClasses(clWater, 4, clCliff, 4, clPlayer, 20, clMetal, 10, clRock, 5, clPath, 1), clMetal, scaleByMapSize(6, 24)); Engine.SetProgress(46); g_Map.log("Creating kushite towers"); createObjectGroups( new SimpleGroup([new RandomObject(oTowers, 1, 1, 0, 1)], true, clTower), 0, [ stayClasses(clIsland, scaleByMapSize(4, 8)), new NearTileClassConstraint(clTemple, 25), avoidClasses(clTower, 12, clPlayer, 30), avoidCollisions ], scaleByMapSize(4, 12), 200); Engine.SetProgress(49); var [forestTrees, stragglerTrees] = getTreeCounts(400, 3000, 0.7); createForests( [tForestFloorLand, tForestFloorLand, tForestFloorLand, pForestPalmsLand, pForest2Land], [avoidCollisions, avoidClasses(clIsland, 0, clPlayer, 20, clForest, 18, clWater, 2)], clForest, forestTrees / 2); Engine.SetProgress(52); createForests( [tForestFloorIsland, tForestFloorIsland, tForestFloorIsland, pForestPalmsIsland, pForest2Island], [stayClasses(clIsland, 0), avoidClasses(clForest, 15, clWater, 2), avoidCollisions], clForest, forestTrees / 2); Engine.SetProgress(55); g_Map.log("Creating dirt patches"); createPatches( [scaleByMapSize(5, 15)], tDirt, avoidClasses(clWater, 0, clIsland, 0, clForest, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(5, 30), clDirt); Engine.SetProgress(58); g_Map.log("Creating statues"); createObjectGroupsByAreas( new SimpleGroup([new RandomObject(aStatues, 1, 1, 0, 1)], true, clStatue), 0, [ stayClasses(clIsland, scaleByMapSize(8, 24)), new NearTileClassConstraint(clTemple, 10), avoidCollisions ], scaleByMapSize(2, 10), 400, [areaIsland]); Engine.SetProgress(61); g_Map.log("Creating treasure"); createObjectGroupsByAreas( new SimpleGroup([new RandomObject(oTreasure, 1, 2, 0, 1)], true, clTreasure), 0, avoidCollisions, scaleByMapSize(4, 10), 100, areaCityPatch); Engine.SetProgress(62); g_Map.log("Creating hero"); createObjectGroups( new SimpleGroup([new RandomObject(oHeroes, 1, 1, 0, 1)], true, clSoldier), 0, [ stayClasses(clIsland, scaleByMapSize(2, 24)), new NearTileClassConstraint(clTemple, 14), avoidCollisions ], 1, 500); Engine.SetProgress(64); g_Map.log("Creating soldiers"); createObjectGroups( new SimpleGroup([new RandomObject(oUnits, 1, 1, 0, 1)], true, clSoldier), 0, [ new StaticConstraint( [ stayClasses(clIsland, scaleByMapSize(2, 24)), new NearTileClassConstraint(clTemple, 20) ]), avoidCollisions ], scaleByMapSize(12, 60), 200); Engine.SetProgress(67); g_Map.log("Creating berries"); createObjectGroups( new SimpleGroup([new SimpleObject(oBerryBush, 3, 5, 1, 2)], true, clFood), 0, avoidCollisions, scaleByMapSize(4, 12), 250); Engine.SetProgress(70); g_Map.log("Creating rhinos"); createObjectGroups( new SimpleGroup([new SimpleObject(oRhino, 1, 1, 0, 1)], true, clFood), 0, avoidCollisions, scaleByMapSize(2, 10), 50); Engine.SetProgress(73); g_Map.log("Creating warthog"); createObjectGroups( new SimpleGroup([new SimpleObject(oWarthog, 1, 1, 0, 1)], true, clFood), 0, avoidCollisions, scaleByMapSize(2, 10), 50); Engine.SetProgress(77); g_Map.log("Creating gazelles"); createObjectGroups( new SimpleGroup([new SimpleObject(oGazelle, 5, 7, 2, 4)], true, clFood), 0, [avoidClasses(clIsland, 1), avoidCollisions], scaleByMapSize(2, 10), 50); Engine.SetProgress(80); g_Map.log("Creating giraffes"); createObjectGroups( new SimpleGroup([new SimpleObject(oGiraffe, 2, 3, 2, 4), new SimpleObject(oGiraffeInfant, 2, 3, 2, 4)], true, clFood), 0, avoidCollisions, scaleByMapSize(2, 10), 50); Engine.SetProgress(83); if (!isNomad()) { g_Map.log("Creating lions"); createObjectGroups( new SimpleGroup([new SimpleObject(oLion, 1, 2, 2, 4), new SimpleObject(oLioness, 2, 3, 2, 4)], true, clFood), 0, avoidCollisions, scaleByMapSize(2, 10), 50); Engine.SetProgress(87); } g_Map.log("Creating elephants"); createObjectGroups( new SimpleGroup([new SimpleObject(oElephant, 2, 3, 2, 4), new SimpleObject(oElephantInfant, 2, 3, 2, 4)], true, clFood), 0, avoidCollisions, scaleByMapSize(2, 10), 50); Engine.SetProgress(88); g_Map.log("Creating crocodiles"); createObjectGroups( new SimpleGroup([new SimpleObject(oCrocodile, 2, 3, 3, 5)], true, clFood), 0, [ new NearTileClassConstraint(clWater, 3), avoidCollisions ], scaleByMapSize(2, 10), 50); Engine.SetProgress(89); g_Map.log("Creating hawk"); for (let i = 0; i < scaleByMapSize(0, 2); ++i) g_Map.placeEntityAnywhere(oHawk, 0, mapCenter, randomAngle()); Engine.SetProgress(90); g_Map.log("Creating fish"); createObjectGroups( new SimpleGroup([new SimpleObject(oFish, 1, 2, 0, 1)], true, clFood), 0, [stayClasses(clWater, 8), avoidClasses(clFood, 16)], scaleByMapSize(15, 80), 50); Engine.SetProgress(91); createStragglerTrees( [oAcacia], avoidCollisions, clForest, stragglerTrees); Engine.SetProgress(93); placePlayersNomad(clPlayer, [avoidCollisions, avoidClasses(clIsland, 0)]); Engine.SetProgress(95); createDecoration( aBushesDesert.map(bush => [new SimpleObject(bush, 0, 3, 2, 4)]), aBushesDesert.map(bush => scaleByMapSize(20, 150) * randIntInclusive(1, 3)), [avoidClasses(clIsland, 0), avoidCollisions]); Engine.SetProgress(96); createDecoration( aBushesIslands.map(bush => [new SimpleObject(bush, 0, 4, 2, 4)]), aBushesIslands.map(bush => scaleByMapSize(20, 150) * randIntInclusive(1, 3)), [stayClasses(clIsland, 0), avoidCollisions]); Engine.SetProgress(97); createDecoration( [[new SimpleObject(aRock, 0, 4, 2, 4)]], [[scaleByMapSize(80, 500)]], [avoidClasses(clIsland, 0), avoidCollisions]); Engine.SetProgress(98); createDecoration( aBushesShoreline.map(bush => [new SimpleObject(bush, 0, 3, 2, 4)]), aBushesShoreline.map(bush => scaleByMapSize(200, 1000)), [new HeightConstraint(heightWaterLevel, heightShore), avoidCollisions]); Engine.SetProgress(99); g_Environment = { "SkySet": "cloudless", "SunColor": { "r": 1, "g": 0.964706, "b": 0.909804, "a": 0 }, "SunElevation": 0.908117, "SunRotation": -0.558369, "AmbientColor": { "r": 0.54902, "g": 0.419608, "b": 0.352941, "a": 0 }, "Fog": { "FogFactor": 0.00195313, "FogThickness": 0, "FogColor": { "r": 0.941176, "g": 0.917647, "b": 0.807843, "a": 0 } }, "Water": { "WaterBody": { "Type": "lake", "Color": { "r": 0.443137, "g": 0.341176, "b": 0.14902, "a": 0 }, "Tint": { "r": 0.705882, "g": 0.67451, "b": 0.454902, "a": 0 }, "Waviness": 8.4668, "Murkiness": 0.92, "WindAngle": 0.625864 } }, "Postproc": { "Brightness": 0.0234375, "Contrast": 1.09961, "Saturation": 0.828125, "Bloom": 0.142969, "PostprocEffect": "hdr" } }; g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/english_channel.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/english_channel.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/english_channel.js (revision 26381) @@ -1,267 +1,267 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); const tPrimary = "temp_grass_long"; const tGrass = ["temp_grass", "temp_grass", "temp_grass_d"]; const tGrassDForest = "temp_plants_bog"; const tGrassA = "temp_grass_plants"; const tGrassB = "temp_plants_bog"; const tGrassC = "temp_mud_a"; const tHill = ["temp_highlands", "temp_grass_long_b"]; const tCliff = ["temp_cliff_a", "temp_cliff_b"]; const tRoad = "temp_road"; const tRoadWild = "temp_road_overgrown"; const tGrassPatchBlend = "temp_grass_long_b"; const tGrassPatch = ["temp_grass_d", "temp_grass_clovers"]; const tShore = "temp_dirt_gravel"; const tWater = "temp_dirt_gravel_b"; const oBeech = "gaia/tree/euro_beech"; const oPoplar = "gaia/tree/poplar"; const oApple = "gaia/fruit/apple"; const oOak = "gaia/tree/oak"; const oBerryBush = "gaia/fruit/berry_01"; const oDeer = "gaia/fauna_deer"; const oFish = "gaia/fish/generic"; const oGoat = "gaia/fauna_goat"; const oBoar = "gaia/fauna_boar"; const oStoneLarge = "gaia/rock/temperate_large"; const oStoneSmall = "gaia/rock/temperate_small"; const oMetalLarge = "gaia/ore/temperate_large"; const aGrass = "actor|props/flora/grass_soft_large_tall.xml"; const aGrassShort = "actor|props/flora/grass_soft_large.xml"; const aRockLarge = "actor|geology/stone_granite_large.xml"; const aRockMedium = "actor|geology/stone_granite_med.xml"; const aBushMedium = "actor|props/flora/bush_medit_me_lush.xml"; const aBushSmall = "actor|props/flora/bush_medit_sm_lush.xml"; const aReeds = "actor|props/flora/reeds_pond_lush_a.xml"; const aLillies = "actor|props/flora/water_lillies.xml"; const pForestD = [tGrassDForest + TERRAIN_SEPARATOR + oBeech, tGrassDForest]; var heightSeaGround = -4; var heightShore = 1; var heightLand = 3; var g_Map = new RandomMap(heightShore, tPrimary); const numPlayers = getNumPlayers(); const mapCenter = g_Map.getCenter(); const mapBounds = g_Map.getBounds(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clShallow = g_Map.createTileClass(); var startAngle = randomAngle(); placePlayerBases({ "PlayerPlacement": playerPlacementRiver(startAngle + Math.PI / 2, fractionToTiles(0.6)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oOak, "count": 2 }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(10); paintRiver({ "parallel": false, "start": new Vector2D(mapBounds.left, mapCenter.y).rotateAround(startAngle, mapCenter), "end": new Vector2D(mapBounds.right, mapCenter.y).rotateAround(startAngle, mapCenter), "width": fractionToTiles(0.25), "fadeDist": scaleByMapSize(3, 10), "deviation": 0, "heightRiverbed": heightSeaGround, "heightLand": heightLand, "meanderShort": 20, "meanderLong": 0, "waterFunc": (position, height, riverFraction) => { createTerrain(height < -1.5 ? tWater : tShore).place(position); }, "landFunc": (position, shoreDist1, shoreDist2) => { g_Map.setHeight(position, heightLand + 0.1); } }); Engine.SetProgress(20); createTributaryRivers( startAngle, randIntInclusive(9, scaleByMapSize(13, 21)), scaleByMapSize(10, 20), heightSeaGround, [-6, -1.5], Math.PI / 5, clWater, clShallow, avoidClasses(clPlayer, 8, clBaseResource, 4)); paintTerrainBasedOnHeight(-5, 1, 1, tWater); paintTerrainBasedOnHeight(1, heightLand, 1, tShore); paintTileClassBasedOnHeight(-6, 0.5, 1, clWater); Engine.SetProgress(25); createBumps(avoidClasses(clWater, 5, clPlayer, 20)); Engine.SetProgress(30); createHills([tCliff, tCliff, tHill], avoidClasses(clPlayer, 20, clHill, 15, clWater, 5), clHill, scaleByMapSize(1, 4) * numPlayers); Engine.SetProgress(50); var [forestTrees, stragglerTrees] = getTreeCounts(500, 3000, 0.7); createForests( [tGrass, tGrassDForest, tGrassDForest, pForestD, pForestD], avoidClasses(clPlayer, 20, clForest, 17, clHill, 0, clWater, 6), clForest, forestTrees); Engine.SetProgress(70); g_Map.log("Creating dirt patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [[tGrass,tGrassA], tGrassB, [tGrassB,tGrassC]], [1,1], avoidClasses(clWater, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 6), scaleByMapSize(15, 45), clDirt); g_Map.log("Creating grass patches"); createPatches( [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)], [tGrassPatchBlend, tGrassPatch], [1], avoidClasses(clWater, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 6), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(80); g_Map.log("Creating stone mines"); createMines( [ [new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], avoidClasses(clWater, 2, clForest, 1, clPlayer, 20, clRock, 10, clHill, 2), clRock); g_Map.log("Creating metal mines"); createMines( [ [new SimpleObject(oMetalLarge, 1,1, 0,4)] ], avoidClasses(clWater, 2, clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 2), clMetal ); Engine.SetProgress(85); createDecoration( [ [new SimpleObject(aRockMedium, 1, 3, 0, 1)], [new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)], [new SimpleObject(aGrassShort, 1, 2, 0, 1)], [new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3, 6, 1.2, 2.5)], [new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)] ], [ scaleByMapAreaAbsolute(16), scaleByMapAreaAbsolute(8), scaleByMapAreaAbsolute(13), scaleByMapAreaAbsolute(13), scaleByMapAreaAbsolute(13) ], avoidClasses(clWater, 1, clForest, 0, clPlayer, 0, clHill, 0)); createDecoration( [ [new SimpleObject(aReeds, 1, 3, 0, 1)], [new SimpleObject(aLillies, 1, 2, 0, 1)] ], [ scaleByMapSize(800, 12800), scaleByMapSize(800, 12800) ], stayClasses(clShallow, 0)); createFood( [ [new SimpleObject(oDeer, 5, 7, 0, 4)], [new SimpleObject(oGoat, 2, 3, 0, 2)], [new SimpleObject(oBoar, 2, 3, 0, 2)] ], [ 3 * numPlayers, 3 * numPlayers, 3 * numPlayers ], avoidClasses(clWater, 1, clForest, 0, clPlayer, 20, clHill, 0, clFood, 15), clFood); createFood( [ [new SimpleObject(oBerryBush, 5, 7, 0, 4)] ], [ randIntInclusive(1, 4) * numPlayers + 2 ], avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 10), clFood); createFood( [ [new SimpleObject(oFish, 2, 3, 0, 2)] ], [scaleByMapSize(3, 25) * numPlayers], [avoidClasses(clFood, 6), stayClasses(clWater, 4)], clFood); createStragglerTrees( [oBeech, oPoplar, oApple], avoidClasses(clWater, 1, clForest, 1, clHill, 1, clPlayer, 8, clMetal, 6, clRock, 6), clForest, stragglerTrees); setSkySet("cirrus"); setWaterColor(0.114, 0.192, 0.463); setWaterTint(0.255, 0.361, 0.651); setWaterWaviness(3.0); setWaterType("ocean"); setWaterMurkiness(0.83); setFogThickness(0.35); setFogFactor(0.55); setPPEffect("hdr"); setPPSaturation(0.62); setPPContrast(0.62); setPPBloom(0.37); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/extinct_volcano.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/extinct_volcano.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/extinct_volcano.js (revision 26381) @@ -1,466 +1,466 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); const tHillDark = "cliff volcanic light"; const tHillMedium1 = "ocean_rock_a"; const tHillMedium2 = "ocean_rock_b"; const tHillVeryDark = ["cliff volcanic coarse", "cave_walls"]; const tRoad = "road1"; const tRoadWild = "road1"; const tForestFloor1 = tHillMedium1; const tForestFloor2 = tHillMedium2; const tGrassA = "cliff volcanic light"; const tGrassB = "ocean_rock_a"; const tGrassPatchBlend = "temp_grass_long_b"; const tGrassPatch = ["temp_grass_d", "temp_grass_clovers"]; const tShoreBlend = "cliff volcanic light"; const tShore = "ocean_rock_a"; const tWater = "ocean_rock_b"; const oTree = "gaia/tree/dead"; const oTree2 = "gaia/tree/euro_beech"; const oTree3 = "gaia/tree/oak"; const oTree4 = "gaia/tree/oak_dead"; const oBush = "gaia/tree/bush_temperate"; const oFruitBush = "gaia/fruit/berry_01"; const oRabbit = "gaia/fauna_rabbit"; const oGoat = "gaia/fauna_goat"; const oBear = "gaia/fauna_bear_brown"; const oStoneLarge = "gaia/rock/temperate_large"; const oStoneSmall = "gaia/rock/temperate_small"; const oMetalLarge = "gaia/ore/temperate_large"; const oTower = "structures/palisades_fort"; const aRockLarge = "actor|geology/stone_granite_med.xml"; const aRockMedium = "actor|geology/stone_granite_med.xml"; const aBushMedium = "actor|props/flora/bush_tempe_me.xml"; const aBushSmall = "actor|props/flora/bush_tempe_sm.xml"; const aGrass = "actor|props/flora/grass_soft_large_tall.xml"; const aGrassShort = "actor|props/flora/grass_soft_large.xml"; const aRain = "actor|particle/rain_shower.xml"; const pForestD = [ tForestFloor1 + TERRAIN_SEPARATOR + oTree, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor1 ]; const pForestP = [ tForestFloor1 + TERRAIN_SEPARATOR + oTree3, tForestFloor2 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 ]; var heightSeaGround = -4; var heightLand = 1; var heightHill = 18; var heightPlayerHill = 25; var g_Map = new RandomMap(heightLand, tHillMedium1); var numPlayers = getNumPlayers(); var mapCenter = g_Map.getCenter(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clGrass = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clBumps = g_Map.createTileClass(); var clTower = g_Map.createTileClass(); var clRain = g_Map.createTileClass(); var playerMountainSize = defaultPlayerBaseRadius(); var [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); g_Map.log("Creating CC mountains"); if (!isNomad()) for (let i = 0; i < numPlayers; ++i) { // This one consists of many bumps, creating an omnidirectional ramp createMountain( heightPlayerHill, playerMountainSize, playerMountainSize, Math.floor(scaleByMapSize(4, 10)), undefined, playerPosition[i].x, playerPosition[i].y, tHillDark, clPlayer, 14); // Flatten the initial CC area createArea( new ClumpPlacer(diskArea(playerMountainSize), 0.95, 0.6, Infinity, playerPosition[i]), [ new LayeredPainter([tHillVeryDark, tHillMedium1], [playerMountainSize]), new SmoothElevationPainter(ELEVATION_SET, heightPlayerHill, playerMountainSize), new TileClassPainter(clPlayer) ]); } Engine.SetProgress(8); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], // PlayerTileClass already marked above "BaseResourceClass": clBaseResource, "Walls": "towers", "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oFruitBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oTree2 } // No decoratives }); Engine.SetProgress(15); createVolcano(mapCenter, clHill, tHillVeryDark, undefined, false, ELEVATION_SET); Engine.SetProgress(20); g_Map.log("Creating lakes"); createAreas( new ChainPlacer(5, 6, Math.floor(scaleByMapSize(10, 14)), 0.1), [ new LayeredPainter([tShoreBlend, tShore, tWater], [1, 1]), new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 3), new TileClassPainter(clWater) ], avoidClasses(clPlayer, 0, clHill, 2, clWater, 12), Math.round(scaleByMapSize(6, 12))); Engine.SetProgress(25); createBumps(avoidClasses(clPlayer, 0, clHill, 0), scaleByMapSize(50, 300), 1, 10, 3, 0, scaleByMapSize(4, 10)); paintTileClassBasedOnHeight(10, 100, 0, clBumps); Engine.SetProgress(30); g_Map.log("Creating hills"); createAreas( new ClumpPlacer(scaleByMapSize(20, 150), 0.2, 0.1, Infinity), [ new LayeredPainter([tHillDark, tHillDark, tHillDark], [2, 2]), new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), new TileClassPainter(clHill) ], avoidClasses(clPlayer, 0, clHill, 15, clWater, 2, clBaseResource, 2), scaleByMapSize(2, 8) * numPlayers); Engine.SetProgress(35); g_Map.log("Creating forests"); var [forestTrees, stragglerTrees] = getTreeCounts(1200, 3000, 0.7); var types = [ [[tGrassB, tGrassA, pForestD], [tGrassB, pForestD]], [[tGrassB, tGrassA, pForestP], [tGrassB, pForestP]] ]; var size = forestTrees / (scaleByMapSize(4, 12) * numPlayers); var num = Math.floor(size / types.length); for (let type of types) createAreas( new ClumpPlacer(forestTrees / num, 0.1, 0.1, Infinity), [ new LayeredPainter(type, [2]), new TileClassPainter(clForest) ], avoidClasses( clPlayer, 4, clForest, 10, clHill, 0, clWater, 2), num); Engine.SetProgress(40); g_Map.log("Creating hill patches"); for (let size of [scaleByMapSize(3, 48), scaleByMapSize(5, 84), scaleByMapSize(8, 128)]) for (let type of [[tHillMedium1, tHillDark], [tHillDark, tHillMedium2], [tHillMedium1, tHillMedium2]]) createAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), [ new LayeredPainter(type, [1]), new TileClassPainter(clGrass) ], avoidClasses( clWater, 3, clForest, 0, clHill, 0, clBumps, 0, clPlayer, 0), scaleByMapSize(20, 80)); Engine.SetProgress(45); g_Map.log("Creating grass patches"); createLayeredPatches( [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)], [tGrassPatchBlend, tGrassPatch], [1], avoidClasses( clWater, 1, clForest, 0, clHill, 0, clGrass, 5, clBumps, 0, clPlayer, 0), scaleByMapSize(3, 8), clDirt); Engine.SetProgress(50); g_Map.log("Creating stone mines"); createObjectGroupsDeprecated( new SimpleGroup( [ new SimpleObject(oStoneSmall, 0, 2, 0, 4), new SimpleObject(oStoneLarge, 1, 1, 0, 4) ], true, clRock), 0, [ stayClasses(clBumps, 1), avoidClasses( clWater, 3, clForest, 1, clPlayer, 0, clRock, 15, clHill, 0) ], 100, 100); Engine.SetProgress(55); g_Map.log("Creating small stone quarries"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oStoneSmall, 2, 5, 1, 3)], true, clRock), 0, [ stayClasses(clBumps, 1), avoidClasses( clWater, 3, clForest, 1, clPlayer, 0, clRock, 15, clHill, 0) ], 100, 100); Engine.SetProgress(60); g_Map.log("Creating metal mines"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oMetalLarge, 1, 1, 0, 4)], true, clMetal), 0, [ stayClasses(clBumps, 1), avoidClasses( clWater, 3, clForest, 1, clPlayer, 0, clMetal, 15, clRock, 10, clHill, 0) ], 100, 100); Engine.SetProgress(65); if (!isNomad()) { g_Map.log("Creating towers"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oTower, 1, 1, 0, 4)], true, clTower), 0, [ stayClasses(clBumps, 3), avoidClasses( clMetal, 5, clRock, 5, clHill, 0, clTower, 60, clPlayer, 10, clForest, 2) ], 500, 1); } Engine.SetProgress(67); createDecoration( [ [ new SimpleObject(aGrassShort, 1, 2, 0, 1) ], [ new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3, 6, 1.2, 2.5) ], [ new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2) ] ], [ scaleByMapAreaAbsolute(15), scaleByMapAreaAbsolute(15), scaleByMapAreaAbsolute(15) ], [ stayClasses(clGrass, 0), avoidClasses( clWater, 0, clForest, 0, clPlayer, 0, clHill, 0) ]); Engine.SetProgress(70); createDecoration( [ [ new SimpleObject(aRockMedium, 1, 3, 0, 1) ], [ new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2) ] ], [ scaleByMapSize(15, 250), scaleByMapSize(15, 150) ], avoidClasses( clWater, 0, clForest, 0, clPlayer, 0, clHill, 0 )); Engine.SetProgress(75); createFood( [ [new SimpleObject(oRabbit, 5, 7, 2, 4)], [new SimpleObject(oGoat, 3, 5, 2, 4)] ], [ scaleByMapSize(1, 6) * numPlayers, scaleByMapSize(3, 10) * numPlayers ], [ avoidClasses( clWater, 1, clForest, 0, clPlayer, 0, clHill, 1, clFood, 20) ], clFood); Engine.SetProgress(78); createFood( [ [new SimpleObject(oBear, 1, 1, 0, 2)] ], [ 3 * numPlayers ], [ avoidClasses( clWater, 1, clForest, 0, clPlayer, 0, clHill, 1, clFood, 20 ), stayClasses(clForest, 2) ], clFood); Engine.SetProgress(81); createFood( [ [new SimpleObject(oFruitBush, 1, 2, 0, 4)] ], [ 3 * numPlayers ], [stayClasses(clGrass, 1), avoidClasses(clWater, 1, clForest, 0, clPlayer, 0, clHill, 1, clFood, 10)], clFood); Engine.SetProgress(85); createStragglerTrees( [oTree, oTree2, oTree3, oTree4, oBush], [ stayClasses(clGrass, 1), avoidClasses( clWater, 5, clForest, 1, clHill, 1, clPlayer, 0, clMetal, 4, clRock, 4) ], clForest, stragglerTrees); Engine.SetProgress(90); g_Map.log("Creating straggler bushes"); createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject(oBush, 1, 3, 0, 3)], true, clForest ), 0, [ stayClasses(clGrass, 3), avoidClasses( clWater, 1, clForest, 1, clPlayer, 0, clMetal, 4, clRock, 4) ], stragglerTrees); Engine.SetProgress(95); g_Map.log("Creating rain drops"); createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject(aRain, 2, 2, 1, 4)], true, clRain), 0, avoidClasses(clRain, 5), scaleByMapSize(80, 250)); Engine.SetProgress(98); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clHill, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); setSkySet("rain"); setWaterType("lake"); setWaterWaviness(2); setWaterColor(0.1, 0.13, 0.15); setWaterTint(0.058, 0.05, 0.035); setWaterMurkiness(0.9); setPPEffect("hdr"); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/fields_of_meroe.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/fields_of_meroe.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/fields_of_meroe.js (revision 26381) @@ -1,451 +1,451 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); if (g_MapSettings.Biome) setSelectedBiome(); else setBiome("fields_of_meroe/dry"); const tMainDirt = g_Terrains.mainDirt; const tSecondaryDirt = g_Terrains.secondaryDirt; const tDirt = g_Terrains.dirt; const tLush = "desert_grass_a"; const tSLush = "desert_grass_a_sand"; const tFarmland = "desert_farmland"; const tRoad = "savanna_tile_a"; const tRoadWild = "desert_city_tile"; const tRiverBank = "savanna_riparian_wet"; const tForestFloor = "savanna_forestfloor_b"; const oBush = g_Gaia.berry; const oBaobab = "gaia/tree/baobab"; const oAcacia = "gaia/tree/acacia"; const oDatePalm = "gaia/tree/date_palm"; const oSDatePalm = "gaia/tree/cretan_date_palm_short"; const oGazelle = "gaia/fauna_gazelle"; const oGiraffe = "gaia/fauna_giraffe"; const oLion = "gaia/fauna_lion"; const oFish = "gaia/fish/generic"; const oHawk = "birds/buzzard"; const oStoneLarge = "gaia/rock/savanna_large"; const oStoneSmall = "gaia/rock/desert_small"; const oMetalLarge = "gaia/ore/savanna_large"; const oMetalSmall = "gaia/ore/desert_small"; const oHouse = "structures/kush/house"; const oFarmstead = "structures/kush/farmstead"; const oField = "structures/kush/field"; const oPyramid = "structures/kush/pyramid_small"; const oPyramidLarge = "structures/kush/pyramid_large"; const oKushUnits = isNomad() ? "units/kush/support_female_citizen" : "units/kush/infantry_javelineer_merc_e"; const aRain = g_Decoratives.rain; const aBushA = g_Decoratives.bushA; const aBushB = g_Decoratives.bushB; const aBushes = [aBushA, aBushB]; const aReeds = "actor|props/flora/reeds_pond_lush_a.xml"; const aRockA = g_Decoratives.rock; const aRockB = "actor|geology/shoreline_large.xml"; const aRockC = "actor|geology/shoreline_small.xml"; const pForestP = [tForestFloor + TERRAIN_SEPARATOR + oAcacia, tForestFloor]; const heightSeaGround = g_Heights.seaGround; const heightReedsDepth = -2.5; const heightCataract = -1; const heightShore = 1; const heightLand = 2; const heightDunes = 11; const heightOffsetBump = 1.4; const heightOffsetBumpPassage = 4; const g_Map = new RandomMap(heightLand, tMainDirt); const numPlayers = getNumPlayers(); const mapCenter = g_Map.getCenter(); const mapBounds = g_Map.getBounds(); var clPlayer = g_Map.createTileClass(); var clKushiteVillages = g_Map.createTileClass(); var clRiver = g_Map.createTileClass(); var clShore = g_Map.createTileClass(); var clDunes = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clRain = g_Map.createTileClass(); var clCataract = g_Map.createTileClass(); var kushVillageBuildings = { "houseA": { "template": oHouse, "offset": new Vector2D(5, 5) }, "houseB": { "template": oHouse, "offset": new Vector2D(5, 0) }, "houseC": { "template": oHouse, "offset": new Vector2D(5, -5) }, "farmstead": { "template": oFarmstead, "offset": new Vector2D(-5, 0) }, "fieldA": { "template": oField, "offset": new Vector2D(-5, 5) }, "fieldB": { "template": oField, "offset": new Vector2D(-5, -5) }, "pyramid": { "template": oPyramid, "offset": new Vector2D(0, -5) } }; const riverTextures = [ { "left": fractionToTiles(0), "right": fractionToTiles(0.04), "terrain": tLush, "tileClass": clShore }, { "left": fractionToTiles(0.04), "right": fractionToTiles(0.06), "terrain": tSLush, "tileClass": clShore } ]; const riverAngle = Math.PI/5; paintRiver({ "parallel": false, "start": new Vector2D(fractionToTiles(0.25), mapBounds.top).rotateAround(riverAngle, mapCenter), "end": new Vector2D(fractionToTiles(0.25), mapBounds.bottom).rotateAround(riverAngle, mapCenter), "width": scaleByMapSize(12, 36), "fadeDist": scaleByMapSize(3, 12), "deviation": 1, "heightRiverbed": heightSeaGround, "heightLand": heightShore, "meanderShort": 14, "meanderLong": 18, "waterFunc": (position, height, z) => { clRiver.add(position); createTerrain(tRiverBank).place(position); }, "landFunc": (position, shoreDist1, shoreDist2) => { for (let riv of riverTextures) if (riv.left < +shoreDist1 && +shoreDist1 < riv.right || riv.left < -shoreDist2 && -shoreDist2 < riv.right) { riv.tileClass.add(position); if (riv.terrain) createTerrain(riv.terrain).place(position); } } }); Engine.SetProgress(10); g_Map.log("Creating cataracts"); for (let x of [fractionToTiles(randFloat(0.15, 0.25)), fractionToTiles(randFloat(0.75, 0.85))]) { let anglePassage = riverAngle + Math.PI / 2 * randFloat(0.8, 1.2); let areaPassage = createArea( new PathPlacer( new Vector2D(x, mapBounds.bottom).rotateAround(anglePassage, mapCenter), new Vector2D(x, mapBounds.top).rotateAround(anglePassage, mapCenter), scaleByMapSize(20, 30), 0, 1, 0, 0, Infinity), [ new SmoothElevationPainter(ELEVATION_SET, heightCataract, 2), new TileClassPainter(clCataract) ], new HeightConstraint(-Infinity, 0)); createAreasInAreas( new ClumpPlacer(4, 0.4, 0.6, 0.5), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBumpPassage, 2), undefined, scaleByMapSize(15, 30), 20, [areaPassage]); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(aReeds, 2, 4, 0, 1)], true), 0, undefined, scaleByMapSize(20, 50), 20, [areaPassage]); } var [playerIDs, playerPosition] = playerPlacementRandom(sortAllPlayers(), avoidClasses(clRiver, 15, clPlayer, 30)); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad, "radius": 10, "width": 3, "painters": [new TileClassPainter(clPlayer)] }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "type": "stone_formation", "template": oStoneSmall, "terrain": tSecondaryDirt } ], "groupElements": [new RandomObject(aBushes, 2, 4, 2, 3)] }, "Trees": { "template": pickRandom([oBaobab, oAcacia]), "count": 3 } }); Engine.SetProgress(15); g_Map.log("Getting random coordinates for Kushite settlements"); var kushiteTownPositions = []; for (let retryCount = 0; retryCount < scaleByMapSize(3, 10); ++retryCount) { let coordinate = g_Map.randomCoordinate(true); if (new AndConstraint(avoidClasses(clPlayer, 40, clForest, 5, clKushiteVillages, 50, clRiver, 15)).allows(coordinate)) { kushiteTownPositions.push(coordinate); createArea( new ClumpPlacer(40, 0.6, 0.3, Infinity, coordinate), [ new TerrainPainter(tRoad), new TileClassPainter(clKushiteVillages) ]); } } g_Map.log("Placing the Kushite buildings"); for (let coordinate of kushiteTownPositions) { for (let building in kushVillageBuildings) g_Map.placeEntityPassable(kushVillageBuildings[building].template, 0, Vector2D.add(coordinate, kushVillageBuildings[building].offset), Math.PI); createObjectGroup(new SimpleGroup([new SimpleObject(oKushUnits, 5, 7, 1, 2)], true, clKushiteVillages, coordinate), 0); } g_Map.log("Creating kushite pyramids"); createObjectGroups( new SimpleGroup([new SimpleObject(oPyramidLarge, 1, 1, 0, 1)], true, clKushiteVillages), 0, avoidClasses(clPlayer, 20, clForest, 5, clKushiteVillages, 30, clRiver, 10), scaleByMapSize(1, 7), 200); Engine.SetProgress(20); g_Map.log("Creating bumps"); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), new StaticConstraint(avoidClasses(clPlayer, 5, clKushiteVillages, 10, clRiver, 20)), scaleByMapSize(300, 800)); g_Map.log("Creating dunes"); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(5, 15)), 0.5), [ new SmoothElevationPainter(ELEVATION_SET, heightDunes, 2), new TileClassPainter(clDunes) ], avoidClasses(clPlayer, 3, clRiver, 20, clDunes, 10, clKushiteVillages, 10), scaleByMapSize(1, 3) * numPlayers * 3); Engine.SetProgress(25); var [forestTrees, stragglerTrees] = getTreeCounts(400, 2000, 0.7); createForests( [tMainDirt[0], tForestFloor, tForestFloor, pForestP, pForestP], avoidClasses(clPlayer, 20, clForest, 20, clDunes, 2, clRiver, 20, clKushiteVillages, 10), clForest, forestTrees); Engine.SetProgress(40); g_Map.log("Creating dirt patches"); for (let size of [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)]) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5), new LayeredPainter([tSecondaryDirt, tDirt], [1]), avoidClasses(clDunes, 0, clForest, 0, clPlayer, 5, clRiver, 10), scaleByMapSize(50, 90)); g_Map.log("Creating patches of farmland"); for (let size of [scaleByMapSize(30, 40), scaleByMapSize(35, 50)]) createAreas( new ClumpPlacer(size, 0.4, 0.6), new TerrainPainter(tFarmland), avoidClasses(clDunes, 3, clForest, 3, clPlayer, 5, clKushiteVillages, 5, clRiver, 10), scaleByMapSize(1, 10)); Engine.SetProgress(60); g_Map.log("Creating stone mines"); createObjectGroups( new SimpleGroup( [ new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4) ], true, clRock), 0, avoidClasses(clRiver, 4, clCataract, 4, clPlayer, 20, clRock, 15, clKushiteVillages, 5, clDunes, 2, clForest, 4), scaleByMapSize(2, 8), 50); g_Map.log("Creating small stone quarries"); createObjectGroups( new SimpleGroup([new SimpleObject(oStoneSmall, 2, 5, 1, 3, 0, 2 * Math.PI, 1)], true, clRock), 0, avoidClasses(clRiver, 4, clCataract, 4, clPlayer, 20, clRock, 15, clKushiteVillages, 5, clDunes, 2, clForest, 4), scaleByMapSize(2, 8), 50); g_Map.log("Creating metal mines"); createObjectGroups( new SimpleGroup( [ new SimpleObject(oMetalSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oMetalLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4) ], true, clMetal), 0, avoidClasses(clRiver, 4, clCataract, 4, clPlayer, 20, clRock, 10, clMetal, 15, clKushiteVillages, 5, clDunes, 2, clForest, 4), scaleByMapSize(2, 8), 50); g_Map.log("Creating small metal quarries"); createObjectGroups( new SimpleGroup([new SimpleObject(oMetalSmall, 2, 5, 1, 3, 0, 2 * Math.PI, 1)], true, clMetal), 0, avoidClasses(clRiver, 4, clCataract, 4, clPlayer, 20, clRock, 10, clMetal, 15, clKushiteVillages, 5, clDunes, 2, clForest, 4), scaleByMapSize(2, 8), 50); Engine.SetProgress(70); g_Map.log("Creating gazelle"); createObjectGroups( new SimpleGroup([new SimpleObject(oGazelle, 4, 6, 1, 4)], true, clFood), 0, avoidClasses(clForest, 0, clKushiteVillages, 10, clPlayer, 5, clDunes, 1, clFood, 25, clRiver, 2, clMetal, 4, clRock, 4), 2 * numPlayers, 50); g_Map.log("Creating giraffe"); createObjectGroups( new SimpleGroup([new SimpleObject(oGiraffe, 4, 6, 1, 4)], true, clFood), 0, avoidClasses(clForest, 0, clKushiteVillages, 10, clPlayer, 5, clDunes, 1, clFood, 25, clRiver, 2, clMetal, 4, clRock, 4), 2 * numPlayers, 50); g_Map.log("Creating lions"); if (!isNomad()) createObjectGroups( new SimpleGroup([new SimpleObject(oLion, 2, 3, 0, 2)], true, clFood), 0, avoidClasses(clForest, 0, clKushiteVillages, 10, clPlayer, 5, clDunes, 1, clFood, 25, clRiver, 2, clMetal, 4, clRock, 4), 3 * numPlayers, 50); g_Map.log("Creating hawk"); for (let i = 0; i < scaleByMapSize(1, 3); ++i) g_Map.placeEntityAnywhere(oHawk, 0, mapCenter, randomAngle()); g_Map.log("Creating fish"); createObjectGroups( new SimpleGroup([new SimpleObject(oFish, 1, 2, 0, 1)], true, clFood), 0, [stayClasses(clRiver, 4), avoidClasses(clFood, 16, clCataract, 10)], scaleByMapSize(15, 80), 50); Engine.SetProgress(80); createStragglerTrees( [oBaobab, oAcacia], avoidClasses(clForest, 3, clFood, 1, clDunes, 1, clPlayer, 1, clMetal, 6, clRock, 6, clRiver, 15, clKushiteVillages, 15), clForest, stragglerTrees); createStragglerTrees( [oBaobab, oAcacia], avoidClasses(clForest, 1, clFood, 1, clDunes, 3, clPlayer, 1, clMetal, 6, clRock, 6, clRiver, 15, clKushiteVillages, 15), clForest, stragglerTrees * (isNomad() ? 3 : 1)); createStragglerTrees( [oDatePalm, oSDatePalm], [avoidClasses(clPlayer, 5, clFood, 1), stayClasses(clShore, 2)], clForest, stragglerTrees * 10); Engine.SetProgress(90); g_Map.log("Creating reeds on the shore"); createObjectGroups( new SimpleGroup([new SimpleObject(aReeds, 3, 5, 0, 1)], true), 0, [ new HeightConstraint(heightReedsDepth, heightShore), avoidClasses(clCataract, 2) ], scaleByMapSize(500, 1000), 50); g_Map.log("Creating small decorative rocks"); createObjectGroups( new SimpleGroup([new SimpleObject(aRockA, 2, 4, 0, 1)], true), 0, avoidClasses(clForest, 0, clPlayer, 0, clDunes, 0, clRiver, 5, clCataract, 5, clMetal, 4, clRock, 4), scaleByMapSize(16, 262), 50); createObjectGroups( new SimpleGroup([new SimpleObject(aRockB, 1, 2, 0, 1), new SimpleObject(aRockC, 1, 3, 0, 1)], true), 0, [ new NearTileClassConstraint(clCataract, 5), new HeightConstraint(-Infinity, heightShore) ], scaleByMapSize(30, 50), 50); g_Map.log("Creating bushes"); createObjectGroups( new SimpleGroup([new SimpleObject(aBushB, 1, 2, 0, 1), new SimpleObject(aBushA, 1, 3, 0, 2)], true), 0, avoidClasses(clForest, 0, clPlayer, 0, clDunes, 0, clRiver, 15, clMetal, 4, clRock, 4), scaleByMapSize(50, 500), 50); Engine.SetProgress(95); g_Map.log("Creating rain drops"); if (aRain) createObjectGroups( new SimpleGroup([new SimpleObject(aRain, 1, 1, 1, 4)], true, clRain), 0, avoidClasses(clRain, 5), scaleByMapSize(60, 200)); Engine.SetProgress(98); placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clKushiteVillages, 18, clMetal, 4, clRock, 4, clDunes, 4, clFood, 2, clRiver, 5)); setSunElevation(Math.PI / 8); setSunRotation(randomAngle()); setSunColor(0.746, 0.718, 0.539); setWaterColor(0.292, 0.347, 0.691); setWaterTint(0.550, 0.543, 0.437); setFogColor(0.8, 0.76, 0.61); setFogThickness(0.2); setFogFactor(0.2); setPPEffect("hdr"); setPPContrast(0.65); setPPSaturation(0.42); setPPBloom(0.6); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/flood.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/flood.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/flood.js (revision 26381) @@ -1,299 +1,299 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); setSelectedBiome(); const tMainTerrain = g_Terrains.mainTerrain; const tForestFloor1 = g_Terrains.forestFloor1; const tForestFloor2 = g_Terrains.forestFloor2; const tCliff = g_Terrains.cliff; const tTier1Terrain = g_Terrains.tier1Terrain; const tTier2Terrain = g_Terrains.tier2Terrain; const tTier3Terrain = g_Terrains.tier3Terrain; const tRoad = g_Terrains.road; const tRoadWild = g_Terrains.roadWild; const tTier4Terrain = g_Terrains.tier4Terrain; const tShore = g_Terrains.shore; const tWater = g_Terrains.water; var tHill = g_Terrains.hill; var tDirt = g_Terrains.dirt; if (currentBiome() == "generic/temperate") { tDirt = ["medit_shrubs_a", "grass_field"]; tHill = ["grass_field", "peat_temp"]; } const oTree1 = g_Gaia.tree1; const oTree2 = g_Gaia.tree2; const oTree3 = g_Gaia.tree3; const oTree4 = g_Gaia.tree4; const oTree5 = g_Gaia.tree5; const oFruitBush = g_Gaia.fruitBush; const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal; const oFish = g_Gaia.fish; const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal; const oStoneLarge = g_Gaia.stoneLarge; const oMetalLarge = g_Gaia.metalLarge; const aGrass = g_Decoratives.grass; const aGrassShort = g_Decoratives.grassShort; const aRockLarge = g_Decoratives.rockLarge; const aRockMedium = g_Decoratives.rockMedium; const aBushMedium = g_Decoratives.bushMedium; const aBushSmall = g_Decoratives.bushSmall; const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2]; const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1]; const heightSeaGround = -2; const heightLand = 2; const shoreRadius = 6; var g_Map = new RandomMap(heightSeaGround, tWater); const clPlayer = g_Map.createTileClass(); const clHill = g_Map.createTileClass(); const clMountain = g_Map.createTileClass(); const clForest = g_Map.createTileClass(); const clDirt = g_Map.createTileClass(); const clRock = g_Map.createTileClass(); const clMetal = g_Map.createTileClass(); const clFood = g_Map.createTileClass(); const clBaseResource = g_Map.createTileClass(); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); g_Map.log("Creating player islands..."); var [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.38)); for (let i = 0; i < numPlayers; ++i) createArea( new ClumpPlacer(diskArea(1.4 * defaultPlayerBaseRadius()), 0.8, 0.1, Infinity, playerPosition[i]), [ new LayeredPainter([tShore, tMainTerrain], [shoreRadius]), new SmoothElevationPainter(ELEVATION_SET, heightLand, shoreRadius), new TileClassPainter(clHill) ]); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "Walls": false, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oFruitBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oTree2, "count": 50, "maxDist": 16, "maxDistGroup": 7 }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(40); g_Map.log("Creating central island"); createArea( new ChainPlacer( 6, Math.floor(scaleByMapSize(10, 15)), Math.floor(scaleByMapSize(200, 300)), Infinity, mapCenter, 0, [Math.floor(fractionToTiles(0.01))]), [ new LayeredPainter([tShore, tMainTerrain], [shoreRadius, 100]), new SmoothElevationPainter(ELEVATION_SET, heightLand, shoreRadius), new TileClassPainter(clHill) ], avoidClasses(clPlayer, 40)); for (let m = 0; m < randIntInclusive(20, 34); ++m) { let elevRand = randIntInclusive(6, 20); createArea( new ChainPlacer( 7, 15, Math.floor(scaleByMapSize(15, 20)), Infinity, new Vector2D(fractionToTiles(randFloat(0, 1)), fractionToTiles(randFloat(0, 1))), 0, [Math.floor(fractionToTiles(0.01))]), [ new LayeredPainter([tDirt, tHill], [Math.floor(elevRand / 3), 40]), new SmoothElevationPainter(ELEVATION_SET, elevRand, Math.floor(elevRand / 3)), new TileClassPainter(clHill) ], [avoidClasses(clBaseResource, 2, clPlayer, 40), stayClasses(clHill, 6)]); } for (let m = 0; m < randIntInclusive(8, 17); ++m) { let elevRand = randIntInclusive(15, 29); createArea( new ChainPlacer( 5, 8, Math.floor(scaleByMapSize(15, 20)), Infinity, new Vector2D(randIntExclusive(0, mapSize), randIntExclusive(0, mapSize)), 0, [Math.floor(fractionToTiles(0.01))]), [ new LayeredPainter([tCliff, tForestFloor2], [Math.floor(elevRand / 3), 40]), new SmoothElevationPainter(ELEVATION_MODIFY, elevRand, Math.floor(elevRand / 3)), new TileClassPainter(clMountain) ], [avoidClasses(clBaseResource, 2, clPlayer, 40), stayClasses(clHill, 6)]); } g_Map.log("Creating center bounty"); createObjectGroup( new SimpleGroup( [new SimpleObject(oMetalLarge, 3, 6, 25, Math.floor(fractionToTiles(0.25)))], true, clBaseResource, mapCenter), 0, [avoidClasses(clBaseResource, 20, clPlayer, 40, clMountain, 4), stayClasses(clHill, 10)]); createObjectGroup( new SimpleGroup( [new SimpleObject(oStoneLarge, 3, 6, 25, Math.floor(fractionToTiles(0.25)))], true, clBaseResource, mapCenter), 0, [avoidClasses(clBaseResource, 20, clPlayer, 40, clMountain, 4), stayClasses(clHill, 10)]); g_Map.log("Creating fish"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oFish, 2, 3, 0, 2)], true, clFood), 0, avoidClasses(clHill, 10, clFood, 20), 10 * numPlayers, 60); var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(0.7)); createForests( [tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2], [avoidClasses(clPlayer, 25, clForest, 10, clBaseResource, 3, clMetal, 6, clRock, 6, clMountain, 2), stayClasses(clHill, 6)], clForest, forestTrees); let types = [oTree1, oTree2, oTree4, oTree3]; createStragglerTrees( types, [avoidClasses(clBaseResource, 2, clMetal, 6, clRock, 6, clMountain, 2, clPlayer, 25), stayClasses(clHill, 6)], clForest, stragglerTrees); Engine.SetProgress(65); g_Map.log("Creating dirt patches"); var numb = currentBiome() == "generic/savanna" ? 3 : 1; for (let size of [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)]) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5), [ new LayeredPainter([[tMainTerrain, tTier1Terrain], [tTier1Terrain, tTier2Terrain], [tTier2Terrain, tTier3Terrain]], [1, 1]), new TileClassPainter(clDirt) ], avoidClasses(clForest, 0, clMountain, 0, clDirt, 5, clPlayer, 10), numb * scaleByMapSize(15, 45)); g_Map.log("Painting shorelines"); paintTerrainBasedOnHeight(1, heightLand, 0, tMainTerrain); paintTerrainBasedOnHeight(heightSeaGround, 1, 3, tTier1Terrain); g_Map.log("Creating grass patches"); for (let size of [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)]) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5), new TerrainPainter(tTier4Terrain), avoidClasses(clForest, 0, clMountain, 0, clDirt, 5, clPlayer, 10), numb * scaleByMapSize(15, 45)); createFood( [ [new SimpleObject(oMainHuntableAnimal, 5, 7, 0, 4)], [new SimpleObject(oSecondaryHuntableAnimal, 2, 3, 0, 2)] ], [3 * numPlayers, 3 * numPlayers], [avoidClasses(clForest, 0, clPlayer, 20, clMountain, 1, clFood, 4, clRock, 6, clMetal, 6), stayClasses(clHill, 6)], clFood); Engine.SetProgress(75); createFood( [ [new SimpleObject(oFruitBush, 5, 7, 0, 4)] ], [3 * numPlayers], [avoidClasses(clForest, 0, clPlayer, 15, clMountain, 1, clFood, 4, clRock, 6, clMetal, 6), stayClasses(clHill, 6)], clFood); Engine.SetProgress(85); var planetm = currentBiome() == "generic/india" ? 8 : 1; createDecoration( [ [new SimpleObject(aRockMedium, 1, 3, 0, 1)], [new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)], [new SimpleObject(aGrassShort, 2, 15, 0, 1)], [new SimpleObject(aGrass, 2, 10, 0, 1.8), new SimpleObject(aGrassShort, 3, 10, 1.2, 2.5)], [new SimpleObject(aBushMedium, 1, 5, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)] ], [ scaleByMapAreaAbsolute(16), scaleByMapAreaAbsolute(8), planetm * scaleByMapAreaAbsolute(13), planetm * scaleByMapAreaAbsolute(13), planetm * scaleByMapAreaAbsolute(13) ], avoidClasses(clForest, 2, clPlayer, 20, clMountain, 5, clFood, 1, clBaseResource, 2)); var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(0.1)); createForests( [tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2], avoidClasses(clPlayer, 30, clHill, 10, clFood, 5), clForest, forestTrees); g_Map.log("Creating small grass tufts"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(aGrassShort, 1, 2, 0, 1)]), 0, [avoidClasses(clMountain, 2, clPlayer, 2, clDirt, 0), stayClasses(clHill, 8)], planetm * scaleByMapSize(13, 200)); placePlayersNomad( clPlayer, new AndConstraint([ stayClasses(clHill, 2), avoidClasses(clMountain, 2, clForest, 1, clMetal, 4, clRock, 4, clFood, 2)])); setSkySet(pickRandom(["cloudless", "cumulus", "overcast"])); setWaterMurkiness(0.4); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/gear.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/gear.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/gear.js (revision 26381) @@ -1,316 +1,316 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); TILE_CENTERED_HEIGHT_MAP = true; setSelectedBiome(); const tMainTerrain = g_Terrains.mainTerrain; const tForestFloor1 = g_Terrains.forestFloor1; const tForestFloor2 = g_Terrains.forestFloor2; const tCliff = g_Terrains.cliff; const tTier1Terrain = g_Terrains.tier1Terrain; const tTier2Terrain = g_Terrains.tier2Terrain; const tTier3Terrain = g_Terrains.tier3Terrain; const tHill = g_Terrains.mainTerrain; const tRoad = g_Terrains.road; const tRoadWild = g_Terrains.roadWild; const tTier4Terrain = g_Terrains.tier4Terrain; const tShore = g_Terrains.shore; const tWater = g_Terrains.water; const oTree1 = g_Gaia.tree1; const oTree2 = g_Gaia.tree2; const oTree3 = g_Gaia.tree3; const oTree4 = g_Gaia.tree4; const oTree5 = g_Gaia.tree5; const oFruitBush = g_Gaia.fruitBush; const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal; const oFish = g_Gaia.fish; const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal; const oStoneLarge = g_Gaia.stoneLarge; const oStoneSmall = g_Gaia.stoneSmall; const oMetalLarge = g_Gaia.metalLarge; const aGrass = g_Decoratives.grass; const aGrassShort = g_Decoratives.grassShort; const aRockLarge = g_Decoratives.rockLarge; const aRockMedium = g_Decoratives.rockMedium; const aBushMedium = g_Decoratives.bushMedium; const aBushSmall = g_Decoratives.bushSmall; const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2]; const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1]; var heightSeaGround = -4; var heightShallow = -2; var heightLand = 3; var heightRing = 4; var heightHill = 20; var g_Map = new RandomMap(heightLand, tMainTerrain); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var radiusPlayers = fractionToTiles(0.35); var radiusCentralLake = fractionToTiles(0.27); var radiusCentralRingLand = fractionToTiles(0.21); var radiusCentralWaterRing = fractionToTiles(0.17); var radiusCentralIsland = fractionToTiles(0.14); var radiusCentralHill = fractionToTiles(0.12); var [playerIDs, playerPosition, playerAngle, startAngle] = playerPlacementCircle(radiusPlayers); g_Map.log("Determining number of rivers between players"); var split = 1; if (mapSize == 128 && numPlayers <= 2) split = 2; else if (mapSize == 192 && numPlayers <= 3) split = 2; else if (mapSize == 256) { if (numPlayers <= 3) split = 3; else if (numPlayers == 4) split = 2; } else if (mapSize == 320) { if (numPlayers <= 3) split = 3; else if (numPlayers == 4) split = 2; } else if (mapSize == 384) { if (numPlayers <= 3) split = 4; else if (numPlayers == 4) split = 3; else if (numPlayers == 5) split = 2; } else if (mapSize == 448) { if (numPlayers <= 2) split = 5; else if (numPlayers <= 4) split = 4; else if (numPlayers == 5) split = 3; else if (numPlayers == 6) split = 2; } g_Map.log("Creating big circular lake"); createArea( new DiskPlacer(radiusCentralLake, mapCenter), new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4)); g_Map.log("Creating rivers between players"); for (let m = 0; m < numPlayers * split; ++m) { let angle = startAngle + (m + 0.5) * 2 * Math.PI / (numPlayers * split); let position1 = Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.15), 0).rotate(-angle)); let position2 = Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.6), 0).rotate(-angle)); createArea( new PathPlacer(position1, position2, scaleByMapSize(14, 40), 0, scaleByMapSize(3, 9), 0.2, 0.05), new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4), avoidClasses(clPlayer, 5)); } g_Map.log("Create path from the island to the center"); for (let m = 0; m < numPlayers * split; ++m) { let angle = startAngle + m * 2 * Math.PI / (numPlayers * split); let position1 = Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.05), 0).rotate(-angle)); let position2 = Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.49), 0).rotate(-angle)); createArea( new PathPlacer(position1, position2, scaleByMapSize(10, 40), 0, scaleByMapSize(3, 9), 0.2, 0.05), new SmoothElevationPainter(ELEVATION_SET, heightLand, 4)); } g_Map.log("Creating ring of land connecting players"); createArea( new DiskPlacer(radiusCentralRingLand, mapCenter), new SmoothElevationPainter(ELEVATION_SET, heightRing, 4)); g_Map.log("Creating inner ring of water"); createArea( new DiskPlacer(radiusCentralWaterRing, mapCenter), new SmoothElevationPainter(ELEVATION_SET, heightShallow, 3)); g_Map.log("Creating central island"); createArea( new DiskPlacer(radiusCentralIsland, mapCenter), new SmoothElevationPainter(ELEVATION_SET, heightRing, 3)); g_Map.log("Creating hill on the central island"); createArea( new DiskPlacer(radiusCentralHill, mapCenter), new SmoothElevationPainter(ELEVATION_SET, heightHill, 8)); paintTerrainBasedOnHeight(-6, 1, 1, tWater); paintTerrainBasedOnHeight(1, 2, 1, tShore); paintTerrainBasedOnHeight(2, 21, 1, tMainTerrain); paintTileClassBasedOnHeight(-6, 0.5, 1, clWater); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "baseResourceConstraint": avoidClasses(clWater, 2), "Walls": "towers", "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oFruitBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oTree1, "count": 2 }, "Decoratives": { "template": aGrassShort } }); if (randBool()) createHills([tMainTerrain, tCliff, tHill], avoidClasses(clPlayer, 20, clHill, 15, clWater, 2), clHill, scaleByMapSize(1, 4) * numPlayers); else createMountains(tCliff, avoidClasses(clPlayer, 20, clHill, 15, clWater, 2), clHill, scaleByMapSize(1, 4) * numPlayers); var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(1)); createForests( [tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2], avoidClasses(clPlayer, 20, clForest, 17, clHill, 0, clWater, 2), clForest, forestTrees); Engine.SetProgress(50); g_Map.log("Creating dirt patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [[tMainTerrain,tTier1Terrain],[tTier1Terrain,tTier2Terrain], [tTier2Terrain,tTier3Terrain]], [1,1], avoidClasses(clWater, 3, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45), clDirt); g_Map.log("Creating grass patches"); createPatches( [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)], tTier4Terrain, avoidClasses(clWater, 3, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(55); g_Map.log("Creating stone mines"); createMines( [ [new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), clRock); g_Map.log("Creating metal mines"); createMines( [ [new SimpleObject(oMetalLarge, 1,1, 0,4)] ], avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 1), clMetal ); g_Map.log("Creating fish"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oFish, 1,1, 0,3)], true, clFood), 0, [stayClasses(clWater, 8), avoidClasses(clFood, 14)], scaleByMapSize(400, 2000), 100); Engine.SetProgress(65); var planetm = 1; if (currentBiome() == "generic/india") planetm = 8; createDecoration( [ [new SimpleObject(aRockMedium, 1, 3, 0, 1)], [new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)], [new SimpleObject(aGrassShort, 1, 2, 0, 1)], [new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3, 6, 1.2, 2.5)], [new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)] ], [ scaleByMapAreaAbsolute(16), scaleByMapAreaAbsolute(8), planetm * scaleByMapAreaAbsolute(13), planetm * scaleByMapAreaAbsolute(13), planetm * scaleByMapAreaAbsolute(13) ], avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0)); Engine.SetProgress(70); createFood( [ [new SimpleObject(oMainHuntableAnimal, 5, 7, 0, 4)], [new SimpleObject(oSecondaryHuntableAnimal, 2, 3, 0, 2)] ], [ 3 * numPlayers, 3 * numPlayers ], avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 20), clFood); createFood( [ [new SimpleObject(oFruitBush, 5, 7, 0, 4)] ], [ 3 * numPlayers ], avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 10), clFood); createStragglerTrees( [oTree1, oTree2, oTree4, oTree3], avoidClasses(clWater, 5, clForest, 7, clHill, 1, clPlayer, 12, clMetal, 6, clRock, 6), clForest, stragglerTrees); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/gulf_of_bothnia.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/gulf_of_bothnia.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/gulf_of_bothnia.js (revision 26381) @@ -1,252 +1,252 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); TILE_CENTERED_HEIGHT_MAP = true; if (g_MapSettings.Biome) setSelectedBiome(); else // TODO: Replace ugly default for atlas by a dropdown setBiome("gulf_of_bothnia/winter"); const tPrimary = g_Terrains.mainTerrain; const tForestFloor = g_Terrains.forestFloor1; const tCliff = g_Terrains.cliff; const tSecondary = g_Terrains.tier1Terrain; const tHalfSnow = g_Terrains.tier2Terrain; const tSnowLimited = g_Terrains.tier3Terrain; const tRoad = g_Terrains.road; const tRoadWild = g_Terrains.roadWild; const tShore = g_Terrains.shore; const tWater = g_Terrains.water; const oPine = g_Gaia.tree1; const oBerryBush = g_Gaia.fruitBush; const oStoneLarge = g_Gaia.stoneLarge; const oStoneSmall = g_Gaia.stoneSmall; const oMetalLarge = g_Gaia.metalLarge; const oMetalSmall = g_Gaia.metalSmall; const oDeer = g_Gaia.mainHuntableAnimal; const oRabbit = g_Gaia.secondaryHuntableAnimal; const oFish = g_Gaia.fish; const aGrass = g_Decoratives.grass; const aGrassShort = g_Decoratives.grassShort; const aRockLarge = g_Decoratives.rockLarge; const aRockMedium = g_Decoratives.rockMedium; const aBushMedium = g_Decoratives.bushMedium; const aBushSmall = g_Decoratives.bushSmall; const heightSeaGround = g_Heights.seaGround; const heightShore = g_Heights.shore; const heightLand = g_Heights.land; const fishCount = g_ResourceCounts.fish; const bushCount = g_ResourceCounts.bush; const pForest = [tForestFloor + TERRAIN_SEPARATOR + oPine, tForestFloor]; var g_Map = new RandomMap(heightLand, tPrimary); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var startAngle = randomAngle(); placePlayerBases({ "PlayerPlacement": [sortAllPlayers(), ...playerPlacementCustomAngle( fractionToTiles(0.35), mapCenter, i => startAngle + 1/3 * Math.PI * (1 + 2 * (numPlayers == 1 ? 1 : 2 * i / (numPlayers - 1))))], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oPine, "count": 2 }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(20); g_Map.log("Creating the gulf"); var gulfLakePositions = [ { "numCircles": 200, "x": fractionToTiles(0), "radius": fractionToTiles(0.175) }, { "numCircles": 120, "x": fractionToTiles(0.3), "radius": fractionToTiles(0.2) }, { "numCircles": 100, "x": fractionToTiles(0.5), "radius": fractionToTiles(0.225) } ]; for (let gulfLake of gulfLakePositions) { let position = Vector2D.add(mapCenter, new Vector2D(gulfLake.x, 0).rotate(-startAngle)).round(); createArea( new ChainPlacer( 2, Math.floor(scaleByMapSize(5, 16)), Math.floor(scaleByMapSize(35, gulfLake.numCircles)), Infinity, position, 0, [Math.floor(gulfLake.radius)]), [ new TerrainPainter(tPrimary), new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4), new TileClassPainter(clWater) ], avoidClasses(clPlayer,scaleByMapSize(20, 28))); } if (currentBiome() === "gulf_of_bothnia/frozen_lake") { createAreas( new ChainPlacer( 1, 4, scaleByMapSize(16, 40), 0.3), new ElevationPainter(-2), stayClasses(clWater, 2), scaleByMapSize(10, 40)); } paintTerrainBasedOnHeight(heightShore, heightLand, Elevation_ExcludeMin_ExcludeMax, tShore); paintTerrainBasedOnHeight(-Infinity, heightShore, Elevation_ExcludeMin_IncludeMax, tWater); createBumps(avoidClasses(clWater, 2, clPlayer, 10)); if (randBool()) createHills([tPrimary, tCliff, tPrimary], avoidClasses(clPlayer, 20, clHill, 15, clWater, 0), clHill, scaleByMapSize(1, 4) * numPlayers); else createMountains(tCliff, avoidClasses(clPlayer, 20, clHill, 15, clWater, 0), clHill, scaleByMapSize(1, 4) * numPlayers); var [forestTrees, stragglerTrees] = getTreeCounts(500, 3000, 0.7); createDefaultForests( [tPrimary, tForestFloor, tForestFloor, pForest, pForest], avoidClasses(clPlayer, 20, clForest, 16, clHill, 0, clWater, 2), clForest, forestTrees); Engine.SetProgress(60); g_Map.log("Creating dirt patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [[tPrimary,tSecondary],[tSecondary,tHalfSnow], [tHalfSnow,tSnowLimited]], [1,1], avoidClasses(clWater, 6, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45), clDirt); g_Map.log("Creating grass patches"); createPatches( [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)], tHalfSnow, avoidClasses(clWater, 6, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(65); g_Map.log("Creating metal mines"); createBalancedMetalMines( oMetalSmall, oMetalLarge, clMetal, avoidClasses(clWater, 2, clForest, 0, clPlayer, scaleByMapSize(15, 25), clHill, 1), 0.9 ); g_Map.log("Creating stone mines"); createBalancedStoneMines( oStoneSmall, oStoneLarge, clRock, avoidClasses(clWater, 2, clForest, 0, clPlayer, scaleByMapSize(15, 25), clHill, 1, clMetal, 10), 0.9 ); Engine.SetProgress(70); createDecoration( [ [new SimpleObject(aRockMedium, 1, 3, 0, 1)], [new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)], [new SimpleObject(aGrassShort, 1, 2, 0, 1)], [new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3, 6, 1.2, 2.5)], [new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)] ], [ scaleByMapAreaAbsolute(16), scaleByMapAreaAbsolute(8), scaleByMapSize(bushCount.min, bushCount.max), scaleByMapSize(bushCount.min, bushCount.max), scaleByMapSize(bushCount.min, bushCount.max) ], avoidClasses(clWater, 0, clForest, 0, clPlayer, 5, clHill, 0, clBaseResource, 5)); Engine.SetProgress(75); createFood( [ [new SimpleObject(oDeer, 5, 7, 0, 4)], [new SimpleObject(oRabbit, 2, 3, 0, 2)] ], [ 3 * numPlayers, 3 * numPlayers ], avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 20), clFood); createFood( [[new SimpleObject(oBerryBush, 5, 7, 0, 4)]], [randIntInclusive(1, 4) * numPlayers + 2], avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 10), clFood); createFood( [[new SimpleObject(oFish, 2, 3, 0, 2)]], [scaleByMapSize(fishCount.min, fishCount.max)], [avoidClasses(clFood, 20), stayClasses(clWater, 6)], clFood); Engine.SetProgress(85); createStragglerTrees( [oPine], avoidClasses(clWater, 3, clForest, 1, clHill, 1, clPlayer, 12, clMetal, 6, clRock, 6), clForest, stragglerTrees); // Avoid the lake, even if frozen placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); setSunElevation(Math.PI * randFloat(1/6, 1/4)); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/hyrcanian_shores.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/hyrcanian_shores.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/hyrcanian_shores.js (revision 26381) @@ -1,358 +1,358 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); setSelectedBiome(); const tPrimary = g_Terrains.mainTerrain; const tGrass = g_Terrains.tier1Terrain; const tGrassPForest = g_Terrains.forestFloor1; const tGrassDForest = g_Terrains.forestFloor2; const tCliff = g_Terrains.cliff; const tGrassA = g_Terrains.tier2Terrain; const tGrassB = g_Terrains.tier3Terrain; const tGrassC = g_Terrains.tier4Terrain; const tHill = g_Terrains.hill; const tRoad = g_Terrains.road; const tRoadWild = g_Terrains.roadWild; const tGrassPatch = g_Terrains.dirt; const tShore = g_Terrains.shoreBlend; const tWater = g_Terrains.shore; const oPoplar = g_Gaia.tree1; const oPalm = g_Gaia.tree2; const oApple = g_Gaia.tree3; const oOak = g_Gaia.tree4; const oBerryBush = g_Gaia.fruitBush; const oDeer = g_Gaia.mainHuntableAnimal; const oFish = g_Gaia.fish; const oGoat = "gaia/fauna_goat"; const oBoar = "gaia/fauna_boar"; const oStoneLarge = g_Gaia.stoneLarge; const oStoneSmall = g_Gaia.stoneSmall; const oMetalLarge = g_Gaia.metalLarge; const aGrass = g_Decoratives.grass; const aGrassShort = g_Decoratives.grassShort; const aRockLarge = g_Decoratives.rockLarge; const aRockMedium = g_Decoratives.rockMedium; const aBushMedium = g_Decoratives.bushMedium; const aBushSmall = g_Decoratives.bushSmall; const pForestD = [tGrassDForest + TERRAIN_SEPARATOR + oPoplar, tGrassDForest]; const pForestP = [tGrassPForest + TERRAIN_SEPARATOR + oOak, tGrassPForest]; const heightSeaGround1 = -3; const heightShore1 = -1.5; const heightShore2 = 0; const heightLand = 1; const heightOffsetBump = 4; const heightHill = 15; var g_Map = new RandomMap(heightLand, tPrimary); const mapCenter = g_Map.getCenter(); const mapBounds = g_Map.getBounds(); const numPlayers = getNumPlayers(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clHighlands = g_Map.createTileClass(); var waterPosition = fractionToTiles(0.25); var highlandsPosition = fractionToTiles(0.75); var startAngle = randomAngle(); placePlayerBases({ "PlayerPlacement": [sortAllPlayers(), playerPlacementLine(startAngle, mapCenter, fractionToTiles(0.2))], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oOak, "count": 2 }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(10); paintRiver({ "parallel": true, "start": new Vector2D(mapBounds.left, mapBounds.top).rotateAround(startAngle, mapCenter), "end": new Vector2D(mapBounds.right, mapBounds.top).rotateAround(startAngle, mapCenter), "width": 2 * waterPosition, "fadeDist": scaleByMapSize(6, 25), "deviation": 0, "heightRiverbed": heightSeaGround1, "heightLand": heightLand, "meanderShort": 20, "meanderLong": 0, "waterFunc": (position, height, riverFraction) => { if (height < heightShore2) clWater.add(position); createTerrain(height < heightShore1 ? tWater : tShore).place(position); } }); Engine.SetProgress(20); g_Map.log("Marking highlands area"); createArea( new ConvexPolygonPlacer( [ new Vector2D(mapBounds.left, mapBounds.top - highlandsPosition), new Vector2D(mapBounds.right, mapBounds.top - highlandsPosition), new Vector2D(mapBounds.left, mapBounds.bottom), new Vector2D(mapBounds.right, mapBounds.bottom) ].map(pos => pos.rotateAround(startAngle, mapCenter)), Infinity), new TileClassPainter(clHighlands)); g_Map.log("Creating fish"); for (let i = 0; i < scaleByMapSize(10, 20); ++i) createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oFish, 2, 3, 0, 2)], true, clFood), 0, [stayClasses(clWater, 2), avoidClasses(clFood, 3)], numPlayers, 50); Engine.SetProgress(25); g_Map.log("Creating bumps"); createAreas( new ClumpPlacer(scaleByMapSize(10, 60), 0.3, 0.06, Infinity), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 3), stayClasses(clHighlands, 1), scaleByMapSize(300, 600)); Engine.SetProgress(30); g_Map.log("Creating hills"); createAreas( new ClumpPlacer(scaleByMapSize(20, 150), 0.2, 0.1, Infinity), [ new LayeredPainter([tCliff, tHill], [2]), new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), new TileClassPainter(clHill) ], avoidClasses(clPlayer, 20, clWater, 5, clHill, 15, clHighlands, 5), scaleByMapSize(1, 4) * numPlayers); Engine.SetProgress(35); g_Map.log("Creating mainland forests"); const [forestTrees, stragglerTrees] = getTreeCounts(1000, 3500, 0.85); const highlandShare = 0.4; { var types = [ [[tGrassDForest, tGrass, pForestD], [tGrassDForest, pForestD]] ]; const numberOfForests = scaleByMapSize(20, 100) / types[0].length; for (const type of types) createAreas( new ClumpPlacer(forestTrees * (1.0 - highlandShare) / numberOfForests, 0.1, 0.1, Infinity), [ new LayeredPainter(type, [2]), new TileClassPainter(clForest) ], avoidClasses(clPlayer, 20, clWater, 3, clForest, 10, clHill, 0, clBaseResource, 3, clHighlands, 2), numberOfForests); Engine.SetProgress(45); } g_Map.log("Creating highland forests"); { var types = [ [[tGrassDForest, tGrass, pForestP], [tGrassDForest, pForestP]] ]; const numberOfForests = scaleByMapSize(8, 50) / types[0].length; for (const type of types) createAreas( new ClumpPlacer(forestTrees * (highlandShare) / numberOfForests, 0.1, 0.1, Infinity), [ new LayeredPainter(type, [2]), new TileClassPainter(clForest) ], [ avoidClasses(clPlayer, 20, clWater, 3, clForest, 10, clHill, 0, clBaseResource, 3), stayClasses(clHighlands, 2) ], numberOfForests, 30); } Engine.SetProgress(70); g_Map.log("Creating dirt patches"); for (let size of [scaleByMapSize(3, 48), scaleByMapSize(5, 84), scaleByMapSize(8, 128)]) createAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), [ new LayeredPainter([[tGrass, tGrassA], [tGrassA, tGrassB], [tGrassB, tGrassC]], [1, 1]), new TileClassPainter(clDirt) ], avoidClasses(clWater, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 4), scaleByMapSize(15, 45)); Engine.SetProgress(75); g_Map.log("Creating grass patches"); for (let size of [scaleByMapSize(2, 32), scaleByMapSize(3, 48), scaleByMapSize(5, 80)]) createAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), new LayeredPainter([tGrassC, tGrassPatch], [2]), avoidClasses(clWater, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 6, clBaseResource, 6), scaleByMapSize(15, 45)); Engine.SetProgress(80); g_Map.log("Creating stone mines"); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clWater, 0, clForest, 1, clPlayer, 20, clRock, 10, clHill, 2)], scaleByMapSize(4,16), 100 ); g_Map.log("Creating small stone quarries"); group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clWater, 0, clForest, 1, clPlayer, 20, clRock, 10, clHill, 2)], scaleByMapSize(4,16), 100 ); g_Map.log("Creating metal mines"); group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4)], true, clMetal); createObjectGroupsDeprecated(group, 0, [avoidClasses(clWater, 0, clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 2)], scaleByMapSize(5, 20), 100 ); Engine.SetProgress(85); g_Map.log("Creating small decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockMedium, 1,3, 0,1)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0), scaleByMapSize(16, 262), 50 ); Engine.SetProgress(90); g_Map.log("Creating large decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockLarge, 1,2, 0,1), new SimpleObject(aRockMedium, 1,3, 0,2)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0), scaleByMapSize(8, 131), 50 ); g_Map.log("Creating deer"); group = new SimpleGroup( [new SimpleObject(oDeer, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clHill, 0, clFood, 5), 6 * numPlayers, 50 ); g_Map.log("Creating sheep"); group = new SimpleGroup( [new SimpleObject(oGoat, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clHill, 0, clFood, 20), 3 * numPlayers, 50 ); g_Map.log("Creating berry bush"); group = new SimpleGroup( [new SimpleObject(oBerryBush, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 6, clForest, 0, clPlayer, 20, clHill, 1, clFood, 10), randIntInclusive(1, 4) * numPlayers + 2, 50 ); g_Map.log("Creating boar"); group = new SimpleGroup( [new SimpleObject(oBoar, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clHill, 0, clFood, 20), 2 * numPlayers, 50 ); createStragglerTrees( [oPoplar, oPalm, oApple], avoidClasses(clWater, 1, clForest, 1, clHill, 1, clPlayer, 10, clMetal, 6, clRock, 6), clForest, stragglerTrees); g_Map.log("Creating small grass tufts"); group = new SimpleGroup( [new SimpleObject(aGrassShort, 1,2, 0,1, -Math.PI / 8, Math.PI / 8)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 2, clHill, 2, clPlayer, 2, clDirt, 0), scaleByMapSize(13, 200) ); g_Map.log("Creating large grass tufts"); group = new SimpleGroup( [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)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clHill, 2, clPlayer, 2, clDirt, 1, clForest, 0), scaleByMapSize(13, 200) ); Engine.SetProgress(95); g_Map.log("Creating bushes"); group = new SimpleGroup( [new SimpleObject(aBushMedium, 1,2, 0,2), new SimpleObject(aBushSmall, 2,4, 0,2)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 1, clHill, 1, clPlayer, 1, clDirt, 1), scaleByMapSize(13, 200), 50 ); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); setWaterWaviness(2.0); setWaterType("ocean"); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/island_stronghold.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/island_stronghold.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/island_stronghold.js (revision 26381) @@ -1,411 +1,411 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmgen2"); Engine.LoadLibrary("rmbiome"); const g_InitialMineDistance = 14; const g_InitialTrees = 50; setSelectedBiome(); const tMainTerrain = g_Terrains.mainTerrain; const tForestFloor1 = g_Terrains.forestFloor1; const tForestFloor2 = g_Terrains.forestFloor2; const tCliff = g_Terrains.cliff; const tTier1Terrain = g_Terrains.tier1Terrain; const tTier2Terrain = g_Terrains.tier2Terrain; const tTier3Terrain = g_Terrains.tier3Terrain; const tHill = g_Terrains.hill; const tTier4Terrain = g_Terrains.tier4Terrain; const tShore = g_Terrains.shore; const tWater = g_Terrains.water; const oTree1 = g_Gaia.tree1; const oTree2 = g_Gaia.tree2; const oTree3 = g_Gaia.tree3; const oTree4 = g_Gaia.tree4; const oTree5 = g_Gaia.tree5; const oFruitBush = g_Gaia.fruitBush; const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal; const oFish = g_Gaia.fish; const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal; const oStoneLarge = g_Gaia.stoneLarge; const oStoneSmall = g_Gaia.stoneSmall; const oMetalLarge = g_Gaia.metalLarge; const oWhale = "gaia/fauna_whale_humpback"; const oShipwreck = "gaia/treasure/shipwreck"; const oShipDebris = "gaia/treasure/shipwreck_debris"; const oObelisk = "structures/obelisk"; const aGrass = g_Decoratives.grass; const aGrassShort = g_Decoratives.grassShort; const aRockLarge = g_Decoratives.rockLarge; const aRockMedium = g_Decoratives.rockMedium; const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2]; const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1]; const heightSeaGround = -10; const heightLand = 3; const heightHill = 18; var g_Map = new RandomMap(heightSeaGround, tWater); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); const clPlayer = g_Map.createTileClass(); const clHill = g_Map.createTileClass(); const clForest = g_Map.createTileClass(); const clDirt = g_Map.createTileClass(); const clRock = g_Map.createTileClass(); const clMetal = g_Map.createTileClass(); const clFood = g_Map.createTileClass(); const clBaseResource = g_Map.createTileClass(); const clLand = g_Map.createTileClass(); var startAngle = randomAngle(); var teams = getTeamsArray(); var numTeams = teams.filter(team => team).length; var teamPosition = distributePointsOnCircle(numTeams, startAngle, fractionToTiles(0.3), mapCenter)[0]; var teamRadius = fractionToTiles(0.05); var teamNo = 0; g_Map.log("Creating player islands and bases"); for (let i = 0; i < teams.length; ++i) { if (!teams[i] || isNomad()) continue; ++teamNo; let [playerPosition, playerAngle] = distributePointsOnCircle(teams[i].length, startAngle + 2 * Math.PI / teams[i].length, teamRadius, teamPosition[i]); playerPosition.forEach(position => position.round()); for (let p = 0; p < teams[i].length; ++p) { addCivicCenterAreaToClass(playerPosition[p], clPlayer); createArea( new ChainPlacer(2, Math.floor(scaleByMapSize(5, 11)), Math.floor(scaleByMapSize(60, 250)), Infinity, playerPosition[p], Infinity, [defaultPlayerBaseRadius() * 3/4]), [ new TerrainPainter(tMainTerrain), new SmoothElevationPainter(ELEVATION_SET, heightLand, 2), new TileClassPainter(clLand) ]); placeCivDefaultStartingEntities(playerPosition[p], teams[i][p], false); } let mineAngle = randFloat(-1, 1) * Math.PI / teams[i].length; let mines = [ { "template": oMetalLarge, "angle": mineAngle }, { "template": oStoneLarge, "angle": mineAngle + Math.PI / 4 } ]; // Mines for (let p = 0; p < teams[i].length; ++p) for (let mine of mines) { let position = Vector2D.add(playerPosition[p], new Vector2D(g_InitialMineDistance, 0).rotate(-playerAngle[p] - mine.angle)); createObjectGroup( new SimpleGroup([new SimpleObject(mine.template, 1, 1, 0, 4)], true, clBaseResource, position), 0, [avoidClasses(clBaseResource, 4, clPlayer, 4), stayClasses(clLand, 5)]); } // Trees for (let p = 0; p < teams[i].length; ++p) { let tries = 10; for (let x = 0; x < tries; ++x) { let tAngle = playerAngle[p] + randFloat(-1, 1) * 2 * Math.PI / teams[i].length; let treePosition = Vector2D.add(playerPosition[p], new Vector2D(16, 0).rotate(-tAngle)).round(); if (createObjectGroup( new SimpleGroup([new SimpleObject(oTree2, g_InitialTrees, g_InitialTrees, 0, 7)], true, clBaseResource, treePosition), 0, [avoidClasses(clBaseResource, 4, clPlayer, 4), stayClasses(clLand, 4)])) break; } } for (let p = 0; p < teams[i].length; ++p) placePlayerBaseBerries({ "template": oFruitBush, "playerID": teams[i][p], "playerPosition": playerPosition[p], "BaseResourceClass": clBaseResource, "baseResourceConstraint": new AndConstraint([avoidClasses(clPlayer, 4), stayClasses(clLand, 5)]) }); for (let p = 0; p < teams[i].length; ++p) - placePlayerBaseChicken({ + placePlayerBaseStartingAnimal({ "playerID": teams[i][p], "playerPosition": playerPosition[p], "BaseResourceClass": clBaseResource, "baseResourceConstraint": new AndConstraint([avoidClasses(clPlayer, 4), stayClasses(clLand, 5)]) }); // Huntable animals for (let p = 0; p < teams[i].length; ++p) { createObjectGroup( new SimpleGroup([new SimpleObject(oMainHuntableAnimal, 2 * numPlayers / numTeams, 2 * numPlayers / numTeams, 0, Math.floor(fractionToTiles(0.2)))], true, clBaseResource, teamPosition[i]), 0, [avoidClasses(clBaseResource, 2, clPlayer, 10), stayClasses(clLand, 5)]); createObjectGroup( new SimpleGroup( [new SimpleObject(oSecondaryHuntableAnimal, 4 * numPlayers / numTeams, 4 * numPlayers / numTeams, 0, Math.floor(fractionToTiles(0.2)))], true, clBaseResource, teamPosition[i]), 0, [avoidClasses(clBaseResource, 2, clPlayer, 10), stayClasses(clLand, 5)]); } } Engine.SetProgress(40); g_Map.log("Creating big islands"); createAreas( new ChainPlacer( Math.floor(scaleByMapSize(4, 8) * (isNomad() ? 2 : 1)), Math.floor(scaleByMapSize(8, 16) * (isNomad() ? 2 : 1)), Math.floor(scaleByMapSize(25, 60)), 0.07, undefined, scaleByMapSize(30, 70)), [ new TerrainPainter(tMainTerrain), new SmoothElevationPainter(ELEVATION_SET, heightLand, 6), new TileClassPainter(clLand) ], avoidClasses(clLand, 3, clPlayer, 3), scaleByMapSize(4, 14) * (isNomad() ? 2 : 1), 1); g_Map.log("Creating small islands"); createAreas( new ChainPlacer(Math.floor(scaleByMapSize(4, 7)), Math.floor(scaleByMapSize(7, 10)), Math.floor(scaleByMapSize(16, 40)), 0.07, undefined, scaleByMapSize(22, 40)), [ new LayeredPainter([tMainTerrain, tMainTerrain], [2]), new SmoothElevationPainter(ELEVATION_SET, heightLand, 6), new TileClassPainter(clLand) ], avoidClasses(clLand, 3, clPlayer, 3), scaleByMapSize(6, 55), 1); Engine.SetProgress(70); g_Map.log("Smoothing heightmap"); createArea( new MapBoundsPlacer(), new SmoothingPainter(1, 0.8, 5)); // repaint clLand to compensate for smoothing unPaintTileClassBasedOnHeight(-10, 10, 3, clLand); paintTileClassBasedOnHeight(0, 5, 3, clLand); Engine.SetProgress(85); createBumps(avoidClasses(clPlayer, 20)); createMines( [ [new SimpleObject(oMetalLarge, 1, 1, 0, 4)] ], [avoidClasses(clForest, 1, clPlayer, 40, clRock, 20), stayClasses(clLand, 4)], clMetal); createMines( [ [new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)] ], [avoidClasses(clForest, 1, clPlayer, 40, clMetal, 20), stayClasses(clLand, 4)], clRock); var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(1)); createForests( [tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2], [avoidClasses(clPlayer, 10, clForest, 20, clBaseResource, 5, clRock, 6, clMetal, 6), stayClasses(clLand, 3)], clForest, forestTrees); g_Map.log("Creating hills"); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(16, 40)), 0.5), [ new LayeredPainter([tCliff, tHill], [2]), new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), new TileClassPainter(clHill) ], [avoidClasses(clBaseResource, 20, clHill, 15, clRock, 6, clMetal, 6), stayClasses(clLand, 0)], scaleByMapSize(4, 13) ); g_Map.log("Smoothing heightmap"); createArea( new MapBoundsPlacer(), new SmoothingPainter(1, 0.8, 3)); createStragglerTrees( [oTree1, oTree2, oTree4, oTree3], [ avoidClasses(clForest, 10, clPlayer, 20, clMetal, 6, clRock, 6, clHill, 1), stayClasses(clLand, 4) ], clForest, stragglerTrees); createFood( [ [new SimpleObject(oMainHuntableAnimal, 5, 7, 0, 4)], [new SimpleObject(oSecondaryHuntableAnimal, 2, 3, 0, 2)] ], [3 * numPlayers, 3 * numPlayers], [avoidClasses(clForest, 0, clPlayer, 20, clHill, 1, clRock, 6, clMetal, 6), stayClasses(clLand, 2)], clFood); createFood( [ [new SimpleObject(oFruitBush, 5, 7, 0, 4)] ], [3 * numPlayers], [avoidClasses(clForest, 0, clPlayer, 15, clHill, 1, clFood, 4, clRock, 6, clMetal, 6), stayClasses(clLand, 2)], clFood); if (currentBiome() == "generic/sahara") { g_Map.log("Creating obelisks"); let group = new SimpleGroup( [new SimpleObject(oObelisk, 1, 1, 0, 1)], true ); createObjectGroupsDeprecated( group, 0, [avoidClasses(clBaseResource, 0, clHill, 0, clRock, 0, clMetal, 0, clFood, 0), stayClasses(clLand, 1)], scaleByMapSize(3, 8), 1000 ); } g_Map.log("Creating dirt patches"); let numb = currentBiome() == "generic/savanna" ? 3 : 1; for (let size of [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)]) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5), [ new LayeredPainter([[tMainTerrain, tTier1Terrain], [tTier1Terrain, tTier2Terrain], [tTier2Terrain, tTier3Terrain]], [1, 1]), new TileClassPainter(clDirt) ], [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 0), stayClasses(clLand, 4)], numb*scaleByMapSize(15, 45)); g_Map.log("Creating grass patches"); for (let size of [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)]) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5), new TerrainPainter(tTier4Terrain), [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 0), stayClasses(clLand, 4)], numb * scaleByMapSize(15, 45)); g_Map.log("Creating small decorative rocks"); let group = new SimpleGroup( [new SimpleObject(aRockMedium, 1, 3, 0, 1)], true ); createObjectGroupsDeprecated( group, 0, [avoidClasses(clForest, 0, clHill, 0), stayClasses(clLand, 2)], scaleByMapSize(16, 262), 50 ); g_Map.log("Creating large decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)], true ); createObjectGroupsDeprecated( group, 0, [avoidClasses(clForest, 0, clHill, 0), stayClasses(clLand, 2)], scaleByMapSize(8, 131), 50 ); g_Map.log("Creating fish"); group = new SimpleGroup( [new SimpleObject(oFish, 2, 3, 0, 2)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clLand, 4, clFood, 20), 25 * numPlayers, 60 ); g_Map.log("Creating Whales"); group = new SimpleGroup( [new SimpleObject(oWhale, 1, 1, 0, 3)], true, clFood ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clLand, 4),avoidClasses(clFood, 8)], scaleByMapSize(5, 20), 100 ); g_Map.log("Creating shipwrecks"); group = new SimpleGroup( [new SimpleObject(oShipwreck, 1, 1, 0, 1)], true, clFood ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clLand, 4),avoidClasses(clFood, 8)], scaleByMapSize(12, 16), 100 ); g_Map.log("Creating shipwreck debris"); group = new SimpleGroup( [new SimpleObject(oShipDebris, 1, 1, 0, 1)], true, clFood ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clLand, 4),avoidClasses(clFood, 8)], scaleByMapSize(10, 20), 100 ); g_Map.log("Creating small grass tufts"); let planetm = currentBiome() == "generic/india" ? 8 : 1; group = new SimpleGroup( [new SimpleObject(aGrassShort, 1, 2, 0, 1, -Math.PI / 8, Math.PI / 8)] ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clHill, 2, clPlayer, 2, clDirt, 0), stayClasses(clLand, 3)], planetm * scaleByMapSize(13, 200) ); Engine.SetProgress(95); g_Map.log("Creating large grass tufts"); group = new SimpleGroup( [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)] ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clHill, 2, clPlayer, 2, clDirt, 1, clForest, 0), stayClasses(clLand, 5)], planetm * scaleByMapSize(13, 200) ); paintTerrainBasedOnHeight(1, 2, 0, tShore); paintTerrainBasedOnHeight(heightSeaGround, 1, 3, tWater); placePlayersNomad(clPlayer, [stayClasses(clLand, 4), avoidClasses(clHill, 2, clForest, 1, clMetal, 4, clRock, 4, clFood, 2)]); setSkySet(pickRandom(["cloudless", "cumulus", "overcast"])); setSunRotation(randomAngle()); setSunElevation(randFloat(1/5, 1/3) * Math.PI); setWaterWaviness(2); Engine.SetProgress(100); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/jebel_barkal.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/jebel_barkal.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/jebel_barkal.js (revision 26381) @@ -1,1505 +1,1505 @@ /** * For historic reference, see http://www.jebelbarkal.org/images/maps/siteplan.jpg */ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("heightmap"); TILE_CENTERED_HEIGHT_MAP = true; const tSand = "desert_sand_dunes_100"; const tHilltop = ["new_savanna_dirt_c", "new_savanna_dirt_d"]; const tHillGround = ["savanna_dirt_rocks_a", "savanna_dirt_rocks_b", "savanna_dirt_rocks_c"]; const tHillCliff = ["savanna_cliff_a_red", "savanna_cliff_b_red"]; const tRoadDesert = "savanna_tile_a"; const tRoadFertileLand = "savanna_tile_a"; const tWater = "desert_sand_wet"; const tGrass = ["savanna_shrubs_a_wetseason", "alpine_grass_b_wild", "medit_shrubs_a", "steppe_grass_green_a"]; const tForestFloorFertile = pickRandom(tGrass); const tGrassTransition1 = "desert_grass_a"; const tGrassTransition2 = "steppe_grass_dirt_66"; const tPath = "road2"; const tPathWild = "road_med"; const oAcacia = "gaia/tree/acacia"; const oPalmPath = "gaia/tree/cretan_date_palm_tall"; const oPalms = [ "gaia/tree/cretan_date_palm_tall", "gaia/tree/cretan_date_palm_short", "gaia/tree/palm_tropic", "gaia/tree/date_palm", "gaia/tree/senegal_date_palm", "gaia/tree/medit_fan_palm" ]; const oBerryBushGrapes = "gaia/fruit/grapes"; const oBerryBushDesert = "gaia/fruit/berry_05"; const oStoneLargeDesert = "gaia/rock/desert_large"; const oStoneSmallDesert = "gaia/rock/desert_small"; const oMetalLargeDesert = "gaia/ore/desert_large"; const oMetalSmallDesert = "gaia/ore/desert_small"; const oStoneLargeFertileLand = "gaia/rock/desert_large"; const oStoneSmallFertileLand = "gaia/rock/greece_small"; const oMetalLargeFertileLand = "gaia/ore/desert_large"; const oMetalSmallFertileLand = "gaia/ore/temperate_small"; const oFoodTreasureBin = "gaia/treasure/food_bin"; const oFoodTreasureCrate = "gaia/treasure/food_crate"; const oFoodTreasureJars = "gaia/treasure/food_jars"; const oWoodTreasure = "gaia/treasure/wood"; const oStoneTreasure = "gaia/treasure/stone"; const oMetalTreasure = "gaia/treasure/metal"; const oTreasuresHill = [oWoodTreasure, oStoneTreasure, oMetalTreasure]; const oTreasuresCity = [oFoodTreasureBin, oFoodTreasureCrate, oFoodTreasureJars].concat(oTreasuresHill); const oGiraffe = "gaia/fauna_giraffe"; const oGiraffeInfant = "gaia/fauna_giraffe_infant"; const oGazelle = "gaia/fauna_gazelle"; const oRhino = "gaia/fauna_rhinoceros_white"; const oWarthog = "gaia/fauna_boar"; const oElephant = "gaia/fauna_elephant_african_bush"; const oElephantInfant = "gaia/fauna_elephant_african_infant"; const oLion = "gaia/fauna_lion"; const oLioness = "gaia/fauna_lioness"; const oCrocodile = "gaia/fauna_crocodile_nile"; const oFish = "gaia/fish/tilapia"; const oHawk = "birds/buzzard"; const oTempleApedemak = "structures/kush/temple"; const oTempleAmun = "structures/kush/temple_amun"; const oPyramidLarge = "structures/kush/pyramid_large"; const oPyramidSmall = "structures/kush/pyramid_small"; const oWonderPtol = "structures/ptol/wonder"; const oFortress = "structures/kush/fortress"; const oTower = g_MapSettings.Size >= 256 && getDifficulty() >= 3 ? "structures/kush/defense_tower" : "structures/kush/sentry_tower"; const oHouse = "structures/kush/house"; const oMarket = "structures/kush/market"; const oForge = "structures/kush/forge"; const oBlemmyeCamp = "structures/kush/camp_blemmye"; const oNobaCamp = "structures/kush/camp_noba"; const oCivicCenter = "structures/kush/civil_centre"; const oBarracks = "structures/kush/barracks"; const oStable = "structures/kush/stable"; const oElephantStable = "structures/kush/elephant_stable"; const oWallMedium = "structures/kush/wall_medium"; const oWallGate = "structures/kush/wall_gate"; const oWallTower = "structures/kush/wall_tower"; const oPalisadeMedium = "structures/palisades_medium"; const oPalisadeGate = "structures/palisades_gate"; const oPalisadeTower = "structures/palisades_tower"; const oKushCitizenArcher = "units/kush/infantry_archer_b"; const oKushHealer = "units/kush/support_healer_b"; const oKushChampionArcher = "units/kush/champion_infantry_archer"; const oKushChampions = [ oKushChampionArcher, "units/kush/champion_infantry_amun", "units/kush/champion_infantry_apedemak" ]; const oPtolSiege = ["units/ptol/siege_lithobolos_unpacked", "units/ptol/siege_polybolos_unpacked"]; const oTriggerPointCityPath = "trigger/trigger_point_A"; const oTriggerPointAttackerPatrol = "trigger/trigger_point_B"; const aPalmPath = actorTemplate("flora/trees/palm_cretan_date_tall"); const aRock = actorTemplate("geology/stone_savanna_med"); const aHandcart = actorTemplate("props/special/eyecandy/handcart_1"); const aPlotFence = actorTemplate("props/special/common/plot_fence"); const aStatueKush = actorTemplate("props/special/eyecandy/statues_kush"); const aStatues = [ "props/structures/kushites/statue_pedestal_rectangular", "props/structures/kushites/statue_pedestal_rectangular_lion" ].map(actorTemplate); const aBushesFertileLand = [ ...new Array(3).fill("props/flora/shrub_spikes"), ...new Array(3).fill("props/flora/ferns"), "props/flora/shrub_tropic_plant_a", "props/flora/shrub_tropic_plant_b", "props/flora/shrub_tropic_plant_flower", "props/flora/foliagebush", "props/flora/bush", "props/flora/bush_medit_la", "props/flora/bush_medit_la_lush", "props/flora/bush_medit_me_lush", "props/flora/bush_medit_sm", "props/flora/bush_medit_sm_lush", "props/flora/bush_tempe_la_lush" ].map(actorTemplate); const aBushesCity = [ "props/flora/bush_dry_a", "props/flora/bush_medit_la_dry", "props/flora/bush_medit_me_dry", "props/flora/bush_medit_sm", "props/flora/bush_medit_sm_dry", ].map(actorTemplate); const aBushesDesert = [ "props/flora/bush_tempe_me_dry", "props/flora/grass_soft_dry_large_tall", "props/flora/grass_soft_dry_small_tall" ].map(actorTemplate).concat(aBushesCity); const aWaterDecoratives = ["props/flora/reeds_pond_lush_a"].map(actorTemplate); const pForestPalms = [ tForestFloorFertile, ...oPalms.map(tree => tForestFloorFertile + TERRAIN_SEPARATOR + tree), tForestFloorFertile]; const heightScale = num => num * g_MapSettings.Size / 320; const minHeightSource = 3; const maxHeightSource = 800; const g_Map = new RandomMap(0, tSand); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); const mapBounds = g_Map.getBounds(); const numPlayers = getNumPlayers(); const clHill = g_Map.createTileClass(); const clCliff = g_Map.createTileClass(); const clDesert = g_Map.createTileClass(); const clFertileLand = g_Map.createTileClass(); const clWater = g_Map.createTileClass(); const clIrrigationCanal = g_Map.createTileClass(); const clPassage = g_Map.createTileClass(); const clPlayer = g_Map.createTileClass(); const clBaseResource = g_Map.createTileClass(); const clFood = g_Map.createTileClass(); const clForest = g_Map.createTileClass(); const clRock = g_Map.createTileClass(); const clMetal = g_Map.createTileClass(); const clTreasure = g_Map.createTileClass(); const clCity = g_Map.createTileClass(); const clPath = g_Map.createTileClass(); const clPathStatues = g_Map.createTileClass(); const clPathCrossing = g_Map.createTileClass(); const clStatue = g_Map.createTileClass(); const clWall = g_Map.createTileClass(); const clGate = g_Map.createTileClass(); const clRoad = g_Map.createTileClass(); const clTriggerPointCityPath = g_Map.createTileClass(); const clTriggerPointMap = g_Map.createTileClass(); const clSoldier = g_Map.createTileClass(); const clTower = g_Map.createTileClass(); const clFortress = g_Map.createTileClass(); const clTemple = g_Map.createTileClass(); const clRitualPlace = g_Map.createTileClass(); const clPyramid = g_Map.createTileClass(); const clHouse = g_Map.createTileClass(); const clForge = g_Map.createTileClass(); const clStable = g_Map.createTileClass(); const clElephantStable = g_Map.createTileClass(); const clCivicCenter = g_Map.createTileClass(); const clBarracks = g_Map.createTileClass(); const clBlemmyeCamp = g_Map.createTileClass(); const clNobaCamp = g_Map.createTileClass(); const clMarket = g_Map.createTileClass(); const clDecorative = g_Map.createTileClass(); const riverAngle = 0.05 * Math.PI; const hillRadius = scaleByMapSize(40, 120); const positionPyramids = new Vector2D(fractionToTiles(0.15), fractionToTiles(0.75)); const pathWidth = 4; const pathWidthCenter = 10; const pathWidthSecondary = 6; const placeNapataWall = mapSize < 192 || getDifficulty() < 2 ? false : getDifficulty() < 3 ? "napata_palisade" : "napata_wall"; const layoutFertileLandTextures = [ { "left": fractionToTiles(0), "right": fractionToTiles(0.04), "terrain": createTerrain(tGrassTransition1), "tileClass": clFertileLand }, { "left": fractionToTiles(0.04), "right": fractionToTiles(0.08), "terrain": createTerrain(tGrassTransition2), "tileClass": clDesert } ]; var layoutKushTemples = [ ...new Array(2).fill(0).map((v, i) => ({ "template": oTempleApedemak, "pathOffset": new Vector2D(0, 9), "minMapSize": i == 0 ? 320 : 0 })), { "template": oTempleAmun, "pathOffset": new Vector2D(0, 12), "minMapSize": 256 }, { "template": oWonderPtol, "pathOffset": new Vector2D(0, scaleByMapSize(9, 14)), "minMapSize": 0 }, { "template": oTempleAmun, "pathOffset": new Vector2D(0, 12), "minMapSize": 256 }, ...new Array(2).fill(0).map((v, i) => ({ "template": oTempleApedemak, "pathOffset": new Vector2D(0, 9), "minMapSize": i == 0 ? 320 : 0 })) ].filter(temple => mapSize >= temple.minMapSize); /** * The buildings are set as uncapturable, otherwise the player would gain the buildings via root territory and can delete them without effort. * Keep the entire city uncapturable as a consistent property of the city. */ const layoutKushCity = [ { "templateName": "uncapturable|" + oHouse, "difficulty": "Very Easy", "painters": new TileClassPainter(clHouse) }, { "templateName": oFortress, "difficulty": "Medium", "constraints": [avoidClasses(clFortress, 25), new NearTileClassConstraint(clPath, 8)], "painters": new TileClassPainter(clFortress) }, { "templateName": oCivicCenter, "difficulty": "Easy", "constraints": [avoidClasses(clCivicCenter, 60), new NearTileClassConstraint(clPath, 8)], "painters": new TileClassPainter(clCivicCenter) }, { "templateName": oElephantStable, "difficulty": "Easy", "constraints": avoidClasses(clElephantStable, 10), "painters": new TileClassPainter(clElephantStable) }, { "templateName": oStable, "difficulty": "Easy", "constraints": avoidClasses(clStable, 20), "painters": new TileClassPainter(clStable) }, { "templateName": oBarracks, "difficulty": "Easy", "constraints": avoidClasses(clBarracks, 12), "painters": new TileClassPainter(clBarracks) }, { "templateName": oTower, "difficulty": "Easy", "constraints": avoidClasses(clTower, 17), "painters": new TileClassPainter(clTower) }, { "templateName": "uncapturable|" + oMarket, "difficulty": "Very Easy", "constraints": avoidClasses(clMarket, 15), "painters": new TileClassPainter(clMarket) }, { "templateName": "uncapturable|" + oForge, "difficulty": "Very Easy", "constraints": avoidClasses(clForge, 30), "painters": new TileClassPainter(clForge) }, { "templateName": oNobaCamp, "difficulty": "Easy", "constraints": avoidClasses(clNobaCamp, 30), "painters": new TileClassPainter(clNobaCamp) }, { "templateName": oBlemmyeCamp, "difficulty": "Easy", "constraints": avoidClasses(clBlemmyeCamp, 30), "painters": new TileClassPainter(clBlemmyeCamp) } ].filter(building => getDifficulty() >= getDifficulties().find(difficulty => difficulty.Name == building.difficulty).Difficulty); g_WallStyles.napata_wall = { "short": readyWallElement("uncapturable|" + oWallMedium), "medium": readyWallElement("uncapturable|" + oWallMedium), "tower": readyWallElement("uncapturable|" + oWallTower), "gate": readyWallElement("uncapturable|" + oWallGate), "overlap": 0.05 }; g_WallStyles.napata_palisade = { "short": readyWallElement("uncapturable|" + oPalisadeMedium), "medium": readyWallElement("uncapturable|" + oPalisadeMedium), "tower": readyWallElement("uncapturable|" + oPalisadeTower), "gate": readyWallElement("uncapturable|" + oPalisadeGate), "overlap": 0.05 }; Engine.SetProgress(10); g_Map.log("Loading hill heightmap"); createArea( new MapBoundsPlacer(), new HeightmapPainter( translateHeightmap( new Vector2D(-12, scaleByMapSize(-12, -25)), undefined, convertHeightmap1Dto2D(Engine.LoadMapTerrain("maps/random/jebel_barkal.pmp").height)), minHeightSource, maxHeightSource)); const heightDesert = g_Map.getHeight(mapCenter); const heightFertileLand = heightDesert - heightScale(2); const heightShoreline = heightFertileLand - heightScale(0.5); const heightWaterLevel = heightFertileLand - heightScale(3); const heightPassage = heightWaterLevel - heightScale(1.5); const heightIrrigationCanal = heightWaterLevel - heightScale(4); const heightSeaGround = heightWaterLevel - heightScale(8); const heightHill = heightDesert + heightScale(4); const heightHilltop = heightHill + heightScale(90); const heightHillArchers = (heightHilltop + heightHill) / 2; const heightOffsetPath = heightScale(-2.5); const heightOffsetRoad = heightScale(-1.5); const heightOffsetWalls = heightScale(2.5); const heightOffsetStatue = heightScale(2.5); g_Map.log("Flattening land"); createArea( new MapBoundsPlacer(), new ElevationPainter(heightDesert), new HeightConstraint(-Infinity, heightDesert)); // Fertile land var widthFertileLand = fractionToTiles(0.33); paintRiver({ "parallel": true, "start": new Vector2D(mapBounds.left, mapBounds.bottom).rotateAround(-riverAngle, mapCenter), "end": new Vector2D(mapBounds.right, mapBounds.bottom).rotateAround(-riverAngle, mapCenter), "width": 2 * widthFertileLand, "fadeDist": 8, "deviation": 0, "heightLand": heightDesert, "heightRiverbed": heightFertileLand, "meanderShort": 40, "meanderLong": 0, "waterFunc": (position, height, riverFraction) => { createTerrain(tGrass).place(position); clFertileLand.add(position); }, "landFunc": (position, shoreDist1, shoreDist2) => { for (let riv of layoutFertileLandTextures) if (riv.left < +shoreDist1 && +shoreDist1 < riv.right || riv.left < -shoreDist2 && -shoreDist2 < riv.right) { riv.tileClass.add(position); riv.terrain.place(position); } } }); // Nile paintRiver({ "parallel": true, "start": new Vector2D(mapBounds.left, mapBounds.bottom).rotateAround(-riverAngle, mapCenter), "end": new Vector2D(mapBounds.right, mapBounds.bottom).rotateAround(-riverAngle, mapCenter), "width": fractionToTiles(0.2), "fadeDist": 4, "deviation": 0, "heightLand": heightFertileLand, "heightRiverbed": heightSeaGround, "meanderShort": 40, "meanderLong": 0 }); Engine.SetProgress(30); g_Map.log("Computing player locations"); const playerIDs = sortAllPlayers(); const playerPosition = playerPlacementArcs( playerIDs, mapCenter, fractionToTiles(0.38), riverAngle - 0.5 * Math.PI, 0.05 * Math.PI, 0.55 * Math.PI); if (!isNomad()) { g_Map.log("Marking player positions"); for (let position of playerPosition) addCivicCenterAreaToClass(position, clPlayer); } g_Map.log("Marking water"); createArea( new MapBoundsPlacer(), [ new TileClassPainter(clWater), new TileClassUnPainter(clFertileLand) ], new HeightConstraint(-Infinity, heightWaterLevel)); g_Map.log("Marking desert"); const avoidWater = new StaticConstraint(avoidClasses(clWater, 0)); createArea( new MapBoundsPlacer(), new TileClassPainter(clDesert), [ new HeightConstraint(-Infinity, heightHill), avoidWater, avoidClasses(clFertileLand, 0) ]); const stayDesert = new StaticConstraint(stayClasses(clDesert, 0)); const stayFertileLand = new StaticConstraint(stayClasses(clFertileLand, 0)); g_Map.log("Finding possible irrigation canal locations"); var irrigationCanalAreas = []; for (let i = 0; i < 30; ++i) { let x = fractionToTiles(randFloat(0, 1)); irrigationCanalAreas.push( createArea( new PathPlacer( new Vector2D(x, mapBounds.bottom).rotateAround(-riverAngle, mapCenter), new Vector2D(x, mapBounds.top).rotateAround(-riverAngle, mapCenter), 3, 0, 10, 0.1, 0.01, Infinity), undefined, avoidClasses(clDesert, 2))); } g_Map.log("Creating irrigation canals"); var irrigationCanalLocations = []; for (let area of irrigationCanalAreas) { if (!area.getPoints().length || area.getPoints().some(point => !avoidClasses(clPlayer, scaleByMapSize(8, 13), clIrrigationCanal, scaleByMapSize(15, 25)).allows(point))) continue; irrigationCanalLocations.push(pickRandom(area.getPoints()).clone().rotateAround(riverAngle, mapCenter).x); createArea( new MapBoundsPlacer(), [ new SmoothElevationPainter(ELEVATION_SET, heightIrrigationCanal, 1), new TileClassPainter(clIrrigationCanal) ], [new StayAreasConstraint([area]), new HeightConstraint(heightIrrigationCanal, heightDesert)]); } g_Map.log("Creating passages"); var previousPassageY = randIntInclusive(0, widthFertileLand); var areasPassages = []; irrigationCanalLocations.sort((a, b) => a - b); for (let i = 0; i < irrigationCanalLocations.length; ++i) { let previous = i == 0 ? mapBounds.left : irrigationCanalLocations[i - 1]; let next = i == irrigationCanalLocations.length - 1 ? mapBounds.right : irrigationCanalLocations[i + 1]; let x1 = (irrigationCanalLocations[i] + previous) / 2; let x2 = (irrigationCanalLocations[i] + next) / 2; let y; // The passages should be at different locations, so that enemies can't attack each other easily for (let tries = 0; tries < 100; ++tries) { y = (previousPassageY + randIntInclusive(0.2 * widthFertileLand, 0.8 * widthFertileLand)) % widthFertileLand; let pos = new Vector2D((x1 + x2) / 2, y).rotateAround(-riverAngle, mapCenter).round(); if (g_Map.validTilePassable(new Vector2D(pos.x, pos.y)) && avoidClasses(clDesert, 12).allows(pos) && new HeightConstraint(heightIrrigationCanal, heightFertileLand).allows(pos)) break; } let area = createArea( new PathPlacer( new Vector2D(x1, y).rotateAround(-riverAngle, mapCenter), new Vector2D(x2, y).rotateAround(-riverAngle, mapCenter), 10, 0, 1, 0, 0, Infinity), [ new ElevationPainter(heightPassage), new TileClassPainter(clPassage) ], [ new HeightConstraint(-Infinity, heightPassage), stayClasses(clFertileLand, 2) ]); if (!area || !area.getPoints().length) continue; previousPassageY = y; areasPassages.push(area); } Engine.SetProgress(40); g_Map.log("Marking hill"); createArea( new MapBoundsPlacer(), new TileClassPainter(clHill), new HeightConstraint(heightHill, Infinity)); g_Map.log("Marking water"); const areaWater = createArea( new MapBoundsPlacer(), new TileClassPainter(clWater), new HeightConstraint(-Infinity, heightWaterLevel)); g_Map.log("Painting water and shoreline"); createArea( new MapBoundsPlacer(), new TerrainPainter(tWater), new HeightConstraint(-Infinity, heightShoreline)); g_Map.log("Painting hill"); const areaHill = createArea( new MapBoundsPlacer(), new TerrainPainter(tHillGround), new HeightConstraint(heightHill, Infinity)); g_Map.log("Painting hilltop"); const areaHilltop = createArea( new MapBoundsPlacer(), new TerrainPainter(tHilltop), [ new HeightConstraint(heightHilltop, Infinity), new SlopeConstraint(-Infinity, 2) ]); Engine.SetProgress(50); for (let i = 0; i < numPlayers; ++i) { let isDesert = clDesert.has(playerPosition[i]); placePlayerBase({ "playerID": playerIDs[i], "playerPosition": playerPosition[i], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "baseResourceConstraint": avoidClasses(clPlayer, 4, clWater, 4), "Walls": mapSize <= 256 || getDifficulty() >= 3 ? "towers" : "walls", "CityPatch": { "outerTerrain": isDesert ? tRoadDesert : tRoadFertileLand, "innerTerrain": isDesert ? tRoadDesert : tRoadFertileLand }, - "Chicken": { + "StartingAnimal": { "template": oGazelle, "distance": 15, "minGroupDistance": 2, "maxGroupDistance": 4, "minGroupCount": 2, "maxGroupCount": 3 }, "Berries": { "template": isDesert ? oBerryBushDesert : oBerryBushGrapes }, "Mines": { "types": [ { "template": isDesert ? oMetalLargeDesert : oMetalLargeFertileLand }, { "template": isDesert ? oStoneLargeDesert : oStoneLargeFertileLand } ] }, "Trees": { "template": isDesert ? oAcacia : pickRandom(oPalms), "count": isDesert ? scaleByMapSize(5, 10) : scaleByMapSize(15, 30) }, "Treasures": { "types": [ { "template": oWoodTreasure, "count": isDesert ? 4 : 0 }, { "template": oStoneTreasure, "count": isDesert ? 1 : 0 }, { "template": oMetalTreasure, "count": isDesert ? 1 : 0 } ] }, "Decoratives": { "template": isDesert ? aRock : pickRandom(aBushesFertileLand) } }); } g_Map.log("Placing pyramids"); const areaPyramids = createArea(new DiskPlacer(scaleByMapSize(5, 14), positionPyramids)); // Retry loops are needed due to the self-avoidance createObjectGroupsByAreas( new SimpleGroup( [new RandomObject( [oPyramidLarge, oPyramidSmall], scaleByMapSize(1, 6), scaleByMapSize(2, 8), scaleByMapSize(6, 8), scaleByMapSize(6, 14), Math.PI * 1.35, Math.PI * 1.5, scaleByMapSize(6, 8))], true, clPyramid), 0, undefined, 1, 50, [areaPyramids]); Engine.SetProgress(60); // The city is a circle segment of this maximum size g_Map.log("Computing city grid"); var gridCenter = new Vector2D(0, fractionToTiles(0.3)).rotate(-riverAngle).add(mapCenter).round(); var gridMaxAngle = Math.min(scaleByMapSize(1/3, 1), 2/3) * Math.PI; var gridStartAngle = -Math.PI / 2 -gridMaxAngle / 2 + riverAngle; var gridRadius = y => hillRadius + 18 * y; var gridPointsX = layoutKushTemples.length; var gridPointsY = Math.floor(scaleByMapSize(2, 5)); var gridPointXCenter = Math.floor(gridPointsX / 2); var gridPointYCenter = Math.floor(gridPointsY / 2); // Maps from grid position to map position var cityGridPosition = []; var cityGridAngle = []; for (let y = 0; y < gridPointsY; ++y) [cityGridPosition[y], cityGridAngle[y]] = distributePointsOnCircularSegment( gridPointsX, gridMaxAngle, gridStartAngle, gridRadius(y), gridCenter); g_Map.log("Marking city path crossings"); for (let y in cityGridPosition) for (let x in cityGridPosition[y]) { cityGridPosition[y][x].round(); createArea( new DiskPlacer(pathWidth, cityGridPosition[y][x]), [ new TileClassPainter(clPath), new TileClassPainter(clPathCrossing) ]); } g_Map.log("Marking horizontal city paths"); var areasCityPaths = []; for (let y = 0; y < gridPointsY; ++y) for (let x = 1; x < gridPointsX; ++x) { let width = y == gridPointYCenter ? pathWidthSecondary : pathWidth; areasCityPaths.push( createArea( new PathPlacer(cityGridPosition[y][x - 1], cityGridPosition[y][x], width, 0, 8, 0, 0, Infinity), new TileClassPainter(clPath))); } g_Map.log("Marking vertical city paths"); for (let y = 1; y < gridPointsY; ++y) for (let x = 0; x < gridPointsX; ++x) { let width = Math.abs(x - gridPointXCenter) == 0 ? pathWidthCenter : Math.abs(x - gridPointXCenter) == 1 ? pathWidthSecondary : pathWidth; areasCityPaths.push( createArea( new PathPlacer(cityGridPosition[y - 1][x], cityGridPosition[y][x], width, 0, 8, 0, 0, Infinity), new TileClassPainter(clPath))); } Engine.SetProgress(70); g_Map.log("Placing kushite temples"); var entitiesTemples = []; var templePosition = []; for (let i = 0; i < layoutKushTemples.length; ++i) { let x = i + (gridPointsX - layoutKushTemples.length) / 2; templePosition[i] = Vector2D.add(cityGridPosition[0][x], layoutKushTemples[i].pathOffset.rotate(-Math.PI / 2 - cityGridAngle[0][x])); entitiesTemples[i] = g_Map.placeEntityPassable(layoutKushTemples[i].template, 0, templePosition[i], cityGridAngle[0][x]); } g_Map.log("Marking temple area"); createArea( new EntitiesObstructionPlacer(entitiesTemples, 0, Infinity), new TileClassPainter(clTemple)); g_Map.log("Smoothing temple ground"); createArea( new MapBoundsPlacer(), new ElevationBlendingPainter(heightDesert, 0.8), new NearTileClassConstraint(clTemple, 0)); g_Map.log("Painting cliffs"); createArea( new MapBoundsPlacer(), [ new TerrainPainter(tHillCliff), new TileClassPainter(clCliff) ], [ stayClasses(clHill, 0), new SlopeConstraint(2, Infinity) ]); g_Map.log("Painting temple ground"); createArea( new MapBoundsPlacer(), new TerrainPainter(tPathWild), [ new NearTileClassConstraint(clTemple, 1), avoidClasses(clPath, 0, clCliff, 1) ]); g_Map.log("Placing lion statues in the central path"); var statueCount = scaleByMapSize(10, 40); var centralPathStart = cityGridPosition[0][gridPointXCenter]; var centralPathLength = centralPathStart.distanceTo(cityGridPosition[gridPointsY - 1][gridPointXCenter]); var centralPathAngle = cityGridAngle[0][gridPointXCenter]; for (let i = 0; i < 2; ++i) for (let stat = 0; stat < statueCount; ++stat) { let start = new Vector2D(0, pathWidthCenter * 3/4 * (i - 0.5)).rotate(centralPathAngle).add(centralPathStart); let position = new Vector2D(centralPathLength, 0).mult(stat / statueCount).rotate(-centralPathAngle).add(start).add(new Vector2D(0.5, 0.5)); if (!avoidClasses(clPathCrossing, 2).allows(position)) continue; g_Map.placeEntityPassable(pickRandom(aStatues), 0, position, centralPathAngle - Math.PI * (i + 0.5)); clPathStatues.add(position.round()); } g_Map.log("Placing guardian infantry in the central path"); var centralChampionsCount = scaleByMapSize(2, 40); for (let i = 0; i < 2; ++i) for (let champ = 0; champ < centralChampionsCount; ++champ) { let start = new Vector2D(0, pathWidthCenter * 1/2 * (i - 0.5)).rotate(-centralPathAngle).add(centralPathStart); let position = new Vector2D(centralPathLength, 0).mult(champ / centralChampionsCount).rotate(-centralPathAngle).add(start).add(new Vector2D(0.5, 0.5)); if (!avoidClasses(clPathCrossing, 2).allows(position)) continue; g_Map.placeEntityPassable(pickRandom(oKushChampions), 0, position, centralPathAngle - Math.PI * (i - 0.5)); clPathStatues.add(position.round()); } g_Map.log("Placing kushite statues in the secondary paths"); for (let x of [gridPointXCenter - 1, gridPointXCenter + 1]) { g_Map.placeEntityAnywhere(aStatueKush, 0, cityGridPosition[gridPointYCenter][x], cityGridAngle[gridPointYCenter][x]); clPathStatues.add(cityGridPosition[gridPointYCenter][x]); } g_Map.log("Creating ritual place near the wonder"); var ritualPosition = Vector2D.average([ templePosition[Math.floor(templePosition.length / 2) - 1], templePosition[Math.ceil(templePosition.length / 2) - 1], cityGridPosition[0][gridPointXCenter], cityGridPosition[0][gridPointXCenter - 1] ]).round(); var ritualAngle = (cityGridAngle[0][gridPointXCenter] + cityGridAngle[0][gridPointXCenter - 1]) / 2 + Math.PI / 2; g_Map.placeEntityPassable(aStatueKush, 0, ritualPosition, ritualAngle - Math.PI / 2); createArea( new DiskPlacer(scaleByMapSize(4, 6), ritualPosition), [ new LayeredPainter([tPathWild, tPath], [1]), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetPath, 2), new TileClassPainter(clRitualPlace) ], avoidClasses(clCliff, 1)); createArea( new DiskPlacer(0, new Vector2D(-1, -1).add(ritualPosition)), new ElevationPainter(heightDesert + heightOffsetStatue)); g_Map.log("Placing healers at the ritual place"); var [healerPosition, healerAngle] = distributePointsOnCircularSegment( scaleByMapSize(2, 10), Math.PI, ritualAngle, scaleByMapSize(2, 3), ritualPosition); for (let i = 0; i < healerPosition.length; ++i) g_Map.placeEntityPassable(oKushHealer, 0, healerPosition[i], healerAngle[i] + Math.PI); g_Map.log("Placing statues at the ritual place"); var [statuePosition, statueAngle] = distributePointsOnCircularSegment( scaleByMapSize(4, 8), Math.PI, ritualAngle, scaleByMapSize(3, 4), ritualPosition); for (let i = 0; i < statuePosition.length; ++i) g_Map.placeEntityPassable(pickRandom(aStatues), 0, statuePosition[i], statueAngle[i] + Math.PI); g_Map.log("Placing palms at the ritual place"); var palmPosition = distributePointsOnCircularSegment( scaleByMapSize(6, 16), Math.PI, ritualAngle, scaleByMapSize(4, 5), ritualPosition)[0]; for (let i = 0; i < palmPosition.length; ++i) if (avoidClasses(clTemple, 1).allows(palmPosition[i])) g_Map.placeEntityPassable(oPalmPath, 0, palmPosition[i], randomAngle()); g_Map.log("Painting city paths"); var areaPaths = createArea( new MapBoundsPlacer(), [ new LayeredPainter([tPathWild, tPath], [1]), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetPath, 1) ], stayClasses(clPath, 0)); g_Map.log("Placing triggerpoints on city paths"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(oTriggerPointCityPath, 1, 1, 0, 0)], true, clTriggerPointCityPath), 0, [avoidClasses(clTriggerPointCityPath, 8), stayClasses(clPathCrossing, 2)], scaleByMapSize(20, 100), 30, [areaPaths]); g_Map.log("Placing city districts"); for (let y = 1; y < gridPointsY; ++y) for (let x = 1; x < gridPointsX; ++x) createArea( new ConvexPolygonPlacer([cityGridPosition[y - 1][x - 1], cityGridPosition[y - 1][x], cityGridPosition[y][x - 1], cityGridPosition[y][x]], Infinity), [ new TerrainPainter(tRoadDesert), new CityPainter(layoutKushCity, (-cityGridAngle[y][x - 1] - cityGridAngle[y][x]) / 2, 0), new TileClassPainter(clCity) ], new StaticConstraint(avoidClasses(clPath, 0))); var entitiesGates; if (placeNapataWall) { g_Map.log("Placing front walls"); let wallGridMaxAngleSummand = scaleByMapSize(0.04, 0.03) * Math.PI; let wallGridStartAngle = gridStartAngle - wallGridMaxAngleSummand / 2; let wallGridRadiusFront = gridRadius(gridPointsY - 1) + pathWidth - 1; let wallGridMaxAngleFront = gridMaxAngle + wallGridMaxAngleSummand; let entitiesWalls = placeCircularWall( gridCenter, wallGridRadiusFront, ["tower", "short", "tower", "gate", "tower", "medium", "tower", "short"], placeNapataWall, 0, wallGridStartAngle, wallGridMaxAngleFront, true, 0, 0); g_Map.log("Placing side and back walls"); let wallGridRadiusBack = hillRadius - scaleByMapSize(15, 25); let wallGridMaxAngleBack = gridMaxAngle + wallGridMaxAngleSummand; let wallGridPositionFront = distributePointsOnCircularSegment(gridPointsX, wallGridMaxAngleBack, wallGridStartAngle, wallGridRadiusFront, gridCenter)[0]; let wallGridPositionBack = distributePointsOnCircularSegment(gridPointsX, wallGridMaxAngleBack, wallGridStartAngle, wallGridRadiusBack, gridCenter)[0]; let wallGridPosition = [wallGridPositionFront[0], ...wallGridPositionBack, wallGridPositionFront[wallGridPositionFront.length - 1]]; for (let x = 1; x < wallGridPosition.length; ++x) entitiesWalls = entitiesWalls.concat( placeLinearWall( wallGridPosition[x - 1], wallGridPosition[x], ["tower", "gate", "tower", "short", "tower", "short", "tower"], placeNapataWall, 0, false, avoidClasses(clHill, 0, clTemple, 0))); g_Map.log("Marking walls"); createArea( new EntitiesObstructionPlacer(entitiesWalls, 0, Infinity), new TileClassPainter(clWall)); g_Map.log("Marking gates"); entitiesGates = entitiesWalls.filter(entity => entity.templateName.endsWith(oWallGate)); createArea( new EntitiesObstructionPlacer(entitiesGates, 0, Infinity), new TileClassPainter(clGate)); g_Map.log("Painting wall terrain"); createArea( new MapBoundsPlacer(), [ new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetWalls, 2), new TerrainPainter(tPathWild) ], [ new NearTileClassConstraint(clWall, 1), avoidClasses(clCliff, 0) ]); g_Map.log("Painting gate terrain"); for (let entity of entitiesGates) createArea( new DiskPlacer(pathWidth, entity.GetPosition2D()), [ new LayeredPainter([tPathWild, tPath], [1]), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetPath, 2), ], [ avoidClasses(clCliff, 0, clPath, 0, clCity, 0), new NearTileClassConstraint(clPath, pathWidth + 1) ]); } Engine.SetProgress(70); g_Map.log("Finding road starting points"); var roadStartLocations = shuffleArray( entitiesGates ? entitiesGates.map(entity => entity.GetPosition2D()) : [ ...cityGridPosition.map(gridPos => gridPos[0]), ...cityGridPosition.map(gridPos => gridPos[gridPos.length - 1]), ...cityGridPosition[cityGridPosition.length - 1] ]); g_Map.log("Finding possible roads"); var roadConstraint = new StaticConstraint( [ stayDesert, avoidClasses(clHill, 0, clCity, 0, clPyramid, 6, clPlayer, 16) ]); var areaCityPaths = new Area(areasCityPaths.reduce((points, area) => points.concat(area.getPoints()), [])); var areaRoads = []; for (let roadStart of roadStartLocations) { if (areaRoads.length >= scaleByMapSize(2, 5)) break; let closestPoint = areaCityPaths.getClosestPointTo(roadStart); roadConstraint = new StaticConstraint([roadConstraint, avoidClasses(clRoad, 20)]); for (let tries = 0; tries < 30; ++tries) { let area = createArea( new PathPlacer( Vector2D.add(closestPoint, new Vector2D(0, 3/4 * mapSize).rotate(closestPoint.angleTo(roadStart))), roadStart, scaleByMapSize(5, 3), 0.1, 5, 0.5, 0, 0), new TileClassPainter(clRoad), roadConstraint); if (area && area.getPoints().length) { areaRoads.push(area); break; } } } g_Map.log("Painting roads"); createArea( new MapBoundsPlacer(), [ new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetRoad, 1), new LayeredPainter([tPathWild, tPath], [1]), ], [stayClasses(clRoad, 0), avoidClasses(clPath, 0)]); g_Map.log("Marking road palm area"); var areaRoadPalms = createArea( new MapBoundsPlacer(), undefined, [ new NearTileClassConstraint(clRoad, 1), avoidClasses(clRoad, 0, clPath, 1, clWall, 4, clGate, 4) ]); if (areaRoadPalms && areaRoadPalms.getPoints().length) { g_Map.log("Placing road palms"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(oPalmPath, 1, 1, 0, 0)], true, clForest), 0, avoidClasses(clForest, 2, clGate, 7), scaleByMapSize(40, 250), 20, [areaRoadPalms]); g_Map.log("Placing road bushes"); createObjectGroupsByAreas( new SimpleGroup([new RandomObject(aBushesCity, 1, 1, 0, 0)], true, clForest), 0, avoidClasses(clForest, 1), scaleByMapSize(40, 200), 20, [areaRoadPalms]); } Engine.SetProgress(75); g_Map.log("Marking city bush area"); var areaCityBushes = createArea( new MapBoundsPlacer(), undefined, [ new NearTileClassConstraint(clPath, 1), avoidClasses( clPath, 0, clRoad, 0, clPyramid, 20, clRitualPlace, 8, clTemple, 3, clWall, 3, clTower, 1, clFortress, 1, clHouse, 1, clForge, 1, clElephantStable, 1, clStable, 1, clCivicCenter, 1, clBarracks, 1, clBlemmyeCamp, 1, clNobaCamp, 1, clMarket, 1) ]); g_Map.log("Marking city palm area"); var areaCityPalms = createArea( new MapBoundsPlacer(), undefined, [ new StayAreasConstraint([areaCityBushes]), avoidClasses(clElephantStable, 3) ]); g_Map.log("Placing city palms"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(aPalmPath, 1, 1, 0, 0)], true, clForest), 0, avoidClasses(clForest, 3), scaleByMapSize(40, 400), 15, [areaCityPalms]); g_Map.log("Placing city bushes"); createObjectGroupsByAreas( new SimpleGroup([new RandomObject(aBushesCity, 1, 1, 0, 0)], true, clForest), 0, avoidClasses(clForest, 1), scaleByMapSize(20, 200), 15, [areaCityBushes]); if (placeNapataWall) { g_Map.log("Marking wall palm area"); var areaWallPalms = createArea( new MapBoundsPlacer(), undefined, new StaticConstraint([ new NearTileClassConstraint(clWall, 2), avoidClasses(clPath, 1, clRoad, 1, clWall, 1, clGate, 3, clTemple, 2, clHill, 6) ])); g_Map.log("Placing wall palms"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(oPalmPath, 1, 1, 0, 0)], true, clForest), 0, avoidClasses(clForest, 2), scaleByMapSize(40, 250), 50, [areaWallPalms]); } createBumps( new StaticConstraint(avoidClasses(clPlayer, 6, clCity, 0, clWater, 2, clHill, 0, clPath, 0, clRoad, 0, clTemple, 4, clPyramid, 8, clWall, 0, clGate, 4)), scaleByMapSize(30, 300), 1, 8, 4, 0, 3); Engine.SetProgress(80); g_Map.log("Setting up common constraints and areas"); const nearWater = new NearTileClassConstraint(clWater, 3); var avoidCollisionsNomad = new AndConstraint( [ new StaticConstraint(avoidClasses( clCliff, 0, clHill, 0, clPlayer, 15, clWater, 1, clPath, 2, clRitualPlace, 10, clTemple, 4, clPyramid, 7, clCity, 4, clWall, 4, clGate, 8)), avoidClasses(clForest, 1, clRock, 4, clMetal, 4, clFood, 2, clSoldier, 1, clTreasure, 1) ]); var avoidCollisions = new AndConstraint( [ avoidCollisionsNomad, new StaticConstraint(avoidClasses(clRoad, 6, clFood, 6)) ]); const areaDesert = createArea(new MapBoundsPlacer(), undefined, stayDesert); const areaFertileLand = createArea(new MapBoundsPlacer(), undefined, stayFertileLand); createForests( [tForestFloorFertile, tForestFloorFertile, tForestFloorFertile, pForestPalms, pForestPalms], [stayFertileLand, avoidClasses(clForest, 15), new StaticConstraint([avoidClasses(clWater, 2), avoidCollisions])], clForest, scaleByMapSize(250, 2000)); g_Map.log("Creating mines"); const avoidCollisionsMines = [ avoidClasses(clRock, 10, clMetal, 10), new StaticConstraint(avoidClasses( clWater, 4, clCliff, 4, clCity, 4, clRitualPlace, 10, clPlayer, 20, clForest, 4, clPyramid, 6, clTemple, 4, clPath, 4, clRoad, 4, clGate, 8)) ]; const mineObjects = (templateSmall, templateLarge) => ({ "large": [ new SimpleObject(templateSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(templateLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4) ], "small": [ new SimpleObject(templateSmall, 3, 4, 1, 3, 0, 2 * Math.PI, 1) ] }); const mineObjectsPerBiome = [ { "desert": mineObjects(oMetalSmallDesert, oMetalLargeDesert), "fertileLand": mineObjects(oMetalSmallFertileLand, oMetalLargeFertileLand), "tileClass": clMetal }, { "desert": mineObjects(oStoneSmallDesert, oStoneLargeDesert), "fertileLand": mineObjects(oStoneSmallFertileLand, oStoneLargeFertileLand), "tileClass": clRock } ]; for (let i = 0; i < scaleByMapSize(6, 22); ++i) { let mineObjectsBiome = pickRandom(mineObjectsPerBiome); for (let i in mineObjectsBiome.desert) createObjectGroupsByAreas( new SimpleGroup(mineObjectsBiome.desert[i], true, mineObjectsBiome.tileClass), 0, avoidCollisionsMines.concat([avoidClasses(clFertileLand, 12, mineObjectsBiome.tileClass, 15)]), 1, 60, [areaDesert]); } for (let i = 0; i < (isNomad() ? scaleByMapSize(6, 16) : scaleByMapSize(0, 8)); ++i) { let mineObjectsBiome = pickRandom(mineObjectsPerBiome); createObjectGroupsByAreas( new SimpleGroup(mineObjectsBiome.fertileLand.small, true, mineObjectsBiome.tileClass), 0, avoidCollisionsMines.concat([avoidClasses(clDesert, 5, clMetal, 15, clRock, 15, mineObjectsBiome.tileClass, 20)]), 1, 80, [areaFertileLand]); } g_Map.log("Placing triggerpoints for attackers"); createObjectGroups( new SimpleGroup([new SimpleObject(oTriggerPointAttackerPatrol, 1, 1, 0, 0)], true, clTriggerPointMap), 0, [avoidClasses(clCity, 8, clCliff, 4, clHill, 4, clWater, 0, clWall, 2, clForest, 1, clRock, 4, clMetal, 4, clTriggerPointMap, 15)], scaleByMapSize(20, 100), 30); g_Map.log("Creating berries"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(oBerryBushGrapes, 4, 6, 1, 2)], true, clFood), 0, avoidCollisions, scaleByMapSize(3, 15), 50, [areaFertileLand]); g_Map.log("Creating rhinos"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(oRhino, 1, 1, 0, 1)], true, clFood), 0, avoidCollisions, scaleByMapSize(2, 10), 50, [areaDesert]); g_Map.log("Creating warthogs"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(oWarthog, 1, 1, 0, 1)], true, clFood), 0, avoidCollisions, scaleByMapSize(2, 10), 50, [areaFertileLand]); g_Map.log("Creating giraffes"); createObjectGroups( new SimpleGroup([new SimpleObject(oGiraffe, 2, 3, 2, 4), new SimpleObject(oGiraffeInfant, 2, 3, 2, 4)], true, clFood), 0, avoidCollisions, scaleByMapSize(2, 10), 50); g_Map.log("Creating gazelles"); createObjectGroups( new SimpleGroup([new SimpleObject(oGazelle, 5, 7, 2, 4)], true, clFood), 0, avoidCollisions, scaleByMapSize(2, 10), 50, [areaDesert]); if (!isNomad()) { g_Map.log("Creating lions"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(oLion, 1, 2, 2, 4), new SimpleObject(oLioness, 2, 3, 2, 4)], true, clFood), 0, [avoidCollisions, avoidClasses(clPlayer, 20)], scaleByMapSize(2, 10), 50, [areaDesert]); } g_Map.log("Creating elephants"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(oElephant, 2, 3, 2, 4), new SimpleObject(oElephantInfant, 2, 3, 2, 4)], true, clFood), 0, avoidCollisions, scaleByMapSize(2, 10), 50, [areaDesert]); g_Map.log("Creating crocodiles"); if (!isNomad()) createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(oCrocodile, 2, 3, 3, 5)], true, clFood), 0, [nearWater, avoidCollisions], scaleByMapSize(1, 6), 50, [areaFertileLand]); Engine.SetProgress(85); g_Map.log("Marking irrigation canal tree area"); var areaIrrigationCanalTrees = createArea( new MapBoundsPlacer(), undefined, [ nearWater, avoidClasses(clPassage, 3), avoidCollisions ]); g_Map.log("Creating irrigation canal trees"); createObjectGroupsByAreas( new SimpleGroup([new RandomObject(oPalms, 1, 1, 1, 1)], true, clForest), 0, avoidClasses(clForest, 1), scaleByMapSize(100, 600), 50, [areaIrrigationCanalTrees]); createStragglerTrees( oPalms, [stayFertileLand, avoidCollisions], clForest, scaleByMapSize(50, 400), 200); createStragglerTrees( [oAcacia], [stayDesert, avoidCollisions], clForest, scaleByMapSize(50, 400), 200); g_Map.log("Placing archer groups on the hilltop"); createObjectGroupsByAreas( new SimpleGroup([new RandomObject([oKushCitizenArcher, oKushChampionArcher], scaleByMapSize(4, 10), scaleByMapSize(6, 20), 1, 4)], true, clSoldier), 0, new StaticConstraint([avoidClasses(clCliff, 1), new NearTileClassConstraint(clCliff, 5)]), scaleByMapSize(1, 5) / 3 * getDifficulty(), 250, [areaHilltop]); g_Map.log("Placing individual archers on the hill"); createObjectGroupsByAreas( new SimpleGroup([new RandomObject([oKushCitizenArcher, oKushChampionArcher], 1, 1, 1, 3)], true, clSoldier), 0, new StaticConstraint([ new HeightConstraint(heightHillArchers, heightHilltop), avoidClasses(clCliff, 1, clSoldier, 1), new NearTileClassConstraint(clCliff, 5) ]), scaleByMapSize(8, 100) / 3 * getDifficulty(), 250, [areaHill]); g_Map.log("Placing siege engines on the hilltop"); createObjectGroupsByAreas( new SimpleGroup([new RandomObject(oPtolSiege, 1, 1, 1, 3)], true, clSoldier), 0, new StaticConstraint([new NearTileClassConstraint(clCliff, 5), avoidClasses(clCliff, 1, clSoldier, 1)]), scaleByMapSize(1, 6) / 3 * getDifficulty(), 250, [areaHilltop]); const avoidCollisionsPyramids = new StaticConstraint([avoidCollisions, new NearTileClassConstraint(clPyramid, 10)]); if (!isNomad()) { g_Map.log("Placing soldiers near pyramids"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(oKushCitizenArcher, 1, 1, 1, 1)], true, clSoldier), 0, avoidCollisionsPyramids, scaleByMapSize(3, 8), 250, [areaPyramids]); g_Map.log("Placing treasures at the pyramid"); createObjectGroupsByAreas( new SimpleGroup([new RandomObject(oTreasuresHill, 1, 1, 2, 2)], true, clTreasure), 0, avoidCollisionsPyramids, scaleByMapSize(1, 10), 250, [areaPyramids]); } g_Map.log("Placing treasures on the hilltop"); createObjectGroupsByAreas( new SimpleGroup([new RandomObject(oTreasuresHill, 1, 1, 2, 2)], true, clTreasure), 0, avoidClasses(clCliff, 1, clTreasure, 1), scaleByMapSize(8, 35), 250, [areaHilltop]); g_Map.log("Placing treasures in the city"); var pathBorderConstraint = new AndConstraint([ new StaticConstraint([new NearTileClassConstraint(clCity, 1)]), avoidClasses(clTreasure, 2, clStatue, 10, clPathStatues, 4, clWall, 2, clForest, 1) ]); createObjectGroupsByAreas( new SimpleGroup([new RandomObject(oTreasuresCity, 1, 1, 0, 2)], true, clTreasure), 0, pathBorderConstraint, scaleByMapSize(2, 60), 500, [areaPaths]); g_Map.log("Placing handcarts on the paths"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(aHandcart, 1, 1, 1, 1)], true, clDecorative), 0, [pathBorderConstraint, avoidClasses(clDecorative, 10)], scaleByMapSize(0, 5), 250, [areaPaths]); g_Map.log("Placing fence in fertile land"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(aPlotFence, 1, 1, 1, 1)], true, clDecorative), 0, new StaticConstraint([avoidCollisions, avoidClasses(clWater, 6, clDecorative, 10)]), scaleByMapSize(1, 10), 250, [areaFertileLand]); g_Map.log("Creating fish"); createObjectGroups( new SimpleGroup([new SimpleObject(oFish, 3, 4, 2, 3)], true, clFood), 0, [new StaticConstraint(stayClasses(clWater, 6)), avoidClasses(clFood, 12)], scaleByMapSize(20, 120), 50); Engine.SetProgress(95); avoidCollisions = new StaticConstraint(avoidCollisions); createDecoration( aBushesDesert.map(bush => [new SimpleObject(bush, 0, 3, 2, 4)]), aBushesDesert.map(bush => scaleByMapSize(20, 120) * randIntInclusive(1, 3)), [stayDesert, avoidCollisions]); createDecoration( aBushesFertileLand.map(bush => [new SimpleObject(bush, 0, 4, 2, 4)]), aBushesFertileLand.map(bush => scaleByMapSize(20, 120) * randIntInclusive(1, 3)), [stayFertileLand, avoidCollisions]); createDecoration( [[new SimpleObject(aRock, 0, 4, 2, 4)]], [[scaleByMapSize(80, 500)]], [stayDesert, avoidCollisions]); createDecoration( aBushesFertileLand.map(bush => [new SimpleObject(bush, 0, 3, 2, 4)]), aBushesFertileLand.map(bush => scaleByMapSize(100, 800)), [new HeightConstraint(heightWaterLevel, heightShoreline), avoidCollisions]); g_Map.log("Creating reeds"); createObjectGroupsByAreas( new SimpleGroup([new RandomObject(aWaterDecoratives, 2, 4, 1, 2)], true), 0, new StaticConstraint(new NearTileClassConstraint(clFertileLand, 4)), scaleByMapSize(50, 400), 20, [areaWater]); g_Map.log("Creating reeds at the irrigation canals"); for (let area of areasPassages) createObjectGroupsByAreas( new SimpleGroup([new RandomObject(aWaterDecoratives, 2, 4, 1, 2)], true), 0, undefined, 15, 20, [area]); g_Map.log("Creating hawk"); for (let i = 0; i < scaleByMapSize(0, 2); ++i) g_Map.placeEntityAnywhere(oHawk, 0, mapCenter, randomAngle()); placePlayersNomad(clPlayer, [avoidClasses(clHill, 15, clSoldier, 20, clCity, 15, clWall, 20), avoidCollisionsNomad]); setWindAngle(-0.43); setWaterHeight(heightWaterLevel + SEA_LEVEL); setWaterTint(0.161, 0.286, 0.353); setWaterColor(0.129, 0.176, 0.259); setWaterWaviness(8); setWaterMurkiness(0.87); setWaterType("lake"); setAmbientColor(0.58, 0.443, 0.353); setSunColor(0.733, 0.746, 0.574); setSunRotation(Math.PI / 2 * randFloat(-1, 1)); setSunElevation(Math.PI / 7); setFogFactor(0); setFogThickness(0); setFogColor(0.69, 0.616, 0.541); setPPEffect("hdr"); setPPContrast(0.67); setPPSaturation(0.42); setPPBloom(0.23); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/latium.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/latium.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/latium.js (revision 26381) @@ -1,469 +1,469 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); const tOceanDepths = "medit_sea_depths"; const tOceanRockDeep = "medit_sea_coral_deep"; const tOceanRockShallow = "medit_rocks_wet"; const tOceanCoral = "medit_sea_coral_plants"; const tBeachWet = "medit_sand_wet"; const tBeachDry = "medit_sand"; const tBeachGrass = "medit_rocks_grass"; const tBeachCliff = "medit_dirt"; const tCity = "medit_city_tile"; const tGrassDry = ["medit_grass_field_brown", "medit_grass_field_dry", "medit_grass_field_b"]; const tGrass = ["medit_grass_field_dry", "medit_grass_field_brown", "medit_grass_field_b"]; const tGrassShrubs = ["medit_grass_shrubs", "medit_grass_flowers"]; const tGrassRock = ["medit_rocks_grass"]; const tDirt = "medit_dirt"; const tDirtCliff = "medit_cliff_italia"; const tGrassCliff = "medit_cliff_italia_grass"; const tCliff = ["medit_cliff_italia", "medit_cliff_italia", "medit_cliff_italia_grass"]; const tForestFloor = "medit_grass_wild"; const oBeech = "gaia/tree/euro_beech"; const oBerryBush = "gaia/fruit/berry_01"; const oCarob = "gaia/tree/carob"; const oCypress1 = "gaia/tree/cypress"; const oCypress2 = "gaia/tree/cypress"; const oLombardyPoplar = "gaia/tree/poplar_lombardy"; const oPalm = "gaia/tree/medit_fan_palm"; const oPine = "gaia/tree/aleppo_pine"; const oDeer = "gaia/fauna_deer"; const oFish = "gaia/fish/generic"; const oSheep = "gaia/fauna_sheep"; const oStoneLarge = "gaia/rock/mediterranean_large"; const oStoneSmall = "gaia/rock/mediterranean_small"; const oMetalLarge = "gaia/ore/mediterranean_large"; const aBushMedDry = "actor|props/flora/bush_medit_me_dry.xml"; const aBushMed = "actor|props/flora/bush_medit_me.xml"; const aBushSmall = "actor|props/flora/bush_medit_sm.xml"; const aBushSmallDry = "actor|props/flora/bush_medit_sm_dry.xml"; const aGrass = "actor|props/flora/grass_soft_large_tall.xml"; const aGrassDry = "actor|props/flora/grass_soft_dry_large_tall.xml"; const aRockLarge = "actor|geology/stone_granite_large.xml"; const aRockMed = "actor|geology/stone_granite_med.xml"; const aRockSmall = "actor|geology/stone_granite_small.xml"; const pPalmForest = [tForestFloor+TERRAIN_SEPARATOR+oPalm, tGrass]; const pPineForest = [tForestFloor+TERRAIN_SEPARATOR+oPine, tGrass]; const pPoplarForest = [tForestFloor+TERRAIN_SEPARATOR+oLombardyPoplar, tGrass]; const pMainForest = [tForestFloor+TERRAIN_SEPARATOR+oCarob, tForestFloor+TERRAIN_SEPARATOR+oBeech, tGrass, tGrass]; const heightSeaGround = -16; const heightLand = 0; const heightPlayer = 5; const heightHill = 12; var g_Map = new RandomMap(heightLand, tGrass); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); const mapBounds = g_Map.getBounds(); var clWater = g_Map.createTileClass(); var clCliff = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clPlayer = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var WATER_WIDTH = 0.1; var horizontal = randBool(); g_Map.log("Creating players"); var startAngle = randBool() ? 0 : Math.PI / 2; var playerPosition = playerPlacementLine(startAngle + Math.PI / 2, mapCenter, fractionToTiles(randFloat(0.42, 0.46))); function distanceToPlayers(x, z) { let r = Infinity; for (let i = 0; i < numPlayers; ++i) { var dx = x - tilesToFraction(playerPosition[i].x); var dz = z - tilesToFraction(playerPosition[i].y); r = Math.min(r, Math.square(dx) + Math.square(dz)); } return Math.sqrt(r); } function playerNearness(x, z) { var d = fractionToTiles(distanceToPlayers(x,z)); if (d < 13) return 0; if (d < 19) return (d-13)/(19-13); return 1; } for (let x of [mapBounds.left, mapBounds.right]) paintRiver({ "parallel": true, "start": new Vector2D(x, mapBounds.top).rotateAround(startAngle, mapCenter), "end": new Vector2D(x, mapBounds.bottom).rotateAround(startAngle, mapCenter), "width": 2 * fractionToTiles(WATER_WIDTH), "fadeDist": 16, "deviation": 0, "heightRiverbed": heightSeaGround, "heightLand": heightLand, "meanderShort": 0, "meanderLong": 0, "waterFunc": (position, height, z) => { clWater.add(position); } }); Engine.SetProgress(10); g_Map.log("Painting elevation"); var noise0 = new Noise2D(scaleByMapSize(4, 16)); var noise1 = new Noise2D(scaleByMapSize(8, 32)); var noise2 = new Noise2D(scaleByMapSize(15, 60)); var noise2a = new Noise2D(scaleByMapSize(20, 80)); var noise2b = new Noise2D(scaleByMapSize(35, 140)); var noise3 = new Noise2D(scaleByMapSize(4, 16)); var noise4 = new Noise2D(scaleByMapSize(6, 24)); var noise5 = new Noise2D(scaleByMapSize(11, 44)); for (var ix = 0; ix <= mapSize; ix++) for (var iz = 0; iz <= mapSize; iz++) { let position = new Vector2D(ix, iz); var x = ix / (mapSize + 1.0); var z = iz / (mapSize + 1.0); var pn = playerNearness(x, z); let c = startAngle ? z : x; let distToWater = clWater.has(position) ? 0 : (0.5 - WATER_WIDTH - Math.abs(c - 0.5)); let h = distToWater ? heightHill * (1 - Math.abs(c - 0.5) / (0.5 - WATER_WIDTH)) : g_Map.getHeight(position); // add some base noise var baseNoise = 16*noise0.get(x,z) + 8*noise1.get(x,z) + 4*noise2.get(x,z) - (16+8+4)/2; if ( baseNoise < 0 ) { baseNoise *= pn; baseNoise *= Math.max(0.1, distToWater / (0.5 - WATER_WIDTH)); } var oldH = h; h += baseNoise; // add some higher-frequency noise on land if ( oldH > 0 ) h += (0.4 * noise2a.get(x,z) + 0.2 * noise2b.get(x,z)) * Math.min(oldH / 10, 1); // create cliff noise if ( h > -10 ) { var cliffNoise = (noise3.get(x,z) + 0.5*noise4.get(x,z)) / 1.5; if (h < 1) { var u = 1 - 0.3*((h-1)/-10); cliffNoise *= u; } cliffNoise += 0.05 * distToWater / (0.5 - WATER_WIDTH); if (cliffNoise > 0.6) { var u = 0.8 * (cliffNoise - 0.6); cliffNoise += u * noise5.get(x,z); cliffNoise /= (1 + u); } cliffNoise -= 0.59; cliffNoise *= pn; if (cliffNoise > 0) h += 19 * Math.min(cliffNoise, 0.045) / 0.045; } g_Map.setHeight(position, h); } Engine.SetProgress(20); g_Map.log("Painting terrain"); var noise6 = new Noise2D(scaleByMapSize(10, 40)); var noise7 = new Noise2D(scaleByMapSize(20, 80)); var noise8 = new Noise2D(scaleByMapSize(13, 52)); var noise9 = new Noise2D(scaleByMapSize(26, 104)); var noise10 = new Noise2D(scaleByMapSize(50, 200)); for (var ix = 0; ix < mapSize; ix++) for (var iz = 0; iz < mapSize; iz++) { let position = new Vector2D(ix, iz); var x = ix / (mapSize + 1.0); var z = iz / (mapSize + 1.0); var pn = playerNearness(x, z); // Compute height difference let minH = +Infinity; let maxH = -Infinity; for (let vertex of g_TileVertices) { let height = g_Map.getHeight(Vector2D.add(position, vertex)); minH = Math.min(minH, height); maxH = Math.max(maxH, height); } var diffH = maxH - minH; // figure out if we're at the top of a cliff using min adjacent height var minAdjHeight = minH; if (maxH > 15) { var maxNx = Math.min(ix + 2, mapSize); var maxNz = Math.min(iz + 2, mapSize); for (let nx = Math.max(ix - 1, 0); nx <= maxNx; ++nx) for (let nz = Math.max(iz - 1, 0); nz <= maxNz; ++nz) minAdjHeight = Math.min(minAdjHeight, g_Map.getHeight(new Vector2D(nx, nz))); } // choose a terrain based on elevation var t = tGrass; // water if (maxH < -12) t = tOceanDepths; else if (maxH < -8.8) t = tOceanRockDeep; else if (maxH < -4.7) t = tOceanCoral; else if (maxH < -2.8) t = tOceanRockShallow; else if (maxH < 0.9 && minH < 0.35) t = tBeachWet; else if (maxH < 1.5 && minH < 0.9) t = tBeachDry; else if (maxH < 2.3 && minH < 1.3) t = tBeachGrass; if (minH < 0) clWater.add(position); // cliffs if (diffH > 2.9 && minH > -7) { t = tCliff; clCliff.add(position); } else if (diffH > 2.5 && minH > -5 || maxH - minAdjHeight > 2.9 && minH > 0) { if (minH < -1) t = tCliff; else if (minH < 0.5) t = tBeachCliff; else t = [tDirtCliff, tGrassCliff, tGrassCliff, tGrassRock, tCliff]; clCliff.add(position); } // Don't place resources onto potentially impassable mountains if (minH >= 20) clCliff.add(position); // forests if (g_Map.getHeight(position) < 11 && diffH < 2 && minH > 1) { var forestNoise = (noise6.get(x,z) + 0.5*noise7.get(x,z)) / 1.5 * pn - 0.59; // Thin out trees a bit if (forestNoise > 0 && randBool()) { if (minH < 11 && minH >= 4) { var typeNoise = noise10.get(x,z); if (typeNoise < 0.43 && forestNoise < 0.05) t = pPoplarForest; else if (typeNoise < 0.63) t = pMainForest; else t = pPineForest; clForest.add(position); } else if (minH < 4) { t = pPalmForest; clForest.add(position); } } } // grass variations if (t == tGrass) { var grassNoise = (noise8.get(x,z) + 0.6*noise9.get(x,z)) / 1.6; if (grassNoise < 0.3) t = (diffH > 1.2) ? tDirtCliff : tDirt; else if (grassNoise < 0.34) { t = (diffH > 1.2) ? tGrassCliff : tGrassDry; if (diffH < 0.5 && randBool(0.02)) g_Map.placeEntityAnywhere(aGrassDry, 0, randomPositionOnTile(position), randomAngle()); } else if (grassNoise > 0.61) { t = (diffH > 1.2 ? tGrassRock : tGrassShrubs); } else if (diffH < 0.5 && randBool(0.02)) g_Map.placeEntityAnywhere(aGrass, 0, randomPositionOnTile(position), randomAngle()); } createTerrain(t).place(position); } Engine.SetProgress(30); placePlayerBases({ "PlayerPlacement": [primeSortAllPlayers(), playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "baseResourceConstraint": avoidClasses(clCliff, 4), "CityPatch": { "radius": 11, "outerTerrain": tGrass, "innerTerrain": tCity, "width": 4, "painters": [ new SmoothElevationPainter(ELEVATION_SET, heightPlayer, 2) ] }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush, "distance": 9 }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oPalm, "count": 5, "minDist": 10, "maxDist": 11 } // No decoratives }); Engine.SetProgress(40); g_Map.log("Creating bushes"); var group = new SimpleGroup( [new SimpleObject(aBushSmall, 0,2, 0,2), new SimpleObject(aBushSmallDry, 0,2, 0,2), new SimpleObject(aBushMed, 0,1, 0,2), new SimpleObject(aBushMedDry, 0,1, 0,2)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 4, clCliff, 2), scaleByMapSize(9, 146), 50 ); Engine.SetProgress(45); g_Map.log("Creating rocks"); group = new SimpleGroup( [new SimpleObject(aRockSmall, 0,3, 0,2), new SimpleObject(aRockMed, 0,2, 0,2), new SimpleObject(aRockLarge, 0,1, 0,2)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 2, clCliff, 1), scaleByMapSize(9, 146), 50 ); Engine.SetProgress(50); g_Map.log("Creating large stone mines"); group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 1, clForest, 4, clPlayer, 40, clRock, 60, clMetal, 10, clCliff, 3), scaleByMapSize(4,16), 100 ); g_Map.log("Creating small stone mines"); group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock); createObjectGroups(group, 0, avoidClasses(clForest, 4, clWater, 1, clPlayer, 40, clRock, 30, clMetal, 10, clCliff, 3), scaleByMapSize(4,16), 100 ); g_Map.log("Creating metal mines"); group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,2)], true, clMetal); createObjectGroups(group, 0, avoidClasses(clForest, 4, clWater, 1, clPlayer, 40, clMetal, 50, clCliff, 3), scaleByMapSize(4,16), 100 ); Engine.SetProgress(60); createStragglerTrees( [oCarob, oBeech, oLombardyPoplar, oLombardyPoplar, oPine], avoidClasses(clWater, 5, clCliff, 4, clForest, 2, clPlayer, 15, clMetal, 6, clRock, 6), clForest, scaleByMapSize(10, 190)); Engine.SetProgress(70); g_Map.log("Creating straggler cypresses"); group = new SimpleGroup( [new SimpleObject(oCypress2, 1,3, 0,3), new SimpleObject(oCypress1, 0,2, 0,2)], true ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 5, clCliff, 4, clForest, 2, clPlayer, 15, clMetal, 6, clRock, 6), scaleByMapSize(5, 75), 50 ); Engine.SetProgress(80); g_Map.log("Creating sheep"); group = new SimpleGroup([new SimpleObject(oSheep, 2,4, 0,2)], true, clFood); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 5, clForest, 2, clCliff, 1, clPlayer, 20, clMetal, 6, clRock, 6, clFood, 8), 3 * numPlayers, 50 ); Engine.SetProgress(85); g_Map.log("Creating fish"); createObjectGroups( new SimpleGroup([new SimpleObject(oFish, 1, 1, 0, 1)], true, clFood), 0, [ avoidClasses(clFood, 10), stayClasses(clWater, 4), new HeightConstraint(-Infinity, heightLand) ], scaleByMapSize(8, 32)); Engine.SetProgress(90); g_Map.log("Creating deer"); group = new SimpleGroup( [new SimpleObject(oDeer, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 5, clForest, 2, clCliff, 1, clPlayer, 20, clMetal, 6, clRock, 6, clFood, 8), 3 * numPlayers, 50 ); Engine.SetProgress(95); g_Map.log("Creating berry bushes"); group = new SimpleGroup([new SimpleObject(oBerryBush, 5,7, 0,3)], true, clFood); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 5, clForest, 2, clCliff, 1, clPlayer, 20, clMetal, 6, clRock, 6, clFood, 8), 1.5 * numPlayers, 100 ); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clCliff, 2, clForest, 1, clMetal, 4, clRock, 4, clFood, 2)); setSkySet("sunny"); setWaterColor(0.024,0.262,0.224); setWaterTint(0.133, 0.325,0.255); setWaterWaviness(2.5); setWaterType("ocean"); setWaterMurkiness(0.8); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/mainland.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/mainland.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/mainland.js (revision 26381) @@ -1,196 +1,196 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); setSelectedBiome(); const tMainTerrain = g_Terrains.mainTerrain; const tForestFloor1 = g_Terrains.forestFloor1; const tForestFloor2 = g_Terrains.forestFloor2; const tCliff = g_Terrains.cliff; const tTier1Terrain = g_Terrains.tier1Terrain; const tTier2Terrain = g_Terrains.tier2Terrain; const tTier3Terrain = g_Terrains.tier3Terrain; const tHill = g_Terrains.hill; const tRoad = g_Terrains.road; const tRoadWild = g_Terrains.roadWild; const tTier4Terrain = g_Terrains.tier4Terrain; const oTree1 = g_Gaia.tree1; const oTree2 = g_Gaia.tree2; const oTree3 = g_Gaia.tree3; const oTree4 = g_Gaia.tree4; const oTree5 = g_Gaia.tree5; const oFruitBush = g_Gaia.fruitBush; const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal; const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal; const oStoneLarge = g_Gaia.stoneLarge; const oStoneSmall = g_Gaia.stoneSmall; const oMetalLarge = g_Gaia.metalLarge; const oMetalSmall = g_Gaia.metalSmall; const aGrass = g_Decoratives.grass; const aGrassShort = g_Decoratives.grassShort; const aRockLarge = g_Decoratives.rockLarge; const aRockMedium = g_Decoratives.rockMedium; const aBushMedium = g_Decoratives.bushMedium; const aBushSmall = g_Decoratives.bushSmall; const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2]; const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1]; const heightLand = 3; var g_Map = new RandomMap(heightLand, tMainTerrain); const numPlayers = getNumPlayers(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oFruitBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oTree1, "count": 5 }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(20); createBumps(avoidClasses(clPlayer, 20)); if (randBool()) createHills([tCliff, tCliff, tHill], avoidClasses(clPlayer, 20, clHill, 15), clHill, scaleByMapSize(3, 15)); else createMountains(tCliff, avoidClasses(clPlayer, 20, clHill, 15), clHill, scaleByMapSize(3, 15)); var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(1)); createDefaultForests( [tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2], avoidClasses(clPlayer, 20, clForest, 18, clHill, 0), clForest, forestTrees); Engine.SetProgress(50); g_Map.log("Creating dirt patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [[tMainTerrain,tTier1Terrain],[tTier1Terrain,tTier2Terrain], [tTier2Terrain,tTier3Terrain]], [1, 1], avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45), clDirt); g_Map.log("Creating grass patches"); createPatches( [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)], tTier4Terrain, avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(55); g_Map.log("Creating metal mines"); createBalancedMetalMines( oMetalSmall, oMetalLarge, clMetal, avoidClasses(clForest, 1, clPlayer, scaleByMapSize(20, 35), clHill, 1) ); g_Map.log("Creating stone mines"); createBalancedStoneMines( oStoneSmall, oStoneLarge, clRock, avoidClasses(clForest, 1, clPlayer, scaleByMapSize(20, 35), clHill, 1, clMetal, 10) ); Engine.SetProgress(65); var planetm = 1; if (currentBiome() == "generic/india") planetm = 8; createDecoration( [ [new SimpleObject(aRockMedium, 1, 3, 0, 1)], [new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)], [new SimpleObject(aGrassShort, 1, 2, 0, 1)], [new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3,6, 1.2, 2.5)], [new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)] ], [ scaleByMapAreaAbsolute(16), scaleByMapAreaAbsolute(8), planetm * scaleByMapAreaAbsolute(13), planetm * scaleByMapAreaAbsolute(13), planetm * scaleByMapAreaAbsolute(13) ], avoidClasses(clForest, 0, clPlayer, 0, clHill, 0)); Engine.SetProgress(70); createFood( [ [new SimpleObject(oMainHuntableAnimal, 5, 7, 0, 4)], [new SimpleObject(oSecondaryHuntableAnimal, 2, 3, 0, 2)] ], [ 3 * numPlayers, 3 * numPlayers ], avoidClasses(clForest, 0, clPlayer, 20, clHill, 1, clMetal, 4, clRock, 4, clFood, 20), clFood); Engine.SetProgress(75); createFood( [ [new SimpleObject(oFruitBush, 5, 7, 0, 4)] ], [ 3 * numPlayers ], avoidClasses(clForest, 0, clPlayer, 20, clHill, 1, clMetal, 4, clRock, 4, clFood, 10), clFood); Engine.SetProgress(85); createStragglerTrees( [oTree1, oTree2, oTree4, oTree3], avoidClasses(clForest, 8, clHill, 1, clPlayer, 12, clMetal, 6, clRock, 6, clFood, 1), clForest, stragglerTrees); placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/oasis.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/oasis.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/oasis.js (revision 26381) @@ -1,313 +1,313 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); const tSand = ["desert_sand_dunes_100", "desert_dirt_cracks","desert_sand_smooth", "desert_dirt_rough", "desert_dirt_rough_2", "desert_sand_smooth"]; const tDune = ["desert_sand_dunes_50"]; const tForestFloor = "desert_forestfloor_palms"; const tDirt = ["desert_dirt_rough","desert_dirt_rough","desert_dirt_rough", "desert_dirt_rough_2", "desert_dirt_rocks_2"]; const tRoad = "desert_city_tile"; const tRoadWild = "desert_city_tile"; const tShore = "dirta"; const tWater = "desert_sand_wet"; const ePalmShort = "gaia/tree/cretan_date_palm_short"; const ePalmTall = "gaia/tree/cretan_date_palm_tall"; const eBush = "gaia/fruit/grapes"; const eCamel = "gaia/fauna_camel"; const eGazelle = "gaia/fauna_gazelle"; const eLion = "gaia/fauna_lion"; const eLioness = "gaia/fauna_lioness"; const eStoneMine = "gaia/rock/desert_large"; const eMetalMine = "gaia/ore/desert_large"; const aFlower1 = "actor|props/flora/decals_flowers_daisies.xml"; const aWaterFlower = "actor|props/flora/water_lillies.xml"; const aReedsA = "actor|props/flora/reeds_pond_lush_a.xml"; const aReedsB = "actor|props/flora/reeds_pond_lush_b.xml"; const aRock = "actor|geology/stone_desert_med.xml"; const aBushA = "actor|props/flora/bush_desert_dry_a.xml"; const aBushB = "actor|props/flora/bush_desert_dry_a.xml"; const aSand = "actor|particle/blowing_sand.xml"; const pForestMain = [tForestFloor + TERRAIN_SEPARATOR + ePalmShort, tForestFloor + TERRAIN_SEPARATOR + ePalmTall, tForestFloor]; const pOasisForestLight = [tForestFloor + TERRAIN_SEPARATOR + ePalmShort, tForestFloor + TERRAIN_SEPARATOR + ePalmTall, tForestFloor,tForestFloor,tForestFloor ,tForestFloor,tForestFloor,tForestFloor,tForestFloor]; const heightSeaGround = -3; const heightFloraMin = -2.5; const heightFloraReedsMax = -1.9; const heightFloraMax = -1; const heightLand = 1; const heightSand = 3.4; const heightOasisPath = 4; const heightOffsetBump = 4; const heightOffsetDune = 18; var g_Map = new RandomMap(heightLand, tSand); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clOasis = g_Map.createTileClass(); var clPassage = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var waterRadius = scaleByMapSize(7, 50); var shoreDistance = scaleByMapSize(4, 10); var forestDistance = scaleByMapSize(6, 20); var [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); g_Map.log("Creating small oasis near the players..."); var forestDist = 1.2 * defaultPlayerBaseRadius(); for (let i = 0; i < numPlayers; ++i) { let forestPosition; let forestAngle; do { forestAngle = Math.PI / 3 * randFloat(1, 2); forestPosition = Vector2D.add(playerPosition[i], new Vector2D(forestDist, 0).rotate(-forestAngle)); } while ( !createArea( new ClumpPlacer(70, 1, 0.5, Infinity, forestPosition), [ new LayeredPainter([tForestFloor, pForestMain], [0]), new TileClassPainter(clBaseResource) ], avoidClasses(clBaseResource, 0))); let waterPosition; let flowerPosition; let reedsPosition; do { let waterAngle = forestAngle + randFloat(1, 5) / 3 * Math.PI; waterPosition = Vector2D.add(forestPosition, new Vector2D(6, 0).rotate(-waterAngle)).round(); flowerPosition = Vector2D.add(forestPosition, new Vector2D(3, 0).rotate(-waterAngle)).round(); reedsPosition = Vector2D.add(forestPosition, new Vector2D(5, 0).rotate(-waterAngle)).round(); } while ( !createArea( new ClumpPlacer(diskArea(4.5), 0.9, 0.4, Infinity, waterPosition), [ new LayeredPainter([tShore, tWater], [1]), new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 3) ], avoidClasses(clBaseResource, 0))); createObjectGroup(new SimpleGroup([new SimpleObject(aFlower1, 1, 5, 0, 3)], true, undefined, flowerPosition), 0); createObjectGroup(new SimpleGroup([new SimpleObject(aReedsA, 1, 3, 0, 0)], true, undefined, reedsPosition), 0); } Engine.SetProgress(20); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad, "painters": [ new TileClassPainter(clPlayer) ] }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": eBush }, "Mines": { "types": [ { "template": eMetalMine }, { "template": eStoneMine }, ], "distance": defaultPlayerBaseRadius(), "maxAngle": Math.PI / 2, "groupElements": shuffleArray([aBushA, aBushB, ePalmShort, ePalmTall]).map(t => new SimpleObject(t, 1, 1, 3, 4)) } // Starting trees were set above // No decoratives }); Engine.SetProgress(30); g_Map.log("Creating central oasis"); createArea( new ClumpPlacer(diskArea(forestDistance + shoreDistance + waterRadius), 0.8, 0.2, Infinity, mapCenter), [ new LayeredPainter([pOasisForestLight, tWater], [forestDistance]), new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, forestDistance + shoreDistance), new TileClassPainter(clOasis) ]); Engine.SetProgress(40); g_Map.log("Creating bumps"); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, Infinity), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 3), avoidClasses(clPlayer, 10, clBaseResource, 6, clOasis, 4), scaleByMapSize(30, 70)); g_Map.log("Creating dirt patches"); createAreas( new ClumpPlacer(80, 0.3, 0.06, Infinity), new TerrainPainter(tDirt), avoidClasses(clPlayer, 10, clBaseResource, 6, clOasis, 4, clForest, 4), scaleByMapSize(15, 50)); g_Map.log("Creating dunes"); createAreas( new ClumpPlacer(120, 0.3, 0.06, Infinity), [ new TerrainPainter(tDune), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetDune, 30) ], avoidClasses(clPlayer, 10, clBaseResource, 6, clOasis, 4, clForest, 4), scaleByMapSize(15, 50)); Engine.SetProgress(50); if (mapSize > 150 && randBool()) { g_Map.log("Creating path though the oasis"); let pathWidth = scaleByMapSize(7, 18); let points = distributePointsOnCircle(2, randomAngle(), waterRadius + shoreDistance + forestDistance + pathWidth, mapCenter)[0]; createArea( new PathPlacer(points[0], points[1], pathWidth, 0.4, 1, 0.2, 0), [ new TerrainPainter(tSand), new SmoothElevationPainter(ELEVATION_SET, heightOasisPath, 5), new TileClassPainter(clPassage) ]); } g_Map.log("Creating some straggler trees around the passage"); var group = new SimpleGroup([new SimpleObject(ePalmTall, 1,1, 0,0),new SimpleObject(ePalmShort, 1, 2, 1, 2), new SimpleObject(aBushA, 0,2, 1,3)], true, clForest); createObjectGroupsDeprecated(group, 0, stayClasses(clPassage, 3), scaleByMapSize(60, 250), 100); g_Map.log("Creating stone mines"); group = new SimpleGroup([new SimpleObject(eStoneMine, 1,1, 0,0),new SimpleObject(ePalmShort, 1,2, 3,3),new SimpleObject(ePalmTall, 0,1, 3,3) ,new SimpleObject(aBushB, 1,1, 2,2), new SimpleObject(aBushA, 0,2, 1,3)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clOasis, 10, clForest, 1, clPlayer, 30, clRock, 10,clBaseResource, 2, clHill, 1), scaleByMapSize(6,25), 100 ); g_Map.log("Creating metal mines"); group = new SimpleGroup([new SimpleObject(eMetalMine, 1,1, 0,0),new SimpleObject(ePalmShort, 1,2, 2,3),new SimpleObject(ePalmTall, 0,1, 2,2) ,new SimpleObject(aBushB, 1,1, 2,2), new SimpleObject(aBushA, 0,2, 1,3)], true, clMetal); createObjectGroupsDeprecated(group, 0, avoidClasses(clOasis, 10, clForest, 1, clPlayer, 30, clMetal, 10,clBaseResource, 2, clRock, 10, clHill, 1), scaleByMapSize(6,25), 100 ); Engine.SetProgress(65); g_Map.log("Creating small decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRock, 2,4, 0,2)], true, undefined ); createObjectGroupsDeprecated(group, 0, avoidClasses(clOasis, 3, clForest, 0, clPlayer, 10, clHill, 1, clFood, 20), 30, scaleByMapSize(10, 50)); Engine.SetProgress(70); g_Map.log("Creating camels"); group = new SimpleGroup( [new SimpleObject(eCamel, 1,2, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clOasis, 3, clForest, 0, clPlayer, 10, clHill, 1, clFood, 20), 1 * numPlayers, 50 ); Engine.SetProgress(75); g_Map.log("Creating gazelles"); group = new SimpleGroup( [new SimpleObject(eGazelle, 2,4, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clOasis, 3, clForest, 0, clPlayer, 10, clHill, 1, clFood, 20), 1 * numPlayers, 50 ); Engine.SetProgress(85); g_Map.log("Creating oasis animals"); for (let i = 0; i < scaleByMapSize(5, 30); ++i) { let animalPos = Vector2D.add(mapCenter, new Vector2D(forestDistance + shoreDistance + waterRadius, 0).rotate(randomAngle())); createObjectGroup( new RandomGroup( [ new SimpleObject(eLion, 1, 2, 0, 4), new SimpleObject(eLioness, 1, 2, 2, 4), new SimpleObject(eGazelle, 4, 6, 1, 5), new SimpleObject(eCamel, 1, 2, 1, 5) ], true, clFood, animalPos), 0); } Engine.SetProgress(90); g_Map.log("Creating bushes"); var group = new SimpleGroup( [new SimpleObject(aBushB, 1,2, 0,2), new SimpleObject(aBushA, 2,4, 0,2)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clOasis, 2, clHill, 1, clPlayer, 1, clPassage, 1), scaleByMapSize(10, 40), 20 ); var objectsWaterFlora = [ new SimpleObject(aReedsA, 5, 12, 0, 2), new SimpleObject(aReedsB, 5, 12, 0, 2) ]; g_Map.log("Creating sand blows and beautifications"); for (var sandx = 0; sandx < mapSize; sandx += 4) for (var sandz = 0; sandz < mapSize; sandz += 4) { let position = new Vector2D(sandx, sandz); let height = g_Map.getHeight(position); if (height > heightSand) { if (randBool((height - heightSand) / 1.4)) createObjectGroup(new SimpleGroup([new SimpleObject(aSand, 0, 1, 0, 2)], true, undefined, position), 0); } else if (height > heightFloraMin && height < heightFloraMax) { if (randBool(0.4)) createObjectGroup(new SimpleGroup([new SimpleObject(aWaterFlower, 1, 4, 1, 2)], true, undefined, position), 0); else if (randBool(0.7) && height < heightFloraReedsMax) createObjectGroup(new SimpleGroup(objectsWaterFlora, true, undefined, position), 0); if (clPassage.countMembersInRadius(position, 2)) { if (randBool(0.4)) createObjectGroup(new SimpleGroup([new SimpleObject(aWaterFlower, 1, 4, 1, 2)], true, undefined, position), 0); else if (randBool(0.7) && height < heightFloraReedsMax) createObjectGroup(new SimpleGroup(objectsWaterFlora, true, undefined, position), 0); } } } placePlayersNomad(clPlayer, avoidClasses(clOasis, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); setSkySet("sunny"); setSunColor(0.914,0.827,0.639); setSunRotation(Math.PI/3); setSunElevation(0.5); setWaterColor(0, 0.227, 0.843); setWaterTint(0, 0.545, 0.859); setWaterWaviness(1.0); setWaterType("clap"); setWaterMurkiness(0.5); setAmbientColor(0.501961, 0.501961, 0.501961); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/ratumacos.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/ratumacos.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/ratumacos.js (revision 26381) @@ -1,379 +1,379 @@ /** * Heightmap image source: * Imagery by Jesse Allen, NASA's Earth Observatory, * using data from the General Bathymetric Chart of the Oceans (GEBCO) * produced by the British Oceanographic Data Centre. * https://visibleearth.nasa.gov/view.php?id=73934 * * Licensing: Public Domain, https://visibleearth.nasa.gov/useterms.php * * The heightmap image is reproduced using: * wget https://eoimages.gsfc.nasa.gov/images/imagerecords/73000/73934/gebco_08_rev_elev_C1_grey_geo.tif * lat=49.31; lon=1.1; width=1 * 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") * gdal_translate -projwin $lon2 $lat2 $lon1 $lat1 gebco_08_rev_elev_C1_grey_geo.tif ratumacos.tif * convert ratumacos.tif -resize 512 -contrast-stretch 0 ratumacos.png * No further changes should be applied to the image to keep it easily interchangeable. */ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmgen2"); Engine.LoadLibrary("rmbiome"); setBiome("generic/alpine"); g_Terrains.mainTerrain = "new_alpine_grass_d"; g_Terrains.forestFloor1 = "alpine_grass_d"; g_Terrains.forestFloor2 = "alpine_grass_c"; g_Terrains.tier1Terrain = "new_alpine_grass_c"; g_Terrains.tier2Terrain = "new_alpine_grass_b"; g_Terrains.tier3Terrain = "alpine_grass_a"; g_Terrains.tier4Terrain = "new_alpine_grass_e"; g_Gaia.mainHuntableAnimal = "gaia/fauna_deer"; g_Gaia.secondaryHuntableAnimal = "gaia/fauna_pig"; g_Gaia.fish = "gaia/fish/tilapia"; g_Gaia.tree1 = "gaia/tree/poplar"; g_Gaia.tree2 = "gaia/tree/toona"; g_Gaia.tree3 = "gaia/fruit/apple"; g_Gaia.tree4 = "gaia/tree/acacia"; g_Gaia.tree5 = "gaia/tree/carob"; g_Decoratives.grass = "actor|props/flora/grass_soft_large.xml"; g_Decoratives.grassShort = "actor|props/flora/grass_tufts_a.xml"; g_Decoratives.rockLarge = "actor|geology/stone_granite_med.xml"; g_Decoratives.rockMedium = "actor|geology/stone_granite_small.xml"; g_Decoratives.bushMedium = "actor|props/flora/bush_tempe_a.xml"; g_Decoratives.bushSmall = "actor|props/flora/bush_tempe_b.xml"; g_Decoratives.reeds = "actor|props/flora/reeds_pond_lush_a.xml"; g_Decoratives.lillies = "actor|props/flora/water_lillies.xml"; const heightScale = num => num * g_MapSettings.Size / 320; const heightReedsMin = heightScale(-2); const heightShallow = heightScale(-1); const heightWaterLevel = heightScale(0); const heightShoreline = heightScale(3); const heightPlayer = heightScale(10); const g_Map = new RandomMap(0, g_Terrains.mainTerrain); const mapBounds = g_Map.getBounds(); const mapCenter = g_Map.getCenter(); const riverAngle = 0.65 * Math.PI; initTileClasses(["shoreline", "shallows"]); g_Map.LoadHeightmapImage("ratumacos.png", -3, 20); Engine.SetProgress(15); g_Map.log("Smoothing heightmap"); createArea( new MapBoundsPlacer(), new SmoothingPainter(1, 0.1, 1)); Engine.SetProgress(25); g_Map.log("Creating shallows"); for (let i = 0; i < scaleByMapSize(5, 12); ++i) { let x = fractionToTiles(randFloat(0, 1)); createPassage({ "start": new Vector2D(x, mapBounds.bottom).rotateAround(riverAngle + Math.PI / 2 * randFloat(0.8, 1.2), mapCenter), "end": new Vector2D(x, mapBounds.top).rotateAround(riverAngle + Math.PI / 2 * randFloat(0.8, 1.2), mapCenter), "startWidth": scaleByMapSize(8, 12), "endWidth": scaleByMapSize(8, 12), "smoothWidth": 2, "startHeight": heightShallow, "endHeight": heightShallow, "constraints": new HeightConstraint(-Infinity, heightShallow) }); } g_Map.log("Painting water"); createArea( new MapBoundsPlacer(), [ new TerrainPainter(g_Terrains.water), new TileClassPainter(g_TileClasses.water) ], new HeightConstraint(-Infinity, heightWaterLevel)); Engine.SetProgress(30); g_Map.log("Marking land"); createArea( new MapBoundsPlacer(), new TileClassPainter(g_TileClasses.land), avoidClasses(g_TileClasses.water, 0)); Engine.SetProgress(35); g_Map.log("Painting shoreline"); createArea( new MapBoundsPlacer(), [ new TerrainPainter(g_Terrains.shore), new TileClassPainter(g_TileClasses.shoreline) ], new HeightConstraint(heightWaterLevel, heightShoreline)); Engine.SetProgress(40); placePlayerBases({ "PlayerPlacement": playerPlacementRiver(riverAngle, fractionToTiles(0.6)), "PlayerTileClass": g_TileClasses.player, "BaseResourceClass": g_TileClasses.baseResource, "Walls": "towers", "CityPatch": { "outerTerrain": g_Terrains.roadWild, "innerTerrain": g_Terrains.road, "painters": [ new SmoothElevationPainter(ELEVATION_SET, heightPlayer, 2) ] }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": g_Gaia.fruitBush }, "Mines": { "types": [ { "template": g_Gaia.metalLarge }, { "template": g_Gaia.stoneLarge } ] }, "Trees": { "template": g_Gaia.tree1, "count": 2 }, "Decoratives": { "template": g_Decoratives.rockMedium } }); addElements([ { "func": addLayeredPatches, "avoid": [ g_TileClasses.dirt, 5, g_TileClasses.forest, 2, g_TileClasses.mountain, 2, g_TileClasses.player, 12, g_TileClasses.water, 3, g_TileClasses.shoreline, 3 ], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["many"] }, { "func": addDecoration, "avoid": [ g_TileClasses.forest, 2, g_TileClasses.mountain, 2, g_TileClasses.player, 12, g_TileClasses.water, 3, g_TileClasses.shoreline, 3 ], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["many"] } ]); addElements(shuffleArray([ { "func": addSmallMetal, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.forest, 3, g_TileClasses.mountain, 6, g_TileClasses.player, 30, g_TileClasses.rock, 20, g_TileClasses.metal, 30, g_TileClasses.water, 3, g_TileClasses.shoreline, 3 ], "sizes": ["normal"], "mixes": ["same"], "amounts": ["few"] }, { "func": addMetal, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.forest, 3, g_TileClasses.mountain, 6, g_TileClasses.player, 30, g_TileClasses.rock, 30, g_TileClasses.metal, 20, g_TileClasses.water, 3, g_TileClasses.shoreline, 3 ], "sizes": ["normal"], "mixes": ["same"], "amounts": ["normal"] }, { "func": addStone, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.forest, 3, g_TileClasses.mountain, 6, g_TileClasses.player, 30, g_TileClasses.rock, 30, g_TileClasses.metal, 20, g_TileClasses.water, 3, g_TileClasses.shoreline, 3 ], "sizes": ["normal"], "mixes": ["same"], "amounts": ["normal"] }, { "func": addForests, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.forest, 8, g_TileClasses.metal, 3, g_TileClasses.mountain, 6, g_TileClasses.player, 20, g_TileClasses.rock, 3, g_TileClasses.water, 2, g_TileClasses.shoreline, 2 ], "sizes": ["normal"], "mixes": ["same"], "amounts": ["many"] } ])); addElements(shuffleArray([ { "func": addAnimals, "avoid": [ g_TileClasses.animals, 20, g_TileClasses.forest, 2, g_TileClasses.metal, 2, g_TileClasses.mountain, 6, g_TileClasses.player, 20, g_TileClasses.rock, 2, g_TileClasses.water, 3, g_TileClasses.shoreline, 3 ], "sizes": ["huge"], "mixes": ["similar"], "amounts": ["tons"] }, { "func": addAnimals, "avoid": [ g_TileClasses.animals, 20, g_TileClasses.forest, 2, g_TileClasses.metal, 2, g_TileClasses.mountain, 6, g_TileClasses.player, 20, g_TileClasses.rock, 2, g_TileClasses.water, 3, g_TileClasses.shoreline, 3 ], "sizes": ["huge"], "mixes": ["similar"], "amounts": ["tons"] }, { "func": addBerries, "avoid": [ g_TileClasses.berries, 30, g_TileClasses.forest, 5, g_TileClasses.metal, 10, g_TileClasses.mountain, 2, g_TileClasses.player, 20, g_TileClasses.rock, 10, g_TileClasses.water, 3, g_TileClasses.shoreline, 3 ], "sizes": ["normal"], "mixes": ["same"], "amounts": ["many"] }, { "func": addStragglerTrees, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.forest, 4, g_TileClasses.metal, 2, g_TileClasses.mountain, 6, g_TileClasses.player, 12, g_TileClasses.rock, 2, g_TileClasses.water, 5, g_TileClasses.shoreline, 3 ], "sizes": ["normal"], "mixes": ["same"], "amounts": ["tons"] } ])); Engine.SetProgress(80); createDecoration( [ [new SimpleObject(g_Decoratives.reeds, 1, 3, 0, 1)], [new SimpleObject(g_Decoratives.lillies, 1, 2, 0, 1)] ], [ scaleByMapAreaAbsolute(1800), scaleByMapAreaAbsolute(900) ], new HeightConstraint(heightReedsMin, heightShoreline) ); Engine.SetProgress(90); g_Map.log("Placing fish"); addElements([ { "func": addFish, "avoid": [ g_TileClasses.fish, 10, ], "stay": [g_TileClasses.water, 4], "sizes": ["normal"], "mixes": ["similar"], "amounts": ["few"] } ]); Engine.SetProgress(95); placePlayersNomad( g_Map.createTileClass(), [ stayClasses(g_TileClasses.land, 4), avoidClasses( g_TileClasses.forest, 1, g_TileClasses.rock, 4, g_TileClasses.metal, 4, g_TileClasses.animals, 1) ]); setSunColor(0.733, 0.746, 0.574); setWaterHeight(20 + heightWaterLevel); setWaterTint(0.224, 0.271, 0.270); setWaterColor(0.224, 0.271, 0.270); setWaterWaviness(8); setWaterMurkiness(0.87); setWaterType("clap"); setAmbientColor(0.521, 0.475, 0.322); setSunRotation(-Math.PI); setSunElevation(Math.PI / 6.25); setFogFactor(0); setFogThickness(0); setFogColor(0.69, 0.616, 0.541); setPPEffect("hdr"); setPPContrast(0.67); setPPSaturation(0.42); setPPBloom(0.23); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/pyrenean_sierra.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/pyrenean_sierra.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/pyrenean_sierra.js (revision 26381) @@ -1,467 +1,467 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); TILE_CENTERED_HEIGHT_MAP = true; const tGrassSpecific = ["new_alpine_grass_d","new_alpine_grass_d", "new_alpine_grass_e"]; const tGrass = ["new_alpine_grass_d", "new_alpine_grass_b", "new_alpine_grass_e"]; const tGrassMidRange = ["new_alpine_grass_b", "alpine_grass_a"]; const tGrassHighRange = ["new_alpine_grass_a", "alpine_grass_a", "alpine_grass_rocky"]; const tHighRocks = ["alpine_cliff_b", "alpine_cliff_c","alpine_cliff_c", "alpine_grass_rocky"]; const tSnowedRocks = ["alpine_cliff_b", "alpine_cliff_snow"]; const tTopSnow = ["alpine_snow_rocky","alpine_snow_a"]; const tTopSnowOnly = ["alpine_snow_a"]; const tDirtyGrass = ["new_alpine_grass_d","alpine_grass_d","alpine_grass_c", "alpine_grass_b"]; const tLushGrass = ["new_alpine_grass_a","new_alpine_grass_d"]; const tMidRangeCliffs = ["alpine_cliff_b","alpine_cliff_c"]; const tHighRangeCliffs = ["alpine_mountainside","alpine_cliff_snow" ]; const tSand = ["beach_c", "beach_d"]; const tSandTransition = ["beach_scrub_50_"]; const tWater = ["sand_wet_a","sand_wet_b","sand_wet_b","sand_wet_b"]; const tGrassLandForest = "alpine_forrestfloor"; const tGrassLandForest2 = "alpine_grass_d"; const tForestTransition = ["new_alpine_grass_d", "new_alpine_grass_b","alpine_grass_d"]; const tRoad = "new_alpine_citytile"; const tRoadWild = "new_alpine_citytile"; const oBeech = "gaia/tree/euro_beech"; const oPine = "gaia/tree/aleppo_pine"; const oBerryBush = "gaia/fruit/berry_01"; const oDeer = "gaia/fauna_deer"; const oFish = "gaia/fish/generic"; const oRabbit = "gaia/fauna_rabbit"; const oStoneLarge = "gaia/rock/alpine_large"; const oStoneSmall = "gaia/rock/alpine_small"; const oMetalLarge = "gaia/ore/alpine_large"; const oMetalSmall = "gaia/ore/alpine_small"; const aGrass = "actor|props/flora/grass_soft_small_tall.xml"; const aGrassShort = "actor|props/flora/grass_soft_large.xml"; const aRockLarge = "actor|geology/stone_granite_med.xml"; const aRockMedium = "actor|geology/stone_granite_med.xml"; const aBushMedium = "actor|props/flora/bush_medit_me.xml"; const aBushSmall = "actor|props/flora/bush_medit_sm.xml"; const pForestLand = [tGrassLandForest + TERRAIN_SEPARATOR + oPine,tGrassLandForest + TERRAIN_SEPARATOR + oBeech, tGrassLandForest2 + TERRAIN_SEPARATOR + oPine,tGrassLandForest2 + TERRAIN_SEPARATOR + oBeech, tGrassLandForest,tGrassLandForest2,tGrassLandForest2,tGrassLandForest2]; const pForestLandLight = [tGrassLandForest + TERRAIN_SEPARATOR + oPine,tGrassLandForest + TERRAIN_SEPARATOR + oBeech, tGrassLandForest2 + TERRAIN_SEPARATOR + oPine,tGrassLandForest2 + TERRAIN_SEPARATOR + oBeech, tGrassLandForest,tGrassLandForest2,tForestTransition,tGrassLandForest2, tGrassLandForest,tForestTransition,tGrassLandForest2,tForestTransition, tGrassLandForest2,tGrassLandForest2,tGrassLandForest2,tGrassLandForest2]; const pForestLandVeryLight = [ tGrassLandForest2 + TERRAIN_SEPARATOR + oPine,tGrassLandForest2 + TERRAIN_SEPARATOR + oBeech, tForestTransition,tGrassLandForest2,tForestTransition,tForestTransition,tForestTransition, tGrassLandForest,tForestTransition,tGrassLandForest2,tForestTransition, tGrassLandForest2,tGrassLandForest2,tGrassLandForest2,tGrassLandForest2]; const heightInit = -100; const heightOcean = -22; const heightWaterTerrain = -14; const heightBase = -6; const heightSand = -2; const heightSandTransition = 0; const heightGrass = 6; const heightWaterLevel = 8; const heightPyreneans = 15; const heightGrassMidRange = 18; const heightGrassHighRange = 30; const heightPassage = scaleByMapSize(25, 40); const heightHighRocks = heightPassage + 5; const heightSnowedRocks = heightHighRocks + 10; const heightMountain = heightHighRocks + 20; const heightOffsetHill = 7; const heightOffsetHillRandom = 2; var g_Map = new RandomMap(heightInit, tGrass); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clPass = g_Map.createTileClass(); var clPyrenneans = g_Map.createTileClass(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var startAngle = randomAngle(); var oceanAngle = startAngle + randFloat(-1, 1) * Math.PI / 12; var mountainLength = fractionToTiles(0.68); var mountainWidth = scaleByMapSize(15, 55); var mountainPeaks = 100 * scaleByMapSize(1, 10); var mountainOffset = randFloat(-1, 1) * scaleByMapSize(1, 12); var passageLength = scaleByMapSize(8, 50); var terrainPerHeight = [ { "maxHeight": heightGrass, "steepness": 5, "terrainGround": tGrass, "terrainSteep": tMidRangeCliffs }, { "maxHeight": heightGrassMidRange, "steepness": 8, "terrainGround": tGrassMidRange, "terrainSteep": tMidRangeCliffs }, { "maxHeight": heightGrassHighRange, "steepness": 8, "terrainGround": tGrassHighRange, "terrainSteep": tMidRangeCliffs }, { "maxHeight": heightHighRocks, "steepness": 8, "terrainGround": tHighRocks, "terrainSteep": tHighRangeCliffs }, { "maxHeight": heightSnowedRocks, "steepness": 7, "terrainGround": tSnowedRocks, "terrainSteep": tHighRangeCliffs }, { "maxHeight": Infinity, "steepness": 6, "terrainGround": tTopSnowOnly, "terrainSteep": tTopSnow } ]; g_Map.log("Creating initial sinusoidal noise"); var baseHeights = []; for (var ix = 0; ix < mapSize; ix++) { baseHeights.push([]); for (var iz = 0; iz < mapSize; iz++) { let position = new Vector2D(ix, iz); if (g_Map.inMapBounds(position)) { let height = heightBase + randFloat(-1, 1) + scaleByMapSize(1, 3) * (Math.cos(ix / scaleByMapSize(5, 30)) + Math.sin(iz / scaleByMapSize(5, 30))); g_Map.setHeight(position, height); baseHeights[ix].push(height); } else baseHeights[ix].push(heightInit); } } var playerIDs = sortAllPlayers(); var playerPosition = playerPlacementArcs( playerIDs, mapCenter, fractionToTiles(0.35), oceanAngle, 0.1 * Math.PI, 0.9 * Math.PI); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oPine }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(30); g_Map.log("Creating the pyreneans"); var mountainVec = new Vector2D(mountainLength, 0).rotate(-startAngle); var mountainStart = Vector2D.sub(mapCenter, Vector2D.div(mountainVec, 2)); var mountainDirection = mountainVec.clone().normalize(); createPyreneans(); paintTileClassBasedOnHeight(heightPyreneans, Infinity, Elevation_ExcludeMin_ExcludeMax, clPyrenneans); Engine.SetProgress(40); /** * Generates the mountain peak noise. * * @param {number} x - between 0 and 1 * @returns {number} between 0 and 1 */ function sigmoid(x, peakPosition) { return 1 / (1 + Math.exp(x)) * // If we're too far from the border, we flatten (0.2 - Math.max(0, Math.abs(0.5 - peakPosition) - 0.3)) * 5; } function createPyreneans() { for (let peak = 0; peak < mountainPeaks; ++peak) { let peakPosition = peak / mountainPeaks; let peakHeight = randFloat(0, 10); for (let distance = 0; distance < mountainWidth; distance += 1/3) { let rest = 2 * (1 - distance / mountainWidth); let sigmoidX = - 1 * (rest - 1.9) + - 4 * (rest - randFloat(0.9, 1.1)) * (rest - randFloat(0.9, 1.1)) * (rest - randFloat(0.9, 1.1)); for (let direction of [-1, 1]) { let pos = Vector2D.sum([ Vector2D.add(mountainStart, Vector2D.mult(mountainDirection, peakPosition * mountainLength)), new Vector2D(mountainOffset, 0).rotate(-peakPosition * Math.PI * 4), new Vector2D(distance, 0).rotate(-startAngle - direction * Math.PI / 2) ]).round(); g_Map.setHeight(pos, baseHeights[pos.x][pos.y] + (heightMountain + peakHeight + randFloat(-9, 9)) * sigmoid(sigmoidX, peakPosition)); } } } } g_Map.log("Creating passages"); var passageLocation = 0.35; var passageVec = mountainDirection.perpendicular().mult(passageLength); for (let passLoc of [passageLocation, 1 - passageLocation]) for (let direction of [1, -1]) { let passageStart = Vector2D.add(mountainStart, Vector2D.mult(mountainVec, passLoc)); let passageEnd = Vector2D.add(passageStart, Vector2D.mult(passageVec, direction)); createPassage({ "start": passageStart, "end": passageEnd, "startHeight": heightPassage, "startWidth": 7, "endWidth": 7, "smoothWidth": 2, "tileClass": clPass }); } Engine.SetProgress(50); g_Map.log("Smoothing the pyreneans"); createArea( new MapBoundsPlacer(), new SmoothingPainter(1, 0.3, 1), new NearTileClassConstraint(clPyrenneans, 1)); g_Map.log("Creating oceans"); for (let ocean of distributePointsOnCircle(2, oceanAngle, fractionToTiles(0.48), mapCenter)[0]) createArea( new ClumpPlacer(diskArea(fractionToTiles(0.18)), 0.9, 0.05, Infinity, ocean), [ new ElevationPainter(heightOcean), new TileClassPainter(clWater) ]); g_Map.log("Smoothing around the water"); createArea( new MapBoundsPlacer(), new SmoothingPainter(5, 0.9, 1), new NearTileClassConstraint(clWater, 5)); Engine.SetProgress(55); g_Map.log("Creating hills"); createAreas( new ClumpPlacer(scaleByMapSize(60, 120), 0.3, 0.06, Infinity), [ new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetHill, 4, heightOffsetHillRandom), new TerrainPainter(tGrassSpecific), new TileClassPainter(clHill) ], avoidClasses(clWater, 5, clPlayer, 20, clBaseResource, 6, clPyrenneans, 2), scaleByMapSize(5, 35)); g_Map.log("Creating forests"); var types = [[tForestTransition, pForestLandVeryLight, pForestLandLight, pForestLand]]; var size = scaleByMapSize(40, 115) * Math.PI; var num = Math.floor(scaleByMapSize(8,40) / types.length); for (let type of types) createAreas( new ClumpPlacer(size, 0.2, 0.1, Infinity), [ new LayeredPainter(type, [scaleByMapSize(1, 2), scaleByMapSize(3, 6), scaleByMapSize(3, 6)]), new TileClassPainter(clForest) ], avoidClasses(clPlayer, 20, clPyrenneans,0, clForest, 7, clWater, 2), num); Engine.SetProgress(60); g_Map.log("Creating lone trees"); var num = scaleByMapSize(80,400); var group = new SimpleGroup([new SimpleObject(oPine, 1,2, 1,3),new SimpleObject(oBeech, 1,2, 1,3)], true, clForest); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 1, clPlayer, 8,clPyrenneans, 1), num, 20 ); g_Map.log("Painting terrain by height and slope"); for (let i = 0; i < terrainPerHeight.length; ++i) for (let steep of [false, true]) createArea( new MapBoundsPlacer(), new TerrainPainter(steep ? terrainPerHeight[i].terrainSteep : terrainPerHeight[i].terrainGround), [ new NearTileClassConstraint(clPyrenneans, 2), new HeightConstraint(terrainPerHeight[i - 1] ? terrainPerHeight[i - 1].maxHeight : -Infinity, terrainPerHeight[i].maxHeight), steep ? new SlopeConstraint(terrainPerHeight[i].steepness, Infinity) : new SlopeConstraint(-Infinity, terrainPerHeight[i].steepness), ]); for (let x = 0; x < mapSize; ++x) for (let z = 0; z < mapSize; ++z) { let position = new Vector2D(x, z); let height = g_Map.getHeight(position); let heightDiff = g_Map.getSlope(position); let terrainShore = getShoreTerrain(position, height, heightDiff); if (terrainShore) createTerrain(terrainShore).place(position); } function getShoreTerrain(position, height, heightDiff) { if (height <= heightWaterTerrain) return tWater; if (height <= heightSand && new NearTileClassConstraint(clWater, 2).allows(position)) return heightDiff < 2.5 ? tSand : tMidRangeCliffs; // Notice the sand transition is also be painted below height -2 if (height <= heightSandTransition && new NearTileClassConstraint(clWater, 3).allows(position)) return heightDiff < 2.5 ? tSandTransition : tMidRangeCliffs; return undefined; } g_Map.log("Creating dirt patches"); for (let size of [scaleByMapSize(3, 20), scaleByMapSize(5, 40), scaleByMapSize(8, 60)]) createAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), [ new TerrainPainter(tDirtyGrass), new TileClassPainter(clDirt) ], avoidClasses(clWater, 3, clForest, 0, clPyrenneans,5, clHill, 0, clDirt, 5, clPlayer, 6), scaleByMapSize(15, 45)); g_Map.log("Creating grass patches"); for (let size of [scaleByMapSize(2, 32), scaleByMapSize(3, 48), scaleByMapSize(5, 80)]) createAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), new TerrainPainter(tLushGrass), avoidClasses(clWater, 3, clForest, 0, clPyrenneans,5, clHill, 0, clDirt, 5, clPlayer, 6), scaleByMapSize(15, 45)); Engine.SetProgress(70); // making more in dirt areas so as to appear different g_Map.log("Creating small grass tufts"); var group = new SimpleGroup( [new SimpleObject(aGrassShort, 1,2, 0,1, -Math.PI / 8, Math.PI / 8)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 2, clHill, 2, clPlayer, 5, clDirt, 0, clPyrenneans,2), scaleByMapSize(13, 200) ); createObjectGroupsDeprecated(group, 0, stayClasses(clDirt,1), scaleByMapSize(13, 200),10); g_Map.log("Creating large grass tufts"); group = new SimpleGroup( [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)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clHill, 2, clPlayer, 5, clDirt, 1, clForest, 0, clPyrenneans,2), scaleByMapSize(13, 200) ); createObjectGroupsDeprecated(group, 0, stayClasses(clDirt,1), scaleByMapSize(13, 200),10); Engine.SetProgress(75); g_Map.log("Creating bushes"); group = new SimpleGroup( [new SimpleObject(aBushMedium, 1,2, 0,2), new SimpleObject(aBushSmall, 2,4, 0,2)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 2, clPlayer, 1, clPyrenneans, 1), scaleByMapSize(13, 200), 50 ); Engine.SetProgress(80); g_Map.log("Creating metal mines"); createBalancedMetalMines( oMetalSmall, oMetalLarge, clMetal, avoidClasses(clWater, 2, clForest, 0, clPlayer, scaleByMapSize(15, 25), clPyrenneans, 3) ); g_Map.log("Creating stone mines"); createBalancedStoneMines( oStoneSmall, oStoneLarge, clRock, avoidClasses(clWater, 2, clForest, 0, clPlayer, scaleByMapSize(15, 25), clPyrenneans, 3, clMetal, 10) ); Engine.SetProgress(85); g_Map.log("Creating small decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockMedium, 1,3, 0,1)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 0), scaleByMapSize(16, 262), 50 ); g_Map.log("Creating large decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockLarge, 1,2, 0,1), new SimpleObject(aRockMedium, 1,3, 0,2)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 0), scaleByMapSize(8, 131), 50 ); Engine.SetProgress(90); g_Map.log("Creating deer"); group = new SimpleGroup( [new SimpleObject(oDeer, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clPyrenneans, 1, clFood, 15), 3 * numPlayers, 50 ); g_Map.log("Creating rabbit"); group = new SimpleGroup( [new SimpleObject(oRabbit, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clPyrenneans, 1, clFood,15), 3 * numPlayers, 50 ); g_Map.log("Creating berry bush"); group = new SimpleGroup( [new SimpleObject(oBerryBush, 5,7, 0,4)],true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clPyrenneans, 1, clFood, 10), randIntInclusive(1, 4) * numPlayers + 2, 50); g_Map.log("Creating fish"); group = new SimpleGroup( [new SimpleObject(oFish, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clFood, 15), stayClasses(clWater, 6)], 20 * numPlayers, 60 ); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clPyrenneans, 4, clForest, 1, clMetal, 4, clRock, 4, clFood, 2)); setSunElevation(Math.PI * randFloat(1/5, 1/3)); setSunRotation(randomAngle()); setSkySet("cumulus"); setSunColor(0.73,0.73,0.65); setAmbientColor(0.45,0.45,0.50); setWaterColor(0.263, 0.353, 0.616); setWaterTint(0.104, 0.172, 0.563); setWaterWaviness(5.0); setWaterType("ocean"); setWaterMurkiness(0.83); setWaterHeight(heightWaterLevel); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/rivers.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rivers.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/rivers.js (revision 26381) @@ -1,289 +1,289 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); setSelectedBiome(); const tMainTerrain = g_Terrains.mainTerrain; const tForestFloor1 = g_Terrains.forestFloor1; const tForestFloor2 = g_Terrains.forestFloor2; const tCliff = g_Terrains.cliff; const tTier1Terrain = g_Terrains.tier1Terrain; const tTier2Terrain = g_Terrains.tier2Terrain; const tTier3Terrain = g_Terrains.tier3Terrain; const tHill = g_Terrains.hill; const tRoad = g_Terrains.road; const tRoadWild = g_Terrains.roadWild; const tTier4Terrain = g_Terrains.tier4Terrain; var tShore = g_Terrains.shore; var tWater = g_Terrains.water; if (currentBiome() == "generic/india") { tShore = "tropic_dirt_b_plants"; tWater = "tropic_dirt_b"; } const oTree1 = g_Gaia.tree1; const oTree2 = g_Gaia.tree2; const oTree3 = g_Gaia.tree3; const oTree4 = g_Gaia.tree4; const oTree5 = g_Gaia.tree5; const oFruitBush = g_Gaia.fruitBush; const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal; const oFish = g_Gaia.fish; const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal; const oStoneLarge = g_Gaia.stoneLarge; const oStoneSmall = g_Gaia.stoneSmall; const oMetalLarge = g_Gaia.metalLarge; const oMetalSmall = g_Gaia.metalSmall; const aGrass = g_Decoratives.grass; const aGrassShort = g_Decoratives.grassShort; const aReeds = g_Decoratives.reeds; const aLillies = g_Decoratives.lillies; const aRockLarge = g_Decoratives.rockLarge; const aRockMedium = g_Decoratives.rockMedium; const aBushMedium = g_Decoratives.bushMedium; const aBushSmall = g_Decoratives.bushSmall; const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2]; const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1]; const heightSeaGround = -3; const heightShallows = -1; const heightLand = 1; var g_Map = new RandomMap(heightLand, tMainTerrain); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clShallow = g_Map.createTileClass(); var [playerIDs, playerPosition, playerAngle, startAngle] = playerPlacementCircle(fractionToTiles(0.35)); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oFruitBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oTree1, "count": 2 }, "Decoratives": { "template": aGrassShort } }); g_Map.log("Creating central lake"); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.075)), 0.7, 0.1, Infinity, mapCenter), [ new LayeredPainter([tShore, tWater], [1]), new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4), new TileClassPainter(clWater) ]); g_Map.log("Creating rivers between opponents"); let numRivers = isNomad() ? randIntInclusive(4, 8) : numPlayers; let rivers = distributePointsOnCircle(numRivers, startAngle + Math.PI / numRivers, fractionToTiles(0.5), mapCenter)[0]; for (let i = 0; i < numRivers; ++i) { if (isNomad() ? randBool() : areAllies(playerIDs[i], playerIDs[(i + 1) % numPlayers])) continue; let shallowLocation = randFloat(0.2, 0.7); let shallowWidth = randFloat(0.12, 0.21); paintRiver({ "parallel": true, "start": rivers[i], "end": mapCenter, "width": scaleByMapSize(10, 30), "fadeDist": 5, "deviation": 0, "heightLand": heightLand, "heightRiverbed": heightSeaGround, "minHeight": heightSeaGround, "meanderShort": 10, "meanderLong": 0, "waterFunc": (position, height, riverFraction) => { clWater.add(position); let isShallow = height < heightShallows && riverFraction > shallowLocation && riverFraction < shallowLocation + shallowWidth; let newHeight = isShallow ? heightShallows : Math.max(height, heightSeaGround); if (g_Map.getHeight(position) < newHeight) return; g_Map.setHeight(position, newHeight); createTerrain(height >= 0 ? tShore : tWater).place(position); if (isShallow) clShallow.add(position); } }); } Engine.SetProgress(40); createBumps(avoidClasses(clWater, 2, clPlayer, 20)); if (randBool()) createHills([tMainTerrain, tCliff, tHill], avoidClasses(clPlayer, 20, clHill, 15, clWater, 2), clHill, scaleByMapSize(3, 15)); else createMountains(tCliff, avoidClasses(clPlayer, 20, clHill, 15, clWater, 2), clHill, scaleByMapSize(3, 15)); var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(1)); createDefaultForests( [tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2], avoidClasses(clPlayer, 20, clForest, 17, clHill, 0, clWater, 2), clForest, forestTrees); Engine.SetProgress(50); g_Map.log("Creating dirt patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [[tMainTerrain,tTier1Terrain],[tTier1Terrain,tTier2Terrain], [tTier2Terrain,tTier3Terrain]], [1,1], avoidClasses(clWater, 3, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45), clDirt); g_Map.log("Creating grass patches"); createPatches( [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)], tTier4Terrain, avoidClasses(clWater, 3, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(55); g_Map.log("Creating metal mines"); createBalancedMetalMines( oMetalSmall, oMetalLarge, clMetal, avoidClasses(clWater, 3, clForest, 1, clPlayer, scaleByMapSize(20, 35), clHill, 1) ); g_Map.log("Creating stone mines"); createBalancedStoneMines( oStoneSmall, oStoneLarge, clRock, avoidClasses(clWater, 3, clForest, 1, clPlayer, scaleByMapSize(20, 35), clHill, 1, clMetal, 10) ); Engine.SetProgress(65); var planetm = 1; if (currentBiome() == "generic/india") planetm = 8; createDecoration( [ [new SimpleObject(aRockMedium, 1, 3, 0, 1)], [new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)], [new SimpleObject(aGrassShort, 1, 2, 0, 1)], [new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3, 6, 1.2, 2.5)], [new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)] ], [ scaleByMapAreaAbsolute(16), scaleByMapAreaAbsolute(8), planetm * scaleByMapAreaAbsolute(13), planetm * scaleByMapAreaAbsolute(13), planetm * scaleByMapAreaAbsolute(13) ], avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0)); createDecoration( [ [new SimpleObject(aReeds, 1, 3, 0, 1)], [new SimpleObject(aLillies, 1, 2, 0, 1)] ], [ scaleByMapAreaAbsolute(800), scaleByMapAreaAbsolute(800) ], stayClasses(clShallow, 0)); Engine.SetProgress(70); createFood( [ [new SimpleObject(oMainHuntableAnimal, 5, 7, 0, 4)], [new SimpleObject(oSecondaryHuntableAnimal, 2, 3, 0, 2)] ], [ 3 * numPlayers, 3 * numPlayers ], avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 20), clFood); createFood( [ [new SimpleObject(oFruitBush, 5, 7, 0, 4)] ], [ 3 * numPlayers ], avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 10), clFood); createFood( [ [new SimpleObject(oFish, 2, 3, 0, 2)] ], [ 25 * numPlayers ], [avoidClasses(clFood, 20), stayClasses(clWater, 6)], clFood); Engine.SetProgress(85); createStragglerTrees( [oTree1, oTree2, oTree4, oTree3], avoidClasses(clWater, 5, clForest, 7, clHill, 1, clPlayer, 12, clMetal, 6, clRock, 6), clForest, stragglerTrees); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clFood, 2, clHill, 4)); setWaterWaviness(3.0); setWaterType("lake"); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/polar_sea.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/polar_sea.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/polar_sea.js (revision 26381) @@ -1,288 +1,288 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); var tPrimary = ["polar_snow_a"]; var tSecondary = "polar_snow_glacial"; var tHalfSnow = ["ice_01", "ice_dirt"]; var tSnowLimited = ["polar_snow_b", "polar_ice"]; var tDirt = "ice_dirt"; var tRoad = "polar_ice_b"; var tRoadWild = "polar_ice_cracked"; var tShore = "polar_ice_snow"; var tWater = "polar_ice_c"; var oArcticFox = "gaia/fauna_fox_arctic"; var oArcticWolf = "gaia/fauna_wolf_arctic_violent"; var oMuskox = "gaia/fauna_muskox"; var oWalrus = "gaia/fauna_walrus"; var oWhaleFin = "gaia/fauna_whale_fin"; var oWhaleHumpback = "gaia/fauna_whale_humpback"; var oFish = "gaia/fish/generic"; var oStoneLarge = "gaia/rock/mediterranean_large"; var oStoneSmall = "gaia/rock/alpine_small"; var oMetalLarge = "gaia/ore/badlands_large"; var oWoodTreasure = "gaia/treasure/wood"; var oMarket = "skirmish/structures/default_market"; var aRockLarge = "actor|geology/stone_granite_med.xml"; var aRockMedium = "actor|geology/stone_granite_med.xml"; var aIceberg = "actor|props/special/eyecandy/iceberg.xml"; var heightSeaGround = -4; var heightLand = 2; var heightCliff = 3; var g_Map = new RandomMap(heightLand, tPrimary); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); var clPlayer = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clArcticWolf = g_Map.createTileClass(); var [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); var treasures = [{ "template": oWoodTreasure, "count": isNomad() ? 16 : 14 }]; g_Map.log("Creating player markets"); if (!isNomad()) for (let i = 0; i < numPlayers; ++i) { let marketPos = Vector2D.add(playerPosition[i], new Vector2D(12, 0).rotate(randomAngle())).round(); g_Map.placeEntityPassable(oMarket, playerIDs[i], marketPos, BUILDING_ORIENTATION); addCivicCenterAreaToClass(marketPos, clBaseResource); } placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "Walls": "towers", "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { "template": oMuskox }, // No berries, no trees, no decoratives "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Treasures": { "types": treasures }, }); Engine.SetProgress(30); g_Map.log("Creating central lake"); createArea( new ChainPlacer( 2, Math.floor(scaleByMapSize(5, 16)), Math.floor(scaleByMapSize(35, 200)), Infinity, mapCenter, 0, [Math.floor(fractionToTiles(0.17))]), [ new LayeredPainter([tShore, tWater], [1]), new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4), new TileClassPainter(clWater) ], avoidClasses(clPlayer, 20)); Engine.SetProgress(40); g_Map.log("Creating small lakes"); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(2, 4)), Math.floor(scaleByMapSize(20, 140)), 0.7), [ new LayeredPainter([tShore, tWater], [1]), new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 5), new TileClassPainter(clWater) ], avoidClasses(clPlayer, 20), scaleByMapSize(10, 16), 1); Engine.SetProgress(50); createBumps(avoidClasses(clWater, 2, clPlayer, 20)); Engine.SetProgress(60); createHills( [tPrimary, tPrimary, tSecondary], avoidClasses(clPlayer, 20, clHill, 35), clHill, scaleByMapSize(20, 240)); Engine.SetProgress(65); g_Map.log("Creating dirt patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [[tDirt, tHalfSnow], [tHalfSnow, tSnowLimited]], [2], avoidClasses(clWater, 3, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45), clDirt); g_Map.log("Creating glacier patches"); createPatches( [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)], tSecondary, avoidClasses(clWater, 3, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(70); g_Map.log("Creating stone mines"); createMines( [ [new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], [new SimpleObject(oStoneSmall, 2, 5, 1, 3)] ], avoidClasses(clWater, 3, clPlayer, 20, clRock, 18, clHill, 2), clRock); g_Map.log("Creating metal mines"); createMines( [ [new SimpleObject(oMetalLarge, 1, 1, 0, 4)] ], avoidClasses(clWater, 3, clPlayer, 20, clMetal, 18, clRock, 5, clHill, 2), clMetal); Engine.SetProgress(75); createDecoration( [ [ new SimpleObject(aRockMedium, 1, 3, 0, 1) ], [ new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2) ] ], [ scaleByMapAreaAbsolute(16), scaleByMapAreaAbsolute(8), ], avoidClasses(clWater, 0, clPlayer, 0)); createDecoration( [ [new SimpleObject(aIceberg, 1, 1, 1, 1)] ], [ scaleByMapAreaAbsolute(8) ], [stayClasses(clWater, 4), avoidClasses(clHill, 2)]); Engine.SetProgress(80); createFood( [ [new SimpleObject(oArcticFox, 1, 2, 0, 3)], [new SimpleObject(isNomad() ? oArcticFox : oArcticWolf, 4, 6, 0, 4)], [new SimpleObject(oWalrus, 2, 3, 0, 2)], [new SimpleObject(oMuskox, 2, 3, 0, 2)] ], [ 3 * numPlayers, 5 * numPlayers, 5 * numPlayers, 12 * numPlayers ], avoidClasses(clPlayer, 35, clFood, 16, clWater, 2, clMetal, 4, clRock, 4, clHill, 2), clFood); createFood( [ [new SimpleObject(oWhaleFin, 1, 2, 0, 2)], [new SimpleObject(oWhaleHumpback, 1, 2, 0, 2)] ], [ scaleByMapSize(1, 6) * 3, scaleByMapSize(1, 6) * 3, ], [avoidClasses(clFood, 20, clHill, 5), stayClasses(clWater, 6)], clFood); createFood( [ [new SimpleObject(oFish, 2, 3, 0, 2)] ], [ 100 ], [avoidClasses(clFood, 12, clHill, 5), stayClasses(clWater, 6)], clFood); Engine.SetProgress(85); // Create trigger points where wolves spawn createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject("trigger/trigger_point_A", 1, 1, 0, 0)], true, clArcticWolf), 0, avoidClasses(clWater, 2, clMetal, 4, clRock, 4, clPlayer, 15, clHill, 2, clArcticWolf, 20), 1000, 100); Engine.SetProgress(95); if (g_MapSettings.Daytime !== undefined ? g_MapSettings.Daytime == "dawn" : randBool(1/3)) { setSkySet("sunset 1"); setSunColor(0.8, 0.7, 0.6); setAmbientColor(0.7, 0.6, 0.7); setSunElevation(Math.PI * randFloat(1/24, 1/7)); } else { setSkySet(pickRandom(["cumulus", "rain", "mountainous", "overcast", "rain", "stratus"])); setSunElevation(Math.PI * randFloat(1/9, 1/7)); } if (isNomad()) { let constraint = avoidClasses(clWater, 4, clMetal, 4, clRock, 4, clHill, 4, clFood, 2); [playerIDs, playerPosition] = placePlayersNomad(clPlayer, constraint); for (let i = 0; i < numPlayers; ++i) placePlayerBaseTreasures({ "playerID": playerIDs[i], "playerPosition": playerPosition[i], "BaseResourceClass": clBaseResource, "baseResourceConstraint": constraint, "types": treasures }); } setSunRotation(randomAngle()); setWaterColor(0.3, 0.3, 0.4); setWaterTint(0.75, 0.75, 0.75); setWaterMurkiness(0.92); setWaterWaviness(0.5); setWaterType("clap"); setFogThickness(0.76); setFogFactor(0.7); setPPEffect("hdr"); setPPContrast(0.6); setPPSaturation(0.45); setPPBloom(0.4); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/river_archipelago.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/river_archipelago.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/river_archipelago.js (revision 26381) @@ -1,521 +1,521 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); const tGrass = ["tropic_grass_c", "tropic_grass_c", "tropic_grass_c", "tropic_grass_c", "tropic_grass_plants", "tropic_plants", "tropic_plants_b"]; const tGrassA = "tropic_plants_c"; const tGrassB = "tropic_plants_c"; const tGrassC = "tropic_grass_c"; const tForestFloor = "tropic_grass_plants"; const tCliff = ["tropic_cliff_a", "tropic_cliff_a", "tropic_cliff_a", "tropic_cliff_a_plants"]; const tPlants = "tropic_plants"; const tRoad = "tropic_citytile_a"; const tRoadWild = "tropic_citytile_plants"; const tShoreBlend = "tropic_beach_dry_plants"; const tShore = "tropic_beach_dry"; const tWater = "tropic_beach_wet"; const oTree = "gaia/tree/toona"; const oPalm1 = "gaia/tree/palm_tropic"; const oPalm2 = "gaia/tree/palm_tropical"; const oStoneLarge = "gaia/rock/tropical_large"; const oStoneSmall = "gaia/rock/tropical_small"; const oMetalLarge = "gaia/ore/tropical_large"; const oFish = "gaia/fish/generic"; const oDeer = "gaia/fauna_deer"; const oTiger = "gaia/fauna_tiger"; const oBoar = "gaia/fauna_boar"; const oPeacock = "gaia/fauna_peacock"; const oBush = "gaia/fruit/berry_01"; const oSpearman = "units/maur/infantry_spearman_b"; const oArcher = "units/maur/infantry_archer_b"; const oArcherElephant = "units/maur/elephant_archer_b"; const aRockLarge = "actor|geology/stone_granite_large.xml"; const aRockMedium = "actor|geology/stone_granite_med.xml"; const aBush1 = "actor|props/flora/plant_tropic_a.xml"; const aBush2 = "actor|props/flora/plant_lg.xml"; const aBush3 = "actor|props/flora/plant_tropic_large.xml"; const pForestD = [tForestFloor + TERRAIN_SEPARATOR + oTree, tForestFloor]; const pForestP1 = [tForestFloor + TERRAIN_SEPARATOR + oPalm1, tForestFloor]; const pForestP2 = [tForestFloor + TERRAIN_SEPARATOR + oPalm2, tForestFloor]; const heightSeaGround = -8; const heightWaterLevel = 0; const heightShore = 1; const heightShoreBlend = 2.8; const heightLand = 3; const heightHill = 25; var g_Map = new RandomMap(heightSeaGround, tGrass); const numPlayers = getNumPlayers(); const mapCenter = g_Map.getCenter(); const mapBounds = g_Map.getBounds(); var clPlayer = g_Map.createTileClass(); var clPlayerTerritory = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clGaia = g_Map.createTileClass(); var clStrip = []; var startAngle = randomAngle(); var connectPlayers = randBool(); // Map layout var stripWidthsLeft = connectPlayers ? - [[0.03, 0.09], [0.14, 0.25], [0.36, 0.46]] : + [[0.03, 0.09], [0.14, 0.25], [0.36, 0.46]] : [[0, 0.06], [0.12, 0.23], [0.33, 0.43]]; // Mirror var stripWidthsRight = clone(stripWidthsLeft); stripWidthsRight.reverse(); stripWidthsRight = stripWidthsRight.map(strip => [1 - strip[1], 1 - strip[0]]); var stripWidths = stripWidthsLeft.concat(stripWidthsRight); g_Map.log("Creating strips"); for (let i = 0; i < stripWidths.length; ++i) { clStrip[i] = g_Map.createTileClass(); let isPlayerStrip = i == 2 || i == 3; for (let j = 0; j < scaleByMapSize(20, 100); ++j) { let position = new Vector2D( randFloat(mapBounds.bottom, mapBounds.top), fractionToTiles(randFloat(...stripWidths[i]))).rotateAround(startAngle, mapCenter).round(); createArea( new ChainPlacer( 1, Math.floor(scaleByMapSize(3, connectPlayers && isPlayerStrip ? 8 : 7)), Math.floor(scaleByMapSize(30, 60)), Infinity, position), [ new TerrainPainter(tGrass), new SmoothElevationPainter(ELEVATION_SET, heightLand, 3), new TileClassPainter(clStrip[i]) ]); } } Engine.SetProgress(20); var playerPosition = playerPlacementLine(startAngle, mapCenter, fractionToTiles(1 - stripWidthsLeft[2][0] - stripWidthsLeft[2][1])); // Either left vs right or top vs bottom var playerIDs = randBool() ? sortAllPlayers() : primeSortAllPlayers(); g_Map.log("Ensuring player territory"); var playerRadius = scaleByMapSize(12, 20); for (let i = 0; i < numPlayers; ++i) createArea( new ChainPlacer(1, 6, 40, 1, playerPosition[i], 0, [Math.floor(playerRadius)]), [ new TerrainPainter(tGrass), new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), new TileClassPainter(clPlayerTerritory) ]); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "baseResourceConstraint": stayClasses(clPlayerTerritory, 4), "Walls": "towers", "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad, "radius": playerRadius / 3 }, - "Chicken": { + "StartingAnimal": { "template": oPeacock }, "Berries": { "template": oBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oTree, "count": 40 } // No decoratives }); Engine.SetProgress(35); var areaWater = createArea( new HeightPlacer(Elevation_IncludeMin_ExcludeMax, -Infinity, heightWaterLevel), [ new TerrainPainter(tWater), new TileClassPainter(clWater) ]); createArea( new HeightPlacer(Elevation_IncludeMin_ExcludeMax, heightWaterLevel, heightShore), new TerrainPainter(tShore)); createArea( new HeightPlacer(Elevation_IncludeMin_ExcludeMax, heightShore, heightShoreBlend), new TerrainPainter(tShoreBlend)); Engine.SetProgress(40); if (!isNomad()) { g_Map.log("Creating gaia"); for (let i = 0; i < 2; ++i) for (let j = 0; j < scaleByMapSize(1, 8); ++j) createObjectGroups( new SimpleGroup( [ new SimpleObject(oSpearman, 8, 12, 2, 3), new SimpleObject(oArcher, 8, 12, 2, 3), new SimpleObject(oArcherElephant, 2, 3, 4, 5) ], true, clGaia), 0, [ avoidClasses( clWater, 2, clForest, 1, clPlayerTerritory, 0, clHill, 1, clGaia, 15), stayClasses(clStrip[i == 0 ? 0 : stripWidths.length - 1], 1) ], scaleByMapSize(5, 10), 50); } g_Map.log("Creating hills"); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(16, 40)), 0.1), [ new LayeredPainter([tCliff, tGrass], [3]), new SmoothElevationPainter(ELEVATION_SET, heightHill, 3), new TileClassPainter(clHill) ], [ avoidClasses( clPlayerTerritory, 0, clHill, 5, clGaia, 1, clWater, 2) ], scaleByMapSize(1, 5)); createBumps(avoidClasses(clPlayer, 8, clWater, 2), scaleByMapSize(20, 150), 2, 8, 4, 1, 4); Engine.SetProgress(50); g_Map.log("Creating forests"); var [forestTrees, stragglerTrees] = getTreeCounts(1000, 4000, 0.7); var types = [ [[tGrass, tGrass, tGrass, tGrass, pForestD], [tGrass, tGrass, tGrass, pForestD]], [[tGrass, tGrass, tGrass, tGrass, pForestP1], [tGrass, tGrass, tGrass, pForestP1]], [[tGrass, tGrass, tGrass, tGrass, pForestP2], [tGrass, tGrass, tGrass, pForestP2]] ]; var size = forestTrees / (scaleByMapSize(3, 6) * numPlayers); var num = Math.floor(size / types.length); for (let type of types) createAreas( new ChainPlacer( 1, Math.floor(scaleByMapSize(3, 5)), forestTrees / (num * Math.floor(scaleByMapSize(2, 4))), 0.5), [ new LayeredPainter(type, [2]), new TileClassPainter(clForest) ], avoidClasses( clPlayer, 12, clForest, 6, clHill, 0, clGaia, 1, clWater, 2), num); createStragglerTrees( [oTree, oPalm1, oPalm2], avoidClasses( clWater, 5, clForest, 1, clHill, 1, clPlayer, 8, clBaseResource, 4, clGaia, 1, clMetal, 4, clRock, 4), clForest, stragglerTrees); Engine.SetProgress(60); g_Map.log("Creating grass patches"); for (let size of [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)]) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5), [ new LayeredPainter([tGrassC, tGrassA, tGrassB], [2, 1]), new TileClassPainter(clDirt) ], avoidClasses( clWater, 8, clForest, 0, clHill, 0, clGaia, 1, clPlayerTerritory, 0, clDirt, 16), scaleByMapSize(20, 80)); g_Map.log("Creating dirt patches"); for (let size of [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)]) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5), [ new TerrainPainter(tPlants), new TileClassPainter(clDirt) ], avoidClasses( clWater, 8, clForest, 0, clHill, 0, clGaia, 1, clPlayerTerritory, 0, clDirt, 16), scaleByMapSize(20, 80)); g_Map.log("Creating stone mines"); createObjectGroups( new SimpleGroup( [ new SimpleObject(oStoneSmall, 0, 2, 0, 4), new SimpleObject(oStoneLarge, 1, 1, 0, 4) ], true, clRock), 0, avoidClasses( clWater, 3, clForest, 1, clPlayerTerritory, 0, clGaia, 1, clRock, 10, clHill, 1), scaleByMapSize(4, 16), 50); g_Map.log("Creating small stone mines"); createObjectGroups( new SimpleGroup([new SimpleObject(oStoneSmall, 2, 5, 1, 3)], true, clRock), 0, avoidClasses( clWater, 4, clForest, 1, clPlayerTerritory, 0, clGaia, 1, clRock, 10, clHill, 1), scaleByMapSize(2, 8), 50); g_Map.log("Creating metal mines"); createObjectGroups( new SimpleGroup([new SimpleObject(oMetalLarge, 1, 1, 0, 4)], true, clMetal), 0, avoidClasses( clWater, 4, clForest, 1, clPlayerTerritory, 0, clGaia, 1, clMetal, 10, clRock, 5, clHill, 1), scaleByMapSize(4, 16), 50); g_Map.log("Creating small decorative rocks"); createObjectGroups( new SimpleGroup([new SimpleObject(aRockMedium, 1, 3, 0, 1)], true), 0, avoidClasses( clWater, 2, clForest, 1, clGaia, 1, clPlayer, 8, clBaseResource, 4, clHill, 0), scaleByMapSize(50, 800), 20); g_Map.log("Creating large decorative rocks"); createObjectGroups( new SimpleGroup([ new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2) ], true), 0, avoidClasses( clWater, 2, clForest, 1, clGaia, 1, clPlayer, 8, clBaseResource, 4, clHill, 0), scaleByMapSize(25, 400), 50); g_Map.log("Creating small grass tufts"); createObjectGroups( new SimpleGroup([new SimpleObject(aBush1, 1, 2, 0, 1)]), 0, avoidClasses( clWater, 4, clHill, 2, clPlayer, 8, clGaia, 1, clBaseResource, 4, clDirt, 0), scaleByMapSize(100, 500)); Engine.SetProgress(70); g_Map.log("Creating large grass tufts"); createObjectGroups( new SimpleGroup([ new SimpleObject(aBush2, 2, 4, 0, 1.8, -Math.PI / 8, Math.PI / 8), new SimpleObject(aBush1, 3, 6, 1.2, 2.5, -Math.PI / 8, Math.PI / 8) ]), 0, avoidClasses( clWater, 4, clHill, 2, clGaia, 1, clPlayer, 8, clBaseResource, 4, clDirt, 1, clForest, 0), scaleByMapSize(100, 500)); Engine.SetProgress(85); g_Map.log("Creating bushes"); createObjectGroups( new SimpleGroup([ new SimpleObject(aBush3, 1, 2, 0, 2), new SimpleObject(aBush2, 2, 4, 0, 2) ]), 0, avoidClasses( clWater, 4, clHill, 1, clPlayerTerritory, 0, clGaia, 1, clDirt, 1), scaleByMapSize(100, 500)); g_Map.log("Creating deer"); createObjectGroups( new SimpleGroup([new SimpleObject(oDeer, 5, 7, 0, 4)], true, clFood), 0, avoidClasses( clWater, 4, clForest, 0, clPlayerTerritory, 0, clGaia, 1, clHill, 1, clFood, 20), 3 * numPlayers, 20); g_Map.log("Creating boar"); createObjectGroups( new SimpleGroup([new SimpleObject(oBoar, 2, 4, 0, 4)], true, clFood), 0, avoidClasses( clWater, 4, clForest, 0, clPlayerTerritory, 0, clGaia, 1, clHill, 1, clRock, 4, clMetal, 4, clFood, 20), 2 * numPlayers, 20); g_Map.log("Creating tigers"); createObjectGroups( new SimpleGroup([new SimpleObject(oTiger, 1, 1, 0, 4)], true, clFood), 0, avoidClasses( clWater, 4, clForest, 0, clPlayerTerritory, 0, clGaia, 1, clHill, 1, clRock, 4, clMetal, 4, clFood, 20), 2 * numPlayers, 20); Engine.SetProgress(95); g_Map.log("Creating berry bush"); createObjectGroups( new SimpleGroup([new SimpleObject(oBush, 5, 7, 0, 4)], true, clFood), 0, avoidClasses( clWater, 4, clForest, 0, clPlayerTerritory, 0, clGaia, 1, clHill, 1, clRock, 4, clMetal, 4, clFood, 10), randIntInclusive(1, 4) * numPlayers, 20); g_Map.log("Creating fish"); createObjectGroupsByAreas( new SimpleGroup([new SimpleObject(oFish, 2, 3, 0, 2)], true, clFood), 0, [avoidClasses(clFood, 15), stayClasses(clWater, 4)], scaleByMapSize(20, 100), 20, [areaWater]); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clFood, 2, clHill, 4)); setSunColor(0.6, 0.6, 0.6); setSunElevation(Math.PI/ 3); setWaterColor(0.424, 0.534, 0.639); setWaterTint(0.369, 0.765, 0.745); setWaterWaviness(1.0); setWaterType("default"); setWaterMurkiness(0.35); setFogFactor(0.03); setFogThickness(0.2); setPPEffect("hdr"); setPPContrast(0.7); setPPSaturation(0.65); setPPBloom(0.6); setSkySet("stratus"); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/rhine_marshlands.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rhine_marshlands.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/rhine_marshlands.js (revision 26381) @@ -1,309 +1,309 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); const tGrass = ["temp_grass", "temp_grass", "temp_grass_d"]; const tForestFloor = "temp_plants_bog"; const tGrassA = "temp_grass_plants"; const tGrassB = "temp_plants_bog"; const tMud = "temp_mud_a"; const tRoad = "temp_road"; const tRoadWild = "temp_road_overgrown"; const tShoreBlend = "temp_grass_plants"; const tShore = "temp_plants_bog"; const tWater = "temp_mud_a"; const oBeech = "gaia/tree/euro_beech"; const oOak = "gaia/tree/oak"; const oBerryBush = "gaia/fruit/berry_01"; const oDeer = "gaia/fauna_deer"; const oHorse = "gaia/fauna_horse"; const oWolf = "gaia/fauna_wolf"; const oRabbit = "gaia/fauna_rabbit"; const oStoneLarge = "gaia/rock/temperate_large"; const oStoneSmall = "gaia/rock/temperate_small"; const oMetalLarge = "gaia/ore/temperate_large"; const aGrass = "actor|props/flora/grass_soft_small_tall.xml"; const aGrassShort = "actor|props/flora/grass_soft_large.xml"; const aRockLarge = "actor|geology/stone_granite_med.xml"; const aRockMedium = "actor|geology/stone_granite_med.xml"; const aReeds = "actor|props/flora/reeds_pond_lush_a.xml"; const aLillies = "actor|props/flora/water_lillies.xml"; const aBushMedium = "actor|props/flora/bush_medit_me.xml"; const aBushSmall = "actor|props/flora/bush_medit_sm.xml"; const pForestD = [tForestFloor + TERRAIN_SEPARATOR + oBeech, tForestFloor]; const pForestP = [tForestFloor + TERRAIN_SEPARATOR + oOak, tForestFloor]; const heightMarsh = -2; const heightLand = 1; const heightOffsetBumpWater = 1; const heightOffsetBumpLand = 2; var g_Map = new RandomMap(heightLand, tGrass); const numPlayers = getNumPlayers(); var clPlayer = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oBeech }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(15); g_Map.log("Creating bumps"); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, Infinity), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBumpLand, 2), avoidClasses(clPlayer, 13), scaleByMapSize(300, 800)); g_Map.log("Creating marshes"); for (let i = 0; i < 7; ++i) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(6, 12)), Math.floor(scaleByMapSize(15, 60)), 0.8), [ new LayeredPainter([tShoreBlend, tShore, tWater], [1, 1]), new SmoothElevationPainter(ELEVATION_SET, heightMarsh, 3), new TileClassPainter(clWater) ], avoidClasses(clPlayer, 20, clWater, Math.round(scaleByMapSize(7,16)*randFloat(0.8,1.35))), scaleByMapSize(4,20)); g_Map.log("Creating reeds"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(aReeds, 5, 10, 0, 4), new SimpleObject(aLillies, 5, 10, 0, 4)], true), 0, stayClasses(clWater, 1), scaleByMapSize(400,2000), 100); Engine.SetProgress(40); g_Map.log("Creating bumps"); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, Infinity), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBumpWater, 2), stayClasses(clWater, 2), scaleByMapSize(50, 100)); g_Map.log("Creating forests"); var [forestTrees, stragglerTrees] = getTreeCounts(500, 2500, 0.7); var types = [ [[tForestFloor, tGrass, pForestD], [tForestFloor, pForestD]], [[tForestFloor, tGrass, pForestP], [tForestFloor, pForestP]] ]; var size = forestTrees / (scaleByMapSize(3,6) * numPlayers); var num = Math.floor(size / types.length); for (let type of types) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), forestTrees / (num * Math.floor(scaleByMapSize(2, 4))), Infinity), [ new LayeredPainter(type, [2]), new TileClassPainter(clForest) ], avoidClasses(clPlayer, 20, clWater, 0, clForest, 10), num); Engine.SetProgress(50); g_Map.log("Creating mud patches"); for (let size of [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)]) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, Infinity), [ new LayeredPainter([tGrassA, tGrassB, tMud], [1, 1]), new TileClassPainter(clDirt) ], avoidClasses(clWater, 1, clForest, 0, clDirt, 5, clPlayer, 8), scaleByMapSize(15, 45)); g_Map.log("Creating stone mines"); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clWater, 0, clForest, 1, clPlayer, 20, clRock, 10)], scaleByMapSize(4,16), 100 ); g_Map.log("Creating small stone quarries"); group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clWater, 0, clForest, 1, clPlayer, 20, clRock, 10)], scaleByMapSize(4,16), 100 ); g_Map.log("Creating metal mines"); group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4)], true, clMetal); createObjectGroupsDeprecated(group, 0, [avoidClasses(clWater, 0, clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5)], scaleByMapSize(4,16), 100 ); Engine.SetProgress(60); g_Map.log("Creating small decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockMedium, 1,3, 0,1)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 0), scaleByMapSize(16, 262), 50 ); Engine.SetProgress(65); g_Map.log("Creating large decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockLarge, 1,2, 0,1), new SimpleObject(aRockMedium, 1,3, 0,2)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 0), scaleByMapSize(8, 131), 50 ); Engine.SetProgress(70); g_Map.log("Creating deer"); group = new SimpleGroup( [new SimpleObject(oDeer, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clFood, 13), 6 * numPlayers, 50 ); g_Map.log("Creating horse"); group = new SimpleGroup( [new SimpleObject(oHorse, 1,3, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clFood, 13), 3 * numPlayers, 50 ); Engine.SetProgress(75); g_Map.log("Creating rabbit"); group = new SimpleGroup( [new SimpleObject(oRabbit, 5,7, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clFood, 13), 6 * numPlayers, 50 ); g_Map.log("Creating wolf"); group = new SimpleGroup( [new SimpleObject(oWolf, 1,3, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 20, clFood, 13), 3 * numPlayers, 50 ); g_Map.log("Creating berry bush"); group = new SimpleGroup( [new SimpleObject(oBerryBush, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clFood, 10), randIntInclusive(1, 4) * numPlayers + 2, 50 ); Engine.SetProgress(80); createStragglerTrees( [oOak, oBeech], avoidClasses(clForest, 1, clPlayer, 13, clMetal, 6, clRock, 6, clWater, 0), clForest, stragglerTrees); Engine.SetProgress(85); g_Map.log("Creating small grass tufts"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(aGrassShort, 1, 2, 0, 1)]), 0, avoidClasses(clWater, 2, clPlayer, 13, clDirt, 0), scaleByMapSize(13, 200)); Engine.SetProgress(90); g_Map.log("Creating large grass tufts"); createObjectGroupsDeprecated( new SimpleGroup( [ new SimpleObject(aGrass, 2, 4, 0, 1.8), new SimpleObject(aGrassShort, 3, 6, 1.2, 2.5) ]), 0, avoidClasses(clWater, 3, clPlayer, 13, clDirt, 1, clForest, 0), scaleByMapSize(13, 200)); Engine.SetProgress(95); g_Map.log("Creating bushes"); createObjectGroupsDeprecated( new SimpleGroup( [ new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2) ]), 0, avoidClasses(clWater, 1, clPlayer, 13, clDirt, 1), scaleByMapSize(13, 200), 50); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clFood, 2)); setSkySet("cirrus"); setWaterColor(0.753,0.635,0.345); // muddy brown setWaterTint(0.161,0.514,0.635); // clear blue for blueness setWaterMurkiness(0.8); setWaterWaviness(1.0); setWaterType("clap"); setFogThickness(0.25); setFogFactor(0.6); setPPEffect("hdr"); setPPSaturation(0.44); setPPBloom(0.3); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/rmbiome/defaultbiome.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rmbiome/defaultbiome.json (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/rmbiome/defaultbiome.json (revision 26381) @@ -1,67 +1,67 @@ { "Environment": { "AmbientColor": { "r": 0.364706, "g": 0.376471, "b": 0.419608 } }, "Terrains": { "mainTerrain": [ "temperate_grass_02" ], "forestFloor1": "temperate_forestfloor_01", "forestFloor2": "temperate_forestfloor_02", "tier1Terrain": "temperate_grass_dirt_02", "tier2Terrain": "temperate_grass_03", "tier3Terrain": "temperate_grass_04", "tier4Terrain": "temperate_grass_01", "cliff": [ "temperate_cliff_01", "temperate_cliff_02" ], "hill": [ "temperate_rocks_dirt_01", "temperate_grass_dirt_03" ], "dirt": [ "temperate_mud_01", "temperate_grass_mud_01" ], "road": "temperate_paving_03", "roadWild": "temperate_paving_01", "shoreBlend": "temperate_grass_dirt_01", "shore": "temperate_rocks_dirt_01", "water": "temperate_rocks_dirt_01" }, "Gaia": { "tree1": "gaia/tree/oak", "tree2": "gaia/tree/oak_holly", "tree3": "gaia/tree/oak_hungarian", "tree4": "gaia/tree/pine_black", "tree5": "gaia/tree/pine_maritime", "fruitBush": "gaia/fruit/berry_01", - "chicken": "gaia/fauna_chicken", + "startingAnimal": "gaia/fauna_chicken", "fish": "gaia/fish/generic", "mainHuntableAnimal": "gaia/fauna_deer", "secondaryHuntableAnimal": "gaia/fauna_sheep", "stoneLarge": "gaia/rock/temperate_large", "stoneSmall": "gaia/rock/temperate_cut", "metalLarge": "gaia/ore/temperate_01", "metalSmall": "gaia/ore/temperate_02" }, "Decoratives": { "grass": "actor|props/flora/grass_soft_large_tall.xml", "grassShort": "actor|props/flora/grass_soft_large.xml", "reeds": "actor|props/flora/cattails.xml", "lillies": "actor|props/flora/water_lillies.xml", "rockLarge": "actor|geology/stone_granite_med.xml", "rockMedium": "actor|geology/stone_granite_small.xml", "bushMedium": "actor|props/flora/bush_medit_me.xml", "bushSmall": "actor|props/flora/bush_medit_sm.xml", "tree": "actor|flora/trees/elm_dead.xml" }, "ResourceCounts": { "trees": { "min": 500, "max": 3000, "forestProbability": 0.7 } } } Index: ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/autumn.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/autumn.json (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/autumn.json (revision 26381) @@ -1,96 +1,96 @@ { "Description": { "Title": "Rhine Valley (Fall)", "Description": "The first leaves have fallen. The landscape is a dazzling dash of colors irrevocably intertwined. The native beech and oak trees of this temperate zone display a multi-colored foliage while animals try to prepare for the approaching winter." }, "Environment": { "SunColor": { "r": 1.032, "g": 0.99, "b": 0.866 }, "SunElevation": 0.446, "SunRotation": -0.488, "AmbientColor": { "r": 0.364706, "g": 0.376471, "b": 0.419608 }, "Water": { "WaterBody": { "Color": { "r": 0.419608, "g": 0.364706, "b": 0.313726 }, "Tint": { "r": 0.501961, "g": 0.501961, "b": 0.247059 }, "Murkiness": 0.97, "Waviness": 5 } }, "Postproc": { "PostprocEffect": "hdr", "Saturation": 0.95, "Contrast": 1.05, "Bloom": 0.16 } }, "Terrains": { "mainTerrain": [ "temperate_grass_04", "temperate_grass_05" ], "forestFloor1": "temperate_forestfloor_02_autumn", "forestFloor2": "temperate_forestfloor_02_autumn", "cliff": [ "temperate_cliff_01", "temperate_cliff_02" ], "tier1Terrain": [ "temperate_grass_05" ], "tier2Terrain": [ "temperate_grass_dirt_02" ], "tier3Terrain": [ "alpine_grass_01" ], "tier4Terrain": [ "temperate_grass_02" ], "hill": [ "temperate_rocks_dirt_01" ], "dirt": [ "temperate_grass_dirt_01", "temperate_grass_dirt_02" ], "road": "temperate_paving_01", "roadWild": "temperate_paving_01", "shoreBlend": "temperate_grass_dirt_01", "shore": "temperate_grass_dirt_01", "water": "temperate_mud_01" }, "Gaia": { "tree1": "gaia/tree/oak_aut", "tree2": "gaia/tree/euro_beech_aut", "tree3": "gaia/tree/oak_hungarian_autumn", "tree4": "gaia/tree/poplar_lombardy_autumn", "tree5": "gaia/tree/temperate_autumn", "fruitBush": "gaia/fruit/berry_01", - "chicken": "gaia/fauna_chicken", + "startingAnimal": "gaia/fauna_chicken", "fish": "gaia/fish/generic", "mainHuntableAnimal": "gaia/fauna_deer", "secondaryHuntableAnimal": "gaia/fauna_sheep", "stoneLarge": "gaia/rock/temperate_large_02", "stoneSmall": "gaia/rock/temperate_small", "metalLarge": "gaia/ore/temperate_01", "metalSmall": "gaia/ore/temperate_small" }, "Decoratives": { "grass": "actor|props/flora/grass_soft_large_tall.xml", "grassShort": "actor|props/flora/grass_soft_large.xml", "reeds": "actor|props/flora/cattails.xml", "lillies": "actor|props/flora/water_lillies.xml", "rockLarge": "actor|geology/stone_granite_med.xml", "rockMedium": "actor|geology/stone_granite_small.xml", "bushMedium": "gaia/tree/bush_temperate", "bushSmall": "actor|props/flora/bush_medit_sm.xml", "tree": "actor|flora/trees/elm_dead.xml" }, "ResourceCounts": { "trees": { "min": 1000, "max": 6000, "forestProbability": 0.7 } } } Index: ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/savanna.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/savanna.json (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/savanna.json (revision 26381) @@ -1,91 +1,91 @@ { "Description": { "Title": "Sudanian Savanna", "Description": "The transition between the dry Sahara to the north and the tropical forests to the south. The sunlight floods through the open canopy and lights the grassland between the trees, where herds of zebras, wildebeest, giraffes and elephants roam." }, "Environment": { "SkySet": "cloudless", "SunElevation": 0.6, "SunRotation": -0.45, "SunColor": { "r": 1.246471, "g": 1.108824, "b": 0.98902 }, "AmbientColor": { "r": 0.351373, "g": 0.402353, "b": 0.476863 }, "Water": { "WaterBody": { "Color": { "r": 0.059608, "g": 0.204706, "b": 0.223726 }, "Tint": { "r": 0.201961, "g": 0.301961, "b": 0.047059 }, "Murkiness": 0.92, "Waviness": 1.5 } }, "Fog": { "FogThickness": 0.005, "FogFactor": 0.0015, "FogColor": { "r": 0.847059, "g": 0.737255, "b": 0.482353 } }, "Postproc": { "PostprocEffect": "hdr", "Saturation": 1.0, "Brightness": 0.0, "Contrast": 1.00, "Bloom": 0.132 } }, "Terrains": { "mainTerrain": [ "savanna_grass_01" ], "forestFloor1": "sahara_dirt_cracks_01", "forestFloor2": "sahara_dirt_02", "cliff": [ "sahara_rock_01" ], "tier1Terrain": "aegean_grass_01", "tier2Terrain": "savanna_grass_03", "tier3Terrain": "aegean_grass_01", "tier4Terrain": "aegean_grass_02", "hill": [ "sahara_rock_01" ], "dirt": [ "aegean_grass_02" ], "road": "sahara_paving_stones_02", "roadWild": "sahara_paving_stones_02", "shoreBlend": "steppe_grass_04", "shore": "steppe_grass_04", "water": "india_sand_01" }, "Gaia": { "tree1": "gaia/tree/acacia", "tree2": "gaia/tree/baobab", "tree3": "gaia/tree/bush_temperate", "tree4": "gaia/tree/baobab_3_mature", "tree5": "gaia/tree/baobab", "fruitBush": "gaia/fruit/berry_05", - "chicken": "gaia/fauna_chicken", + "startingAnimal": "gaia/fauna_chicken", "fish": "gaia/fish/generic", "secondaryHuntableAnimal": "gaia/fauna_gazelle", "stoneLarge": "gaia/rock/desert_large", "stoneSmall": "gaia/rock/temperate_small", "metalLarge": "gaia/ore/sahara_01", "metalSmall": "gaia/ore/desert_small" }, "Decoratives": { "grass": "actor|props/flora/grass_savanna_field_tall.xml", "grassShort": "actor|props/flora/grass_savanna.xml", "reeds": "actor|props/flora/reeds_pond_lush_a.xml", "lillies": "actor|props/flora/reeds_pond_lush_b.xml", "rockLarge": "actor|geology/stone_desert_med.xml", "rockMedium": "actor|geology/stone_desert_med.xml", "bushMedium": "actor|props/flora/bush_desert_dry_a.xml", "bushSmall": "actor|props/flora/bush_desert_dry_a.xml", "tree": "gaia/tree/bush_temperate" }, "ResourceCounts": { "trees": { "min": 1000, "max": 4500, "forestProbability": 0.25 } } } Index: ps/trunk/binaries/data/mods/public/maps/random/rmbiome/gulf_of_bothnia/late_spring.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rmbiome/gulf_of_bothnia/late_spring.json (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/rmbiome/gulf_of_bothnia/late_spring.json (revision 26381) @@ -1,72 +1,72 @@ { "Description": { "Title": "Late Spring", "Description": "A late spring breeze ripples through the conifer forests of the Gulf of Bothnia. Herds of deer dot the landscape and playful rabbits frolick in the undergrowth." }, "Environment": { "SkySet": "stormy", "SunColor": { "r": 1.032, "g": 0.99, "b": 0.866 }, "SunElevation": 0.846, "SunRotation": -0.488, "AmbientColor": { "r": 0.264706, "g": 0.276471, "b": 0.319608 }, "Water": { "WaterBody": { "Type": "lake", "Color": { "r": 0.035, "g": 0.098, "b": 0.314 }, "Tint": { "r": 0.28, "g": 0.3, "b": 0.59 }, "Murkiness": 0.88, "Waviness": 5 } }, "Fog": { "FogThickness": 0.26, "FogFactor": 0.004 }, "Postproc": { "PostprocEffect": "hdr", "Saturation": 0.96, "Contrast": 1.03, "Bloom": 0.176 } }, "Terrains": { "mainTerrain": "alpine_dirt_grass_50", "forestFloor1": "alpine_forrestfloor", "cliff": ["alpine_cliff_a", "alpine_cliff_b", "alpine_cliff_c"], "tier1Terrain": "alpine_grass_rocky", "tier2Terrain": ["alpine_grass_snow_50", "alpine_dirt_snow"], "tier3Terrain": "alpine_snow_rocky", "road": "new_alpine_citytile", "roadWild": "new_alpine_citytile", "shore": "alpine_shore_rocks_grass_50", "water": "alpine_shore_rocks" }, "Gaia": { "tree1": "gaia/tree/pine", "fruitBush": "gaia/fruit/berry_01", - "chicken": "gaia/fauna_chicken", + "startingAnimal": "gaia/fauna_chicken", "mainHuntableAnimal": "gaia/fauna_deer", "secondaryHuntableAnimal": "gaia/fauna_rabbit", "fish": "gaia/fish/generic", "stoneLarge": "gaia/rock/alpine_large", "stoneSmall": "gaia/rock/alpine_small", "metalLarge": "gaia/ore/alpine_large" }, "Decoratives": { "grass": "actor|props/flora/grass_soft_small_tall.xml", "grassShort": "actor|props/flora/grass_soft_large.xml", "rockLarge": "actor|geology/stone_granite_med.xml", "rockMedium": "actor|geology/stone_granite_med.xml", "bushMedium": "actor|props/flora/bush_medit_me.xml", "bushSmall": "actor|props/flora/bush_medit_sm.xml" }, "ResourceCounts": { "fish": { "min": 20, "max": 80 }, "bush": { "min": 13, "max": 200 } }, "Heights": { "seaGround": -3, "shore": 1, "land": 3 } } Index: ps/trunk/binaries/data/mods/public/maps/random/saharan_oases.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/saharan_oases.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/saharan_oases.js (revision 26381) @@ -1,241 +1,241 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); const tPrimary = "desert_sand_dunes_100"; const tCity = "desert_city_tile"; const tCityPlaza = "desert_city_tile_plaza"; const tFineSand = "desert_sand_smooth"; const tDirt1 = "desert_dirt_rough_2"; const tSandDunes = "desert_sand_dunes_50"; const tDirt2 = "desert_dirt_rough"; const tDirtCracks = "desert_dirt_cracks"; const tShore = "desert_shore_stones"; const tWaterDeep = "desert_shore_stones_wet"; const tLush = "desert_grass_a"; const tSLush = "desert_grass_a_sand"; const oGrapeBush = "gaia/fruit/grapes"; const oCamel = "gaia/fauna_camel"; const oGazelle = "gaia/fauna_gazelle"; const oGoat = "gaia/fauna_goat"; const oStoneLarge = "gaia/rock/badlands_large"; const oStoneSmall = "gaia/rock/desert_small"; const oMetalLarge = "gaia/ore/desert_large"; const oDatePalm = "gaia/tree/date_palm"; const oSDatePalm = "gaia/tree/cretan_date_palm_short"; const oWoodTreasure = "gaia/treasure/wood"; const oFoodTreasure = "gaia/treasure/food_bin"; const aBush1 = "actor|props/flora/bush_desert_a.xml"; const aBush2 = "actor|props/flora/bush_desert_dry_a.xml"; const aBush3 = "actor|props/flora/bush_medit_sm_dry.xml"; const aBush4 = "actor|props/flora/plant_desert_a.xml"; const aDecorativeRock = "actor|geology/stone_desert_med.xml"; const pForest = [tLush + TERRAIN_SEPARATOR + oDatePalm, tLush + TERRAIN_SEPARATOR + oSDatePalm, tLush]; const heightLand = 1; const heightOffsetOasis = -3; var g_Map = new RandomMap(heightLand, tPrimary); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); var clPlayer = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clTreasure = g_Map.createTileClass(); var [playerIDs, playerPosition, playerAngle] = playerPlacementCircle(fractionToTiles(0.35)); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tCityPlaza, "innerTerrain": tCity }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oGrapeBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oSDatePalm }, "Decoratives": { "template": aBush1 } }); Engine.SetProgress(30); g_Map.log("Creating oases"); var oasisRadius = fractionToTiles(scaleByMapSize(0.19, 0.22)); for (let i = 0; i < numPlayers; ++i) { let position = Vector2D.add(mapCenter, new Vector2D(oasisRadius, 0).rotate(-playerAngle[i])); createArea( new ClumpPlacer(diskArea(scaleByMapSize(16, 60)) * 0.185, 0.6, 0.15, 0, position), [ new LayeredPainter( [tSLush ,[tLush, pForest], [tLush, pForest], tShore, tShore, tWaterDeep], [2, 2, 1, 3, 1]), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetOasis, 10), new TileClassPainter(clWater) ]); } Engine.SetProgress(50); g_Map.log("Creating grass patches"); for (let size of [scaleByMapSize(3, 48), scaleByMapSize(5, 84), scaleByMapSize(8, 128)]) createAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), [ new LayeredPainter( [[tDirt1, tSandDunes], [tSandDunes, tDirt2], [tDirt2, tDirt1]], [1, 1] ), new TileClassPainter(clDirt) ], avoidClasses(clForest, 0, clPlayer, 0, clWater, 1, clDirt, 5), scaleByMapSize(15, 45)); Engine.SetProgress(55); g_Map.log("Creating dirt patches"); for (let size of [scaleByMapSize(3, 48), scaleByMapSize(5, 84), scaleByMapSize(8, 128)]) createAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), [ new LayeredPainter( [[tDirt2, tDirtCracks], [tDirt2, tFineSand], [tDirtCracks, tFineSand]], [1, 1] ), new TileClassPainter(clDirt) ], avoidClasses(clForest, 0, clDirt, 5, clPlayer, 0, clWater, 1), scaleByMapSize(15, 45)); Engine.SetProgress(60); g_Map.log("Creating stone mines"); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 26, clRock, 10, clWater, 1), 2*scaleByMapSize(4,16), 100 ); g_Map.log("Creating small stone quarries"); group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 26, clRock, 10, clWater, 1), 2*scaleByMapSize(4,16), 100 ); g_Map.log("Creating metal mines"); group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4)], true, clMetal); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 26, clMetal, 10, clRock, 5, clWater, 1), 2*scaleByMapSize(4,16), 100 ); g_Map.log("Creating small decorative rocks"); group = new SimpleGroup( [new SimpleObject(aDecorativeRock, 1,3, 0,1)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clWater, 1, clForest, 0, clPlayer, 0), scaleByMapSize(16, 262), 50 ); g_Map.log("Creating shrubs"); group = new SimpleGroup( [new SimpleObject(aBush2, 1,2, 0,1), new SimpleObject(aBush1, 1,3, 0,2), new SimpleObject(aBush4, 1,2, 0,1), new SimpleObject(aBush3, 1,3, 0,2)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clWater, 1, clPlayer, 0), scaleByMapSize(10, 100), 50 ); g_Map.log("Creating small decorative rocks on mines"); group = new SimpleGroup( [new SimpleObject(aDecorativeRock, 1,3, 0,1)], true ); createObjectGroupsDeprecated( group, 0, stayClasses(clRock, 0), 5*scaleByMapSize(16, 262), 50 ); group = new SimpleGroup( [new SimpleObject(aDecorativeRock, 1,3, 0,1)], true ); createObjectGroupsDeprecated( group, 0, stayClasses(clMetal, 0), 5*scaleByMapSize(16, 262), 50 ); g_Map.log("Creating gazelles"); group = new SimpleGroup([new SimpleObject(oGazelle, 5,7, 0,4)], true, clFood); createObjectGroupsDeprecated(group, 0, borderClasses(clWater, 8, 5), 6*scaleByMapSize(5,20), 50 ); g_Map.log("Creating goats"); group = new SimpleGroup([new SimpleObject(oGoat, 2,4, 0,3)], true, clFood); createObjectGroupsDeprecated(group, 0, borderClasses(clWater, 8, 5), 5*scaleByMapSize(5,20), 50 ); g_Map.log("Creating treasures"); group = new SimpleGroup([new SimpleObject(oFoodTreasure, 1,1, 0,2)], true, clTreasure); createObjectGroupsDeprecated(group, 0, borderClasses(clWater, 8, 5), 3*scaleByMapSize(5,20), 50 ); group = new SimpleGroup([new SimpleObject(oWoodTreasure, 1,1, 0,2)], true, clTreasure); createObjectGroupsDeprecated(group, 0, borderClasses(clWater, 8, 5), 3*scaleByMapSize(5,20), 50 ); g_Map.log("Creating camels"); group = new SimpleGroup([new SimpleObject(oCamel, 2,4, 0,2)], true, clFood); createObjectGroupsDeprecated(group, 0, borderClasses(clWater, 14, 5), 5*scaleByMapSize(5,20), 50 ); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clFood, 2, clTreasure, 2)); setSkySet("sunny"); setSunColor(0.746, 0.718, 0.539); setWaterColor(0, 0.227, 0.843); setWaterTint(0, 0.545, 0.859); setWaterWaviness(1.0); setWaterType("clap"); setWaterMurkiness(0.5); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/snowflake_searocks.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/snowflake_searocks.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/snowflake_searocks.js (revision 26381) @@ -1,446 +1,446 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); TILE_CENTERED_HEIGHT_MAP = true; setSelectedBiome(); const tMainTerrain = g_Terrains.mainTerrain; const tForestFloor1 = g_Terrains.forestFloor1; const tForestFloor2 = g_Terrains.forestFloor2; const tCliff = g_Terrains.cliff; const tTier1Terrain = g_Terrains.tier1Terrain; const tTier2Terrain = g_Terrains.tier2Terrain; const tTier3Terrain = g_Terrains.tier3Terrain; const tHill = g_Terrains.mainTerrain; const tRoad = g_Terrains.road; const tRoadWild = g_Terrains.roadWild; const tTier4Terrain = g_Terrains.tier4Terrain; const tWater = g_Terrains.water; const oTree1 = g_Gaia.tree1; const oTree2 = g_Gaia.tree2; const oTree3 = g_Gaia.tree3; const oTree4 = g_Gaia.tree4; const oTree5 = g_Gaia.tree5; const oFruitBush = g_Gaia.fruitBush; const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal; const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal; const oStoneLarge = g_Gaia.stoneLarge; const oStoneSmall = g_Gaia.stoneSmall; const oMetalLarge = g_Gaia.metalLarge; const aGrass = g_Decoratives.grass; const aGrassShort = g_Decoratives.grassShort; const aRockLarge = g_Decoratives.rockLarge; const aRockMedium = g_Decoratives.rockMedium; const aBushMedium = g_Decoratives.bushMedium; const aBushSmall = g_Decoratives.bushSmall; const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2]; const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1]; const heightIsland = 20; const heightSeaGround = -5; var g_Map = new RandomMap(heightSeaGround, tWater); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); var clPlayer = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clLand = g_Map.createTileClass(); const playerIslandRadius = scaleByMapSize(15, 30); const islandBetweenPlayerAndCenterDist = 0.16; const islandBetweenPlayerAndCenterRadius = 0.81; const centralIslandRadius = 0.36; var [playerIDs, playerPosition, playerAngle, startAngle] = playerPlacementCircle(fractionToTiles(0.35)); var numIslands = 0; var isConnected = []; var islandPos = []; function initIsConnected() { for (let m = 0; m < numIslands; ++m) { isConnected[m] = []; for (let n = 0; n < numIslands; ++n) isConnected[m][n] = 0; } } function createIsland(islandID, size, tileClass) { createArea( new ClumpPlacer(size * diskArea(playerIslandRadius), 0.95, 0.6, Infinity, islandPos[islandID]), [ new TerrainPainter(tHill), new SmoothElevationPainter(ELEVATION_SET, heightIsland, 2), new TileClassPainter(tileClass) ]); } function createIslandAtRadialLocation(playerID, islandID, playerIDOffset, distFromCenter, islandRadius) { let angle = startAngle + (playerID * 2 + playerIDOffset) * Math.PI / numPlayers; islandPos[islandID] = Vector2D.add(mapCenter, new Vector2D(fractionToTiles(distFromCenter), 0).rotate(-angle)).round(); createIsland(islandID, islandRadius, clLand); } function createSnowflakeSearockWithCenter(sizeID) { let [tertiaryIslandDist, tertiaryIslandRadius, islandBetweenPlayersDist, islandBetweenPlayersRadius] = islandSizes[sizeID]; let islandID_center = 4 * numPlayers; numIslands = islandID_center + 1; initIsConnected(); g_Map.log("Creating central island"); islandPos[islandID_center] = mapCenter; createIsland(islandID_center, centralIslandRadius, clLand); for (let playerID = 0; playerID < numPlayers; ++playerID) { let playerID_neighbor = playerID + 1 < numPlayers ? playerID + 1 : 0; let islandID_player = playerID; let islandID_playerNeighbor = playerID_neighbor; let islandID_betweenPlayers = playerID + numPlayers; let islandID_betweenPlayerAndCenter = playerID + 2 * numPlayers; let islandID_betweenPlayerAndCenterNeighbor = playerID_neighbor + 2 * numPlayers; let islandID_tertiary = playerID + 3 * numPlayers; g_Map.log("Creating island between the player and their neighbor"); isConnected[islandID_betweenPlayers][islandID_player] = 1; isConnected[islandID_betweenPlayers][islandID_playerNeighbor] = 1; createIslandAtRadialLocation(playerID, islandID_betweenPlayers, 1, islandBetweenPlayersDist, islandBetweenPlayersRadius); g_Map.log("Creating an island between the player and the center"); isConnected[islandID_betweenPlayerAndCenter][islandID_player] = 1; isConnected[islandID_betweenPlayerAndCenter][islandID_center] = 1; isConnected[islandID_betweenPlayerAndCenter][islandID_betweenPlayerAndCenterNeighbor] = 1; createIslandAtRadialLocation(playerID, islandID_betweenPlayerAndCenter, 0, islandBetweenPlayerAndCenterDist, islandBetweenPlayerAndCenterRadius); g_Map.log("Creating tertiary island, at the map border"); isConnected[islandID_tertiary][islandID_betweenPlayers] = 1; createIslandAtRadialLocation(playerID, islandID_tertiary, 1, tertiaryIslandDist, tertiaryIslandRadius); } } /** * Creates one island in front of every player and connects it with the neighbors. */ function createSnowflakeSearockWithoutCenter() { numIslands = 2 * numPlayers; initIsConnected(); for (let playerID = 0; playerID < numPlayers; ++playerID) { let playerID_neighbor = playerID + 1 < numPlayers ? playerID + 1 : 0; let islandID_player = playerID; let islandID_playerNeighbor = playerID_neighbor; let islandID_inFrontOfPlayer = playerID + numPlayers; let islandID_inFrontOfPlayerNeighbor = playerID_neighbor + numPlayers; isConnected[islandID_player][islandID_playerNeighbor] = 1; isConnected[islandID_player][islandID_inFrontOfPlayer] = 1; isConnected[islandID_inFrontOfPlayer][islandID_inFrontOfPlayerNeighbor] = 1; createIslandAtRadialLocation(playerID, islandID_inFrontOfPlayer, 0, islandBetweenPlayerAndCenterDist, islandBetweenPlayerAndCenterRadius); } } function createSnowflakeSearockTiny() { numIslands = numPlayers + 1; initIsConnected(); let islandID_center = numPlayers; g_Map.log("Creating central island"); islandPos[islandID_center] = mapCenter; createIsland(numPlayers, 1, clLand); for (let playerID = 0; playerID < numPlayers; ++playerID) { let islandID_player = playerID; isConnected[islandID_player][islandID_center] = 1; } } const islandSizes = { "medium": [0.41, 0.49, 0.26, 1], "large1": [0.41, 0.49, 0.24, 1], "large2": [0.41, 0.36, 0.28, 0.81] }; if (mapSize <= 128) { createSnowflakeSearockTiny(); } else if (mapSize <= 192) { createSnowflakeSearockWithoutCenter(); } else if (mapSize <= 256) { if (numPlayers < 6) createSnowflakeSearockWithCenter("medium"); else createSnowflakeSearockWithoutCenter(); } else if (mapSize <= 320) { if (numPlayers < 8) createSnowflakeSearockWithCenter("medium"); else createSnowflakeSearockWithoutCenter(); } else createSnowflakeSearockWithCenter(numPlayers < 6 ? "large1" : "large2"); g_Map.log("Creating player islands"); for (let i = 0; i < numPlayers; ++i) { islandPos[i] = playerPosition[i]; createIsland(i, 1, isNomad() ? clLand : clPlayer); } g_Map.log("Creating connectors"); for (let i = 0; i < numIslands; ++i) for (let j = 0; j < numIslands; ++j) if (isConnected[i][j]) createArea( new PathPlacer(islandPos[i], islandPos[j], 11, 0, 1, 0, 0, Infinity), [ new SmoothElevationPainter(ELEVATION_SET, heightIsland, 2), new TerrainPainter(tHill), new TileClassPainter(clLand) ]); g_Map.log("Painting cliffs"); createArea( new MapBoundsPlacer(), new TerrainPainter(tCliff), new SlopeConstraint(2, Infinity)); Engine.SetProgress(30); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], // PlayerTileClass already marked above "BaseResourceClass": clBaseResource, "baseResourceConstraint": stayClasses(clPlayer, 4), "Walls": "towers", "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oFruitBush, "distance": playerIslandRadius - 4 }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ], "distance": playerIslandRadius - 4 }, "Trees": { "template": oTree1, "count": scaleByMapSize(10, 50), "minDist": 11, "maxDist": 11 }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(40); g_Map.log("Creating forests"); var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(1)); var types = [ [[tForestFloor2, tMainTerrain, pForest1], [tForestFloor2, pForest1]], [[tForestFloor1, tMainTerrain, pForest2], [tForestFloor1, pForest2]] ]; var size = forestTrees / (scaleByMapSize(2, 8) * numPlayers) * (currentBiome() == "generic/savanna" ? 2 : 1); var num = Math.floor(size / types.length); for (let type of types) createAreas( new ClumpPlacer(forestTrees / num, 0.1, 0.1, Infinity), [ new LayeredPainter(type, [2]), new TileClassPainter(clForest) ], [avoidClasses(clPlayer, 6, clForest, 10), stayClasses(clLand, 4)], num); Engine.SetProgress(55); g_Map.log("Creating stone mines"); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 1, clPlayer, 10, clRock, 10), stayClasses(clLand, 5)], 5*scaleByMapSize(4,16), 100 ); g_Map.log("Creating small stone quarries"); group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 1, clPlayer, 10, clRock, 10), stayClasses(clLand, 5)], 5*scaleByMapSize(4,16), 100 ); g_Map.log("Creating metal mines"); group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4)], true, clMetal); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 1, clPlayer, 10, clMetal, 10, clRock, 5), stayClasses(clLand, 5)], 5*scaleByMapSize(4,16), 100 ); Engine.SetProgress(65); g_Map.log("Creating dirt patches"); for (let size of [scaleByMapSize(3, 48), scaleByMapSize(5, 84), scaleByMapSize(8, 128)]) createAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), [ new LayeredPainter([[tMainTerrain, tTier1Terrain],[tTier1Terrain, tTier2Terrain], [tTier2Terrain, tTier3Terrain]], [1, 1]), new TileClassPainter(clDirt) ], [avoidClasses(clForest, 0, clDirt, 5, clPlayer, 12), stayClasses(clLand, 5)], scaleByMapSize(15, 45)); g_Map.log("Creating grass patches"); for (let size of [scaleByMapSize(2, 32), scaleByMapSize(3, 48), scaleByMapSize(5, 80)]) createAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), new TerrainPainter(tTier4Terrain), [avoidClasses(clForest, 0, clDirt, 5, clPlayer, 12), stayClasses(clLand, 5)], scaleByMapSize(15, 45)); g_Map.log("Creating small decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockMedium, 1,3, 0,1)], true ); createObjectGroupsDeprecated( group, 0, [avoidClasses(clForest, 0, clPlayer, 0), stayClasses(clLand, 4)], scaleByMapSize(16, 262), 50 ); g_Map.log("Creating large decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockLarge, 1,2, 0,1), new SimpleObject(aRockMedium, 1,3, 0,2)], true ); createObjectGroupsDeprecated( group, 0, [avoidClasses(clForest, 0, clPlayer, 0), stayClasses(clLand, 4)], scaleByMapSize(8, 131), 50 ); Engine.SetProgress(70); g_Map.log("Creating deer"); group = new SimpleGroup( [new SimpleObject(oMainHuntableAnimal, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 0, clPlayer, 10, clFood, 20), stayClasses(clLand, 4)], 3 * numPlayers, 50 ); Engine.SetProgress(75); g_Map.log("Creating sheep"); group = new SimpleGroup( [new SimpleObject(oSecondaryHuntableAnimal, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 0, clPlayer, 10, clFood, 20), stayClasses(clLand, 4)], 3 * numPlayers, 50 ); g_Map.log("Creating fruits"); group = new SimpleGroup( [new SimpleObject(oFruitBush, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 0, clPlayer, 10, clFood, 20), stayClasses(clLand, 4)], 3 * numPlayers, 50 ); Engine.SetProgress(85); createStragglerTrees( [oTree1, oTree2, oTree4, oTree3], [avoidClasses(clForest, 1, clPlayer, 9, clMetal, 6, clRock, 6), stayClasses(clLand, 4)], clForest, stragglerTrees); var planetm = 1; if (currentBiome() == "generic/india") planetm = 8; g_Map.log("Creating small grass tufts"); group = new SimpleGroup( [new SimpleObject(aGrassShort, 1,2, 0,1, -Math.PI / 8, Math.PI / 8)] ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clPlayer, 2, clDirt, 0), stayClasses(clLand, 4)], planetm * scaleByMapSize(13, 200) ); Engine.SetProgress(90); g_Map.log("Creating large grass tufts"); group = new SimpleGroup( [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)] ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clPlayer, 2, clDirt, 1, clForest, 0), stayClasses(clLand, 4)], planetm * scaleByMapSize(13, 200) ); Engine.SetProgress(95); g_Map.log("Creating bushes"); group = new SimpleGroup( [new SimpleObject(aBushMedium, 1,2, 0,2), new SimpleObject(aBushSmall, 2,4, 0,2)] ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clPlayer, 1, clDirt, 1), stayClasses(clLand, 4)], planetm * scaleByMapSize(13, 200), 50 ); placePlayersNomad( clPlayer, [ stayClasses(clLand, 8), avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clFood, 2) ]); setSkySet(pickRandom(["cirrus", "cumulus", "sunny"])); setSunRotation(randomAngle()); setSunElevation(Math.PI * randFloat(1/5, 1/3)); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/wild_lake.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/wild_lake.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/wild_lake.js (revision 26381) @@ -1,580 +1,580 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); Engine.LoadLibrary("heightmap"); var g_Map = new RandomMap(0, "whiteness"); /** * getArray - To ensure a terrain texture is contained within an array */ function getArray(stringOrArrayOfStrings) { if (typeof stringOrArrayOfStrings == "string") return [stringOrArrayOfStrings]; return stringOrArrayOfStrings; } setSelectedBiome(); // Terrain, entities and actors let wildLakeBiome = [ // 0 Deep water { "texture": getArray(g_Terrains.water), "actor": [[g_Gaia.fish], 0.01], "textureHS": getArray(g_Terrains.water), "actorHS": [[g_Gaia.fish], 0.03] }, // 1 Shallow water { "texture": getArray(g_Terrains.water), "actor": [[g_Decoratives.lillies, g_Decoratives.reeds], 0.3], "textureHS": getArray(g_Terrains.water), "actorHS": [[g_Decoratives.lillies], 0.1] }, // 2 Shore { "texture": getArray(g_Terrains.shore), "actor": [ [ g_Gaia.tree1, g_Gaia.tree1, g_Gaia.tree2, g_Gaia.tree2, g_Gaia.mainHuntableAnimal, g_Decoratives.grass, g_Decoratives.grass, g_Decoratives.rockMedium, g_Decoratives.rockMedium, g_Decoratives.bushMedium, g_Decoratives.bushMedium ], 0.3 ], "textureHS": getArray(g_Terrains.cliff), "actorHS": [[g_Decoratives.grassShort, g_Decoratives.rockMedium, g_Decoratives.bushSmall], 0.1] }, // 3 Low ground { "texture": getArray(g_Terrains.tier1Terrain), "actor": [ [ g_Decoratives.grass, g_Decoratives.grassShort, g_Decoratives.rockLarge, g_Decoratives.rockMedium, g_Decoratives.bushMedium, g_Decoratives.bushSmall ], 0.2 ], "textureHS": getArray(g_Terrains.cliff), "actorHS": [[g_Decoratives.grassShort, g_Decoratives.rockMedium, g_Decoratives.bushSmall], 0.1] }, // 4 Mid ground. Player and path height { "texture": getArray(g_Terrains.mainTerrain), "actor": [ [ g_Decoratives.grass, g_Decoratives.grassShort, g_Decoratives.rockLarge, g_Decoratives.rockMedium, g_Decoratives.bushMedium, g_Decoratives.bushSmall ], 0.2 ], "textureHS": getArray(g_Terrains.cliff), "actorHS": [[g_Decoratives.grassShort, g_Decoratives.rockMedium, g_Decoratives.bushSmall], 0.1] }, // 5 High ground { "texture": getArray(g_Terrains.tier2Terrain), "actor": [ [ g_Decoratives.grass, g_Decoratives.grassShort, g_Decoratives.rockLarge, g_Decoratives.rockMedium, g_Decoratives.bushMedium, g_Decoratives.bushSmall ], 0.2 ], "textureHS": getArray(g_Terrains.cliff), "actorHS": [[g_Decoratives.grassShort, g_Decoratives.rockMedium, g_Decoratives.bushSmall], 0.1] }, // 6 Lower hilltop forest border { "texture": getArray(g_Terrains.dirt), "actor": [ [ g_Gaia.tree1, g_Gaia.tree3, g_Gaia.fruitBush, g_Gaia.secondaryHuntableAnimal, g_Decoratives.grass, g_Decoratives.rockMedium, g_Decoratives.bushMedium ], 0.3 ], "textureHS": getArray(g_Terrains.cliff), "actorHS": [[g_Decoratives.grassShort, g_Decoratives.rockMedium, g_Decoratives.bushSmall], 0.1] }, // 7 Hilltop forest { "texture": getArray(g_Terrains.forestFloor1), "actor": [ [ g_Gaia.tree1, g_Gaia.tree2, g_Gaia.tree3, g_Gaia.tree4, g_Gaia.tree5, g_Decoratives.tree, g_Decoratives.grass, g_Decoratives.rockMedium, g_Decoratives.bushMedium ], 0.5 ], "textureHS": getArray(g_Terrains.cliff), "actorHS": [[g_Decoratives.grassShort, g_Decoratives.rockMedium, g_Decoratives.bushSmall], 0.1] } ]; const wildLakeEntities = Engine.ReadJSONFile("maps/random/wild_lake_biomes.json"); const farmEntities = wildLakeEntities[currentBiome()].farmEntities; const mercenaryCampEntities = wildLakeEntities[currentBiome()].mercenaryCampEntities; const guards = mercenaryCampEntities .map(ent => ent.Template) .filter(ent => ent.indexOf("units/") != -1); const campEntities = wildLakeEntities.campEntities.concat(guards); /** * Resource spots and other points of interest */ function placeMine(position, centerEntity, decorativeActors = [ g_Decoratives.grass, g_Decoratives.grassShort, g_Decoratives.rockLarge, g_Decoratives.rockMedium, g_Decoratives.bushMedium, g_Decoratives.bushSmall ] ) { g_Map.placeEntityPassable(centerEntity, 0, position, randomAngle()); let quantity = randIntInclusive(11, 23); let dAngle = 2 * Math.PI / quantity; for (let i = 0; i < quantity; ++i) g_Map.placeEntityPassable( pickRandom(decorativeActors), 0, Vector2D.add(position, new Vector2D(randFloat(2, 5), 0).rotate(-dAngle * randFloat(i, i + 1))), randomAngle()); } // Groves, only wood let groveActors = [g_Decoratives.grass, g_Decoratives.rockMedium, g_Decoratives.bushMedium]; let clGrove = g_Map.createTileClass(); let clGaiaCamp = g_Map.createTileClass(); function placeGrove(point, groveEntities = [ g_Gaia.tree1, g_Gaia.tree1, g_Gaia.tree1, g_Gaia.tree1, g_Gaia.tree1, g_Gaia.tree2, g_Gaia.tree2, g_Gaia.tree2, g_Gaia.tree2, g_Gaia.tree3, g_Gaia.tree3, g_Gaia.tree3, g_Gaia.tree4, g_Gaia.tree4, g_Gaia.tree5 ], groveActors = [g_Decoratives.grass, g_Decoratives.rockMedium, g_Decoratives.bushMedium], groveTileClass = undefined, groveTerrainTexture = getArray(g_Terrains.forestFloor1) ) { let position = new Vector2D(point.x, point.y); g_Map.placeEntityPassable(pickRandom(["structures/gaul/outpost", g_Gaia.tree1]), 0, position, randomAngle()); let quantity = randIntInclusive(20, 30); let dAngle = 2 * Math.PI / quantity; for (let i = 0; i < quantity; ++i) { let angle = dAngle * randFloat(i, i + 1); let dist = randFloat(2, 5); let objectList = groveEntities; if (i % 3 == 0) objectList = groveActors; let pos = Vector2D.add(position, new Vector2D(dist, 0).rotate(-angle)); g_Map.placeEntityPassable(pickRandom(objectList), 0, pos, randomAngle()); let painters = [new TerrainPainter(groveTerrainTexture)]; if (groveTileClass) painters.push(new TileClassPainter(groveTileClass)); createArea( new ClumpPlacer(5, 1, 1, Infinity, pos), painters); } } g_WallStyles.other = { "overlap": 0, "fence": readyWallElement("structures/fence_long", "gaia"), "fence_short": readyWallElement("structures/fence_short", "gaia"), "bench": { "angle": Math.PI / 2, "length": 1.5, "indent": 0, "bend": 0, "templateName": "structures/bench" }, "foodBin": { "angle": Math.PI / 2, "length": 1.5, "indent": 0, "bend": 0, "templateName": "gaia/treasure/food_bin" }, "animal": { "angle": 0, "length": 0, "indent": 0.75, "bend": 0, "templateName": farmEntities.animal }, "farmstead": { "angle": Math.PI, "length": 0, "indent": -3, "bend": 0, "templateName": farmEntities.building } }; let fences = [ new Fortress("fence", [ "foodBin", "farmstead", "bench", "turn_0.25", "animal", "turn_0.25", "fence", "turn_0.25", "animal", "turn_0.25", "fence", "turn_0.25", "animal", "turn_0.25", "fence" ]), new Fortress("fence", [ "foodBin", "farmstead", "fence", "turn_0.25", "animal", "turn_0.25", "fence", "turn_0.25", "animal", "turn_0.25", "bench", "animal", "fence", "turn_0.25", "animal", "turn_0.25", "fence" ]), new Fortress("fence", [ "foodBin", "farmstead", "turn_0.5", "bench", "turn_-0.5", "fence_short", "turn_0.25", "animal", "turn_0.25", "fence", "turn_0.25", "animal", "turn_0.25", "fence", "turn_0.25", "animal", "turn_0.25", "fence_short", "animal", "fence" ]), new Fortress("fence", [ "foodBin", "farmstead", "turn_0.5", "fence_short", "turn_-0.5", "bench", "turn_0.25", "animal", "turn_0.25", "fence", "turn_0.25", "animal", "turn_0.25", "fence", "turn_0.25", "animal", "turn_0.25", "fence_short", "animal", "fence" ]), new Fortress("fence", [ "foodBin", "farmstead", "fence", "turn_0.25", "animal", "turn_0.25", "bench", "animal", "fence", "turn_0.25", "animal", "turn_0.25", "fence_short", "animal", "fence", "turn_0.25", "animal", "turn_0.25", "fence_short", "animal", "fence" ]) ]; let num = fences.length; for (let i = 0; i < num; ++i) fences.push(new Fortress("fence", clone(fences[i].wall).reverse())); // Camps with fire and gold treasure function placeCamp(position, centerEntity = "actor|props/special/eyecandy/campfire.xml" ) { g_Map.placeEntityPassable(centerEntity, 0, position, randomAngle()); let quantity = randIntInclusive(5, 11); let dAngle = 2 * Math.PI / quantity; for (let i = 0; i < quantity; ++i) { let angle = dAngle * randFloat(i, i + 1); let dist = randFloat(1, 3); g_Map.placeEntityPassable(pickRandom(campEntities), 0, Vector2D.add(position, new Vector2D(dist, 0).rotate(-angle)), randomAngle()); } addCivicCenterAreaToClass(position, clGaiaCamp); } function placeStartLocationResources( point, - foodEntities = [g_Gaia.fruitBush, g_Gaia.chicken], + foodEntities = [g_Gaia.fruitBush, g_Gaia.startingAnimal], groveEntities = [ g_Gaia.tree1, g_Gaia.tree1, g_Gaia.tree1, g_Gaia.tree1, g_Gaia.tree1, g_Gaia.tree2, g_Gaia.tree2, g_Gaia.tree2, g_Gaia.tree2, g_Gaia.tree3, g_Gaia.tree3, g_Gaia.tree3, g_Gaia.tree4, g_Gaia.tree4, g_Gaia.tree5 ], groveTerrainTexture = getArray(g_Terrains.forestFloor1), averageDistToCC = 10, dAverageDistToCC = 2 ) { function getRandDist() { return averageDistToCC + randFloat(-dAverageDistToCC, dAverageDistToCC); } let currentAngle = randomAngle(); // Stone let dAngle = 4/9 * Math.PI; let angle = currentAngle + randFloat(dAngle / 4, 3 * dAngle / 4); placeMine(Vector2D.add(point, new Vector2D(averageDistToCC, 0).rotate(-angle)), g_Gaia.stoneLarge); currentAngle += dAngle; // Wood let quantity = 80; dAngle = 2/3 * Math.PI / quantity; for (let i = 0; i < quantity; ++i) { angle = currentAngle + randFloat(0, dAngle); let dist = getRandDist(); let objectList = groveEntities; if (i % 2 == 0) objectList = groveActors; let position = Vector2D.add(point, new Vector2D(dist, 0).rotate(-angle)); g_Map.placeEntityPassable(pickRandom(objectList), 0, position, randomAngle()); createArea( new ClumpPlacer(5, 1, 1, Infinity, position), [ new TerrainPainter(groveTerrainTexture), new TileClassPainter(clGrove) ]); currentAngle += dAngle; } // Metal dAngle = 4/9 * Math.PI; angle = currentAngle + randFloat(dAngle / 4, 3 * dAngle / 4); placeMine(Vector2D.add(point, new Vector2D(averageDistToCC, 0).rotate(-angle)), g_Gaia.metalLarge); currentAngle += dAngle; // Berries and domestic animals quantity = 15; dAngle = 4/9 * Math.PI / quantity; for (let i = 0; i < quantity; ++i) { angle = currentAngle + randFloat(0, dAngle); let dist = getRandDist(); g_Map.placeEntityPassable(pickRandom(foodEntities), 0, Vector2D.add(point, new Vector2D(dist, 0).rotate(-angle)), randomAngle()); currentAngle += dAngle; } } /** * Base terrain shape generation and settings */ // Height range by map size let heightScale = (g_Map.size + 512) / 1024 / 5; let heightRange = { "min": MIN_HEIGHT * heightScale, "max": MAX_HEIGHT * heightScale }; // Water coverage let averageWaterCoverage = 1 / 5; // NOTE: Since terrain generation is quite unpredictable actual water coverage might vary much with the same value let heightSeaGround = -MIN_HEIGHT + heightRange.min + averageWaterCoverage * (heightRange.max - heightRange.min); // Water height in environment and the engine let heightSeaGroundAdjusted = heightSeaGround + MIN_HEIGHT; // Water height as terrain height setWaterHeight(heightSeaGround); // Generate base terrain shape let lowH = heightRange.min; let medH = (heightRange.min + heightRange.max) / 2; // Lake let initialHeightmap = [ [medH, medH, medH, medH, medH, medH], [medH, medH, medH, medH, medH, medH], [medH, medH, lowH, lowH, medH, medH], [medH, medH, lowH, lowH, medH, medH], [medH, medH, medH, medH, medH, medH], [medH, medH, medH, medH, medH, medH], ]; if (g_Map.size < 256) { initialHeightmap = [ [medH, medH, medH, medH, medH], [medH, medH, medH, medH, medH], [medH, medH, lowH, medH, medH], [medH, medH, medH, medH, medH], [medH, medH, medH, medH, medH] ]; } if (g_Map.size >= 384) { initialHeightmap = [ [medH, medH, medH, medH, medH, medH, medH, medH], [medH, medH, medH, medH, medH, medH, medH, medH], [medH, medH, medH, medH, medH, medH, medH, medH], [medH, medH, medH, lowH, lowH, medH, medH, medH], [medH, medH, medH, lowH, lowH, medH, medH, medH], [medH, medH, medH, medH, medH, medH, medH, medH], [medH, medH, medH, medH, medH, medH, medH, medH], [medH, medH, medH, medH, medH, medH, medH, medH], ]; } setBaseTerrainDiamondSquare(heightRange.min, heightRange.max, initialHeightmap, 0.8); g_Map.log("Eroding map"); for (let i = 0; i < 5; ++i) splashErodeMap(0.1); g_Map.log("Smoothing map"); createArea( new MapBoundsPlacer(), new SmoothingPainter(1, 0.5, Math.ceil(g_Map.size/128) + 1)); g_Map.log("Rescaling map"); rescaleHeightmap(heightRange.min, heightRange.max); Engine.SetProgress(25); /** * Prepare terrain texture placement */ let heighLimits = [ heightRange.min + 3/4 * (heightSeaGroundAdjusted - heightRange.min), // 0 Deep water heightSeaGroundAdjusted, // 1 Shallow water heightSeaGroundAdjusted + 2/8 * (heightRange.max - heightSeaGroundAdjusted), // 2 Shore heightSeaGroundAdjusted + 3/8 * (heightRange.max - heightSeaGroundAdjusted), // 3 Low ground heightSeaGroundAdjusted + 4/8 * (heightRange.max - heightSeaGroundAdjusted), // 4 Player and path height heightSeaGroundAdjusted + 6/8 * (heightRange.max - heightSeaGroundAdjusted), // 5 High ground heightSeaGroundAdjusted + 7/8 * (heightRange.max - heightSeaGroundAdjusted), // 6 Lower forest border heightRange.max // 7 Forest ]; let playerHeightRange = { "min": heighLimits[3], "max": heighLimits[4] }; let resourceSpotHeightRange = { "min": (heighLimits[2] + heighLimits[3]) / 2, "max": (heighLimits[4] + heighLimits[5]) / 2 }; let playerHeight = (playerHeightRange.min + playerHeightRange.max) / 2; // Average player height g_Map.log("Chosing starting locations"); let [playerIDs, playerPosition] = groupPlayersCycle(getStartLocationsByHeightmap(playerHeightRange, 1000, 30)); g_Map.log("Smoothing starting locations before height calculation"); for (let position of playerPosition) createArea( new ClumpPlacer(diskArea(20), 0.8, 0.8, Infinity, position), new SmoothElevationPainter(ELEVATION_SET, g_Map.getHeight(position), 20)); Engine.SetProgress(30); /** * Calculate tile centered height map after start position smoothing but before placing paths * This has nothing to to with TILE_CENTERED_HEIGHT_MAP which should be false! */ let tchm = getTileCenteredHeightmap(); g_Map.log("Get points per height"); let areas = heighLimits.map(heightLimit => []); for (let x = 0; x < tchm.length; ++x) for (let y = 0; y < tchm[0].length; ++y) { let minHeight = heightRange.min; for (let h = 0; h < heighLimits.length; ++h) { if (tchm[x][y] >= minHeight && tchm[x][y] <= heighLimits[h]) { areas[h].push(new Vector2D(x, y)); break; } minHeight = heighLimits[h]; } } g_Map.log("Get slope limits per heightrange"); let slopeMap = getSlopeMap(); let minSlope = []; let maxSlope = []; for (let h = 0; h < heighLimits.length; ++h) { minSlope[h] = Infinity; maxSlope[h] = 0; for (let point of areas[h]) { let slope = slopeMap[point.x][point.y]; if (slope > maxSlope[h]) maxSlope[h] = slope; if (slope < minSlope[h]) minSlope[h] = slope; } } g_Map.log("Paint areas by height and slope"); for (let h = 0; h < heighLimits.length; ++h) for (let point of areas[h]) { let actor; let texture = pickRandom(wildLakeBiome[h].texture); if (slopeMap[point.x][point.y] < (minSlope[h] + maxSlope[h]) / 2) { if (randBool(wildLakeBiome[h].actor[1])) actor = pickRandom(wildLakeBiome[h].actor[0]); } else { texture = pickRandom(wildLakeBiome[h].textureHS); if (randBool(wildLakeBiome[h].actorHS[1])) actor = pickRandom(wildLakeBiome[h].actorHS[0]); } g_Map.setTexture(point, texture); if (actor) g_Map.placeEntityAnywhere(actor, 0, randomPositionOnTile(point), randomAngle()); } Engine.SetProgress(40); g_Map.log("Placing resources"); let avoidPoints = playerPosition.map(pos => pos.clone()); for (let i = 0; i < avoidPoints.length; ++i) avoidPoints[i].dist = 30; let resourceSpots = getPointsByHeight(resourceSpotHeightRange, avoidPoints).map(point => new Vector2D(point.x, point.y)); Engine.SetProgress(55); g_Map.log("Placing players"); if (isNomad()) placePlayersNomad( g_Map.createTileClass(), [ new HeightConstraint(playerHeightRange.min, playerHeightRange.max), avoidClasses(clGaiaCamp, 8) ]); else for (let p = 0; p < playerIDs.length; ++p) { placeCivDefaultStartingEntities(playerPosition[p], playerIDs[p], g_Map.size > 192); placeStartLocationResources(playerPosition[p]); } let mercenaryCamps = isNomad() ? 0 : Math.ceil(g_Map.size / 256); g_Map.log("Placing at most " + mercenaryCamps + " mercenary camps"); for (let i = 0; i < resourceSpots.length; ++i) { let radius; let choice = i % (isNomad() ? 4 : 5); if (choice == 0) placeMine(resourceSpots[i], g_Gaia.stoneLarge); if (choice == 1) placeMine(resourceSpots[i], g_Gaia.metalLarge); if (choice == 2) placeGrove(resourceSpots[i]); if (choice == 3) { placeCamp(resourceSpots[i]); radius = 5; } if (choice == 4) { if (mercenaryCamps) { placeStartingEntities(resourceSpots[i], 0, mercenaryCampEntities); radius = 15; --mercenaryCamps; } else { placeCustomFortress(resourceSpots[i], pickRandom(fences), "other", 0, randomAngle()); radius = 10; } } if (radius) createArea( new DiskPlacer(radius, resourceSpots[i]), new SmoothElevationPainter(ELEVATION_SET, g_Map.getHeight(resourceSpots[i]), radius / 3)); } g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/arctic.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/arctic.json (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/arctic.json (revision 26381) @@ -1,102 +1,102 @@ { "Description": { "Title": "Arctic", "Description": "A region in the high snowy mountains. Biting winds sweep through the abundant conifer forests, making even the more resilient deer and mountain goats shiver." }, "Environment": { "SkySet": "stormy", "SunColor": { "r": 0.98, "g": 1.01, "b": 1.045 }, "SunElevation": 0.502494, "SunRotation": -0.626047, "AmbientColor": { "r": 0.294118, "g": 0.392157, "b": 0.494118 }, "Water": { "WaterBody": { "Color": { "r": 0.0784314, "g": 0.247059, "b": 0.419608 }, "Tint": { "r": 0.471, "g": 1, "b": 0.501961 }, "Murkiness": 0.88, "Waviness": 2 } }, "Fog": { "FogThickness": 0.0, "FogFactor": 0.005, "FogColor": { "r": 0.784314, "g": 0.886275, "b": 0.976471 } }, "Postproc": { "PostprocEffect": "hdr", "Brightness": 0, "Saturation": 1, "Contrast": 1, "Bloom": 0.16 } }, "Terrains": { "mainTerrain": [ "alpine_snow_01", "alpine_snow_02" ], "forestFloor1": "alpine_forestfloor_02", "forestFloor2": "alpine_forestfloor_02", "cliff": [ "alpine_rock_01", "alpine_rock_02" ], "tier1Terrain": [ "alpine_snow_01" ], "tier2Terrain": [ "alpine_snow_02" ], "tier3Terrain": [ "polar_snow_b" ], "tier4Terrain": "alpine_snow_02", "hill": [ "alpine_rock_01_snow", "alpine_rock_02_snow" ], "dirt": [ "alpine_snow_01", "alpine_snow_02" ], "road": "alpine_paving_stones_01", "roadWild": "alpine_paving_stones_01", "shoreBlend": "alpine_rock_01_snow", "shore": "alpine_rocks_dirt_01", "water": "alpine_rocks_dirt_01" }, "Gaia": { "tree1": "gaia/tree/fir_winter", "tree2": "gaia/tree/pine_w", "tree3": "gaia/tree/pine_w", "tree4": "gaia/tree/fir_winter", "tree5": "gaia/tree/fir_winter", "fruitBush": "gaia/fruit/berry_02", - "chicken": "gaia/fauna_chicken", + "startingAnimal": "gaia/fauna_chicken", "mainHuntableAnimal": "gaia/fauna_muskox", "fish": "gaia/fish/tuna", "secondaryHuntableAnimal": "gaia/fauna_walrus", "stoneLarge": "gaia/rock/temperate_large_03", "stoneSmall": "gaia/rock/temperate_small", "metalLarge": "gaia/ore/temperate_02", "metalSmall": "gaia/ore/temperate_small" }, "Decoratives": { "grass": "gaia/tree/bush_temperate_winter", "grassShort": "gaia/tree/bush_temperate_winter", "reeds": "actor|props/flora/reeds_pond_dry.xml", "lillies": "actor|geology/stone_granite_small.xml", "rockLarge": "actor|geology/stone_granite_large.xml", "rockMedium": "actor|geology/stone_granite_med.xml", "bushMedium": "gaia/tree/bush_temperate_winter", "bushSmall": "actor|props/flora/bush_desert_dry_a.xml", "tree": "actor|flora/trees/fir_tree_winter.xml" }, "ResourceCounts": { "trees": { "min": 500, "max": 2000, "forestProbability": 0.6 } } } Index: ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/sahara.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/sahara.json (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/sahara.json (revision 26381) @@ -1,89 +1,89 @@ { "Description": { "Title": "Sahara", "Description": "A semi-desert area that boasts numerous clumps of date palms and acacia trees. Herds of camels roam the wild and the occasional gazelle jumps up in fright at being disturbed." }, "Environment": { "SunColor": { "r": 0.976471, "g": 0.858824, "b": 0.74902 }, "SunElevation": 0.7, "SunRotation": -0.3, "AmbientColor": { "r": 0.231373, "g": 0.282353, "b": 0.356863 }, "Water": { "WaterBody": { "Color": { "r": 0.376, "g": 0.267, "b": 0.122 }, "Tint": { "r": 0.502, "g": 0.502, "b": 0 }, "Murkiness": 0.9, "Waviness": 3 } }, "Fog": { "FogThickness": 0.05, "FogFactor": 0.003, "FogColor": { "r": 0.992, "g": 0.949, "b": 0.839 } }, "Postproc": { "PostprocEffect": "hdr", "Saturation": 0.95, "Contrast": 1.02, "Bloom": 0.120 } }, "Terrains": { "mainTerrain": [ "sahara_sand_01", "sahara_sand_02", "sahara_sand_05" ], "forestFloor1": "sahara_forestfloor_01", "forestFloor2": "sahara_forestfloor_02", "cliff": [ "sahara_rock_01" ], "tier1Terrain": "sahara_rocks_dirt_01", "tier2Terrain": "sahara_rocks_dirt_02", "tier3Terrain": "sahara_sand_03", "tier4Terrain": "sahara_sand_04", "hill": [ "sahara_dirt_02" ], "dirt": [ "sahara_dirt_01", "sahara_dirt_02" ], "road": "sahara_paving_stones_01", "roadWild": "sahara_paving_stones_01_sand_01", "shoreBlend": "sahara_sand_01_dunes", "shore": "sahara_sand_02", "water": "sahara_sand_04_wet" }, "Gaia": { "fruitBush": "gaia/fruit/date", - "chicken": "gaia/fauna_goat", + "startingAnimal": "gaia/fauna_goat", "mainHuntableAnimal": "gaia/fauna_camel", "fish": "gaia/fish/generic", "secondaryHuntableAnimal": "gaia/fauna_gazelle", "stoneLarge": "gaia/rock/desert_large", "stoneSmall": "gaia/rock/desert_small", "metalLarge": "gaia/ore/sahara_01", "metalSmall": "gaia/ore/desert_small", "tree3": "gaia/tree/juniper_prickly" }, "Decoratives": { "grass": "actor|props/flora/bush_desert_dry_a.xml", "grassShort": "actor|props/flora/plant_desert_a.xml", "reeds": "actor|props/flora/papyrus.xml", "lillies": "actor|props/flora/water_lillies.xml", "rockLarge": "actor|geology/stone_desert_med.xml", "rockMedium": "actor|geology/stone_desert_med.xml", "bushMedium": "gaia/tree/bush_tropic", "bushSmall": "actor|props/flora/bush_dry_a.xml", "tree": "gaia/tree/date_palm_dead" }, "ResourceCounts": { "trees": { "min": 500, "max": 1000, "forestProbability": 0.4 } } } Index: ps/trunk/binaries/data/mods/public/maps/random/rmbiome/gulf_of_bothnia/frozen_lake.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rmbiome/gulf_of_bothnia/frozen_lake.json (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/rmbiome/gulf_of_bothnia/frozen_lake.json (revision 26381) @@ -1,72 +1,72 @@ { "Description": { "Title": "Frozen Lake", "Description": "Solidifying its grip, the harsh cold has succeeded in freezing up the gulf. The thick ice formed is capable of withstanding any weight." }, "Environment": { "SkySet": "stormy", "SunColor": { "r": 0.85, "g": 0.87, "b": 0.90 }, "SunElevation": 0.502494, "SunRotation": -0.626047, "AmbientColor": { "r": 0.194118, "g": 0.292157, "b": 0.394118 }, "Water": { "WaterBody": { "Type": "lake", "Color": { "r": 0.035, "g": 0.098, "b": 0.314 }, "Tint": { "r": 0.28, "g": 0.3, "b": 0.59 }, "Murkiness": 0.88, "Waviness": 5 } }, "Fog": { "FogThickness": 0.23, "FogFactor": 0.0041 }, "Postproc": { "PostprocEffect": "hdr", "Saturation": 0.68, "Contrast": 1.03, "Bloom": 0.176 } }, "Terrains": { "mainTerrain": ["alpine_snow_a", "alpine_snow_b"], "forestFloor1": "alpine_snow_a", "cliff": "alpine_cliff_snow", "tier1Terrain": "polar_ice_snow", "tier2Terrain": "polar_ice_cracked", "tier3Terrain": ["alpine_snow_a", "alpine_snow_b"], "road": "new_alpine_citytile", "roadWild": "new_alpine_citytile", "shore": "polar_ice_snow", "water": ["polar_ice_snow", "polar_ice"] }, "Gaia": { "tree1": "gaia/tree/pine_w", "fruitBush": "gaia/fruit/berry_01", - "chicken": "gaia/fauna_chicken", + "startingAnimal": "gaia/fauna_chicken", "mainHuntableAnimal": "gaia/fauna_deer", "secondaryHuntableAnimal": "gaia/fauna_rabbit", "fish": "gaia/fish/generic", "stoneLarge": "gaia/rock/alpine_large", "stoneSmall": "gaia/rock/alpine_small", "metalLarge": "gaia/ore/alpine_large" }, "Decoratives": { "grass": "actor|props/flora/grass_soft_dry_small_tall.xml", "grassShort": "actor|props/flora/grass_soft_dry_large.xml", "rockLarge": "actor|geology/stone_granite_med.xml", "rockMedium": "actor|geology/stone_granite_med.xml", "bushMedium": "actor|props/flora/bush_medit_me_dry.xml", "bushSmall": "actor|props/flora/bush_medit_sm_dry.xml" }, "ResourceCounts": { "fish": { "min": 0, "max": 0 }, "bush": { "min": 0, "max": 0 } }, "Heights": { "seaGround": 1, "shore": 4, "land": 7 } } Index: ps/trunk/binaries/data/mods/public/maps/random/rmgen2/setup.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rmgen2/setup.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/rmgen2/setup.js (revision 26381) @@ -1,334 +1,334 @@ var g_Amounts = { "scarce": 0.2, "few": 0.5, "normal": 1, "many": 1.75, "tons": 3 }; var g_Mixes = { "same": 0, "similar": 0.1, "normal": 0.25, "varied": 0.5, "unique": 0.75 }; var g_Sizes = { "tiny": 0.5, "small": 0.75, "normal": 1, "big": 1.25, "huge": 1.5, }; var g_AllAmounts = Object.keys(g_Amounts); var g_AllMixes = Object.keys(g_Mixes); var g_AllSizes = Object.keys(g_Sizes); var g_DefaultTileClasses = [ "animals", "baseResource", "berries", "bluff", "bluffIgnore", // performance improvement "dirt", "fish", "food", "forest", "hill", "land", "map", "metal", "mountain", "plateau", "player", "prop", "ramp", "rock", "settlement", "spine", "valley", "water" ]; var g_TileClasses; var g_PlayerbaseTypes = { "line": { "getPosition": (distance, groupedDistance, startAngle) => placeLine(getTeamsArray(), distance, groupedDistance, startAngle), "distance": fractionToTiles(randFloat(0.2, 0.35)), "groupedDistance": fractionToTiles(randFloat(0.08, 0.1)), "walls": false }, "radial": { "getPosition": (distance, groupedDistance, startAngle) => playerPlacementCircle(distance, startAngle), "distance": fractionToTiles(randFloat(0.25, 0.35)), "groupedDistance": fractionToTiles(randFloat(0.08, 0.1)), "walls": true }, "randomGroup": { "getPosition": (distance, groupedDistance, startAngle) => playerPlacementRandom(sortAllPlayers()) || playerPlacementCircle(distance, startAngle), "distance": fractionToTiles(randFloat(0.25, 0.35)), "groupedDistance": fractionToTiles(randFloat(0.08, 0.1)), "walls": true }, "stronghold": { "getPosition": (distance, groupedDistance, startAngle) => placeStronghold(getTeamsArray(), distance, groupedDistance, startAngle), "distance": fractionToTiles(randFloat(0.2, 0.35)), "groupedDistance": fractionToTiles(randFloat(0.08, 0.1)), "walls": false } }; /** * Adds an array of elements to the map. */ function addElements(elements) { for (let element of elements) element.func( [ avoidClasses.apply(null, element.avoid), stayClasses.apply(null, element.stay || null) ], pickSize(element.sizes), pickMix(element.mixes), pickAmount(element.amounts), element.baseHeight || 0); } /** * Converts "amount" terms to numbers. */ function pickAmount(amounts) { let amount = pickRandom(amounts); if (amount in g_Amounts) return g_Amounts[amount]; return g_Amounts.normal; } /** * Converts "mix" terms to numbers. */ function pickMix(mixes) { let mix = pickRandom(mixes); if (mix in g_Mixes) return g_Mixes[mix]; return g_Mixes.normal; } /** * Converts "size" terms to numbers. */ function pickSize(sizes) { let size = pickRandom(sizes); if (size in g_Sizes) return g_Sizes[size]; return g_Sizes.normal; } /** * Choose starting locations for all players. * * @param {string} type - "radial", "line", "stronghold", "randomGroup" * @param {number} distance - radial distance from the center of the map * @param {number} groupedDistance - space between players within a team * @param {number} startAngle - determined by the map that might want to place something between players * @returns {Array|undefined} - If successful, each element is an object that contains id, angle, x, z for each player */ function createBasesByPattern(type, distance, groupedDistance, startAngle) { return createBases(...g_PlayerbaseTypes[type].getPosition(distance, groupedDistance, startAngle), g_PlayerbaseTypes[type].walls); } function createBases(playerIDs, playerPosition, walls) { g_Map.log("Creating bases"); for (let i = 0; i < getNumPlayers(); ++i) createBase(playerIDs[i], playerPosition[i], walls); return [playerIDs, playerPosition]; } /** * Create the base for a single player. * * @param {Object} player - contains id, angle, x, z * @param {boolean} walls - Whether or not iberian gets starting walls */ function createBase(playerID, playerPosition, walls) { placePlayerBase({ "playerID": playerID, "playerPosition": playerPosition, "PlayerTileClass": g_TileClasses.player, "BaseResourceClass": g_TileClasses.baseResource, "baseResourceConstraint": avoidClasses(g_TileClasses.water, 0, g_TileClasses.mountain, 0), "Walls": g_Map.getSize() > 192 && walls, "CityPatch": { "outerTerrain": g_Terrains.roadWild, "innerTerrain": g_Terrains.road, "painters": [ new TileClassPainter(g_TileClasses.player) ] }, - "Chicken": { - "template": g_Gaia.chicken + "StartingAnimal": { + "template": g_Gaia.startingAnimal }, "Berries": { "template": g_Gaia.fruitBush }, "Mines": { "types": [ { "template": g_Gaia.metalLarge }, { "template": g_Gaia.stoneLarge } ] }, "Trees": { "template": g_Gaia.tree1, "count": currentBiome() == "generic/savanna" ? 5 : 15 }, "Decoratives": { "template": g_Decoratives.grassShort } }); } /** * Return an array where each element is an array of playerIndices of a team. */ function getTeamsArray() { var playerIDs = sortAllPlayers(); var numPlayers = getNumPlayers(); // Group players by team var teams = []; for (let i = 0; i < numPlayers; ++i) { let team = getPlayerTeam(playerIDs[i]); if (team == -1) continue; if (!teams[team]) teams[team] = []; teams[team].push(playerIDs[i]); } // Players without a team get a custom index for (let i = 0; i < numPlayers; ++i) if (getPlayerTeam(playerIDs[i]) == -1) teams.push([playerIDs[i]]); // Remove unused indices return teams.filter(team => true); } /** * Place teams in a line-pattern. * * @param {Array} playerIDs - typically randomized indices of players of a single team * @param {number} distance - radial distance from the center of the map * @param {number} groupedDistance - distance between players * @param {number} startAngle - determined by the map that might want to place something between players. * * @returns {Array} - contains id, angle, x, z for every player */ function placeLine(teamsArray, distance, groupedDistance, startAngle) { let playerIDs = []; let playerPosition = []; let mapCenter = g_Map.getCenter(); let dist = fractionToTiles(0.45); for (let i = 0; i < teamsArray.length; ++i) { var safeDist = distance; if (distance + teamsArray[i].length * groupedDistance > dist) safeDist = dist - teamsArray[i].length * groupedDistance; var teamAngle = startAngle + (i + 1) * 2 * Math.PI / teamsArray.length; for (let p = 0; p < teamsArray[i].length; ++p) { playerIDs.push(teamsArray[i][p]); playerPosition.push(Vector2D.add(mapCenter, new Vector2D(safeDist + p * groupedDistance, 0).rotate(-teamAngle)).round()); } } return [playerIDs, playerPosition]; } /** * Place given players in a stronghold-pattern. * * @param teamsArray - each item is an array of playerIDs placed per stronghold * @param distance - radial distance from the center of the map * @param groupedDistance - distance between neighboring players * @param {number} startAngle - determined by the map that might want to place something between players */ function placeStronghold(teamsArray, distance, groupedDistance, startAngle) { var mapCenter = g_Map.getCenter(); let playerIDs = []; let playerPosition = []; for (let i = 0; i < teamsArray.length; ++i) { var teamAngle = startAngle + (i + 1) * 2 * Math.PI / teamsArray.length; var teamPosition = Vector2D.add(mapCenter, new Vector2D(distance, 0).rotate(-teamAngle)); var teamGroupDistance = groupedDistance; // If we have a team of above average size, make sure they're spread out if (teamsArray[i].length > 4) teamGroupDistance = Math.max(fractionToTiles(0.08), groupedDistance); // If we have a solo player, place them on the center of the team's location if (teamsArray[i].length == 1) teamGroupDistance = fractionToTiles(0); // TODO: Ensure players are not placed outside of the map area, similar to placeLine // Create player base for (var p = 0; p < teamsArray[i].length; ++p) { var angle = startAngle + (p + 1) * 2 * Math.PI / teamsArray[i].length; playerIDs.push(teamsArray[i][p]); playerPosition.push(Vector2D.add(teamPosition, new Vector2D(teamGroupDistance, 0).rotate(-angle)).round()); } } return [playerIDs, playerPosition]; } /** * Creates tileClass for the default classes and every class given. * * @param {Array} newClasses * @returns {Object} - maps from classname to ID */ function initTileClasses(newClasses) { var classNames = g_DefaultTileClasses; if (newClasses) classNames = classNames.concat(newClasses); g_TileClasses = {}; for (var className of classNames) g_TileClasses[className] = g_Map.createTileClass(); } Index: ps/trunk/binaries/data/mods/public/maps/random/scythian_rivulet.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/scythian_rivulet.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/scythian_rivulet.js (revision 26381) @@ -1,318 +1,318 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); const tMainTerrain = "alpine_snow_a"; const tTier1Terrain = "snow rough"; const tTier2Terrain = "snow_01"; const tTier3Terrain = "snow rocks"; const tForestFloor1 = "alpine_forrestfloor_snow"; const tForestFloor2 = "polar_snow_rocks"; const tCliff = ["alpine_cliff_a", "alpine_cliff_b"]; const tHill = "alpine_snow_glacial"; const tRoad = "new_alpine_citytile"; const tRoadWild = "alpine_snow_rocky"; const tShore = "alpine_shore_rocks_icy"; const tWater = "polar_ice_b"; const oTreeDead = "gaia/tree/dead"; const oOak = "gaia/tree/oak_dead"; const oPine = "gaia/tree/pine"; const oGrapes = "gaia/fruit/grapes"; const oBush = "gaia/tree/bush_badlands"; const oDeer = "gaia/fauna_deer"; const oRabbit = "gaia/fauna_rabbit"; const oWolf1 = "gaia/fauna_wolf"; const oWolf2 = "gaia/fauna_wolf_arctic"; const oHawk = "birds/buzzard"; const oFish = "gaia/fish/generic"; const oStoneLarge = "gaia/rock/alpine_large"; const oStoneSmall = "gaia/rock/alpine_small"; const oMetalLarge = "gaia/ore/alpine_large"; const aRockLarge = "actor|geology/stone_granite_large.xml"; const aRockMedium = "actor|geology/stone_granite_med.xml"; const aBushMedium = "actor|props/flora/plant_desert_a.xml"; const aBushSmall = "actor|props/flora/bush_desert_a.xml"; const aReeds = "actor|props/flora/reeds_pond_lush_a.xml"; const aOutpostPalisade = "actor|props/structures/britons/outpost_palisade.xml"; const aWorkshopChariot= "actor|props/structures/britons/workshop_chariot_01.xml"; const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTreeDead, tForestFloor2 + TERRAIN_SEPARATOR + oOak, tForestFloor2]; const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTreeDead, tForestFloor1]; var heightSeaGround = -2; var heightShoreLower = 0.7; var heightShoreUpper = 1; var heightLand = 2; var heightSnowline = 12; var heightOffsetLargeBumps = 4; var g_Map = new RandomMap(heightShoreUpper, tMainTerrain); const numPlayers = getNumPlayers(); const mapCenter = g_Map.getCenter(); const mapBounds = g_Map.getBounds(); var clPlayer = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRiver = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clShallowsFlora = g_Map.createTileClass(); var riverWidth = fractionToTiles(0.1); var startAngle = randomAngle(); var [playerIDs, playerPosition] = playerPlacementRiver(startAngle, fractionToTiles(0.6)); if (!isNomad()) for (let position of playerPosition) addCivicCenterAreaToClass(position, clPlayer); paintRiver({ "parallel": false, "start": new Vector2D(mapCenter.x, mapBounds.top).rotateAround(startAngle, mapCenter), "end": new Vector2D(mapCenter.x, mapBounds.bottom).rotateAround(startAngle, mapCenter), "width": riverWidth, "fadeDist": scaleByMapSize(3, 14), "deviation": 6, "heightRiverbed": heightSeaGround, "heightLand": heightLand, "meanderShort": 40, "meanderLong": 20 }); Engine.SetProgress(10); paintTileClassBasedOnHeight(-Infinity, heightShoreUpper, Elevation_ExcludeMin_ExcludeMax, clRiver); Engine.SetProgress(15); createTributaryRivers( startAngle + Math.PI / 2, 4, 10, heightSeaGround, [-Infinity, heightSeaGround], Math.PI / 5, clWater, undefined, avoidClasses(clPlayer, 4)); Engine.SetProgress(25); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "baseResourceConstraint": avoidClasses(clWater, 4), "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { "template": oDeer, "distance": 18, "minGroupDistance": 2, "maxGroupDistance": 4, "minGroupCount": 2, "maxGroupCount": 3 }, "Berries": { "template": oGrapes, "minCount": 3, "maxCount": 3 }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oTreeDead, "count": 10 }, "Decoratives": { "template": aBushSmall, "minDist": 10, "maxDist": 12 } }); Engine.SetProgress(30); g_Map.log("Creating pools"); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(2, 5)), Math.floor(scaleByMapSize(15, 60)), 0.8), new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 3), avoidClasses(clPlayer, 20), scaleByMapSize(6, 20)); Engine.SetProgress(40); createBumps(avoidClasses(clPlayer, 2)); if (randBool()) createHills([tCliff, tCliff, tHill], avoidClasses(clPlayer, 20, clWater, 1, clHill, 15, clRiver, 10), clHill, scaleByMapSize(3, 15)); else createMountains(tCliff, avoidClasses(clPlayer, 20, clWater, 1, clHill, 15, clRiver, 10), clHill, scaleByMapSize(3, 15)); g_Map.log("Creating large bumps"); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, Infinity), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetLargeBumps, 3), avoidClasses(clPlayer, 2), scaleByMapSize(100, 800)); createBumps(avoidClasses(clPlayer, 20)); paintTileClassBasedOnHeight(-Infinity, heightShoreUpper, Elevation_ExcludeMin_ExcludeMax, clWater); paintTerrainBasedOnHeight(-Infinity, heightShoreUpper, Elevation_ExcludeMin_ExcludeMax, tWater); paintTerrainBasedOnHeight(heightShoreUpper, heightShoreLower, Elevation_ExcludeMin_ExcludeMax, tShore); paintTerrainBasedOnHeight(heightSnowline, Infinity, Elevation_ExcludeMin_ExcludeMax, tMainTerrain); Engine.SetProgress(50); g_Map.log("Creating dirt patches"); createLayeredPatches( [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)], [[tMainTerrain, tTier1Terrain], [tTier1Terrain, tTier2Terrain], [tTier2Terrain, tTier3Terrain]], [1, 1], avoidClasses(clHill, 2, clDirt, 5, clPlayer, 12, clWater, 5, clForest, 4), scaleByMapSize(25, 55), clDirt); var [forestTrees, stragglerTrees] = getTreeCounts(200, 1200, 0.7); createForests( [tForestFloor1, tForestFloor2, tForestFloor1, pForest1, pForest2], avoidClasses(clPlayer, 20, clWater, 2, clHill, 2, clForest, 12), clForest, forestTrees); createStragglerTrees( [oTreeDead, oOak, oPine, oBush], avoidClasses(clPlayer, 17, clWater, 2, clHill, 2, clForest, 1, clRiver, 4), clForest, stragglerTrees); Engine.SetProgress(55); g_Map.log("Creating stone mines"); // Allow mines on the bumps at the river createMines( [ [new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], [new SimpleObject(oStoneSmall, 2, 5, 1, 3)] ], avoidClasses(clForest, 4, clWater, 1, clPlayer, 20, clRock, 15, clHill, 1), clRock); g_Map.log("Creating metal mines"); createMines( [ [new SimpleObject(oMetalLarge, 1, 1, 0, 4)] ], avoidClasses(clForest, 4, clWater, 1, clPlayer, 20, clMetal, 15, clRock, 5, clHill, 1), clMetal); Engine.SetProgress(65); createDecoration( [ [ new SimpleObject(aRockMedium, 1, 3, 0, 1) ], [ new SimpleObject(aBushSmall, 1, 2, 0, 1), new SimpleObject(aBushMedium, 1, 3, 0, 2), new SimpleObject(aRockLarge, 1, 2, 0, 1) ] ], [ scaleByMapAreaAbsolute(16), scaleByMapSize(40, 360) ], avoidClasses(clWater, 2, clForest, 0, clPlayer, 20, clHill, 1)); Engine.SetProgress(70); createFood( [ [new SimpleObject(oHawk, 1, 1, 0, 3)], [new SimpleObject(oWolf1, 4, 6, 0, 4)], [new SimpleObject(oWolf2, 4, 8, 0, 4)], [new SimpleObject(oDeer, 4, 6, 0, 2)], [new SimpleObject(oRabbit, 1, 3, 4, 6)] ], [ scaleByMapSize(3, 10), scaleByMapSize(3, 10), scaleByMapSize(3, 10), scaleByMapSize(5, 20), scaleByMapSize(5, 20) ], avoidClasses(clWater, 3, clPlayer, 20, clHill, 1, clFood, 10)); Engine.SetProgress(75); createFood( [ [new SimpleObject(oFish, 1, 2, 0, 2)] ], [ 3 * numPlayers ], [avoidClasses(clPlayer, 8, clForest, 1, clHill, 4), stayClasses (clWater, 6)], clFood); g_Map.log("Creating shallow flora"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(aReeds, 6, 14, 1, 5)], false, clShallowsFlora), 0, [ new HeightConstraint(-1, 0), avoidClasses(clShallowsFlora, 25), ], 20 * scaleByMapSize(13, 200), 80); g_Map.log("Creating gallic decoratives"); createDecoration( [ [new SimpleObject(aOutpostPalisade, 1, 1, 0, 1)], [new SimpleObject(aWorkshopChariot, 1, 1, 0, 1)], ], [ scaleByMapSize(2, 7), scaleByMapSize(2, 7) ], avoidClasses(clForest, 1, clPlayer, 20, clBaseResource, 5, clHill, 4, clFood, 4, clWater, 5, clRock, 9, clMetal, 9)); placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 10, clWater, 5)); setSkySet(pickRandom(["fog", "stormy", "sunset"])); setSunElevation(0.27); setSunRotation(randomAngle()); setSunColor(0.746, 0.718, 0.539); setWaterColor(0.292, 0.347, 0.691); setWaterTint(0.550, 0.543, 0.437); setWaterMurkiness(0.83); setWaterType("clap"); setWindAngle(startAngle); setFogColor(0.8, 0.76, 0.61); setFogThickness(2); setFogFactor(1.2); setPPEffect("hdr"); setPPContrast(0.65); setPPSaturation(0.42); setPPBloom(0.6); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/unknown.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/unknown.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/unknown.js (revision 26381) @@ -1,1077 +1,1077 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); Engine.LoadLibrary("rmbiome"); TILE_CENTERED_HEIGHT_MAP = true; setSelectedBiome(); const tMainTerrain = g_Terrains.mainTerrain; const tForestFloor1 = g_Terrains.forestFloor1; const tForestFloor2 = g_Terrains.forestFloor2; const tCliff = g_Terrains.cliff; const tTier1Terrain = g_Terrains.tier1Terrain; const tTier2Terrain = g_Terrains.tier2Terrain; const tTier3Terrain = g_Terrains.tier3Terrain; const tHill = g_Terrains.hill; const tRoad = g_Terrains.road; const tRoadWild = g_Terrains.roadWild; const tTier4Terrain = g_Terrains.tier4Terrain; const tShore = g_Terrains.shore; const tWater = g_Terrains.water; const oTree1 = g_Gaia.tree1; const oTree2 = g_Gaia.tree2; const oTree4 = g_Gaia.tree4; const oTree5 = g_Gaia.tree5; const oFruitBush = g_Gaia.fruitBush; const oMainHuntableAnimal = g_Gaia.mainHuntableAnimal; const oSecondaryHuntableAnimal = g_Gaia.secondaryHuntableAnimal; const oFish = g_Gaia.fish; const oStoneLarge = g_Gaia.stoneLarge; const oStoneSmall = g_Gaia.stoneSmall; const oMetalLarge = g_Gaia.metalLarge; const oWoodTreasure = "gaia/treasure/wood"; const aGrass = g_Decoratives.grass; const aGrassShort = g_Decoratives.grassShort; const aReeds = g_Decoratives.reeds; const aLillies = g_Decoratives.lillies; const aRockLarge = g_Decoratives.rockLarge; const aRockMedium = g_Decoratives.rockMedium; const aBushMedium = g_Decoratives.bushMedium; const aBushSmall = g_Decoratives.bushSmall; const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2]; const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1]; const heightSeaGround = -5; const heightLand = 3; const heightCliff = 3.12; const heightHill = 18; const heightOffsetBump = 2; var g_Map = new RandomMap(heightSeaGround, tWater); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); const mapBounds = g_Map.getBounds(); var clPlayer = g_Map.createTileClass(); var clPlayerTerritory = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clPeninsulaSteam = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clLand = g_Map.createTileClass(); var clShallow = g_Map.createTileClass(); var landElevationPainter = new SmoothElevationPainter(ELEVATION_SET, heightLand, 4); var unknownMapFunctions = { "land": [ "Continent", "Isthmus", "CentralRiverLand", "EdgeSeas", "Gulf", "Lakes", "Passes", "Lowlands", "Mainland" ], "naval": [ "CentralSea", "CentralRiverNaval", "Archipelago", "RiversAndLake" ] }; /** * The player IDs and locations shall only be determined by the landscape functions if it's not a nomad game, * because nomad maps randomize the locations after the terrain generation. * The locations should only determined by the landscape functions to avoid placing bodies of water and resources into civic centers and the starting resources. */ var playerIDs = sortAllPlayers(); var playerPosition = []; var g_StartingTreasures = false; var g_StartingWalls = true; function createUnknownMap() { const landscape = g_MapSettings.Landscape || pickRandom([...unknownMapFunctions.land, ...unknownMapFunctions.naval]); global["unknown" + landscape](); paintUnknownMapBasedOnHeight(); createUnknownPlayerBases(); createUnknownObjects(); placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2, clWater, 10)); } /** * Chain of islands or many disconnected islands. */ function unknownArchipelago() { g_StartingWalls = "towers"; g_StartingTreasures = true; let [pIDs, islandPosition] = playerPlacementCircle(fractionToTiles(0.35)); if (!isNomad()) { [playerIDs, playerPosition] = [pIDs, islandPosition]; markPlayerArea("large"); } g_Map.log("Creating islands"); let islandSize = diskArea(scaleByMapSize(17, 29)); for (let i = 0; i < numPlayers; ++i) createArea( new ClumpPlacer(islandSize, 0.8, 0.1, Infinity, islandPosition[i]), landElevationPainter); let type = isNomad() ? randIntInclusive(1, 2) : randIntInclusive(1, 3); if (type == 1) { g_Map.log("Creating archipelago"); createAreas( new ClumpPlacer(islandSize * randFloat(0.8, 1.2), 0.8, 0.1, Infinity), [ landElevationPainter, new TileClassPainter(clLand) ], null, scaleByMapSize(2, 5) * randIntInclusive(8, 14)); g_Map.log("Creating shore jaggedness with small puddles"); createAreas( new ClumpPlacer(scaleByMapSize(15, 80), 0.2, 0.1, Infinity), [ new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), new TileClassPainter(clLand) ], borderClasses(clLand, 6, 3), scaleByMapSize(12, 130) * 2, 150); } else if (type == 2) { g_Map.log("Creating islands"); createAreas( new ClumpPlacer(islandSize * randFloat(0.6, 1.4), 0.8, 0.1, randFloat(0.0, 0.2)), [ landElevationPainter, new TileClassPainter(clLand) ], avoidClasses(clLand, 3, clPlayerTerritory, 3), scaleByMapSize(6, 10) * randIntInclusive(8, 14)); g_Map.log("Creating small islands"); createAreas( new ClumpPlacer(islandSize * randFloat(0.3, 0.7), 0.8, 0.1, 0.07), [ new SmoothElevationPainter(ELEVATION_SET, heightLand, 6), new TileClassPainter(clLand) ], avoidClasses(clLand, 3, clPlayerTerritory, 3), scaleByMapSize(2, 6) * randIntInclusive(6, 15), 25); } else if (type == 3) { g_Map.log("Creating tight islands"); createAreas( new ClumpPlacer(islandSize * randFloat(0.8, 1.2), 0.8, 0.1, Infinity), [ landElevationPainter, new TileClassPainter(clLand) ], avoidClasses(clLand, randIntInclusive(8, 16), clPlayerTerritory, 3), scaleByMapSize(2, 5) * randIntInclusive(8, 14)); } } /** * Disk shaped mainland with water on the edge. */ function unknownContinent() { let waterHeight = -5; if (!isNomad()) { g_Map.log("Ensuring player area"); [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.25)); markPlayerArea("small"); for (let i = 0; i < numPlayers; ++i) createArea( new ChainPlacer( 2, Math.floor(scaleByMapSize(5, 9)), Math.floor(scaleByMapSize(5, 20)), Infinity, playerPosition[i], 0, [Math.floor(scaleByMapSize(23, 50))]), [ landElevationPainter, new TileClassPainter(clLand) ]); } g_Map.log("Creating continent"); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.38)), 0.9, 0.09, Infinity, mapCenter), [ landElevationPainter, new TileClassPainter(clLand) ]); if (randBool(1/3)) { g_Map.log("Creating peninsula (i.e. half the map not being surrounded by water)"); let angle = randomAngle(); let peninsulaPosition1 = Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.25), 0).rotate(-angle)); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.38)), 0.9, 0.09, Infinity, peninsulaPosition1), [ landElevationPainter, new TileClassPainter(clLand) ]); g_Map.log("Remembering to not paint shorelines into the peninsula"); let peninsulaPosition2 = Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.35), 0).rotate(-angle)); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.33)), 0.9, 0.01, Infinity, peninsulaPosition2), new TileClassPainter(clPeninsulaSteam)); } createShoreJaggedness(waterHeight, clLand, 7); } function unknownCentralSea() { unknownCentralSeaOrIsthmus(false); } function unknownIsthmus() { unknownCentralSeaOrIsthmus(true); } /** * Creates a huge central river, possibly connecting the riversides with a narrow piece of land. */ function unknownCentralSeaOrIsthmus(isthmus) { let waterHeight = -3; let startAngle = randomAngle(); let [riverStart, riverEnd] = centralRiverCoordinates(startAngle); paintRiver({ "parallel": false, "start": riverStart, "end": riverEnd, "width": fractionToTiles(scaleByMapSize(0.27, 0.42) + randFloat(0, 0.08)), "fadeDist": scaleByMapSize(3, 12), "deviation": 0, "heightRiverbed": waterHeight, "heightLand": heightLand, "meanderShort": 20, "meanderLong": 0, "waterFunc": (position, height, riverFraction) => { if (height < 0) clWater.add(position); }, "landFunc": (position, shoreDist1, shoreDist2) => { g_Map.setHeight(position, 3.1); clLand.add(position); } }); if (!isNomad()) { [playerIDs, playerPosition] = playerPlacementRiver(startAngle + Math.PI / 2, fractionToTiles(0.6)); markPlayerArea("small"); } if (isthmus) { g_Map.log("Creating isthmus (i.e. connecting the two riversides with a big land passage)"); let [isthmusStart, isthmusEnd] = centralRiverCoordinates(startAngle + Math.PI / 2); createArea( new PathPlacer( isthmusStart, isthmusEnd, scaleByMapSize(randIntInclusive(16, 24), randIntInclusive(100, 140)), 0.5, 3 * scaleByMapSize(1, 4), 0.1, 0.01), [ landElevationPainter, new TileClassPainter(clLand), new TileClassUnPainter(clWater) ]); } createExtensionsOrIslands(); // Don't createShoreJaggedness since it doesn't fit artistically here } function unknownCentralRiverLand() { unknownCentralRiver(true); } function unknownCentralRiverNaval() { unknownCentralRiver(false); } /** * Creates a very small central river. */ function unknownCentralRiver(shallows) { let waterHeight = -4; let heightShallow = -2; createArea( new MapBoundsPlacer(), new ElevationPainter(heightLand)); let startAngle = randomAngle(); if (!isNomad()) { [playerIDs, playerPosition] = playerPlacementRiver(startAngle + Math.PI / 2, fractionToTiles(0.5)); markPlayerArea("large"); } g_Map.log("Creating the main river"); let [coord1, coord2] = centralRiverCoordinates(startAngle); createArea( new PathPlacer(coord1, coord2, scaleByMapSize(14, 24), 0.5, scaleByMapSize(3, 12), 0.1, 0.01), new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), avoidClasses(clPlayerTerritory, 4)); g_Map.log("Creating small water spots at the map border to ensure separation of players"); for (let coord of [coord1, coord2]) createArea( new ClumpPlacer(diskArea(scaleByMapSize(5, 10)), 0.95, 0.6, Infinity, coord), new SmoothElevationPainter(ELEVATION_SET, waterHeight, 2), avoidClasses(clPlayerTerritory, 8)); if (shallows) { g_Map.log("Creating the shallows of the main river"); for (let i = 0; i <= randIntInclusive(1, scaleByMapSize(4, 8)); ++i) { let location = fractionToTiles(randFloat(0.15, 0.85)); createPassage({ "start": new Vector2D(location, mapBounds.top).rotateAround(startAngle, mapCenter), "end": new Vector2D(location, mapBounds.bottom).rotateAround(startAngle, mapCenter), "startWidth": scaleByMapSize(8, 12), "endWidth": scaleByMapSize(8, 12), "smoothWidth": 2, "startHeight": heightShallow, "endHeight": heightShallow, "constraints": new HeightConstraint(-Infinity, heightShallow), "tileClass": clShallow }); } } if (randBool(2/3)) createTributaryRivers( startAngle, randIntInclusive(8, scaleByMapSize(12, 16)), scaleByMapSize(10, 20), -4, [-6, -1.5], Math.PI / 5, clWater, clShallow, avoidClasses(clPlayerTerritory, 3)); } /** * Creates a circular lake in the middle and possibly a river between each player ("pizza slices"). */ function unknownRiversAndLake() { let waterHeight = -4; createArea( new MapBoundsPlacer(), new ElevationPainter(heightLand)); let startAngle; if (!isNomad()) { let playerAngle; [playerIDs, playerPosition, playerAngle, startAngle] = playerPlacementCircle(fractionToTiles(0.35)); markPlayerArea("small"); } let lake = randBool(3/4); if (lake) { g_Map.log("Creating lake"); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.17)), 0.7, 0.1, Infinity, mapCenter), [ new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), new TileClassPainter(clWater) ]); createShoreJaggedness(waterHeight, clWater, 3); } // TODO: On nomad because the resource imbalances per island are too drastic { g_Map.log("Creating small rivers separating players"); for (let river of distributePointsOnCircle(numPlayers, startAngle + Math.PI / numPlayers, fractionToTiles(0.5), mapCenter)[0]) { createArea( new PathPlacer(mapCenter, river, scaleByMapSize(14, 24), 0.4, 3 * scaleByMapSize(1, 3), 0.2, 0.05), [ new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), new TileClassPainter(clWater) ], avoidClasses(clPlayer, 5)); createArea( new ClumpPlacer(diskArea(scaleByMapSize(4, 22)), 0.95, 0.6, Infinity, river), [ new SmoothElevationPainter(ELEVATION_SET, waterHeight, 0), new TileClassPainter(clWater) ], avoidClasses(clPlayer, 5)); } g_Map.log("Creating small lake"); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.04)), 0.7, 0.1, Infinity, mapCenter), [ new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), new TileClassPainter(clWater) ]); } if (!isNomad && lake && randBool(2/3)) { g_Map.log("Creating small central island"); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.05)), 0.7, 0.1, Infinity, mapCenter), [ landElevationPainter, new TileClassPainter(clWater) ]); } } /** * Align players on a land strip with seas bordering on one or both sides that can hold islands. */ function unknownEdgeSeas() { let waterHeight = -4; createArea( new MapBoundsPlacer(), new ElevationPainter(heightLand)); let startAngle = randomAngle(); if (!isNomad()) { playerIDs = sortAllPlayers(); playerPosition = playerPlacementLine(startAngle + Math.PI / 2, mapCenter, fractionToTiles(0.2)); // Don't place the shoreline inside the CC, but possibly into the players territory markPlayerArea("small"); } for (let side of pickRandom([[0], [Math.PI], [0, Math.PI]])) paintRiver({ "parallel": true, "start": new Vector2D(mapBounds.left, mapBounds.top).rotateAround(side + startAngle, mapCenter), "end": new Vector2D(mapBounds.left, mapBounds.bottom).rotateAround(side + startAngle, mapCenter), "width": scaleByMapSize(80, randFloat(270, 320)), "fadeDist": scaleByMapSize(2, 8), "deviation": 0, "heightRiverbed": waterHeight, "heightLand": heightLand, "meanderShort": 20, "meanderLong": 0 }); createExtensionsOrIslands(); paintTileClassBasedOnHeight(0, heightCliff, 1, clLand); createShoreJaggedness(waterHeight, clLand, 7, false); } /** * Land shaped like a concrescent moon around a central lake. */ function unknownGulf() { let waterHeight = -3; createArea( new MapBoundsPlacer(), new ElevationPainter(heightLand)); let startAngle = randomAngle(); if (!isNomad()) { g_Map.log("Determining player locations"); playerPosition = playerPlacementCustomAngle( fractionToTiles(0.35), mapCenter, i => startAngle + 2/3 * Math.PI * (-1 + (numPlayers == 1 ? 1 : 2 * i / (numPlayers - 1))))[0]; markPlayerArea("large"); } let gulfParts = [ { "radius": fractionToTiles(0.16), "distance": fractionToTiles(0) }, { "radius": fractionToTiles(0.2), "distance": fractionToTiles(0.2) }, { "radius": fractionToTiles(0.22), "distance": fractionToTiles(0.49) } ]; for (let gulfPart of gulfParts) { let position = Vector2D.sub(mapCenter, new Vector2D(gulfPart.distance, 0).rotate(-startAngle)).round(); createArea( new ClumpPlacer(diskArea(gulfPart.radius), 0.7, 0.05, Infinity, position), [ new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), new TileClassPainter(clWater) ], avoidClasses(clPlayerTerritory, defaultPlayerBaseRadius())); } } /** * Mainland style with some small random lakes. */ function unknownLakes() { let waterHeight = -5; createArea( new MapBoundsPlacer(), new ElevationPainter(heightLand)); if (!isNomad()) { [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); markPlayerArea("large"); } g_Map.log("Creating lakes"); createAreas( new ClumpPlacer(scaleByMapSize(160, 700), 0.2, 0.1, Infinity), [ new SmoothElevationPainter(ELEVATION_SET, waterHeight, 5), new TileClassPainter(clWater) ], [avoidClasses(clPlayerTerritory, 12), randBool() ? avoidClasses(clWater, 8) : new NullConstraint()], scaleByMapSize(5, 16)); } /** * A large hill leaving players only a small passage to each of the the two neighboring players. */ function unknownPasses() { let heightMountain = 24; let waterHeight = -4; createArea( new MapBoundsPlacer(), new ElevationPainter(heightLand)); let playerAngle; let startAngle; if (!isNomad()) { [playerIDs, playerPosition, playerAngle, startAngle] = playerPlacementCircle(fractionToTiles(0.35)); markPlayerArea("small"); } else startAngle = randomAngle(); g_Map.log("Creating a mountain range between neighboring players"); for (let mountain of distributePointsOnCircle(numPlayers, startAngle + Math.PI / numPlayers, fractionToTiles(0.5), mapCenter)[0]) { createArea( new PathPlacer(mapCenter, mountain, scaleByMapSize(14, 24), 0.4, 3 * scaleByMapSize(1, 3), 0.2, 0.05), [ // More smoothing than this often results in the mountainrange becoming passable to one player. new SmoothElevationPainter(ELEVATION_SET, heightMountain, 1), new TileClassPainter(clWater) ], avoidClasses(clPlayer, 5)); // Small mountain at the map border between the players to ensure separation of players createArea( new ClumpPlacer(diskArea(scaleByMapSize(4, 22)), 0.95, 0.6, Infinity, mountain), new SmoothElevationPainter(ELEVATION_SET, heightMountain, 0), avoidClasses(clPlayer, 5)); } g_Map.log("Creating passages between neighboring players"); let passes = distributePointsOnCircle(numPlayers * 2, startAngle, fractionToTiles(0.35), mapCenter)[0]; for (let i = 0; i < numPlayers; ++i) { createArea( new PathPlacer( passes[2 * i], passes[2 * ((i + 1) % numPlayers)], scaleByMapSize(14, 24), 0.4, 3 * scaleByMapSize(1, 3), 0.2, 0.05), new SmoothElevationPainter(ELEVATION_SET, heightLand, 2)); } if (randBool(2/5)) { g_Map.log("Create central lake"); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.1)), 0.7, 0.1, Infinity, mapCenter), [ new SmoothElevationPainter(ELEVATION_SET, waterHeight, 3), new TileClassPainter(clWater) ]); } else { g_Map.log("Fill area between the paths"); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.05)), 0.7, 0.1, Infinity, mapCenter), [ new SmoothElevationPainter(ELEVATION_SET, heightMountain, 4), new TileClassPainter(clWater) ]); } } /** * Land enclosed by a hill that leaves small areas for civic centers and large central place. */ function unknownLowlands() { let heightMountain = 30; g_Map.log("Creating mountain that is going to separate players"); createArea( new MapBoundsPlacer(), new ElevationPainter(heightMountain)); let playerAngle; let startAngle; if (!isNomad()) { [playerIDs, playerPosition, playerAngle, startAngle] = playerPlacementCircle(fractionToTiles(0.35)); markPlayerArea("small"); } else startAngle = randomAngle(); g_Map.log("Creating valleys enclosed by the mountain"); let valleys = numPlayers; if (mapSize >= 128 && numPlayers <= 2 || mapSize >= 192 && numPlayers <= 3 || mapSize >= 320 && numPlayers <= 4 || mapSize >= 384 && numPlayers <= 5 || mapSize >= 448 && numPlayers <= 6) valleys *= 2; g_Map.log("Creating player valley"); for (let valley of distributePointsOnCircle(valleys, startAngle, fractionToTiles(0.35), mapCenter)[0]) { createArea( new ClumpPlacer(diskArea(scaleByMapSize(18, 32)), 0.65, 0.1, Infinity, valley), [ new SmoothElevationPainter(ELEVATION_SET, heightLand, 2), new TileClassPainter(clLand) ]); // Passage from player to center createArea( new PathPlacer(mapCenter, valley, scaleByMapSize(14, 24), 0.4, 3 * scaleByMapSize(1, 3), 0.2, 0.05), [ landElevationPainter, new TileClassPainter(clWater) ]); } g_Map.log("Creating the big central area"); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.18)), 0.7, 0.1, Infinity, mapCenter), [ landElevationPainter, new TileClassPainter(clWater) ]); } /** * No water, no hills. */ function unknownMainland() { createArea( new MapBoundsPlacer(), new ElevationPainter(3)); if (!isNomad()) { [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); markPlayerArea("small"); } } function centralRiverCoordinates(angle) { return [ new Vector2D(mapBounds.left + 1, mapCenter.y), new Vector2D(mapBounds.right - 1, mapCenter.y) ].map(v => v.rotateAround(angle, mapCenter)); } function createShoreJaggedness(waterHeight, borderClass, shoreDist, inwards = true) { g_Map.log("Creating shore jaggedness"); for (let i = 0; i < 2; ++i) if (i || inwards) createAreas( new ChainPlacer(2, Math.floor(scaleByMapSize(4, 6)), 15, Infinity), [ new SmoothElevationPainter(ELEVATION_SET, i ? heightLand : waterHeight, 4), i ? new TileClassPainter(clLand) : new TileClassUnPainter(clLand) ], [ avoidClasses(clPlayer, 20, clPeninsulaSteam, 20), borderClasses(borderClass, shoreDist, shoreDist) ], scaleByMapSize(7, 130) * 2, 150); } function createExtensionsOrIslands() { let rnd = randIntInclusive(1, 3); if (rnd == 1) { g_Map.log("Creating islands"); createAreas( new ClumpPlacer(Math.square(randIntInclusive(scaleByMapSize(8, 15), scaleByMapSize(15, 23))), 0.8, 0.1, randFloat(0, 0.2)), [ landElevationPainter, new TileClassPainter(clLand) ], avoidClasses(clLand, 3, clPlayer, 3), scaleByMapSize(2, 5) * randIntInclusive(8, 14)); } else if (rnd == 2) { g_Map.log("Creating extentions"); createAreas( new ChainPlacer(Math.floor(scaleByMapSize(4, 7)), Math.floor(scaleByMapSize(7, 10)), Math.floor(scaleByMapSize(16, 40)), 0.07), [ landElevationPainter, new TileClassPainter(clLand) ], null, scaleByMapSize(2, 5) * randIntInclusive(8, 14)); } } /** * Prevent impassable terrain and resource collisions at the the civic center and starting resources. */ function markPlayerArea(size) { for (let i = 0; i < numPlayers; ++i) { addCivicCenterAreaToClass(playerPosition[i], clPlayer); if (size == "large") createArea( new ClumpPlacer(diskArea(scaleByMapSize(17, 29) / 3), 0.6, 0.3, Infinity, playerPosition[i]), new TileClassPainter(clPlayerTerritory)); } } function paintUnknownMapBasedOnHeight() { paintTerrainBasedOnHeight(heightCliff, 40, 1, tCliff); paintTerrainBasedOnHeight(3, heightCliff, 1, tMainTerrain); paintTerrainBasedOnHeight(1, 3, 1, tShore); paintTerrainBasedOnHeight(-8, 1, 2, tWater); unPaintTileClassBasedOnHeight(0, heightCliff, 1, clWater); unPaintTileClassBasedOnHeight(-6, 0, 1, clLand); paintTileClassBasedOnHeight(-6, 0, 1, clWater); paintTileClassBasedOnHeight(0, heightCliff, 1, clLand); paintTileClassBasedOnHeight(heightCliff, 40, 1, clHill); } /** * Place resources and decoratives after the player territory was marked. */ function createUnknownObjects() { g_Map.log("Creating bumps"); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, Infinity), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), [avoidClasses(clWater, 2, clPlayer, 10), stayClasses(clLand, 3)], randIntInclusive(0, scaleByMapSize(1, 2) * 200)); g_Map.log("Creating hills"); createAreas( new ClumpPlacer(scaleByMapSize(20, 150), 0.2, 0.1, Infinity), [ new LayeredPainter([tCliff, tHill], [2]), new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), new TileClassPainter(clHill) ], [avoidClasses(clPlayer, 15, clHill, randIntInclusive(6, 18)), stayClasses(clLand, 0)], randIntInclusive(0, scaleByMapSize(4, 8))*randIntInclusive(1, scaleByMapSize(4, 9)) ); Engine.SetProgress(30); g_Map.log("Creating forests"); let [numForest, numStragglers] = getTreeCounts(...rBiomeTreeCount(1)); let types = [ [[tForestFloor2, tMainTerrain, pForest1], [tForestFloor2, pForest1]], [[tForestFloor1, tMainTerrain, pForest2], [tForestFloor1, pForest2]] ]; let size = numForest / (scaleByMapSize(2, 8) * numPlayers); let num = Math.floor(size / types.length); for (let type of types) createAreas( new ClumpPlacer(numForest / num, 0.1, 0.1, Infinity), [ new LayeredPainter(type, [2]), new TileClassPainter(clForest) ], [avoidClasses(clPlayer, 20, clForest, randIntInclusive(5, 15), clHill, 2), stayClasses(clLand, 4)], num); Engine.SetProgress(50); g_Map.log("Creating dirt patches"); let patchCount = (currentBiome() == "generic/savanna" ? 3 : 1) * scaleByMapSize(15, 45); for (let patchSize of [scaleByMapSize(3, 48), scaleByMapSize(5, 84), scaleByMapSize(8, 128)]) createAreas( new ClumpPlacer(patchSize, 0.3, 0.06, 0.5), [ new LayeredPainter([[tMainTerrain, tTier1Terrain], [tTier1Terrain, tTier2Terrain], [tTier2Terrain, tTier3Terrain]], [1, 1]), new TileClassPainter(clDirt) ], [avoidClasses(clForest, 0, clHill, 2, clDirt, 5, clPlayer, 7), stayClasses(clLand, 4)], patchCount); g_Map.log("Creating grass patches"); for (let size of [scaleByMapSize(2, 32), scaleByMapSize(3, 48), scaleByMapSize(5, 80)]) createAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), new TerrainPainter(tTier4Terrain), [avoidClasses(clForest, 0, clHill, 2, clDirt, 5, clPlayer, 7), stayClasses(clLand, 4)], patchCount); Engine.SetProgress(55); g_Map.log("Creating stone mines"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], true, clRock), 0, [avoidClasses(clForest, 1, clPlayer, 10, clRock, 10, clHill, 2), stayClasses(clLand, 3)], randIntInclusive(scaleByMapSize(2, 9), scaleByMapSize(9, 40)), 100); g_Map.log("Creating small stone quarries"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oStoneSmall, 2, 5, 1, 3)], true, clRock), 0, [avoidClasses(clForest, 1, clPlayer, 10, clRock, 10, clHill, 2), stayClasses(clLand, 3)], randIntInclusive(scaleByMapSize(2, 9), scaleByMapSize(9, 40)), 100); g_Map.log("Creating metal mines"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oMetalLarge, 1, 1, 0, 4)], true, clMetal), 0, [avoidClasses(clForest, 1, clPlayer, 10, clMetal, 10, clRock, 5, clHill, 2), stayClasses(clLand, 3)], randIntInclusive(scaleByMapSize(2, 9), scaleByMapSize(9, 40)), 100); Engine.SetProgress(65); g_Map.log("Creating small decorative rocks"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(aRockMedium, 1, 3, 0, 1)], true), 0, [avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 2), stayClasses(clLand, 3)], scaleByMapSize(16, 262), 50); g_Map.log("Creating large decorative rocks"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(aRockLarge, 1, 2, 0, 1), new SimpleObject(aRockMedium, 1, 3, 0, 2)], true), 0, [avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 2), stayClasses(clLand, 3)], scaleByMapSize(8, 131), 50); Engine.SetProgress(70); g_Map.log("Creating deer"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oMainHuntableAnimal, 5, 7, 0, 4)], true, clFood), 0, [avoidClasses(clWater, 0, clForest, 0, clPlayer, 8, clHill, 2, clFood, 20), stayClasses(clLand, 2)], randIntInclusive(numPlayers + 3, 5 * numPlayers + 4), 50); g_Map.log("Creating berry bush"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oFruitBush, 5, 7, 0, 4)], true, clFood), 0, [avoidClasses(clWater, 0, clForest, 0, clPlayer, 8, clHill, 2, clFood, 20), stayClasses(clLand, 2)], randIntInclusive(1, 4) * numPlayers + 2, 50); Engine.SetProgress(75); g_Map.log("Creating sheep"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oSecondaryHuntableAnimal, 2, 3, 0, 2)], true, clFood), 0, [avoidClasses(clWater, 0, clForest, 0, clPlayer, 8, clHill, 2, clFood, 20), stayClasses(clLand, 2)], randIntInclusive(numPlayers + 3, 5 * numPlayers + 4), 50); g_Map.log("Creating fish"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oFish, 2, 3, 0, 2)], true, clFood), 0, avoidClasses(clLand, 4, clForest, 0, clPlayer, 0, clHill, 2, clFood, 20), randIntInclusive(15, 40) * numPlayers, 60); Engine.SetProgress(85); g_Map.log("Creating straggler trees"); types = [g_Gaia.tree1, g_Gaia.tree2, g_Gaia.tree3, g_Gaia.tree4]; num = Math.floor(numStragglers / types.length); for (let type of types) createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(type, 1, 1, 0, 3)], true, clForest), 0, [avoidClasses(clWater, 1, clForest, 1, clHill, 2, clPlayer, 0, clMetal, 6, clRock, 6, clBaseResource, 6), stayClasses(clLand, 4)], num); let planetm = currentBiome() == "generic/india" ? 8 : 1; g_Map.log("Creating small grass tufts"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(aGrassShort, 1, 2, 0, 1, -Math.PI / 8, Math.PI / 8)]), 0, [avoidClasses(clWater, 2, clHill, 2, clPlayer, 2, clDirt, 0), stayClasses(clLand, 3)], planetm * scaleByMapSize(13, 200)); Engine.SetProgress(90); g_Map.log("Creating large grass tufts"); createObjectGroupsDeprecated( new SimpleGroup([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)]), 0, [avoidClasses(clWater, 3, clHill, 2, clPlayer, 2, clDirt, 1, clForest, 0), stayClasses(clLand, 3)], planetm * scaleByMapSize(13, 200)); Engine.SetProgress(95); g_Map.log("Creating shallow flora"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(aLillies, 1, 2, 0, 2), new SimpleObject(aReeds, 2, 4, 0, 2)]), 0, stayClasses(clShallow, 1), 60 * scaleByMapSize(13, 200), 80); g_Map.log("Creating bushes"); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(aBushMedium, 1, 2, 0, 2), new SimpleObject(aBushSmall, 2, 4, 0, 2)]), 0, [avoidClasses(clWater, 1, clHill, 2, clPlayer, 1, clDirt, 1), stayClasses(clLand, 3)], planetm * scaleByMapSize(13, 200), 50); setSkySet(pickRandom(["cirrus", "cumulus", "sunny", "sunny 1", "mountainous", "stratus"])); setSunRotation(randomAngle()); setSunElevation(Math.PI * randFloat(1/5, 1/3)); } function createUnknownPlayerBases() { placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "BaseResourceClass": clBaseResource, "Walls": g_StartingWalls, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad, "painters": [ new TileClassPainter(clPlayer) ] }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oFruitBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Treasures": { "types": [ { "template": oWoodTreasure, "count": g_StartingTreasures ? 14 : 0 } ] }, "Trees": { "template": oTree1 }, "Decoratives": { "template": aGrassShort } }); } createUnknownMap(); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/alpine.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/alpine.json (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/alpine.json (revision 26381) @@ -1,100 +1,100 @@ { "Description": { "Title": "Subalpine", "Description": "Between the high summits of the Alps, the valleys are filled with fog in the early morning. The ground is full of gravel and rocks, but silver fir and spruce trees grow between them and provide shelter for deer and mountain goats." }, "Environment": { "SkySet": "cloudless", "SunColor": { "r": 1.01866, "g": 1.0395, "b": 0.97284 }, "SunElevation": 0.589049, "SunRotation": -1.442871, "AmbientColor": { "r": 0.389608, "g": 0.374118, "b": 0.523922 }, "Water": { "WaterBody": { "Type": "clap", "Color": { "r": 0.0784314, "g": 0.247059, "b": 0.419608 }, "Tint": { "r": 0.471, "g": 1, "b": 0.501961 }, "Murkiness": 0.88, "Waviness": 2 } }, "Fog": { "FogThickness": 0.00195313, "FogFactor": 0.00305664, "FogColor": { "r": 0.8, "g": 0.8, "b": 0.9 } }, "Postproc": { "PostprocEffect": "hdr", "Brightness": 0, "Saturation": 1, "Contrast": 1, "Bloom": 0.14 } }, "Terrains": { "mainTerrain": [ "steppe_grass_02" ], "forestFloor1": "alpine_forestfloor_01", "forestFloor2": "alpine_forestfloor_01", "cliff": [ "alpine_rock_02" ], "tier1Terrain": [ "steppe_grass_dirt_02" ], "tier2Terrain": [ "alpine_forestfloor_02" ], "tier3Terrain": [ "steppe_rocks_dirt_01" ], "tier4Terrain": "aegean_grass_dirt_03", "hill": [ "alpine_rock_01", "alpine_rock_02" ], "dirt": [ "alpine_forestfloor_01" ], "road": "alpine_paving_stones_02", "roadWild": "alpine_paving_stones_02", "shoreBlend": "aegean_grass_dirt_03", "shore": "aegean_grass_dirt_03", "water": "steppe_rocks_dirt_01" }, "Gaia": { "tree1": "gaia/tree/pine", "tree2": "gaia/tree/fir", "tree3": "gaia/tree/oak_hungarian_autumn", "tree4": "gaia/tree/fir_sapling", "tree5": "gaia/tree/elm", "fruitBush": "gaia/fruit/berry_01", - "chicken": "gaia/fauna_chicken", + "startingAnimal": "gaia/fauna_chicken", "mainHuntableAnimal": "gaia/fauna_goat", "fish": "gaia/fish/tuna", "secondaryHuntableAnimal": "gaia/fauna_deer", "stoneLarge": "gaia/rock/temperate_large_02", "stoneSmall": "gaia/rock/temperate_small", "metalLarge": "gaia/ore/temperate_02", "metalSmall": "gaia/ore/temperate_small" }, "Decoratives": { "grass": "actor|props/flora/grass_soft_small_tall.xml", "grassShort": "actor|props/flora/grass_soft_large.xml", "reeds": "actor|props/flora/cattails.xml", "lillies": "actor|geology/stone_granite_large.xml", "rockLarge": "actor|geology/stone_granite_large.xml", "rockMedium": "actor|geology/stone_granite_med.xml", "bushMedium": "gaia/tree/bush_temperate", "bushSmall": "actor|flora/trees/lavender_bush_01.xml", "tree": "actor|flora/trees/pine.xml" }, "ResourceCounts": { "trees": { "min": 1000, "max": 2000, "forestProbability": 0.85 } } } Index: ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/nubia.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/nubia.json (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/nubia.json (revision 26381) @@ -1,92 +1,92 @@ { "Description": { "Title": "Nubia", "Description": "Nubia, a dry climate in which only the hardy Baobab trees thrive. Solitary gazelles graze the sparse grass, while herds of zebras, wildebeest, giraffes or elephants roam the wild in search of food." }, "Environment": { "SunColor": { "r": 1.10039, "g": 1.05979, "b": 0.99212 }, "SunElevation": 0.7, "SunRotation": -1.7, "AmbientColor": { "r": 0.354118, "g": 0.361961, "b": 0.389412 }, "Water": { "WaterBody": { "Color": { "r": 0.337255, "g": 0.247059, "b": 0.0784314 }, "Tint": { "r": 0.337255, "g": 0.247059, "b": 0.0784314 }, "Murkiness": 0.96, "Waviness": 5 } }, "Fog": { "FogThickness": 0.01, "FogFactor": 0.00205078, "FogColor": { "r": 0.929412, "g": 0.87451, "b": 0.839216 } }, "Postproc": { "PostprocEffect": "hdr", "Contrast": 1.04, "Saturation": 0.95, "Bloom": 0.142969 } }, "Terrains": { "mainTerrain": [ "nubia_sand_01", "nubia_sand_ripples", "nubia_sand_dunes_01" ], "forestFloor1": "nubia_forestfloor_01", "forestFloor2": "nubia_forestfloor_01", "cliff": [ "nubia_rock_02", "nubia_rock_01" ], "tier1Terrain": "nubia_sand_03", "tier2Terrain": "nubia_rocks_dirt_01", "tier3Terrain": "nubia_rocks_dirt_02", "tier4Terrain": "nubia_rocks_dirt_03", "hill": [ "nubia_dirt_02", "nubia_dirt_01" ], "dirt": [ "nubia_dirt_01", "nubia_dirt_02", "nubia_dirt_03", "nubia_dirt_04" ], "road": "nubia_paving_stones_01", "roadWild": "nubia_paving_stones_01_sand_01", "shoreBlend": "nubia_dirt_cracks_01", "shore": "nubia_sand_02", "water": "nubia_sand_02_wet" }, "Gaia": { "tree3": "gaia/tree/baobab_4_dead", "fruitBush": "gaia/fruit/date", - "chicken": "gaia/fauna_chicken", + "startingAnimal": "gaia/fauna_chicken", "fish": "gaia/fish/generic", "secondaryHuntableAnimal": "gaia/fauna_gazelle", "stoneLarge": "gaia/rock/savanna_large", "stoneSmall": "gaia/rock/savanna_small", "metalLarge": "gaia/ore/india_01", "metalSmall": "gaia/ore/desert_small" }, "Decoratives": { "grass": "actor|props/flora/grass_savanna_field_tall.xml", "grassShort": "actor|props/flora/grass_savanna.xml", "reeds": "actor|props/flora/papyrus.xml", "lillies": "actor|props/flora/water_lillies.xml", "rockLarge": "actor|geology/stone_savanna_med.xml", "rockMedium": "actor|geology/stone_savanna_med.xml", "bushMedium": "gaia/tree/bush_tropic", "bushSmall": "actor|props/flora/bush_dry_a.xml", "tree": "gaia/tree/date_palm_dead" }, "ResourceCounts": { "trees": { "min": 500, "max": 1000, "forestProbability": 0.25 } } } Index: ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/temperate.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/temperate.json (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/temperate.json (revision 26381) @@ -1,80 +1,80 @@ { "Description": { "Title": "Temperate", "Description": "Lush grasslands carpet the land, in places giving way to magnificent and diverse broadleaf forests. Poplars, pines, beeches and oaks all vie for supremacy but this root-war is a neverending struggle. Numerous apple trees dot the land, deer and sheep gorge themselves on this years fallen fruit." }, "Environment": { "SunColor": { "r": 1.032, "g": 0.99, "b": 0.866 }, "SunElevation": 0.846, "SunRotation": -0.488, "AmbientColor": { "r": 0.364706, "g": 0.376471, "b": 0.419608 }, "Water": { "WaterBody": { "Color": { "r": 0.419608, "g": 0.364706, "b": 0.313726 }, "Tint": { "r": 0.501961, "g": 0.501961, "b": 0.247059 }, "Murkiness": 0.97, "Waviness": 5 } }, "Fog": { "FogThickness": 0.0, "FogFactor": 0.0024, "FogColor": { "r": 0.894118, "g": 0.894118, "b": 0.894118 } }, "Postproc": { "PostprocEffect": "hdr", "Saturation": 0.95, "Contrast": 1.05, "Bloom": 0.16 } }, "Terrains": { "cliff": [ "temperate_cliff_01", "temperate_cliff_02" ], "hill": [ "temperate_rocks_dirt_01", "temperate_grass_dirt_03" ], "dirt": [ "temperate_mud_01", "temperate_grass_mud_01" ], "road": "temperate_paving_03", "roadWild": "temperate_paving_03", "shoreBlend": "temperate_grass_dirt_01", "shore": "temperate_grass_mud_01", "water": "temperate_mud_01" }, "Gaia": { "fruitBush": "gaia/fruit/berry_01", - "chicken": "gaia/fauna_chicken", + "startingAnimal": "gaia/fauna_chicken", "fish": "gaia/fish/generic", "mainHuntableAnimal": "gaia/fauna_deer", "secondaryHuntableAnimal": "gaia/fauna_sheep", "stoneLarge": "gaia/rock/temperate_large_02", "stoneSmall": "gaia/rock/temperate_small", "metalLarge": "gaia/ore/temperate_01", "metalSmall": "gaia/ore/temperate_small", "tree3": "gaia/fruit/apple" }, "Decoratives": { "grass": "actor|props/flora/grass_soft_large_tall.xml", "grassShort": "actor|props/flora/grass_soft_large.xml", "reeds": "actor|props/flora/cattails.xml", "lillies": "actor|props/flora/water_lillies.xml", "rockLarge": "actor|geology/stone_granite_med.xml", "rockMedium": "actor|geology/stone_granite_small.xml", "bushMedium": "gaia/tree/bush_temperate", "bushSmall": "actor|props/flora/bush_medit_sm.xml", "tree": "actor|flora/trees/elm_dead.xml" }, "ResourceCounts": { "trees": { "min": 1000, "max": 3000, "forestProbability": 0.7 } } } Index: ps/trunk/binaries/data/mods/public/maps/random/rmgen-common/player.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rmgen-common/player.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/rmgen-common/player.js (revision 26381) @@ -1,845 +1,849 @@ /** * @file These functions locate and place the starting entities of players. */ var g_NomadTreasureTemplates = { "food": "gaia/treasure/food_jars", "wood": "gaia/treasure/wood", "stone": "gaia/treasure/stone", "metal": "gaia/treasure/metal" }; /** * These are identifiers of functions that can generate parts of a player base. * There must be a function starting with placePlayerBase and ending with this name. * This is a global so mods can extend this from external files. */ var g_PlayerBaseFunctions = [ // Possibly mark player class first here and use it afterwards "CityPatch", // Create the largest and most important entities first "Trees", "Mines", "Treasures", "Berries", - "Chicken", + "StartingAnimal", "Decoratives" ]; function isNomad() { return !!g_MapSettings.Nomad; } function getNumPlayers() { return g_MapSettings.PlayerData.length - 1; } function getCivCode(playerID) { return g_MapSettings.PlayerData[playerID].Civ; } function areAllies(playerID1, playerID2) { return g_MapSettings.PlayerData[playerID1].Team !== undefined && g_MapSettings.PlayerData[playerID2].Team !== undefined && g_MapSettings.PlayerData[playerID1].Team != -1 && g_MapSettings.PlayerData[playerID2].Team != -1 && g_MapSettings.PlayerData[playerID1].Team === g_MapSettings.PlayerData[playerID2].Team; } function getPlayerTeam(playerID) { if (g_MapSettings.PlayerData[playerID].Team === undefined) return -1; return g_MapSettings.PlayerData[playerID].Team; } /** * Gets the default starting entities for the civ of the given player, as defined by the civ file. */ function getStartingEntities(playerID) { return g_CivData[getCivCode(playerID)].StartEntities; } /** * Places the given entities at the given location (typically a civic center and starting units). * @param location - A Vector2D specifying tile coordinates. * @param civEntities - An array of objects with the Template property and optionally a Count property. * The first entity is placed in the center, the other ones surround it. */ function placeStartingEntities(location, playerID, civEntities, dist = 6, orientation = BUILDING_ORIENTATION) { // Place the central structure let i = 0; let firstTemplate = civEntities[i].Template; if (firstTemplate.startsWith("structures/")) { g_Map.placeEntityPassable(firstTemplate, playerID, location, orientation); ++i; } // Place entities surrounding it let space = 2; for (let j = i; j < civEntities.length; ++j) { let angle = orientation - Math.PI * (1 - j / 2); let count = civEntities[j].Count || 1; for (let num = 0; num < count; ++num) { let position = Vector2D.sum([ location, new Vector2D(dist, 0).rotate(-angle), new Vector2D(space * (-num + (count - 1) / 2), 0).rotate(angle) ]); g_Map.placeEntityPassable(civEntities[j].Template, playerID, position, angle); } } } /** * Places the default starting entities as defined by the civilization definition, optionally including city walls. */ function placeCivDefaultStartingEntities(position, playerID, wallType, dist = 6, orientation = BUILDING_ORIENTATION) { placeStartingEntities(position, playerID, getStartingEntities(playerID), dist, orientation); placeStartingWalls(position, playerID, wallType, orientation); } /** * If the map is large enough and the civilization defines them, places the initial city walls or towers. * @param {string|boolean} wallType - Either "towers" to only place the wall turrets or a boolean indicating enclosing city walls. */ function placeStartingWalls(position, playerID, wallType, orientation = BUILDING_ORIENTATION) { let civ = getCivCode(playerID); if (civ != "iber" || g_Map.getSize() <= 128) return; // TODO: should prevent trees inside walls // When fixing, remove the DeleteUponConstruction flag from template_gaia_flora.xml if (wallType == "towers") placePolygonalWall(position, 15, ["entry"], "tower", civ, playerID, orientation, 7); else if (wallType) placeGenericFortress(position, 20, playerID); } /** * Places the civic center and starting resources for all given players. */ function placePlayerBases(playerBaseArgs) { g_Map.log("Creating playerbases"); let [playerIDs, playerPosition] = playerBaseArgs.PlayerPlacement; for (let i = 0; i < getNumPlayers(); ++i) { playerBaseArgs.playerID = playerIDs[i]; playerBaseArgs.playerPosition = playerPosition[i]; placePlayerBase(playerBaseArgs); } } /** * Places the civic center and starting resources. */ function placePlayerBase(playerBaseArgs) { if (isNomad()) return; placeCivDefaultStartingEntities(playerBaseArgs.playerPosition, playerBaseArgs.playerID, playerBaseArgs.Walls !== undefined ? playerBaseArgs.Walls : true); if (playerBaseArgs.PlayerTileClass) addCivicCenterAreaToClass(playerBaseArgs.playerPosition, playerBaseArgs.PlayerTileClass); for (let functionID of g_PlayerBaseFunctions) { let funcName = "placePlayerBase" + functionID; let func = global[funcName]; if (!func) throw new Error("Could not find " + funcName); if (!playerBaseArgs[functionID]) continue; let args = playerBaseArgs[functionID]; // Copy some global arguments to the arguments for each function for (let prop of ["playerID", "playerPosition", "BaseResourceClass", "baseResourceConstraint"]) args[prop] = playerBaseArgs[prop]; func(args); } } function defaultPlayerBaseRadius() { return scaleByMapSize(15, 25); } /** * Marks the corner and center tiles of an area that is about the size of a Civic Center with the given TileClass. * Used to prevent resource collisions with the Civic Center. */ function addCivicCenterAreaToClass(position, tileClass) { createArea( new DiskPlacer(5, position), new TileClassPainter(tileClass)); } /** * Helper function. */ function getPlayerBaseArgs(playerBaseArgs) { let baseResourceConstraint = playerBaseArgs.BaseResourceClass && avoidClasses(playerBaseArgs.BaseResourceClass, 4); if (playerBaseArgs.baseResourceConstraint) baseResourceConstraint = new AndConstraint([baseResourceConstraint, playerBaseArgs.baseResourceConstraint]); return [ (property, defaultVal) => playerBaseArgs[property] === undefined ? defaultVal : playerBaseArgs[property], playerBaseArgs.playerPosition, baseResourceConstraint ]; } function placePlayerBaseCityPatch(args) { let [get, basePosition, baseResourceConstraint] = getPlayerBaseArgs(args); let painters = []; if (args.outerTerrain && args.innerTerrain) painters.push(new LayeredPainter([args.outerTerrain, args.innerTerrain], [get("width", 1)])); if (args.painters) painters = painters.concat(args.painters); createArea( new ClumpPlacer( Math.floor(diskArea(get("radius", defaultPlayerBaseRadius() / 3))), get("coherence", 0.6), get("smoothness", 0.3), get("failFraction", Infinity), basePosition), painters); } -function placePlayerBaseChicken(args) +function placePlayerBaseStartingAnimal(args) { let [get, basePosition, baseResourceConstraint] = getPlayerBaseArgs(args); + const template = get("template", "gaia/fauna_chicken"); + const count = template === "gaia/fauna_chicken" ? 5 : + Math.round(5 * (Engine.GetTemplate("gaia/fauna_chicken").ResourceSupply.Max / Engine.GetTemplate(get("template")).ResourceSupply.Max)) + for (let i = 0; i < get("groupCount", 2); ++i) { let success = false; for (let tries = 0; tries < get("maxTries", 30); ++tries) { let position = new Vector2D(0, get("distance", 9)).rotate(randomAngle()).add(basePosition); if (createObjectGroup( new SimpleGroup( [ new SimpleObject( - get("template", "gaia/fauna_chicken"), - get("minGroupCount", 5), - get("maxGroupCount", 5), + template, + get("minGroupCount", count), + get("maxGroupCount", count), get("minGroupDistance", 0), get("maxGroupDistance", 2)) ], true, args.BaseResourceClass, position), 0, baseResourceConstraint)) { success = true; break; } } if (!success) { - error("Could not place chicken for player " + args.playerID); + error("Could not place startingAnimal for player " + args.playerID); return; } } } function placePlayerBaseBerries(args) { let [get, basePosition, baseResourceConstraint] = getPlayerBaseArgs(args); for (let tries = 0; tries < get("maxTries", 30); ++tries) { let position = new Vector2D(0, get("distance", 12)).rotate(randomAngle()).add(basePosition); if (createObjectGroup( new SimpleGroup( [new SimpleObject(args.template, get("minCount", 5), get("maxCount", 5), get("maxDist", 1), get("maxDist", 3))], true, args.BaseResourceClass, position), 0, baseResourceConstraint)) return; } error("Could not place berries for player " + args.playerID); } function placePlayerBaseMines(args) { let [get, basePosition, baseResourceConstraint] = getPlayerBaseArgs(args); let angleBetweenMines = randFloat(get("minAngle", Math.PI / 6), get("maxAngle", Math.PI / 3)); let mineCount = args.types.length; let groupElements = []; if (args.groupElements) groupElements = groupElements.concat(args.groupElements); for (let tries = 0; tries < get("maxTries", 75); ++tries) { // First find a place where all mines can be placed let pos = []; let startAngle = randomAngle(); for (let i = 0; i < mineCount; ++i) { let angle = startAngle + angleBetweenMines * (i + (mineCount - 1) / 2); pos[i] = new Vector2D(0, get("distance", 12)).rotate(angle).add(basePosition).round(); if (!g_Map.validTilePassable(pos[i]) || !baseResourceConstraint.allows(pos[i])) { pos = undefined; break; } } if (!pos) continue; // Place the mines for (let i = 0; i < mineCount; ++i) { if (args.types[i].type && args.types[i].type == "stone_formation") { createStoneMineFormation(pos[i], args.types[i].template, args.types[i].terrain); args.BaseResourceClass.add(pos[i]); continue; } createObjectGroup( new SimpleGroup( [new SimpleObject(args.types[i].template, 1, 1, 0, 0)].concat(groupElements), true, args.BaseResourceClass, pos[i]), 0); } return; } error("Could not place mines for player " + args.playerID); } function placePlayerBaseTrees(args) { let [get, basePosition, baseResourceConstraint] = getPlayerBaseArgs(args); let num = Math.floor(get("count", scaleByMapSize(7, 20))); for (let x = 0; x < get("maxTries", 30); ++x) { let position = new Vector2D(0, randFloat(get("minDist", 11), get("maxDist", 13))).rotate(randomAngle()).add(basePosition).round(); if (createObjectGroup( new SimpleGroup( [new SimpleObject(args.template, num, num, get("minDistGroup", 0), get("maxDistGroup", 5))], false, args.BaseResourceClass, position), 0, baseResourceConstraint)) return; } error("Could not place starting trees for player " + args.playerID); } function placePlayerBaseTreasures(args) { let [get, basePosition, baseResourceConstraint] = getPlayerBaseArgs(args); for (let resourceTypeArgs of args.types) { get = (property, defaultVal) => resourceTypeArgs[property] === undefined ? defaultVal : resourceTypeArgs[property]; let success = false; for (let tries = 0; tries < get("maxTries", 30); ++tries) { let position = new Vector2D(0, randFloat(get("minDist", 11), get("maxDist", 13))).rotate(randomAngle()).add(basePosition).round(); if (createObjectGroup( new SimpleGroup( [new SimpleObject(resourceTypeArgs.template, get("count", 14), get("count", 14), get("minDistGroup", 1), get("maxDistGroup", 3))], false, args.BaseResourceClass, position), 0, baseResourceConstraint)) { success = true; break; } } if (!success) { error("Could not place treasure " + resourceTypeArgs.template + " for player " + args.playerID); return; } } } /** * Typically used for placing grass tufts around the civic centers. */ function placePlayerBaseDecoratives(args) { let [get, basePosition, baseResourceConstraint] = getPlayerBaseArgs(args); for (let i = 0; i < get("count", scaleByMapSize(2, 5)); ++i) { let success = false; for (let x = 0; x < get("maxTries", 30); ++x) { let position = new Vector2D(0, randIntInclusive(get("minDist", 8), get("maxDist", 11))).rotate(randomAngle()).add(basePosition).round(); if (createObjectGroup( new SimpleGroup( [new SimpleObject(args.template, get("minCount", 2), get("maxCount", 5), 0, 1)], false, args.BaseResourceClass, position), 0, baseResourceConstraint)) { success = true; break; } } if (!success) // Don't warn since the decoratives are not important return; } } function placePlayersNomad(playerClass, constraints) { if (!isNomad()) return undefined; g_Map.log("Placing nomad starting units"); let distance = scaleByMapSize(60, 240); let constraint = new StaticConstraint(constraints); let numPlayers = getNumPlayers(); let playerIDs = shuffleArray(sortAllPlayers()); let playerPosition = []; for (let i = 0; i < numPlayers; ++i) { let objects = getStartingEntities(playerIDs[i]).filter(ents => ents.Template.startsWith("units/")).map( ents => new SimpleObject(ents.Template, ents.Count || 1, ents.Count || 1, 1, 3)); // Add treasure if too few resources for a civic center let ccCost = Engine.GetTemplate("structures/" + getCivCode(playerIDs[i]) + "/civil_centre").Cost.Resources; for (let resourceType in ccCost) { let treasureTemplate = g_NomadTreasureTemplates[resourceType]; let count = Math.max(0, Math.ceil( (ccCost[resourceType] - (g_MapSettings.StartingResources || 0)) / Engine.GetTemplate(treasureTemplate).Treasure.Resources[resourceType])); objects.push(new SimpleObject(treasureTemplate, count, count, 3, 5)); } // Try place these entities at a random location let group = new SimpleGroup(objects, true, playerClass); let success = false; for (let distanceFactor of [1, 1/2, 1/4, 0]) if (createObjectGroups(group, playerIDs[i], new AndConstraint([constraint, avoidClasses(playerClass, distance * distanceFactor)]), 1, 200, false).length) { success = true; playerPosition[i] = group.centerPosition; break; } if (!success) throw new Error("Could not place starting units for player " + playerIDs[i] + "!"); } return [playerIDs, playerPosition]; } /** * Sorts an array of player IDs by team index. Players without teams come first. * Randomize order for players of the same team. */ function sortPlayers(playerIDs) { return shuffleArray(playerIDs).sort((playerID1, playerID2) => getPlayerTeam(playerID1) - getPlayerTeam(playerID2)); } /** * Randomize playerIDs but sort by team. * * @returns {Array} - every item is an array of player indices */ function sortAllPlayers() { let playerIDs = []; for (let i = 0; i < getNumPlayers(); ++i) playerIDs.push(i+1); return sortPlayers(playerIDs); } /** * Rearrange order so that teams of neighboring players alternate (if the given IDs are sorted by team). */ function primeSortPlayers(playerIDs) { let prime = []; for (let i = 0; i < Math.floor(playerIDs.length / 2); ++i) { prime.push(playerIDs[i]); prime.push(playerIDs[playerIDs.length - 1 - i]); } if (playerIDs.length % 2) prime.push(playerIDs[Math.floor(playerIDs.length / 2)]); return prime; } function primeSortAllPlayers() { return primeSortPlayers(sortAllPlayers()); } /* * Separates playerIDs into two arrays such that teammates are in the same array, * unless everyone's on the same team in which case they'll be split in half. */ function partitionPlayers(playerIDs) { let teamIDs = Array.from(new Set(playerIDs.map(getPlayerTeam))); let teams = teamIDs.map(teamID => playerIDs.filter(playerID => getPlayerTeam(playerID) == teamID)); if (teamIDs.indexOf(-1) != -1) teams = teams.concat(teams.splice(teamIDs.indexOf(-1), 1)[0].map(playerID => [playerID])); if (teams.length == 1) { let idx = Math.floor(teams[0].length / 2); teams = [teams[0].slice(idx), teams[0].slice(0, idx)]; } teams.sort((a, b) => b.length - a.length); // Use the greedy algorithm: add the next team to the side with fewer players return teams.reduce(([east, west], team) => east.length > west.length ? [east, west.concat(team)] : [east.concat(team), west], [[], []]); } /** * Determine player starting positions on a circular pattern. */ function playerPlacementCircle(radius, startingAngle = undefined, center = undefined) { let startAngle = startingAngle !== undefined ? startingAngle : randomAngle(); let [playerPosition, playerAngle] = distributePointsOnCircle(getNumPlayers(), startAngle, radius, center || g_Map.getCenter()); return [sortAllPlayers(), playerPosition.map(p => p.round()), playerAngle, startAngle]; } /** * Determine player starting positions on a circular pattern, with a custom angle for each player. * Commonly used for gulf terrains. */ function playerPlacementCustomAngle(radius, center, playerAngleFunc) { let playerPosition = []; let playerAngle = []; let numPlayers = getNumPlayers(); for (let i = 0; i < numPlayers; ++i) { playerAngle[i] = playerAngleFunc(i); playerPosition[i] = Vector2D.add(center, new Vector2D(radius, 0).rotate(-playerAngle[i])).round(); } return [playerPosition, playerAngle]; } /** * Returns player starting positions equally spaced along an arc. */ function playerPlacementArc(playerIDs, center, radius, startAngle, endAngle) { return distributePointsOnCircularSegment( playerIDs.length + 2, endAngle - startAngle, startAngle, radius, center )[0].slice(1, -1).map(p => p.round()); } /** * Returns player starting positions located on two symmetrically placed arcs, with teammates placed on the same arc. */ function playerPlacementArcs(playerIDs, center, radius, mapAngle, startAngle, endAngle) { let [east, west] = partitionPlayers(playerIDs); let eastPosition = playerPlacementArc(east, center, radius, mapAngle + startAngle, mapAngle + endAngle); let westPosition = playerPlacementArc(west, center, radius, mapAngle - startAngle, mapAngle - endAngle); return playerIDs.map(playerID => east.indexOf(playerID) != -1 ? eastPosition[east.indexOf(playerID)] : westPosition[west.indexOf(playerID)]); } /** * Returns player starting positions located on two parallel lines, typically used by central river maps. * If there are two teams with an equal number of players, each team will occupy exactly one line. * Angle 0 means the players are placed in north to south direction, i.e. along the Z axis. */ function playerPlacementRiver(angle, width, center = undefined) { let numPlayers = getNumPlayers(); let numPlayersEven = numPlayers % 2 == 0; let mapSize = g_Map.getSize(); let centerPosition = center || g_Map.getCenter(); let playerPosition = []; for (let i = 0; i < numPlayers; ++i) { let currentPlayerEven = i % 2 == 0; let offsetDivident = numPlayersEven || currentPlayerEven ? (i + 1) % 2 : 0; let offsetDivisor = numPlayersEven ? 0 : currentPlayerEven ? +1 : -1; playerPosition[i] = new Vector2D( width * (i % 2) + (mapSize - width) / 2, fractionToTiles(((i - 1 + offsetDivident) / 2 + 1) / ((numPlayers + offsetDivisor) / 2 + 1)) ).rotateAround(angle, centerPosition).round(); } return [primeSortAllPlayers(), playerPosition]; } /** * Returns starting positions located on two parallel lines. * The locations on the first line are shifted in comparison to the other line. */ function playerPlacementLine(angle, center, width) { let playerPosition = []; let numPlayers = getNumPlayers(); for (let i = 0; i < numPlayers; ++i) playerPosition[i] = Vector2D.add( center, new Vector2D( fractionToTiles((i + 1) / (numPlayers + 1) - 0.5), width * (i % 2 - 1/2) ).rotate(angle) ).round(); return playerPosition; } /** * Returns a random location for each player that meets the given constraints and * orders the playerIDs so that players become grouped by team. */ function playerPlacementRandom(playerIDs, constraints = undefined) { let locations = []; let attempts = 0; let resets = 0; let mapCenter = g_Map.getCenter(); let playerMinDistSquared = Math.square(fractionToTiles(0.25)); let borderDistance = fractionToTiles(0.08); let area = createArea(new MapBoundsPlacer(), undefined, new AndConstraint(constraints)); for (let i = 0; i < getNumPlayers(); ++i) { const position = pickRandom(area.getPoints()); if (!position) return undefined; // Minimum distance between initial bases must be a quarter of the map diameter if (locations.some(loc => loc.distanceToSquared(position) < playerMinDistSquared) || position.distanceToSquared(mapCenter) > Math.square(mapCenter.x - borderDistance)) { --i; ++attempts; // Reset if we're in what looks like an infinite loop if (attempts > 500) { locations = []; i = -1; attempts = 0; ++resets; // Reduce minimum player distance progressively if (resets % 25 == 0) playerMinDistSquared *= 0.95; // If we only pick bad locations, stop trying to place randomly if (resets == 500) return undefined; } continue; } locations[i] = position; } return groupPlayersByArea(playerIDs, locations); } /** * Pick locations from the given set so that teams end up grouped. */ function groupPlayersByArea(playerIDs, locations) { playerIDs = sortPlayers(playerIDs); let minDist = Infinity; let minLocations; // Of all permutations of starting locations, find the one where // the sum of the distances between allies is minimal, weighted by teamsize. heapsPermute(shuffleArray(locations).slice(0, playerIDs.length), v => v.clone(), permutation => { let dist = 0; let teamDist = 0; let teamSize = 0; for (let i = 1; i < playerIDs.length; ++i) { let team1 = getPlayerTeam(playerIDs[i - 1]); let team2 = getPlayerTeam(playerIDs[i]); ++teamSize; if (team1 != -1 && team1 == team2) teamDist += permutation[i - 1].distanceTo(permutation[i]); else { dist += teamDist / teamSize; teamDist = 0; teamSize = 0; } } if (teamSize) dist += teamDist / teamSize; if (dist < minDist) { minDist = dist; minLocations = permutation; } }); return [playerIDs, minLocations]; } /** * Sorts the playerIDs so that team members are as close as possible on a ring. */ function groupPlayersCycle(startLocations) { let startLocationOrder = sortPointsShortestCycle(startLocations); let newStartLocations = []; for (let i = 0; i < startLocations.length; ++i) newStartLocations.push(startLocations[startLocationOrder[i]]); startLocations = newStartLocations; // Sort players by team let playerIDs = []; let teams = []; for (let i = 0; i < g_MapSettings.PlayerData.length - 1; ++i) { playerIDs.push(i+1); let t = g_MapSettings.PlayerData[i + 1].Team; if (teams.indexOf(t) == -1 && t !== undefined) teams.push(t); } playerIDs = sortPlayers(playerIDs); if (!teams.length) return [playerIDs, startLocations]; // Minimize maximum distance between players within a team let minDistance = Infinity; let bestShift; for (let s = 0; s < playerIDs.length; ++s) { let maxTeamDist = 0; for (let pi = 0; pi < playerIDs.length - 1; ++pi) { let t1 = getPlayerTeam(playerIDs[(pi + s) % playerIDs.length]); if (teams.indexOf(t1) === -1) continue; for (let pj = pi + 1; pj < playerIDs.length; ++pj) { if (t1 != getPlayerTeam(playerIDs[(pj + s) % playerIDs.length])) continue; maxTeamDist = Math.max( maxTeamDist, Math.euclidDistance2D( startLocations[pi].x, startLocations[pi].y, startLocations[pj].x, startLocations[pj].y)); } } if (maxTeamDist < minDistance) { minDistance = maxTeamDist; bestShift = s; } } if (bestShift) { let newPlayerIDs = []; for (let i = 0; i < playerIDs.length; ++i) newPlayerIDs.push(playerIDs[(i + bestShift) % playerIDs.length]); playerIDs = newPlayerIDs; } return [playerIDs, startLocations]; } Index: ps/trunk/binaries/data/mods/public/maps/random/sahel_watering_holes.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/sahel_watering_holes.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/sahel_watering_holes.js (revision 26381) @@ -1,386 +1,386 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); const tGrass = "savanna_grass_a"; const tForestFloor = "savanna_forestfloor_a"; const tCliff = "savanna_cliff_b"; const tDirtRocksA = "savanna_dirt_rocks_c"; const tDirtRocksB = "savanna_dirt_rocks_a"; const tDirtRocksC = "savanna_dirt_rocks_b"; const tHill = "savanna_cliff_a"; const tRoad = "savanna_tile_a_red"; const tRoadWild = "savanna_tile_a_red"; const tGrassPatch = "savanna_grass_b"; const tShore = "savanna_riparian_bank"; const tWater = "savanna_riparian_wet"; const oBaobab = "gaia/tree/baobab"; const oFig = "gaia/fruit/fig"; const oBerryBush = "gaia/fruit/berry_01"; const oWildebeest = "gaia/fauna_wildebeest"; const oFish = "gaia/fish/generic"; const oGazelle = "gaia/fauna_gazelle"; const oElephant = "gaia/fauna_elephant_african_bush"; const oGiraffe = "gaia/fauna_giraffe"; const oZebra = "gaia/fauna_zebra"; const oStoneLarge = "gaia/rock/desert_large"; const oStoneSmall = "gaia/rock/savanna_small"; const oMetalLarge = "gaia/ore/savanna_large"; const aGrass = "actor|props/flora/grass_savanna.xml"; const aGrassShort = "actor|props/flora/grass_medit_field.xml"; const aRockLarge = "actor|geology/stone_savanna_med.xml"; const aRockMedium = "actor|geology/stone_savanna_med.xml"; const aBushMedium = "actor|props/flora/bush_desert_dry_a.xml"; const aBushSmall = "actor|props/flora/bush_dry_a.xml"; const pForest = [tForestFloor + TERRAIN_SEPARATOR + oBaobab, tForestFloor + TERRAIN_SEPARATOR + oBaobab, tForestFloor]; const heightSeaGround = -4; const heightShallows = -2; const heightLand = 3; const heightHill = 35; const heightOffsetBump = 2; var g_Map = new RandomMap(heightLand, tGrass); const numPlayers = getNumPlayers(); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clShallows = g_Map.createTileClass(); var [playerIDs, playerPosition, playerAngle, startAngle] = playerPlacementCircle(fractionToTiles(0.35)); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oBaobab, "count": 5 }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(20); g_Map.log("Creating rivers"); var riverStart = distributePointsOnCircle(numPlayers, startAngle + Math.PI / numPlayers, fractionToTiles(0.15), mapCenter)[0]; var riverEnd = distributePointsOnCircle(numPlayers, startAngle + Math.PI / numPlayers, fractionToTiles(0.49), mapCenter)[0]; for (let i = 0; i < numPlayers; ++i) { let neighborID = (i + 1) % numPlayers; // Lake near the center createArea( new ClumpPlacer(diskArea(scaleByMapSize(5, 30)), 0.95, 0.6, Infinity, riverStart[i]), [ new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4), new TileClassPainter(clWater) ], avoidClasses(clPlayer, 5)); // River between the players createArea( new PathPlacer(riverStart[i], riverEnd[i], scaleByMapSize(10, 50), 0.2, 3 * scaleByMapSize(1, 4), 0.2, 0.05), [ new LayeredPainter([tShore, tWater, tWater], [1, 3]), new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4), new TileClassPainter(clWater) ], avoidClasses(clPlayer, 5)); // Lake near the map border createArea( new ClumpPlacer(diskArea(scaleByMapSize(5, 22)), 0.95, 0.6, Infinity, riverEnd[i]), [ new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4), new TileClassPainter(clWater) ], avoidClasses(clPlayer, 5)); // Shallows between neighbors createPassage({ "start": playerPosition[i], "end": playerPosition[neighborID], "startWidth": 10, "endWidth": 10, "smoothWidth": 4, "startHeight": heightShallows, "endHeight": heightShallows, "constraints": new HeightConstraint(-Infinity, heightShallows), "tileClass": clShallows }); // Animals in shallows let shallowPosition = Vector2D.average([playerPosition[i], playerPosition[neighborID]]).round(); let objects = [ new SimpleObject(oWildebeest, 5, 6, 0, 4), new SimpleObject(oElephant, 2, 3, 0, 4) ]; for (let object of objects) createObjectGroup(new SimpleGroup([object], true, clFood, shallowPosition), 0); } paintTerrainBasedOnHeight(-6, 2, 1, tWater); g_Map.log("Creating bumps"); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, Infinity), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), avoidClasses(clWater, 2, clPlayer, 20), scaleByMapSize(100, 200)); g_Map.log("Creating hills"); createAreas( new ClumpPlacer(scaleByMapSize(20, 150), 0.2, 0.1, Infinity), [ new LayeredPainter([tGrass, tCliff, tHill], [1, 2]), new SmoothElevationPainter(ELEVATION_SET, heightHill, 3), new TileClassPainter(clHill) ], avoidClasses(clPlayer, 20, clHill, 15, clWater, 3), scaleByMapSize(1, 4) * numPlayers); g_Map.log("Creating forests"); var [forestTrees, stragglerTrees] = getTreeCounts(160, 900, 0.02); var types = [ [[tForestFloor, tGrass, pForest], [tForestFloor, pForest]] ]; var size = forestTrees / (0.5 * scaleByMapSize(2,8) * numPlayers); var num = Math.floor(size / types.length); for (let type of types) createAreas( new ClumpPlacer(forestTrees / num, 0.1, 0.1, Infinity), [ new LayeredPainter(type, [2]), new TileClassPainter(clForest) ], avoidClasses(clPlayer, 20, clForest, 10, clHill, 0, clWater, 2), num ); Engine.SetProgress(50); g_Map.log("Creating dirt patches"); for (let size of [scaleByMapSize(3, 48), scaleByMapSize(5, 84), scaleByMapSize(8, 128)]) createAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), [ new LayeredPainter( [[tGrass, tDirtRocksA], [tDirtRocksA, tDirtRocksB], [tDirtRocksB, tDirtRocksC]], [1, 1]), new TileClassPainter(clDirt) ], avoidClasses(clWater, 3, clForest, 0, clHill, 0, clPlayer, 20), scaleByMapSize(15, 45)); g_Map.log("Creating grass patches"); for (let size of [scaleByMapSize(2, 32), scaleByMapSize(3, 48), scaleByMapSize(5, 80)]) createAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), new TerrainPainter(tGrassPatch), avoidClasses(clWater, 3, clForest, 0, clHill, 0, clPlayer, 20), scaleByMapSize(15, 45)); Engine.SetProgress(55); g_Map.log("Creating stone mines"); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), scaleByMapSize(4,16), 100 ); g_Map.log("Creating small stone quarries"); group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), scaleByMapSize(4,16), 100 ); g_Map.log("Creating metal mines"); group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4)], true, clMetal); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 1), scaleByMapSize(4,16), 100 ); Engine.SetProgress(65); g_Map.log("Creating small decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockMedium, 1,3, 0,1)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0), scaleByMapSize(16, 262), 50 ); g_Map.log("Creating large decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRockLarge, 1,2, 0,1), new SimpleObject(aRockMedium, 1,3, 0,2)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0), scaleByMapSize(8, 131), 50 ); Engine.SetProgress(70); g_Map.log("Creating wildebeest"); group = new SimpleGroup( [new SimpleObject(oWildebeest, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 5), 3 * numPlayers, 50 ); Engine.SetProgress(75); g_Map.log("Creating gazelle"); group = new SimpleGroup( [new SimpleObject(oGazelle, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 5), 3 * numPlayers, 50 ); g_Map.log("Creating elephant"); group = new SimpleGroup( [new SimpleObject(oElephant, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 5), 3 * numPlayers, 50 ); g_Map.log("Creating giraffe"); group = new SimpleGroup( [new SimpleObject(oGiraffe, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 5), 3 * numPlayers, 50 ); g_Map.log("Creating zebra"); group = new SimpleGroup( [new SimpleObject(oZebra, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 5), 3 * numPlayers, 50 ); g_Map.log("Creating fish"); group = new SimpleGroup( [new SimpleObject(oFish, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, [avoidClasses(clFood, 20), stayClasses(clWater, 6)], 25 * numPlayers, 60 ); g_Map.log("Creating berry bush"); group = new SimpleGroup( [new SimpleObject(oBerryBush, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 10), randIntInclusive(1, 4) * numPlayers + 2, 50 ); Engine.SetProgress(85); createStragglerTrees( [oBaobab, oBaobab, oBaobab, oFig], avoidClasses(clWater, 5, clForest, 1, clHill, 1, clPlayer, 12, clMetal, 6, clRock, 6), clForest, stragglerTrees); var planetm = 4; g_Map.log("Creating small grass tufts"); group = new SimpleGroup( [new SimpleObject(aGrassShort, 1,2, 0,1, -Math.PI / 8, Math.PI / 8)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 2, clHill, 2, clPlayer, 2), planetm * scaleByMapSize(13, 200) ); Engine.SetProgress(90); g_Map.log("Creating large grass tufts"); group = new SimpleGroup( [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)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clHill, 2, clPlayer, 2, clForest, 0), planetm * scaleByMapSize(13, 200) ); Engine.SetProgress(95); g_Map.log("Creating bushes"); group = new SimpleGroup( [new SimpleObject(aBushMedium, 1,2, 0,2), new SimpleObject(aBushSmall, 2,4, 0,2)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 2, clHill, 1, clPlayer, 1), planetm * scaleByMapSize(13, 200), 50 ); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clHill, 4, clForest, 1, clMetal, 4, clRock, 4, clFood, 2)); setSkySet("sunny"); setSunRotation(randomAngle()); setSunElevation(Math.PI * randFloat(1/5, 1/4)); setWaterColor(0.478,0.42,0.384); // greyish setWaterTint(0.58,0.22,0.067); // reddish setWaterMurkiness(0.87); setWaterWaviness(0.5); setWaterType("clap"); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/the_nile.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/the_nile.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/the_nile.js (revision 26381) @@ -1,412 +1,412 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); var tPrimary = "desert_sand_dunes_100"; var tCity = "desert_city_tile"; var tCityPlaza = "desert_city_tile_plaza"; var tFineSand = "desert_sand_smooth"; var tForestFloor = "desert_forestfloor_palms"; var tGrass = "desert_dirt_rough_2"; var tGrassSand50 = "desert_sand_dunes_50"; var tGrassSand25 = "desert_dirt_rough"; var tDirt = "desert_dirt_rough"; var tDirtCracks = "desert_dirt_cracks"; var tShore = "desert_sand_wet"; var tLush = "desert_grass_a"; var tSLush = "desert_grass_a_sand"; var tSDry = "desert_plants_b"; var oBerryBush = "gaia/fruit/berry_01"; var oCamel = "gaia/fauna_camel"; var oGazelle = "gaia/fauna_gazelle"; var oGoat = "gaia/fauna_goat"; var oStoneLarge = "gaia/rock/badlands_large"; var oStoneSmall = "gaia/rock/desert_small"; var oMetalLarge = "gaia/ore/desert_large"; var oDatePalm = "gaia/tree/date_palm"; var oSDatePalm = "gaia/tree/cretan_date_palm_short"; var eObelisk = "structures/obelisk"; var ePyramid = "gaia/ruins/pyramid_minor"; var oWoodTreasure = "gaia/treasure/wood"; var oFoodTreasure = "gaia/treasure/food_bin"; var aBush1 = "actor|props/flora/bush_desert_a.xml"; var aBush2 = "actor|props/flora/bush_desert_dry_a.xml"; var aBush3 = "actor|props/flora/bush_medit_sm_dry.xml"; var aBush4 = "actor|props/flora/plant_desert_a.xml"; var aDecorativeRock = "actor|geology/stone_desert_med.xml"; var aReeds = "actor|props/flora/reeds_pond_lush_a.xml"; var aLillies = "actor|props/flora/water_lillies.xml"; var pForest = [tForestFloor + TERRAIN_SEPARATOR + oDatePalm, tForestFloor + TERRAIN_SEPARATOR + oSDatePalm, tForestFloor]; const heightLand = 1; const heightShore = 2; const heightPonds = -7; const heightSeaGround = -3; const heightOffsetBump = 2; var g_Map = new RandomMap(heightLand, tPrimary); const mapSize = g_Map.getSize(); const mapCenter = g_Map.getCenter(); const mapBounds = g_Map.getBounds(); var aPlants = mapSize < 256 ? "actor|props/flora/grass_tropical.xml" : "actor|props/flora/grass_tropic_field_tall.xml"; var numPlayers = getNumPlayers(); var clPlayer = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clDirt = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clGrass = g_Map.createTileClass(); var clDesert = g_Map.createTileClass(); var clPond = g_Map.createTileClass(); var clShore = g_Map.createTileClass(); var clTreasure = g_Map.createTileClass(); var desertWidth = fractionToTiles(0.25); var startAngle = randomAngle(); placePlayerBases({ "PlayerPlacement": playerPlacementRiver(startAngle, fractionToTiles(0.4)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tCityPlaza, "innerTerrain": tCity }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oDatePalm, "count": 2 }, "Decoratives": { "template": aBush1 } }); Engine.SetProgress(30); const riverTextures = [ { "left": fractionToTiles(0), "right": fractionToTiles(0.04), "terrain": tLush, "tileClass": clShore }, { "left": fractionToTiles(0.04), "right": fractionToTiles(0.06), "terrain": tSLush, "tileClass": clShore }, { "left": fractionToTiles(0.06), "right": fractionToTiles(0.09), "terrain": tSDry, "tileClass": clShore }, { "left": fractionToTiles(0.25), "right": fractionToTiles(0.5), "tileClass": clDesert } ]; const plantFrequency = 2; var plantID = 0; paintRiver({ "parallel": true, "start": new Vector2D(mapCenter.x, mapBounds.top).rotateAround(startAngle, mapCenter), "end": new Vector2D(mapCenter.x, mapBounds.bottom).rotateAround(startAngle, mapCenter), "width": fractionToTiles(0.1), "fadeDist": scaleByMapSize(3, 12), "deviation": 0.5, "heightRiverbed": heightSeaGround, "heightLand": heightShore, "meanderShort": 12, "meanderLong": 50, "waterFunc": (position, height, riverFraction) => { clWater.add(position); createTerrain(tShore).place(position); // Place river bushes if (height <= -0.2 || height >= 0.1) return; if (plantID % plantFrequency == 0) { plantID = 0; g_Map.placeEntityAnywhere(aPlants, 0, position, randomAngle()); } ++plantID; }, "landFunc": (position, shoreDist1, shoreDist2) => { for (let riv of riverTextures) if (riv.left < +shoreDist1 && +shoreDist1 < riv.right || riv.left < -shoreDist2 && -shoreDist2 < riv.right) { riv.tileClass.add(position); if (riv.terrain) createTerrain(riv.terrain).place(position); } } }); Engine.SetProgress(40); g_Map.log("Creating bumps"); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, Infinity), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), avoidClasses(clWater, 2, clPlayer, 6), scaleByMapSize(100, 200)); g_Map.log("Creating ponds"); var numLakes = Math.round(scaleByMapSize(1, 4) * numPlayers / 2); var waterAreas = createAreas( new ClumpPlacer(scaleByMapSize(2, 5) * 50, 0.8, 0.1, Infinity), [ new TerrainPainter(tShore), new SmoothElevationPainter(ELEVATION_SET, heightPonds, 4), new TileClassPainter(clPond) ], avoidClasses(clPlayer, 25, clWater, 20, clPond, 10), numLakes); g_Map.log("Creating reeds"); createObjectGroupsByAreasDeprecated( new SimpleGroup([new SimpleObject(aReeds, 1, 3, 0, 1)], true), 0, stayClasses(clPond, 1), numLakes, 100, waterAreas); g_Map.log("Creating lillies"); createObjectGroupsByAreasDeprecated( new SimpleGroup([new SimpleObject(aLillies, 1, 3, 0, 1)], true), 0, stayClasses(clPond, 1), numLakes, 100, waterAreas); g_Map.log("Creating forests"); var [forestTrees, stragglerTrees] = getTreeCounts(700, 3500, 0.5); var num = scaleByMapSize(10,30); createAreas( new ClumpPlacer(forestTrees / num, 0.15, 0.1, 0.5), [ new TerrainPainter([pForest, tForestFloor]), new TileClassPainter(clForest) ], avoidClasses(clPlayer, 19, clForest, 4, clWater, 1, clDesert, 5, clPond, 2, clBaseResource, 3), num, 50); Engine.SetProgress(50); g_Map.log("Creating grass patches"); for (let size of [scaleByMapSize(3, 48), scaleByMapSize(5, 84), scaleByMapSize(8, 128)]) createAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), [ new LayeredPainter( [[tGrass, tGrassSand50], [tGrassSand50, tGrassSand25], [tGrassSand25, tGrass]], [1, 1]), new TileClassPainter(clDirt) ], avoidClasses(clForest, 0, clGrass, 5, clPlayer, 10, clWater, 1, clDirt, 5, clShore, 1, clPond, 1), scaleByMapSize(15, 45)); Engine.SetProgress(55); g_Map.log("Creating dirt patches"); for (let size of [scaleByMapSize(3, 48), scaleByMapSize(5, 84), scaleByMapSize(8, 128)]) createAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), [ new LayeredPainter( [[tDirt, tDirtCracks], [tDirt, tFineSand], [tDirtCracks, tFineSand]], [1, 1]), new TileClassPainter(clDirt) ], avoidClasses(clForest, 0, clDirt, 5, clPlayer, 10, clWater, 1, clGrass, 5, clShore, 1, clPond, 1), scaleByMapSize(15, 45)); Engine.SetProgress(60); g_Map.log("Creating stone mines"); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clWater, 1, clPond, 1), scaleByMapSize(4,16), 100 ); g_Map.log("Creating small stone quarries"); group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clWater, 1, clPond, 1), scaleByMapSize(4,16), 100 ); g_Map.log("Creating metal mines"); group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4)], true, clMetal); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clWater, 1, clPond, 1), scaleByMapSize(4,16), 100 ); g_Map.log("Creating stone mines"); group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clWater, 1, clPond, 1), stayClasses(clDesert, 3)], scaleByMapSize(6,20), 100 ); g_Map.log("Creating small stone quarries"); group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clWater, 1, clPond, 1), stayClasses(clDesert, 3)], scaleByMapSize(6,20), 100 ); g_Map.log("Creating metal mines"); group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4)], true, clMetal); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clWater, 1, clPond, 1), stayClasses(clDesert, 3)], scaleByMapSize(6,20), 100 ); Engine.SetProgress(65); g_Map.log("Creating small decorative rocks"); group = new SimpleGroup( [new SimpleObject(aDecorativeRock, 1,3, 0,1)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clWater, 1, clForest, 0, clPlayer, 0, clPond, 1), scaleByMapSize(16, 262), 50 ); g_Map.log("Creating shrubs"); group = new SimpleGroup( [new SimpleObject(aBush2, 1,2, 0,1), new SimpleObject(aBush1, 1,3, 0,2), new SimpleObject(aBush4, 1,2, 0,1), new SimpleObject(aBush3, 1,3, 0,2)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clWater, 1, clPlayer, 0, clPond, 1), scaleByMapSize(20, 180), 50 ); Engine.SetProgress(70); g_Map.log("Creating gazelles"); group = new SimpleGroup([new SimpleObject(oGazelle, 5,7, 0,4)], true, clFood); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 20, clWater, 1, clFood, 10, clDesert, 5, clPond, 1), 3*scaleByMapSize(5,20), 50 ); g_Map.log("Creating goats"); group = new SimpleGroup([new SimpleObject(oGoat, 2,4, 0,3)], true, clFood); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 20, clWater, 1, clFood, 10, clDesert, 5, clPond, 1), 3*scaleByMapSize(5,20), 50 ); g_Map.log("Creating treasures"); group = new SimpleGroup([new SimpleObject(oFoodTreasure, 1,1, 0,2)], true, clTreasure); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 20, clWater, 1, clFood, 2, clDesert, 5, clTreasure, 6, clPond, 1), 3*scaleByMapSize(5,20), 50 ); group = new SimpleGroup([new SimpleObject(oWoodTreasure, 1,1, 0,2)], true, clTreasure); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 20, clWater, 1, clFood, 2, clDesert, 5, clTreasure, 6, clPond, 1), 3*scaleByMapSize(5,20), 50 ); g_Map.log("Creating camels"); group = new SimpleGroup([new SimpleObject(oCamel, 2,4, 0,2)], true, clFood); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 20, clWater, 1, clFood, 10, clDesert, 5, clTreasure, 2, clPond, 1), 3*scaleByMapSize(5,20), 50 ); Engine.SetProgress(90); createStragglerTrees( [oDatePalm, oSDatePalm], avoidClasses(clForest, 0, clWater, 1, clPlayer, 20, clMetal, 6, clDesert, 1, clTreasure, 2, clPond, 1), clForest, stragglerTrees / 2); createStragglerTrees( [oDatePalm, oSDatePalm], avoidClasses(clForest, 0, clWater, 1, clPlayer, 20, clMetal, 6, clTreasure, 2), clForest, stragglerTrees / 10); createStragglerTrees( [oDatePalm, oSDatePalm], borderClasses(clPond, 1, 4), clForest, stragglerTrees); g_Map.log("Creating obelisks"); group = new SimpleGroup( [new SimpleObject(eObelisk, 1,1, 0,1)], true ); createObjectGroupsDeprecated( group, 0, [avoidClasses(clWater, 4, clForest, 3, clPlayer, 20, clMetal, 6, clRock, 6, clPond, 4, clTreasure, 2), stayClasses(clDesert, 3)], scaleByMapSize(5, 30), 50 ); g_Map.log("Creating pyramids"); group = new SimpleGroup( [new SimpleObject(ePyramid, 1,1, 0,1)], true ); createObjectGroupsDeprecated( group, 0, [avoidClasses(clWater, 7, clForest, 6, clPlayer, 20, clMetal, 5, clRock, 5, clPond, 7, clTreasure, 2), stayClasses(clDesert, 3)], scaleByMapSize(2, 6), 50 ); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clFood, 2)); setSkySet("sunny"); setSunColor(0.711, 0.746, 0.574); setWaterColor(0.541,0.506,0.416); setWaterTint(0.694,0.592,0.522); setWaterMurkiness(1); setWaterWaviness(3.0); setWaterType("lake"); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/aegean.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/aegean.json (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/aegean.json (revision 26381) @@ -1,89 +1,89 @@ { "Description": { "Title": "Aegean-Anatolian", "Description": "Start in a region blessed with the Mediterranean climate, a warm and inviting land. The cypresses are in a perpetual struggle with the dominant fan palms while deer graze in their shadows, blissfully unaware." }, "Environment": { "SunColor": { "r": 1.023, "g": 0.923, "b": 0.714 }, "SunElevation": 0.90, "SunRotation": -0.909, "AmbientColor": { "r": 0.4, "g": 0.4, "b": 0.4 }, "Water": { "WaterBody": { "Color": { "r": 0.024, "g": 0.212, "b": 0.212 }, "Tint": { "r": 0.133, "g": 0.725, "b": 0.855 }, "Murkiness": 0.8, "Waviness": 3 } }, "Fog": { "FogThickness": 0.25, "FogFactor": 0.003 }, "Postproc": { "PostprocEffect": "hdr", "Brightness": 0, "Saturation": 1, "Contrast": 1, "Bloom": 0.16 } }, "Terrains": { "mainTerrain": [ "aegean_grass_02", "aegean_grass_dirt_01", "aegean_grass_01" ], "forestFloor1": "aegean_forestfloor_01", "forestFloor2": "aegean_grass_01", "cliff": [ "aegean_cliff_01", "aegean_cliff_02" ], "tier1Terrain": "aegean_grass_dirt_01", "tier2Terrain": "aegean_grass_01", "tier3Terrain": "aegean_grass_03", "tier4Terrain": "aegean_grass_02", "hill": [ "aegean_mountain_01", "aegean_dirt_rocks_01" ], "dirt": [ "aegean_dirt_01", "aegean_rocks_grass_01" ], "road": "aegean_paving_02", "roadWild": "aegean_rocks_grass_01", "shoreBlend": "aegean_sand_01", "shore": "aegean_sand_01", "water": "aegean_sand_02_wet" }, "Gaia": { - "chicken": "gaia/fauna_chicken", + "startingAnimal": "gaia/fauna_chicken", "mainHuntableAnimal": "gaia/fauna_deer", "fish": "gaia/fish/generic", "secondaryHuntableAnimal": "gaia/fauna_sheep", "stoneLarge": "gaia/rock/mediterranean_large", "stoneSmall": "gaia/rock/mediterranean_small", "metalLarge": "gaia/ore/aegean_anatolian_01", "metalSmall": "gaia/ore/temperate_small" }, "Decoratives": { "grass": "gaia/tree/bush_temperate", "grassShort": "actor|props/flora/bush_medit_sm.xml", "reeds": "actor|props/flora/reeds_pond_lush_b.xml", "lillies": "actor|props/flora/water_lillies.xml", "rockLarge": "actor|geology/stone_granite_large.xml", "rockMedium": "actor|geology/stone_granite_med.xml", "bushMedium": "gaia/tree/bush_temperate", "bushSmall": "actor|props/flora/bush_medit_sm.xml", "tree": "actor|flora/trees/cypress_mediterranean_wild.xml" }, "ResourceCounts": { "trees": { "min": 500, "max": 2000, "forestProbability": 0.6 } } } Index: ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/india.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/india.json (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/india.json (revision 26381) @@ -1,97 +1,97 @@ { "Description": { "Title": "India", "Description": "Explore the mysterious tropics. An extremely green, but also extremely humid environment awaits. The tall Toona trees look on disapprovingly at this invasion of their privacy and ferocious tigers are determined to defend their territory at all costs." }, "Environment": { "SunColor": { "r": 1.03162, "g": 0.99521, "b": 0.865752, "a": 0 }, "SunElevation": 1.85, "SunRotation": 0.0, "AmbientColor": { "r": 0.364706, "g": 0.376471, "b": 0.419608 }, "Water": { "WaterBody": { "Color": { "r": 0.584, "g": 0.824, "b": 0.929 }, "Tint": { "r": 0.569, "g": 0.965, "b": 0.945 }, "Murkiness": 0.45, "Waviness": 1.5 } }, "Fog": { "FogThickness": 0.0, "FogFactor": 0.0024, "FogColor": { "r": 0.87451, "g": 0.87451, "b": 0.87451 } }, "Postproc": { "PostprocEffect": "hdr", "Contrast": 1, "Saturation": 1, "Bloom": 0.16 } }, "Terrains": { "mainTerrain": [ "india_grass_01", "india_grass_02", "india_grass_dirt_01", "india_grass_dirt_02" ], "forestFloor1": "india_forestfloor_01", "forestFloor2": "india_forestfloor_02", "cliff": [ "india_cliff_02", "india_cliff_03" ], "tier1Terrain": "india_grass_02", "tier2Terrain": "india_mud_01", "tier3Terrain": "india_grass_dirt_01", "tier4Terrain": "india_grass_dirt_02", "hill": [ "india_dirt_01", "india_dirt_02" ], "dirt": [ "india_dirt_01", "india_dirt_02", "india_dirt_03" ], "road": "india_paving_02", "roadWild": "india_paving_02", "shoreBlend": "india_grass_dirt_01", "shore": "india_sand_01", "water": "india_mud_01" }, "Gaia": { "tree1": "gaia/tree/banyan", "tree2": "gaia/tree/strangler", "tree3": "gaia/tree/teak", "tree4": "gaia/tree/palm_palmyra", "tree5": "gaia/tree/palm_tropical", "fruitBush": "gaia/fruit/date", - "chicken": "gaia/fauna_peacock", + "startingAnimal": "gaia/fauna_peacock", "mainHuntableAnimal": "gaia/fauna_peacock", "fish": "gaia/fish/generic", "secondaryHuntableAnimal": "gaia/fauna_elephant_asian", "stoneLarge": "gaia/rock/temperate_large_02", "stoneSmall": "gaia/rock/tropical_small", "metalLarge": "gaia/ore/india_01", "metalSmall": "gaia/ore/alpine_small" }, "Decoratives": { "grass": "actor|props/flora/grass_tropic_field.xml", "grassShort": "actor|props/flora/plant_tropic_a.xml", "reeds": "actor|flora/trees/palm_nipa.xml", "lillies": "actor|props/flora/water_lillies.xml", "rockLarge": "actor|geology/stone_india_small.xml", "rockMedium": "actor|geology/stone_india_small.xml", "bushMedium": "gaia/tree/bush_tropic", "bushSmall": "actor|props/flora/plant_tropic_large.xml", "tree": "gaia/tree/palm_areca" }, "ResourceCounts": { "trees": { "min": 1000, "max": 6000, "forestProbability": 0.8 } } } Index: ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/steppe.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/steppe.json (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/rmbiome/generic/steppe.json (revision 26381) @@ -1,99 +1,99 @@ { "Description": { "Title": "Eurasian Steppe", "Description": "Wide grasslands stretching to the horizon, without any trees blocking the view. The Steppe is home to large herds of wild horses, which graze peacefully on the empty land, but flee quickly if you try to catch them." }, "Environment": { "SkySet": "sunrise", "SunColor": { "r": 0.85866, "g": 0.85095, "b": 0.73284 }, "SunElevation": 0.421456, "SunRotation": -1.526047, "AmbientColor": { "r": 0.504118, "g": 0.462157, "b": 0.604118 }, "Water": { "WaterBody": { "Color": { "r": 0.419608, "g": 0.364706, "b": 0.343726 }, "Tint": { "r": 0.501961, "g": 0.501961, "b": 0.307059 }, "Murkiness": 0.97, "Waviness": 4.01367 } }, "Fog": { "FogThickness": 0.26, "FogFactor": 0.004 }, "Postproc": { "PostprocEffect": "hdr", "Saturation": 0.95, "Contrast": 1.05, "Bloom": 0.211 } }, "Terrains": { "mainTerrain": [ "steppe_grass_03" ], "forestFloor1": "steppe_grass_dirt_01", "forestFloor2": "aegean_grass_dirt_03", "cliff": [ "aegean_cliff_seaside_01", "steppe_rocks_dirt_01" ], "tier1Terrain": [ "steppe_grass_02" ], "tier2Terrain": [ "steppe_grass_dirt_02" ], "tier3Terrain": [ "steppe_grass_dirt_03" ], "tier4Terrain": "steppe_grass_dirt_01", "hill": [ "steppe_rocks_dirt_01", "steppe_rocks_dirt_01" ], "dirt": [ "steppe_grass_dirt_01", "india_grass_dirt_02" ], "road": "sahara_paving_stones_01", "roadWild": "sahara_paving_stones_01", "shoreBlend": "steppe_grass_03", "shore": "india_grass_dirt_02", "water": "steppe_grass_mud_01" }, "Gaia": { "tree1": "gaia/tree/bush_steppe_01", "tree2": "gaia/tree/bush_steppe_02", "tree3": "gaia/tree/bush_steppe_01", "tree4": "gaia/tree/bush_steppe_03", "tree5": "gaia/tree/bush_steppe_02", "fruitBush": "gaia/fruit/berry_01", - "chicken": "gaia/fauna_chicken", + "startingAnimal": "gaia/fauna_chicken", "mainHuntableAnimal": "gaia/fauna_horse", "fish": "gaia/fish/tuna", "secondaryHuntableAnimal": "gaia/fauna_horse", "stoneLarge": "gaia/rock/desert_large", "stoneSmall": "gaia/rock/tropical_small", "metalLarge": "gaia/ore/sahara_01", "metalSmall": "gaia/ore/desert_small" }, "Decoratives": { "grass": "actor|props/flora/grass_temp_field_brown.xml", "grassShort": "actor|props/flora/grass_temp_field_brown.xml", "reeds": "actor|props/flora/reeds_pond_lush_a.xml", "lillies": "actor|props/flora/water_lillies.xml", "rockLarge": "actor|geology/stone_granite_med.xml", "rockMedium": "actor|props/flora/grass_temp_field_brown.xml", "bushMedium": "actor|geology/stone_granite_med.xml", "bushSmall": "actor|props/flora/grass_temp_field_brown.xml", "tree": "actor|flora/trees/temperate_bush_biome.xml" }, "ResourceCounts": { "trees": { "min": 800, "max": 1400, "forestProbability": 0.7 } } } Index: ps/trunk/binaries/data/mods/public/maps/random/rmbiome/gulf_of_bothnia/winter.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rmbiome/gulf_of_bothnia/winter.json (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/rmbiome/gulf_of_bothnia/winter.json (revision 26381) @@ -1,72 +1,72 @@ { "Description": { "Title": "Winter", "Description": "Winter has set in, carpeting the land with its first snow. The still unfrozen gulf offers great fishing opportunities." }, "Environment": { "SkySet": "stormy", "SunColor": { "r": 0.99, "g": 0.98, "b": 0.85 }, "SunElevation": 0.846, "SunRotation": -0.488, "AmbientColor": { "r": 0.264706, "g": 0.276471, "b": 0.319608 }, "Water": { "WaterBody": { "Type": "lake", "Color": { "r": 0.035, "g": 0.098, "b": 0.314 }, "Tint": { "r": 0.28, "g": 0.3, "b": 0.59 }, "Murkiness": 0.88, "Waviness": 5 } }, "Fog": { "FogThickness": 0.19, "FogFactor": 0.0035 }, "Postproc": { "PostprocEffect": "hdr", "Saturation": 0.74, "Contrast": 1.03, "Bloom": 0.176 } }, "Terrains": { "mainTerrain": ["alpine_snow_a", "alpine_snow_b"], "forestFloor1": "alpine_forrestfloor_snow", "cliff": ["alpine_cliff_snow"], "tier1Terrain": "alpine_grass_snow_50", "tier2Terrain": ["alpine_grass_snow_50", "alpine_dirt_snow"], "tier3Terrain": ["alpine_snow_a", "alpine_snow_b"], "road": "new_alpine_citytile", "roadWild": "new_alpine_citytile", "shore": "alpine_shore_rocks_icy", "water": "alpine_shore_rocks" }, "Gaia": { "tree1": "gaia/tree/pine_w", "fruitBush": "gaia/fruit/berry_01", - "chicken": "gaia/fauna_chicken", + "startingAnimal": "gaia/fauna_chicken", "mainHuntableAnimal": "gaia/fauna_deer", "secondaryHuntableAnimal": "gaia/fauna_rabbit", "fish": "gaia/fish/generic", "stoneLarge": "gaia/rock/alpine_large", "stoneSmall": "gaia/rock/alpine_small", "metalLarge": "gaia/ore/alpine_large" }, "Decoratives": { "grass": "actor|props/flora/grass_soft_dry_small_tall.xml", "grassShort": "actor|props/flora/grass_soft_dry_large.xml", "rockLarge": "actor|geology/stone_granite_med.xml", "rockMedium": "actor|geology/stone_granite_med.xml", "bushMedium": "actor|props/flora/bush_medit_me_dry.xml", "bushSmall": "actor|props/flora/bush_medit_sm_dry.xml" }, "ResourceCounts": { "fish": { "min": 20, "max": 80 }, "bush": { "min": 13, "max": 200 } }, "Heights": { "seaGround": -3, "shore": 1, "land": 3 } } Index: ps/trunk/binaries/data/mods/public/maps/random/sahel.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/sahel.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/sahel.js (revision 26381) @@ -1,241 +1,241 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); const tPrimary = "savanna_grass_a"; const tGrass2 = "savanna_grass_b"; const tGrass3 = "savanna_shrubs_a"; const tDirt1 = "savanna_dirt_rocks_a"; const tDirt2 = "savanna_dirt_rocks_b"; const tDirt3 = "savanna_dirt_rocks_c"; const tDirt4 = "savanna_dirt_b"; const tCityTiles = "savanna_tile_a"; const tShore = "savanna_riparian_bank"; const tWater = "savanna_riparian_wet"; const oBaobab = "gaia/tree/baobab"; const oBerryBush = "gaia/fruit/berry_05"; const oGazelle = "gaia/fauna_gazelle"; const oGiraffe = "gaia/fauna_giraffe"; const oGiraffeInfant = "gaia/fauna_giraffe_infant"; const oElephant = "gaia/fauna_elephant_african_bush"; const oElephantInfant = "gaia/fauna_elephant_african_infant"; const oLion = "gaia/fauna_lion"; const oLioness = "gaia/fauna_lioness"; const oZebra = "gaia/fauna_zebra"; const oStoneSmall = "gaia/rock/savanna_small"; const oMetalLarge = "gaia/ore/savanna_large"; const aBush = "actor|props/flora/bush_medit_sm_dry.xml"; const aRock = "actor|geology/stone_savanna_med.xml"; const heightSeaGround = -5; const heightLand = 1; var g_Map = new RandomMap(heightLand, tPrimary); var numPlayers = getNumPlayers(); var mapSize = g_Map.getSize(); var clPlayer = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clWater = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tCityTiles, "innerTerrain": tCityTiles }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "type": "stone_formation", "template": oStoneSmall, "terrain": tDirt4 } ] }, "Trees": { "template": oBaobab, "count": scaleByMapSize(2, 7), "minDistGroup": 2, "maxDistGroup": 7 } // No decoratives }); Engine.SetProgress(20); g_Map.log("Creating big patches"); var patches = [tGrass2, tGrass3]; for (var i = 0; i < patches.length; i++) createAreas( new ChainPlacer(Math.floor(scaleByMapSize(3, 6)), Math.floor(scaleByMapSize(10, 20)), Math.floor(scaleByMapSize(15, 60)), Infinity), new TerrainPainter(patches[i]), avoidClasses(clPlayer, 10), scaleByMapSize(5, 20)); g_Map.log("Creating small patches"); for (let size of [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)]) for (let patch of [tDirt1, tDirt2, tDirt3]) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, Infinity), new TerrainPainter(patch), avoidClasses(clPlayer, 12), scaleByMapSize(4, 15)); g_Map.log("Creating water holes"); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), Math.floor(scaleByMapSize(20, 60)), Infinity), [ new LayeredPainter([tShore, tWater], [1]), new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 7), new TileClassPainter(clWater) ], avoidClasses(clPlayer, 24), scaleByMapSize(1, 3)); Engine.SetProgress(55); g_Map.log("Creating stone mines"); for (var i = 0; i < scaleByMapSize(12,30); ++i) { let position = new Vector2D(randIntExclusive(0, mapSize), randIntExclusive(0, mapSize)); if (avoidClasses(clPlayer, 30, clRock, 25, clWater, 10).allows(position)) { createStoneMineFormation(position, oStoneSmall, tDirt4); clRock.add(position); } } g_Map.log("Creating metal mines"); var group = new SimpleGroup([new SimpleObject(oMetalLarge, 1, 1, 0, 4)], true, clMetal); createObjectGroupsDeprecated(group, 0, avoidClasses(clPlayer, 20, clMetal, 10, clRock, 8, clWater, 4), scaleByMapSize(2,8), 100 ); Engine.SetProgress(65); g_Map.log("Creating small decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRock, 1,3, 0,3)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clPlayer, 7, clWater, 1), scaleByMapSize(200, 1200), 1 ); Engine.SetProgress(70); g_Map.log("Creating gazelle"); group = new SimpleGroup( [new SimpleObject(oGazelle, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 1, clPlayer, 20, clFood, 11), scaleByMapSize(4,12), 50 ); g_Map.log("Creating zebra"); group = new SimpleGroup( [new SimpleObject(oZebra, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 1, clPlayer, 20, clFood, 11), scaleByMapSize(4,12), 50 ); g_Map.log("Creating giraffe"); group = new SimpleGroup( [new SimpleObject(oGiraffe, 2,4, 0,4), new SimpleObject(oGiraffeInfant, 0,2, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 1, clPlayer, 20, clFood, 11), scaleByMapSize(4,12), 50 ); g_Map.log("Creating elephants"); group = new SimpleGroup( [new SimpleObject(oElephant, 2,4, 0,4), new SimpleObject(oElephantInfant, 0,2, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 1, clPlayer, 20, clFood, 11), scaleByMapSize(4,12), 50 ); g_Map.log("Creating lions"); group = new SimpleGroup( [new SimpleObject(oLion, 0,1, 0,4), new SimpleObject(oLioness, 2,3, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 1, clPlayer, 20, clFood, 11), scaleByMapSize(4,12), 50 ); g_Map.log("Creating berry bush"); group = new SimpleGroup( [new SimpleObject(oBerryBush, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clPlayer, 20, clFood, 12, clRock, 7, clMetal, 6), randIntInclusive(1, 4) * numPlayers + 2, 50 ); Engine.SetProgress(85); createStragglerTrees( [oBaobab], avoidClasses(clForest, 1, clPlayer, 20, clMetal, 6, clRock, 7, clWater, 1), clForest, scaleByMapSize(70, 500)); g_Map.log("Creating large grass tufts"); group = new SimpleGroup( [new SimpleObject(aBush, 2,4, 0,1.8, -Math.PI / 8, Math.PI / 8)] ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clPlayer, 2, clForest, 0), scaleByMapSize(100, 1200) ); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clFood, 2)); setSunColor(0.87451, 0.847059, 0.647059); setWaterColor(0.741176, 0.592157, 0.27451); setWaterTint(0.741176, 0.592157, 0.27451); setWaterWaviness(2.0); setWaterType("clap"); setWaterMurkiness(0.835938); setAmbientColor(0.447059, 0.509804, 0.54902); setFogFactor(0.25); setFogThickness(0.15); setFogColor(0.847059, 0.737255, 0.482353); setPPEffect("hdr"); setPPContrast(0.57031); setPPBloom(0.34); g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/syria.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/syria.js (revision 26380) +++ ps/trunk/binaries/data/mods/public/maps/random/syria.js (revision 26381) @@ -1,285 +1,285 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen-common"); const tMainDirt = ["desert_dirt_rocks_1", "desert_dirt_cracks"]; const tForestFloor1 = "forestfloor_dirty"; const tForestFloor2 = "desert_forestfloor_palms"; const tGrassSands = "desert_grass_a_sand"; const tGrass = "desert_grass_a"; const tSecondaryDirt = "medit_dirt_dry"; const tCliff = ["desert_cliff_persia_1", "desert_cliff_persia_2"]; const tHill = ["desert_dirt_rocks_1", "desert_dirt_rocks_2", "desert_dirt_rocks_3"]; const tDirt = ["desert_dirt_rough", "desert_dirt_rough_2"]; const tRoad = "desert_shore_stones"; const tRoadWild = "desert_grass_a_stones"; const oTamarix = "gaia/tree/tamarix"; const oPalm = "gaia/tree/date_palm"; const oPine = "gaia/tree/aleppo_pine"; const oBush = "gaia/fruit/grapes"; const oCamel = "gaia/fauna_camel"; const oGazelle = "gaia/fauna_gazelle"; const oLion = "gaia/fauna_lion"; const oStoneLarge = "gaia/rock/desert_large"; const oStoneSmall = "gaia/rock/desert_small"; const oMetalLarge = "gaia/ore/desert_large"; const aRock = "actor|geology/stone_desert_med.xml"; const aBushA = "actor|props/flora/bush_desert_dry_a.xml"; const aBushB = "actor|props/flora/bush_desert_dry_a.xml"; const aBushes = [aBushA, aBushB]; const pForestP = [tForestFloor2 + TERRAIN_SEPARATOR + oPalm, tForestFloor2]; const pForestT = [tForestFloor1 + TERRAIN_SEPARATOR + oTamarix,tForestFloor2]; const heightLand = 1; const heightHill = 22; const heightOffsetBump = 2; var g_Map = new RandomMap(heightLand, tMainDirt); const mapCenter = g_Map.getCenter(); const numPlayers = getNumPlayers(); var clPlayer = g_Map.createTileClass(); var clHill = g_Map.createTileClass(); var clForest = g_Map.createTileClass(); var clRock = g_Map.createTileClass(); var clMetal = g_Map.createTileClass(); var clFood = g_Map.createTileClass(); var clBaseResource = g_Map.createTileClass(); var clGrass = g_Map.createTileClass(); var [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); g_Map.log("Creating big grass patches around the playerbases"); for (let i = 0; i < numPlayers; ++i) { if (!isNomad()) createArea( new ClumpPlacer(diskArea(defaultPlayerBaseRadius()), 0.9, 0.5, Infinity, playerPosition[i]), new TileClassPainter(clPlayer)); createArea( new ChainPlacer( 2, Math.floor(scaleByMapSize(5, 12)), Math.floor(scaleByMapSize(25, 60)) / (isNomad() ? 2 : 1), Infinity, playerPosition[i], 0, [Math.floor(scaleByMapSize(16, 30))]), [ new LayeredPainter([tGrassSands, tGrass], [3]), new TileClassPainter(clGrass) ]); } Engine.SetProgress(10); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], // PlayerTileClass marked above "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad, "radius": 10, "width": 3 }, - "Chicken": { + "StartingAnimal": { }, "Berries": { "template": oBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ], "groupElements": [new RandomObject(aBushes, 2, 4, 2, 3)] }, "Trees": { "template": pickRandom([oPalm, oTamarix]), "count": 3 } // No decoratives }); Engine.SetProgress(20); g_Map.log("Creating bumps"); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, Infinity), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), avoidClasses(clPlayer, 13), scaleByMapSize(300, 800)); g_Map.log("Creating hills"); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(16, 40)), 0.5), [ new LayeredPainter([tCliff, tHill], [2]), new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), new TileClassPainter(clHill) ], avoidClasses(clPlayer, 3, clGrass, 1, clHill, 10), scaleByMapSize(1, 3) * numPlayers * 3); Engine.SetProgress(25); g_Map.log("Creating forests"); var [forestTrees, stragglerTrees] = getTreeCounts(400, 2000, 0.7); var types = [ [[tMainDirt, tForestFloor2, pForestP], [tForestFloor2, pForestP]], [[tMainDirt, tForestFloor1, pForestT], [tForestFloor1, pForestT]] ]; var size = forestTrees / (scaleByMapSize(3,6) * numPlayers); var num = Math.floor(size / types.length); for (let type of types) createAreas( new ChainPlacer( 1, Math.floor(scaleByMapSize(3, 5)), forestTrees / (num * Math.floor(scaleByMapSize(2, 4))), 0.5), [ new LayeredPainter(type, [2]), new TileClassPainter(clForest) ], avoidClasses(clPlayer, 1, clGrass, 1, clForest, 10, clHill, 1), num); Engine.SetProgress(40); g_Map.log("Creating dirt patches"); for (let size of [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)]) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5), new LayeredPainter([tSecondaryDirt, tDirt], [1]), avoidClasses(clHill, 0, clForest, 0, clPlayer, 8, clGrass, 1), scaleByMapSize(50, 90)); Engine.SetProgress(60); g_Map.log("Creating big patches"); for (let size of [scaleByMapSize(6, 30), scaleByMapSize(10, 50), scaleByMapSize(16, 70)]) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5), new LayeredPainter([tSecondaryDirt, tDirt], [1]), avoidClasses(clHill, 0, clForest, 0, clPlayer, 8, clGrass, 1), scaleByMapSize(30, 90)); Engine.SetProgress(70); g_Map.log("Creating stone mines"); createObjectGroupsDeprecated( new SimpleGroup( [ new SimpleObject(oStoneSmall, 0, 2, 0, 4, 0, 2 * Math.PI, 1), new SimpleObject(oStoneLarge, 1, 1, 0, 4, 0, 2 * Math.PI, 4), new RandomObject(aBushes, 2, 4, 0, 2) ], true, clRock), 0, [avoidClasses(clForest, 1, clPlayer, 10, clRock, 10, clHill, 1, clGrass, 1)], scaleByMapSize(2, 8), 100); g_Map.log("Creating small stone quarries"); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3), new RandomObject(aBushes, 2,4, 0,2)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 1, clPlayer, 10, clRock, 10, clHill, 1, clGrass, 1)], scaleByMapSize(2,8), 100 ); g_Map.log("Creating metal mines"); group = new SimpleGroup([new SimpleObject(oMetalLarge, 1,1, 0,4), new RandomObject(aBushes, 2,4, 0,2)], true, clMetal); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 1, clPlayer, 10, clMetal, 10, clRock, 5, clHill, 1, clGrass, 1)], scaleByMapSize(2,8), 100 ); g_Map.log("Creating small decorative rocks"); group = new SimpleGroup( [new SimpleObject(aRock, 1,3, 0,1)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clForest, 0, clPlayer, 0, clHill, 0), scaleByMapSize(16, 262), 50 ); g_Map.log("Creating bushes"); group = new SimpleGroup( [new SimpleObject(aBushB, 1,2, 0,1), new SimpleObject(aBushA, 1,3, 0,2)], true ); createObjectGroupsDeprecated( group, 0, avoidClasses(clForest, 0, clPlayer, 0, clHill, 0), scaleByMapSize(50, 500), 50 ); Engine.SetProgress(80); g_Map.log("Creating gazelle"); group = new SimpleGroup( [new SimpleObject(oGazelle, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 1, clHill, 1, clFood, 20, clGrass, 2), 3 * numPlayers, 50 ); g_Map.log("Creating lions"); group = new SimpleGroup( [new SimpleObject(oLion, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 1, clHill, 1, clFood, 20, clGrass, 2), 3 * numPlayers, 50 ); g_Map.log("Creating camels"); group = new SimpleGroup( [new SimpleObject(oCamel, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 0, clPlayer, 1, clHill, 1, clFood, 20, clGrass, 2), 3 * numPlayers, 50 ); Engine.SetProgress(85); createStragglerTrees( [oPalm, oTamarix, oPine], avoidClasses(clForest, 1, clHill, 1, clPlayer, 1, clMetal, 6, clRock, 6), clForest, stragglerTrees); createStragglerTrees( [oPalm, oTamarix, oPine], [avoidClasses(clForest, 1, clHill, 1, clPlayer, 1, clMetal, 6, clRock, 6), stayClasses(clGrass, 3)], clForest, stragglerTrees * (isNomad() ? 3 : 1)); placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); setSkySet("sunny"); setSunElevation(Math.PI / 8); setSunRotation(randomAngle()); setSunColor(0.746, 0.718, 0.539); setWaterColor(0.292, 0.347, 0.691); setWaterTint(0.550, 0.543, 0.437); setWaterMurkiness(0.83); setFogColor(0.8, 0.76, 0.61); setFogThickness(0.2); setFogFactor(0.4); setPPEffect("hdr"); setPPContrast(0.65); setPPSaturation(0.42); setPPBloom(0.6); g_Map.ExportMap();