Index: ps/trunk/binaries/data/mods/public/maps/random/aegean_sea.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/aegean_sea.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/aegean_sea.js (revision 20904) @@ -1,305 +1,307 @@ Engine.LoadLibrary("rmgen"); 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/flora_bush_berry"; const oDeer = "gaia/fauna_deer"; const oFish = "gaia/fauna_fish"; const oSheep = "gaia/fauna_sheep"; const oGoat = "gaia/fauna_goat"; const oStoneLarge = "gaia/geology_stonemine_medit_quarry"; const oStoneSmall = "gaia/geology_stone_mediterranean"; const oMetalLarge = "gaia/geology_metal_mediterranean_slabs"; const oDatePalm = "gaia/flora_tree_cretan_date_palm_short"; const oSDatePalm = "gaia/flora_tree_cretan_date_palm_tall"; const oCarob = "gaia/flora_tree_carob"; const oFanPalm = "gaia/flora_tree_medit_fan_palm"; const oPoplar = "gaia/flora_tree_poplar_lombardy"; const oCypress = "gaia/flora_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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightSeaGround = -3; +const heightSeaBump = -2.5; +const heightCorralsLower = -2; +const heightCorralsUpper = -1.5; +const heightShore = 1; +const heightLand = 2; +const heightIsland = 6; + +InitMap(heightShore, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); const mapCenter = getMapCenter(); const mapBounds = getMapBounds(); var clPlayer = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clGrass = createTileClass(); var clHill = createTileClass(); var clIsland = createTileClass(); -var waterHeight = -3; -var corralsHeightLower = -2; -var corralsHeightUpper = -1.5; -var shoreHeight = 1; -var landHeight = 2; - placePlayerBases({ "PlayerPlacement": playerPlacementRiver(0, fractionToTiles(0.6)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tCityPlaza, "innerTerrain": tCity }, "Chicken": { }, "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), "end": new Vector2D(mapCenter.x, mapBounds.bottom), "width": fractionToTiles(0.35), "fadeDist": scaleByMapSize(6, 25), "deviation": 0, - "waterHeight": waterHeight, - "landHeight": landHeight, + "heightRiverbed": heightSeaGround, + "heightLand": heightLand, "meanderShort": 20, "meanderLong": 0 }); paintTileClassBasedOnHeight(-Infinity, 0.7, Elevation_ExcludeMin_ExcludeMax, clWater); -paintTerrainBasedOnHeight(-Infinity, shoreHeight, Elevation_ExcludeMin_ExcludeMax, tShoreLower); -paintTerrainBasedOnHeight(shoreHeight, landHeight, Elevation_ExcludeMin_ExcludeMax, tShoreUpper); +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)); 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); 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); log("Creating undersea bumps..."); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(16, 40)), 0.5), - new SmoothElevationPainter(ELEVATION_SET, -2.5, 3), + new SmoothElevationPainter(ELEVATION_SET, heightSeaBump, 3), stayClasses(clWater, 6), scaleByMapSize(10, 50)); 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, 6, 4), + new SmoothElevationPainter(ELEVATION_SET, heightIsland, 4), paintClass(clIsland) ], [avoidClasses(clPlayer, 8, clForest, 1, clIsland, 15), stayClasses (clWater, 6)], scaleByMapSize(1, 4) * numPlayers ); -paintTerrainBasedOnHeight(-Infinity, waterHeight, Elevation_IncludeMin_IncludeMax, tSeaDepths); -paintTerrainBasedOnHeight(waterHeight, corralsHeightLower, Elevation_ExcludeMin_IncludeMax, tCoralsLower); -paintTerrainBasedOnHeight(corralsHeightLower, corralsHeightUpper, Elevation_ExcludeMin_IncludeMax, tCoralsUpper); +paintTerrainBasedOnHeight(-Infinity, heightSeaGround, Elevation_IncludeMin_IncludeMax, tSeaDepths); +paintTerrainBasedOnHeight(heightSeaGround, heightCorralsLower, Elevation_ExcludeMin_IncludeMax, tCoralsLower); +paintTerrainBasedOnHeight(heightCorralsLower, heightCorralsUpper, Elevation_ExcludeMin_IncludeMax, tCoralsUpper); log("Creating island stone mines..."); createMines( [ [new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], stayClasses(clIsland, 4), clRock); log("Creating island metal mines..."); createMines( [ [new SimpleObject(oMetalLarge, 1,1, 0,4)] ], stayClasses(clIsland, 4), clMetal ); log("Creating stone mines..."); createMines( [ [new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clWater, 1, clHill, 1), clRock); 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) ] ], [ scaleByMapSize(16, 262), 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); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/caledonian_meadows.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/caledonian_meadows.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/caledonian_meadows.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "Caledonian Meadows", "Script" : "caledonian_meadows.js", "Preview" : "caledonian_meadows.png", "Description" : "Fertile lands surrounded by harsh terrain.\nRemains of recent snowfalls still haunt the forests, and torrential rivers from the snowmelt have barely died away.\nAiming at a realistic terrain, this map might not always be balanced.", "CircularMap" : true, "BaseTerrain" : "whiteness", - "Keywords": [], - "BaseHeight" : 0 + "Keywords": [] } } Index: ps/trunk/binaries/data/mods/public/maps/random/cantabrian_highlands.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/cantabrian_highlands.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/cantabrian_highlands.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Cantabrian Highlands", "Script" : "cantabrian_highlands.js", "Description" : "Each player starts on a hill surrounded by steep cliffs. Represents Cantabria, a mountainous region in the North of the Iberian peninsula.", "BaseTerrain" : ["temp_grass_long"], - "BaseHeight" : 3, "Preview" : "cantabrian_highlands.png", "CircularMap" : true } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/canyon.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/canyon.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/canyon.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "Canyon", "Script" : "canyon.js", "Description" : "Players start around the map in deep canyons.", "BaseTerrain" : ["medit_sea_depths"], - "BaseHeight" : 30, "Preview" : "canyon.png", "SupportedBiomes": true, "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/continent.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/continent.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/continent.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "Continent", "Script" : "continent.js", "Description" : "All players starts on a continent surrounded by water.", "BaseTerrain" : ["medit_sea_depths"], - "BaseHeight" : -5, "Preview" : "continent.png", "SupportedBiomes": true, "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/corinthian_isthmus.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/corinthian_isthmus.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/corinthian_isthmus.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Corinthian Isthmus", "Script" : "corinthian_isthmus.js", "Description" : "Two Mediterranean land masses connected by a narrow spit of land, called an 'Isthmus'.", "BaseTerrain" : ["medit_grass_shrubs", "medit_rocks_grass_shrubs", "medit_rocks_shrubs", "medit_rocks_grass", "medit_shrubs"], - "BaseHeight" : 3, "CircularMap" : true, "Preview" : "corinthian_isthmus.png" } } Index: ps/trunk/binaries/data/mods/public/maps/random/cycladic_archipelago.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/cycladic_archipelago.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/cycladic_archipelago.js (revision 20904) @@ -1,357 +1,362 @@ Engine.LoadLibrary("rmgen"); 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 oBeech = "gaia/flora_tree_euro_beech"; const oBerryBush = "gaia/flora_bush_berry"; const oCarob = "gaia/flora_tree_carob"; const oCypress1 = "gaia/flora_tree_cypress"; const oCypress2 = "gaia/flora_tree_cypress"; const oLombardyPoplar = "gaia/flora_tree_poplar_lombardy"; const oPalm = "gaia/flora_tree_medit_fan_palm"; const oPine = "gaia/flora_tree_aleppo_pine"; const oDateT = "gaia/flora_tree_cretan_date_palm_tall"; const oDateS = "gaia/flora_tree_cretan_date_palm_short"; const oDeer = "gaia/fauna_deer"; const oFish = "gaia/fauna_fish"; const oWhale = "gaia/fauna_whale_humpback"; const oStoneLarge = "gaia/geology_stonemine_medit_quarry"; const oStoneSmall = "gaia/geology_stone_mediterranean"; const oMetalLarge = "gaia/geology_metal_mediterranean_slabs"; const oShipwreck = "other/special_treasure_shipwreck"; const oShipDebris = "other/special_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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightSeaGround = -5; +const heightLand = 3; +const heightHill = 12; +const heightOffsetBump = 2; + +InitMap(heightSeaGround, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); var clCoral = createTileClass(); var clPlayer = createTileClass(); var clIsland = createTileClass(); var clCity = createTileClass(); var clDirt = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = 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) { log("Creating deep ocean rocks..."); createArea( new ClumpPlacer(diskArea(radius + coralRadius), 0.7, 0.1, 10, position.x, position.y), [ new LayeredPainter([tOceanRockDeep, tOceanCoral], [5]), paintClass(clCoral) ], avoidClasses(clCoral, 0, clPlayer, 0)); log("Creating island..."); areas.push( createArea( new ClumpPlacer(diskArea(radius), 0.7, 0.1, 10, position.x, position.y), [ new LayeredPainter([tOceanCoral, tBeachWet, tBeachDry, tBeach, tBeachBlend, tGrass], [1, 3, 1, 1, 2]), - new SmoothElevationPainter(ELEVATION_SET, 3, 5), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 5), paintClass(tileClass) ], avoidClasses(clPlayer, 0))); } 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)); } 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": [ paintClass(clCity) ] }, "Chicken": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oPalm, "count": 2 } // No decoratives }); Engine.SetProgress(20); log("Creating bumps..."); createAreasInAreas( new ClumpPlacer(scaleByMapSize(20, 60), 0.3, 0.06, 1), - new SmoothElevationPainter(ELEVATION_MODIFY, 2, 3), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 3), avoidClasses(clCity, 0), scaleByMapSize(25, 75),15, areas); Engine.SetProgress(34); log("Creating hills..."); createAreasInAreas( new ClumpPlacer(scaleByMapSize(20, 150), 0.2, 0.1, 1), [ new LayeredPainter([tCliff, tCliffShrubs], [2]), - new SmoothElevationPainter(ELEVATION_SET, 12, 2), + new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), paintClass(clHill) ], avoidClasses(clCity, 15, clHill, 15), scaleByMapSize(5, 30), 15, areas); Engine.SetProgress(38); paintTileClassBasedOnHeight(-Infinity, 0, Elevation_ExcludeMin_ExcludeMax, clWater); 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, 1), [ new LayeredPainter(type, [2]), paintClass(clForest) ], avoidClasses(clCity, 1, clWater, 3, clForest, 3, clHill, 1, clBaseResource, 4), scaleByMapSize(10, 64), 20, areas); Engine.SetProgress(42); log("Creating stone mines..."); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,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); 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, 2)], scaleByMapSize(4,16), 200, areas ); Engine.SetProgress(50); 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); 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]), paintClass(clDirt) ], avoidClasses(clWater, 3, clHill, 0, clDirt, 6, clCity, 0, clBaseResource, 4), scaleByMapSize(4, 16), 20, areas); Engine.SetProgress(58); 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], []), paintClass(clDirt) ], avoidClasses(clWater, 3, clHill, 0, clDirt, 6, clCity, 0, clBaseResource, 4), scaleByMapSize(4, 16), 20, areas); Engine.SetProgress(62); 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); 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); 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); 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); 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, 2, clFood, 8), 3 * numPlayers, 50 ); Engine.SetProgress(82); 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, 2, clFood, 8), 1.5 * numPlayers, 100 ); Engine.SetProgress(86); 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); 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); 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); 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)); setSkySet("sunny"); setWaterColor(0.2,0.294,0.49); setWaterTint(0.208, 0.659, 0.925); setWaterMurkiness(0.72); setWaterWaviness(3.0); setWaterType("ocean"); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/danubius.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/danubius.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/danubius.json (revision 20904) @@ -1,16 +1,15 @@ { "settings" : { "Name" : "Danubius", "Script" : "danubius.js", "Description" : "Players start along the banks of the river Danube in the period following the expansion into Pannonia by the Celtic Boii tribe. Seeking to consolidate their hold on this land, celtic reinforcements have been sent to root out the remaining foreign cultures. Players not only have to vie for power amongst themselves, but also beat back these ruthless invaders. Ultimately, the Boii were defeated by the rising power of the Dacians, hence leading to the reemergence of the Geto-Dacian Confederation under King Burebista.", "BaseTerrain" : ["temp_grass_aut", "temp_grass_plants_aut", "temp_grass_c_aut", "temp_grass_d_aut"], - "BaseHeight" : 4, "Keywords": ["trigger"], "CircularMap" : true, "Preview" : "danubius.png", "TriggerScripts" : [ "scripts/TriggerHelper.js", "random/danubius_triggers.js" ] } } Index: ps/trunk/binaries/data/mods/public/maps/random/empire.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/empire.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/empire.js (revision 20904) @@ -1,233 +1,233 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen2"); Engine.LoadLibrary("rmbiome"); setSelectedBiome(); -InitMap(g_MapSettings.BaseHeight, g_Terrains.mainTerrain); +InitMap(2, g_Terrains.mainTerrain); initTileClasses(); createArea( new MapBoundsPlacer(), paintClass(g_TileClasses.land)); Engine.SetProgress(10); const teamsArray = getTeamsArray(); const startAngle = randomAngle(); addBases("stronghold", fractionToTiles(0.37), fractionToTiles(0.04), startAngle); Engine.SetProgress(20); // Change the starting angle and add the players again var rotation = Math.PI; if (teamsArray.length == 2) rotation = Math.PI / 2; if (teamsArray.length == 4) rotation = 5/4 * Math.PI; addBases("stronghold", fractionToTiles(0.15), fractionToTiles(0.04), startAngle + rotation); Engine.SetProgress(40); addElements(shuffleArray([ { "func": addHills, "avoid": [ g_TileClasses.bluff, 5, g_TileClasses.hill, 15, g_TileClasses.mountain, 2, g_TileClasses.plateau, 5, g_TileClasses.player, 20, g_TileClasses.valley, 2, g_TileClasses.water, 2 ], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": ["tons"] }, { "func": addMountains, "avoid": [ g_TileClasses.bluff, 20, g_TileClasses.mountain, 25, g_TileClasses.plateau, 20, g_TileClasses.player, 20, g_TileClasses.valley, 10, g_TileClasses.water, 15 ], "sizes": ["huge"], "mixes": ["same", "similar"], "amounts": ["tons"] }, { "func": addPlateaus, "avoid": [ g_TileClasses.bluff, 20, g_TileClasses.mountain, 25, g_TileClasses.plateau, 20, g_TileClasses.player, 40, g_TileClasses.valley, 10, g_TileClasses.water, 15 ], "sizes": ["huge"], "mixes": ["same", "similar"], "amounts": ["tons"] } ])); Engine.SetProgress(50); addElements([ { "func": addLayeredPatches, "avoid": [ g_TileClasses.bluff, 2, g_TileClasses.dirt, 5, g_TileClasses.forest, 2, g_TileClasses.mountain, 2, g_TileClasses.plateau, 2, g_TileClasses.player, 12, g_TileClasses.water, 3 ], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["normal"] }, { "func": addDecoration, "avoid": [ g_TileClasses.bluff, 2, g_TileClasses.forest, 2, g_TileClasses.mountain, 2, g_TileClasses.plateau, 2, g_TileClasses.player, 12, g_TileClasses.water, 3 ], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["normal"] } ]); Engine.SetProgress(60); addElements(shuffleArray([ { "func": addMetal, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.bluff, 5, g_TileClasses.forest, 3, g_TileClasses.mountain, 2, g_TileClasses.player, 30, g_TileClasses.rock, 10, g_TileClasses.metal, 20, g_TileClasses.plateau, 2, g_TileClasses.water, 3 ], "sizes": ["normal"], "mixes": ["same"], "amounts": g_AllAmounts }, { "func": addStone, "avoid": [g_TileClasses.berries, 5, g_TileClasses.bluff, 5, g_TileClasses.forest, 3, g_TileClasses.mountain, 2, g_TileClasses.player, 30, g_TileClasses.rock, 20, g_TileClasses.metal, 10, g_TileClasses.plateau, 2, g_TileClasses.water, 3 ], "sizes": ["normal"], "mixes": ["same"], "amounts": g_AllAmounts }, { "func": addForests, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.bluff, 5, g_TileClasses.forest, 18, g_TileClasses.metal, 3, g_TileClasses.mountain, 5, g_TileClasses.plateau, 2, g_TileClasses.player, 20, g_TileClasses.rock, 3, g_TileClasses.water, 2 ], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": ["few", "normal", "many", "tons"] } ])); Engine.SetProgress(80); addElements(shuffleArray([ { "func": addBerries, "avoid": [ g_TileClasses.berries, 30, g_TileClasses.bluff, 5, g_TileClasses.forest, 5, g_TileClasses.metal, 10, g_TileClasses.mountain, 2, g_TileClasses.plateau, 2, g_TileClasses.player, 20, g_TileClasses.rock, 10, g_TileClasses.water, 3 ], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": g_AllAmounts }, { "func": addAnimals, "avoid": [ g_TileClasses.animals, 20, g_TileClasses.bluff, 5, g_TileClasses.forest, 2, g_TileClasses.metal, 2, g_TileClasses.mountain, 1, g_TileClasses.plateau, 2, g_TileClasses.player, 20, g_TileClasses.rock, 2, g_TileClasses.water, 3 ], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": g_AllAmounts }, { "func": addStragglerTrees, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.bluff, 5, g_TileClasses.forest, 7, g_TileClasses.metal, 2, g_TileClasses.mountain, 1, g_TileClasses.plateau, 2, g_TileClasses.player, 12, g_TileClasses.rock, 2, g_TileClasses.water, 5 ], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": g_AllAmounts } ])); Engine.SetProgress(90); placePlayersNomad( g_TileClasses.player, avoidClasses( g_TileClasses.plateau, 4, g_TileClasses.forest, 1, g_TileClasses.metal, 4, g_TileClasses.rock, 4, g_TileClasses.mountain, 4, g_TileClasses.animals, 2)); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/corsica.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/corsica.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/corsica.js (revision 20904) @@ -1,539 +1,541 @@ Engine.LoadLibrary("rmgen"); 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/flora_tree_aleppo_pine"; var ePalmTall = "gaia/flora_tree_cretan_date_palm_tall"; var eFanPalm = "gaia/flora_tree_medit_fan_palm"; var eApple = "gaia/flora_tree_apple"; var eBush = "gaia/flora_bush_berry"; var eFish = "gaia/fauna_fish"; var ePig = "gaia/fauna_pig"; var eStoneMine = "gaia/geology_stonemine_medit_quarry"; var eMetalMine = "gaia/geology_metal_mediterranean_slabs"; 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"; -InitMap(g_MapSettings.BaseHeight, tVeryDeepWater); +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; + +InitMap(heightSeaGround, tVeryDeepWater); var numPlayers = getNumPlayers(); var mapSize = getMapSize(); var mapCenter = getMapCenter(); var clIsland = createTileClass(); var clCreek = createTileClass(); var clWater = createTileClass(); var clCliffs = createTileClass(); var clForest = createTileClass(); var clShore = createTileClass(); var clPlayer = createTileClass(); var clBaseResource = createTileClass(); var clPassage = createTileClass(); var clSettlement = 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); -var heightMain = 5; -var heightCreeks = -5; -var heightBeaches = -1; -var heightOffsetMainRelief = 30; -var heightOffsetLevel1 = 9; -var heightOffsetLevel2 = 8; -var heightOffsetBumps = 2; -var heightOffsetAntiBumps = -5; - 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) { log("Creating island area..."); createArea( new ClumpPlacer(diskArea(radiusIsland), 1, 0.5, 10, islandLocations[island].x, islandLocations[island].y), [ new LayeredPainter([tCliffs, tGrass], [2]), new SmoothElevationPainter(ELEVATION_SET, heightMain, 0), paintClass(clIsland) ]); 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(fractionToSize(0.05) / 2, 0.6, 0.03, 10, location.x, location.y), [ new LayeredPainter([tCliffs, tGrass], [2]), new SmoothElevationPainter(ELEVATION_SET, heightMain, 1), paintClass(clIsland) ]); } 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, 10, location.x, location.y), [ new TerrainPainter(tSteepCliffs), new SmoothElevationPainter(ELEVATION_SET, heightCreeks, 0), paintClass(clCreek) ]); } 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, 10, Math.round((start.x + end.x * 3) / 4), Math.round((start.y + end.y * 3) / 4)), new SmoothElevationPainter(ELEVATION_SET, heightBeaches, 5)); createPassage({ "start": start, "end": end, "startWidth": 18, "endWidth": 25, "smoothWidth": 4, "tileClass": clShore }); } log("Creating main relief..."); createArea( new ClumpPlacer(diskArea(radiusIsland), 1, 0.2, 10, islandLocations[island].x, islandLocations[island].y), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetMainRelief, fractionToTiles(0.45))); log("Creating first level plateau..."); createArea( new ClumpPlacer(diskArea(radiusLevel1), 0.95, 0.02, 10, islandLocations[island].x, islandLocations[island].y), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetLevel1, 1)); 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) { log("Creating second level plateau..."); createArea( new ClumpPlacer(diskArea(radiusLevel2), 0.98, 0.04, 10, islandLocations[island].x, islandLocations[island].y), [ new LayeredPainter([tCliffs, tGrass], [2]), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetLevel2, 1) ]); 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); 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])); ++p; } } placePlayerBases({ "PlayerPlacement": [sortAllPlayers(), playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "Walls": false, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad, "coherence": 0.8, "radius": 6, "painters": [ paintClass(clSettlement) ] }, "Chicken": { }, "Berries": { "template": eBush }, "Mines": { "types": [ { "template": eMetalMine }, { "template": eStoneMine } ] } // Sufficient starting trees around, no decoratives }); Engine.SetProgress(40); log("Creating bumps..."); createAreas( new ClumpPlacer(70, 0.6, 0.1, 4), [new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBumps, 3)], [ stayClasses(clIsland, 2), avoidClasses(clPlayer, 6, clPassage, 2) ], scaleByMapSize(20, 100), 5); log("Creating anti bumps..."); createAreas( new ClumpPlacer(120, 0.3, 0.1, 4), new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetAntiBumps, 6), avoidClasses(clPlayer, 6, clPassage, 2, clIsland, 2), scaleByMapSize(20, 100), 5); log("Painting water..."); paintTileClassBasedOnHeight(-Infinity, 0, Elevation_ExcludeMin_ExcludeMax, clWater); log("Painting land..."); for (let mapX = 0; mapX < mapSize; ++mapX) for (let mapZ = 0; mapZ < mapSize; ++mapZ) { let terrain = getCosricaSardiniaTerrain(mapX, mapZ); if (!terrain) continue; createTerrain(terrain).place(mapX, mapZ); if (terrain == tCliffs || terrain == tSteepCliffs) addToClass(mapX, mapZ, clCliffs); } function getCosricaSardiniaTerrain(mapX, mapZ) { let isWater = getTileClass(clWater).countMembersInRadius(mapX, mapZ, 3); let isShore = getTileClass(clShore).countMembersInRadius(mapX, mapZ, 2); let isPassage = getTileClass(clPassage).countMembersInRadius(mapX, mapZ, 2); let isSettlement = getTileClass(clSettlement).countMembersInRadius(mapX, mapZ, 2); if (isSettlement) return undefined; let height = getHeight(mapX, mapZ); let heightDiff = getHeightDiff(mapX, mapZ); if (height >= 0.5 && height < 1.5 && isShore) return tSandTransition; // Paint land cliffs and grass if (height >= 1 && !isWater) { if (isPassage) return tGrass; if (heightDiff >= 10) return height > 25 ? tSteepCliffs : tCliffs; if (height < 17) return tGrass; if (heightDiff < 5) return tHill; return tMountain; } if (heightDiff >= 9) 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 && heightDiff < 6) return tDeepWater; return undefined; } Engine.SetProgress(65); 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); log("Creating grass patches..."); createAreas( new ClumpPlacer(20, 0.3, 0.06, 0.5), [ new TerrainPainter(tLushGrass), paintClass(clForest) ], avoidClasses( clWater, 1, clPlayer, 6, clBaseResource, 3, clCliffs, 1), scaleByMapSize(10, 40)); 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); 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); 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); 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); 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); 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); setTerrainAmbientColor(0.564706,0.543726,0.419608); setUnitsAmbientColor(0.53,0.55,0.45); setWaterColor(0.2,0.294,0.49); setWaterTint(0.208, 0.659, 0.925); setWaterMurkiness(0.72); setWaterWaviness(2.0); setWaterType("ocean"); ExportMap(); // no need for preliminary rounding function getHeightDiff(x1, z1) { var height = getHeight(Math.round(x1),Math.round(z1)); var diff = 0; if (z1 + 1 < mapSize) diff += Math.abs(getHeight(Math.round(x1),Math.round(z1+1)) - height); if (x1 + 1 < mapSize && z1 + 1 < mapSize) diff += Math.abs(getHeight(Math.round(x1+1),Math.round(z1+1)) - height); if (x1 + 1 < mapSize) diff += Math.abs(getHeight(Math.round(x1+1),Math.round(z1)) - height); if (x1 + 1 < mapSize && z1 - 1 >= 0) diff += Math.abs(getHeight(Math.round(x1+1),Math.round(z1-1)) - height); if (z1 - 1 >= 0) diff += Math.abs(getHeight(Math.round(x1),Math.round(z1-1)) - height); if (x1 - 1 >= 0 && z1 - 1 >= 0) diff += Math.abs(getHeight(Math.round(x1-1),Math.round(z1-1)) - height); if (x1 - 1 >= 0) diff += Math.abs(getHeight(Math.round(x1-1),Math.round(z1)) - height); if (x1 - 1 >= 0 && z1 + 1 < mapSize) diff += Math.abs(getHeight(Math.round(x1-1),Math.round(z1+1)) - height); return diff; } Index: ps/trunk/binaries/data/mods/public/maps/random/cycladic_archipelago.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/cycladic_archipelago.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/cycladic_archipelago.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "Cycladic Archipelago", "Script" : "cycladic_archipelago.js", "Description" : "Each player starts on an island surrounded by water.\n\nThe Cyclades is an island group in the Aegean Sea, south-east of the mainland of Greece. They are one of the island groups which constitute the Aegean archipelago. The name refers to the islands around the sacred island of Delos. The Cyclades comprise about 220 islands. The islands are peaks of a submerged mountainous terrain, with the exception of two volcanic islands, Milos and Santorini. The climate is generally dry and mild, but with the exception of Naxos the soil is not very fertile.", "BaseTerrain" : ["medit_sea_depths"], - "BaseHeight" : -5, "Keywords": ["naval"], "Preview" : "cycladic_archipelago.png", "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/deep_forest.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/deep_forest.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/deep_forest.js (revision 20904) @@ -1,198 +1,202 @@ Engine.LoadLibrary("rmgen"); -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); - -var clPlayer = createTileClass(); -var clPath = createTileClass(); -var clHill = createTileClass(); -var clForest = createTileClass(); -var clBaseResource = createTileClass(); - var templateStone = "gaia/geology_stone_temperate"; var templateStoneMine = "gaia/geology_stonemine_temperate_quarry"; var templateMetalMine = "gaia/geology_metal_temperate_slabs"; var templateTemple = "other/unfinished_greek_temple"; var terrainWood = ['temp_grass_mossy|gaia/flora_tree_oak', 'temp_forestfloor_pine|gaia/flora_tree_pine', 'temp_mud_plants|gaia/flora_tree_dead', 'temp_plants_bog|gaia/flora_tree_oak_large', "temp_dirt_gravel_plants|gaia/flora_tree_aleppo_pine", 'temp_forestfloor_autumn|gaia/flora_tree_carob']; //'temp_forestfloor_autumn|gaia/flora_tree_fig' var terrainWoodBorder = ['temp_grass_plants|gaia/flora_tree_euro_beech', 'temp_grass_mossy|gaia/flora_tree_poplar', 'temp_grass_mossy|gaia/flora_tree_poplar_lombardy', 'temp_grass_long|gaia/flora_bush_temperate', 'temp_mud_plants|gaia/flora_bush_temperate', 'temp_mud_plants|gaia/flora_bush_badlands', 'temp_grass_long|gaia/flora_tree_apple', 'temp_grass_clovers|gaia/flora_bush_berry', 'temp_grass_clovers_2|gaia/flora_bush_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', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_dirt_gravel', 'temp_grass_b', 'temp_grass_b|gaia/fauna_pig', 'temp_dirt_gravel|gaia/fauna_chicken']; 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; + +InitMap(heightLand, g_MapSettings.BaseTerrain); + var mapSize = getMapSize(); var mapArea = getMapArea(); var mapRadius = mapSize/2; var mapCenter = getMapCenter(); +var clPlayer = createTileClass(); +var clPath = createTileClass(); +var clHill = createTileClass(); +var clForest = createTileClass(); +var clBaseResource = 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 256*192/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) / mapArea, 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]), paintClass(clPlayer) ] }, // Chicken already placed at the base terrain "Berries": { "template": "gaia/flora_bush_grapes", "minCount": 2, "maxCount": 2, "minDist": 10, "maxDist": 10 }, "Mines": { "types": [ { "template": templateMetalMine }, { "template": templateStoneMine } ], "minAngle": Math.PI / 2, "maxAngle": Math.PI }, "Trees": { "template": "gaia/flora_tree_oak_large", "count": 2 } }); Engine.SetProgress(10); 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, -2, 2, 1), + new SmoothElevationPainter(ELEVATION_SET, heightPath, 2, heightOffsetRandomPath), paintClass(clPath) ], avoidClasses(clHill, 0, clBaseResource, 4)); } Engine.SetProgress(50); 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(); placeObject(position.x, position.y, resourcePerPlayer[rIndex], 0, randomAngle()); createArea( new ClumpPlacer(40, 1/2, 1/8, 1, position.x, position.y), [ new LayeredPainter([terrainHillBorder, terrainHill], [1]), new ElevationPainter(randFloat(1, 2)), paintClass(clHill) ]); } Engine.SetProgress(60); log("Placing temple..."); placeObject(mapCenter.x, mapCenter.y, templateTemple, 0, randomAngle()); addToClass(mapCenter.x, mapCenter.y, clBaseResource); log("Creating central mountain..."); createArea( new ClumpPlacer(Math.square(radiusEC), 1/2, 1/8, 1, mapCenter.x, mapCenter.y), [ new LayeredPainter([terrainHillBorder, terrainHill], [radiusEC/4]), new ElevationPainter(randFloat(1, 2)), paintClass(clHill) ]); // Woods and general hight map for (var x = 0; x < mapSize; x++) for (var z = 0;z < mapSize;z++) { // The 0.5 is a correction for the entities placed on the center of tiles var radius = Math.euclidDistance2D(x + 0.5, z + 0.5, mapCenter.x, mapCenter.y); var minDistToSL = mapSize; for (var i=0; i < numPlayers; i++) minDistToSL = Math.min(minDistToSL, Math.euclidDistance2D(x, z, playerPosition[i].x, playerPosition[i].y)); // 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.validT(x, z)) { let border = tDensActual < randFloat(0, bushChance * maxTreeDensity); createArea( new ClumpPlacer(1, 1, 1, 1, x, z), [ new TerrainPainter(border ? terrainWoodBorder : terrainWood), new ElevationPainter(randFloat(0, 1)), paintClass(clForest) ], avoidClasses(clPath, 1, clHill, border ? 0 : 1)); } // General hight map var hVarMiddleHill = mapSize / 64 * (1 + Math.cos(3/2 * Math.PI * radius / mapRadius)); var hVarHills = 5 * (1 + Math.sin(x / 10) * Math.sin(z / 10)); setHeight(x, z, getHeight(x, z) + hVarMiddleHill + hVarHills + 1); } Engine.SetProgress(95); placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clBaseResource, 4)); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/empire.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/empire.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/empire.json (revision 20904) @@ -1,13 +1,12 @@ { "settings" : { "Name" : "Empire", "Script" : "empire.js", "Description" : "A neighboring province has pledged alegiance to your rule. It's up to you to command them to victory.", "BaseTerrain" : ["medit_sea_depths"], - "BaseHeight" : 2, "Keywords": [], "Preview" : "empire.png", "SupportedBiomes": true, "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/aegean_sea.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/aegean_sea.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/aegean_sea.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "Aegean Sea", "Script" : "aegean_sea.js", "Description" : "Players start on two sides of a sea with scattered islands.", "BaseTerrain" : ["medit_grass_shrubs", "medit_rocks_grass_shrubs", "medit_rocks_shrubs", "medit_rocks_grass", "medit_shrubs"], - "BaseHeight" : 1, "Keywords": ["naval"], "CircularMap" : true, "Preview" : "aegean_sea.png" } } Index: ps/trunk/binaries/data/mods/public/maps/random/african_plains.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/african_plains.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/african_plains.js (revision 20904) @@ -1,293 +1,295 @@ Engine.LoadLibrary("rmgen"); -var tPrimary = ["savanna_grass_a"]; +var tPrimary = "savanna_grass_a"; var tForestFloor = "savanna_forestfloor_a"; var tCliff = ["savanna_cliff_a", "savanna_cliff_a_red", "savanna_cliff_b", "savanna_cliff_b_red"]; var tSecondary = "savanna_grass_b"; -var tGrassShrubs = ["savanna_shrubs_a"]; -var tGrass = ["savanna_grass_a_wetseason", "savanna_grass_b_wetseason"]; +var tGrassShrubs = "savanna_shrubs_a"; var tDirt = "savanna_dirt_a"; var tDirt2 = "savanna_dirt_a_red"; var tDirt3 = "savanna_dirt_b"; var tDirt4 = "savanna_dirt_rocks_a"; var tCitytiles = "savanna_tile_a"; var tShore = "savanna_riparian_bank"; var tWater = "savanna_riparian_wet"; var oBaobab = "gaia/flora_tree_baobab"; var oPalm = "gaia/flora_tree_senegal_date_palm"; var oBerryBush = "gaia/flora_bush_berry"; var oWildebeest = "gaia/fauna_wildebeest"; var oZebra = "gaia/fauna_zebra"; var oRhino = "gaia/fauna_rhino"; var oLion = "gaia/fauna_lion"; var oLioness = "gaia/fauna_lioness"; var oHawk = "gaia/fauna_hawk"; 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"; var oFish = "gaia/fauna_fish"; var oStoneSmall = "gaia/geology_stone_savanna_small"; var oMetalLarge = "gaia/geology_metal_savanna_slabs"; var aBush = "actor|props/flora/bush_medit_sm_dry.xml"; var aRock = "actor|geology/stone_savanna_med.xml"; const pForest = [tForestFloor + TERRAIN_SEPARATOR + oPalm, tForestFloor]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +var heightSeaGround = -5; +var heightLand = 2; +var heightCliff = 3; + +InitMap(heightLand, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tPrimary, "innerTerrain": tCitytiles }, "Chicken": { }, "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); createHills([tDirt2, tCliff, tGrassShrubs], avoidClasses(clPlayer, 35, clForest, 20, clHill, 20, clWater, 2), clHill, scaleByMapSize(5, 8)); Engine.SetProgress(30); var lakeAreas = []; var playerConstraint = new AvoidTileClassConstraint(clPlayer, 20); var waterConstraint = new AvoidTileClassConstraint(clWater, 8); for (var x = 0; x < mapSize; ++x) for (var z = 0; z < mapSize; ++z) if (playerConstraint.allows(x, z) && waterConstraint.allows(x, z)) lakeAreas.push([x, z]); log("Creating water holes..."); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), Math.floor(scaleByMapSize(60, 100)), 5), [ new LayeredPainter([tShore, tWater], [1]), - new SmoothElevationPainter(ELEVATION_SET, -5, 7), + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 7), paintClass(clWater) ], avoidClasses(clPlayer, 22, clWater, 8, clHill, 2), scaleByMapSize(2, 5) ); Engine.SetProgress(45); -paintTerrainBasedOnHeight(3, Math.floor(scaleByMapSize(20, 40)), 0, tCliff); -paintTerrainBasedOnHeight(Math.floor(scaleByMapSize(20, 40)), 100, 3, tGrass); +paintTerrainBasedOnHeight(heightCliff, Infinity, 0, tCliff); createBumps(avoidClasses(clWater, 2, clPlayer, 20)); var [forestTrees, stragglerTrees] = getTreeCounts(500, 3000, 0.7); createForests( [tPrimary, tForestFloor, tForestFloor, pForest, pForest], avoidClasses(clPlayer, 20, clForest, 20, clHill, 0, clWater, 2), clForest, forestTrees); 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); 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); 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(60); log("Creating stone mines..."); createMines( [ [new SimpleObject(oStoneSmall, 0,2, 0,4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], avoidClasses(clWater, 4, clForest, 4, clPlayer, 20, clRock, 10, clHill, 4), clRock); log("Creating metal mines..."); createMines( [ [new SimpleObject(oMetalLarge, 1,1, 0,4)] ], avoidClasses(clWater, 4, clForest, 4, clPlayer, 20, clMetal, 18, clRock, 5, clHill, 4), clMetal ); Engine.SetProgress(70); createDecoration( [ [new SimpleObject(aBush, 1,3, 0,1)], [new SimpleObject(aRock, 1,2, 0,1)] ], [ scaleByMapSize(8, 131), scaleByMapSize(8, 131) ], avoidClasses(clWater, 0, clForest, 0, clPlayer, 0, clHill, 0)); Engine.SetProgress(75); log("Creating giraffes..."); var group = new SimpleGroup( [new SimpleObject(oGiraffe, 2,4, 0,4), new SimpleObject(oGiraffe2, 0,2, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clPlayer, 20, clFood, 11, clHill, 4), scaleByMapSize(4,12), 50 ); log("Creating elephants..."); group = new SimpleGroup( [new SimpleObject(oElephant, 2,4, 0,4), new SimpleObject(oElephant2, 0,2, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clPlayer, 20, clFood, 11, clHill, 4), scaleByMapSize(4,12), 50 ); 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, 3, clPlayer, 20, clFood, 11, clHill, 4), scaleByMapSize(4,12), 50 ); 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); createFood( [ [new SimpleObject(oCrocodile, 2, 3, 0, 3)] ], [ 3 * numPlayers, ], stayClasses(clWater, 6), clFood); 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); createStragglerTrees( [oBaobab], avoidClasses(clWater, 5, clForest, 2, clHill, 3, clPlayer, 12, clMetal, 4, clRock, 4), clForest, stragglerTrees); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); setPPEffect("hdr"); setPPSaturation(0.48); setPPContrast(0.53); setPPBloom(0.12); setFogThickness(0.25); setFogFactor(0.25); setFogColor(0.8, 0.7, 0.5); setSkySet("sunny"); setSunRotation(randomAngle()); setSunElevation(Math.PI * randFloat(1/4, 1/2)); setWaterColor(0.223, 0.247, 0.2); // dark majestic blue setWaterTint(0.462, 0.756, 0.566); // light blue setWaterMurkiness(5.92); setWaterWaviness(0); setWaterType("clap"); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/african_plains.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/african_plains.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/african_plains.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "African Plains", "Script" : "african_plains.js", "Description" : "The central region of the vast continent of Africa, birthplace of humanity. Players start in a lush area teeming with vegetation and wildlife.", "BaseTerrain" : ["savanna_grass_a"], - "BaseHeight" : 2, "Keywords": [], "Preview" : "african_plains.png", "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/alpine_lakes.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/alpine_lakes.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/alpine_lakes.js (revision 20904) @@ -1,300 +1,303 @@ Engine.LoadLibrary("rmgen"); if (randBool()) { log("Late spring biome..."); 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/flora_tree_pine"; var oBerryBush = "gaia/flora_bush_berry"; var oDeer = "gaia/fauna_deer"; var oFish = "gaia/fauna_fish"; var oRabbit = "gaia/fauna_rabbit"; var oStoneLarge = "gaia/geology_stonemine_alpine_quarry"; var oStoneSmall = "gaia/geology_stone_alpine_a"; var oMetalLarge = "gaia/geology_metal_alpine_slabs"; 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 { log("Winter biome..."); 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/flora_tree_pine_w"; var oBerryBush = "gaia/flora_bush_berry"; var oDeer = "gaia/fauna_deer"; var oFish = "gaia/fauna_fish"; var oRabbit = "gaia/fauna_rabbit"; var oStoneLarge = "gaia/geology_stonemine_alpine_quarry"; var oStoneSmall = "gaia/geology_stone_alpine_a"; var oMetalLarge = "gaia/geology_metal_alpine_slabs"; 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]; -InitMap(g_MapSettings.BaseHeight, tPrimary); +var heightSeaGround = -5; +var heightLand = 3; + +InitMap(heightLand, tPrimary); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, "Chicken": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oPine, "count": scaleByMapSize(3, 12) }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(20); log("Creating hills..."); 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); var lakeAreas = []; var playerConstraint = new AvoidTileClassConstraint(clPlayer, 20); var waterConstraint = new AvoidTileClassConstraint(clWater, 8); for (var x = 0; x < mapSize; ++x) for (var z = 0; z < mapSize; ++z) if (playerConstraint.allows(x, z) && waterConstraint.allows(x, z)) lakeAreas.push([x, z]); var lakeAreaLen; log("Creating lakes..."); var numLakes = scaleByMapSize(5, 16); for (var i = 0; i < numLakes; ++i) { lakeAreaLen = lakeAreas.length; if (!lakeAreaLen) break; let chosenPoint = pickRandom(lakeAreas); let newLake = createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(4, 8)), Math.floor(scaleByMapSize(40, 180)), 0.7, chosenPoint[0], chosenPoint[1]), [ new LayeredPainter([tShore, tWater, tWater], [1, 3]), - new SmoothElevationPainter(ELEVATION_SET, -5, 5), + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 5), paintClass(clWater) ], avoidClasses(clPlayer, 20, clWater, 8), 1, 1 ); if (newLake && newLake.length) { var n = 0; for (var j = 0; j < lakeAreaLen; ++j) { var x = lakeAreas[j][0], z = lakeAreas[j][1]; if (playerConstraint.allows(x, z) && waterConstraint.allows(x, z)) lakeAreas[n++] = lakeAreas[j]; } lakeAreas.length = n; } } 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); 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); 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); log("Creating stone mines..."); createMines( [ [new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), clRock); 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)] ], [ scaleByMapSize(16, 262), scaleByMapSize(8, 131), scaleByMapSize(13, 200), scaleByMapSize(13, 200), scaleByMapSize(13, 200) ], 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"); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/alpine_lakes.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/alpine_lakes.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/alpine_lakes.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Alpine Lakes", "Script" : "alpine_lakes.js", "Description" : "High Alpine mountains surrounding deep valleys strung with mountain streams and finger-like lakes.", "BaseTerrain" : ["alpine_dirt_grass_50"], - "BaseHeight" : 3, "CircularMap" : true, "Preview" : "alpine_lakes.png" } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/alpine_valley.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/alpine_valley.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/alpine_valley.js (revision 20904) @@ -1,545 +1,544 @@ Engine.LoadLibrary("rmgen"); 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.x1 = this.currentEdgeStart.x; this.pathplacer.z1 = this.currentEdgeStart.y; this.pathplacer.x2 = this.currentEdgeEnd.x; this.pathplacer.z2 = this.currentEdgeEnd.y; this.pathplacer.width = this.mountainWidth; log("Creating mountainrange..."); if (!createArea(this.pathplacer, this.painters, this.constraint)) return false; log("Creating circular mountains at both ends of that mountainrange..."); for (let point of [this.currentEdgeStart, this.currentEdgeEnd]) createArea( new ClumpPlacer(Math.floor(diskArea(this.mountainWidth / 2)), 0.95, 0.6, 10, point.x, point.y), this.painters, this.constraint); return true; }; /** * This is the only function meant to be publicly accessible. */ MountainRangeBuilder.prototype.CreateMountainRanges = function() { while (this.possibleEdges.length) { 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()) { log("Late spring biome..."); 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/flora_tree_pine"; var oBerryBush = "gaia/flora_bush_berry"; var oDeer = "gaia/fauna_deer"; var oRabbit = "gaia/fauna_rabbit"; var oStoneLarge = "gaia/geology_stonemine_alpine_quarry"; var oStoneSmall = "gaia/geology_stone_alpine_a"; var oMetalLarge = "gaia/geology_metal_alpine_slabs"; 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 { log("Winter biome..."); 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/flora_tree_pine_w"; var oBerryBush = "gaia/flora_bush_berry"; var oDeer = "gaia/fauna_deer"; var oRabbit = "gaia/fauna_rabbit"; var oStoneLarge = "gaia/geology_stonemine_alpine_quarry"; var oStoneSmall = "gaia/geology_stone_alpine_a"; var oMetalLarge = "gaia/geology_metal_alpine_slabs"; 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]; -InitMap(g_MapSettings.BaseHeight, tPrimary); +InitMap(heightLand, tPrimary); const numPlayers = getNumPlayers(); const mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); -/** - * Minimum distance between two mountainranges. - */ -var snowlineHeight = 29; -var mountainHeight = 30; - var [playerIDs, playerPosition, playerAngle, startAngle] = playerPlacementCircle(fractionToTiles(0.35)); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, "Chicken": { }, "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, undefined, undefined, 0.4, scaleByMapSize(3, 12), 0.1, 0.1, 0.1), "painters":[ new LayeredPainter([tCliff, tPrimary], [3]), - new SmoothElevationPainter(ELEVATION_SET, mountainHeight, 2), + new SmoothElevationPainter(ELEVATION_SET, heightMountain, 2), paintClass(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(getMapBaseHeight() + 0.1, snowlineHeight, 0, tCliff); -paintTerrainBasedOnHeight(snowlineHeight, mountainHeight, 3, tSnowLimited); +paintTerrainBasedOnHeight(heightLand + 0.1, snowlineHeight, 0, tCliff); +paintTerrainBasedOnHeight(snowlineHeight, heightMountain, 3, tSnowLimited); log("Creating bumps..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1), - new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), avoidClasses(clPlayer, 10), scaleByMapSize(100, 200)); Engine.SetProgress(40); log("Creating hills..."); createAreas( new ClumpPlacer(scaleByMapSize(40, 150), 0.2, 0.1, 1), [ new LayeredPainter([tCliff, tSnowLimited], [2]), - new SmoothElevationPainter(ELEVATION_SET, mountainHeight, 2), + new SmoothElevationPainter(ELEVATION_SET, heightMountain, 2), paintClass(clHill) ], avoidClasses(clPlayer, 20, clHill, 14), scaleByMapSize(10, 80) * numPlayers ); Engine.SetProgress(50); 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, 1), [ new LayeredPainter(type, [2]), paintClass(clForest) ], avoidClasses(clPlayer, 12, clForest, 10, clHill, 0), num); Engine.SetProgress(60); 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]), paintClass(clDirt) ], avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12), scaleByMapSize(15, 45)); 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); log("Creating stone mines..."); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), scaleByMapSize(4,16), 100 ); 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 ); 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); 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 ); 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); 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 ); 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 ); 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); 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); 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); 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)); setWaterColor(0.0, 0.047, 0.286); // dark majestic blue setWaterTint(0.471, 0.776, 0.863); // light blue setWaterMurkiness(0.72); setWaterWaviness(2.0); setWaterType("lake"); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/alpine_valley.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/alpine_valley.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/alpine_valley.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Alpine Valley", "Script" : "alpine_valley.js", "Description" : "High Alpine mountains bordering deep valleys.", "BaseTerrain" : ["alpine_dirt_grass_50"], - "BaseHeight" : 3, "Preview" : "alpine_valley.png", "CircularMap" : true } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/ambush.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/ambush.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/ambush.js (revision 20904) @@ -1,208 +1,210 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen2"); Engine.LoadLibrary("rmbiome"); setSelectedBiome(); -InitMap(g_MapSettings.BaseHeight, g_Terrains.mainTerrain); +var heightLand = 2; + +InitMap(heightLand, g_Terrains.mainTerrain); initTileClasses(); createArea( new MapBoundsPlacer(), paintClass(g_TileClasses.land)); Engine.SetProgress(10); const pos = randomStartingPositionPattern(getTeamsArray()); addBases(pos.setup, pos.distance, pos.separation, randomAngle()); Engine.SetProgress(20); addElements([ { "func": addBluffs, - "baseHeight": getMapBaseHeight(), + "baseHeight": heightLand, "avoid": [ g_TileClasses.bluff, 12, g_TileClasses.hill, 5, g_TileClasses.player, 35 ], "sizes": ["normal", "big", "huge"], "mixes": ["same"], "amounts": ["tons"] }, { "func": addHills, "avoid": [ g_TileClasses.bluff, 5, g_TileClasses.hill, 15, g_TileClasses.player, 20 ], "sizes": ["normal", "big"], "mixes": ["normal"], "amounts": ["tons"] } ]); Engine.SetProgress(30); addElements([ { "func": addLayeredPatches, "avoid": [ g_TileClasses.bluff, 2, g_TileClasses.dirt, 5, g_TileClasses.forest, 2, g_TileClasses.mountain, 2, g_TileClasses.player, 12, g_TileClasses.water, 3 ], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["normal"] }, { "func": addDecoration, "avoid": [ g_TileClasses.bluff, 2, g_TileClasses.forest, 2, g_TileClasses.mountain, 2, g_TileClasses.player, 12, g_TileClasses.water, 3 ], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["normal"] } ]); Engine.SetProgress(50); addElements(shuffleArray([ { "func": addMetal, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.forest, 3, g_TileClasses.mountain, 2, g_TileClasses.player, 30, g_TileClasses.rock, 10, g_TileClasses.metal, 20, g_TileClasses.water, 3 ], "stay": [g_TileClasses.bluff, 5], "sizes": ["normal"], "mixes": ["same"], "amounts": ["tons"] }, { "func": addStone, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.forest, 3, g_TileClasses.mountain, 2, g_TileClasses.player, 30, g_TileClasses.rock, 20, g_TileClasses.metal, 10, g_TileClasses.water, 3 ], "stay": [g_TileClasses.bluff, 5], "sizes": ["normal"], "mixes": ["same"], "amounts": ["tons"] }, // Forests on bluffs { "func": addForests, "avoid": [ g_TileClasses.forest, 6, g_TileClasses.metal, 3, g_TileClasses.mountain, 5, g_TileClasses.player, 20, g_TileClasses.rock, 3, g_TileClasses.water, 2 ], "stay": [g_TileClasses.bluff, 5], "sizes": ["big"], "mixes": ["normal"], "amounts": ["tons"] }, // Forests on mainland { "func": addForests, "avoid": [ g_TileClasses.bluff, 10, g_TileClasses.forest, 10, g_TileClasses.metal, 3, g_TileClasses.mountain, 5, g_TileClasses.player, 20, g_TileClasses.rock, 3, g_TileClasses.water, 2 ], "sizes": ["small"], "mixes": ["same"], "amounts": ["normal"] } ])); Engine.SetProgress(70); addElements(shuffleArray([ { "func": addBerries, "avoid": [ g_TileClasses.bluff, 5, g_TileClasses.forest, 5, g_TileClasses.metal, 10, g_TileClasses.mountain, 2, g_TileClasses.player, 20, g_TileClasses.rock, 10, g_TileClasses.water, 3 ], "sizes": ["normal"], "mixes": ["same"], "amounts": ["few"] }, { "func": addAnimals, "avoid": [ g_TileClasses.bluff, 5, g_TileClasses.forest, 2, g_TileClasses.metal, 2, g_TileClasses.mountain, 1, g_TileClasses.player, 12, g_TileClasses.rock, 2, g_TileClasses.water, 3 ], "sizes": ["small"], "mixes": ["similar"], "amounts": ["normal", "many"] }, { "func": addStragglerTrees, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.bluff, 5, g_TileClasses.forest, 7, g_TileClasses.metal, 2, g_TileClasses.mountain, 1, g_TileClasses.player, 12, g_TileClasses.rock, 2, g_TileClasses.water, 5 ], "sizes": ["tiny"], "mixes": ["same"], "amounts": ["many"] } ])); Engine.SetProgress(90); placePlayersNomad( g_TileClasses.player, avoidClasses( g_TileClasses.bluff, 4, g_TileClasses.water, 4, g_TileClasses.forest, 1, g_TileClasses.metal, 4, g_TileClasses.rock, 4, g_TileClasses.mountain, 4, g_TileClasses.animals, 2)); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/ambush.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/ambush.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/ambush.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "Ambush", "Script" : "ambush.js", "Description" : "High bluffs overlook the terrain below. Bountiful resources await on the cliffs, but beware of enemies planning an ambush.", "BaseTerrain" : ["medit_sea_depths"], - "BaseHeight" : 2, "Preview" : "ambush.png", "SupportedBiomes": true, "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/anatolian_plateau.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/anatolian_plateau.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/anatolian_plateau.js (revision 20904) @@ -1,244 +1,247 @@ Engine.LoadLibrary("rmgen"); 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/flora_tree_poplar_lombardy"; const oBush = "gaia/flora_bush_temperate"; const oBerryBush = "gaia/flora_bush_berry"; const oRabbit = "gaia/fauna_rabbit"; const oSheep = "gaia/fauna_sheep"; const oStoneLarge = "gaia/geology_stonemine_medit_quarry"; const oStoneSmall = "gaia/geology_stone_mediterranean"; const oMetalLarge = "gaia/geology_metal_mediterranean_slabs"; 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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +var heightLand = 1; +var heightOffsetBump = 2; + +InitMap(heightLand, g_MapSettings.BaseTerrain); var numPlayers = getNumPlayers(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, "Chicken": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oPoplar }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(20); log("Creating bumps..."); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(2, 5)), 0.5), - new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), avoidClasses(clPlayer, 13), scaleByMapSize(300, 800)); 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, 1), [ new LayeredPainter(type, [2]), paintClass(clForest) ], avoidClasses(clPlayer, 13, clForest, 20, clHill, 1), num); Engine.SetProgress(50); 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); 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); 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(55); log("Creating stone mines..."); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), scaleByMapSize(1,4), 100 ); 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 ); 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); 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 ); 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); 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 ); 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); 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); 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); 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); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/anatolian_plateau.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/anatolian_plateau.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/anatolian_plateau.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Anatolian Plateau", "Script" : "anatolian_plateau.js", "Description" : "An indefensible open land with little wood and stone, representing the central basin of Asia Minor.", "BaseTerrain" : ["steppe_grass_a", "steppe_grass_c", "steppe_grass_d"], - "BaseHeight" : 1, "Preview" : "anatolian_plateau.png", "CircularMap" : true } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/archipelago.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/archipelago.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/archipelago.js (revision 20904) @@ -1,268 +1,269 @@ Engine.LoadLibrary("rmgen"); 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 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/special_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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +var heightSeaGround = -5; +var heightLand = 3; +var heightShore = 1; + +InitMap(heightSeaGround, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clLand = createTileClass(); -var landHeight = 3; -var shoreHeight = 1; - var islandRadius = scaleByMapSize(22, 31); var [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); 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)), 1, playerPosition[i].x, playerPosition[i].y, 0, [Math.floor(islandRadius)]), - new SmoothElevationPainter(ELEVATION_SET, landHeight, 4)); + new SmoothElevationPainter(ELEVATION_SET, heightLand, 4)); 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, undefined, scaleByMapSize(30, 70)), [ - new SmoothElevationPainter(ELEVATION_SET, landHeight, 4), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), paintClass(clLand) ], null, scaleByMapSize(1, 5) * randIntInclusive(5, 10)); -paintTerrainBasedOnHeight(landHeight - 0.6, landHeight + 0.4, 3, tMainTerrain); -paintTerrainBasedOnHeight(shoreHeight, landHeight, 0, tShore); -paintTerrainBasedOnHeight(getMapBaseHeight(), shoreHeight, 2, tWater); +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": [ paintClass(clPlayer) ] }, "Chicken": { }, "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); var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(1)); createForests( [tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2], [avoidClasses(clPlayer, 20, clForest, 17, clHill, 0), stayClasses(clLand, 4)], clForest, forestTrees); Engine.SetProgress(50); 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); 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); log("Creating stone mines..."); createMines( [ [new SimpleObject(oStoneSmall, 0,2, 0,4), 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 ); 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() == "tropic" ? 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)] ], [ scaleByMapSize(16, 262), scaleByMapSize(8, 131), planetm * scaleByMapSize(13, 200), planetm * scaleByMapSize(13, 200), planetm * scaleByMapSize(13, 200) ], [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"); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/archipelago.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/archipelago.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/archipelago.json (revision 20904) @@ -1,13 +1,12 @@ { "settings" : { "Name" : "Archipelago", "Script" : "archipelago.js", "Description" : "A maze of islands of different sizes and shapes. Players start with more wood than normal.", "BaseTerrain" : ["medit_sand_wet"], - "BaseHeight" : -5, "Keywords": ["naval"], "Preview" : "archipelago.png", "SupportedBiomes": true, "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/arctic_summer.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/arctic_summer.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/arctic_summer.js (revision 20904) @@ -1,322 +1,325 @@ Engine.LoadLibrary("rmgen"); 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/flora_bush_badlands"; var oBush2 = "gaia/flora_bush_temperate"; var oBerryBush = "gaia/flora_bush_berry"; 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/fauna_fish"; var oStoneLarge = "gaia/geology_stonemine_alpine_quarry"; var oStoneSmall = "gaia/geology_stone_alpine_a"; var oMetalLarge = "gaia/geology_metal_alpine_slabs"; var oWoodTreasure = "gaia/special_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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +var heightSeaGround = -5; +var heightLand = 2; + +InitMap(heightLand, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tPrimary, "innerTerrain": tSecondary }, "Chicken": { "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); log("Creating hills..."); createHills( [tPrimary, tCliff, tHill], avoidClasses( clPlayer, 35, clForest, 20, clHill, 50, clWater, 2), clHill, scaleByMapSize(1, 240)); Engine.SetProgress(30); log("Creating lakes..."); createAreas( new ChainPlacer( 1, Math.floor(scaleByMapSize(4, 8)), Math.floor(scaleByMapSize(40, 180)), 1), [ new LayeredPainter([tShore, tWater, tWater], [1, 3]), - new SmoothElevationPainter(ELEVATION_SET, -5, 5), + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 5), paintClass(clWater) ], avoidClasses(clPlayer, 15), scaleByMapSize(1, 20)); Engine.SetProgress(45); log("Creating bumps..."); 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); 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); 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); 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); log("Creating stone mines..."); createMines( [ [new SimpleObject(oStoneSmall, 0, 2, 0, 4), new SimpleObject(oStoneLarge, 1, 1, 0, 4)], [new SimpleObject(oStoneSmall, 2, 5, 1, 3)] ], avoidClasses( clWater, 3, clForest, 1, clPlayer, 20, clRock, 18, clHill, 1), clRock); 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) ] ], [ scaleByMapSize(16, 262), scaleByMapSize(8, 131), ], 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); setTerrainAmbientColor(0.7, 0.6, 0.7); setUnitsAmbientColor(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"); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/arctic_summer.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/arctic_summer.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/arctic_summer.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "Arctic Summer", "Script" : "arctic_summer.js", "Description" : "Summer has arrived to the cold regions of the north and with it have many animals, profiting from its milder climate. Wolves, ever present, have shed their winter clothes; deer, hares and muskox populate the plains. The last traces of winter are rapidly disappearing, only to reappear very soon.", "BaseTerrain" : ["alpine_grass_rocky"], - "BaseHeight" : 2, "Keywords": [], "Preview" : "arctic_summer.png", "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/ardennes_forest.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/ardennes_forest.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/ardennes_forest.js (revision 20904) @@ -1,459 +1,465 @@ Engine.LoadLibrary("rmgen"); -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); - -const numPlayers = getNumPlayers(); -const mapSize = getMapSize(); -const mapCenter = getMapCenter(); - const tGrass = ["new_alpine_grass_b", "new_alpine_grass_c", "new_alpine_grass_d"]; const tPineForestFloor = "temp_forestfloor_pine"; const tForestFloor = [tPineForestFloor, tPineForestFloor, "alpine_dirt_grass_50"]; const tCliff = ["alpine_cliff_c", "alpine_cliff_c", "alpine_grass_rocky"]; const tCity = ["new_alpine_citytile", "new_alpine_grass_dirt_a"]; const tGrassPatch = ["alpine_grass_a", "alpine_grass_b"]; const oBoar = "gaia/fauna_boar"; const oDeer = "gaia/fauna_deer"; const oBear = "gaia/fauna_bear"; const oPig = "gaia/fauna_pig"; const oBerryBush = "gaia/flora_bush_berry"; const oMetalSmall = "gaia/geology_metal_alpine"; const oMetalLarge = "gaia/geology_metal_temperate_slabs"; const oStoneSmall = "gaia/geology_stone_alpine_a"; const oStoneLarge = "gaia/geology_stonemine_temperate_quarry"; const oOak = "gaia/flora_tree_oak"; const oOakLarge = "gaia/flora_tree_oak_large"; const oPine = "gaia/flora_tree_pine"; const oAleppoPine = "gaia/flora_tree_aleppo_pine"; 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/aleppo_pine.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; + +InitMap(heightHill, g_MapSettings.BaseTerrain); + +const numPlayers = getNumPlayers(); +const mapSize = getMapSize(); +const mapCenter = getMapCenter(); + var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clForestJoin = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clHillDeco = createTileClass(); log("Creating the central dip..."); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.42)), 0.94, 0.05, 0.1, mapCenter.x, mapCenter.y), [ new LayeredPainter([tCliff, tGrass], [3]), - new SmoothElevationPainter(ELEVATION_SET, 30, 3) + new SmoothElevationPainter(ELEVATION_SET, heightLand, 3) ]); Engine.SetProgress(5); // Find all hills var noise0 = new Noise2D(20); for (var ix = 0; ix < mapSize; ix++) for (var iz = 0; iz < mapSize; iz++) { var h = getHeight(ix,iz); if(h > 40){ addToClass(ix,iz,clHill); // Add hill noise var x = ix / (mapSize + 1.0); var z = iz / (mapSize + 1.0); var n = (noise0.get(x,z) - 0.5) * 40; setHeight(ix, iz, 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 - playerPosition[i].x; var dz = z - 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": { "template": oPig }, "Berries": { "template": oBerryBush, "minCount": 3, "maxCount": 3 }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ], "distance": 16 }, "Trees": { "template": oOak, "count": 2 } // No decoratives }); log("Marking player territory larger than the city patch..."); for (let i = 0; i < numPlayers; ++i) createArea( new ClumpPlacer(250, 0.95, 0.3, 0.1, playerPosition[i].x, playerPosition[i].y), paintClass(clPlayer)); Engine.SetProgress(30); 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, 50, size < 50 ? 2 : 4), + new SmoothElevationPainter(ELEVATION_SET, heightHill, size < 50 ? 2 : 4), paintClass(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, 10, 3) + 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, 10, 2), + new SmoothElevationPainter(ELEVATION_SET, heightRavine, 2), paintClass(clHill) ], avoidClasses(clPlayer, 6, clBaseResource, 2, clHill, 5), scaleByMapSize(1, 3)); if (size > 150 && ravine.length) { 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, 2, 2) + new SmoothElevationPainter(ELEVATION_SET, hRavineValley, 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, 40, 2), + new SmoothElevationPainter(ELEVATION_SET, hRavineHill, 2), paintClass(clHill) ], [avoidClasses(clHillDeco, 2), borderClasses(clHill, 15, 1)], ravine.length * 2, 50, ravine); } } Engine.SetProgress(50); var explorableArea = {}; explorableArea.points = []; var playerClass = getTileClass(clPlayer); var hillDecoClass = getTileClass(clHillDeco); for (var ix = 0; ix < mapSize; ix++) { for (var iz = 0; iz < mapSize; iz++) { var h = getHeight(ix,iz); if(h > 15 && h < 45 && playerClass.countMembersInRadius(ix, iz, 1) == 0) { // explorable area var pt = {}; pt.x = ix; pt.z = iz; explorableArea.points.push(pt); } if (h > 35 && randBool(0.1) || h < 15 && randBool(0.05) && hillDecoClass.countMembersInRadius(ix, iz, 1) == 0) placeObject(ix + randFloat(0, 1), iz + randFloat(0, 1), pickRandom(aTrees), 0, randomAngle()); } } 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++) { var z = iz / (mapSize + 1.0); var h = getHeight(ix,iz); var pn = playerNearness(x,z); var n = (noise0.get(x,z) - 0.5) * 10; setHeight(ix, iz, h + (n * pn)); } } Engine.SetProgress(60); log("Creating forests..."); var [forestTrees, stragglerTrees] = getTreeCounts(400, 6000, 0.8); var [forestTreesJoin, forestTrees] = getTreeCounts(forestTrees, forestTrees, 0.25); var num = forestTrees / (scaleByMapSize(6, 16) * numPlayers); createAreasInAreas( new ClumpPlacer(forestTrees / num, 0.1, 0.1, 1), [ new TerrainPainter(pForest), paintClass(clForest) ], avoidClasses(clPlayer, 5, clBaseResource, 4, clForest, 6, clHill, 4), num, 100, [explorableArea] ); var num = forestTreesJoin / (scaleByMapSize(4,6) * numPlayers); createAreasInAreas( new ClumpPlacer(forestTreesJoin / num, 0.1, 0.1, 1), [ new TerrainPainter(pForest), paintClass(clForest), paintClass(clForestJoin) ], [avoidClasses(clPlayer, 5, clBaseResource, 4, clForestJoin, 5, clHill, 4), borderClasses(clForest, 1, 4)], num, 100, [explorableArea] ); Engine.SetProgress(70); 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, tGrassPatch], [tGrassPatch, tGrass], [tGrass, tGrassPatch]], [1, 1]), avoidClasses(clForest, 0, clHill, 2, clPlayer, 5), scaleByMapSize(15, 45)); 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); log("Creating stone mines..."); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 1,2, 0,4), new SimpleObject(oStoneLarge, 0,1, 0,4)], true, clRock); createObjectGroupsByAreasDeprecated(group, 0, [avoidClasses(clHill, 4, clForest, 2, clPlayer, 20, clRock, 10)], scaleByMapSize(6,20), 100, [explorableArea] ); log("Creating small stone mines..."); group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock); createObjectGroupsByAreasDeprecated(group, 0, [avoidClasses(clHill, 4, clForest, 2, clPlayer, 20, clRock, 10)], scaleByMapSize(6,20), 100, [explorableArea] ); log("Creating metal mines..."); group = new SimpleGroup([new SimpleObject(oMetalSmall, 1,2, 0,4), new SimpleObject(oMetalLarge, 0,1, 0,4)], true, clMetal); createObjectGroupsByAreasDeprecated(group, 0, [avoidClasses(clHill, 4, clForest, 2, clPlayer, 20, clMetal, 10, clRock, 5)], scaleByMapSize(6,20), 100, [explorableArea] ); Engine.SetProgress(80); log("Creating wildlife..."); 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); 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 ); 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); 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); 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)); setTerrainAmbientColor(0.44,0.51,0.56); setUnitsAmbientColor(0.44,0.51,0.56); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/ardennes_forest.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/ardennes_forest.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/ardennes_forest.json (revision 20904) @@ -1,13 +1,12 @@ { "settings" : { "Name" : "Ardennes Forest", "Script" : "ardennes_forest.js", "Description" : "Each player starts deep in the forest.\n\nThe Ardennes is a region of extensive forests, rolling hills and ridges formed within the Givetian Ardennes mountain range, primarily in modern day Belgium and Luxembourg. The region took its name from the ancient Silva, a vast forest in Roman times called Arduenna Silva.", "BaseTerrain" : [ "temp_forestfloor_pine", "temp_forestfloor_pine", "alpine_cliff_c", "alpine_grass_rocky" ], - "BaseHeight" : 50, "CircularMap" : true, "Preview" : "ardennes_forest.png" } } Index: ps/trunk/binaries/data/mods/public/maps/random/atlas_mountains.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/atlas_mountains.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/atlas_mountains.js (revision 20904) @@ -1,219 +1,221 @@ Engine.LoadLibrary("rmgen"); 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/flora_tree_carob"; const oAleppoPine = "gaia/flora_tree_aleppo_pine"; const oBerryBush = "gaia/flora_bush_berry"; const oDeer = "gaia/fauna_deer"; const oSheep = "gaia/fauna_sheep"; const oStoneLarge = "gaia/geology_stonemine_medit_quarry"; const oStoneSmall = "gaia/geology_stone_mediterranean"; const oMetalLarge = "gaia/geology_metal_mediterranean_slabs"; const oWoodTreasure = "gaia/special_treasure_wood"; const oFoodTreasure = "gaia/special_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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightLand = 3; + +InitMap(heightLand, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clTreasure = createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, "Chicken": { }, "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); 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); 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); log("Creating stone mines..."); createMines( [ [new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], avoidClasses(clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 2), clRock); 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)] ], [ scaleByMapSize(16, 262), scaleByMapSize(8, 131), scaleByMapSize(13, 200), scaleByMapSize(13, 200), scaleByMapSize(13, 200) ], 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); 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 ); 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); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/atlas_mountains.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/atlas_mountains.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/atlas_mountains.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Atlas Mountains", "Script" : "atlas_mountains.js", "Description" : "A rugged land with small room for buildings with scarce wood. Represents the mountain range in the north-west africa.", "BaseTerrain" : ["medit_rocks_grass", "medit_rocks_grass", "medit_rocks_grass", "medit_rocks_grass", "medit_rocks_grass_shrubs", "medit_rocks_shrubs"], - "BaseHeight" : 3, "Preview" : "atlas_mountains.png", "CircularMap" : true } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/belgian_uplands.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/belgian_uplands.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/belgian_uplands.js (revision 20904) @@ -1,406 +1,408 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("heightmap"); -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightLand = 0; + +InitMap(heightLand, g_MapSettings.BaseTerrain); var numPlayers = getNumPlayers(); var mapSize = getMapSize(); var mapCenter = getMapCenter(); // Function to apply a heightmap function setReliefmap(reliefmap) { // g_Map.height = reliefmap; for (var x = 0; x <= mapSize; x++) for (var y = 0; y <= mapSize; y++) setHeight(x, y, reliefmap[x][y]); } // Set target min and max height depending on map size to make average stepness the same on all map sizes var heightRange = {"min": MIN_HEIGHT * mapSize / 8192, "max": MAX_HEIGHT * mapSize / 8192}; // Set average water coverage var averageWaterCoverage = 1/3; // NOTE: Since errosion is not predictable actual water coverage might differ much with the same value if (mapSize < 200) // Sink the waterlevel on tiny maps to ensure enough space averageWaterCoverage = 2/3 * averageWaterCoverage; -var waterHeight = -MIN_HEIGHT + heightRange.min + averageWaterCoverage * (heightRange.max - heightRange.min); -var waterHeightAdjusted = waterHeight + MIN_HEIGHT; -setWaterHeight(waterHeight); +var heightSeaGround = -MIN_HEIGHT + heightRange.min + averageWaterCoverage * (heightRange.max - heightRange.min); +var heightSeaGroundAdjusted = heightSeaGround + MIN_HEIGHT; +setWaterHeight(heightSeaGround); // Prepare terrain texture by height placement var textueByHeight = []; // Deep water -textueByHeight.push({"upperHeightLimit": heightRange.min + 1/3 * (waterHeightAdjusted - heightRange.min), "terrain": "temp_sea_rocks"}); +textueByHeight.push({"upperHeightLimit": heightRange.min + 1/3 * (heightSeaGroundAdjusted - heightRange.min), "terrain": "temp_sea_rocks"}); // Medium deep water (with fish) var terrains = ["temp_sea_weed"]; terrains = terrains.concat(terrains, terrains, terrains, terrains); terrains = terrains.concat(terrains, terrains, terrains, terrains); terrains.push("temp_sea_weed|gaia/fauna_fish"); -textueByHeight.push({"upperHeightLimit": heightRange.min + 2/3 * (waterHeightAdjusted - heightRange.min), "terrain": terrains}); +textueByHeight.push({"upperHeightLimit": heightRange.min + 2/3 * (heightSeaGroundAdjusted - heightRange.min), "terrain": terrains}); // Flat Water -textueByHeight.push({"upperHeightLimit": heightRange.min + 3/3 * (waterHeightAdjusted - heightRange.min), "terrain": "temp_mud_a"}); +textueByHeight.push({"upperHeightLimit": heightRange.min + 3/3 * (heightSeaGroundAdjusted - heightRange.min), "terrain": "temp_mud_a"}); // Water surroundings/bog (with stone/metal some rabits and bushes) var terrains = ["temp_plants_bog", "temp_plants_bog_aut", "temp_dirt_gravel_plants", "temp_grass_d"]; terrains = terrains.concat(terrains, terrains, terrains, terrains, terrains); terrains = ["temp_plants_bog|gaia/flora_bush_temperate"].concat(terrains, terrains); terrains = ["temp_dirt_gravel_plants|gaia/geology_metal_temperate", "temp_dirt_gravel_plants|gaia/geology_stone_temperate", "temp_plants_bog|gaia/fauna_rabbit"].concat(terrains, terrains); terrains = ["temp_plants_bog_aut|gaia/flora_tree_dead"].concat(terrains, terrains); -textueByHeight.push({"upperHeightLimit": waterHeightAdjusted + 1/6 * (heightRange.max - waterHeightAdjusted), "terrain": terrains}); +textueByHeight.push({"upperHeightLimit": heightSeaGroundAdjusted + 1/6 * (heightRange.max - heightSeaGroundAdjusted), "terrain": terrains}); // Juicy grass near bog -textueByHeight.push({"upperHeightLimit": waterHeightAdjusted + 2/6 * (heightRange.max - waterHeightAdjusted), +textueByHeight.push({"upperHeightLimit": heightSeaGroundAdjusted + 2/6 * (heightRange.max - heightSeaGroundAdjusted), "terrain": ["temp_grass", "temp_grass_d", "temp_grass_long_b", "temp_grass_plants"]}); // Medium level grass // var testActor = "actor|geology/decal_stone_medit_a.xml"; -textueByHeight.push({"upperHeightLimit": waterHeightAdjusted + 3/6 * (heightRange.max - waterHeightAdjusted), +textueByHeight.push({"upperHeightLimit": heightSeaGroundAdjusted + 3/6 * (heightRange.max - heightSeaGroundAdjusted), "terrain": ["temp_grass", "temp_grass_b", "temp_grass_c", "temp_grass_mossy"]}); // Long grass near forest border -textueByHeight.push({"upperHeightLimit": waterHeightAdjusted + 4/6 * (heightRange.max - waterHeightAdjusted), +textueByHeight.push({"upperHeightLimit": heightSeaGroundAdjusted + 4/6 * (heightRange.max - heightSeaGroundAdjusted), "terrain": ["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"]}); // Forest border (With wood/food plants/deer/rabits) var terrains = ["temp_grass_plants|gaia/flora_tree_euro_beech", "temp_grass_mossy|gaia/flora_tree_poplar", "temp_grass_mossy|gaia/flora_tree_poplar_lombardy", "temp_grass_long|gaia/flora_bush_temperate", "temp_mud_plants|gaia/flora_bush_temperate", "temp_mud_plants|gaia/flora_bush_badlands", "temp_grass_long|gaia/flora_tree_apple", "temp_grass_clovers|gaia/flora_bush_berry", "temp_grass_clovers_2|gaia/flora_bush_grapes", "temp_grass_plants|gaia/fauna_deer", "temp_grass_long_b|gaia/fauna_rabbit"]; var numTerrains = terrains.length; for (var i = 0; i < numTerrains; i++) terrains.push("temp_grass_plants"); -textueByHeight.push({"upperHeightLimit": waterHeightAdjusted + 5/6 * (heightRange.max - waterHeightAdjusted), "terrain": terrains}); +textueByHeight.push({"upperHeightLimit": heightSeaGroundAdjusted + 5/6 * (heightRange.max - heightSeaGroundAdjusted), "terrain": terrains}); // Unpassable woods -textueByHeight.push({"upperHeightLimit": waterHeightAdjusted + 6/6 * (heightRange.max - waterHeightAdjusted), +textueByHeight.push({"upperHeightLimit": heightSeaGroundAdjusted + 6/6 * (heightRange.max - heightSeaGroundAdjusted), "terrain": ["temp_grass_mossy|gaia/flora_tree_oak", "temp_forestfloor_pine|gaia/flora_tree_pine", "temp_grass_mossy|gaia/flora_tree_oak", "temp_forestfloor_pine|gaia/flora_tree_pine", "temp_mud_plants|gaia/flora_tree_dead", "temp_plants_bog|gaia/flora_tree_oak_large", "temp_dirt_gravel_plants|gaia/flora_tree_aleppo_pine", "temp_forestfloor_autumn|gaia/flora_tree_carob"]}); var minTerrainDistToBorder = 3; Engine.SetProgress(5); // - Generate Heightmap // - Search valid start position tiles // - Choose a good start position derivation (largest distance between closest players) // - Restart the loop if start positions are invalid or two players are to close to each other var goodStartPositionsFound = false; var minDistBetweenPlayers = 16 + mapSize / 16; // Don't set this higher than 25 for tiny maps! It will take forever with 8 players! var enoughTiles = false; var tries = 0; var lowerHeightLimit = textueByHeight[3].upperHeightLimit; var upperHeightLimit = textueByHeight[6].upperHeightLimit; while (!goodStartPositionsFound) { tries++; log("Starting giant while loop try " + tries); // Generate reliefmap var myReliefmap = clone(g_Map.height); setRandomHeightmap(heightRange.min, heightRange.max, myReliefmap); for (var i = 0; i < 50 + mapSize/4; i++) // Cycles depend on mapsize (more cycles -> bigger structures) globalSmoothHeightmap(0.8, myReliefmap); rescaleHeightmap(heightRange.min, heightRange.max, myReliefmap); setReliefmap(myReliefmap); // Find good start position tiles var possibleStartPositions = []; var neededDistance = 7; var distToBorder = 2 * neededDistance; // Has to be greater than neededDistance! Otherwise the check if low/high ground is near will fail... // Check for valid points by height for (var x = distToBorder + minTerrainDistToBorder; x < mapSize - distToBorder - minTerrainDistToBorder; x++) for (var y = distToBorder + minTerrainDistToBorder; y < mapSize - distToBorder - minTerrainDistToBorder; y++) { var actualHeight = getHeight(x, y); if (actualHeight > lowerHeightLimit && actualHeight < upperHeightLimit) { // Check for points within a valid area by height (rectangular since faster) var isPossible = true; for (var offX = - neededDistance; offX <= neededDistance; offX++) for (var offY = - neededDistance; offY <= neededDistance; offY++) { var testHeight = getHeight(x + offX, y + offY); if (testHeight <= lowerHeightLimit || testHeight >= upperHeightLimit) { isPossible = false; break; } } if (isPossible) possibleStartPositions.push([x, y]); } } // Trying to reduce the number of possible start locations... // Reduce to tiles in a circle of mapSize / 2 distance to the center (to avoid players placed in corners) var possibleStartPositionsTemp = []; for (var i = 0; i < possibleStartPositions.length; i++) { if (Math.euclidDistance2D(...possibleStartPositions[i], mapCenter.x, mapCenter.y) < mapSize / 2) possibleStartPositionsTemp.push(possibleStartPositions[i]); } possibleStartPositions = clone(possibleStartPositionsTemp); // Reduce to tiles near low and high ground (Rectangular check since faster) to make sure each player has access to all resource types. var possibleStartPositionsTemp = []; var maxDistToResources = distToBorder; // Has to be <= distToBorder! var minNumLowTiles = 10; var minNumHighTiles = 10; for (var i = 0; i < possibleStartPositions.length; i++) { var numLowTiles = 0; var numHighTiles = 0; for (var dx = - maxDistToResources; dx < maxDistToResources; dx++) { for (var dy = - maxDistToResources; dy < maxDistToResources; dy++) { var testHeight = getHeight(possibleStartPositions[i][0] + dx, possibleStartPositions[i][1] + dy); if (testHeight < lowerHeightLimit) numLowTiles++; if (testHeight > upperHeightLimit) numHighTiles++; if (numLowTiles > minNumLowTiles && numHighTiles > minNumHighTiles) break; } if (numLowTiles > minNumLowTiles && numHighTiles > minNumHighTiles) break; } if (numLowTiles > minNumLowTiles && numHighTiles > minNumHighTiles) possibleStartPositionsTemp.push(possibleStartPositions[i]); } possibleStartPositions = clone(possibleStartPositionsTemp); if(possibleStartPositions.length > numPlayers) enoughTiles = true; else { enoughTiles = false; log("possibleStartPositions.length < numPlayers, possibleStartPositions.length = " + possibleStartPositions.length + ", numPlayers = " + numPlayers); } // Find a good start position derivation if (enoughTiles) { // Get some random start location derivations. NOTE: Iterating over all possible derivations is just too much (valid points * numPlayers) var maxTries = 100000; var possibleDerivations = []; for (var i = 0; i < maxTries; i++) { var vector = []; for (var p = 0; p < numPlayers; p++) vector.push(randIntExclusive(0, possibleStartPositions.length)); possibleDerivations.push(vector); } // Choose the start location derivation with the greatest minimum distance between players var maxMinDist = 0; for (var d = 0; d < possibleDerivations.length; d++) { var minDist = 2 * mapSize; for (var p1 = 0; p1 < numPlayers - 1; p1++) { for (var p2 = p1 + 1; p2 < numPlayers; p2++) { if (p1 != p2) { minDist = Math.min(minDist, Math.euclidDistance2D(...possibleStartPositions[possibleDerivations[d][p1]], ...possibleStartPositions[possibleDerivations[d][p2]])); if (minDist < maxMinDist) break; } } if (minDist < maxMinDist) break; } if (minDist > maxMinDist) { maxMinDist = minDist; var bestDerivation = possibleDerivations[d]; } } if (maxMinDist > minDistBetweenPlayers) { goodStartPositionsFound = true; log("Exiting giant while loop after " + tries + " tries with a minimum player distance of " + maxMinDist); } else log("maxMinDist <= " + minDistBetweenPlayers + ", maxMinDist = " + maxMinDist); } } Engine.SetProgress(60); log("Painting terrain by height and add props..."); var propDensity = 1; // 1 means as determined in the loop, less for large maps as set below if (mapSize > 500) propDensity = 1/4; else if (mapSize > 400) propDensity = 3/4; for(var x = minTerrainDistToBorder; x < mapSize - minTerrainDistToBorder; x++) { for (var y = minTerrainDistToBorder; y < mapSize - minTerrainDistToBorder; y++) { var textureMinHeight = heightRange.min; for (var i = 0; i < textueByHeight.length; i++) { if (getHeight(x, y) >= textureMinHeight && getHeight(x, y) <= textueByHeight[i].upperHeightLimit) { createTerrain(textueByHeight[i].terrain).place(x, y); // Add some props at... if (i == 0) // ...deep water { if (randBool(propDensity / 100)) placeObject(x, y, "actor|props/flora/pond_lillies_large.xml", 0, randomAngle()); else if (randBool(propDensity / 40)) placeObject(x, y, "actor|props/flora/water_lillies.xml", 0, randomAngle()); } if (i == 1) // ...medium water (with fish) { if (randBool(propDensity / 200)) placeObject(x, y, "actor|props/flora/pond_lillies_large.xml", 0, randomAngle()); else if (randBool(propDensity / 100)) placeObject(x, y, "actor|props/flora/water_lillies.xml", 0, randomAngle()); } if (i == 2) // ...low water/mud { if (randBool(propDensity / 200)) placeObject(x, y, "actor|props/flora/water_log.xml", 0, randomAngle()); else if (randBool(propDensity / 100)) placeObject(x, y, "actor|props/flora/water_lillies.xml", 0, randomAngle()); else if (randBool(propDensity / 40)) placeObject(x, y, "actor|geology/highland_c.xml", 0, randomAngle()); else if (randBool(propDensity / 20)) placeObject(x, y, "actor|props/flora/reeds_pond_lush_b.xml", 0, randomAngle()); else if (randBool(propDensity / 10)) placeObject(x, y, "actor|props/flora/reeds_pond_lush_a.xml", 0, randomAngle()); } if (i == 3) // ...water suroundings/bog { if (randBool(propDensity / 200)) placeObject(x, y, "actor|props/flora/water_log.xml", 0, randomAngle()); else if (randBool(propDensity / 100)) placeObject(x, y, "actor|geology/highland_c.xml", 0, randomAngle()); else if (randBool(propDensity / 40)) placeObject(x, y, "actor|props/flora/reeds_pond_lush_a.xml", 0, randomAngle()); } if (i == 4) // ...low height grass { if (randBool(propDensity / 800)) placeObject(x, y, "actor|props/flora/grass_field_flowering_tall.xml", 0, randomAngle()); else if (randBool(propDensity / 400)) placeObject(x, y, "actor|geology/gray_rock1.xml", 0, randomAngle()); else if (randBool(propDensity / 200)) placeObject(x, y, "actor|props/flora/bush_tempe_sm_lush.xml", 0, randomAngle()); else if (randBool(propDensity / 100)) placeObject(x, y, "actor|props/flora/bush_tempe_b.xml", 0, randomAngle()); else if (randBool(propDensity / 40)) placeObject(x, y, "actor|props/flora/grass_soft_small_tall.xml", 0, randomAngle()); } if (i == 5) // ...medium height grass { if (randBool(propDensity / 800)) placeObject(x, y, "actor|geology/decal_stone_medit_a.xml", 0, randomAngle()); else if (randBool(propDensity / 400)) placeObject(x, y, "actor|props/flora/decals_flowers_daisies.xml", 0, randomAngle()); else if (randBool(propDensity / 200)) placeObject(x, y, "actor|props/flora/bush_tempe_underbrush.xml", 0, randomAngle()); else if (randBool(propDensity / 100)) placeObject(x, y, "actor|props/flora/grass_soft_small_tall.xml", 0, randomAngle()); else if (randBool(propDensity / 40)) placeObject(x, y, "actor|props/flora/grass_temp_field.xml", 0, randomAngle()); } if (i == 6) // ...high height grass { if (randBool(propDensity / 400)) placeObject(x, y, "actor|geology/stone_granite_boulder.xml", 0, randomAngle()); else if (randBool(propDensity / 200)) placeObject(x, y, "actor|props/flora/foliagebush.xml", 0, randomAngle()); else if (randBool(propDensity / 100)) placeObject(x, y, "actor|props/flora/bush_tempe_underbrush.xml", 0, randomAngle()); else if (randBool(propDensity / 40)) placeObject(x, y, "actor|props/flora/grass_soft_small_tall.xml", 0, randomAngle()); else if (randBool(propDensity / 20)) placeObject(x, y, "actor|props/flora/ferns.xml", 0, randomAngle()); } if (i == 7) // ...forest border (with wood/food plants/deer/rabits) { if (randBool(propDensity / 400)) placeObject(x, y, "actor|geology/highland_c.xml", 0, randomAngle()); else if (randBool(propDensity / 200)) placeObject(x, y, "actor|props/flora/bush_tempe_a.xml", 0, randomAngle()); else if (randBool(propDensity / 100)) placeObject(x, y, "actor|props/flora/ferns.xml", 0, randomAngle()); else if (randBool(propDensity / 40)) placeObject(x, y, "actor|props/flora/grass_soft_tuft_a.xml", 0, randomAngle()); } if (i == 8) // ...woods { if (randBool(propDensity / 200)) placeObject(x, y, "actor|geology/highland2_moss.xml", 0, randomAngle()); else if (randBool(propDensity / 100)) placeObject(x, y, "actor|props/flora/grass_soft_tuft_a.xml", 0, randomAngle()); else if (randBool(propDensity / 40)) placeObject(x, y, "actor|props/flora/ferns.xml", 0, randomAngle()); } break; } else textureMinHeight = textueByHeight[i].upperHeightLimit; } } } Engine.SetProgress(90); if (isNomad()) placePlayersNomad(createTileClass(), new HeightConstraint(lowerHeightLimit, upperHeightLimit)); else { log("Placing players and starting resources..."); let playerIDs = sortAllPlayers(); let resourceDistance = 8; let resourceSpacing = 1; let resourceCount = 4; for (let i = 0; i < numPlayers; ++i) { let playerPos = new Vector2D(possibleStartPositions[bestDerivation[i]][0], possibleStartPositions[bestDerivation[i]][1]); placeCivDefaultStartingEntities(playerPos, playerIDs[i], false); for (let j = 1; j <= 4; ++j) { let uAngle = BUILDING_ORIENTATION - Math.PI * (2-j) / 2; for (let k = 0; k < resourceCount; ++k) { let pos = Vector2D.sum([ playerPos, new Vector2D(resourceDistance, 0).rotate(-uAngle), new Vector2D(k * resourceSpacing, 0).rotate(-uAngle - Math.PI/2), new Vector2D(-0.75 * resourceSpacing * Math.floor(resourceCount / 2), 0).rotate(-uAngle - Math.PI/2) ]); placeObject(pos.x, pos.y, j % 2 ? "gaia/flora_tree_cypress" : "gaia/flora_bush_berry", 0, randomAngle()); } } } } ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/belgian_uplands.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/belgian_uplands.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/belgian_uplands.json (revision 20904) @@ -1,14 +1,13 @@ { "settings" : { "Name" : "Belgian Uplands", "Script" : "belgian_uplands.js", "Description" : "An experimental map with its heightmap generated by erosion to look more natural. Not all seeds will be fair though! Tiny maps with 8 players may take a while to generate.", "DisabledTemplates": [ "structures/ptol_lighthouse" ], "CircularMap" : false, "BaseTerrain" : ["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"], - "BaseHeight" : 0, "Preview" : "belgian_uplands.png" } } Index: ps/trunk/binaries/data/mods/public/maps/random/botswanan_haven.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/botswanan_haven.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/botswanan_haven.js (revision 20904) @@ -1,390 +1,396 @@ Engine.LoadLibrary("rmgen"); 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/flora_bush_temperate"; const oBaobab = "gaia/flora_tree_baobab"; const oToona = "gaia/flora_tree_toona"; const oBerryBush = "gaia/flora_bush_berry"; const oGazelle = "gaia/fauna_gazelle"; const oZebra = "gaia/fauna_zebra"; const oWildebeest = "gaia/fauna_wildebeest"; const oLion = "gaia/fauna_lion"; const oRhino = "gaia/fauna_rhino"; const oCrocodile = "gaia/fauna_crocodile"; 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/geology_stonemine_temperate_quarry"; const oStoneSmall = "gaia/geology_stone_savanna_small"; const oMetalLarge = "gaia/geology_metal_savanna_slabs"; 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"; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightMarsh = -2; +const heightOffsetBump = 1; +const heightLand = 3; +const heightHill = 15; +const heightOffsetBump = 2; + +InitMap(heightLand, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clForest = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tCityTile, "innerTerrain": tCityTile }, "Chicken": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oBaobab }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(15); log("Creating bumps..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.6, 0.1, 1), - new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), avoidClasses(clPlayer, 13), scaleByMapSize(300, 800)); 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, 15, 2), + new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), paintClass(clHill) ], avoidClasses(clPlayer, 20, clHill, 15, clWater, 0), scaleByMapSize(1, 4) * numPlayers * 3); 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, -2, 3), + new SmoothElevationPainter(ELEVATION_SET, hMarsh, 3), paintClass(clWater) ], avoidClasses(clPlayer, 25, clWater, Math.round(scaleByMapSize(7, 16) * randFloat(0.8, 1.35))), scaleByMapSize(4, 20)); 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); log("Creating bumps..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1), - new SmoothElevationPainter(ELEVATION_MODIFY, 1, 2), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), stayClasses(clWater, 2), scaleByMapSize(50, 100)); 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, 1), [ new LayeredPainter([tGrassA, tGrassB, tMud], [1, 1]), paintClass(clDirt) ], avoidClasses(clWater, 1, clHill, 0, clDirt, 5, clPlayer, 8), scaleByMapSize(15, 45)); Engine.SetProgress(50); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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); 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, 1, clRock, 1), clForest, scaleByMapSize(60, 500)); Engine.SetProgress(85); 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); 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); 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); 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); 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); 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); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/botswanan_haven.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/botswanan_haven.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/botswanan_haven.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "Botswanan Haven", "Script" : "botswanan_haven.js", "Description" : "Botswanan Africa during the wet season, a land which was arid and inhospitable just weeks before has come to life totally transformed. Herds of zebras graze amid the tall, lush grasses in which lions lie waiting, while in the shallow pools lurk fearsome crocodiles.", "BaseTerrain" : ["savanna_grass_b_wetseason"], - "BaseHeight" : 3, "Keywords": [], "CircularMap" : true, "Preview" : "botswanan_haven.png" } } Index: ps/trunk/binaries/data/mods/public/maps/random/caledonian_meadows.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/caledonian_meadows.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/caledonian_meadows.js (revision 20904) @@ -1,451 +1,451 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmbiome"); Engine.LoadLibrary("heightmap"); -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +InitMap(0, g_MapSettings.BaseTerrain); /** * Drags a path to a target height smoothing it at the edges and return some points along the path. */ function placeRandomPathToHeight( start, target, targetHeight, tileClass = undefined, texture = "road_rome_a", width = 10, distance = 4, strength = 0.08, heightmap = g_Map.height) { let pathPoints = []; let position = clone(start); while (true) { rectangularSmoothToHeight(position, width, width, targetHeight, strength, heightmap); if (texture) { let painters = [new TerrainPainter(texture)]; if (tileClass !== undefined) painters.push(paintClass(tileClass)); createArea( new ClumpPlacer(0.3 * Math.square(width), 1, 1, 1, Math.floor(position.x), Math.floor(position.y)), painters); } pathPoints.push({ "x": position.x, "y": position.y, "dist": distance }); // Check for distance to target and setup for next loop if needed if (Math.euclidDistance2D(position.x, position.y, target.x, target.y) < distance / 2) break; let angleToTarget = getAngle(position.x, position.y, target.x, target.y); let angleOff = randFloat(-1, 1) * Math.PI / 2; position.x += distance * Math.cos(angleToTarget + angleOff); position.y += distance * Math.sin(angleToTarget + angleOff); } return pathPoints; } /** * Design resource spots */ // Mines let decorations = [ "actor|geology/gray1.xml", "actor|geology/gray_rock1.xml", "actor|geology/highland1.xml", "actor|geology/highland2.xml", "actor|geology/highland3.xml", "actor|geology/highland_c.xml", "actor|geology/highland_d.xml", "actor|geology/highland_e.xml", "actor|props/flora/bush.xml", "actor|props/flora/bush_dry_a.xml", "actor|props/flora/bush_highlands.xml", "actor|props/flora/bush_tempe_a.xml", "actor|props/flora/bush_tempe_b.xml", "actor|props/flora/ferns.xml" ]; function placeMine(point, centerEntity) { placeObject(point.x, point.y, centerEntity, 0, randomAngle()); let quantity = randIntInclusive(11, 23); 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); placeObject(point.x + dist * Math.cos(angle), point.y + dist * Math.sin(angle), pickRandom(decorations), 0, randomAngle()); } } // Food, fences with domestic animals g_WallStyles.other = { "overlap": 0, "fence": readyWallElement("other/fence_long", "gaia"), "fence_short": readyWallElement("other/fence_short", "gaia"), "bench": { "angle": Math.PI / 2, "length": 1.5, "indent": 0, "bend": 0, "templateName": "other/bench" }, "sheep": { "angle": 0, "length": 0, "indent": 0.75, "bend": 0, "templateName": "gaia/fauna_sheep" }, "foodBin": { "angle": Math.PI / 2, "length": 1.5, "indent": 0, "bend": 0, "templateName": "gaia/special_treasure_food_bin" }, "farmstead": { "angle": Math.PI, "length": 0, "indent": -3, "bend": 0, "templateName": "structures/brit_farmstead" } }; let fences = [ new Fortress("fence", [ "foodBin", "farmstead", "bench", "turn_0.25", "sheep", "turn_0.25", "fence", "turn_0.25", "sheep", "turn_0.25", "fence", "turn_0.25", "sheep", "turn_0.25", "fence" ]), new Fortress("fence", [ "foodBin", "farmstead", "fence", "turn_0.25", "sheep", "turn_0.25", "fence", "turn_0.25", "sheep", "turn_0.25", "bench", "sheep", "fence", "turn_0.25", "sheep", "turn_0.25", "fence" ]), new Fortress("fence", [ "foodBin", "farmstead", "turn_0.5", "bench", "turn_-0.5", "fence_short", "turn_0.25", "sheep", "turn_0.25", "fence", "turn_0.25", "sheep", "turn_0.25", "fence", "turn_0.25", "sheep", "turn_0.25", "fence_short", "sheep", "fence" ]), new Fortress("fence", [ "foodBin", "farmstead", "turn_0.5", "fence_short", "turn_-0.5", "bench", "turn_0.25", "sheep", "turn_0.25", "fence", "turn_0.25", "sheep", "turn_0.25", "fence", "turn_0.25", "sheep", "turn_0.25", "fence_short", "sheep", "fence" ]), new Fortress("fence", [ "foodBin", "farmstead", "fence", "turn_0.25", "sheep", "turn_0.25", "bench", "sheep", "fence", "turn_0.25", "sheep", "turn_0.25", "fence_short", "sheep", "fence", "turn_0.25", "sheep", "turn_0.25", "fence_short", "sheep", "fence" ]) ]; let num = fences.length; for (let i = 0; i < num; ++i) fences.push(new Fortress("fence", clone(fences[i].wall).reverse())); // Groves, only Wood let groveEntities = ["gaia/flora_bush_temperate", "gaia/flora_tree_euro_beech"]; let groveActors = [ "actor|geology/highland1_moss.xml", "actor|geology/highland2_moss.xml", "actor|props/flora/bush.xml", "actor|props/flora/bush_dry_a.xml", "actor|props/flora/bush_highlands.xml", "actor|props/flora/bush_tempe_a.xml", "actor|props/flora/bush_tempe_b.xml", "actor|props/flora/ferns.xml" ]; let clGrove = createTileClass(); function placeGrove(point) { placeObject(point.x, point.y, pickRandom(["structures/gaul_outpost", "gaia/flora_tree_oak_new"]), 0, 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 x = point.x + dist * Math.cos(angle); let y = point.y + dist * Math.sin(angle); placeObject(x, y, pickRandom(objectList), 0, randomAngle()); createArea(new ClumpPlacer(5, 1, 1, 1, Math.floor(x), Math.floor(y)), [new TerrainPainter("temp_grass_plants"), paintClass(clGrove)]); } } // Camps with fire and gold treasure function placeCamp(point, centerEntity = "actor|props/special/eyecandy/campfire.xml", otherEntities = ["gaia/special_treasure_metal", "gaia/special_treasure_standing_stone", "units/brit_infantry_slinger_b", "units/brit_infantry_javelinist_b", "units/gaul_infantry_slinger_b", "units/gaul_infantry_javelinist_b", "units/gaul_champion_fanatic", "actor|props/special/common/waypoint_flag.xml", "actor|props/special/eyecandy/barrel_a.xml", "actor|props/special/eyecandy/basket_celt_a.xml", "actor|props/special/eyecandy/crate_a.xml", "actor|props/special/eyecandy/dummy_a.xml", "actor|props/special/eyecandy/handcart_1.xml", "actor|props/special/eyecandy/handcart_1_broken.xml", "actor|props/special/eyecandy/sack_1.xml", "actor|props/special/eyecandy/sack_1_rough.xml" ] ) { placeObject(point.x, point.y, centerEntity, 0, 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); placeObject(point.x + dist * Math.cos(angle), point.y + dist * Math.sin(angle), pickRandom(otherEntities), 0, randomAngle()); } } function placeStartLocationResources(point, foodEntities = ["gaia/flora_bush_berry", "gaia/fauna_chicken", "gaia/fauna_chicken"]) { let currentAngle = randomAngle(); // Stone and chicken let dAngle = 4/9 * Math.PI; let angle = currentAngle + randFloat(dAngle / 4, 3 * dAngle / 4); let dist = 12; let x = point.x + dist * Math.cos(angle); let y = point.y + dist * Math.sin(angle); placeMine({ "x": x, "y": y }, "gaia/geology_stonemine_temperate_quarry"); currentAngle += dAngle; // Wood let quantity = 80; dAngle = 2 * Math.PI / quantity / 3; for (let i = 0; i < quantity; ++i) { angle = currentAngle + randFloat(0, dAngle); dist = randFloat(10, 15); let objectList = groveEntities; if (i % 2 == 0) objectList = groveActors; x = point.x + dist * Math.cos(angle); y = point.y + dist * Math.sin(angle); placeObject(x, y, pickRandom(objectList), 0, randomAngle()); createArea(new ClumpPlacer(5, 1, 1, 1, Math.floor(x), Math.floor(y)), [new TerrainPainter("temp_grass_plants"), paintClass(clGrove)]); currentAngle += dAngle; } // Metal and chicken dAngle = 2 * Math.PI * 2 / 9; angle = currentAngle + randFloat(dAngle / 4, 3 * dAngle / 4); dist = 13; x = point.x + dist * Math.cos(angle); y = point.y + dist * Math.sin(angle); placeMine({ "x": x, "y": y }, "gaia/geology_metal_temperate_slabs"); currentAngle += dAngle; // Berries quantity = 15; dAngle = 2 * Math.PI / quantity * 2 / 9; for (let i = 0; i < quantity; ++i) { angle = currentAngle + randFloat(0, dAngle); dist = randFloat(10, 15); x = point.x + dist * Math.cos(angle); y = point.y + dist * Math.sin(angle); placeObject(x, y, pickRandom(foodEntities), 0, randomAngle()); currentAngle += dAngle; } } /** * Environment settings */ setBiome("alpine"); g_Environment.Fog.FogColor = { "r": 0.8, "g": 0.8, "b": 0.8, "a": 0.01 }; g_Environment.Water.WaterBody.Colour = { "r" : 0.3, "g" : 0.05, "b" : 0.1, "a" : 0.1 }; g_Environment.Water.WaterBody.Murkiness = 0.4; /** * Base terrain shape generation and settings */ let heightScale = (g_Map.size + 256) / 768 / 4; 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 waterHeight = -MIN_HEIGHT + heightRange.min + averageWaterCoverage * (heightRange.max - heightRange.min); // Water height in environment and the engine -let waterHeightAdjusted = waterHeight + MIN_HEIGHT; // Water height in RMGEN -setWaterHeight(waterHeight); +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 in RMGEN +setWaterHeight(heightSeaGround); log("Generating terrain using diamon-square..."); let medH = (heightRange.min + heightRange.max) / 2; let initialHeightmap = [[medH, medH], [medH, medH]]; setBaseTerrainDiamondSquare(heightRange.min, heightRange.max, initialHeightmap, 0.8); log("Apply erosion..."); for (let i = 0; i < 5; ++i) splashErodeMap(0.1); rescaleHeightmap(heightRange.min, heightRange.max); Engine.SetProgress(25); let heighLimits = [ - heightRange.min + 1/3 * (waterHeightAdjusted - heightRange.min), // 0 Deep water - heightRange.min + 2/3 * (waterHeightAdjusted - heightRange.min), // 1 Medium Water - heightRange.min + (waterHeightAdjusted - heightRange.min), // 2 Shallow water - waterHeightAdjusted + 1/8 * (heightRange.max - waterHeightAdjusted), // 3 Shore - waterHeightAdjusted + 2/8 * (heightRange.max - waterHeightAdjusted), // 4 Low ground - waterHeightAdjusted + 3/8 * (heightRange.max - waterHeightAdjusted), // 5 Player and path height - waterHeightAdjusted + 4/8 * (heightRange.max - waterHeightAdjusted), // 6 High ground - waterHeightAdjusted + 5/8 * (heightRange.max - waterHeightAdjusted), // 7 Lower forest border - waterHeightAdjusted + 6/8 * (heightRange.max - waterHeightAdjusted), // 8 Forest - waterHeightAdjusted + 7/8 * (heightRange.max - waterHeightAdjusted), // 9 Upper forest border - waterHeightAdjusted + (heightRange.max - waterHeightAdjusted)]; // 10 Hilltop + heightRange.min + 1/3 * (heightSeaGroundAdjusted - heightRange.min), // 0 Deep water + heightRange.min + 2/3 * (heightSeaGroundAdjusted - heightRange.min), // 1 Medium Water + heightRange.min + (heightSeaGroundAdjusted - heightRange.min), // 2 Shallow water + heightSeaGroundAdjusted + 1/8 * (heightRange.max - heightSeaGroundAdjusted), // 3 Shore + heightSeaGroundAdjusted + 2/8 * (heightRange.max - heightSeaGroundAdjusted), // 4 Low ground + heightSeaGroundAdjusted + 3/8 * (heightRange.max - heightSeaGroundAdjusted), // 5 Player and path height + heightSeaGroundAdjusted + 4/8 * (heightRange.max - heightSeaGroundAdjusted), // 6 High ground + heightSeaGroundAdjusted + 5/8 * (heightRange.max - heightSeaGroundAdjusted), // 7 Lower forest border + heightSeaGroundAdjusted + 6/8 * (heightRange.max - heightSeaGroundAdjusted), // 8 Forest + heightSeaGroundAdjusted + 7/8 * (heightRange.max - heightSeaGroundAdjusted), // 9 Upper forest border + heightSeaGroundAdjusted + (heightRange.max - heightSeaGroundAdjusted)]; // 10 Hilltop let playerHeight = (heighLimits[4] + heighLimits[5]) / 2; // Average player height log("Determining height-dependent biome..."); // Texture and actor presets let myBiome = []; myBiome.push({ // 0 Deep water "texture": ["shoreline_stoney_a"], "actor": [["gaia/fauna_fish", "actor|geology/stone_granite_boulder.xml"], 0.02], "textureHS": ["alpine_mountainside"], "actorHS": [["gaia/fauna_fish"], 0.1] }); myBiome.push({ // 1 Medium Water "texture": ["shoreline_stoney_a", "alpine_shore_rocks"], "actor": [["actor|geology/stone_granite_boulder.xml", "actor|geology/stone_granite_med.xml"], 0.03], "textureHS": ["alpine_mountainside"], "actorHS": [["actor|geology/stone_granite_boulder.xml", "actor|geology/stone_granite_med.xml"], 0.0] }); myBiome.push({ // 2 Shallow water "texture": ["alpine_shore_rocks"], "actor": [["actor|props/flora/reeds_pond_dry.xml", "actor|geology/stone_granite_large.xml", "actor|geology/stone_granite_med.xml", "actor|props/flora/reeds_pond_lush_b.xml"], 0.2], "textureHS": ["alpine_mountainside"], "actorHS": [["actor|props/flora/reeds_pond_dry.xml", "actor|geology/stone_granite_med.xml"], 0.1] }); myBiome.push({ // 3 Shore "texture": ["alpine_shore_rocks_grass_50", "alpine_grass_rocky"], "actor": [["gaia/flora_tree_pine", "gaia/flora_bush_badlands", "actor|geology/highland1_moss.xml", "actor|props/flora/grass_soft_tuft_a.xml", "actor|props/flora/bush.xml"], 0.3], "textureHS": ["alpine_mountainside"], "actorHS": [["actor|props/flora/grass_soft_tuft_a.xml"], 0.1] }); myBiome.push({ // 4 Low ground "texture": ["alpine_dirt_grass_50", "alpine_grass_rocky"], "actor": [["actor|geology/stone_granite_med.xml", "actor|props/flora/grass_soft_tuft_a.xml", "actor|props/flora/bush.xml", "actor|props/flora/grass_medit_flowering_tall.xml"], 0.2], "textureHS": ["alpine_grass_rocky"], "actorHS": [["actor|geology/stone_granite_med.xml", "actor|props/flora/grass_soft_tuft_a.xml"], 0.1] }); myBiome.push({ // 5 Player and path height "texture": ["new_alpine_grass_c", "new_alpine_grass_b", "new_alpine_grass_d"], "actor": [["actor|geology/stone_granite_small.xml", "actor|props/flora/grass_soft_small.xml", "actor|props/flora/grass_medit_flowering_tall.xml"], 0.2], "textureHS": ["alpine_grass_rocky"], "actorHS": [["actor|geology/stone_granite_small.xml", "actor|props/flora/grass_soft_small.xml"], 0.1] }); myBiome.push({ // 6 High ground "texture": ["new_alpine_grass_a", "alpine_grass_rocky"], "actor": [["actor|geology/stone_granite_med.xml", "actor|props/flora/grass_tufts_a.xml", "actor|props/flora/bush_highlands.xml", "actor|props/flora/grass_medit_flowering_tall.xml"], 0.2], "textureHS": ["alpine_grass_rocky"], "actorHS": [["actor|geology/stone_granite_med.xml", "actor|props/flora/grass_tufts_a.xml"], 0.1] }); myBiome.push({ // 7 Lower forest border "texture": ["new_alpine_grass_mossy", "alpine_grass_rocky"], "actor": [["gaia/flora_tree_pine", "gaia/flora_tree_oak", "actor|props/flora/grass_tufts_a.xml", "gaia/flora_bush_berry", "actor|geology/highland2_moss.xml", "gaia/fauna_goat", "actor|props/flora/bush_tempe_underbrush.xml"], 0.3], "textureHS": ["alpine_cliff_c"], "actorHS": [["actor|props/flora/grass_tufts_a.xml", "actor|geology/highland2_moss.xml"], 0.1] }); myBiome.push({ // 8 Forest "texture": ["alpine_forrestfloor"], "actor": [["gaia/flora_tree_pine", "gaia/flora_tree_pine", "gaia/flora_tree_pine", "gaia/flora_tree_pine", "actor|geology/highland2_moss.xml", "actor|props/flora/bush_highlands.xml"], 0.5], "textureHS": ["alpine_cliff_c"], "actorHS": [["actor|geology/highland2_moss.xml", "actor|geology/stone_granite_med.xml"], 0.1] }); myBiome.push({ // 9 Upper forest border "texture": ["alpine_forrestfloor_snow", "new_alpine_grass_dirt_a"], "actor": [["gaia/flora_tree_pine", "actor|geology/snow1.xml"], 0.3], "textureHS": ["alpine_cliff_b"], "actorHS": [["actor|geology/stone_granite_med.xml", "actor|geology/snow1.xml"], 0.1] }); myBiome.push({ // 10 Hilltop "texture": ["alpine_cliff_a", "alpine_cliff_snow"], "actor": [["actor|geology/highland1.xml"], 0.05], "textureHS": ["alpine_cliff_c"], "actorHS": [["actor|geology/highland1.xml"], 0.0] }); let [playerIDs, startLocations] = sortPlayersByLocation(getStartLocationsByHeightmap({ "min": heighLimits[4], "max": heighLimits[5] }, 1000, 30)); Engine.SetProgress(30); log("Smooth player locations..."); for (let p = 0; p < playerIDs.length; ++p) rectangularSmoothToHeight(startLocations[p], 35, 35, playerHeight, 0.7); log("Creating paths..."); let tchm = getTileCenteredHeightmap(); // Calculate tileCenteredHeightMap (This has nothing to to with TILE_CENTERED_HEIGHT_MAP which should be false) let pathPoints = []; let clPath = createTileClass(); for (let i = 0; i < startLocations.length; ++i) { let start = startLocations[i]; let target = startLocations[(i + 1) % startLocations.length]; pathPoints = pathPoints.concat(placeRandomPathToHeight(start, target, playerHeight, clPath)); } Engine.SetProgress(45); log("Determining resource locations..."); let avoidPoints = clone(startLocations); for (let i = 0; i < avoidPoints.length; ++i) avoidPoints[i].dist = 30; let resourceSpots = getPointsByHeight({ "min": (heighLimits[3] + heighLimits[4]) / 2, "max": (heighLimits[5] + heighLimits[6]) / 2 }, avoidPoints, clPath); Engine.SetProgress(55); /** * Divide tiles in areas by height and avoid paths */ let areas = []; for (let h = 0; h < heighLimits.length; ++h) areas.push([]); for (let x = 0; x < tchm.length; ++x) for (let y = 0; y < tchm[0].length; ++y) { if (g_Map.tileClasses[clPath].inclusionCount[x][y] > 0) // Avoid paths continue; 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({ "x": x, "y": y }); break; } else minHeight = heighLimits[h]; } } /** * Get max slope of each area */ let slopeMap = getSlopeMap(); let minSlope = []; let maxSlope = []; for (let h = 0; h < heighLimits.length; ++h) { minSlope[h] = Infinity; maxSlope[h] = 0; for (let t = 0; t < areas[h].length; ++t) { let x = areas[h][t].x; let y = areas[h][t].y; let slope = slopeMap[x][y]; if (slope > maxSlope[h]) maxSlope[h] = slope; if (slope < minSlope[h]) minSlope[h] = slope; } } log("Painting areas by height and slope..."); for (let h = 0; h < heighLimits.length; ++h) for (let t = 0; t < areas[h].length; ++t) { let x = areas[h][t].x; let y = areas[h][t].y; let actor = undefined; let texture = pickRandom(myBiome[h].texture); if (slopeMap[x][y] < 0.4 * (minSlope[h] + maxSlope[h])) { if (randBool(myBiome[h].actor[1])) actor = pickRandom(myBiome[h].actor[0]); } else { texture = pickRandom(myBiome[h].textureHS); if (randBool(myBiome[h].actorHS[1])) actor = pickRandom(myBiome[h].actorHS[0]); } g_Map.texture[x][y] = g_Map.getTextureID(texture); if (actor) placeObject(randFloat(x, x + 1), randFloat(y, y + 1), actor, 0, randomAngle()); } Engine.SetProgress(80); log("Placing players..."); if (isNomad()) placePlayersNomad(createTileClass(), new HeightConstraint(heighLimits[4], heighLimits[5])); else for (let p = 0; p < playerIDs.length; ++p) { let point = startLocations[p]; placeCivDefaultStartingEntities(point, playerIDs[p], true); placeStartLocationResources(startLocations[p]); } log("Placing resources, farmsteads, groves and camps..."); for (let i = 0; i < resourceSpots.length; ++i) { let choice = i % 5; if (choice == 0) placeMine(resourceSpots[i], "gaia/geology_stonemine_temperate_formation"); if (choice == 1) placeMine(resourceSpots[i], "gaia/geology_metal_temperate_slabs"); if (choice == 2) placeCustomFortress(resourceSpots[i].x, resourceSpots[i].y, pickRandom(fences), "other", 0, randomAngle()); if (choice == 3) placeGrove(resourceSpots[i]); if (choice == 4) placeCamp(resourceSpots[i]); } 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 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/cantabrian_highlands.js (revision 20904) @@ -1,278 +1,281 @@ Engine.LoadLibrary("rmgen"); 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 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 tShoreBlend = "temp_grass_plants"; const tShore = "temp_plants_bog"; const tWater = "temp_mud_a"; const oOak = "gaia/flora_tree_oak"; const oOakLarge = "gaia/flora_tree_oak_large"; const oApple = "gaia/flora_tree_apple"; const oPine = "gaia/flora_tree_pine"; const oAleppoPine = "gaia/flora_tree_aleppo_pine"; const oBerryBush = "gaia/flora_bush_berry"; const oDeer = "gaia/fauna_deer"; const oFish = "gaia/fauna_fish"; const oSheep = "gaia/fauna_sheep"; const oStoneLarge = "gaia/geology_stonemine_temperate_quarry"; const oStoneSmall = "gaia/geology_stone_temperate"; const oMetalLarge = "gaia/geology_metal_temperate_slabs"; 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/pond_lillies_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 pForestD = [tGrassDForest + TERRAIN_SEPARATOR + oOak, tGrassDForest + TERRAIN_SEPARATOR + oOakLarge, tGrassDForest]; const pForestP = [tGrassPForest + TERRAIN_SEPARATOR + oPine, tGrassPForest + TERRAIN_SEPARATOR + oAleppoPine, tGrassPForest]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightSeaGround = -7; +const heightLand = 3; +const heightHill = 20; + +InitMap(heightLand, g_MapSettings.BaseTerrain); var numPlayers = getNumPlayers(); var mapSize = getMapSize(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var playerHillRadius = defaultPlayerBaseRadius() / (isNomad() ? 1.5 : 1); -var playerHillElevation = 20; var [playerIDs, playerPosition, playerAngle] = playerPlacementCircle(fractionToTiles(0.35)); log("Creating player hills and ramps..."); for (let i = 0; i < numPlayers; ++i) { createArea( new ClumpPlacer(diskArea(playerHillRadius), 0.95, 0.6, 10, playerPosition[i].x, playerPosition[i].y), [ new LayeredPainter([tCliff, tHill], [2]), - new SmoothElevationPainter(ELEVATION_SET, playerHillElevation, 2), + new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), paintClass(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": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oOak, "count": 2 }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(10); log("Creating lakes..."); var numLakes = Math.round(scaleByMapSize(1,4) * numPlayers); var waterAreas = createAreas( new ClumpPlacer(scaleByMapSize(100, 250), 0.8, 0.1, 10), [ new LayeredPainter([tShoreBlend, tShore, tWater], [1, 1]), - new SmoothElevationPainter(ELEVATION_SET, -7, 6), + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 6), paintClass(clWater) ], avoidClasses(clPlayer, 2, clWater, 20), numLakes ); Engine.SetProgress(15); log("Creating reeds..."); var group = new SimpleGroup( [new SimpleObject(aReeds, 5,10, 0,4), new SimpleObject(aLillies, 0,1, 0,4)], true ); createObjectGroupsByAreasDeprecated(group, 0, [borderClasses(clWater, 3, 0), stayClasses(clWater, 1)], numLakes, 100, waterAreas ); Engine.SetProgress(20); log("Creating fish..."); createObjectGroupsByAreasDeprecated( 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); log("Creating hills..."); createHills([tCliff, tCliff, tHill], avoidClasses(clPlayer, 2, clWater, 5, clHill, 15), clHill, scaleByMapSize(1, 4) * numPlayers); Engine.SetProgress(35); var [forestTrees, stragglerTrees] = getTreeCounts(500, 3000, 0.7); createForests( [tGrass, tGrassDForest, tGrassPForest, pForestP, pForestD], avoidClasses(clPlayer, 1, clWater, 3, clForest, 17, clHill, 1), clForest, forestTrees); Engine.SetProgress(40); 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); 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); log("Creating stone mines..."); createMines( [ [new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], avoidClasses(clWater, 0, clForest, 1, clPlayer, 5, clRock, 10, clHill, 1), clRock); Engine.SetProgress(55); log("Creating metal mines..."); createMines( [ [new SimpleObject(oMetalLarge, 1,1, 0,4)] ], avoidClasses(clWater, 0, clForest, 1, clPlayer, 5, clMetal, 10, clRock, 5, clHill, 1), 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)] ], [ scaleByMapSize(16, 262), scaleByMapSize(8, 131), scaleByMapSize(13, 200), scaleByMapSize(13, 200), scaleByMapSize(13, 200) ], 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); setPPEffect("hdr"); setPPSaturation(0.62); setPPContrast(0.62); setPPBloom(0.3); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/canyon.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/canyon.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/canyon.js (revision 20904) @@ -1,358 +1,358 @@ Engine.LoadLibrary("rmgen"); 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/special_treasure_wood"; const oFoodTreasure = "gaia/special_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]; -InitMap(g_MapSettings.BaseHeight, tMainTerrain); +const heightLand = 3; +const heightHill = 30; + +InitMap(heightHill, tMainTerrain); var numPlayers = getNumPlayers(); var mapSize = getMapSize(); var mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clHill2 = createTileClass(); var clForest = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clLand = createTileClass(); -var landHeight = 3; -var hillHeight = 30; - var playerCanyonRadius = scaleByMapSize(18, 32); var [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); 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, 10, playerPosition[i].x, playerPosition[i].y), [ new LayeredPainter([tMainTerrain, tMainTerrain], [2]), - new SmoothElevationPainter(ELEVATION_SET, landHeight, 2), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 2), paintClass(j == 1 || isNomad() ? clLand : clPlayer) ]); log("Creating center area..."); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.16)), 0.7, 0.1, 10, mapCenter.x, mapCenter.y), [ new LayeredPainter([tMainTerrain, tMainTerrain], [3]), - new SmoothElevationPainter(ELEVATION_SET, landHeight, 3), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 3), paintClass(clLand) ]); createArea( new ClumpPlacer(150, 0.6, 0.3, 10, mapCenter.x, mapCenter.y), paintClass(clHill)); log("Creating hills..."); for (let i = 0; i < scaleByMapSize(9, 16); ++i) createArea( new PathPlacer( randIntExclusive(1, mapSize), randIntExclusive(1, mapSize), randIntExclusive(1, mapSize), randIntExclusive(1, mapSize), scaleByMapSize(11, 16), 0.4, 3 * scaleByMapSize(1, 4), 0.1, 0), [ - new SmoothElevationPainter(ELEVATION_SET, hillHeight, 3), + new SmoothElevationPainter(ELEVATION_SET, heightHill, 3), paintClass(clHill2) ], avoidClasses(clPlayer, 6, clHill2, 3, clHill, 2)); for (let g = 0; g < scaleByMapSize(5, 30); ++g) { var tx = randIntInclusive(1, mapSize - 1); var tz = randIntInclusive(1, mapSize - 1); var newarea = createArea( new ClumpPlacer(diskArea(fractionToTiles(0.06)), 0.7, 0.1, 10, tx, tz), [ new LayeredPainter([tMainTerrain, tMainTerrain], [3]), - new SmoothElevationPainter(ELEVATION_SET, landHeight, 3), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 3), paintClass(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(Math.euclidDistance2D(tx, tz, playerPosition[i].x, playerPosition[i].y)); 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(tx, tz, playerPosition[playerID].x, playerPosition[playerID].y, scaleByMapSize(11, 17), 0.4, scaleByMapSize(3, 12), 0.1, 0.1), [ new LayeredPainter([tMainTerrain, tMainTerrain], [3]), - new SmoothElevationPainter(ELEVATION_SET, landHeight, 3), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 3), paintClass(clLand) ]); } } for (let i = 0; i < numPlayers; ++i) { log("Creating path from player to center and to neighbor..."); let neighbor = i + 1 < numPlayers ? i + 1 : 0; for (let position of [playerPosition[neighbor], mapCenter]) createArea( new PathPlacer( playerPosition[i].x, playerPosition[i].y, position.x, position.y, scaleByMapSize(8, 13), 0.4, 3 * scaleByMapSize(1, 4), 0.1, 0), [ new LayeredPainter([tRoadWild, tRoad], [1]), - new SmoothElevationPainter(ELEVATION_SET, landHeight, 2), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 2), paintClass(clLand), paintClass(clHill) ]); } log("Painting center place..."); createArea( new ClumpPlacer(150, 0.6, 0.3, 10, mapCenter.x, mapCenter.y), new LayeredPainter([tRoad, tRoad], [1])); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], // PlayerTileClass already marked above "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoad, "innerTerrain": tRoad, "radius": playerCanyonRadius / 3 }, "Chicken": { }, "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); 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); 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); log("Creating stone mines..."); createMines( [ [new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], [avoidClasses(clForest, 1, clPlayer, 3, clRock, 10, clHill, 1, clHill2, 1), stayClasses(clLand, 2)], clRock); 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() == "tropic") 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 * scaleByMapSize(16, 262), 3 * scaleByMapSize(8, 131), planetm * scaleByMapSize(13, 200), planetm * scaleByMapSize(13, 200), planetm * scaleByMapSize(13, 200) ], avoidClasses(clForest, 0, clPlayer, 0, clHill, 0)); 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); log("Creating treasures..."); for (let i = 0; i < randIntInclusive(3, 8); ++i) for (let template of [oFoodTreasure, oWoodTreasure]) placeObject(mapCenter.x + randFloat(-7, 7), mapCenter.y + randFloat(-7, 7), template, 0, randomAngle()); placePlayersNomad( clPlayer, [stayClasses(clLand, 4), avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clHill2, 4, clFood, 2)]); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/continent.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/continent.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/continent.js (revision 20904) @@ -1,255 +1,258 @@ Engine.LoadLibrary("rmgen"); 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 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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightSeaGround = -5; +const heightLand = 3; + +InitMap(heightSeaGround, g_MapSettings.BaseTerrain); var numPlayers = getNumPlayers(); var mapSize = getMapSize(); var mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clLand = createTileClass(); log("Creating continent..."); createArea( new ChainPlacer( 2, Math.floor(scaleByMapSize(5, 12)), Math.floor(scaleByMapSize(60, 700)), 1, mapCenter.x, mapCenter.y, 0, [Math.floor(fractionToTiles(0.33))]), [ - new SmoothElevationPainter(ELEVATION_SET, 3, 4), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), paintClass(clLand) ]); var [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.25)); 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)), 1, playerPosition[i].x, playerPosition[i].y, 0, [Math.floor(scaleByMapSize(23, 50))]), [ - new SmoothElevationPainter(ELEVATION_SET, 3, 4), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), paintClass(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": { }, "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)); createForests( [tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2], [avoidClasses(clPlayer, 20, clForest, 17, clHill, 0, clBaseResource,2), stayClasses(clLand, 4)], clForest, forestTrees); Engine.SetProgress(50); 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); 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); log("Creating stone mines..."); createMines( [ [new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], [avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), stayClasses(clLand, 6)], clRock); log("Creating metal mines..."); createMines( [ [new SimpleObject(oMetalLarge, 1,1, 0,4)] ], [avoidClasses(clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 1), stayClasses(clLand, 6)], clMetal ); Engine.SetProgress(65); // create decoration var planetm = 1; if (currentBiome() == "tropic") 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)] ], [ scaleByMapSize(16, 262), scaleByMapSize(8, 131), planetm * scaleByMapSize(13, 200), planetm * scaleByMapSize(13, 200), planetm * scaleByMapSize(13, 200) ], [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"); 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 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/corinthian_isthmus.js (revision 20904) @@ -1,270 +1,270 @@ Engine.LoadLibrary("rmgen"); 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", "medit_grass_field_a"]; 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 tShore = "medit_sand"; const tWater = "medit_sand_wet"; const oBerryBush = "gaia/flora_bush_berry"; const oDeer = "gaia/fauna_deer"; const oFish = "gaia/fauna_fish"; const oSheep = "gaia/fauna_sheep"; const oGoat = "gaia/fauna_goat"; const oStoneLarge = "gaia/geology_stonemine_medit_quarry"; const oStoneSmall = "gaia/geology_stone_mediterranean"; const oMetalLarge = "gaia/geology_metal_mediterranean_slabs"; const oDatePalm = "gaia/flora_tree_cretan_date_palm_short"; const oSDatePalm = "gaia/flora_tree_cretan_date_palm_tall"; const oCarob = "gaia/flora_tree_carob"; const oFanPalm = "gaia/flora_tree_medit_fan_palm"; const oPoplar = "gaia/flora_tree_poplar_lombardy"; const oCypress = "gaia/flora_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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +var heightSeaGround = -4; +var heightLand = 3; + +InitMap(heightLand, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clGrass = createTileClass(); var clHill = createTileClass(); -var landHeight = getMapBaseHeight(); -var waterHeight = -4; - log("Creating the main river"); var riverAngle = randFloat(0, Math.PI); var riverWidth = scaleByMapSize(15, 70); var riverStart = new Vector2D(mapCenter.x, 0).rotateAround(riverAngle, mapCenter); var riverEnd = new Vector2D(mapCenter.x, mapSize).rotateAround(riverAngle, mapCenter); createArea( new PathPlacer(riverStart.x, riverStart.y, riverEnd.x, riverEnd.y, riverWidth, 0.2, 15 * scaleByMapSize(1, 3), 0.04, 0.01), - new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4)); + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4)); log("Creating small puddles at the map border to ensure players being separated..."); for (let point of [riverStart, riverEnd]) createArea( new ClumpPlacer(Math.floor(diskArea(riverWidth / 2)), 0.95, 0.6, 10, point.x, point.y), - new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4)); + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4)); log("Creating passage connecting the two riversides..."); var passageStart = riverStart.rotateAround(Math.PI / 2, mapCenter); var passageEnd = riverEnd.rotateAround(Math.PI / 2, mapCenter); createArea( new PathPlacer( passageStart.x, passageStart.y, passageEnd.x, passageEnd.y, scaleByMapSize(10, 30), 0.5, 3 * scaleByMapSize(1, 4), 0.1, 0.01), - new SmoothElevationPainter(ELEVATION_SET, landHeight, 4)); + new SmoothElevationPainter(ELEVATION_SET, heightLand, 4)); paintTerrainBasedOnHeight(-6, 1, 1, tWater); paintTerrainBasedOnHeight(1, 2, 1, tShore); paintTerrainBasedOnHeight(2, 5, 1, tGrass); paintTileClassBasedOnHeight(-6, 0.5, 1, clWater); placePlayerBases({ "PlayerPlacement": playerPlacementRiver(riverAngle, fractionToTiles(0.6)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "Walls": "towers", "CityPatch": { "outerTerrain": tCityPlaza, "innerTerrain": tCity }, "Chicken": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oCarob, "count": 2 }, "Decoratives": { "template": aBush1 } }); 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)); 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); 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); log("Creating stone mines..."); createMines( [ [new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], avoidClasses(clForest, 4, clPlayer, 15, clRock, 10, clWater, 4, clHill, 4), clRock); log("Creating metal mines..."); createMines( [ [new SimpleObject(oMetalLarge, 1,1, 0,4)] ], avoidClasses(clForest, 4, clPlayer, 15, clMetal, 10, clRock, 5, clWater, 4, clHill, 4), 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) ] ], [ scaleByMapSize(16, 262), 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, 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, 10, 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, 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); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); setSkySet("sunny"); setSunColor(0.917, 0.828, 0.734); setWaterColor(0, 0.501961, 1); setWaterTint(0.501961, 1, 1); setWaterWaviness(2.5); setWaterType("ocean"); setWaterMurkiness(0.49); setFogFactor(0.3); setFogThickness(0.25); setPPEffect("hdr"); setPPContrast(0.62); setPPSaturation(0.51); setPPBloom(0.12); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/corsica.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/corsica.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/corsica.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "Corsica vs Sardinia", "Script" : "corsica.js", "Description" : "The players start on two opposing islands, both with a very jagged relief that will make landing difficult.", "BaseTerrain" : ["medit_dirt", "medit_dirt_b", "medit_dirt_c"], - "BaseHeight" : -8, "Keywords": ["naval"], "Preview" : "corsica.png", "CircularMap" : false } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/danubius.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/danubius.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/danubius.js (revision 20904) @@ -1,806 +1,809 @@ Engine.LoadLibrary("rmgen"); // 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 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/flora_bush_berry"; const oDeer = "gaia/fauna_deer"; const oFish = "gaia/fauna_fish"; const oSheep = "gaia/fauna_sheep"; const oGoat = "gaia/fauna_goat"; const oWolf = "gaia/fauna_wolf"; const oHawk = "gaia/fauna_hawk"; const oRabbit = "gaia/fauna_rabbit"; const oBoar = "gaia/fauna_boar"; const oBear = "gaia/fauna_bear"; const oStoneLarge = "gaia/geology_stonemine_temperate_quarry"; const oStoneRuins = "gaia/special_ruins_standing_stone"; const oMetalLarge = "gaia/geology_metal_mediterranean_slabs"; const oApple = "gaia/flora_tree_apple"; const oAcacia = "gaia/flora_tree_acacia"; const oOak = "gaia/flora_tree_oak_aut"; const oOak2 = "gaia/flora_tree_oak_aut_new"; const oOak3 = "gaia/flora_tree_oak_dead"; const oOak4 = "gaia/flora_tree_oak"; const oPopolar = "gaia/flora_tree_poplar_lombardy"; const oBeech = "gaia/flora_tree_euro_beech_aut"; const oBeech2 = "gaia/flora_tree_euro_beech"; const oTreasures = [ "gaia/special_treasure_food_barrel", "gaia/special_treasure_food_bin", "gaia/special_treasure_stone", "gaia/special_treasure_wood", "gaia/special_treasure_metal" ]; const oCivicCenter = "structures/gaul_civil_centre"; const oHouse = "structures/gaul_house"; const oTemple = "structures/gaul_temple"; const oTavern = "structures/gaul_tavern"; const oTower = "structures/gaul_defense_tower"; const oSentryTower = "structures/gaul_sentry_tower"; const oOutpost = "structures/gaul_outpost"; const oHut = "other/celt_hut"; const oLongHouse = "other/celt_longhouse"; const oPalisadeTower = "other/palisades_rocks_watchtower"; const oTallSpikes = "other/palisades_tall_spikes"; const oAngleSpikes = "other/palisades_angle_spike"; const oFemale = "units/gaul_support_female_citizen"; const oHealer = "units/gaul_support_healer_b"; const oSkirmisher = "units/gaul_infantry_javelinist_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; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightSeaGround = -3; +const heightShore = 1; +const heightLand = 3; +const heightPath = 5; +const heightIsland = 6; + +InitMap(heightLand, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); const mapBounds = getMapBounds(); var clMiddle = createTileClass(); var clPlayer = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clLand = [createTileClass(), createTileClass()]; var clLandPatrolPoint = [createTileClass(), createTileClass()]; var clCCAttackerPatrolPoint = [createTileClass(), createTileClass()]; var clShore = [createTileClass(), createTileClass()]; var clShoreUngarrisonPoint = [createTileClass(), createTileClass()]; var clShip = createTileClass(); var clShipPatrol = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clHill = createTileClass(); var clIsland = createTileClass(); var clTreasure = createTileClass(); var clWaterLog = createTileClass(); var clGauls = createTileClass(); var clTower = createTileClass(); var clOutpost = createTileClass(); var clPath = createTileClass(); var clRitualPlace = createTileClass(); var waterWidth = fractionToTiles(0.3); -var waterHeight = -3; -var shoreHeight = 1; -var landHeight = 2; // 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, 3 * numPlayers); // Place a gallic village on small maps and larger var gallicCC = mapSize >= smallMapSize; if (gallicCC) { 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 gX = i == 0 ? mapBounds.left + gaulCityBorderDistance : mapBounds.right - gaulCityBorderDistance; let gZ = mapCenter.y; if (addCelticRitual) { // Don't position the meeting place at the center of the map let mX = i == 0 ? mapBounds.left + waterWidth : mapBounds.right - waterWidth; let mZ = mapCenter.y + fractionToTiles(randFloat(0.1, 0.4)) * (randBool() ? 1 : -1); // 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 placer = new PathPlacer( gX + gaulCityRadius * (i == 0 ? 1 : -1), gZ, mX, mZ, 4, // width 0.4, // waviness 4, // smoothness 0.2, // offset 0.05); // tapering createArea( placer, [ new LayeredPainter([tShore, tRoad, tRoad], [1, 3]), - new SmoothElevationPainter(ELEVATION_SET, 5, 4), + new SmoothElevationPainter(ELEVATION_SET, heightPath, 4), paintClass(clPath) ]); // Create the meeting place near the shoreline at the end of the path createArea( new ClumpPlacer(mRadius * mRadius * Math.PI, 0.6, 0.3, 10, mX, mZ), [ new LayeredPainter([tShore, tShore], [1]), paintClass(clPath), paintClass(clRitualPlace) ]); placeObject(mX, mZ, aCampfire, 0, randomAngle()); let femaleCount = Math.round(mRadius * 2); let maleCount = Math.round(mRadius * 3); let benchCount = Math.round(mRadius * 2); let rugCount = Math.round(mRadius * 2.5); let goatCount = Math.round(mRadius * 1.5); let femaleRadius = mRadius * 0.3; let maleRadius = mRadius * 0.4; let benchRadius = mRadius * 0.5; let rugRadius = mRadius * 0.6; let goatRadius = mRadius * 0.8; let calcBend = entCount => Math.PI * 2 / entCount; let maleBend = calcBend(maleCount); g_WallStyles.celt_ritual = { "overlap": 0, "female": { "angle": Math.PI, "length": femaleRadius, "indent": 0, "bend": calcBend(femaleCount), "templateName": oFemale }, "skirmisher": { "angle": Math.PI, "length": maleRadius, "indent": 0, "bend": maleBend, "templateName": oSkirmisher }, "healer": { "angle": Math.PI, "length": maleRadius, "indent": 0, "bend": maleBend, "templateName": oHealer }, "fanatic": { "angle": Math.PI, "length": maleRadius, "indent": 0, "bend": maleBend, "templateName": oNakedFanatic }, "bench": { "angle": Math.PI / 2, "length": benchRadius, "indent": 0, "bend": calcBend(benchCount), "templateName": aBench }, "rug": { "angle": 0, "length": rugRadius, "indent": 0, "bend": calcBend(rugCount), "templateName": aRug }, "goat": { "angle": Math.PI, "length": goatRadius, "indent": 0, "bend": calcBend(goatCount), "templateName": oGoat } }; placeCustomFortress(mX, mZ, new Fortress("celt ritual females", new Array(femaleCount).fill("female")), "celt_ritual", 0, 0); placeCustomFortress(mX, mZ, new Fortress("celt ritual males", new Array(maleCount).fill(0).map(i => pickRandom(["skirmisher", "healer", "fanatic"]))), "celt_ritual", 0, 0); placeCustomFortress(mX, mZ, new Fortress("celt ritual bench", new Array(benchCount).fill("bench")), "celt_ritual", 0, 0); placeCustomFortress(mX, mZ, new Fortress("celt ritual rug", new Array(rugCount).fill("rug")), "celt_ritual", 0, 0); placeCustomFortress(mX, mZ, new Fortress("celt ritual goat", new Array(goatCount).fill("goat")), "celt_ritual", 0, 0); } placeObject(gX, gZ, oCivicCenter, 0, BUILDING_ORIENTATION + Math.PI * 3/2 * i); // Create the city patch createArea( new ClumpPlacer(diskArea(gaulCityRadius), 0.6, 0.3, 10, gX, gZ), [ new LayeredPainter([tShore, tShore], [1]), paintClass(clGauls) ]); // Place palisade fortress and some city buildings // Use actors to avoid players capturing the buildings g_WallStyles.gaul = clone(g_WallStyles.gaul_stone); g_WallStyles.gaul.house = { "angle": Math.PI, "length": 0, "indent": 4, "bend": 0, "templateName": oHouse }; g_WallStyles.gaul.hut = { "angle": Math.PI, "length": 0, "indent": 4, "bend": 0, "templateName": oHut }; g_WallStyles.gaul.longhouse = { "angle": Math.PI, "length": 0, "indent": 4, "bend": 0, "templateName": oLongHouse }; g_WallStyles.gaul.tavern = { "angle": Math.PI * 3/2, "length": 0, "indent": 4, "bend": 0, "templateName": oTavern }; g_WallStyles.gaul.temple = { "angle": Math.PI * 3/2, "length": 0, "indent": 4, "bend": 0, "templateName": oTemple }; g_WallStyles.gaul.defense_tower = { "angle": Math.PI / 2, "length": 0, "indent": 4, "bend": 0, "templateName": mapSize >= normalMapSize ? (isNomad() ? oSentryTower : oTower) : oPalisadeTower }; // Replace stone walls with palisade walls for (let element of ["gate", "long", "short", "cornerIn", "cornerOut", "tower"]) g_WallStyles.gaul[element] = getWallElement(element, "palisade"); let wall = [ "gate", "hut", "tower", "long", "long", "cornerIn", "defense_tower", "long", "long", "temple", "tower", "long", "house", "short", "tower", "gate", "tower", "longhouse", "long", "long", "cornerIn", "defense_tower", "long", "tavern", "long", "tower"]; wall = wall.concat(wall); placeCustomFortress(gX, gZ, new Fortress("Geto-Dacian Tribal Confederation", wall), "gaul", 0, Math.PI); // Place spikes g_WallStyles.palisade.spikes_tall = readyWallElement("other/palisades_tall_spikes", "gaia"); g_WallStyles.palisade.spike_single = readyWallElement("other/palisades_angle_spike", "gaia"); let threeSpikes = new Array(3).fill("spikes_tall"); let fiveSpikes = new Array(5).fill("spikes_tall"); let spikes = [ "gap_3.6", "spike_single", ...threeSpikes, "turn_0.25", "spike_single", "turn_0.25", ...fiveSpikes, "spike_single", "gap_3.6", "spike_single", ...threeSpikes, "turn_0.25", "spike_single", "turn_0.25", ...threeSpikes, "spike_single" ]; spikes = spikes.concat(spikes); placeCustomFortress(gX, gZ, new Fortress("spikes", spikes), "palisade", 0, Math.PI); // Place treasure, potentially inside buildings for (let i = 0; i < gallicCCTreasureCount; ++i) placeObject( gX + randFloat(-0.8, 0.8) * gaulCityRadius, gZ + randFloat(-0.8, 0.8) * gaulCityRadius, pickRandom(oTreasures), 0, randomAngle()); } } Engine.SetProgress(10); placePlayerBases({ "PlayerPlacement": playerPlacementRiver(0, fractionToTiles(0.6)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "Walls": false, "CityPatch": { "outerTerrain": tShore, "innerTerrain": tRoad }, "Chicken": { }, "Berries": { "template": aBush1 }, "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), "end": new Vector2D(mapCenter.x, mapBounds.bottom), "width": waterWidth, "fadeDist": scaleByMapSize(6, 25), "deviation": 0, - "waterHeight": waterHeight, - "landHeight": landHeight, + "heightRiverbed": heightSeaGround, + "heightLand": heightLand, "meanderShort": 30, "meanderLong": 0, "waterFunc": (ix, iz, height, riverFraction) => { // Distinguish left and right shoreline if (0 < height && height < 1 && iz > ShorelineDistance && iz < mapSize - ShorelineDistance) addToClass(ix, iz, clShore[ix < mapCenter.x ? 0 : 1]); }, "landFunc": (ix, iz, shoreDist1, shoreDist2) => { if (shoreDist1 > 0) addToClass(ix, iz, clLand[0]); if (shoreDist2 < 0) addToClass(ix, iz, clLand[1]); } }); Engine.SetProgress(30); paintTileClassBasedOnHeight(-Infinity, 0.7, Elevation_ExcludeMin_ExcludeMax, clWater); log("Creating shores..."); -paintTerrainBasedOnHeight(-Infinity, shoreHeight, 0, tWater); -paintTerrainBasedOnHeight(shoreHeight, landHeight, 0, tShore); +paintTerrainBasedOnHeight(-Infinity, heightShore, 0, tWater); +paintTerrainBasedOnHeight(heightShore, heightLand, 0, tShore); Engine.SetProgress(35); log("Creating bumps..."); createBumps(avoidClasses(clPlayer, 6, clWater, 2, clPath, 1), scaleByMapSize(30, 300), 1, 8, 4, 0, 3); Engine.SetProgress(40); log("Creating hills..."); 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); 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); log("Creating islands..."); 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, 6, 4), + new SmoothElevationPainter(ELEVATION_SET, heightIsland, 4), paintClass(clIsland) ], [avoidClasses(clIsland, 30), stayClasses (clWater, 10)], scaleByMapSize(1, 4) * numPlayers ); Engine.SetProgress(60); log("Creating island bumps..."); createBumps(stayClasses(clIsland, 2), scaleByMapSize(50, 400), 1, 8, 4, 0, 3); log("Paint seabed..."); paintTerrainBasedOnHeight(-20, -3, 3, tSeaDepths); log("Creating island metal mines..."); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oMetalLarge, 1, 1, 0, 4)], true, clMetal), 0, [avoidClasses(clMetal, 50, clRock, 10), stayClasses(clIsland, 5)], 500, 1 ); log("Creating island stone mines..."); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oStoneLarge, 1, 1, 0, 4)], true, clRock), 0, [avoidClasses(clMetal, 10, clRock, 50), stayClasses(clIsland, 5)], 500, 1 ); Engine.SetProgress(65); log("Creating island towers..."); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oTower, 1, 1, 0, 4)], true, clTower), 0, [avoidClasses(clMetal, 4, clRock, 4, clTower, 20), stayClasses(clIsland, 7)], 500, 1 ); log("Creating island outposts..."); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oOutpost, 1, 1, 0, 4)], true, clOutpost), 0, [avoidClasses(clMetal, 4, clRock, 4, clTower, 5, clOutpost, 20), stayClasses(clIsland, 7)], 500, 1 ); log("Creating metal mines..."); createObjectGroupsDeprecated( 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)], 500, 1 ); log("Creating stone mines..."); createObjectGroupsDeprecated( 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)], 500, 1 ); log("Creating stone ruins..."); createObjectGroupsDeprecated( 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)], 500, 1 ); Engine.SetProgress(70); 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)] ], [ scaleByMapSize(5, 80), scaleByMapSize(5, 80), scaleByMapSize(5, 80), scaleByMapSize(5, 80), scaleByMapSize(5, 80), scaleByMapSize(5, 80), scaleByMapSize(5, 80), scaleByMapSize(5, 80), 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); 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); 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); 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); 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); 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); log("Creating treasures..."); for (let i = 0; i < randomTreasureCount; ++i) createObjectGroupsDeprecated( 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), 1, 50 ); 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) ); log("Creating spawn points for ships..."); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(triggerPointShipSpawn, 1, 1, 0, 0)], true, clShip), 0, [avoidClasses(clShip, 5, clIsland, 4), stayClasses(clWater, 10)], 10000, 1000 ); log("Creating patrol points for ships..."); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(triggerPointShipPatrol, 1, 1, 0, 0)], true, clShipPatrol), 0, [avoidClasses(clShipPatrol, 5, clIsland, 3), stayClasses(clWater, 4)], 10000, 1000 ); log("Creating ungarrison points for ships..."); for (let i = 0; i < 2; ++i) createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject( i == 0 ? triggerPointShipUnloadLeft : triggerPointShipUnloadRight, 1, 1, 0, 0)], true, clShoreUngarrisonPoint[i]), 0, [avoidClasses(clShoreUngarrisonPoint[i], 4), stayClasses(clShore[i], 0)], 20000, 1 ); log("Creating patrol points for land attackers..."); addToClass(mapCenter.x, mapCenter.y, clMiddle); for (let i = 0; i < 2; ++i) { createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject( i == 0 ? triggerPointLandPatrolLeft : triggerPointLandPatrolRight, 1, 1, 0, 0)], true, clLandPatrolPoint[i]), 0, [ avoidClasses(clWater, 5, clForest, 3, clHill, 3, clFood, 1, clRock, 5, clMetal, 5, clPlayer, 10, clGauls, 5, clLandPatrolPoint[i], 5), stayClasses(clLand[i], 0) ], 10000, 100 ); if (gallicCC) createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject( i == 0 ? triggerPointCCAttackerPatrolLeft : triggerPointCCAttackerPatrolRight, 1, 1, 0, 0)], true, clCCAttackerPatrolPoint[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, clCCAttackerPatrolPoint[i], 5, clMiddle, mapSize * 0.5 - 15), stayClasses(clLand[i], 0) ], 10000, 100 ); } log("Creating water logs..."); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(aWaterLog, 1, 1, 0, 0)], true, clWaterLog), 0, [avoidClasses(clShip, 3, clIsland, 4), stayClasses(clWater, 4)], scaleByMapSize(15, 60), 100 ); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clIsland, 4, clGauls, 20, clRitualPlace, 20, clForest, 1, clBaseResource, 4, clHill, 4, clFood, 2)); if (randBool(2/3)) { // Day 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 { // Night setSkySet("dark"); setSunColor(0.4, 0.9, 1.2); setSunElevation(0.13499); setSunRotation(-2.5); setTerrainAmbientColor(0.25, 0.3, 0.45); setUnitsAmbientColor(0.3, 0.35, 0.5); 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); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/deep_forest.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/deep_forest.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/deep_forest.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Deep Forest", "Script" : "deep_forest.js", "Description" : "A deep dark forest in Germania.", "BaseTerrain" : ["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"], - "BaseHeight" : 0, "Preview" : "deep_forest.png", "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/extinct_volcano.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/extinct_volcano.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/extinct_volcano.js (revision 20904) @@ -1,461 +1,465 @@ Engine.LoadLibrary("rmgen"); 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/flora_tree_dead"; const oTree2 = "gaia/flora_tree_euro_beech"; const oTree3 = "gaia/flora_tree_oak"; const oTree4 = "gaia/flora_tree_oak_dead"; const oBush = "gaia/flora_bush_temperate"; const oFruitBush = "gaia/flora_bush_berry"; const oRabbit = "gaia/fauna_rabbit"; const oGoat = "gaia/fauna_goat"; const oBear = "gaia/fauna_bear"; const oStoneLarge = "gaia/geology_stonemine_temperate_quarry"; const oStoneSmall = "gaia/geology_stone_temperate"; const oMetalLarge = "gaia/geology_metal_temperate_slabs"; const oTower = "other/palisades_rocks_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 ]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +var heightSeaGround = -4; +var heightLand = 1; +var heightHill = 18; +var heightPlayerHill = 25; + +InitMap(heightLand, g_MapSettings.BaseTerrain); var numPlayers = getNumPlayers(); var mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clFood = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clGrass = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clBaseResource = createTileClass(); var clBumps = createTileClass(); var clTower = createTileClass(); var clRain = createTileClass(); -var ccMountainHeight = 25; -var ccMountainSize = defaultPlayerBaseRadius(); +var playerMountainSize = defaultPlayerBaseRadius(); var [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); log("Creating CC mountains..."); if (!isNomad()) for (let i = 0; i < numPlayers; ++i) { // This one consists of many bumps, creating an omnidirectional ramp createMountain( - ccMountainHeight, - ccMountainSize, - ccMountainSize, + 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(ccMountainSize), 0.95, 0.6, 10, playerPosition[i].x,playerPosition[i].y), + new ClumpPlacer(diskArea(playerMountainSize), 0.95, 0.6, 10, playerPosition[i].x,playerPosition[i].y), [ - new LayeredPainter([tHillVeryDark, tHillMedium1], [ccMountainSize]), - new SmoothElevationPainter(ELEVATION_SET, ccMountainHeight, ccMountainSize), + new LayeredPainter([tHillVeryDark, tHillMedium1], [playerMountainSize]), + new SmoothElevationPainter(ELEVATION_SET, heightPlayerHill, playerMountainSize), paintClass(clPlayer) ]); } Engine.SetProgress(8); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], // PlayerTileClass already marked above "BaseResourceClass": clBaseResource, "Walls": "towers", "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, "Chicken": { }, "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); 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, -4, 3), + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 3), paintClass(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); log("Creating hills..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 150), 0.2, 0.1, 1), [ new LayeredPainter([tHillDark, tHillDark, tHillDark], [2, 2]), - new SmoothElevationPainter(ELEVATION_SET, 18, 2), + new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), paintClass(clHill) ], avoidClasses(clPlayer, 0, clHill, 15, clWater, 2, clBaseResource, 2), scaleByMapSize(2, 8) * numPlayers); Engine.SetProgress(35); 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, 1), [ new LayeredPainter(type, [2]), paintClass(clForest) ], avoidClasses( clPlayer, 4, clForest, 10, clHill, 0, clWater, 2), num); Engine.SetProgress(40); 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]), paintClass(clGrass) ], avoidClasses( clWater, 3, clForest, 0, clHill, 0, clBumps, 0, clPlayer, 0), scaleByMapSize(20, 80)); Engine.SetProgress(45); 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); 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); 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); 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()) { 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) ] ], [ scaleByMapSize(15, 200), scaleByMapSize(15, 200), scaleByMapSize(15, 200) ], [ 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, 1, clRock, 1) ], clForest, stragglerTrees); Engine.SetProgress(90); 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, 1, clRock, 1) ], stragglerTrees); Engine.SetProgress(95); 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(95); 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"); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/english_channel.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/english_channel.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/english_channel.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "English Channel", "Script" : "english_channel.js", "Description" : "Players start in either northern France or southern Britain while the English channel separates them.", "BaseTerrain" : ["temp_grass_long"], - "BaseHeight" : 1, "Keywords": ["naval"], "Preview" : "english_channel.png", "CircularMap" : true } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/flood.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/flood.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/flood.json (revision 20904) @@ -1,21 +1,20 @@ { "settings" : { "Name" : "Flood", "Script" : "flood.js", "Description" : "A great flood has moved across the valley enabling ships and troops to battle in chest deep waters.", "BaseTerrain" : ["medit_sand_wet"], - "BaseHeight" : -2, "SupportedBiomes": [ "temperate", "snowy", "desert", "alpine", "mediterranean", "tropic", "autumn" ], "Keywords": [], "Preview" : "flood.png", "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/english_channel.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/english_channel.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/english_channel.js (revision 20904) @@ -1,262 +1,263 @@ Engine.LoadLibrary("rmgen"); 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/flora_tree_euro_beech"; const oPoplar = "gaia/flora_tree_poplar"; const oApple = "gaia/flora_tree_apple"; const oOak = "gaia/flora_tree_oak"; const oBerryBush = "gaia/flora_bush_berry"; const oDeer = "gaia/fauna_deer"; const oFish = "gaia/fauna_fish"; const oGoat = "gaia/fauna_goat"; const oBoar = "gaia/fauna_boar"; const oStoneLarge = "gaia/geology_stonemine_temperate_quarry"; const oStoneSmall = "gaia/geology_stone_temperate"; const oMetalLarge = "gaia/geology_metal_temperate_slabs"; 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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +var heightSeaGround = -4; +var heightShore = 1; +var heightLand = 3; + +InitMap(heightShore, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); const mapCenter = getMapCenter(); const mapBounds = getMapBounds(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clShallow = createTileClass(); -var landHeight = 3; -var waterHeight = -4; - placePlayerBases({ "PlayerPlacement": playerPlacementRiver(Math.PI / 2, fractionToTiles(0.6)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, "Chicken": { }, "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), "end": new Vector2D(mapBounds.right, mapCenter.y), "width": fractionToTiles(0.25), "fadeDist": scaleByMapSize(3, 10), "deviation": 0, - "waterHeight": waterHeight, - "landHeight": landHeight, + "heightRiverbed": heightSeaGround, + "heightLand": heightLand, "meanderShort": 20, "meanderLong": 0, "waterFunc": (ix, iz, height, riverFraction) => { createTerrain(height < -1.5 ? tWater : tShore).place(ix, iz); }, "landFunc": (ix, iz, shoreDist1, shoreDist2) => { - setHeight(ix, iz, landHeight + 0.1); + setHeight(ix, iz, heightLand + 0.1); } }); Engine.SetProgress(20); createTributaryRivers( true, randIntInclusive(9, scaleByMapSize(13, 21)), scaleByMapSize(10, 20), - waterHeight, + heightSeaGround, [-6, -1.5], Math.PI / 5, clWater, clShallow, avoidClasses(clPlayer, 8, clBaseResource, 4)); paintTerrainBasedOnHeight(-5, 1, 1, tWater); -paintTerrainBasedOnHeight(1, landHeight, 1, tShore); +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); 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); 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); log("Creating stone mines..."); createMines( [ [new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], avoidClasses(clWater, 2, clForest, 1, clPlayer, 20, clRock, 10, clHill, 2), clRock); 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)] ], [ scaleByMapSize(16, 262), scaleByMapSize(8, 131), scaleByMapSize(13, 200), scaleByMapSize(13, 200), scaleByMapSize(13, 200) ], 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)); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/flood.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/flood.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/flood.js (revision 20904) @@ -1,321 +1,321 @@ Engine.LoadLibrary("rmgen"); 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() == "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]; -InitMap(g_MapSettings.BaseHeight, tWater); +const heightSeaGround = -2; +const heightLand = 2; +const shoreRadius = 6; + +InitMap(heightSeaGround, tWater); const clPlayer = createTileClass(); const clHill = createTileClass(); const clMountain = createTileClass(); const clForest = createTileClass(); const clDirt = createTileClass(); const clRock = createTileClass(); const clMetal = createTileClass(); const clFood = createTileClass(); const clBaseResource = createTileClass(); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); -const landHeight = 2; -const waterHeight = getMapBaseHeight(); -const shoreRadius = 6; - log("Creating the water..."); createArea( new ClumpPlacer(getMapArea(), 1, 1, 1, mapCenter.x, mapCenter.y), [ new LayeredPainter([tWater, tWater, tShore], [1, 4]), - new SmoothElevationPainter(ELEVATION_SET, waterHeight, 2) + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 2) ], avoidClasses(clPlayer, 5)); log("Creating player islands...") var [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.38)); for (let i = 0; i < numPlayers; ++i) createArea( new ClumpPlacer( 2 * diskArea(defaultPlayerBaseRadius()), 0.8, 0.1, 10, playerPosition[i].x, playerPosition[i].y), [ new LayeredPainter([tShore, tMainTerrain], [shoreRadius]), - new SmoothElevationPainter(ELEVATION_SET, landHeight, shoreRadius), + new SmoothElevationPainter(ELEVATION_SET, heightLand, shoreRadius), paintClass(clHill) ]); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "Walls": false, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, "Chicken": { }, "Berries": { "template": oFruitBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oTree2, "count": 50, "maxDist": 16, "maxDistGroup": 7 }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(40); log("Creating central island..."); createArea( new ChainPlacer( 6, Math.floor(scaleByMapSize(10, 15)), Math.floor(scaleByMapSize(200, 300)), 1, mapCenter.x, mapCenter.y, 0, [Math.floor(mapSize * 0.01)]), [ new LayeredPainter([tShore, tMainTerrain], [shoreRadius, 100]), - new SmoothElevationPainter(ELEVATION_SET, landHeight, shoreRadius), + new SmoothElevationPainter(ELEVATION_SET, heightLand, shoreRadius), paintClass(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)), 1, randIntExclusive(0, mapSize), randIntExclusive(0, mapSize), 0, [Math.floor(mapSize * 0.01)]), [ new LayeredPainter([tDirt, tHill], [Math.floor(elevRand / 3), 40]), new SmoothElevationPainter(ELEVATION_SET, elevRand, Math.floor(elevRand / 3)), paintClass(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)), 1, randIntExclusive(0, mapSize), randIntExclusive(0, mapSize), 0, [Math.floor(mapSize * 0.01)]), [ new LayeredPainter([tCliff, tForestFloor2], [Math.floor(elevRand / 3), 40]), new SmoothElevationPainter(ELEVATION_MODIFY, elevRand, Math.floor(elevRand / 3)), paintClass(clMountain) ], [avoidClasses(clBaseResource, 2, clPlayer, 40), stayClasses(clHill, 6)]); } log("Creating center bounty..."); createObjectGroup( new SimpleGroup( [new SimpleObject(oMetalLarge, 3, 6, 25, Math.floor(mapSize * 0.25))], true, clBaseResource, mapCenter.x, mapCenter.y), 0, [avoidClasses(clBaseResource, 20, clPlayer, 40, clMountain, 4), stayClasses(clHill, 10)]); createObjectGroup( new SimpleGroup( [new SimpleObject(oStoneLarge, 3, 6, 25, Math.floor(mapSize * 0.25))], true, clBaseResource, mapCenter.x, mapCenter.y), 0, [avoidClasses(clBaseResource, 20, clPlayer, 40, clMountain, 4), stayClasses(clHill, 10)]); 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, 3, clMountain, 2), stayClasses(clHill, 6)], clForest, forestTrees); let types = [oTree1, oTree2, oTree4, oTree3]; createStragglerTrees( types, [avoidClasses(clBaseResource, 2, clMetal, 6, clRock, 3, clMountain, 2, clPlayer, 25), stayClasses(clHill, 6)], clForest, stragglerTrees); Engine.SetProgress(65); log("Creating dirt patches..."); var numb = currentBiome() == "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]), paintClass(clDirt) ], avoidClasses(clForest, 0, clMountain, 0, clDirt, 5, clPlayer, 10), numb * scaleByMapSize(15, 45)); log("Painting shorelines..."); -paintTerrainBasedOnHeight(1, landHeight, 0, tMainTerrain); -paintTerrainBasedOnHeight(waterHeight, 1, 3, tTier1Terrain); +paintTerrainBasedOnHeight(1, heightLand, 0, tMainTerrain); +paintTerrainBasedOnHeight(heightSeaGround, 1, 3, tTier1Terrain); 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)); log("Creating food..."); 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); log("Creating decoration..."); var planetm = currentBiome() == "tropic" ? 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)] ], [ scaleByMapSize(16, 262), scaleByMapSize(8, 131), planetm * scaleByMapSize(13, 200), planetm * scaleByMapSize(13, 200), planetm * scaleByMapSize(13, 200) ], avoidClasses(clForest, 2, clPlayer, 20, clMountain, 5, clFood, 1, clBaseResource, 2)); log("Creating water forests..."); var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(0.1)); createForests( [tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2], avoidClasses(clPlayer, 30, clHill, 10, clFood, 5), clForest, forestTrees); 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); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/extinct_volcano.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/extinct_volcano.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/extinct_volcano.json (revision 20904) @@ -1,19 +1,18 @@ { "settings" : { "Name" : "Extinct Volcano", "Script" : "extinct_volcano.js", "Description" : "[color=\"red\"]IMPORTANT NOTE: AI PLAYERS DO NOT WORK WITH THIS MAP[/color]\n\nA once fertile valley, desolated by the eruption of the long-dormant volcano in the heart of the region. Following years of empty, scorched deadness, signs of life started reappearing and spreading. Now the land is half-way to the full lushness of its former era. Alas, it is not to be: following a long stretch of drought, interminable rains have set in in the higher regions to the north. Water levels are rising at drastic levels, slowly forcing players to seek the high ground of the lesser, extinct volcanoes or the now again dormant great cone.", "DisabledTemplates": [ "structures/ptol_lighthouse" ], "BaseTerrain" : "ocean_rock_a", - "BaseHeight" : 1, "Keywords": ["trigger"], "CircularMap" : true, "Preview" : "extinctvolcano.png", "TriggerScripts": [ "scripts/TriggerHelper.js", "random/extinct_volcano_triggers.js" ] } } Index: ps/trunk/binaries/data/mods/public/maps/random/fortress.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/fortress.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/fortress.js (revision 20904) @@ -1,304 +1,307 @@ Engine.LoadLibrary("rmgen"); const tGrass = ["temp_grass_aut", "temp_grass_aut", "temp_grass_d_aut"]; const tForestFloor = "temp_grass_aut"; const tGrassA = "temp_grass_plants_aut"; const tGrassB = "temp_grass_b_aut"; const tGrassC = "temp_grass_c_aut"; const tHill = ["temp_highlands_aut", "temp_grass_long_b_aut"]; const tCliff = ["temp_cliff_a", "temp_cliff_b"]; const tRoad = "temp_road_aut"; const tGrassPatch = "temp_grass_plants_aut"; const tShore = "temp_plants_bog_aut"; const tWater = "temp_mud_a"; const oBeech = "gaia/flora_tree_euro_beech_aut"; const oOak = "gaia/flora_tree_oak_aut"; const oPine = "gaia/flora_tree_pine"; const oDeer = "gaia/fauna_deer"; const oFish = "gaia/fauna_fish"; const oSheep = "gaia/fauna_rabbit"; const oBerryBush = "gaia/flora_bush_berry"; const oStoneLarge = "gaia/geology_stonemine_temperate_quarry"; const oStoneSmall = "gaia/geology_stone_temperate"; const oMetalLarge = "gaia/geology_metal_temperate_slabs"; const oFoodTreasure = "gaia/special_treasure_food_bin"; const oWoodTreasure = "gaia/special_treasure_wood"; const oStoneTreasure = "gaia/special_treasure_stone"; const oMetalTreasure = "gaia/special_treasure_metal"; const aGrass = "actor|props/flora/grass_soft_dry_small_tall.xml"; const aGrassShort = "actor|props/flora/grass_soft_dry_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_dry.xml"; const aLillies = "actor|props/flora/water_lillies.xml"; const aBushMedium = "actor|props/flora/bush_medit_me_dry.xml"; const aBushSmall = "actor|props/flora/bush_medit_sm_dry.xml"; const pForestD = [tForestFloor + TERRAIN_SEPARATOR + oBeech, tForestFloor]; const pForestO = [tForestFloor + TERRAIN_SEPARATOR + oOak, tForestFloor]; const pForestP = [tForestFloor + TERRAIN_SEPARATOR + oPine, tForestFloor]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +var heightSeaGround = -4; +var heightLand = 3; + +InitMap(heightLand, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var treasures = [ { "template": oFoodTreasure, "distance": 5 }, { "template": oWoodTreasure, "distance": 5 }, { "template": oMetalTreasure, "distance": 3 }, { "template": oMetalTreasure, "distance": 2 }, ]; var [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); for (let i = 0; i < numPlayers; ++i) { if (isNomad()) break; log("Creating base for player " + playerIDs[i] + "..."); for (let dist of [6, 8]) { let ents = getStartingEntities(playerIDs[i]); if (dist == 8) ents = ents.filter(ent => ent.Template.indexOf("female") != -1 || ent.Template.indexOf("infantry") != -1); placeStartingEntities(playerPosition[i], playerIDs[i], ents, dist); } log("Creating treasure for player " + playerIDs[i] + "..."); let bbAngle = BUILDING_ORIENTATION; for (let treasure of treasures) { let position = Vector2D.add(playerPosition[i], new Vector2D(10, 0).rotate(-bbAngle)) createObjectGroup(new SimpleGroup([new SimpleObject(oFoodTreasure, 5, 5, 0, 2)], true, clBaseResource, position.x, position.y), 0); bbAngle += Math.PI / 2; } log("Painting ground texture for player " + playerIDs[i] + "..."); var civ = getCivCode(playerIDs[i]); var tilesSize = civ == "cart" ? 24 : 22; const minBoundX = Math.max(0, playerPosition[i].x - tilesSize); const minBoundY = Math.max(0, playerPosition[i].y - tilesSize); const maxBoundX = Math.min(mapSize, playerPosition[i].x + tilesSize); const maxBoundY = Math.min(mapSize, playerPosition[i].y + tilesSize); for (var tx = minBoundX; tx < maxBoundX; ++tx) for (var ty = minBoundY; ty < maxBoundY; ++ty) { var unboundSumOfXY = tx + ty - minBoundX - minBoundY; if (unboundSumOfXY > tilesSize && unboundSumOfXY < tilesSize * 3 && tx - ty + minBoundY - minBoundX < tilesSize && ty - tx - minBoundY + minBoundX < tilesSize) { createTerrain(tRoad).place(tx, ty); addToClass(tx, ty, clPlayer); } } log("Placing fortress for player " + playerIDs[i] + "..."); if (civ == "brit" || civ == "gaul" || civ == "iber") { var wall = ["gate", "tower", "long", "cornerIn", "long", "barracks", "tower", "long", "tower", "house", "long", "cornerIn", "long", "house", "tower", "gate", "tower", "house", "long", "cornerIn", "long", "house", "tower", "long", "tower", "house", "long", "cornerIn", "long", "house", "tower"]; } else { var wall = ["gate", "tower", "long", "cornerIn", "long", "barracks", "tower", "long", "tower", "long", "cornerIn", "long", "house", "tower", "gate", "tower", "long", "cornerIn", "long", "house", "tower", "long", "tower", "long", "cornerIn", "long", "house", "tower"]; } placeCustomFortress(playerPosition[i].x, playerPosition[i].y, new Fortress("Spahbod", wall), civ, playerIDs[i], -Math.PI/4); } log("Creating lakes..."); var numLakes = Math.round(scaleByMapSize(1,4) * numPlayers); var waterAreas = createAreas( new ClumpPlacer(scaleByMapSize(100,250), 0.8, 0.1, 10), [ new LayeredPainter([tShore, tWater, tWater], [1, 1]), - new SmoothElevationPainter(ELEVATION_SET, -4, 3), + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 3), paintClass(clWater) ], avoidClasses(clPlayer, 7, clWater, 20), numLakes); Engine.SetProgress(15); log("Creating reeds..."); createObjectGroupsByAreasDeprecated( new SimpleGroup([new SimpleObject(aReeds, 5,10, 0,4), new SimpleObject(aLillies, 0,1, 0,4)], true), 0, [borderClasses(clWater, 3, 0), stayClasses(clWater, 1)], numLakes, 100, waterAreas); Engine.SetProgress(25); log("Creating fish..."); createObjectGroupsByAreasDeprecated( new SimpleGroup( [new SimpleObject(oFish, 1,1, 0,1)], true, clFood ), 0, [stayClasses(clWater, 4), avoidClasses(clFood, 8)], numLakes / 4, 50, waterAreas); Engine.SetProgress(30); createBumps(avoidClasses(clWater, 2, clPlayer, 5)); Engine.SetProgress(35); log("Creating hills..."); createHills([tCliff, tCliff, tHill], avoidClasses(clPlayer, 5, clWater, 5, clHill, 15), clHill, scaleByMapSize(1, 4) * numPlayers); Engine.SetProgress(40); log("Creating forests..."); var [forestTrees, stragglerTrees] = getTreeCounts(500, 2500, 0.7); var types = [ [[tForestFloor, tGrass, pForestD], [tForestFloor, pForestD]], [[tForestFloor, tGrass, pForestO], [tForestFloor, pForestO]], [[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, 0.5), [ new LayeredPainter(type, [2]), paintClass(clForest) ], avoidClasses(clPlayer, 5, clWater, 3, clForest, 15, clHill, 1), num); Engine.SetProgress(50); 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, 1), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(55); log("Creating grass patches..."); createPatches( [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)], tGrassPatch, avoidClasses(clWater, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 1), scaleByMapSize(15, 45), clDirt); Engine.SetProgress(60); log("Creating stone mines..."); createMines( [ [new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], avoidClasses(clWater, 0, clForest, 1, clPlayer, 5, clRock, 10, clHill, 1), clRock); Engine.SetProgress(65); log("Creating metal mines..."); createMines( [ [new SimpleObject(oMetalLarge, 1,1, 0,4)] ], avoidClasses(clWater, 0, clForest, 1, clPlayer, 5, 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)] ], [ scaleByMapSize(16, 262), scaleByMapSize(8, 131), scaleByMapSize(13, 200), scaleByMapSize(13, 200), scaleByMapSize(13, 200) ], avoidClasses(clWater, 0, clForest, 0, clPlayer, 1, clHill, 0)); Engine.SetProgress(80); 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, 6, clHill, 1, clFood, 20), clFood); Engine.SetProgress(85); createFood( [ [new SimpleObject(oBerryBush, 5, 7, 0, 4)] ], [ randIntInclusive(1, 4) * numPlayers + 2 ], avoidClasses(clWater, 2, clForest, 0, clPlayer, 6, clHill, 1, clFood, 10), clFood); Engine.SetProgress(90); createStragglerTrees( [oOak, oBeech, oPine], avoidClasses(clWater, 1, clForest, 1, clHill, 1, clPlayer, 1, clMetal, 6, clRock, 6), clForest, stragglerTrees); Engine.SetProgress(95); placePlayersNomad(clPlayer, avoidClasses(clWater, 2, clHill, 2, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); setSkySet("sunny"); setWaterColor(0.157, 0.149, 0.443); setWaterTint(0.443,0.42,0.824); setWaterWaviness(2.0); setWaterType("lake"); setWaterMurkiness(0.83); setFogFactor(0.35); setFogThickness(0.22); setFogColor(0.82,0.82, 0.73); setPPSaturation(0.56); setPPContrast(0.56); setPPBloom(0.38); setPPEffect("hdr"); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/gear.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/gear.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/gear.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "Gear", "Script" : "gear.js", "Description" : "A land with waterways decorated in a manner similar to spider web.", "BaseTerrain" : ["medit_sea_depths"], - "BaseHeight" : 4, "CircularMap" : true, "SupportedBiomes": true, "Preview" : "gear.png" } } Index: ps/trunk/binaries/data/mods/public/maps/random/gulf_of_bothnia.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/gulf_of_bothnia.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/gulf_of_bothnia.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Gulf of Bothnia", "Script" : "gulf_of_bothnia.js", "Description" : "Players start around a gulf dotted with small islands.\n\nThe Gulf of Bothnia is the northernmost arm of the Baltic Sea.", "BaseTerrain" : ["alpine_dirt_grass_50"], - "BaseHeight" : 3, "Preview" : "gulf_of_bothnia.png", "CircularMap" : true } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/hells_pass.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/hells_pass.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/hells_pass.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "Hell's Pass", "Script" : "hells_pass.js", "Description" : "A narrow pass between steep mountains promotes tight, defensive combat. With bountiful resources far from the front lines, teams may choose to support their exposed teammates financially, or retreat to more fertile, but less defensible ground.", "BaseTerrain" : ["medit_sea_depths"], - "BaseHeight" : 1, "Preview" : "hells_pass.png", "SupportedBiomes": true, "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/india.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/india.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/india.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "India", "Script" : "india.js", "Description" : "Central India just before the monsoon season - a parched land awaits the life-bringing rain which is already two months late. Due to the extended dryness and scorching heat, only the largest lake remains. The hardy trees which have survived the climate are spread out, yet not too scarce.", "BaseTerrain" : "savanna_grass_a", - "BaseHeight" : 1, "Preview" : "india.png", "Keywords": [], "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/islands.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/islands.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/islands.json (revision 20904) @@ -1,13 +1,12 @@ { "settings" : { "Name" : "Islands", "Script" : "islands.js", "Description" : "Players start in small islands while there are many others around.", "BaseTerrain" : ["medit_sand_wet"], - "BaseHeight" : -5, "Keywords": ["naval"], "Preview" : "islands.png", "SupportedBiomes": true, "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/lake.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/lake.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/lake.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "Lake", "Script" : "lake.js", "Description" : "Players start around a lake in the center of the map.", "BaseTerrain" : ["medit_sea_depths"], - "BaseHeight" : 3, "Preview" : "lake.png", "SupportedBiomes": true, "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/lions_den.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/lions_den.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/lions_den.json (revision 20904) @@ -1,13 +1,12 @@ { "settings" : { "Name" : "Lion's Den", "Script" : "lions_den.js", "Description" : "High cliffs protect each player's main base. Venturing into the unknown can be risky, but necessary.", "BaseTerrain" : ["medit_sea_depths"], - "BaseHeight" : 50, "Preview" : "lions_den.png", "Keywords": [], "SupportedBiomes": true, "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/mainland.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/mainland.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/mainland.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "Mainland", "Script" : "mainland.js", "Description" : "A typical map without any water.", "BaseTerrain" : ["medit_sea_depths"], - "BaseHeight" : 3, "Preview" : "mainland.png", "SupportedBiomes": true, "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/neareastern_badlands.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/neareastern_badlands.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/neareastern_badlands.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Neareastern Badlands", "Script" : "neareastern_badlands.js", "Description" : "A jumbled maze of cliffs, canyons, and rugged terrain with an oasis in the center\n\nCappadocia is a historical region in Central Anatolia. In the time of Herodotus, the Cappadocians were reported as occupying the whole region from Mount Taurus to the vicinity of the the Black Sea. Cappadocia, in this sense, was bounded in the south by the chain of the Taurus Mountains that separate it from Cilicia, to the east by the upper Euphrates and the Armenian Highland, to the north by Pontus, and to the west by Lycaonia and eastern Galatia. Cappadocia lies in eastern Anatolia. The relief consists of a high plateau over 1000 m in altitude that is pierced by volcanic peaks. Due to its inland location and high altitude, Cappadocia has a markedly continental climate, with hot dry summers and cold snowy winters. Rainfall is sparse and the region is largely semi-arid.", "BaseTerrain" : ["desert_sand_smooth", "desert_sand_smooth_b"], - "BaseHeight" : 10, "Preview" : "neareastern_badlands.png", "CircularMap" : true } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/gear.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/gear.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/gear.js (revision 20904) @@ -1,299 +1,305 @@ Engine.LoadLibrary("rmgen"); 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]; -InitMap(g_MapSettings.BaseHeight, tMainTerrain); +var heightSeaGround = -4; +var heightShallow = -2; +var heightLand = 3; +var heighRing = 4; +var heightHill = 20; + +InitMap(heightLand, tMainTerrain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapArea = getMapArea(); const mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var [playerIDs, playerPosition, playerAngle, startAngle] = playerPlacementCircle(fractionToTiles(0.35)); 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; } log("Creating big circular lake..."); createArea( new ClumpPlacer(mapArea * 0.23, 1, 1, 10, mapCenter.x, mapCenter.y), - new SmoothElevationPainter(ELEVATION_SET, -3, 4)); + new SmoothElevationPainter(ELEVATION_SET, heightShallow, 4)); for (let m = 0; m < numPlayers * split; ++m) { log("Creating rivers between players..."); 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.x, position1.y, position2.x, position2.y, scaleByMapSize(14, 40), 0, scaleByMapSize(3, 9), 0.2, 0.05), - new SmoothElevationPainter(ELEVATION_SET, -4, 4), + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4), avoidClasses(clPlayer, 5)); log("Create path from the island to the center..."); angle = startAngle + m * 2 * Math.PI / (numPlayers * split); position1 = Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.05), 0).rotate(-angle)); position2 = Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.49), 0).rotate(-angle)); createArea( new PathPlacer(position1.x, position1.y, position2.x, position2.y, scaleByMapSize(10, 40), 0, scaleByMapSize(3, 9), 0.2, 0.05), - new SmoothElevationPainter(ELEVATION_SET, 3, 4)); + new SmoothElevationPainter(ELEVATION_SET, heightLand, 4)); } log("Creating ring of land connecting players..."); createArea( new ClumpPlacer(mapArea * 0.15, 1, 1, 10, mapCenter.x, mapCenter.y), - new SmoothElevationPainter(ELEVATION_SET, 4, 4)); + new SmoothElevationPainter(ELEVATION_SET, heighRing, 4)); log("Creating ring of water separating the central hill from the ring..."); createArea( new ClumpPlacer(mapArea * 0.09, 1, 1, 10, mapCenter.x, mapCenter.y), - new SmoothElevationPainter(ELEVATION_SET, -2, 3)); + new SmoothElevationPainter(ELEVATION_SET, heightShallow, 3)); log("Creating central island..."); createArea( new ClumpPlacer(Math.square(mapSize - 50) * 0.09, 1, 1, 10, mapCenter.x, mapCenter.y), - new SmoothElevationPainter(ELEVATION_SET, 4, 3)); + new SmoothElevationPainter(ELEVATION_SET, heighRing, 3)); log("Creating hill on the central island..."); createArea( new ClumpPlacer(diskArea(scaleByMapSize(6, 18)) * 7, 1, 1, 10, mapCenter.x, mapCenter.y), - new SmoothElevationPainter(ELEVATION_SET, 20, 8)); + 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, "Walls": "towers", "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, "Chicken": { }, "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); 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); 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); log("Creating stone mines..."); createMines( [ [new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), clRock); 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 ); 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() == "tropic") 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)] ], [ scaleByMapSize(16, 262), scaleByMapSize(8, 131), planetm * scaleByMapSize(13, 200), planetm * scaleByMapSize(13, 200), planetm * scaleByMapSize(13, 200) ], 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)); 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 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/gulf_of_bothnia.js (revision 20904) @@ -1,330 +1,333 @@ Engine.LoadLibrary("rmgen"); TILE_CENTERED_HEIGHT_MAP = true; var biome = pickRandom(["late_spring", "winter", "frozen_lake"]); if (biome == "late_spring") { log("Late spring biome..."); - var waterHeight = -3; - var shoreHeight = 1; + var heightSeaGround = -3; + var heightShore = 1; + var heightLand = 3; var fishCount = { "min": 20, "max": 80 }; var bushCount = { "min": 13, "max": 200 }; 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 tRoad = "new_alpine_citytile"; var tRoadWild = "new_alpine_citytile"; var tShore = "alpine_shore_rocks_grass_50"; var tWater = "alpine_shore_rocks"; var oPine = "gaia/flora_tree_pine"; var oBerryBush = "gaia/flora_bush_berry"; var oDeer = "gaia/fauna_deer"; var oFish = "gaia/fauna_fish"; var oRabbit = "gaia/fauna_rabbit"; var oStoneLarge = "gaia/geology_stonemine_alpine_quarry"; var oStoneSmall = "gaia/geology_stone_alpine_a"; var oMetalLarge = "gaia/geology_metal_alpine_slabs"; 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 if (biome == "winter") { log("Winter biome..."); - var waterHeight = -3; - var shoreHeight = 1; + var heightSeaGround = -3; + var heightShore = 1; + var heightLand = 3; var fishCount = { "min": 20, "max": 80 }; var bushCount = { "min": 13, "max": 200 }; 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 tRoad = "new_alpine_citytile"; var tRoadWild = "new_alpine_citytile"; var tShore = "alpine_shore_rocks_icy"; var tWater = "alpine_shore_rocks"; var oPine = "gaia/flora_tree_pine_w"; var oBerryBush = "gaia/flora_bush_berry"; var oDeer = "gaia/fauna_deer"; var oFish = "gaia/fauna_fish"; var oRabbit = "gaia/fauna_rabbit"; var oStoneLarge = "gaia/geology_stonemine_alpine_quarry"; var oStoneSmall = "gaia/geology_stone_alpine_a"; var oMetalLarge = "gaia/geology_metal_alpine_slabs"; 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"; } else if (biome == "frozen_lake") { log("Frozen lake biome..."); - var waterHeight = 0; - var shoreHeight = 2; + var heightSeaGround = 0; + var heightShore = 2; + var heightLand = 3; var fishCount = { "min": 0, "max": 0 }; var bushCount = { "min": 0, "max": 0 }; setFogFactor(0.41); setFogThickness(0.23); setPPSaturation(0.34); setPPEffect("hdr"); var tPrimary = ["alpine_snow_a", "alpine_snow_b"]; var tForestFloor = "alpine_snow_a"; var tCliff = ["alpine_cliff_snow"]; var tSecondary = "polar_ice_snow"; var tHalfSnow = ["polar_ice_cracked"]; var tSnowLimited = ["alpine_snow_a", "alpine_snow_b"]; var tRoad = "new_alpine_citytile"; var tRoadWild = "new_alpine_citytile"; var tShore = "polar_ice_snow"; var tWater = ["polar_ice_snow", "polar_ice"]; var oPine = "gaia/flora_tree_pine_w"; var oBerryBush = "gaia/flora_bush_berry"; var oDeer = "gaia/fauna_deer"; var oFish = "gaia/fauna_fish"; var oRabbit = "gaia/fauna_rabbit"; var oStoneLarge = "gaia/geology_stonemine_alpine_quarry"; var oStoneSmall = "gaia/geology_stone_alpine_a"; var oMetalLarge = "gaia/geology_metal_alpine_slabs"; 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]; -InitMap(g_MapSettings.BaseHeight, tPrimary); +InitMap(heightLand, tPrimary); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var startAngle = -Math.PI / 6; placePlayerBases({ "PlayerPlacement": [sortAllPlayers(), ...playerPlacementCustomAngle( fractionToTiles(0.35), mapCenter, i => startAngle + 2/3 * Math.PI * (numPlayers == 1 ? 1 : 2 * i / (numPlayers - 1)))], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, "Chicken": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oPine, "count": 2 }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(20); log("Creating the gulf..."); var gulfLakePositions = [ { "numCircles": 200, "z": Math.round(fractionToTiles(0.5)), "radius": fractionToTiles(0.175) }, { "numCircles": 120, "z": Math.round(fractionToTiles(0.3)), "radius": fractionToTiles(0.2) }, { "numCircles": 100, "z": Math.round(fractionToTiles(0.01)), "radius": fractionToTiles(0.225) } ]; for (let position of gulfLakePositions) createArea( new ChainPlacer( 2, Math.floor(scaleByMapSize(5, 16)), Math.floor(scaleByMapSize(35, position.numCircles)), 1, mapCenter.x, position.z, 0, [Math.floor(position.radius)]), [ new LayeredPainter([tPrimary, tPrimary, tPrimary, tPrimary], [1, 4, 2]), - new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4), paintClass(clWater) ], avoidClasses(clPlayer,scaleByMapSize(20, 28))); -paintTerrainBasedOnHeight(shoreHeight, getMapBaseHeight(), Elevation_ExcludeMin_ExcludeMax, tShore); -paintTerrainBasedOnHeight(-Infinity, shoreHeight, Elevation_ExcludeMin_IncludeMax, tWater); +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); createForests( [tPrimary, tForestFloor, tForestFloor, pForest, pForest], avoidClasses(clPlayer, 20, clForest, 16, clHill, 0, clWater, 2), clForest, forestTrees); Engine.SetProgress(60); 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); 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); log("Creating stone mines..."); createMines( [ [new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), clRock); 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)] ], [ scaleByMapSize(16, 262), scaleByMapSize(8, 131), 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)); setSkySet("stormy"); setSunRotation(randomAngle()); setSunElevation(Math.PI * randFloat(1/6, 1/4)); setWaterColor(0.035,0.098,0.314); setWaterTint(0.28, 0.3, 0.59); setWaterWaviness(5.0); setWaterType("lake"); setWaterMurkiness(0.88); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/hells_pass.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/hells_pass.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/hells_pass.js (revision 20904) @@ -1,335 +1,331 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen2"); Engine.LoadLibrary("rmbiome"); setSelectedBiome(); -InitMap(g_MapSettings.BaseHeight, Terrains.mainTerrain); +const heightLand = 1; +const heightBarrier = 30; + +InitMap(heightLand, g_Terrains.mainTerrain); initTileClasses(); +const mapCenter = getMapCenter(); + createArea( new MapBoundsPlacer(), paintClass(g_TileClasses.land)); Engine.SetProgress(10); const teamsArray = getTeamsArray(); const startAngle = randomAngle(); addBases("line", fractionToTiles(0.2), fractionToTiles(0.08), startAngle); Engine.SetProgress(20); placeBarriers(); Engine.SetProgress(40); addElements(shuffleArray([ { "func": addBluffs, - "baseHeight": getMapBaseHeight(), + "baseHeight": heightLand, "avoid": [ g_TileClasses.bluff, 20, g_TileClasses.hill, 5, g_TileClasses.mountain, 20, g_TileClasses.plateau, 20, g_TileClasses.player, 30, g_TileClasses.spine, 15, g_TileClasses.valley, 5, g_TileClasses.water, 7 ], "sizes": ["normal", "big"], "mixes": ["varied"], "amounts": ["few"] }, { "func": addHills, "avoid": [ g_TileClasses.bluff, 5, g_TileClasses.hill, 15, g_TileClasses.mountain, 2, g_TileClasses.plateau, 5, g_TileClasses.player, 20, g_TileClasses.spine, 15, g_TileClasses.valley, 2, g_TileClasses.water, 2 ], "sizes": ["normal", "big"], "mixes": ["varied"], "amounts": ["few"] }, { "func": addLakes, "avoid": [ g_TileClasses.bluff, 7, g_TileClasses.hill, 2, g_TileClasses.mountain, 15, g_TileClasses.plateau, 10, g_TileClasses.player, 20, g_TileClasses.spine, 15, g_TileClasses.valley, 10, g_TileClasses.water, 25 ], "sizes": ["big", "huge"], "mixes": ["varied", "unique"], "amounts": ["few"] } ])); Engine.SetProgress(50); addElements([ { "func": addLayeredPatches, "avoid": [ g_TileClasses.bluff, 2, g_TileClasses.dirt, 5, g_TileClasses.forest, 2, g_TileClasses.mountain, 2, g_TileClasses.plateau, 2, g_TileClasses.player, 12, g_TileClasses.spine, 5, g_TileClasses.water, 3 ], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["normal"] }, { "func": addDecoration, "avoid": [ g_TileClasses.bluff, 2, g_TileClasses.forest, 2, g_TileClasses.mountain, 2, g_TileClasses.plateau, 2, g_TileClasses.player, 12, g_TileClasses.spine, 5, g_TileClasses.water, 3 ], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["normal"] } ]); Engine.SetProgress(60); addElements(shuffleArray([ { "func": addMetal, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.bluff, 5, g_TileClasses.forest, 3, g_TileClasses.mountain, 2, g_TileClasses.plateau, 2, g_TileClasses.player, 30, g_TileClasses.rock, 10, g_TileClasses.metal, 20, g_TileClasses.spine, 5, g_TileClasses.water, 3 ], "sizes": ["normal"], "mixes": ["same"], "amounts": g_AllAmounts }, { "func": addStone, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.bluff, 5, g_TileClasses.forest, 3, g_TileClasses.mountain, 2, g_TileClasses.plateau, 2, g_TileClasses.player, 30, g_TileClasses.rock, 20, g_TileClasses.metal, 10, g_TileClasses.spine, 5, g_TileClasses.water, 3 ], "sizes": ["normal"], "mixes": ["same"], "amounts": g_AllAmounts }, { "func": addForests, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.bluff, 5, g_TileClasses.forest, 18, g_TileClasses.metal, 3, g_TileClasses.mountain, 5, g_TileClasses.plateau, 5, g_TileClasses.player, 20, g_TileClasses.rock, 3, g_TileClasses.spine, 5, g_TileClasses.water, 2 ], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": ["few", "normal", "many", "tons"] } ])); Engine.SetProgress(80); addElements(shuffleArray([ { "func": addBerries, "avoid": [ g_TileClasses.berries, 30, g_TileClasses.bluff, 5, g_TileClasses.forest, 5, g_TileClasses.metal, 10, g_TileClasses.mountain, 2, g_TileClasses.plateau, 2, g_TileClasses.player, 20, g_TileClasses.rock, 10, g_TileClasses.spine, 2, g_TileClasses.water, 3 ], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": g_AllAmounts }, { "func": addAnimals, "avoid": [ g_TileClasses.animals, 20, g_TileClasses.bluff, 5, g_TileClasses.forest, 2, g_TileClasses.metal, 2, g_TileClasses.mountain, 1, g_TileClasses.plateau, 2, g_TileClasses.player, 20, g_TileClasses.rock, 2, g_TileClasses.spine, 2, g_TileClasses.water, 3 ], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": g_AllAmounts }, { "func": addStragglerTrees, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.bluff, 5, g_TileClasses.forest, 7, g_TileClasses.metal, 2, g_TileClasses.mountain, 1, g_TileClasses.plateau, 2, g_TileClasses.player, 12, g_TileClasses.rock, 2, g_TileClasses.spine, 2, g_TileClasses.water, 5 ], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": g_AllAmounts } ])); Engine.SetProgress(90); placePlayersNomad( g_TileClasses.player, avoidClasses( g_TileClasses.bluff, 4, g_TileClasses.water, 4, g_TileClasses.spine, 4, g_TileClasses.plateau, 4, g_TileClasses.forest, 1, g_TileClasses.metal, 4, g_TileClasses.rock, 4, g_TileClasses.mountain, 4, g_TileClasses.animals, 2)); ExportMap(); function placeBarriers() { var spineTerrain = g_Terrains.dirt; if (currentBiome() == "snowy") spineTerrain = g_Terrains.tier1Terrain; if (currentBiome() == "alpine" || currentBiome() == "savanna") spineTerrain = g_Terrains.tier2Terrain; if (currentBiome() == "autumn") spineTerrain = g_Terrains.tier4Terrain; let spineCount = isNomad() ? randIntInclusive(1, 4) : teamsArray.length; for (let i = 0; i < spineCount; ++i) { - var mStartCo = 0.07; - var mStopCo = 0.42; var mSize = 8; var mWaviness = 0.6; var mOffset = 0.5; var mTaper = -1.5; if (spineCount > 3 || getMapSize() <= 192) { mWaviness = 0.2; mOffset = 0.2; mTaper = -1; } if (spineCount >= 5) { mSize = 4; mWaviness = 0.2; mOffset = 0.2; mTaper = -0.7; } let angle = startAngle + (i + 0.5) * 2 * Math.PI / spineCount; + let start = Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.075), 0).rotate(-angle)); + let end = Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.42), 0).rotate(-angle)); createArea( - new PathPlacer( - fractionToTiles(0.5 + mStartCo * Math.cos(angle)), - fractionToTiles(0.5 + mStartCo * Math.sin(angle)), - fractionToTiles(0.5 + mStopCo * Math.cos(angle)), - fractionToTiles(0.5 + mStopCo * Math.sin(angle)), - scaleByMapSize(14, mSize), - mWaviness, - 0.1, - mOffset, - mTaper), + new PathPlacer(start.x, start.y, end.x, end.y, scaleByMapSize(14, mSize), mWaviness, 0.1, mOffset, mTaper), [ new LayeredPainter([g_Terrains.cliff, spineTerrain], [2]), - new SmoothElevationPainter(ELEVATION_SET, 30, 2), + new SmoothElevationPainter(ELEVATION_SET, heightBarrier, 2), paintClass(g_TileClasses.spine) ], avoidClasses(g_TileClasses.player, 5, g_TileClasses.baseResource, 5)); } addElements([ { "func": addDecoration, "avoid": [ g_TileClasses.bluff, 2, g_TileClasses.forest, 2, g_TileClasses.mountain, 2, g_TileClasses.player, 12, g_TileClasses.water, 3 ], "stay": [g_TileClasses.spine, 5], "sizes": ["huge"], "mixes": ["unique"], "amounts": ["tons"] } ]); addElements([ { "func": addProps, "avoid": [ g_TileClasses.forest, 2, g_TileClasses.player, 2, g_TileClasses.prop, 20, g_TileClasses.water, 3 ], "stay": [g_TileClasses.spine, 8], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["scarce"] } ]); } Index: ps/trunk/binaries/data/mods/public/maps/random/india.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/india.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/india.js (revision 20904) @@ -1,272 +1,277 @@ Engine.LoadLibrary("rmgen"); 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/flora_tree_palm_tropic"; const oBerryBush = "gaia/flora_bush_berry"; const oRabbit = "gaia/fauna_rabbit"; const oTiger = "gaia/fauna_tiger"; const oCrocodile = "gaia/fauna_crocodile"; const oFish = "gaia/fauna_fish"; const oElephant = "gaia/fauna_elephant_asian"; const oElephantInfant = "gaia/fauna_elephant_asian_infant"; const oBoar = "gaia/fauna_boar"; const oStoneSmall = "gaia/geology_stone_savanna_small"; const oMetalLarge = "gaia/geology_metal_savanna_slabs"; const aBush = "actor|props/flora/bush_medit_sm_dry.xml"; const aRock = "actor|geology/stone_savanna_med.xml"; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightSeaGround = -3; +const heightLand = 1; +const heightShore = 3; +const heightOffsetBump = 2; + +InitMap(heightLand, g_MapSettings.BaseTerrain); var numPlayers = getNumPlayers(); var mapSize = getMapSize(); var mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, // No city patch "Chicken": { }, "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); log("Creating bumps..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.5, 0.08, 1), - new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), avoidClasses(clPlayer, 13), scaleByMapSize(300, 800) ); log("Creating the half dried-up lake..."); createArea( new ChainPlacer( 2, Math.floor(scaleByMapSize(2, 16)), Math.floor(scaleByMapSize(35, 200)), 1, mapCenter.x, mapCenter.y, 0, [Math.floor(mapSize * 0.008 * Math.pow(scaleByMapSize(1, 66), 1/8))]), [ - new SmoothElevationPainter(ELEVATION_SET, -3, 4), + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4), paintClass(clWater) ], avoidClasses(clPlayer, 20)); log("Creating more shore jaggedness..."); createAreas( new ChainPlacer(2, Math.floor(scaleByMapSize(4, 6)), 3, 1), [ - new SmoothElevationPainter(ELEVATION_SET, 3, 4), + new SmoothElevationPainter(ELEVATION_SET, heightShore, 4), unPaintClass(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); var playerConstraint = new AvoidTileClassConstraint(clPlayer, 30); var minesConstraint = new AvoidTileClassConstraint(clRock, 25); var waterConstraint = new AvoidTileClassConstraint(clWater, 10); log("Creating stone mines..."); for (let i = 0; i < scaleByMapSize(12, 30); ++i) { let mX = randIntInclusive(1, mapSize - 1); let mZ = randIntInclusive(1, mapSize - 1); if (playerConstraint.allows(mX, mZ) && minesConstraint.allows(mX, mZ) && waterConstraint.allows(mX, mZ)) { createStoneMineFormation(mX, mZ, oStoneSmall, tDirt4); addToClass(mX, mZ, clRock); } } 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); 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); 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 ); 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 ); log("Creating crocodiles..."); createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject(oCrocodile, 2, 4, 0, 4)], true, clFood ), 0, stayClasses(clWater, 1), scaleByMapSize(4, 12), 50 ); 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 ); 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); 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, 7, clMetal, 2), randIntInclusive(1, 4) * numPlayers + 2, 50 ); Engine.SetProgress(85); log("Creating trees..."); createObjectGroupsDeprecated( new SimpleGroup( [new SimpleObject(oTree, 1, 7, 0, 3)], true, clForest ), 0, avoidClasses(clForest, 1, clPlayer, 20, clMetal, 1, clRock, 7, clWater, 1), scaleByMapSize(70, 500) ); 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); setUnitsAmbientColor(0.57, 0.58, 0.55); setTerrainAmbientColor(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); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/islands.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/islands.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/islands.js (revision 20904) @@ -1,360 +1,364 @@ Engine.LoadLibrary("rmgen"); 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/special_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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightSeaGround = -5; +const heightLand = 3; +const heightOffsetBump = 2; +const heightHill = 18; + +InitMap(heightSeaGround, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clLand = createTileClass(); -var landHeight = 3; var playerIslandRadius = scaleByMapSize(20, 29); var [playerIDs, playerPosition, playerAngle] = playerPlacementCircle(fractionToTiles(0.35)); if (!isNomad()) { log("Creating player islands and docks..."); for (let i = 0; i < numPlayers; i++) { createArea( new ClumpPlacer(diskArea(playerIslandRadius), 0.8, 0.1, 10, playerPosition[i].x, playerPosition[i].y), [ new LayeredPainter([tMainTerrain , tMainTerrain, tMainTerrain], [1, 6]), - new SmoothElevationPainter(ELEVATION_SET, landHeight, 6), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 6), paintClass(clLand), paintClass(clPlayer) ]); - let dockLocation = findLocationInDirectionBasedOnHeight(playerPosition[i], mapCenter, -3 , landHeight - 0.5, landHeight); + let dockLocation = findLocationInDirectionBasedOnHeight(playerPosition[i], mapCenter, -3 , heightLand - 0.5, heightLand); placeObject(dockLocation.x, dockLocation.y, oDock, playerIDs[i], playerAngle[i] + Math.PI); } } 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 LayeredPainter([tMainTerrain, tMainTerrain], [2]), - new SmoothElevationPainter(ELEVATION_SET, landHeight, 6), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 6), paintClass(clLand) ], avoidClasses(clLand, scaleByMapSize(8, 12)), scaleByMapSize(4, 14)); 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 LayeredPainter([tMainTerrain, tMainTerrain], [2]), - new SmoothElevationPainter(ELEVATION_SET, landHeight, 6), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 6), paintClass(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": { }, "Berries": { "template": oFruitBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Treasures": { "types": [ { "template": oWoodTreasure, "count": 14 } ] }, "Trees": { "template": oTree1, "count": 5 }, "Decoratives": { "template": aGrassShort } }); log("Creating bumps..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1), - new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), [avoidClasses(clPlayer, 0), stayClasses(clLand, 3)], scaleByMapSize(20, 100)); 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, 18, 2), + new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), paintClass(clHill) ], [avoidClasses(clPlayer, 2, clHill, 15), stayClasses(clLand, 0)], scaleByMapSize(4, 13)); log("Creating forests..."); var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(1)); var types = [ [[tForestFloor2, tMainTerrain, pForest1], [tForestFloor2, pForest1]], [[tForestFloor1, tMainTerrain, pForest2], [tForestFloor1, pForest2]] ]; if (currentBiome() != "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]), paintClass(clForest) ], [avoidClasses(clPlayer, 0, clForest, 10, clHill, 0), stayClasses(clLand, 6)], num); } Engine.SetProgress(50); log("Creating dirt patches..."); var numberOfPatches = scaleByMapSize(15, 45) * (currentBiome() == "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]), paintClass(clDirt) ], [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 0), stayClasses(clLand, 6)], numberOfPatches); 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); log("Creating stone mines..."); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4), new SimpleObject(oStoneLarge, 1, 1, 0, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 1, clPlayer, 0, clRock, 10, clHill, 1), stayClasses(clLand, 5)], scaleByMapSize(4,16), 100 ); 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 ); 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); 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 ); 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); 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); 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 ); 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 ); 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() == "tropic") planetm = 8; 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); 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); 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); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/lake.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/lake.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/lake.js (revision 20904) @@ -1,250 +1,253 @@ Engine.LoadLibrary("rmgen"); 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 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]; -InitMap(g_MapSettings.BaseHeight, tMainTerrain); +const heightSeaGround = -3; +const heightLand = 3; + +InitMap(heightLand, tMainTerrain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); log("Preventing water in player territory..."); for (let i = 0; i < numPlayers; ++i) addCivicCenterAreaToClass(playerPosition[i], clPlayer); log("Creating the lake...") createArea( new ChainPlacer( 2, Math.floor(scaleByMapSize(5, 16)), Math.floor(scaleByMapSize(35, 200)), 1, mapCenter.x, mapCenter.y, 0, [Math.floor(fractionToTiles(0.2))]), [ - new SmoothElevationPainter(ELEVATION_SET, -3, 4), + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4), paintClass(clWater) ], avoidClasses(clPlayer, 20)); log("Creating more shore jaggedness..."); createAreas( new ChainPlacer(2, Math.floor(scaleByMapSize(4, 6)), 3, 1), [ new LayeredPainter([tCliff, tHill], [2]), unPaintClass(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": { }, "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); 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); 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); 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); log("Creating stone mines..."); createMines( [ [new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), clRock); 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(65); var planetm = 1; if (currentBiome() == "tropic") 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)] ], [ scaleByMapSize(16, 262), scaleByMapSize(8, 131), planetm * scaleByMapSize(13, 200), planetm * scaleByMapSize(13, 200), planetm * scaleByMapSize(13, 200) ], 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"); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/lions_den.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/lions_den.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/lions_den.js (revision 20904) @@ -1,562 +1,567 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen2"); Engine.LoadLibrary("rmbiome"); setSelectedBiome(); const topTerrain = g_Terrains.tier2Terrain; -const valleyHeight = 0; -const pathHeight = 10; -const denHeight = 15; -const hillHeight = getMapBaseHeight(); +const heightValley = 0; +const heightPath = 10; +const heightDen = 15; +const heightHill = 50; + +InitMap(heightHill, topTerrain); -InitMap(hillHeight, topTerrain); const mapArea = getMapArea(); const mapCenter = getMapCenter(); const numPlayers = getNumPlayers(); const startAngle = randomAngle(); initTileClasses(["step"]); createArea( new MapBoundsPlacer(), paintClass(g_TileClasses.land)); Engine.SetProgress(10); addBases("radial", fractionToTiles(0.4), fractionToTiles(randFloat(0.05, 0.1)), startAngle); Engine.SetProgress(20); createSunkenTerrain(); Engine.SetProgress(30); addElements([ { "func": addLayeredPatches, "avoid": [ g_TileClasses.baseResource, 5, g_TileClasses.dirt, 5, g_TileClasses.forest, 2, g_TileClasses.mountain, 2, g_TileClasses.player, 12, g_TileClasses.step, 5 ], "stay": [g_TileClasses.valley, 7], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["normal"] }, { "func": addLayeredPatches, "avoid": [ g_TileClasses.baseResource, 5, g_TileClasses.dirt, 5, g_TileClasses.forest, 2, g_TileClasses.mountain, 2, g_TileClasses.player, 12 ], "stay": [g_TileClasses.settlement, 7], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["normal"] }, { "func": addLayeredPatches, "avoid": [ g_TileClasses.baseResource, 5, g_TileClasses.dirt, 5, g_TileClasses.forest, 2 ], "stay": [g_TileClasses.player, 1], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["normal"] }, { "func": addDecoration, "avoid": [ g_TileClasses.baseResource, 5, g_TileClasses.forest, 2 ], "stay": [g_TileClasses.player, 1], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["normal"] }, { "func": addDecoration, "avoid": [ g_TileClasses.baseResource, 5, g_TileClasses.forest, 2, g_TileClasses.mountain, 2, g_TileClasses.player, 12, g_TileClasses.step, 2 ], "stay": [g_TileClasses.valley, 7], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["normal"] }, { "func": addDecoration, "avoid": [ g_TileClasses.baseResource, 5, g_TileClasses.forest, 2, g_TileClasses.mountain, 2, g_TileClasses.player, 12 ], "stay": [g_TileClasses.settlement, 7], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["normal"] }, { "func": addDecoration, "avoid": [ g_TileClasses.baseResource, 5, g_TileClasses.forest, 2, g_TileClasses.mountain, 2, g_TileClasses.player, 12 ], "stay": [g_TileClasses.step, 7], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["scarce"] } ]); Engine.SetProgress(40); addElements(shuffleArray([ { "func": addMetal, "avoid": [ g_TileClasses.baseResource, 5, g_TileClasses.berries, 5, g_TileClasses.forest, 3, g_TileClasses.player, 30, g_TileClasses.rock, 10, g_TileClasses.metal, 20 ], "stay": [g_TileClasses.settlement, 7], "sizes": ["normal"], "mixes": ["same"], "amounts": ["tons"] }, { "func": addMetal, "avoid": [ g_TileClasses.baseResource, 5, g_TileClasses.berries, 5, g_TileClasses.forest, 3, g_TileClasses.player, 10, g_TileClasses.rock, 10, g_TileClasses.metal, 20, g_TileClasses.mountain, 5, g_TileClasses.step, 5 ], "stay": [g_TileClasses.valley, 7], "sizes": ["normal"], "mixes": ["same"], "amounts": g_AllAmounts }, { "func": addStone, "avoid": [ g_TileClasses.baseResource, 5, g_TileClasses.berries, 5, g_TileClasses.forest, 3, g_TileClasses.player, 30, g_TileClasses.rock, 20, g_TileClasses.metal, 10 ], "stay": [g_TileClasses.settlement, 7], "sizes": ["normal"], "mixes": ["same"], "amounts": ["tons"] }, { "func": addStone, "avoid": [ g_TileClasses.baseResource, 5, g_TileClasses.berries, 5, g_TileClasses.forest, 3, g_TileClasses.player, 10, g_TileClasses.rock, 20, g_TileClasses.metal, 10, g_TileClasses.mountain, 5, g_TileClasses.step, 5 ], "stay": [g_TileClasses.valley, 7], "sizes": ["normal"], "mixes": ["same"], "amounts": g_AllAmounts }, { "func": addForests, "avoid": [ g_TileClasses.baseResource, 5, g_TileClasses.berries, 5, g_TileClasses.forest, 18, g_TileClasses.metal, 3, g_TileClasses.player, 20, g_TileClasses.rock, 3 ], "stay": [g_TileClasses.settlement, 7], "sizes": ["normal", "big"], "mixes": ["same"], "amounts": ["tons"] }, { "func": addForests, "avoid": [ g_TileClasses.baseResource, 5, g_TileClasses.berries, 3, g_TileClasses.forest, 18, g_TileClasses.metal, 3, g_TileClasses.mountain, 5, g_TileClasses.player, 5, g_TileClasses.rock, 3, g_TileClasses.step, 1 ], "stay": [g_TileClasses.valley, 7], "sizes": ["normal", "big"], "mixes": ["same"], "amounts": ["tons"] } ])); Engine.SetProgress(60); addElements(shuffleArray([ { "func": addBerries, "avoid": [ g_TileClasses.baseResource, 5, g_TileClasses.berries, 30, g_TileClasses.forest, 5, g_TileClasses.metal, 10, g_TileClasses.player, 20, g_TileClasses.rock, 10 ], "stay": [g_TileClasses.settlement, 7], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": ["tons"] }, { "func": addBerries, "avoid": [ g_TileClasses.baseResource, 5, g_TileClasses.berries, 30, g_TileClasses.forest, 5, g_TileClasses.metal, 10, g_TileClasses.mountain, 5, g_TileClasses.player, 10, g_TileClasses.rock, 10, g_TileClasses.step, 5 ], "stay": [g_TileClasses.valley, 7], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": g_AllAmounts }, { "func": addAnimals, "avoid": [ g_TileClasses.animals, 20, g_TileClasses.baseResource, 5, g_TileClasses.forest, 0, g_TileClasses.metal, 1, g_TileClasses.player, 20, g_TileClasses.rock, 1 ], "stay": [g_TileClasses.settlement, 7], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": ["tons"] }, { "func": addAnimals, "avoid": [ g_TileClasses.animals, 20, g_TileClasses.baseResource, 5, g_TileClasses.forest, 0, g_TileClasses.metal, 1, g_TileClasses.mountain, 5, g_TileClasses.player, 10, g_TileClasses.rock, 1, g_TileClasses.step, 5 ], "stay": [g_TileClasses.valley, 7], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": g_AllAmounts }, { "func": addStragglerTrees, "avoid": [ g_TileClasses.baseResource, 5, g_TileClasses.berries, 5, g_TileClasses.forest, 7, g_TileClasses.metal, 3, g_TileClasses.player, 12, g_TileClasses.rock, 3 ], "stay": [g_TileClasses.settlement, 7], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": ["tons"] }, { "func": addStragglerTrees, "avoid": [ g_TileClasses.baseResource, 5, g_TileClasses.berries, 5, g_TileClasses.forest, 7, g_TileClasses.metal, 3, g_TileClasses.mountain, 5, g_TileClasses.player, 10, g_TileClasses.rock, 3, g_TileClasses.step, 5 ], "stay": [g_TileClasses.valley, 7], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": ["normal", "many", "tons"] }, { "func": addStragglerTrees, "avoid": [ g_TileClasses.player, 10, g_TileClasses.baseResource, 5, g_TileClasses.berries, 5, g_TileClasses.forest, 3, g_TileClasses.metal, 5, g_TileClasses.rock, 5 ], "stay": [g_TileClasses.player, 1], "sizes": ["huge"], "mixes": ["same"], "amounts": ["tons"] } ])); Engine.SetProgress(75); addElements([ { "func": addDecoration, "avoid": [ g_TileClasses.baseResource, 5, g_TileClasses.valley, 4, g_TileClasses.player, 4, g_TileClasses.settlement, 4, g_TileClasses.step, 4 ], "stay": [g_TileClasses.land, 2], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["tons"] } ]); Engine.SetProgress(80); addElements([ { "func": addProps, "avoid": [ g_TileClasses.baseResource, 5, g_TileClasses.valley, 4, g_TileClasses.player, 4, g_TileClasses.settlement, 4, g_TileClasses.step, 4 ], "stay": [g_TileClasses.land, 2], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["scarce"] } ]); Engine.SetProgress(85); addElements([ { "func": addDecoration, "avoid": [ g_TileClasses.baseResource, 5, g_TileClasses.player, 4, g_TileClasses.settlement, 4, g_TileClasses.step, 4 ], "stay": [g_TileClasses.mountain, 2], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["tons"] } ]); Engine.SetProgress(90); addElements([ { "func": addProps, "avoid": [ g_TileClasses.baseResource, 5, g_TileClasses.player, 4, g_TileClasses.settlement, 4, g_TileClasses.step, 4 ], "stay": [g_TileClasses.mountain, 2], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["scarce"] } ]); Engine.SetProgress(95); placePlayersNomad( g_TileClasses.player, [ - new HeightConstraint(valleyHeight, pathHeight), + new HeightConstraint(heightValley, heightPath), avoidClasses( g_TileClasses.forest, 1, g_TileClasses.metal, 4, g_TileClasses.rock, 4, g_TileClasses.animals, 2) ]); ExportMap(); function createSunkenTerrain() { var base = g_Terrains.mainTerrain; var middle = g_Terrains.dirt; var lower = g_Terrains.tier2Terrain; var road = g_Terrains.road; if (currentBiome() == "snowy") { middle = g_Terrains.tier2Terrain; lower = g_Terrains.tier1Terrain; } if (currentBiome() == "alpine") { middle = g_Terrains.shore; lower = g_Terrains.tier4Terrain; } if (currentBiome() == "mediterranean") { middle = g_Terrains.tier1Terrain; lower = g_Terrains.forestFloor1; } if (currentBiome() == "savanna") { middle = g_Terrains.tier2Terrain; lower = g_Terrains.tier4Terrain; } if (currentBiome() == "tropic" || currentBiome() == "autumn") road = g_Terrains.roadWild; if (currentBiome() == "autumn") middle = g_Terrains.shore; var expSize = mapArea * 0.015 / (numPlayers / 4); var expDist = 0.1 + numPlayers / 200; var expAngle = 0.75; if (numPlayers == 2) { expSize = mapArea * 0.015 / 0.8; expAngle = 0.72; } var nRoad = 0.44; var nExp = 0.425; if (numPlayers < 4) { nRoad = 0.42; nExp = 0.4; } log("Creating central valley..."); createArea( new ClumpPlacer(mapArea * 0.26, 1, 1, 1, mapCenter.x, mapCenter.y), [ new LayeredPainter([g_Terrains.cliff, lower], [3]), - new SmoothElevationPainter(ELEVATION_SET, valleyHeight, 3), + new SmoothElevationPainter(ELEVATION_SET, heightValley, 3), paintClass(g_TileClasses.valley) ]); log("Creating central hill..."); createArea( new ClumpPlacer(mapArea * 0.14, 1, 1, 1, mapCenter.x, mapCenter.y), [ new LayeredPainter([g_Terrains.cliff, topTerrain], [3]), - new SmoothElevationPainter(ELEVATION_SET, hillHeight, 3), + new SmoothElevationPainter(ELEVATION_SET, heightHill, 3), paintClass(g_TileClasses.mountain) ]); let getCoords = (distance, playerID, playerIDOffset) => { let angle = startAngle + (playerID + playerIDOffset) * 2 * Math.PI / numPlayers; - return [ - Math.round(fractionToTiles(0.5 + distance * Math.cos(angle))), - Math.round(fractionToTiles(0.5 + distance * Math.sin(angle))) - ]; + return Vector2D.add(mapCenter, new Vector2D(fractionToTiles(distance), 0).rotate(-angle)).round(); }; for (let i = 0; i < numPlayers; ++i) { - let playerCoords = getCoords(0.4, i, 0); + let playerPosition = getCoords(0.4, i, 0); log("Creating path from player to expansion..."); - let expansionCoords = getCoords(expDist, i, expAngle); + let expansionPosition = getCoords(expDist, i, expAngle); createArea( - new PathPlacer(...playerCoords, ...expansionCoords, 12, 0.7, 0.5, 0.1, -1), + new PathPlacer(playerPosition.x, playerPosition.y, expansionPosition.x, expansionPosition.y, 12, 0.7, 0.5, 0.1, -1), [ new LayeredPainter([g_Terrains.cliff, middle, road], [3, 4]), - new SmoothElevationPainter(ELEVATION_SET, pathHeight, 3), + new SmoothElevationPainter(ELEVATION_SET, heightPath, 3), paintClass(g_TileClasses.step) ]); log("Creating path from player to the neighbor..."); for (let neighborOffset of [-0.5, 0.5]) + { + let neighborPosition = getCoords(nRoad, i, neighborOffset); + let pathPosition = getCoords(0.47, i, 0); createArea( - new PathPlacer(...getCoords(0.47, i, 0), ...getCoords(nRoad, i, neighborOffset), 19, 0.4, 0.5, 0.1, -0.6), + new PathPlacer(pathPosition.x, pathPosition.y, neighborPosition.x, neighborPosition.y, 19, 0.4, 0.5, 0.1, -0.6), [ new LayeredPainter([g_Terrains.cliff, middle, road], [3, 6]), - new SmoothElevationPainter(ELEVATION_SET, pathHeight, 3), + new SmoothElevationPainter(ELEVATION_SET, heightPath, 3), paintClass(g_TileClasses.step) ]); + } log("Creating the den of the player..."); createArea( - new ClumpPlacer(mapArea * 0.03 / (isNomad() ? 2 : 1), 0.9, 0.3, 1, ...playerCoords), + new ClumpPlacer(mapArea * 0.03 / (isNomad() ? 2 : 1), 0.9, 0.3, 1, playerPosition.x, playerPosition.y), [ new LayeredPainter([g_Terrains.cliff, base], [3]), - new SmoothElevationPainter(ELEVATION_SET, denHeight, 3), + new SmoothElevationPainter(ELEVATION_SET, heightDen, 3), paintClass(g_TileClasses.valley) ]); log("Creating the expansion of the player..."); createArea( - new ClumpPlacer(expSize, 0.9, 0.3, 1, ...expansionCoords), + new ClumpPlacer(expSize, 0.9, 0.3, 1, expansionPosition.x, expansionPosition.y), [ new LayeredPainter([g_Terrains.cliff, base], [3]), - new SmoothElevationPainter(ELEVATION_SET, denHeight, 3), + new SmoothElevationPainter(ELEVATION_SET, heightDen, 3), paintClass(g_TileClasses.settlement) ], [avoidClasses(g_TileClasses.settlement, 2)]); } log("Creating the expansions between players after the paths were created..."); for (let i = 0; i < numPlayers; ++i) + { + let position = getCoords(nExp, i, 0.5); createArea( - new ClumpPlacer(expSize, 0.9, 0.3, 1, ...getCoords(nExp, i, 0.5)), + new ClumpPlacer(expSize, 0.9, 0.3, 1, position.x, position.y), [ new LayeredPainter([g_Terrains.cliff, lower], [3]), - new SmoothElevationPainter(ELEVATION_SET, valleyHeight, 3), + new SmoothElevationPainter(ELEVATION_SET, heightValley, 3), paintClass(g_TileClasses.settlement) ]); + } } Index: ps/trunk/binaries/data/mods/public/maps/random/mainland.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/mainland.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/mainland.js (revision 20904) @@ -1,194 +1,196 @@ Engine.LoadLibrary("rmgen"); 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 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]; -InitMap(g_MapSettings.BaseHeight, tMainTerrain); +const heightLand = 3; + +InitMap(heightLand, tMainTerrain); const numPlayers = getNumPlayers(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, "Chicken": { }, "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)); createForests( [tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2], avoidClasses(clPlayer, 20, clForest, 18, clHill, 0), clForest, forestTrees); Engine.SetProgress(50); 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); 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); log("Creating stone mines..."); createMines( [ [new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), clRock); log("Creating metal mines..."); createMines( [ [new SimpleObject(oMetalLarge, 1,1, 0,4)] ], avoidClasses(clForest, 1, clPlayer, 20, clMetal, 10, clRock, 5, clHill, 1), clMetal ); Engine.SetProgress(65); var planetm = 1; if (currentBiome() == "tropic") 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)] ], [ scaleByMapSize(16, 262), scaleByMapSize(8, 131), planetm * scaleByMapSize(13, 200), planetm * scaleByMapSize(13, 200), planetm * scaleByMapSize(13, 200) ], 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, clFood, 20), clFood); Engine.SetProgress(75); createFood( [ [new SimpleObject(oFruitBush, 5, 7, 0, 4)] ], [ 3 * numPlayers ], avoidClasses(clForest, 0, clPlayer, 20, clHill, 1, clFood, 10), clFood); Engine.SetProgress(85); createStragglerTrees( [oTree1, oTree2, oTree4, oTree3], avoidClasses(clForest, 8, clHill, 1, clPlayer, 12, clMetal, 6, clRock, 6), clForest, stragglerTrees); placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); 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 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/neareastern_badlands.js (revision 20904) @@ -1,363 +1,366 @@ Engine.LoadLibrary("rmgen"); const tCity = "desert_city_tile"; const tCityPlaza = "desert_city_tile_plaza"; const tSand = "desert_dirt_rough"; const tDunes = "desert_sand_dunes_100"; const tFineSand = "desert_sand_smooth"; const tCliff = ["desert_cliff_badlands", "desert_cliff_badlands_2"]; const tForestFloor = "desert_forestfloor_palms"; const tGrass = "desert_grass_a"; const tGrassSand25 = "desert_grass_a_stones"; const tDirt = "desert_dirt_rough"; const tShore = "desert_shore_stones"; const tWaterDeep = "desert_shore_stones_wet"; const oBerryBush = "gaia/flora_bush_grapes"; const oCamel = "gaia/fauna_camel"; const oFish = "gaia/fauna_fish"; const oGazelle = "gaia/fauna_gazelle"; const oGiraffe = "gaia/fauna_giraffe"; const oGoat = "gaia/fauna_goat"; const oWildebeest = "gaia/fauna_wildebeest"; const oStoneLarge = "gaia/geology_stonemine_desert_badlands_quarry"; const oStoneSmall = "gaia/geology_stone_desert_small"; const oMetalLarge = "gaia/geology_metal_desert_slabs"; const oDatePalm = "gaia/flora_tree_date_palm"; const oSDatePalm = "gaia/flora_tree_senegal_date_palm"; 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_dry_a.xml"; const aBush4 = "actor|props/flora/plant_desert_a.xml"; const aBushes = [aBush1, aBush2, aBush3, aBush4]; const aDecorativeRock = "actor|geology/stone_desert_med.xml"; const pForest = [tForestFloor + TERRAIN_SEPARATOR + oDatePalm, tForestFloor + TERRAIN_SEPARATOR + oSDatePalm, tForestFloor]; const pForestOasis = [tGrass + TERRAIN_SEPARATOR + oDatePalm, tGrass + TERRAIN_SEPARATOR + oSDatePalm, tGrass]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightLand = 10; + +const heightOffsetOasis = -11; +const heightOffsetHill1 = 16; +const heightOffsetHill2 = 16; +const heightOffsetHill3 = 16; +const heightOffsetBump = 2; + +InitMap(heightLand, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clHill1 = createTileClass(); var clOasis = createTileClass(); var clForest = createTileClass(); var clPatch = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var oasisRadius = scaleByMapSize(14, 40); -var oasisHeight = -11; - -var hillHeight1 = 16; -var hillHeight2 = 16; -var hillHeight3 = 16; 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, 10, playerPosition[i].x, playerPosition[i].y), paintClass(clPlayer)); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tCity, "innerTerrain": tCityPlaza, "width": 3, "radius": 10 }, "Chicken": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oDatePalm } // No decoratives }); Engine.SetProgress(10); log("Creating dune patches..."); createAreas( new ClumpPlacer(scaleByMapSize(40, 150), 0.2, 0.1, 0), [ new TerrainPainter(tDunes), paintClass(clPatch) ], avoidClasses(clPatch, 2, clPlayer, 0), scaleByMapSize(5, 20)); Engine.SetProgress(15); log("Creating sand patches..."); createAreas( new ClumpPlacer(scaleByMapSize(25, 100), 0.2, 0.1, 0), [ new TerrainPainter([tSand, tFineSand]), paintClass(clPatch) ], avoidClasses(clPatch, 2, clPlayer, 0), scaleByMapSize(15, 50)); Engine.SetProgress(20); log("Creating dirt patches..."); createAreas( new ClumpPlacer(scaleByMapSize(25, 100), 0.2, 0.1, 0), [ new TerrainPainter([tDirt]), paintClass(clPatch) ], avoidClasses(clPatch, 2, clPlayer, 0), scaleByMapSize(15, 50)); Engine.SetProgress(25); log("Creating oasis..."); createArea( new ClumpPlacer(diskArea(oasisRadius), 0.6, 0.15, 0, mapCenter.x, mapCenter.y), [ new LayeredPainter([[tSand, pForest], [tGrassSand25, pForestOasis], tGrassSand25, tShore, tWaterDeep], [2, 3, 1, 1]), - new SmoothElevationPainter(ELEVATION_MODIFY, oasisHeight, 8), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetOasis, 8), paintClass(clOasis) ]); Engine.SetProgress(30); log("Creating oasis wildlife..."); var num = Math.round(Math.PI * oasisRadius / 8); var constraint = new AndConstraint([borderClasses(clOasis, 0, 3), avoidClasses(clOasis, 0)]); var halfSize = mapSize/2; for (var i = 0; i < num; ++i) { var r = 0; var angle = 2 * Math.PI / num * i; do { // Work outward until constraint met var gx = Math.round(halfSize + r * Math.cos(angle)); var gz = Math.round(halfSize + r * Math.sin(angle)); ++r; } while (!constraint.allows(gx,gz) && r < halfSize); 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, gx, gz), 0); } constraint = new AndConstraint([borderClasses(clOasis, 15, 0), avoidClasses(clFood, 5)]); num = Math.round(Math.PI * oasisRadius / 16); for (var i = 0; i < num; ++i) { var r = 0; var angle = 2 * Math.PI / num * i; do { // Work outward until constraint met var gx = Math.round(halfSize + r * Math.cos(angle)); var gz = Math.round(halfSize + r * Math.sin(angle)); ++r; } while (!constraint.allows(gx,gz) && r < halfSize); group = new SimpleGroup( [new SimpleObject(oFish, 1,1, 0,1)], true, clFood, gx, gz ); createObjectGroup(group, 0); } Engine.SetProgress(35); 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, hillHeight1, 1), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetHill1, 1), paintClass(clHill1) ], avoidClasses(clOasis, 3, clPlayer, 0, clHill1, 10), scaleByMapSize(10,20), 100 ); Engine.SetProgress(40); 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, hillHeight2, 1), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetHill2, 1), paintClass(clHill1) ], avoidClasses(clOasis, 3, clPlayer, 0, clHill1, 3), scaleByMapSize(15,25), 100)); Engine.SetProgress(45); 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); 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, hillHeight2, 1) + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetHill2, 1) ], [stayClasses(clHill1, 0)], scaleByMapSize(15, 25), 50, hillAreas); Engine.SetProgress(55); 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, hillHeight3, 1) + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetHill3, 1) ], [stayClasses(clHill1, 0)], scaleByMapSize(15,25), 50 ); Engine.SetProgress(60); log("Creating bumps..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 0), - new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), avoidClasses(clOasis, 0, clPlayer, 0, clHill1, 2), scaleByMapSize(100, 200) ); Engine.SetProgress(65); log("Creating forests..."); var [forestTrees, stragglerTrees] = getTreeCounts(500, 2500, 0.5); var num = scaleByMapSize(10,30); createAreas( new ClumpPlacer(forestTrees / num, 0.15, 0.1, 0.5), [ new TerrainPainter([tSand, pForest]), paintClass(clForest) ], avoidClasses(clPlayer, 1, clOasis, 10, clForest, 10, clHill1, 1), num, 50); Engine.SetProgress(70); log("Creating stone mines..."); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4), new SimpleObject(oStoneLarge, 1, 1, 0, 4), new RandomObject(aBushes, 2, 4, 0, 2)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clOasis, 1, clForest, 1, clPlayer, 10, clRock, 10, clHill1, 1)], scaleByMapSize(4,16), 100 ); group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3), new RandomObject(aBushes, 2,4, 0,2)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clOasis, 1, clForest, 1, clPlayer, 10, clRock, 10, clHill1, 1)], scaleByMapSize(4,16), 100 ); 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(clOasis, 1, clForest, 1, clPlayer, 10, clMetal, 10, clRock, 5, clHill1, 1)], scaleByMapSize(4,16), 100 ); Engine.SetProgress(80); log("Creating gazelles..."); 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 ); 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 ); 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); 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) ); 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)); setWaterColor(0, 0.227, 0.843); setWaterTint(0, 0.545, 0.859); setWaterWaviness(1.0); setWaterType("clap"); setWaterMurkiness(0.75); setWaterHeight(20); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/frontier.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/frontier.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/frontier.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "Frontier", "Script" : "frontier.js", "Description" : "A wild, unknown landscape awaits rival explorers.", "BaseTerrain" : ["medit_sea_depths"], "Preview" : "frontier.png", - "BaseHeight" : 2, "SupportedBiomes": true, "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/guadalquivir_river.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/guadalquivir_river.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/guadalquivir_river.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Guadalquivir River", "Script" : "guadalquivir_river.js", "Description" : "Players start in the shores of the Mediterranean Sea with a river flowing between them.\n\nThe Guadalquivir is the fifth longest river in the Iberian peninsula and the second longest river with its entire length in Spain. The Guadalquivir river is the only great navigable river in Spain. Currently it is navigable to Seville, but in Roman times it was navigable to Cordoba. The ancient city of Tartessos was said to have been located at the mouth of the Guadalquivir, although its site has not yet been found.", "BaseTerrain" : ["medit_sand_wet"], - "BaseHeight" : -5, "Preview" : "guadalquivir_river.png", "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/harbor.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/harbor.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/harbor.json (revision 20904) @@ -1,13 +1,12 @@ { "settings" : { "Name" : "Harbor", "Script" : "harbor.js", "Description" : "Players start with some light fishing opportunities in the calm waters of a sheltered harbor. A large bounty of seafood lays beyond the protective cliffs in the deep ocean. Small passages at the base of the cliffs make for tight fighting and easy fortification. Will you fight your way through the narrow passageways or take to the sea?", "BaseTerrain" : ["medit_sea_depths"], - "BaseHeight" : 2, "Keywords": [], "Preview" : "harbor.png", "SupportedBiomes": true, "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/hyrcanian_shores.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/hyrcanian_shores.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/hyrcanian_shores.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Hyrcanian Shores", "Script" : "hyrcanian_shores.js", "Description" : "Each player starts in a coastal area between forested hills and the Caspian Sea.", "BaseTerrain" : ["temp_grass_long"], - "BaseHeight" : 1, "Preview" : "hyrcanian_shores.png", "CircularMap" : true } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/island_stronghold.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/island_stronghold.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/island_stronghold.json (revision 20904) @@ -1,21 +1,20 @@ { "settings" : { "Name" : "Island Stronghold", "Script" : "island_stronghold.js", "Description" : "Teams start off with nearly adjacent civic centers on a small island, offering a fortified base from which to expand.", "BaseTerrain" : ["medit_sand_wet"], - "BaseHeight" : -10, "Keywords": ["naval"], "Preview" : "island_stronghold.png", "SupportedBiomes": [ "temperate", "snowy", "desert", "alpine", "mediterranean", "tropic", "autumn" ], "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/kerala.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/kerala.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/kerala.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Kerala", "Script" : "kerala.js", "Description" : "Players start in the southwestern shores of India between a sea and mountains.", "BaseTerrain" : ["tropic_grass_c", "tropic_grass_c", "tropic_grass_c", "tropic_grass_c", "tropic_grass_plants", "tropic_plants", "tropic_plants_b"], - "BaseHeight" : 3, "Preview" : "kerala.png", "CircularMap" : true } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/latium.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/latium.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/latium.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Latium", "Script" : "latium.js", "Description" : "The Italian peninsula \n\n Latium is the region of central western Italy in which the city of Rome was founded and grew to be the capital city of the Roman Empire. Latium was originally a small triangle of fertile, volcanic soil on which resided the tribe of the Latins. It was located on the left bank (east and south) of the Tiber river, extending northward to the Anio river (a left-bank tributary of the Tiber) and southeastward to the Pomptina Palus (Pontine Marshes, now the Pontine Fields) as far south as the Circeian promontory. The right bank of the Tiber was occupied by the Etruscan city of Veii, and the other borders were occupied by Italic tribes. Subsequently Rome defeated Veii and then its Italic neighbors, expanding Latium to the Apennine Mountains in the northeast and to the opposite end of the marsh in the southeast. The modern descendant, the Italian Regione of Lazio, also called Latium in Latin, and occasionally in modern English, is somewhat larger still, but not as much as double the original Latium.", "BaseTerrain" : ["medit_grass_field_dry", "medit_grass_field_brown", "medit_grass_field_b"], - "BaseHeight" : 0, "Preview" : "latium.png", "CircularMap" : false } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/lorraine_plain.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/lorraine_plain.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/lorraine_plain.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Lorraine Plain", "Script" : "lorraine_plain.js", "Description" : "Players start in a nearly flat Gallic plain divided by a river and its tributaries.", "BaseTerrain" : ["temp_grass_long"], - "BaseHeight" : 3, "Preview" : "lorraine_plain.png", "CircularMap" : true } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/migration.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/migration.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/migration.json (revision 20904) @@ -1,13 +1,12 @@ { "settings" : { "Name" : "Migration", "Script" : "migration.js", "Description" : "Players start in small islands in the eastern part of the map. There is a big continent in the west ready for expansion.", "BaseTerrain" : ["medit_sand_wet"], - "BaseHeight" : -5, "Keywords": ["naval"], "Preview" : "migration.png", "SupportedBiomes": true, "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/new_rms_test.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/new_rms_test.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/new_rms_test.json (revision 20904) @@ -1,10 +1,9 @@ { "settings" : { "Name" : "New RMS Test", "Script" : "new_rms_test.js", "Description" : "A basic test of the random map generator - not playable.", "BaseTerrain" : "grass1_spring", - "BaseHeight" : 0, "Keywords": ["demo"] } } Index: ps/trunk/binaries/data/mods/public/maps/random/fortress.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/fortress.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/fortress.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Fortress", "Script" : "fortress.js", "Description" : "Players start in a ready-made fortress with piles of resources.", "BaseTerrain" : ["temp_grass_aut", "temp_grass_aut", "temp_grass_d_aut"], - "BaseHeight" : 3, "CircularMap" : true, "Preview" : "fortress.png" } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/guadalquivir_river.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/guadalquivir_river.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/guadalquivir_river.js (revision 20904) @@ -1,282 +1,282 @@ Engine.LoadLibrary("rmgen"); 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/flora_tree_poplar"; const oApple = "gaia/flora_tree_apple"; const oCarob = "gaia/flora_tree_carob"; const oBerryBush = "gaia/flora_bush_berry"; const oDeer = "gaia/fauna_deer"; const oFish = "gaia/fauna_fish"; const oSheep = "gaia/fauna_sheep"; const oStoneLarge = "gaia/geology_stonemine_medit_quarry"; const oStoneSmall = "gaia/geology_stone_mediterranean"; const oMetalLarge = "gaia/geology_metal_mediterranean_slabs"; 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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +var heightSeaGround = -3; +var heightShallow = -1.5; +var heightShore = 2; +var heightLand = 3; + +InitMap(heightSeaGround, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); const mapBounds = getMapBounds(); var clPlayer = createTileClass(); var clForest = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clLand = createTileClass(); var clRiver = createTileClass(); var clShallow = createTileClass(); -var landHeight = 3; -var shoreHeight = 2; -var shallowHeight = -1.5; -var waterHeight = -3; - log("Create the continent body"); var continentCenter = new Vector2D(fractionToTiles(0.5), fractionToTiles(0.7)).round(); createArea( new ChainPlacer( 2, Math.floor(scaleByMapSize(5, 12)), Math.floor(scaleByMapSize(60, 700)), 1, continentCenter.x, continentCenter.y, 0, [Math.floor(fractionToTiles(0.49))]), [ new LayeredPainter([tGrass, tGrass, tGrass], [4, 2]), - new SmoothElevationPainter(ELEVATION_SET, landHeight, 4), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), paintClass(clLand) ]); placePlayerBases({ "PlayerPlacement": [primeSortAllPlayers(), ...playerPlacementCustomAngle( fractionToTiles(0.35), continentCenter, i => Math.PI * (-0.46 / numPlayers * (i + i % 2) - (i % 2) / 2))], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "Walls": false, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, "Chicken": { }, "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), "end": new Vector2D(mapCenter.x, mapBounds.bottom), "width": fractionToTiles(0.07), "fadeDist": scaleByMapSize(3, 12), "deviation": 1, - "waterHeight": waterHeight, - "landHeight": shoreHeight, + "heightRiverbed": heightSeaGround, + "heightLand": heightShore, "meanderShort": 12, "meanderLong": 0, "waterFunc": (ix, iz, height, z) => { addToClass(ix, iz, clRiver); createTerrain(tWater).place(ix, iz); - if (height < shallowHeight && ( + if (height < heightShallow && ( z > 0.3 && z < 0.4 || z > 0.5 && z < 0.6 || z > 0.7 && z < 0.8)) { - setHeight(ix, iz, shallowHeight); + setHeight(ix, iz, heightShallow); addToClass(ix, iz, clShallow); } } }); 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); 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); 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); log("Creating stone mines..."); createMines( [ [new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], [avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clRiver, 1), stayClasses(clLand, 5)], clRock); 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)] ], [ scaleByMapSize(16, 262), scaleByMapSize(8, 131), scaleByMapSize(13, 200), scaleByMapSize(13, 200), scaleByMapSize(13, 200) ], [avoidClasses(clPlayer, 1, clDirt, 1, clRiver, 1), stayClasses(clLand, 6)]); log("Create water decoration in the shallow parts"); createDecoration( [ [new SimpleObject(aReeds, 1, 3, 0, 1)], [new SimpleObject(aLillies, 1, 2, 0, 1)] ], [ scaleByMapSize(800, 12800), scaleByMapSize(800, 12800) ], 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); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/harbor.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/harbor.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/harbor.js (revision 20904) @@ -1,450 +1,433 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen2"); Engine.LoadLibrary("rmbiome"); setSelectedBiome(); -InitMap(g_MapSettings.BaseHeight, g_Terrains.mainTerrain); +var heightSeaGround = -18; +var heightLand = 2; +var heightOffsetHarbor = -11; + +InitMap(heightLand, g_Terrains.mainTerrain); initTileClasses(); setFogFactor(0.04); createArea( new MapBoundsPlacer(), paintClass(g_TileClasses.land)); Engine.SetProgress(10); const mapSize = getMapSize(); const mapCenter = getMapCenter(); const startAngle = randomAngle(); const players = addBases("radial", fractionToTiles(0.38), fractionToTiles(0.05), startAngle); Engine.SetProgress(20); addCenterLake(); Engine.SetProgress(30); if (mapSize >= 192) { addHarbors(players); Engine.SetProgress(40); } addSpines(); Engine.SetProgress(50); addElements(shuffleArray([ { "func": addHills, "avoid": [ g_TileClasses.bluff, 5, g_TileClasses.hill, 15, g_TileClasses.mountain, 2, g_TileClasses.plateau, 5, g_TileClasses.player, 20, g_TileClasses.spine, 5, g_TileClasses.valley, 2, g_TileClasses.water, 2 ], "sizes": ["tiny", "small"], "mixes": g_AllMixes, "amounts": g_AllAmounts }, { "func": addMountains, "avoid": [ g_TileClasses.bluff, 20, g_TileClasses.mountain, 25, g_TileClasses.plateau, 20, g_TileClasses.player, 20, g_TileClasses.spine, 20, g_TileClasses.valley, 10, g_TileClasses.water, 15 ], "sizes": ["small"], "mixes": g_AllMixes, "amounts": g_AllAmounts }, { "func": addPlateaus, "avoid": [ g_TileClasses.bluff, 20, g_TileClasses.mountain, 25, g_TileClasses.plateau, 20, g_TileClasses.player, 40, g_TileClasses.spine, 20, g_TileClasses.valley, 10, g_TileClasses.water, 15 ], "sizes": ["small"], "mixes": g_AllMixes, "amounts": g_AllAmounts }, { "func": addBluffs, - "baseHeight": getMapBaseHeight(), + "baseHeight": heightLand, "avoid": [ g_TileClasses.bluff, 20, g_TileClasses.mountain, 25, g_TileClasses.plateau, 20, g_TileClasses.player, 40, g_TileClasses.spine, 20, g_TileClasses.valley, 10, g_TileClasses.water, 15 ], "sizes": ["normal"], "mixes": g_AllMixes, "amounts": g_AllAmounts } ])); Engine.SetProgress(60); addElements(shuffleArray([ { "func": addMetal, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.bluff, 5, g_TileClasses.forest, 3, g_TileClasses.mountain, 2, g_TileClasses.plateau, 2, g_TileClasses.player, 30, g_TileClasses.rock, 10, g_TileClasses.spine, 5, g_TileClasses.metal, 20, g_TileClasses.water, 3 ], "sizes": ["normal"], "mixes": ["same"], "amounts": ["normal", "many"] }, { "func": addStone, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.bluff, 5, g_TileClasses.forest, 3, g_TileClasses.mountain, 2, g_TileClasses.plateau, 2, g_TileClasses.player, 30, g_TileClasses.rock, 20, g_TileClasses.spine, 5, g_TileClasses.metal, 10, g_TileClasses.water, 3 ], "sizes": ["normal"], "mixes": ["same"], "amounts": ["normal", "many"] }, { "func": addForests, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.bluff, 5, g_TileClasses.forest, 8, g_TileClasses.metal, 3, g_TileClasses.mountain, 5, g_TileClasses.plateau, 5, g_TileClasses.player, 20, g_TileClasses.rock, 3, g_TileClasses.spine, 5, g_TileClasses.water, 2 ], "sizes": ["normal"], "mixes": ["similar"], "amounts": ["many"] } ])); Engine.SetProgress(70); addElements(shuffleArray([ { "func": addBerries, "avoid": [ g_TileClasses.berries, 30, g_TileClasses.bluff, 5, g_TileClasses.forest, 5, g_TileClasses.metal, 10, g_TileClasses.mountain, 2, g_TileClasses.plateau, 2, g_TileClasses.player, 20, g_TileClasses.rock, 10, g_TileClasses.spine, 2, g_TileClasses.water, 3 ], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": g_AllAmounts }, { "func": addAnimals, "avoid": [ g_TileClasses.animals, 20, g_TileClasses.bluff, 5, g_TileClasses.forest, 2, g_TileClasses.metal, 2, g_TileClasses.mountain, 1, g_TileClasses.plateau, 2, g_TileClasses.player, 20, g_TileClasses.rock, 2, g_TileClasses.spine, 2, g_TileClasses.water, 3 ], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": g_AllAmounts }, { "func": addStragglerTrees, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.bluff, 5, g_TileClasses.forest, 7, g_TileClasses.metal, 2, g_TileClasses.mountain, 1, g_TileClasses.plateau, 2, g_TileClasses.player, 12, g_TileClasses.rock, 2, g_TileClasses.spine, 2, g_TileClasses.water, 5 ], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": g_AllAmounts } ])); Engine.SetProgress(80); addElements([ { "func": addLayeredPatches, "avoid": [ g_TileClasses.bluff, 2, g_TileClasses.dirt, 5, g_TileClasses.forest, 2, g_TileClasses.mountain, 2, g_TileClasses.plateau, 2, g_TileClasses.player, 12, g_TileClasses.spine, 5, g_TileClasses.water, 3 ], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["normal"] }, { "func": addDecoration, "avoid": [ g_TileClasses.bluff, 2, g_TileClasses.forest, 2, g_TileClasses.mountain, 2, g_TileClasses.plateau, 2, g_TileClasses.player, 12, g_TileClasses.spine, 5, g_TileClasses.water, 3 ], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["normal"] } ]); Engine.SetProgress(90); placePlayersNomad( g_TileClasses.player, avoidClasses( g_TileClasses.bluff, 4, g_TileClasses.water, 4, g_TileClasses.spine, 4, g_TileClasses.plateau, 4, g_TileClasses.forest, 1, g_TileClasses.metal, 4, g_TileClasses.rock, 4, g_TileClasses.mountain, 4, g_TileClasses.animals, 2)); ExportMap(); function addCenterLake() { createArea( new ChainPlacer( 2, Math.floor(scaleByMapSize(2, 12)), Math.floor(scaleByMapSize(35, 160)), 1, mapCenter.x, mapCenter.y, 0, [Math.floor(fractionToTiles(0.2))]), [ new LayeredPainter( [ g_Terrains.shore, g_Terrains.water, g_Terrains.water ], [1, 100] ), - new SmoothElevationPainter(ELEVATION_SET, -18, 10), + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 10), paintClass(g_TileClasses.water) ], avoidClasses(g_TileClasses.player, 20) ); let fDist = 50; if (mapSize <= 192) fDist = 20; // create a bunch of fish createObjectGroup( new SimpleGroup( [new SimpleObject(g_Gaia.fish, 20, 30, 0, fDist)], true, g_TileClasses.baseResource, mapCenter.x, mapCenter.y ), 0, [ avoidClasses(g_TileClasses.player, 5, g_TileClasses.hill, 3, g_TileClasses.mountain, 3), stayClasses(g_TileClasses.water, 5) ] ); } function addHarbors(players) { for (let player of players) { - let playerPosition = player.position; - let harborPosition = Vector2D.add(playerPosition, Vector2D.sub(mapCenter, playerPosition).div(2.5).round()); - + let harborPosition = Vector2D.add(player.position, Vector2D.sub(mapCenter, player.position).div(2.5).round()); createArea( - new ClumpPlacer(scaleByMapSize(1200, 1200), 0.5, 0.5, 1, harborPosition.x, harborPosition.y), + new ClumpPlacer(1200, 0.5, 0.5, 1, harborPosition.x, harborPosition.y), [ new LayeredPainter([g_Terrains.shore, g_Terrains.water], [2]), - new SmoothElevationPainter(ELEVATION_MODIFY, -11, 3), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetHarbor, 3), paintClass(g_TileClasses.water) ], avoidClasses( g_TileClasses.player, 15, g_TileClasses.hill, 1 ) ); // create fish in harbor createObjectGroup( new SimpleGroup( [new SimpleObject(g_Gaia.fish, 6, 6, 1, 20)], true, g_TileClasses.baseResource, harborPosition.x, harborPosition.y ), 0, [ avoidClasses( g_TileClasses.hill, 3, g_TileClasses.mountain, 3 ), stayClasses(g_TileClasses.water, 5) ] ); } } function addSpines() { + let smallSpines = mapSize <= 192; + let spineSize = smallSpines ? 0.5 : 0.02; + let spineTapering = smallSpines ? -1.4 : -0.1; + let heightOffsetSpine = smallSpines ? 20 : 35; + let numPlayers = getNumPlayers(); let spineTile = g_Terrains.dirt; - let elevation = 35; if (currentBiome() == "snowy") spineTile = g_Terrains.tier1Terrain; if (currentBiome() == "alpine" || currentBiome() == "savanna") spineTile = g_Terrains.tier2Terrain; if (currentBiome() == "autumn") spineTile = g_Terrains.tier4Terrain; let split = 1; if (numPlayers <= 3 || mapSize >= 320 && numPlayers <= 4) split = 2; for (let i = 0; i < numPlayers * split; ++i) { let tang = startAngle + (i + 0.5) * 2 * Math.PI / (numPlayers * split); - - let mStartCo = 0.12; - let mStopCo = 0.40; - let mSize = 0.5; - let mWaviness = 0.6; - let mOffset = 0.4; - let mTaper = -1.4; - - // make small mountain dividers if we're on a small map - if (mapSize <= 192) - { - mSize = 0.02; - mTaper = -0.1; - elevation = 20; - } + let start = Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.12), 0).rotate(-tang)); + let end = Vector2D.add(mapCenter, new Vector2D(fractionToTiles(0.4), 0).rotate(-tang)); createArea( - new PathPlacer( - fractionToTiles(0.5 + mStartCo * Math.cos(tang)), - fractionToTiles(0.5 + mStartCo * Math.sin(tang)), - fractionToTiles(0.5 + mStopCo * Math.cos(tang)), - fractionToTiles(0.5 + mStopCo * Math.sin(tang)), - scaleByMapSize(14, mSize), - mWaviness, - 0.1, - mOffset, - mTaper - ), + new PathPlacer(start.x, start.y, end.x, end.y, scaleByMapSize(14, spineSize), 0.6, 0.1, 0.4, spineTapering), [ new LayeredPainter([g_Terrains.cliff, spineTile], [3]), - new SmoothElevationPainter(ELEVATION_MODIFY, elevation, 3), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetSpine, 3), paintClass(g_TileClasses.spine) ], avoidClasses(g_TileClasses.player, 5) ); } addElements([ { "func": addDecoration, "avoid": [ g_TileClasses.bluff, 2, g_TileClasses.forest, 2, g_TileClasses.mountain, 2, g_TileClasses.player, 12, g_TileClasses.water, 3 ], "stay": [g_TileClasses.spine, 5], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["normal"] } ]); addElements([ { "func": addProps, "avoid": [ g_TileClasses.forest, 2, g_TileClasses.player, 2, g_TileClasses.prop, 20, g_TileClasses.water, 3 ], "stay": [g_TileClasses.spine, 8], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["scarce"] } ]); } Index: ps/trunk/binaries/data/mods/public/maps/random/hyrcanian_shores.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/hyrcanian_shores.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/hyrcanian_shores.js (revision 20904) @@ -1,331 +1,338 @@ Engine.LoadLibrary("rmgen"); const tGrass = ["temp_grass_clovers"]; const tGrassPForest = "temp_plants_bog"; const tGrassDForest = "alpine_dirt_grass_50"; const tCliff = ["temp_cliff_a", "temp_cliff_b"]; const tGrassA = "temp_grass_d"; const tGrassB = "temp_grass_c"; const tGrassC = "temp_grass_clovers_2"; const tHill = ["temp_highlands", "temp_grass_long_b"]; const tRoad = "temp_road"; const tRoadWild = "temp_road_overgrown"; const tGrassPatch = "temp_grass_plants"; const tShore = "medit_sand_wet"; const tWater = "medit_sand_wet"; const oPoplar = "gaia/flora_tree_poplar"; const oPalm = "gaia/flora_tree_cretan_date_palm_short"; const oApple = "gaia/flora_tree_apple"; const oOak = "gaia/flora_tree_oak"; const oBerryBush = "gaia/flora_bush_berry"; const oDeer = "gaia/fauna_deer"; const oFish = "gaia/fauna_fish"; const oGoat = "gaia/fauna_goat"; const oBoar = "gaia/fauna_boar"; const oStoneLarge = "gaia/geology_stonemine_temperate_quarry"; const oStoneSmall = "gaia/geology_stone_temperate"; const oMetalLarge = "gaia/geology_metal_temperate_slabs"; 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 pForestD = [tGrassDForest + TERRAIN_SEPARATOR + oPoplar, tGrassDForest]; const pForestP = [tGrassPForest + TERRAIN_SEPARATOR + oOak, tGrassPForest]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightSeaGround1 = -3; +const heightShore1 = -1.5; +const heightShore2 = 0; +const heightLand = 1; +const heightOffsetBump = 4; +const heightHill = 15; + +InitMap(heightLand, g_MapSettings.BaseTerrain); const mapCenter = getMapCenter(); const mapBounds = getMapBounds(); const numPlayers = getNumPlayers(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clHighlands = createTileClass(); var highlandsPosition = fractionToTiles(0.25); placePlayerBases({ "PlayerPlacement": playerPlacementLine(true, mapCenter, fractionToTiles(0.2)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, "Chicken": { }, "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), "end": new Vector2D(mapBounds.right, mapBounds.top), "width": fractionToTiles(0.5), "fadeDist": scaleByMapSize(6, 25), "deviation": 0, - "waterHeight": -3, - "landHeight": 1, + "heightRiverbed": heightSeaGround1, + "heightLand": heightLand, "meanderShort": 20, "meanderLong": 0, "waterFunc": (ix, iz, height, riverFraction) => { - if (height < 0) + if (height < heightShore2) addToClass(ix, iz, clWater); - createTerrain(height < -1.5 ? tWater : tShore).place(ix, iz); + createTerrain(height < heightShore1 ? tWater : tShore).place(ix, iz); } }); Engine.SetProgress(20); 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); createArea( new RectPlacer(mapBounds.left, mapBounds.bottom + highlandsPosition, mapBounds.right, mapBounds.bottom), paintClass(clHighlands)); log("Creating bumps..."); createAreas( - new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1), - new SmoothElevationPainter(ELEVATION_MODIFY, 4, 3), + new ClumpPlacer(scaleByMapSize(10, 60), 0.3, 0.06, 1), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 3), stayClasses(clHighlands, 1), scaleByMapSize(300, 600)); Engine.SetProgress(30); log("Creating hills..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 150), 0.2, 0.1, 1), [ new LayeredPainter([tCliff, tHill], [2]), - new SmoothElevationPainter(ELEVATION_SET, 15, 2), + new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), paintClass(clHill) ], avoidClasses(clPlayer, 20, clWater, 5, clHill, 15, clHighlands, 5), scaleByMapSize(1, 4) * numPlayers); Engine.SetProgress(35); log("Creating mainland forests..."); var [forestTrees, stragglerTrees] = getTreeCounts(500, 2500, 0.7); var types = [ [[tGrassDForest, tGrass, pForestD], [tGrassDForest, pForestD]] ]; var size = forestTrees * 1.3 / (scaleByMapSize(2,8) * numPlayers); var num = Math.floor(0.7 * size / types.length); for (let type of types) createAreas( new ClumpPlacer(forestTrees / num, 0.1, 0.1, 1), [ new LayeredPainter(type, [2]), paintClass(clForest) ], avoidClasses(clPlayer, 20, clWater, 3, clForest, 10, clHill, 0, clBaseResource, 3), num); Engine.SetProgress(45); log("Creating highland forests..."); var types = [ [[tGrassDForest, tGrass, pForestP], [tGrassDForest, pForestP]] ]; 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, 1), [ new LayeredPainter(type, [2]), paintClass(clForest) ], avoidClasses(clPlayer, 20, clWater, 3, clForest, 2, clHill, 0), num); Engine.SetProgress(70); 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]), paintClass(clDirt) ], avoidClasses(clWater, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 4), scaleByMapSize(15, 45)); Engine.SetProgress(75); 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); log("Creating stone mines..."); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clWater, 0, clForest, 1, clPlayer, 20, clRock, 10, clHill, 2)], scaleByMapSize(4,16), 100 ); 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 ); 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(4,16), 100 ); Engine.SetProgress(85); 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); 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 ); 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 ); 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 ); 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 ); 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); 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) ); 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); 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)); setSkySet("cirrus"); setWaterColor(0.114, 0.192, 0.463); setWaterTint(0.255, 0.361, 0.651); setWaterWaviness(2.0); setWaterType("ocean"); setWaterMurkiness(0.83); 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 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/island_stronghold.js (revision 20904) @@ -1,469 +1,470 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen2"); Engine.LoadLibrary("rmbiome"); Engine.LoadLibrary("heightmap"); 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 = "other/special_treasure_shipwreck"; const oShipDebris = "other/special_treasure_shipwreck_debris"; const oObelisk = "other/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]; -InitMap(g_MapSettings.BaseHeight, tWater); +const heightSeaGround = -10; +const heightLand = 3; +const heightHill = 18; + +InitMap(heightSeaGround, tWater); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); const clPlayer = createTileClass(); const clHill = createTileClass(); const clForest = createTileClass(); const clDirt = createTileClass(); const clRock = createTileClass(); const clMetal = createTileClass(); const clFood = createTileClass(); const clBaseResource = createTileClass(); const clLand = createTileClass(); -const shoreRadius = 6; -const landHeight = 3; - 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; 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()); log("Creating island and starting entities for team " + i); 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)), 1, playerPosition[p].x, playerPosition[p].y, 0, [Math.floor(fractionToTiles(0.01))]), [ - new LayeredPainter([tMainTerrain, tMainTerrain, tMainTerrain], [1, shoreRadius]), - new SmoothElevationPainter(ELEVATION_SET, landHeight, shoreRadius), + new LayeredPainter([tMainTerrain, tMainTerrain, tMainTerrain], [1, 6]), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 6), paintClass(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 } ]; log("Create starting resources for team " + i); 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.x, position.y), 0, [avoidClasses(clBaseResource, 4, clPlayer, 4), stayClasses(clLand, 5)]); } log("Place initial trees for team " + i); 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(); let group = new SimpleGroup( [new SimpleObject(oTree2, g_InitialTrees, g_InitialTrees, 0, 7)], true, clBaseResource, treePosition.x, treePosition.y ); if (createObjectGroup(group, 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({ "playerID": teams[i][p], "playerPosition": playerPosition[p], "BaseResourceClass": clBaseResource, "baseResourceConstraint": new AndConstraint([avoidClasses(clPlayer, 4), stayClasses(clLand, 5)]) }); log("Creating huntable animals for team " + i + "..."); for (let p = 0; p < teams[i].length; ++p) { let group = new SimpleGroup( [new SimpleObject(oMainHuntableAnimal, 2 * numPlayers / numTeams, 2 * numPlayers / numTeams, 0, Math.floor(fractionToTiles(0.2)))], true, clBaseResource, teamPosition[i].x, teamPosition[i].y ); createObjectGroup(group, 0, [avoidClasses(clBaseResource, 2, clPlayer, 10), stayClasses(clLand, 5)]); group = new SimpleGroup( [new SimpleObject(oSecondaryHuntableAnimal, 4 * numPlayers / numTeams, 4 * numPlayers / numTeams, 0, Math.floor(fractionToTiles(0.2)))], true, clBaseResource, teamPosition[i].x, teamPosition[i].y ); createObjectGroup(group, 0, [avoidClasses(clBaseResource, 2, clPlayer, 10), stayClasses(clLand, 5)]); } } Engine.SetProgress(40); log("Creating expansion islands..."); var landAreas = []; var playerConstraint = new AvoidTileClassConstraint(clPlayer, Math.floor(scaleByMapSize(12, 16))); var landConstraint = new AvoidTileClassConstraint(clLand, Math.floor(scaleByMapSize(12, 16))); for (let x = 0; x < mapSize; ++x) for (let z = 0; z < mapSize; ++z) if (playerConstraint.allows(x, z) && landConstraint.allows(x, z)) landAreas.push([x, z]); log("Creating big islands..."); let numIslands = scaleByMapSize(4, 14) * (isNomad() ? 2 : 1); for (let i = 0; i < numIslands; ++i) { let landAreaLen = landAreas.length; if (!landAreaLen) break; let chosenPoint = pickRandom(landAreas); let newIsland = 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, chosenPoint[0], chosenPoint[1], scaleByMapSize(30, 70)), [ new LayeredPainter([tMainTerrain, tMainTerrain], [2]), - new SmoothElevationPainter(ELEVATION_SET, landHeight, 6), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 6), paintClass(clLand) ], avoidClasses(clLand, 3, clPlayer, 3), 1, 1 ); if (!newIsland || !newIsland.length) continue; let n = 0; for (let j = 0; j < landAreaLen; ++j) { let x = landAreas[j][0]; let z = landAreas[j][1]; if (playerConstraint.allows(x, z) && landConstraint.allows(x, z)) landAreas[n++] = landAreas[j]; } landAreas.length = n; } playerConstraint = new AvoidTileClassConstraint(clPlayer, Math.floor(scaleByMapSize(9, 12))); landConstraint = new AvoidTileClassConstraint(clLand, Math.floor(scaleByMapSize(9, 12))); log("Creating small islands..."); numIslands = scaleByMapSize(6, 18) * scaleByMapSize(1, 3); for (let i = 0; i < numIslands; ++i) { let landAreaLen = landAreas.length; if (!landAreaLen) break; let chosenPoint = pickRandom(landAreas); let newIsland = createAreas( new ChainPlacer(Math.floor(scaleByMapSize(4, 7)), Math.floor(scaleByMapSize(7, 10)), Math.floor(scaleByMapSize(16, 40)), 0.07, chosenPoint[0], chosenPoint[1], scaleByMapSize(22, 40)), [ new LayeredPainter([tMainTerrain, tMainTerrain], [2]), - new SmoothElevationPainter(ELEVATION_SET, landHeight, 6), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 6), paintClass(clLand) ], avoidClasses(clLand, 3, clPlayer, 3), 1, 1); if (newIsland === undefined) continue; let temp = []; for (let j = 0; j < landAreaLen; ++j) { let x = landAreas[j][0]; let z = landAreas[j][1]; if (playerConstraint.allows(x, z) && landConstraint.allows(x, z)) temp.push([x, z]); } landAreas = temp; } Engine.SetProgress(70); log("Smoothing heightmap..."); for (let i = 0; i < 5; ++i) globalSmoothHeightmap(); // 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, 3, (numPlayers * 2) + 1)] ], [avoidClasses(clForest, 1, clPlayer, 40, clRock, 20), stayClasses(clLand, 4)], clMetal ); createMines( [ [new SimpleObject(oStoneLarge, 1, 1, 3, (numPlayers * 2) + 1)], [new SimpleObject(oStoneSmall, 2, 2, 2, (numPlayers * 2) + 1)] ], [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); 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, 18, 2), + new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), paintClass(clHill) ], [avoidClasses(clBaseResource, 20, clHill, 15, clRock, 6, clMetal, 6), stayClasses(clLand, 0)], scaleByMapSize(4, 13) ); for (let i = 0; i < 3; ++i) globalSmoothHeightmap(); 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() == "desert") { 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 ); } log("Creating dirt patches..."); let numb = currentBiome() == "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]), paintClass(clDirt) ], [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 0), stayClasses(clLand, 4)], numb*scaleByMapSize(15, 45)); 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)); 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 ); 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 ); 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 ); 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 ); 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 ); 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 ); log("Creating small grass tufts..."); let planetm = currentBiome() == "tropic" ? 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); 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(getMapBaseHeight(), 1, 3, tWater); +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); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/kerala.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/kerala.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/kerala.js (revision 20904) @@ -1,330 +1,333 @@ Engine.LoadLibrary("rmgen"); 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/flora_tree_toona"; const oPalm = "gaia/flora_tree_palm_tropic"; const oStoneLarge = "gaia/geology_stonemine_tropic_quarry"; const oStoneSmall = "gaia/geology_stone_tropic_a"; const oMetalLarge = "gaia/geology_metal_tropic_slabs"; const oFish = "gaia/fauna_fish"; const oDeer = "gaia/fauna_deer"; const oSheep = "gaia/fauna_tiger"; const oBush = "gaia/flora_bush_berry"; 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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightSeaGround = -5; +const heightLand = 3; +const heightHill = 25; + +InitMap(heightLand, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); -const mapSize = getMapSize(); const mapCenter = getMapCenter(); const mapBounds = getMapBounds(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clMountains = createTileClass(); var waterPosition = fractionToTiles(0.31); var mountainPosition = fractionToTiles(0.69); placePlayerBases({ "PlayerPlacement": playerPlacementLine(false, new Vector2D(fractionToTiles(0.55), mapCenter.y), fractionToTiles(0.2)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, "Chicken": { }, "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), "end": new Vector2D(mapBounds.left, mapBounds.bottom), "width": 2 * waterPosition, "fadeDist": 8, "deviation": 0, - "waterHeight": -5, - "landHeight": 3, + "heightRiverbed": heightSeaGround, + "heightLand": heightLand, "meanderShort": 20, "meanderLong": 0, "waterFunc": (ix, iz, height, riverFraction) => { addToClass(ix, iz, clWater); } }); createArea( new RectPlacer(mountainPosition, mapBounds.top, mapBounds.right, mapBounds.bottom), paintClass(clMountains)); log("Creating shores..."); for (let i = 0; i < scaleByMapSize(20, 120); ++i) createArea( new ChainPlacer( 1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(16, 30)), 1, Math.floor(fractionToTiles(randFloat(0.28, 0.34))), Math.floor(fractionToTiles(randFloat(0.1, 0.9)))), [ new LayeredPainter([tGrass, tGrass], [2]), - new SmoothElevationPainter(ELEVATION_SET, 3, 3), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 3), unPaintClass(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); 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, 25, 3), + new SmoothElevationPainter(ELEVATION_SET, heightHill, 3), paintClass(clHill) ], [avoidClasses(clPlayer, 20, clHill, 5, clWater, 2, clBaseResource, 2), stayClasses(clMountains, 0)], scaleByMapSize(5, 40) * numPlayers); 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]), paintClass(clForest) ], avoidClasses(clPlayer, 20, clForest, 10, clHill, 0, clWater, 8), num); Engine.SetProgress(70); 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]), paintClass(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 LayeredPainter([tPlants, tPlants], [1]), paintClass(clDirt) ], avoidClasses(clWater, 8, clForest, 0, clHill, 0, clPlayer, 12, clDirt, 16), scaleByMapSize(20, 80)); log("Creating stone mines..."); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), scaleByMapSize(4,16), 100 ); 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 ); 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 ); 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 ); 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 ); 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); 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); 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(95); createStragglerTrees( [oTree, oPalm], avoidClasses(clWater, 5, clForest, 1, clHill, 1, clPlayer, 12, clMetal, 6, clRock, 6), clForest, stragglerTrees); 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(75); 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 ); 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 ); 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"); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/latium.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/latium.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/latium.js (revision 20904) @@ -1,473 +1,474 @@ Engine.LoadLibrary("rmgen"); 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/flora_tree_euro_beech"; const oBerryBush = "gaia/flora_bush_berry"; const oCarob = "gaia/flora_tree_carob"; const oCypress1 = "gaia/flora_tree_cypress"; const oCypress2 = "gaia/flora_tree_cypress"; const oLombardyPoplar = "gaia/flora_tree_poplar_lombardy"; const oPalm = "gaia/flora_tree_medit_fan_palm"; const oPine = "gaia/flora_tree_aleppo_pine"; const oDeer = "gaia/fauna_deer"; const oFish = "gaia/fauna_fish"; const oSheep = "gaia/fauna_sheep"; const oStoneLarge = "gaia/geology_stonemine_medit_quarry"; const oStoneSmall = "gaia/geology_stone_mediterranean"; const oMetalLarge = "gaia/geology_metal_mediterranean_slabs"; 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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightSeaGround = -16; +const heightLand = 0; +const heightPlayer = 5; +const heightHill = 12; + +InitMap(heightLand, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); const mapBounds = getMapBounds(); var clWater = createTileClass(); var clCliff = createTileClass(); var clForest = createTileClass(); var clMetal = createTileClass(); var clRock = createTileClass(); var clFood = createTileClass(); var clPlayer = createTileClass(); var clBaseResource = createTileClass(); var WATER_WIDTH = 0.1; -var waterHeight = -16; -var landHeight = getMapBaseHeight(); -var hillHeight = 12; - log("Creating players..."); var [playerIDs, playerPosition] = playerPlacementLine(false, mapCenter, fractionToTiles(randFloat(0.42, 0.46))); function distanceToPlayers(x, z) { var r = 10000; for (let i = 0; i < numPlayers; ++i) { var dx = x - playerPosition[i].x; var dz = z - 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), "end": new Vector2D(x, mapBounds.bottom), "width": 2 * fractionToTiles(WATER_WIDTH), "fadeDist": 16, "deviation": 0, - "waterHeight": waterHeight, - "landHeight": landHeight, + "heightRiverbed": heightSeaGround, + "heightLand": heightLand, "meanderShort": 0, "meanderLong": 0, "waterFunc": (ix, iz, height, z) => { addToClass(ix, iz, clWater); } }); Engine.SetProgress(10); 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++) { var x = ix / (mapSize + 1.0); var z = iz / (mapSize + 1.0); var pn = playerNearness(x, z); let distToWater = stayClasses(clWater, 1).allows(ix, iz) ? 0 : (0.5 - WATER_WIDTH - Math.abs(x - 0.5)); - let h = distToWater ? hillHeight * (1 - Math.abs(x - 0.5) / (0.5 - WATER_WIDTH)) : getHeight(ix, iz); + let h = distToWater ? heightHill * (1 - Math.abs(x - 0.5) / (0.5 - WATER_WIDTH)) : getHeight(ix, iz); // 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; } setHeight(ix, iz, h); } Engine.SetProgress(20); 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++) { var x = ix / (mapSize + 1.0); var z = iz / (mapSize + 1.0); var pn = playerNearness(x, z); // get heights of surrounding vertices var h00 = getHeight(ix, iz); var h01 = getHeight(ix, iz+1); var h10 = getHeight(ix+1, iz); var h11 = getHeight(ix+1, iz+1); // find min and max height var maxH = Math.max(h00, h01, h10, h11); var minH = Math.min(h00, h01, h10, h11); 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, getHeight(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) addToClass(ix, iz, clWater); // cliffs if (diffH > 2.9 && minH > -7) { t = tCliff; addToClass(ix, iz, clCliff); } 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]; addToClass(ix, iz, clCliff); } // Don't place resources onto potentially impassable mountains if (minH >= 20) addToClass(ix, iz, clCliff); // forests if (getHeight(ix, iz) < 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; addToClass(ix, iz, clForest); } else if (minH < 4) { t = pPalmForest; addToClass(ix, iz, clForest); } } } // 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)) placeObject(randFloat(ix, ix + 1), randFloat(iz, iz + 1), aGrassDry, 0, randomAngle()); } else if (grassNoise > 0.61) { t = (diffH > 1.2 ? tGrassRock : tGrassShrubs); } else if (diffH < 0.5 && randBool(0.02)) placeObject(randFloat(ix, ix + 1), randFloat(iz, iz + 1), aGrass, 0, randomAngle()); } createTerrain(t).place(ix, iz); } Engine.SetProgress(30); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "baseResourceConstraint": avoidClasses(clCliff, 4), "CityPatch": { "radius": 11, "outerTerrain": tGrass, "innerTerrain": tCity, "width": 4, "painters": [ - new SmoothElevationPainter(ELEVATION_SET, 5, 2) + new SmoothElevationPainter(ELEVATION_SET, heightPlayer, 2) ] }, "Chicken": { }, "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); 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); 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); log("Creating large stone mines..."); group = new SimpleGroup([new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 1, clForest, 4, clPlayer, 40, clRock, 60, clMetal, 10, clCliff, 3), scaleByMapSize(4,16), 100 ); 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 ); 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); 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); 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); log("Creating fish..."); var num = scaleByMapSize(4, 16); var offsetX = mapSize * WATER_WIDTH/2; for (let i = 0; i < num; ++i) createObjectGroup( new SimpleGroup( [new SimpleObject(oFish, 1, 1, 0, 1)], true, clFood, randIntInclusive(offsetX / 2, offsetX * 3/2), Math.round((i + 0.5) * mapSize / num)), 0); for (let i = 0; i < num; ++i) createObjectGroup( new SimpleGroup( [new SimpleObject(oFish, 1, 1, 0, 1)], true, clFood, randIntInclusive(mapSize - offsetX * 3/2, mapSize - offsetX / 2), Math.round((i + 0.5) * mapSize / num)), 0); Engine.SetProgress(90); 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); 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); 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 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/lorraine_plain.js (revision 20904) @@ -1,315 +1,318 @@ Engine.LoadLibrary("rmgen"); 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/flora_tree_euro_beech"; const oOak = "gaia/flora_tree_oak"; const oBerryBush = "gaia/flora_bush_berry"; const oDeer = "gaia/fauna_deer"; const oRabbit = "gaia/fauna_rabbit"; const oStoneLarge = "gaia/geology_stonemine_temperate_quarry"; const oStoneSmall = "gaia/geology_stone_temperate"; const oMetalLarge = "gaia/geology_metal_temperate_slabs"; 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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightSeaGround = -4; +const heightShallows = -2; +const heightLand = 3; +const heightOffsetBump = 2; + +InitMap(heightLand, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); const mapBounds = getMapBounds(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clShallow = createTileClass(); -var waterHeight = -4; -var shallowHeight = -2; var shallowWidth = scaleByMapSize(8, 12); placePlayerBases({ "PlayerPlacement": playerPlacementRiver(Math.PI / 2, fractionToTiles(0.5)), // PlayerTileClass marked below "BaseResourceClass": clBaseResource, "Walls": "towers", "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad, "painters": [ paintClass(clPlayer) ] }, "Chicken": { }, "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) ]; log("Creating the main river..."); createArea( new PathPlacer(riverPositions[0].x, riverPositions[0].y, riverPositions[1].x, riverPositions[1].y, scaleByMapSize(10, 20), 0.5, 3 * scaleByMapSize(1, 4), 0.1, 0.01), - new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4), avoidClasses(clPlayer, 4)); Engine.SetProgress(25); log("Creating small puddles at the map border to ensure players being separated..."); for (let riverPosition of riverPositions) createArea( new ClumpPlacer(Math.floor(diskArea(scaleByMapSize(5, 10))), 0.95, 0.6, 10, riverPosition.x, riverPosition.y), - new SmoothElevationPainter(ELEVATION_SET, waterHeight, 2), + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 2), avoidClasses(clPlayer, 8)); Engine.SetProgress(30); log("Creating the shallows of the main river..."); for (let i = 0; i <= randIntInclusive(3, scaleByMapSize(4, 6)); ++i) { let location = randFloat(0.15, 0.85); createPassage({ "start": new Vector2D(location, 0).mult(mapSize), "end": new Vector2D(location, 1).mult(mapSize), "startWidth": shallowWidth, "endWidth": shallowWidth, "smoothWidth": 2, - "startHeight": shallowHeight, - "endHeight": shallowHeight, - "maxHeight": shallowHeight, + "startHeight": heightShallows, + "endHeight": heightShallows, + "maxHeight": heightShallows, "tileClass": clShallow }); } Engine.SetProgress(35); createTributaryRivers( true, randIntInclusive(9, scaleByMapSize(13, 21)), scaleByMapSize(10, 20), - waterHeight, + 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); log("Creating bumps..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1), - new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2), + 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); 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]), paintClass(clDirt) ], avoidClasses(clWater, 1, clForest, 0, clHill, 0, clDirt, 5, clPlayer, 6), scaleByMapSize(15, 45) ); 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); log("Creating stone mines..."); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4), new SimpleObject(oStoneLarge, 1, 1, 0, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clWater, 0, clForest, 1, clPlayer, 15, clRock, 10, clHill, 1)], scaleByMapSize(4,16), 100 ); 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 ); 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); 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 ); 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 ); 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 ); 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 ); 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); 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) ); 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) ); 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 ); 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); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/migration.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/migration.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/migration.js (revision 20904) @@ -1,369 +1,372 @@ Engine.LoadLibrary("rmgen"); 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/special_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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightSeaGround = -5; +const heightLand = 3; +const heightHill = 18; +const heightOffsetBump = 2; + +InitMap(heightSeaGround, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapArea = getMapArea(); const mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clLand = createTileClass(); var clIsland = createTileClass(); -var landHeight = 3; - var startAngle = 4/7 * Math.PI; var playerIDs = sortAllPlayers(); var [playerPosition, playerAngle] = playerPlacementCustomAngle( fractionToTiles(0.35), mapCenter, i => startAngle - 8/7 * Math.PI * (i + 1) / (numPlayers + 1)); log("Creating player islands and docks..."); for (let i = 0; i < numPlayers; ++i) { createArea( new ClumpPlacer(diskArea(defaultPlayerBaseRadius()), 0.8, 0.1, 10, playerPosition[i].x, playerPosition[i].y), [ new LayeredPainter([tWater, tShore, tMainTerrain], [1, 4]), - new SmoothElevationPainter(ELEVATION_SET, landHeight, 4), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), paintClass(clIsland), paintClass(isNomad() ? clLand : clPlayer) ]); if (isNomad()) continue; let dockLocation = findLocationInDirectionBasedOnHeight(playerPosition[i], mapCenter, -3 , 2.6, 3); placeObject(dockLocation.x, dockLocation.y, oDock, playerIDs[i], playerAngle[i] + Math.PI); } Engine.SetProgress(10); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "Walls": false, // No city patch "Chicken": { }, "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); log("Create the continent body..."); createArea( new ClumpPlacer(mapArea * 0.50, 0.8, 0.08, 10, Math.round(fractionToTiles(0.12)), Math.round(fractionToTiles(0.5))), [ new LayeredPainter([tWater, tShore, tMainTerrain], [4, 2]), - new SmoothElevationPainter(ELEVATION_SET, landHeight, 4), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), paintClass(clLand) ], avoidClasses(clIsland, 8)); Engine.SetProgress(20); log("Creating shore jaggedness..."); createAreas( new ClumpPlacer(scaleByMapSize(15, 80), 0.2, 0.1, 1), [ new LayeredPainter([tMainTerrain, tMainTerrain], [2]), - new SmoothElevationPainter(ELEVATION_SET, landHeight, 4), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), paintClass(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); log("Creating bumps..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1), - new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), [avoidClasses(clIsland, 10), stayClasses(clLand, 3)], scaleByMapSize(100, 200) ); Engine.SetProgress(30); log("Creating hills..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 150), 0.2, 0.1, 1), [ new LayeredPainter([tCliff, tHill], [2]), - new SmoothElevationPainter(ELEVATION_SET, 18, 2), + new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), paintClass(clHill) ], [avoidClasses(clIsland, 10, clHill, 15), stayClasses(clLand, 7)], scaleByMapSize(1, 4) * numPlayers ); Engine.SetProgress(34); 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() == "savanna" ? 2 : 1); var num = Math.floor(size / types.length); for (let type of types) createAreas( new ClumpPlacer(forestTrees / num, 0.1, 0.1, 1), [ new LayeredPainter(type, [2]), paintClass(clForest) ], [avoidClasses(clPlayer, 6, clForest, 10, clHill, 0), stayClasses(clLand, 7)], num); Engine.SetProgress(38); 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]), paintClass(clDirt) ], [ avoidClasses( clForest, 0, clHill, 0, clDirt, 5, clIsland, 0), stayClasses(clLand, 7) ], scaleByMapSize(15, 45)); Engine.SetProgress(42); 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); log("Creating stone mines..."); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,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); 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); 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); 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); 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); 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); 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); 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); 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() == "tropic" ? 8 : 1; 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); 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); 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)]); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/new_rms_test.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/new_rms_test.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/new_rms_test.js (revision 20904) @@ -1,12 +1,11 @@ Engine.LoadLibrary("rmgen"); -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +InitMap(0, g_MapSettings.BaseTerrain); -if (isNomad()) - placePlayersNomad(createTileClass()); -else - placePlayerBases({ - "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.39)) - }); +placePlayerBases({ + "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.39)) +}); + +placePlayersNomad(createTileClass()); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/northern_lights.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/northern_lights.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/northern_lights.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Northern Lights", "Script" : "northern_lights.js", "Description" : "Players start in a tough map to play with scarce wood and dangerous polar animals.", "BaseTerrain" : ["polar_snow_b"], - "BaseHeight" : 3, "Preview" : "northern_lights.png", "CircularMap" : true } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/persian_highlands.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/persian_highlands.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/persian_highlands.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Persian Highlands", "Script" : "persian_highlands.js", "Description" : "A dry central plateau rich in minerals surrounded by rocky hills\n\nThe southern parts of Zagros Mountains were the heart of the Persian empires and population. Although the altitude is high, the southern parts are drier that the northern Zagros, leading to a semi-arid climate. Still there are some sparse oak forests in the higher grounds.", "BaseTerrain" : ["desert_dirt_persia_2", "desert_dirt_persia_1" , "desert_dirt_persia_2", "grass_field_dry", "grass_field_dry"], - "BaseHeight" : 10, "Preview" : "persian_highlands.png", "CircularMap" : true } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/northern_lights.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/northern_lights.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/northern_lights.js (revision 20904) @@ -1,282 +1,285 @@ Engine.LoadLibrary("rmgen"); const tSnowA = ["polar_snow_b"]; const tSnowB = "polar_ice_snow"; const tSnowC = "polar_ice"; const tSnowD = "polar_snow_a"; const tForestFloor = "polar_tundra_snow"; const tCliff = "polar_snow_rocks"; const tSnowE = ["polar_snow_glacial"]; const tRoad = "new_alpine_citytile"; const tRoadWild = "new_alpine_citytile"; const tShoreBlend = "alpine_shore_rocks_icy"; const tShore = "alpine_shore_rocks"; const tWater = "alpine_shore_rocks"; const oPine = "gaia/flora_tree_pine_w"; const oStoneLarge = "gaia/geology_stonemine_alpine_quarry"; const oStoneSmall = "gaia/geology_stone_alpine_a"; const oMetalLarge = "gaia/geology_metal_alpine_slabs"; const oFish = "gaia/fauna_fish"; const oWalrus = "gaia/fauna_walrus"; const oArcticWolf = "gaia/fauna_arctic_wolf"; const aIceberg = "actor|props/special/eyecandy/iceberg.xml"; const pForestD = [tForestFloor + TERRAIN_SEPARATOR + oPine, tForestFloor, tForestFloor]; const pForestS = [tForestFloor + TERRAIN_SEPARATOR + oPine, tForestFloor, tForestFloor, tForestFloor]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightSeaGround = -5; +const heightLake = -4; +const heightLand = 3; +const heightHill = 25; + +InitMap(heightLand, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); const mapBounds = getMapBounds(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clIsland = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); -var landHeight = getMapBaseHeight(); - placePlayerBases({ "PlayerPlacement": playerPlacementLine(true, new Vector2D(fractionToTiles(0.45), mapCenter.y), fractionToTiles(0.2)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, // No chicken, no berries "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oPine, "count": scaleByMapSize(12, 30), } // No decoratives }); Engine.SetProgress(15); paintRiver({ "parallel": true, "start": new Vector2D(mapBounds.left, mapBounds.top), "end": new Vector2D(mapBounds.right, mapBounds.top), "width": 2 * fractionToTiles(0.31), "fadeDist": 8, "deviation": 0, - "waterHeight": -5, - "landHeight": landHeight, + "heightRiverbed": heightSeaGround, + "heightLand": heightLand, "meanderShort": 0, "meanderLong": 0 }); paintTileClassBasedOnHeight(-Infinity, 0.5, Elevation_ExcludeMin_ExcludeMax, clWater); log("Creating shores..."); for (let i = 0; i < scaleByMapSize(20, 120); ++i) createArea( new ChainPlacer( 1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(16, 30)), 1, Math.floor(fractionToTiles(randFloat(0.1, 0.9))), Math.floor(fractionToTiles(randFloat(0.67, 0.74)))), [ new LayeredPainter([tSnowA, tSnowA], [2]), - new SmoothElevationPainter(ELEVATION_SET, landHeight, 3), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 3), unPaintClass(clWater) ]); log("Creating islands..."); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(16, 40)), 0.1), [ new LayeredPainter([tSnowA, tSnowA], [3]), - new SmoothElevationPainter(ELEVATION_SET, landHeight, 3), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 3), paintClass(clIsland), unPaintClass(clWater) ], stayClasses(clWater, 7), scaleByMapSize(10, 80)); paintTerrainBasedOnHeight(-6, 1, 1, tWater); log("Creating lakes..."); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(5, 7)), Math.floor(scaleByMapSize(20, 50)), 0.1), [ new LayeredPainter([tShoreBlend, tShore, tWater], [1, 1]), - new SmoothElevationPainter(ELEVATION_SET, -4, 3), + new SmoothElevationPainter(ELEVATION_SET, heightLake, 3), paintClass(clWater) ], avoidClasses(clPlayer, 20, clWater, 20), Math.round(scaleByMapSize(1, 4) * numPlayers)); paintTerrainBasedOnHeight(1, 2.8, 1, tShoreBlend); paintTileClassBasedOnHeight(-6, 0.5, 1, clWater); Engine.SetProgress(45); log("Creating hills..."); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(16, 40)), 0.1), [ new LayeredPainter([tCliff, tSnowA], [3]), - new SmoothElevationPainter(ELEVATION_SET, 25, 3), + new SmoothElevationPainter(ELEVATION_SET, heightHill, 3), paintClass(clHill) ], avoidClasses(clPlayer, 20, clHill, 15, clWater, 2, clBaseResource, 2), scaleByMapSize(1, 4) * numPlayers ); log("Creating forests..."); var [forestTrees, stragglerTrees] = getTreeCounts(100, 625, 0.7); var types = [ [[tSnowA, tSnowA, tSnowA, tSnowA, pForestD], [tSnowA, tSnowA, tSnowA, pForestD]], [[tSnowA, tSnowA, tSnowA, tSnowA, pForestS], [tSnowA, tSnowA, tSnowA, pForestS]] ]; 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))), 1), [ new LayeredPainter(type, [2]), paintClass(clForest) ], avoidClasses(clPlayer, 20, clForest, 20, clHill, 0, clWater, 8), num); log("Creating iceberg..."); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(aIceberg, 0, 2, 0, 4)], true, clRock), 0, [avoidClasses(clRock, 6), stayClasses(clWater, 4)], scaleByMapSize(4, 16), 100); Engine.SetProgress(70); 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([tSnowD, tSnowB, tSnowC], [2, 1]), paintClass(clDirt) ], avoidClasses( clWater, 8, clForest, 0, clHill, 0, clPlayer, 20, 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 LayeredPainter([tSnowE, tSnowE], [1]), paintClass(clDirt) ], avoidClasses( clWater, 8, clForest, 0, clHill, 0, clPlayer, 20, clDirt, 16), scaleByMapSize(20, 80)); log("Creating stone mines..."); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4), new SimpleObject(oStoneLarge, 1, 1, 0, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), scaleByMapSize(8,32), 100 ); 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(8,32), 100 ); 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(8,32), 100 ); Engine.SetProgress(95); createStragglerTrees( [oPine], avoidClasses(clWater, 5, clForest, 1, clHill, 1, clPlayer, 12, clMetal, 6, clRock, 6), clForest, stragglerTrees); log("Creating deer..."); group = new SimpleGroup( [new SimpleObject(oWalrus, 5,7, 0,4)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 20), 3 * numPlayers, 50 ); Engine.SetProgress(75); log("Creating sheep..."); group = new SimpleGroup( [new SimpleObject(oArcticWolf, 2,3, 0,2)], true, clFood ); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 0, clPlayer, 20, clHill, 1, clFood, 20), 3 * numPlayers, 50 ); 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, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2, clIsland, 4)); setSunColor(0.6, 0.6, 0.6); setSunElevation(Math.PI/ 6); setWaterColor(0.02, 0.17, 0.52); setWaterTint(0.494, 0.682, 0.808); setWaterMurkiness(0.82); setWaterWaviness(0.5); setWaterType("ocean"); setFogFactor(0.95); setFogThickness(0.09); setPPSaturation(0.28); setPPEffect("hdr"); setSkySet("fog"); 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 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/persian_highlands.js (revision 20904) @@ -1,327 +1,330 @@ Engine.LoadLibrary("rmgen"); const tCity = "desert_city_tile_pers_dirt"; if (randBool()) { log("Summer biome..."); var tDirtMain = ["desert_dirt_persia_1", "desert_dirt_persia_2", "grass_field_dry"]; var tLakebed1 = ["desert_lakebed_dry_b", "desert_lakebed_dry"]; var tLakebed2 = ["desert_lakebed_dry_b", "desert_lakebed_dry", "desert_shore_stones", "desert_shore_stones"]; var tCliff = ["desert_cliff_persia_1", "desert_cliff_persia_crumbling"]; var tForestFloor = "medit_grass_field_dry"; var tRocky = "desert_dirt_persia_rocky"; var tRocks = "desert_dirt_persia_rocks"; var tGrass = "grass_field_dry"; } else { log("Spring biome..."); var tDirtMain = ["desert_grass_a", "desert_grass_a", "desert_grass_a", "desert_plants_a"]; var tLakebed1 = ["desert_lakebed_dry_b", "desert_lakebed_dry"]; var tLakebed2 = "desert_grass_a_sand"; var tCliff = ["desert_cliff_persia_1", "desert_cliff_persia_crumbling"]; var tForestFloor = "desert_plants_b_persia"; var tRocky = "desert_plants_b_persia"; var tRocks = "desert_plants_a"; var tGrass = "desert_dirt_persia_rocky"; setTerrainAmbientColor(0.329412, 0.419608, 0.501961); } const oGrapesBush = "gaia/flora_bush_grapes"; const oCamel = "gaia/fauna_camel"; const oSheep = "gaia/fauna_sheep"; const oGoat = "gaia/fauna_goat"; const oStoneLarge = "gaia/geology_stonemine_desert_badlands_quarry"; const oStoneSmall = "gaia/geology_stone_desert_small"; const oMetalLarge = "gaia/geology_metal_desert_slabs"; const oOak = "gaia/flora_tree_oak"; 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_dry_a.xml"; const aBush4 = "actor|props/flora/plant_desert_a.xml"; const aBushes = [aBush1, aBush2, aBush3, aBush4]; const aDecorativeRock = "actor|geology/stone_desert_med.xml"; const pForestO = [tForestFloor + TERRAIN_SEPARATOR + oOak, tForestFloor + TERRAIN_SEPARATOR + oOak, tForestFloor, tDirtMain, tDirtMain]; -InitMap(g_MapSettings.BaseHeight, tDirtMain); +const heightLand = 10; +const heightOffsetValley = -10; + +InitMap(heightLand, tDirtMain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clPatch = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clCP = createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tCity, "innerTerrain": tCity, "painters": [ paintClass(clPlayer) ] }, "Chicken": { }, "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); log("Creating rock patches..."); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 6)), Math.floor(scaleByMapSize(20, 45)), 0), [ new TerrainPainter(tRocky), paintClass(clPatch) ], avoidClasses(clPatch, 2, clPlayer, 0), scaleByMapSize(5, 20)); Engine.SetProgress(15); log("Creating secondary rock patches..."); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), Math.floor(scaleByMapSize(15, 40)), 0), [ new TerrainPainter([tRocky, tRocks]), paintClass(clPatch) ], avoidClasses(clPatch, 2, clPlayer, 4), scaleByMapSize(15, 50)); Engine.SetProgress(20); log("Creating dirt patches..."); createAreas( new ChainPlacer( 1, Math.floor(scaleByMapSize(3, 5)), Math.floor(scaleByMapSize(15, 40)), 0), [ new TerrainPainter([tGrass]), paintClass(clPatch) ], avoidClasses(clPatch, 2, clPlayer, 4), scaleByMapSize(15, 50)); Engine.SetProgress(25); log("Creating centeral plateau..."); createArea( new ChainPlacer( 2, Math.floor(scaleByMapSize(5, 13)), Math.floor(scaleByMapSize(35, 200)), 1, mapCenter.x, mapCenter.y, 0, [Math.floor(scaleByMapSize(18, 68))]), [ new LayeredPainter([tLakebed2, tLakebed1], [6]), - new SmoothElevationPainter(ELEVATION_MODIFY, -10, 8), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetValley, 8), paintClass(clCP) ], avoidClasses(clPlayer, 18)); Engine.SetProgress(30); 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); 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))), 1), [ new LayeredPainter(type, [2]), paintClass(clForest) ], avoidClasses( clPlayer, 6, clForest, 10, clHill, 1, clCP, 1), num); Engine.SetProgress(50); log("Creating stone mines..."); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4), new SimpleObject(oStoneLarge, 1, 1, 0, 4), new RandomObject(aBushes, 2, 4, 0, 2)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 1, clPlayer, 10, clRock, 10, clHill, 1, clCP, 1)], scaleByMapSize(2,8), 100 ); log("Creating small stone quarries..."); 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, clCP, 1)], scaleByMapSize(2,8), 100 ); 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, clCP, 1)], scaleByMapSize(2,8), 100 ); log("Creating centeral stone mines..."); group = new SimpleGroup([new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4), new RandomObject(aBushes, 2,4, 0,2)], true, clRock); createObjectGroupsDeprecated(group, 0, stayClasses(clCP, 6), 5*scaleByMapSize(5,30), 50 ); log("Creating small stone quarries..."); 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 ); 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); 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); 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); 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 ); 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 ); 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 ); 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); setSunColor(1.0, 0.796, 0.374); setSunElevation(Math.PI / 6); setSunRotation(-1.86532); setFogFactor(0.2); setFogThickness(0.0); setFogColor(0.852, 0.746, 0.493); setPPEffect("hdr"); setPPContrast(0.75); setPPSaturation(0.45); setPPBloom(0.3); placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/oasis.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/oasis.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/oasis.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Oasis", "Script" : "oasis.js", "Description" : "Players start around a small oasis in the center of the map which holds much of the available wood on the map.", "BaseTerrain" : ["medit_dirt", "medit_dirt_b", "medit_dirt_c"], - "BaseHeight" : 1, "Preview" : "oasis.png", "CircularMap" : true } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/oasis.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/oasis.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/oasis.js (revision 20904) @@ -1,327 +1,333 @@ Engine.LoadLibrary("rmgen"); 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/flora_tree_cretan_date_palm_short"; const ePalmTall = "gaia/flora_tree_cretan_date_palm_tall"; const eBush = "gaia/flora_bush_grapes"; const eCamel = "gaia/fauna_camel"; const eGazelle = "gaia/fauna_gazelle"; const eLion = "gaia/fauna_lion"; const eLioness = "gaia/fauna_lioness"; const eStoneMine = "gaia/geology_stonemine_desert_quarry"; const eMetalMine = "gaia/geology_metal_desert_slabs"; 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]; -InitMap(g_MapSettings.BaseHeight, tSand); +const heightSeaGround = -3; +const heightLand = 1; +const heightOasisPath = 4; +const heightOffsetBump = 4; +const heightOffsetDune = 18; + +InitMap(heightLand, tSand); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clOasis = createTileClass(); var clPassage = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var waterRadius = scaleByMapSize(7, 50) var shoreDistance = scaleByMapSize(4, 10); var forestDistance = scaleByMapSize(6, 20); var [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); log("Creating small oasis near the players...") var forestDist = 1.2 * defaultPlayerBaseRadius(); for (let i = 0; i < numPlayers; ++i) { // Create starting batches of wood let forestX = 0; let forestY = 0; let forestAngle = 0 do { forestAngle = Math.PI / 3 * randFloat(1, 2); forestX = playerPosition[i].x + Math.round(forestDist * Math.cos(forestAngle)); forestY = playerPosition[i].y + Math.round(forestDist * Math.sin(forestAngle)); } while ( !createArea( new ClumpPlacer(70, 1, 0.5, 10, forestX, forestY), [ new LayeredPainter([tForestFloor, pForestMain], [0]), paintClass(clBaseResource) ], avoidClasses(clBaseResource, 0))); // Creating the water patch explaining the forest do { var watAngle = forestAngle + randFloat(1/3, 5/3) * Math.PI; var watX = Math.round(forestX + 6 * Math.cos(watAngle)); var watY = Math.round(forestY + 6 * Math.sin(watAngle)); createObjectGroup( new SimpleGroup( [new SimpleObject(aFlower1, 1, 5, 0, 3)], true, undefined, Math.round(forestX + 3 * Math.cos(watAngle)), Math.round(forestY + 3 * Math.sin(watAngle))), 0); createObjectGroup( new SimpleGroup( [new SimpleObject(aReedsA, 1, 3, 0, 0)], true, undefined, Math.round(forestX + 5 * Math.cos(watAngle)), Math.round(forestY + 5 * Math.sin(watAngle))), 0); } while ( !createArea( new ClumpPlacer(60, 0.9, 0.4, 5, watX, watY), [ new LayeredPainter([tShore, tWater], [1]), - new SmoothElevationPainter(ELEVATION_MODIFY, -5, 3) + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 3) ], avoidClasses(clBaseResource, 0))); } Engine.SetProgress(20); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad, "painters": [ paintClass(clPlayer) ] }, "Chicken": { }, "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); log("Creating central oasis..."); createArea( new ClumpPlacer(diskArea(forestDistance + shoreDistance + waterRadius), 0.8, 0.2, 10, mapCenter.x, mapCenter.y), [ new LayeredPainter([pOasisForestLight, tWater], [forestDistance]), - new SmoothElevationPainter(ELEVATION_SET, -3, forestDistance + shoreDistance), + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, forestDistance + shoreDistance), paintClass(clOasis) ]); Engine.SetProgress(40); log("Creating bumps..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1), - new SmoothElevationPainter(ELEVATION_MODIFY, 4, 3), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 3), avoidClasses(clPlayer, 10, clBaseResource, 6, clOasis, 4), scaleByMapSize(30, 70)); log("Creating dirt patches..."); createAreas( new ClumpPlacer(80, 0.3, 0.06, 1), new TerrainPainter(tDirt), avoidClasses(clPlayer, 10, clBaseResource, 6, clOasis, 4, clForest, 4), scaleByMapSize(15, 50)); log("Creating dunes..."); createAreas( new ClumpPlacer(120, 0.3, 0.06, 1), [ new TerrainPainter(tDune), - new SmoothElevationPainter(ELEVATION_MODIFY, 18, 30) + 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()) { 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].x, points[0].y, points[1].x, points[1].y, pathWidth, 0.4, 1, 0.2, 0), [ new TerrainPainter(tSand), - new SmoothElevationPainter(ELEVATION_SET, 4, 5), + new SmoothElevationPainter(ELEVATION_SET, hOasisPath, 5), paintClass(clPassage) ]); } 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); 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 ); 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); 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); 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); 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); 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.x, animalPos.y), 0); } Engine.SetProgress(90); 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 ); log("Creating sand blows and beautifications"); for (var sandx = 0; sandx < mapSize; sandx += 4) for (var sandz = 0; sandz < mapSize; sandz += 4) { if (getHeight(sandx,sandz) > 3.4) { if (randBool((getHeight(sandx,sandz) - 3.4) / 1.4)) { group = new SimpleGroup( [new SimpleObject(aSand, 0,1, 0,2)], true, undefined, sandx,sandz ); createObjectGroup(group, 0); } } else if (getHeight(sandx, sandz) > -2.5 && getHeight(sandx,sandz) < -1) { if (randBool(0.4)) { group = new SimpleGroup( [new SimpleObject(aWaterFlower, 1,4, 1,2)], true, undefined, sandx,sandz ); createObjectGroup(group, 0); } else if (randBool(0.7) && getHeight(sandx,sandz) < -1.9) { group = new SimpleGroup( [new SimpleObject(aReedsA, 5,12, 0,2),new SimpleObject(aReedsB, 5,12, 0,2)], true, undefined, sandx,sandz ); createObjectGroup(group, 0); } if (getTileClass(clPassage).countInRadius(sandx,sandz,2,true) > 0) { if (randBool(0.4)) { group = new SimpleGroup( [new SimpleObject(aWaterFlower, 1,4, 1,2)], true, undefined, sandx,sandz ); createObjectGroup(group, 0); } else if (randBool(0.7) && getHeight(sandx,sandz) < -1.9) { group = new SimpleGroup( [new SimpleObject(aReedsA, 5,12, 0,2),new SimpleObject(aReedsB, 5,12, 0,2)], true, undefined, sandx,sandz ); createObjectGroup(group, 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); setTerrainAmbientColor(0.45, 0.5, 0.6); setUnitsAmbientColor(0.501961, 0.501961, 0.501961); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/polar_sea.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/polar_sea.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/polar_sea.json (revision 20904) @@ -1,16 +1,15 @@ { "settings" : { "Name" : "Polar Sea", "Script" : "polar_sea.js", "Description" : "Players start in a cold polar region barren of vegetation. In the sea fish and whales abound, while the fragile icy land teems with huntable walruses and deadly wolves. These wolves, made ravenous by the harsh and forbidding climate, drawn by the scent of prey, have started appearing in terrifying numbers. A wise and strong ruler will not only achieve victory over his enemies, but also keep the number of these beasts at bay, lest they undermine his economy and cause his downfall. [color=\"red\"]Warning: It is inadvisable to disable treasures, since there is no gatherable wood. Not recommended for inexperienced players.[/color]", "BaseTerrain" : ["polar_snow_a"], - "BaseHeight" : 2, "Keywords": ["trigger"], "Preview" : "polar_sea.png", "CircularMap" : true, "TriggerScripts" : [ "scripts/TriggerHelper.js", "random/polar_sea_triggers.js" ] } } Index: ps/trunk/binaries/data/mods/public/maps/random/rhine_marshlands.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rhine_marshlands.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/rhine_marshlands.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Rhine Marshlands", "Script" : "rhine_marshlands.js", "Description" : "Shallow, passable wetlands with little room for building. Represents the lowlands of the Rhine basin in Europe.", "BaseTerrain" : ["temp_grass", "temp_grass", "temp_grass_d"], - "BaseHeight" : 1, "Preview" : "rhine_marshlands.png", "CircularMap" : true } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/rivers.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rivers.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/rivers.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "Rivers", "Script" : "rivers.js", "Description" : "Rivers flow between players and join each other in the center of the map.", "BaseTerrain" : ["temp_grass", "temp_grass_c"], - "BaseHeight" : 1, "Preview" : "rivers.png", "SupportedBiomes": true, "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/saharan_oases.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/saharan_oases.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/saharan_oases.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Saharan Oases", "Script" : "saharan_oases.js", "Description" : "Each players starts near a lush oasis in a large, desolate desert.", "BaseTerrain" : ["desert_sand_dunes_100"], - "BaseHeight" : 1, "Preview" : "saharan_oases.png", "CircularMap" : true } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/sahel_watering_holes.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/sahel_watering_holes.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/sahel_watering_holes.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Sahel Watering Holes", "Script" : "sahel_watering_holes.js", "Description" : "Players start around the map with lines of water between them\n\nThe African savanna is chocked full of animal life for hunting, while the nearby mineral deposits are plentiful. The dry season is approaching and the watering holes are drying up.", "BaseTerrain" : ["savanna_grass_a"], - "BaseHeight" : 3, "CircularMap" : true, "Preview" : "sahel_watering_holes.png" } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/snowflake_searocks.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/snowflake_searocks.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/snowflake_searocks.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "Snowflake Searocks", "Script" : "snowflake_searocks.js", "Description" : "Many small islands connected to each other by narrow passages.", "BaseTerrain" : ["medit_sea_depths"], - "BaseHeight" : -5, "Preview" : "snowflake_searocks.png", "SupportedBiomes": true, "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/survivalofthefittest.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/survivalofthefittest.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/survivalofthefittest.json (revision 20904) @@ -1,17 +1,16 @@ { "settings" : { "Name" : "Survival of the Fittest", "Script" : "survivalofthefittest.js", "Description" : "[color=\"red\"]IMPORTANT NOTE: AI PLAYERS DO NOT WORK WITH THIS MAP[/color]\n\nProtect your base against endless waves of enemies. Use your woman citizen to collect the treasures at the center of the map before others do, and try to build your base up. The last player remaining will be the winner!", "BaseTerrain" : ["medit_sea_depths"], - "BaseHeight" : 30, "Keywords": ["trigger"], "Preview" : "survivalofthefittest.png", "SupportedBiomes": true, "CircularMap" : true, "TriggerScripts": [ "scripts/TriggerHelper.js", "random/survivalofthefittest_triggers.js" ] } } Index: ps/trunk/binaries/data/mods/public/maps/random/the_nile.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/the_nile.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/the_nile.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "The Nile", "Script" : "the_nile.js", "Description" : "A calm wide river, representing the Nile River in Egypt, divides the map into western and eastern parts.", "BaseTerrain" : ["desert_sand_dunes_100"], - "BaseHeight" : 1, "Keywords": ["naval"], "Preview" : "the_nile.png", "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/volcanic_lands.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/volcanic_lands.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/volcanic_lands.js (revision 20904) @@ -1,182 +1,185 @@ Engine.LoadLibrary("rmgen"); var tGrass = ["cliff volcanic light", "ocean_rock_a", "ocean_rock_b"]; var tGrassA = "cliff volcanic light"; var tGrassB = "ocean_rock_a"; var tGrassC = "ocean_rock_b"; var tCliff = ["cliff volcanic coarse", "cave_walls"]; var tRoad = "road1"; var tRoadWild = "road1"; var tLava1 = "LavaTest05"; var tLava2 = "LavaTest04"; var tLava3 = "LavaTest03"; var oTree = "gaia/flora_tree_dead"; var oStoneLarge = "gaia/geology_stonemine_alpine_quarry"; var oStoneSmall = "gaia/geology_stone_alpine_a"; var oMetalLarge = "gaia/geology_metal_alpine_slabs"; var aRockLarge = "actor|geology/stone_granite_med.xml"; var aRockMedium = "actor|geology/stone_granite_med.xml"; var pForestD = [tGrassC + TERRAIN_SEPARATOR + oTree, tGrassC]; var pForestP = [tGrassB + TERRAIN_SEPARATOR + oTree, tGrassB]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightLand = 1; +const heightHill = 18; + +InitMap(heightLand, g_MapSettings.BaseTerrain); var numPlayers = getNumPlayers(); var mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clBaseResource = createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, // No berries, no chicken, no decoratives "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oTree, "count": scaleByMapSize(12, 30) } }); Engine.SetProgress(15); createVolcano(mapCenter, clHill, tCliff, [tLava1, tLava2, tLava3], true, ELEVATION_SET); Engine.SetProgress(45); log("Creating hills..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 150), 0.2, 0.1, 1), [ new LayeredPainter([tCliff, tGrass], [2]), - new SmoothElevationPainter(ELEVATION_SET, 18, 2), + new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), paintClass(clHill) ], avoidClasses(clPlayer, 12, clHill, 15, clBaseResource, 2), scaleByMapSize(2, 8) * numPlayers ); log("Creating forests..."); var [forestTrees, stragglerTrees] = getTreeCounts(200, 1250, 0.7); var types = [ [[tGrassB, tGrassA, pForestD], [tGrassB, pForestD]], [[tGrassB, tGrassA, pForestP], [tGrassB, pForestP]] ]; 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, 1), [ new LayeredPainter(type, [2]), paintClass(clForest) ], avoidClasses(clPlayer, 12, clForest, 10, clHill, 0, clBaseResource, 6), num); Engine.SetProgress(70); 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([tGrassA, tGrassA], [1]), paintClass(clDirt) ], avoidClasses(clForest, 0, clHill, 0, clPlayer, 12), scaleByMapSize(20, 80)); 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([tGrassB, tGrassB], [1]), paintClass(clDirt) ], avoidClasses(clForest, 0, clHill, 0, clPlayer, 12), scaleByMapSize(20, 80)); 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([tGrassC, tGrassC], [1]), paintClass(clDirt) ], avoidClasses(clForest, 0, clHill, 0, clPlayer, 12), scaleByMapSize(20, 80) ); log("Creating stone mines..."); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4), new SimpleObject(oStoneLarge, 1, 1, 0, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 10, clRock, 10, clHill, 1), scaleByMapSize(4,16), 100 ); log("Creating small stone mines..."); group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 10, clRock, 10, clHill, 1), scaleByMapSize(4,16), 100 ); 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), scaleByMapSize(4,16), 100 ); Engine.SetProgress(90); 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 ); 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(95); createStragglerTrees( [oTree], avoidClasses(clForest, 1, clHill, 1, clPlayer, 12, clMetal, 6, clRock, 6, clBaseResource, 6), clForest, stragglerTrees); placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4)); 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 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/polar_sea.js (revision 20904) @@ -1,314 +1,312 @@ Engine.LoadLibrary("rmgen"); var tPrimary = ["polar_snow_a"]; -var tCliff = ["polar_cliff_a", "polar_cliff_b", "polar_cliff_snow"]; 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 = "trigger/fauna_arctic_wolf_attack"; 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/fauna_fish"; var oStoneLarge = "gaia/geology_stonemine_medit_quarry"; var oStoneSmall = "gaia/geology_stone_alpine_a"; var oMetalLarge = "gaia/geology_metal_desert_badlands_slabs"; var oWoodTreasure = "gaia/special_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"; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +var heightSeaGround = -4; +var heightLand = 2; +var heightCliff = 3; + +InitMap(heightLand, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clHill = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clArcticWolf = createTileClass(); -var waterHeight = -4; -var cliffHeight = getMapBaseHeight() + 1; -var snowHeight = Math.floor(scaleByMapSize(20, 40)); - var [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); var treasures = [{ "template": oWoodTreasure, "count": isNomad() ? 16 : 14 }]; 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(); placeObject(marketPos.x, marketPos.y, oMarket, playerIDs[i], BUILDING_ORIENTATION); addCivicCenterAreaToClass(marketPos, clBaseResource); } placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "Walls": "towers", "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, "Chicken": { "template": oMuskox }, // No berries, no trees, no decoratives "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Treasures": { "types": treasures }, }); Engine.SetProgress(30); log("Creating central lake..."); createArea( new ChainPlacer( 2, Math.floor(scaleByMapSize(5, 16)), Math.floor(scaleByMapSize(35, 200)), 1, mapCenter.x, mapCenter.y, 0, [Math.floor(fractionToTiles(0.17))]), [ new LayeredPainter([tShore, tWater, tWater, tWater], [1, 4, 2]), - new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4), paintClass(clWater) ], avoidClasses(clPlayer, 20)); -paintTerrainBasedOnHeight(cliffHeight, snowHeight, Elevation_ExcludeMin_ExcludeMax, tCliff); -paintTerrainBasedOnHeight(snowHeight, Infinity, Elevation_IncludeMin_IncludeMax, tSnowLimited); Engine.SetProgress(40); log("Creating small lakes..."); var lakeAreas = []; var playerConstraint = new AvoidTileClassConstraint(clPlayer, 20); var waterConstraint = new AvoidTileClassConstraint(clWater, 8); for (let x = 0; x < mapSize; ++x) for (let z = 0; z < mapSize; ++z) if (playerConstraint.allows(x, z) && waterConstraint.allows(x, z)) lakeAreas.push([x, z]); var numLakes = scaleByMapSize(10, 16); for (let i = 0; i < numLakes ; ++i) { let chosenPoint = pickRandom(lakeAreas); if (!chosenPoint) break; createAreas( new ChainPlacer( 1, Math.floor(scaleByMapSize(2, 4)), Math.floor(scaleByMapSize(20, 140)), 0.7, chosenPoint[0], chosenPoint[1]), [ new LayeredPainter([tShore, tWater, tWater], [1, 3]), - new SmoothElevationPainter(ELEVATION_SET, waterHeight, 5), + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 5), paintClass(clWater) ], avoidClasses(clPlayer, 20), 1, 1); } Engine.SetProgress(50); createBumps(avoidClasses(clWater, 2, clPlayer, 20)); Engine.SetProgress(60); log("Creating hills..."); createHills( [tPrimary, tPrimary, tSecondary], avoidClasses(clPlayer, 20, clHill, 35), - clHill, scaleByMapSize(20, 240)); + clHill, + scaleByMapSize(20, 240)); Engine.SetProgress(65); 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); 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); log("Creating stone mines..."); createMines( [ [new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], avoidClasses(clWater, 3, clPlayer, 20, clRock, 18, clHill, 2), clRock); 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) ] ], [ scaleByMapSize(16, 262), scaleByMapSize(8, 131), ], avoidClasses(clWater, 0, clPlayer, 0)); createDecoration( [ [new SimpleObject(aIceberg, 1, 1, 1, 1)] ], [ scaleByMapSize(8, 131) ], [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 (randBool(1/3)) { setSkySet("sunset 1"); setSunColor(0.8, 0.7, 0.6); setTerrainAmbientColor(0.7, 0.6, 0.7); setUnitsAmbientColor(0.6, 0.5, 0.6); 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); 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 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/rhine_marshlands.js (revision 20904) @@ -1,303 +1,308 @@ Engine.LoadLibrary("rmgen"); 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/flora_tree_euro_beech"; const oOak = "gaia/flora_tree_oak"; const oBerryBush = "gaia/flora_bush_berry"; const oDeer = "gaia/fauna_deer"; const oHorse = "gaia/fauna_horse"; const oWolf = "gaia/fauna_wolf"; const oRabbit = "gaia/fauna_rabbit"; const oStoneLarge = "gaia/geology_stonemine_temperate_quarry"; const oStoneSmall = "gaia/geology_stone_temperate"; const oMetalLarge = "gaia/geology_metal_temperate_slabs"; 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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightMarsh = -2 +const heightLand = 1; +const heightOffsetBumpWater = 1; +const heightOffsetBumpLand = 2; + +InitMap(heightLand, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); var clPlayer = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, "Chicken": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oBeech }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(15); log("Creating bumps..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1), - new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBumpLand, 2), avoidClasses(clPlayer, 13), scaleByMapSize(300, 800)); 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, -2, 3), + new SmoothElevationPainter(ELEVATION_SET, heightMarsh, 3), paintClass(clWater) ], avoidClasses(clPlayer, 20, clWater, Math.round(scaleByMapSize(7,16)*randFloat(0.8,1.35))), scaleByMapSize(4,20)); 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); log("Creating bumps..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1), - new SmoothElevationPainter(ELEVATION_MODIFY, 1, 2), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBumpWater, 2), stayClasses(clWater, 2), scaleByMapSize(50, 100)); 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))), 1), [ new LayeredPainter(type, [2]), paintClass(clForest) ], avoidClasses(clPlayer, 20, clWater, 0, clForest, 10), num); Engine.SetProgress(50); 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, 1), [ new LayeredPainter([tGrassA, tGrassB, tMud], [1, 1]), paintClass(clDirt) ], avoidClasses(clWater, 1, clForest, 0, clDirt, 5, clPlayer, 8), scaleByMapSize(15, 45)); log("Creating stone mines..."); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4), new SimpleObject(oStoneLarge, 1, 1, 0, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clWater, 0, clForest, 1, clPlayer, 20, clRock, 10)], scaleByMapSize(4,16), 100 ); 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 ); 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); 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); 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); 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 ); 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); 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 ); 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 ); 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); 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); 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); 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); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/rivers.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rivers.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/rivers.js (revision 20904) @@ -1,288 +1,289 @@ Engine.LoadLibrary("rmgen"); 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() == "tropic") { 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 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]; -InitMap(g_MapSettings.BaseHeight, tMainTerrain); +const heightSeaGround = -3; +const heightShallows = -1; +const heightLand = 1; + +InitMap(heightLand, tMainTerrain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clShallow = createTileClass(); -var waterHeight = -3; -var shallowHeight = -1; - var [playerIDs, playerPosition, playerAngle, startAngle] = playerPlacementCircle(fractionToTiles(0.35)); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, "Chicken": { }, "Berries": { "template": oFruitBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oTree1, "count": 2 }, "Decoratives": { "template": aGrassShort } }); log("Creating central lake..."); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.075)), 0.7, 0.1, 10, mapCenter.x, mapCenter.y), [ new LayeredPainter([tShore, tWater, tWater, tWater], [1, 4, 2]), - new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4), paintClass(clWater) ]); 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, - "landHeight": getMapBaseHeight(), - "waterHeight": waterHeight, - "minHeight": waterHeight, + "heightLand": heightLand, + "heightRiverbed": heightSeaGround, + "minHeight": heightSeaGround, "meanderShort": 10, "meanderLong": 0, "waterFunc": (ix, iz, height, riverFraction) => { addToClass(ix, iz, clWater); - let isShallow = height < shallowHeight && + let isShallow = height < heightShallows && riverFraction > shallowLocation && riverFraction < shallowLocation + shallowWidth; - let newHeight = isShallow ? shallowHeight : Math.max(height, waterHeight); + let newHeight = isShallow ? heightShallows : Math.max(height, heightSeaGround); if (getHeight(ix, iz) < newHeight) return; setHeight(ix, iz, newHeight); createTerrain(height >= 0 ? tShore : tWater).place(ix, iz); if (isShallow) addToClass(ix, iz, clShallow); } }); } 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)); createForests( [tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2], avoidClasses(clPlayer, 20, clForest, 17, clHill, 0, clWater, 2), clForest, forestTrees); Engine.SetProgress(50); 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); 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); log("Creating stone mines..."); createMines( [ [new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], [new SimpleObject(oStoneSmall, 2,5, 1,3)] ], avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), clRock); 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(65); var planetm = 1; if (currentBiome() == "tropic") 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)] ], [ scaleByMapSize(16, 262), scaleByMapSize(8, 131), planetm * scaleByMapSize(13, 200), planetm * scaleByMapSize(13, 200), planetm * scaleByMapSize(13, 200) ], avoidClasses(clWater, 0, 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)); 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)); setWaterWaviness(3.0); setWaterType("lake"); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/saharan_oases.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/saharan_oases.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/saharan_oases.js (revision 20904) @@ -1,236 +1,239 @@ Engine.LoadLibrary("rmgen"); 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/flora_bush_grapes"; const oCamel = "gaia/fauna_camel"; const oGazelle = "gaia/fauna_gazelle"; const oGoat = "gaia/fauna_goat"; const oStoneLarge = "gaia/geology_stonemine_desert_badlands_quarry"; const oStoneSmall = "gaia/geology_stone_desert_small"; const oMetalLarge = "gaia/geology_metal_desert_slabs"; const oDatePalm = "gaia/flora_tree_date_palm"; const oSDatePalm = "gaia/flora_tree_cretan_date_palm_short"; const oWoodTreasure = "gaia/special_treasure_wood"; const oFoodTreasure = "gaia/special_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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightLand = 1; +const heightOffsetOasis = -3; + +InitMap(heightLand, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clTreasure = createTileClass(); var [playerIDs, playerPosition, playerAngle] = playerPlacementCircle(fractionToTiles(0.35)); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tCityPlaza, "innerTerrain": tCity }, "Chicken": { }, "Berries": { "template": oGrapeBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oSDatePalm }, "Decoratives": { "template": aBush1 } }); Engine.SetProgress(30); 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.x, position.y), [ new LayeredPainter( [tSLush ,[tLush, pForest], [tLush, pForest], tShore, tShore, tWaterDeep], [2, 2, 1, 3, 1]), - new SmoothElevationPainter(ELEVATION_MODIFY, -3, 10), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetOasis, 10), paintClass(clWater) ]); } Engine.SetProgress(50); 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] ), paintClass(clDirt) ], avoidClasses(clForest, 0, clPlayer, 0, clWater, 1, clDirt, 5), scaleByMapSize(15, 45)); Engine.SetProgress(55); 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] ), paintClass(clDirt) ], avoidClasses(clForest, 0, clDirt, 5, clPlayer, 0, clWater, 1), scaleByMapSize(15, 45)); Engine.SetProgress(60); log("Creating stone mines..."); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 26, clRock, 10, clWater, 1), 2*scaleByMapSize(4,16), 100 ); 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 ); 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 ); 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 ); 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 ); 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 ); 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 ); 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 ); 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 ); 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); ExportMap(); 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 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/sahel_watering_holes.js (revision 20904) @@ -1,388 +1,391 @@ Engine.LoadLibrary("rmgen"); 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/flora_tree_baobab"; const oFig = "gaia/flora_tree_fig"; const oBerryBush = "gaia/flora_bush_berry"; const oWildebeest = "gaia/fauna_wildebeest"; const oFish = "gaia/fauna_fish"; 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/geology_stonemine_desert_quarry"; const oStoneSmall = "gaia/geology_stone_savanna_small"; const oMetalLarge = "gaia/geology_metal_savanna_slabs"; 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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightSeaGround = -4; +const heightShallows = -2; +const heightLand = 3; +const heightHill = 35; +const heightOffsetBump = 2; + +InitMap(heightLand, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clShallows = createTileClass(); -var waterHeight = -4; -var shallowHeight = -2; - var [playerIDs, playerPosition, playerAngle, startAngle] = playerPlacementCircle(fractionToTiles(0.35)); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, "Chicken": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oBaobab, "count": 5 }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(20); 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; log("Creating lake near the center..."); createArea( new ClumpPlacer(Math.floor(diskArea(scaleByMapSize(10, 50)) / 3), 0.95, 0.6, 10, riverStart[i].x, riverStart[i].y), [ - new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4), paintClass(clWater) ], avoidClasses(clPlayer, 5)); log("Creating the river between the players..."); createArea( new PathPlacer(riverStart[i].x, riverStart[i].y, riverEnd[i].x, riverEnd[i].y, scaleByMapSize(10, 50), 0.2, 3 * scaleByMapSize(1, 4), 0.2, 0.05), [ new LayeredPainter([tShore, tWater, tWater], [1, 3]), - new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4), paintClass(clWater) ], avoidClasses(clPlayer, 5)); log("Creating lake near the map border..."); createArea( new ClumpPlacer(Math.floor(diskArea(scaleByMapSize(10, 50)) / 5), 0.95, 0.6, 10, riverEnd[i].x, riverEnd[i].y), [ - new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 4), paintClass(clWater) ], avoidClasses(clPlayer, 5)); log("Creating shallows between neighbors..."); createPassage({ "start": playerPosition[i], "end": playerPosition[neighborID], "startWidth": 10, "endWidth": 10, "smoothWidth": 4, - "startHeight": shallowHeight, - "endHeight": shallowHeight, - "maxHeight": shallowHeight, + "startHeight": heightShallows, + "endHeight": heightShallows, + "maxHeight": heightShallows, "tileClass": clShallows }); log("Creating 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.x, shallowPosition.y), 0); } paintTerrainBasedOnHeight(-6, 2, 1, tWater); log("Creating bumps..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1), - new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), avoidClasses(clWater, 2, clPlayer, 20), scaleByMapSize(100, 200)); log("Creating hills..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 150), 0.2, 0.1, 1), [ new LayeredPainter([tGrass, tCliff, tHill], [1, 2]), - new SmoothElevationPainter(ELEVATION_SET, 35, 3), + new SmoothElevationPainter(ELEVATION_SET, heightHill, 3), paintClass(clHill) ], avoidClasses(clPlayer, 20, clHill, 15, clWater, 3), scaleByMapSize(1, 4) * numPlayers); 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, 1), [ new LayeredPainter(type, [2]), paintClass(clForest) ], avoidClasses(clPlayer, 20, clForest, 10, clHill, 0, clWater, 2), num ); Engine.SetProgress(50); 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]), paintClass(clDirt) ], avoidClasses(clWater, 3, clForest, 0, clHill, 0, clPlayer, 20), scaleByMapSize(15, 45)); 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); log("Creating stone mines..."); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4), new SimpleObject(oStoneLarge, 1, 1, 0, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clRock, 10, clHill, 1), scaleByMapSize(4,16), 100 ); 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 ); 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); 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 ); 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); 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); 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 ); 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 ); 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 ); 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 ); 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 ); 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; 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); 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); 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"); 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 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/snowflake_searocks.js (revision 20904) @@ -1,438 +1,440 @@ Engine.LoadLibrary("rmgen"); 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.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]; -InitMap(g_MapSettings.BaseHeight, tWater); +const heightIsland = 20; +const heightSeaGround = -5; + +InitMap(heightSeaGround, tWater); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clForest = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clLand = createTileClass(); const playerIslandRadius = scaleByMapSize(15, 30); -const islandHeight = 20; 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, 10, islandPos[islandID].x, islandPos[islandID].y), [ new LayeredPainter([tCliff, tHill], [2]), - new SmoothElevationPainter(ELEVATION_SET, islandHeight, 2), + new SmoothElevationPainter(ELEVATION_SET, heightIsland, 2), paintClass(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(); 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; 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); 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); 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; 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"); log("Creating player islands..."); for (let i = 0; i < numPlayers; ++i) { islandPos[i] = playerPosition[i]; createIsland(i, 1, isNomad() ? clLand : clPlayer); } placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], // PlayerTileClass already marked above "BaseResourceClass": clBaseResource, "baseResourceConstraint": stayClasses(clPlayer, 4), "Walls": "towers", "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, "Chicken": { }, "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(30); log("Creating connectors..."); for (let i = 0; i < numIslands; ++i) for (let j = 0; j < numIslands; ++j) if (isConnected[i][j]) createPassage({ "start": islandPos[i], "end": islandPos[j], "startWidth": 11, "endWidth": 11, "smoothWidth": 3, - "maxHeight": islandHeight - 1, + "maxHeight": heightIsland - 1, "tileClass": clLand, "terrain": tHill, "edgeTerrain": tCliff }); 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() == "savanna" ? 2 : 1); var num = Math.floor(size / types.length); for (let type of types) createAreas( new ClumpPlacer(forestTrees / num, 0.1, 0.1, 1), [ new LayeredPainter(type, [2]), paintClass(clForest) ], [avoidClasses(clPlayer, 6, clForest, 10), stayClasses(clLand, 4)], num); Engine.SetProgress(55); log("Creating stone mines..."); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 1, clPlayer, 10, clRock, 10), stayClasses(clLand, 5)], 5*scaleByMapSize(4,16), 100 ); 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 ); 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); 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]), paintClass(clDirt) ], [avoidClasses(clForest, 0, clDirt, 5, clPlayer, 12), stayClasses(clLand, 5)], scaleByMapSize(15, 45)); 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)); 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 ); 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); 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); 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 ); 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() == "tropic") planetm = 8; 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); 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); 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)); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/survivalofthefittest.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/survivalofthefittest.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/survivalofthefittest.js (revision 20904) @@ -1,201 +1,204 @@ Engine.LoadLibrary("rmgen"); 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 tHill = g_Terrains.hill; const tTier1Terrain = g_Terrains.tier1Terrain; const tTier2Terrain = g_Terrains.tier2Terrain; const tTier3Terrain = g_Terrains.tier3Terrain; 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 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 aWaypointFlag = "actor|props/special/common/waypoint_flag.xml"; const pForest1 = [tForestFloor2 + TERRAIN_SEPARATOR + oTree1, tForestFloor2 + TERRAIN_SEPARATOR + oTree2, tForestFloor2]; const pForest2 = [tForestFloor1 + TERRAIN_SEPARATOR + oTree4, tForestFloor1 + TERRAIN_SEPARATOR + oTree5, tForestFloor1]; const oTreasureSeeker = "undeletable|skirmish/units/default_support_female_citizen"; const triggerPointAttacker = "trigger/trigger_point_A"; const triggerPointTreasures = [ "trigger/trigger_point_B", "trigger/trigger_point_C", "trigger/trigger_point_D" ]; -InitMap(g_MapSettings.BaseHeight, tMainTerrain); +const heightLand = 3; +const heightHill = 30; + +InitMap(heightHill, tMainTerrain); var numPlayers = getNumPlayers(); var mapSize = getMapSize(); var mapArea = getMapArea(); var mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clDirt = createTileClass(); var clBaseResource = createTileClass(); var clLand = createTileClass(); var clWomen = createTileClass(); // Create the main treasure area in the middle of the map createArea( new ClumpPlacer(mapArea * scaleByMapSize(0.065, 0.09), 0.7, 0.1, 10, mapCenter.x, mapCenter.y), [ new LayeredPainter([tMainTerrain, tMainTerrain], [3]), - new SmoothElevationPainter(ELEVATION_SET, 3, 3), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 3), paintClass(clLand) ]); Engine.SetProgress(10); var [playerIDs, playerPosition, playerAngle, startAngle] = playerPlacementCircle(fractionToTiles(0.3)); var halfway = distributePointsOnCircle(numPlayers, startAngle, fractionToTiles(0.375), mapCenter)[0].map(v => v.round()); var attacker = distributePointsOnCircle(numPlayers, startAngle, fractionToTiles(0.45), mapCenter)[0].map(v => v.round()); var passage = distributePointsOnCircle(numPlayers, startAngle + Math.PI / numPlayers, fractionToTiles(0.5), mapCenter)[0]; log("Creating player bases and attacker points..."); for (let i = 0; i < numPlayers; ++i) { placeStartingEntities(playerPosition[i], playerIDs[i], getStartingEntities(playerIDs[i]).filter(ent => ent.Template.indexOf("civil_centre") != -1 || ent.Template.indexOf("infantry") != -1)); placePlayerBaseDecoratives({ "playerPosition": playerPosition[i], "template": aGrassShort, "BaseResourceClass": clBaseResource }); log("Creating passage separating players..."); createArea( new PathPlacer(mapCenter.x, mapCenter.y, passage[i].x, passage[i].y, scaleByMapSize(14, 24), 0.4, scaleByMapSize(3, 9), 0.2, 0.05), [ new LayeredPainter([tMainTerrain, tMainTerrain], [1]), - new SmoothElevationPainter(ELEVATION_SET, 3, 4) + new SmoothElevationPainter(ELEVATION_SET, heightLand, 4) ]); log("Placing treasure seeker woman..."); let femaleLocation = findLocationInDirectionBasedOnHeight(playerPosition[i], mapCenter, -3 , 3.5, 3).round(); addToClass(femaleLocation.x, femaleLocation.y, clWomen); placeObject(femaleLocation.x, femaleLocation.y, oTreasureSeeker, playerIDs[i], playerAngle[i] + Math.PI); log("Placing attacker spawn point...."); placeObject(attacker[i].x, attacker[i].y, aWaypointFlag, 0, Math.PI / 2); placeObject(attacker[i].x, attacker[i].y, triggerPointAttacker, playerIDs[i], Math.PI / 2); log("Preventing mountains in the area between player and attackers..."); addCivicCenterAreaToClass(playerPosition[i], clPlayer); addToClass(attacker[i].x, attacker[i].y, clPlayer); addToClass(halfway[i].x, halfway[i].y, clPlayer); } Engine.SetProgress(20); paintTerrainBasedOnHeight(3.12, 29, 1, tCliff); paintTileClassBasedOnHeight(3.12, 29, 1, clHill); for (let triggerPointTreasure of triggerPointTreasures) createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(triggerPointTreasure, 1, 1, 0, 0)], true, clWomen), 0, [avoidClasses(clForest, 5, clPlayer, 5, clHill, 5), stayClasses(clLand, 5)], scaleByMapSize(40, 140), 100 ); Engine.SetProgress(25); createBumps(stayClasses(clLand, 5)); var [forestTrees, stragglerTrees] = getTreeCounts(...rBiomeTreeCount(1)); createForests( [tMainTerrain, tForestFloor1, tForestFloor2, pForest1, pForest2], [avoidClasses(clPlayer, 20, clForest, 5, clHill, 0, clBaseResource,2, clWomen, 5), stayClasses(clLand, 4)], clForest, forestTrees); Engine.SetProgress(30); if (randBool()) createHills( [tMainTerrain, tCliff, tHill], [avoidClasses(clPlayer, 20, clHill, 5, clBaseResource, 3, clWomen, 5), stayClasses(clLand, 5)], clHill, scaleByMapSize(10, 60) * numPlayers); else createMountains( tCliff, [avoidClasses(clPlayer, 20, clHill, 5, clBaseResource, 3, clWomen, 5), stayClasses(clLand, 5)], clHill, scaleByMapSize(10, 60) * numPlayers); Engine.SetProgress(40); createHills( [tCliff, tCliff, tHill], avoidClasses(clPlayer, 20, clHill, 5, clBaseResource, 3, clWomen, 5, clLand, 5), clHill, scaleByMapSize(15, 90) * numPlayers, undefined, undefined, undefined, undefined, 55); Engine.SetProgress(50); 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, clWomen, 5), stayClasses(clLand, 5)], scaleByMapSize(15, 45), clDirt); log("Creating grass patches..."); createPatches( [scaleByMapSize(2, 4), scaleByMapSize(3, 7), scaleByMapSize(5, 15)], tTier4Terrain, [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 12, clWomen, 5), stayClasses(clLand, 5)], scaleByMapSize(15, 45), clDirt); var planetm = 1; if (currentBiome() == "tropic") 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)] ], [ scaleByMapSize(16, 262), scaleByMapSize(8, 131), planetm * scaleByMapSize(13, 200), planetm * scaleByMapSize(13, 200), planetm * scaleByMapSize(13, 200) ], [avoidClasses(clForest, 0, clPlayer, 0, clHill, 0), stayClasses(clLand, 5)]); createStragglerTrees( [oTree1, oTree2, oTree4, oTree3], [avoidClasses(clForest, 7, clHill, 1, clPlayer, 9), stayClasses(clLand, 7)], clForest, stragglerTrees); 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 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/the_nile.js (revision 20904) @@ -1,399 +1,405 @@ Engine.LoadLibrary("rmgen"); 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/flora_bush_berry"; var oCamel = "gaia/fauna_camel"; var oGazelle = "gaia/fauna_gazelle"; var oGoat = "gaia/fauna_goat"; var oStoneLarge = "gaia/geology_stonemine_desert_badlands_quarry"; var oStoneSmall = "gaia/geology_stone_desert_small"; var oMetalLarge = "gaia/geology_metal_desert_slabs"; var oDatePalm = "gaia/flora_tree_date_palm"; var oSDatePalm = "gaia/flora_tree_cretan_date_palm_short"; var eObelisk = "other/obelisk"; var ePyramid = "other/pyramid_minor"; var oWoodTreasure = "gaia/special_treasure_wood"; var oFoodTreasure = "gaia/special_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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightLand = 1; +const heightShore = 2; +const heightPonds = -7; +const heightSeaGround = -3; +const heightOffsetBump = 2; + +InitMap(heightLand, g_MapSettings.BaseTerrain); const mapSize = getMapSize(); const mapCenter = getMapCenter(); const mapBounds = getMapBounds(); var aPlants = mapSize < 256 ? "actor|props/flora/grass_tropical.xml" : "actor|props/flora/grass_tropic_field_tall.xml"; var numPlayers = getNumPlayers(); var clPlayer = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clGrass = createTileClass(); var clDesert = createTileClass(); var clPond = createTileClass(); var clShore = createTileClass(); var clTreasure = createTileClass(); var desertWidth = fractionToTiles(0.25); placePlayerBases({ "PlayerPlacement": playerPlacementRiver(0, fractionToTiles(0.4)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tCityPlaza, "innerTerrain": tCity }, "Chicken": { }, "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), "tileClass": tLush }, { "left": fractionToTiles(0.04), "right": fractionToTiles(0.06), "tileClass": tSLush }, { "left": fractionToTiles(0.06), "right": fractionToTiles(0.09), "tileClass": tSDry } ]; const plantFrequency = 2; var plantID = 0; paintRiver({ "parallel": true, "start": new Vector2D(mapCenter.x, mapBounds.top), "end": new Vector2D(mapCenter.x, mapBounds.bottom), "width": fractionToTiles(0.1), "fadeDist": scaleByMapSize(3, 12), "deviation": 0.5, - "waterHeight": -3, - "landHeight": 2, + "heightRiverbed": heightSeaGround, + "heightLand": heightShore, "meanderShort": 12, "meanderLong": 50, "waterFunc": (ix, iz, height, riverFraction) => { addToClass(ix, iz, clWater); createTerrain(tShore).place(ix, iz); // Place river bushes if (height <= -0.2 || height >= 0.1) return; if (plantID % plantFrequency == 0) { plantID = 0; placeObject(ix, iz, aPlants, 0, randomAngle()); } ++plantID; }, "landFunc": (ix, iz, shoreDist1, shoreDist2) => { for (let riv of riverTextures) if (riv.left < +shoreDist1 && +shoreDist1 < riv.right || riv.left < -shoreDist2 && -shoreDist2 < riv.right) { createTerrain(riv.tileClass).place(ix, iz); addToClass(ix, iz, clShore); } } }); Engine.SetProgress(40); log("Marking desert..."); for (let [left, right] of [[mapBounds.left, mapBounds.left + desertWidth], [mapBounds.right - desertWidth, mapBounds.right]]) createArea( new RectPlacer(left, mapBounds.top, right, mapBounds.bottom), paintClass(clDesert)); log("Creating bumps..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1), - new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), avoidClasses(clWater, 2, clPlayer, 6), scaleByMapSize(100, 200)); 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, 10), [ new LayeredPainter([tShore, tShore, tShore], [1, 1]), - new SmoothElevationPainter(ELEVATION_SET, -7, 4), + new SmoothElevationPainter(ELEVATION_SET, heightPonds, 4), paintClass(clPond) ], avoidClasses(clPlayer, 25, clWater, 20, clPond, 10), numLakes); log("Creating reeds..."); createObjectGroupsByAreasDeprecated( new SimpleGroup([new SimpleObject(aReeds, 1, 3, 0, 1)], true), 0, stayClasses(clPond, 1), numLakes, 100, waterAreas); log("Creating lillies..."); createObjectGroupsByAreasDeprecated( new SimpleGroup([new SimpleObject(aLillies, 1, 3, 0, 1)], true), 0, stayClasses(clPond, 1), numLakes, 100, waterAreas); 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]), paintClass(clForest) ], avoidClasses(clPlayer, 19, clForest, 4, clWater, 1, clDesert, 5, clPond, 2, clBaseResource, 3), num, 50); Engine.SetProgress(50); 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]), paintClass(clDirt) ], avoidClasses(clForest, 0, clGrass, 5, clPlayer, 10, clWater, 1, clDirt, 5, clShore, 1, clPond, 1), scaleByMapSize(15, 45)); Engine.SetProgress(55); 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]), paintClass(clDirt) ], avoidClasses(clForest, 0, clDirt, 5, clPlayer, 10, clWater, 1, clGrass, 5, clShore, 1, clPond, 1), scaleByMapSize(15, 45)); Engine.SetProgress(60); log("Creating stone mines..."); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4), new SimpleObject(oStoneLarge, 1, 1, 0, 4)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clWater, 1, clPond, 1), scaleByMapSize(4,16), 100 ); 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 ); 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 ); log("Creating stone mines..."); group = new SimpleGroup([new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], true, clRock); createObjectGroupsDeprecated(group, 0, [avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clWater, 1, clPond, 1), stayClasses(clDesert, 3)], scaleByMapSize(6,20), 100 ); 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 ); 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); 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 ); 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); 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 ); 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 ); 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 ); 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); 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, 2, clPond, 4, clTreasure, 2), stayClasses(clDesert, 3)], scaleByMapSize(5, 30), 50 ); 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"); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/unknown_land.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/unknown_land.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/unknown_land.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "Unknown Land", "Script" : "unknown_land.js", "Description" : "The unknown.", "BaseTerrain" : ["medit_sand_wet"], - "BaseHeight" : -5, "Preview" : "unknown.png", "SupportedBiomes": true, "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/phoenician_levant.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/phoenician_levant.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/phoenician_levant.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Phoenician Levant", "Script" : "phoenician_levant.js", "Description" : "Players start in the eastern part of the map while a great sea is located to the west.", "BaseTerrain" : ["medit_dirt", "medit_dirt_b", "medit_dirt_c", "medit_rocks_grass", "medit_rocks_grass"], - "BaseHeight" : 1, "Preview" : "phoenician_levant.png", "CircularMap" : false } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/pyrenean_sierra.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/pyrenean_sierra.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/pyrenean_sierra.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Pyrenean Sierra", "Script" : "pyrenean_sierra.js", "Description" : "High mountains separating the enemies.\n\nThe Pyrenees is a great mountain range located between modern France and Spain.", "BaseTerrain" : ["alpine_dirt_grass_50"], - "BaseHeight" : -100, "Preview" : "pyrenean_sierra.png", "CircularMap" : true } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/river_archipelago.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/river_archipelago.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/river_archipelago.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "River Archipelago", "Script" : "river_archipelago.js", "Description" : "Narrow strips of lands are separated by waterways, leaving few and shallow landbridges between them. Tropical wetlands provide plenty of game, but beware of Mauryan tribesmen when exploring the outermost islands.", "BaseTerrain" : ["tropic_grass_c", "tropic_grass_c", "tropic_grass_c", "tropic_grass_c", "tropic_grass_plants", "tropic_plants", "tropic_plants_b"], - "BaseHeight" : -8, "Keywords": ["naval"], "Preview" : "river_archipelago.png", "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/rmgen/library.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rmgen/library.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/rmgen/library.js (revision 20904) @@ -1,445 +1,440 @@ const TERRAIN_SEPARATOR = "|"; const SEA_LEVEL = 20.0; const HEIGHT_UNITS_PER_METRE = 92; const MAP_BORDER_WIDTH = 3; const g_DamageTypes = new DamageTypes(); /** * Constants needed for heightmap_manipulation.js */ const MAX_HEIGHT_RANGE = 0xFFFF / HEIGHT_UNITS_PER_METRE; // Engine limit, Roughly 700 meters const MIN_HEIGHT = - SEA_LEVEL; /** * Length of one tile of the terrain grid in metres. * Useful to transform footprint sizes of templates to the coordinate system used by getMapSize. */ const TERRAIN_TILE_SIZE = Engine.GetTerrainTileSize(); const MAX_HEIGHT = MAX_HEIGHT_RANGE - SEA_LEVEL; /** * Default angle for buildings. */ const BUILDING_ORIENTATION = -1/4 * Math.PI; const g_CivData = deepfreeze(loadCivFiles(false)); function fractionToTiles(f) { return g_Map.size * f; } function tilesToFraction(t) { return t / g_Map.size; } function fractionToSize(f) { return getMapArea() * f; } function sizeToFraction(s) { return s / getMapArea(); } function scaleByMapSize(min, max, minMapSize = 128, maxMapSize = 512) { return min + (max - min) * (g_Map.size - minMapSize) / (maxMapSize - minMapSize); } /** * Retries the given function with those arguments as often as specified. */ function retryPlacing(placeFunc, retryFactor, amount, getResult, behaveDeprecated = false) { let maxFail = amount * retryFactor; let results = []; let good = 0; let bad = 0; while (good < amount && bad <= maxFail) { let result = placeFunc(); if (result !== undefined || behaveDeprecated) { ++good; if (getResult) results.push(result); } else ++bad; } return getResult ? results : good; } /** * Sets the x and z property of the given object (typically a Placer or Group) to a random point on the map. * @param passableOnly - Should be true for entity placement and false for terrain or elevation operations. */ function randomizeCoordinates(obj, passableOnly) { let border = passableOnly ? MAP_BORDER_WIDTH : 0; if (g_MapSettings.CircularMap) { // Polar coordinates // Uniformly distributed on the disk let halfMapSize = g_Map.size / 2 - border; let r = halfMapSize * Math.sqrt(randFloat(0, 1)); let theta = randomAngle(); obj.x = Math.floor(r * Math.cos(theta)) + halfMapSize; obj.z = Math.floor(r * Math.sin(theta)) + halfMapSize; } else { // Rectangular coordinates obj.x = randIntExclusive(border, g_Map.size - border); obj.z = randIntExclusive(border, g_Map.size - border); } } /** * Sets the x and z property of the given JS object (typically a Placer or Group) to a random point of the area. */ function randomizeCoordinatesFromAreas(obj, areas) { let pt = pickRandom(pickRandom(areas).points); obj.x = pt.x; obj.z = pt.z; } // TODO this is a hack to simulate the old behaviour of those functions // until all old maps are changed to use the correct version of these functions function createObjectGroupsDeprecated(group, player, constraint, amount, retryFactor = 10) { return createObjectGroups(group, player, constraint, amount, retryFactor, true); } function createObjectGroupsByAreasDeprecated(group, player, constraint, amount, retryFactor, areas) { return createObjectGroupsByAreas(group, player, constraint, amount, retryFactor, areas, true); } /** * Attempts to place the given number of areas in random places of the map. * Returns actually placed areas. */ function createAreas(centeredPlacer, painter, constraint, amount, retryFactor = 10) { let placeFunc = function() { randomizeCoordinates(centeredPlacer, false); return createArea(centeredPlacer, painter, constraint); }; return retryPlacing(placeFunc, retryFactor, amount, true, false); } /** * Attempts to place the given number of areas in random places of the given areas. * Returns actually placed areas. */ function createAreasInAreas(centeredPlacer, painter, constraint, amount, retryFactor, areas) { let placeFunc = function() { randomizeCoordinatesFromAreas(centeredPlacer, areas); return createArea(centeredPlacer, painter, constraint); }; return retryPlacing(placeFunc, retryFactor, amount, true, false); } /** * Attempts to place the given number of groups in random places of the map. * Returns the number of actually placed groups. */ function createObjectGroups(group, player, constraint, amount, retryFactor = 10, behaveDeprecated = false) { let placeFunc = function() { randomizeCoordinates(group, true); return createObjectGroup(group, player, constraint); }; return retryPlacing(placeFunc, retryFactor, amount, false, behaveDeprecated); } /** * Attempts to place the given number of groups in random places of the given areas. * Returns the number of actually placed groups. */ function createObjectGroupsByAreas(group, player, constraint, amount, retryFactor, areas, behaveDeprecated = false) { let placeFunc = function() { randomizeCoordinatesFromAreas(group, areas); return createObjectGroup(group, player, constraint); }; return retryPlacing(placeFunc, retryFactor, amount, false, behaveDeprecated); } function createTerrain(terrain) { return typeof terrain == "string" ? new SimpleTerrain(...terrain.split(TERRAIN_SEPARATOR)) : new RandomTerrain(terrain.map(t => createTerrain(t))); } function placeObject(x, z, type, player, angle) { if (g_Map.validT(x, z)) g_Map.addObject(new Entity(type, player, x, z, angle)); } function isCircularMap() { return !!g_MapSettings.CircularMap; } -function getMapBaseHeight() -{ - return g_MapSettings.BaseHeight; -} - function createTileClass() { return g_Map.createTileClass(); } function getTileClass(id) { if (!g_Map.validClass(id)) return undefined; return g_Map.tileClasses[id]; } /** * Constructs a new Area shaped by the Placer meeting the Constraints and calls the Painters there. * Supports both Centered and Non-Centered Placers. */ function createArea(placer, painter, constraints) { let points = placer.place(new AndConstraint(constraints)); if (!points) return undefined; let area = g_Map.createArea(points); if (painter instanceof Array) painter = new MultiPainter(painter); painter.paint(area); return area; } /** * @param mode is one of the HeightPlacer constants determining whether to exclude the min/max elevation. */ function paintTerrainBasedOnHeight(minHeight, maxHeight, mode, terrain) { createArea( new HeightPlacer(mode, minHeight, maxHeight), new TerrainPainter(terrain)); } function paintTileClassBasedOnHeight(minHeight, maxHeight, mode, tileClass) { createArea( new HeightPlacer(mode, minHeight, maxHeight), new TileClassPainter(getTileClass(tileClass))); } function unPaintTileClassBasedOnHeight(minHeight, maxHeight, mode, tileClass) { createArea( new HeightPlacer(mode, minHeight, maxHeight), new TileClassUnPainter(getTileClass(tileClass))); } /** * Places the Entities of the given Group if they meet the Constraints * and sets the given player as the owner. */ function createObjectGroup(group, player, constraints) { return group.place(player, new AndConstraint(constraints)); } function getMapSize() { return g_Map.size; } function getMapArea() { return Math.square(g_Map.size); } function getMapCenter() { return deepfreeze(new Vector2D(g_Map.size / 2, g_Map.size / 2)); } function getMapBounds() { return deepfreeze({ "left": fractionToTiles(0), "right": fractionToTiles(1), "top": fractionToTiles(1), "bottom": fractionToTiles(0) }); } 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; } function getHeight(x, z) { return g_Map.getHeight(x, z); } function setHeight(x, z, height) { g_Map.setHeight(x, z, height); } /** * Utility functions for classes */ /** * Add point to given class by id */ function addToClass(x, z, id) { let tileClass = getTileClass(id); if (tileClass !== null) tileClass.add(x, z); } /** * Remove point from the given class by id */ function removeFromClass(x, z, id) { let tileClass = getTileClass(id); if (tileClass !== null) tileClass.remove(x, z); } /** * Create a painter for the given class */ function paintClass(id) { return new TileClassPainter(getTileClass(id)); } /** * Create a painter for the given class */ function unPaintClass(id) { return new TileClassUnPainter(getTileClass(id)); } /** * Create an avoid constraint for the given classes by the given distances */ function avoidClasses(/*class1, dist1, class2, dist2, etc*/) { let ar = []; for (let i = 0; i < arguments.length/2; ++i) ar.push(new AvoidTileClassConstraint(arguments[2*i], arguments[2*i+1])); // Return single constraint if (ar.length == 1) return ar[0]; return new AndConstraint(ar); } /** * Create a stay constraint for the given classes by the given distances */ function stayClasses(/*class1, dist1, class2, dist2, etc*/) { let ar = []; for (let i = 0; i < arguments.length/2; ++i) ar.push(new StayInTileClassConstraint(arguments[2*i], arguments[2*i+1])); // Return single constraint if (ar.length == 1) return ar[0]; return new AndConstraint(ar); } /** * Create a border constraint for the given classes by the given distances */ function borderClasses(/*class1, idist1, odist1, class2, idist2, odist2, etc*/) { let ar = []; for (let i = 0; i < arguments.length/3; ++i) ar.push(new BorderTileClassConstraint(arguments[3*i], arguments[3*i+1], arguments[3*i+2])); // Return single constraint if (ar.length == 1) return ar[0]; return new AndConstraint(ar); } /** * Checks if the given tile is in class "id" */ function checkIfInClass(x, z, id) { let tileClass = getTileClass(id); if (tileClass === null) return 0; let members = tileClass.countMembersInRadius(x, z, 1); if (members === null) return 0; return members; } Index: ps/trunk/binaries/data/mods/public/maps/random/sahel.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/sahel.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/sahel.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Sahel", "Script" : "sahel.js", "Description" : "A somewhat open map with an abundance of food and mineral resources, while wood is somewhat scarce.", "BaseTerrain" : "savanna_grass_a", - "BaseHeight" : 1, "Preview" : "sahel.png", "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/schwarzwald.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/schwarzwald.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/schwarzwald.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Schwarzwald", "Script" : "schwarzwald.js", "Description" : "A forest heavy map with a lake in the middle and plenty of resources.", "CircularMap" : true, "BaseTerrain" : ["temp_grass_plants", "temp_plants_bog"], - "BaseHeight" : 0, "Preview" : "schwarzwald.png" } } Index: ps/trunk/binaries/data/mods/public/maps/random/stronghold.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/stronghold.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/stronghold.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "Stronghold", "Script" : "stronghold.js", "Description" : "Teams start off with nearly adjacent civic centers, offering easy military and construction cooperation. With slivers of personal territory, teammates must rely on each other to defend their rear.", "BaseTerrain" : ["medit_sea_depths"], - "BaseHeight" : 30, "Preview" : "stronghold.png", "SupportedBiomes": true, "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/syria.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/syria.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/syria.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Syria", "Script" : "syria.js", "Description" : "Players start in a plains with slightly rolling highlands.", "BaseTerrain" : ["desert_dirt_rocks_1", "desert_dirt_cracks"], - "BaseHeight" : 1, "Preview" : "syria.png", "CircularMap" : true } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/unknown.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/unknown.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/unknown.json (revision 20904) @@ -1,12 +1,11 @@ { "settings" : { "Name" : "Unknown", "Script" : "unknown.js", "Description" : "The unknown. Warning: May be a naval map.", "BaseTerrain" : ["medit_sand_wet"], - "BaseHeight" : -5, "Preview" : "unknown.png", "SupportedBiomes": true, "CircularMap" : true } } Index: ps/trunk/binaries/data/mods/public/maps/random/phoenician_levant.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/phoenician_levant.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/phoenician_levant.js (revision 20904) @@ -1,323 +1,326 @@ Engine.LoadLibrary("rmgen"); //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/flora_bush_grapes"; const oDeer = "gaia/fauna_deer"; const oFish = "gaia/fauna_fish"; const oSheep = "gaia/fauna_sheep"; const oGoat = "gaia/fauna_goat"; const oStoneLarge = "gaia/geology_stonemine_medit_quarry"; const oStoneSmall = "gaia/geology_stone_mediterranean"; const oMetalLarge = "gaia/geology_metal_mediterranean_slabs"; const oDatePalm = "gaia/flora_tree_cretan_date_palm_short"; const oSDatePalm = "gaia/flora_tree_cretan_date_palm_tall"; const oCarob = "gaia/flora_tree_carob"; const oFanPalm = "gaia/flora_tree_medit_fan_palm"; const oPoplar = "gaia/flora_tree_poplar_lombardy"; const oCypress = "gaia/flora_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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightSeaGround = -3; +const heightShore = -1.5; +const heightLand = 1; +const heightIsland = 6; +const heightHill = 15; +const heightOffsetBump = 2; + +InitMap(heightLand, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); const mapBounds = getMapBounds(); var clPlayer = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clGrass = createTileClass(); var clHill = createTileClass(); var clIsland = createTileClass(); -var waterHeight = -3; -var shoreHeight = -1.5; -var landHeight = getMapBaseHeight(); - placePlayerBases({ "PlayerPlacement": playerPlacementLine(false, new Vector2D(fractionToTiles(0.76), mapCenter.y), fractionToTiles(0.2)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tCityPlaza, "innerTerrain": tCity }, "Chicken": { }, "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), "end": new Vector2D(mapBounds.left, mapBounds.bottom), "width": mapSize, "fadeDist": scaleByMapSize(6, 25), "deviation": 0, - "waterHeight": waterHeight, - "landHeight": landHeight, + "heightRiverbed": heightSeaGround, + "heightLand": heightLand, "meanderShort": 20, "meanderLong": 0 }); Engine.SetProgress(40); -paintTileClassBasedOnHeight(-Infinity, landHeight, Elevation_ExcludeMin_ExcludeMax, clWater); -paintTerrainBasedOnHeight(-Infinity, shoreHeight, Elevation_ExcludeMin_ExcludeMax, tWater); -paintTerrainBasedOnHeight(shoreHeight, landHeight, Elevation_ExcludeMin_ExcludeMax, tShore); +paintTileClassBasedOnHeight(-Infinity, heightLand, Elevation_ExcludeMin_ExcludeMax, clWater); +paintTerrainBasedOnHeight(-Infinity, heightShore, Elevation_ExcludeMin_ExcludeMax, tWater); +paintTerrainBasedOnHeight(heightShore, heightLand, Elevation_ExcludeMin_ExcludeMax, tShore); log("Creating bumps..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1), - new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), avoidClasses(clWater, 2, clPlayer, 20), scaleByMapSize(100, 200)); 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, 15, 2), + new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), paintClass(clHill) ], avoidClasses(clPlayer, 20, clForest, 1, clHill, 15, clWater, 0), scaleByMapSize(1, 4) * numPlayers * 3); 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]), paintClass(clForest) ], avoidClasses(clPlayer, 20, clForest, 10, clWater, 1, clHill, 1, clBaseResource, 3), num, 50); Engine.SetProgress(50); 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]), paintClass(clDirt) ], avoidClasses(clForest, 0, clGrass, 5, clPlayer, 10, clWater, 4, clDirt, 5, clHill, 1), scaleByMapSize(15, 45)); Engine.SetProgress(55); 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]), paintClass(clDirt) ], avoidClasses(clForest, 0, clDirt, 5, clPlayer, 10, clWater, 4, clGrass, 5, clHill, 1), scaleByMapSize(15, 45)); Engine.SetProgress(60); 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, 6, 8), + new SmoothElevationPainter(ELEVATION_SET, heightIsland, 8), paintClass(clIsland), unPaintClass(clWater) ], [stayClasses (clWater, 8)], 1, 100); log("Creating cyprus mines..."); var mines = [ new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4), new SimpleObject(oStoneLarge, 1, 1, 0, 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)); log("Creating stone mines..."); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clForest, 1, clPlayer, 20, clRock, 10, clWater, 3, clHill, 1), scaleByMapSize(4,16), 100 ); 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 ); 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); 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 ); 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); 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 ); 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 ); 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 ); 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 ); 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); setTerrainAmbientColor(0.57, 0.58, 0.55); setUnitsAmbientColor(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)); 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 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/pyrenean_sierra.js (revision 20904) @@ -1,508 +1,511 @@ Engine.LoadLibrary("rmgen"); 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 tPass = ["alpine_cliff_b", "alpine_cliff_c", "alpine_grass_rocky", "alpine_grass_rocky", "alpine_grass_rocky"]; 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/flora_tree_euro_beech"; const oPine = "gaia/flora_tree_aleppo_pine"; const oBerryBush = "gaia/flora_bush_berry"; const oDeer = "gaia/fauna_deer"; const oFish = "gaia/fauna_fish"; const oRabbit = "gaia/fauna_rabbit"; const oStoneLarge = "gaia/geology_stonemine_alpine_quarry"; const oStoneSmall = "gaia/geology_stone_alpine_a"; const oMetalLarge = "gaia/geology_metal_alpine_slabs"; 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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightLand = -100; +const heightOffsetHill = 7; +const heightOffsetHillRandom = 2; + +InitMap(heightLand, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clPass = createTileClass(); var clPyrenneans = createTileClass(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); // Initial Terrain Creation // I'll use very basic noised sinusoidal functions to give the terrain a way aspect // It looks like we can't go higher than ≈ 75. Given this I'll lower the ground const baseHeight = -6; setWaterHeight(8); var MoutainAngle = randFloat(0,2 * Math.PI); var oceanAngle = MoutainAngle + randFloat(-1, 1) * Math.PI / 12; var baseHeights = []; for (var ix = 0; ix < mapSize; ix++) { baseHeights.push([]); for (var iz = 0; iz < mapSize; iz++) { if (g_Map.inMapBounds(ix,iz)) { createTerrain(tGrass).place(ix, iz); let height = baseHeight + randFloat(-1, 1) + scaleByMapSize(1, 3) * (Math.cos(ix / scaleByMapSize(5, 30)) + Math.sin(iz / scaleByMapSize(5, 30))); setHeight(ix, iz, height); baseHeights[ix].push(height); } else baseHeights[ix].push(-100); } } placePlayerBases({ "PlayerPlacement": [primeSortAllPlayers(), ...playerPlacementCustomAngle( fractionToTiles(0.35), mapCenter, i => oceanAngle + Math.PI * (i % 2 ? 1 : -1) * ((1/2 + 1/3 * (2/numPlayers * (i + 1 - i % 2) - 1))))], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad }, "Chicken": { }, "Berries": { "template": oBerryBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oPine }, "Decoratives": { "template": aGrassShort } }); Engine.SetProgress(30); log("Creating the pyreneans..."); var mountainLength = fractionToTiles(0.68); var mountainVec = new Vector2D(mountainLength, 0).rotate(-MoutainAngle); var mountainVecHalf = Vector2D.mult(mountainVec, 1/2); var mountainStart = Vector2D.add(mapCenter, mountainVecHalf); var mountainEnd = Vector2D.sub(mapCenter, mountainVecHalf); // Number of peaks var MountainHeight = scaleByMapSize(50, 65); var NumOfIterations = scaleByMapSize(100,1000); var randomNess = randFloat(-scaleByMapSize(1,12),scaleByMapSize(1,12)); for (var i = 0; i < NumOfIterations; i++) { Engine.SetProgress(45 * i/NumOfIterations + 30 * (1-i/NumOfIterations)); var position = i/NumOfIterations; var width = scaleByMapSize(15,55); var randHeight2 = randFloat(0,10) + MountainHeight; for (var dist = 0; dist < width*3; dist++) { var okDist = dist/3; var S1x = Math.round((mountainStart.x * (1 - position) + mountainEnd.x * position) + randomNess * Math.cos(position * Math.PI * 4) + Math.cos(MoutainAngle + Math.PI / 2) * okDist); var S1z = Math.round((mountainStart.y * (1 - position) + mountainEnd.y * position) + randomNess * Math.sin(position * Math.PI * 4) + Math.sin(MoutainAngle + Math.PI / 2) * okDist); var S2x = Math.round((mountainStart.x * (1 - position) + mountainEnd.x * position) + randomNess * Math.cos(position * Math.PI * 4) + Math.cos(MoutainAngle - Math.PI / 2) * okDist); var S2z = Math.round((mountainStart.y * (1 - position) + mountainEnd.y * position) + randomNess * Math.sin(position * Math.PI * 4) + Math.sin(MoutainAngle - Math.PI / 2) * okDist); // complicated sigmoid // Ranges is 0-1, FormX is 0-1 too. var FormX = (-2*(1-okDist/width)+1.9) - 4*(2*(1-okDist/width)-randFloat(0.9,1.1))*(2*(1-okDist/width)-randFloat(0.9,1.1))*(2*(1-okDist/width)-randFloat(0.9,1.1)); var Formula = (1/(1 + Math.exp(FormX))); // If we're too far from the border, we flatten Formula *= (0.2 - Math.max(0, Math.abs(0.5 - position) - 0.3)) * 5; var randHeight = randFloat(-9,9) * Formula; var height = baseHeights[S1x][S1z]; setHeight(S1x,S1z, height + randHeight2 * Formula + randHeight ); var height = baseHeights[S2x][S2z]; setHeight(S2x,S2z, height + randHeight2 * Formula + randHeight ); if (getHeight(S1x,S1z) > 15) addToClass(S1x,S1z, clPyrenneans); if (getHeight(S2x,S2z) > 15) addToClass(S2x,S2z, clPyrenneans); } } // Allright now slight smoothing (decreasing with height) for (var ix = 1; ix < mapSize-1; ix++) { for (var iz = 1; iz < mapSize-1; iz++) { if (g_Map.inMapBounds(ix,iz) && checkIfInClass(ix,iz,clPyrenneans) ) { var NB = getNeighborsHeight(ix,iz); var index = 9/(1 + Math.max(0,getHeight(ix,iz)/7)); setHeight(ix,iz, (getHeight(ix,iz)*(9-index) + NB*index)/9 ); } } } Engine.SetProgress(48); log("Creating passages..."); var passageLocation = 0.35; -var passageHeight = MountainHeight - 25; var passageLength = scaleByMapSize(8, 50); var passageVec = mountainVec.perpendicular().normalize().mult(passageLength); for (let passLoc of [passageLocation, 1 - passageLocation]) for (let direction of [1, -1]) { let passageStart = Vector2D.add(mountainEnd, Vector2D.mult(mountainVec, passLoc)); let passageEnd = Vector2D.add(passageStart, Vector2D.mult(passageVec, direction)); createPassage({ "start": passageStart, "end": passageEnd, - "startHeight": passageHeight, + "startHeight": MountainHeight - 25, "startWidth": 7, "endWidth": 7, "smoothWidth": 2, "tileClass": clPass }); } Engine.SetProgress(50); // Smoothing the mountains for (var ix = 1; ix < mapSize-1; ix++) for (var iz = 1; iz < mapSize-1; iz++) { if ( g_Map.inMapBounds(ix,iz) && checkIfInClass(ix,iz,clPyrenneans) ) { var NB = getNeighborsHeight(ix,iz); var index = 9/(1 + Math.max(0,(getHeight(ix,iz)-10)/7)); setHeight(ix,iz, (getHeight(ix,iz)*(9-index) + NB*index)/9 ); baseHeights[ix][iz] = (getHeight(ix,iz)*(9-index) + NB*index)/9; } } 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, 10, ocean.x, ocean.y), [ new ElevationPainter(-22), paintClass(clWater) ]); // Smoothing around the water, then going a bit random for (var ix = 1; ix < mapSize-1; ix++) { for (var iz = 1; iz < mapSize-1; iz++) { if ( g_Map.inMapBounds(ix,iz) && getTileClass(clWater).countInRadius(ix,iz,5,true) > 0 ) { var averageHeight = 0; var size = 5; if (getTileClass(clPyrenneans).countInRadius(ix,iz,1,true) > 0) size = 1; else if (getTileClass(clPyrenneans).countInRadius(ix,iz,2,true) > 0) size = 2; else if (getTileClass(clPyrenneans).countInRadius(ix,iz,3,true) > 0) size = 3; else if (getTileClass(clPyrenneans).countInRadius(ix,iz,4,true) > 0) size = 4; var todivide = 0; for (var xx = -size; xx <= size;xx++) for (var yy = -size; yy <= size;yy++) { if (g_Map.inMapBounds(ix + xx,iz + yy) && (xx != 0 || yy != 0)){ averageHeight += getHeight(ix + xx,iz + yy) / (Math.abs(xx) + Math.abs(yy)); todivide += 1 / (Math.abs(xx) + Math.abs(yy)); } } averageHeight += getHeight(ix,iz)*2; averageHeight /= (todivide+2); setHeight(ix,iz, averageHeight ); //baseHeights[ix][iz] = averageHeight; } if ( g_Map.inMapBounds(ix,iz) && getTileClass(clWater).countInRadius(ix,iz,4,true) > 0 && getTileClass(clWater).countInRadius(ix,iz,4) > 0 ) setHeight(ix,iz, getHeight(ix,iz) + randFloat(-1,1)); } } Engine.SetProgress(55); log("Creating hills..."); createAreas( new ClumpPlacer(scaleByMapSize(60, 120), 0.3, 0.06, 5), [ - new SmoothElevationPainter(ELEVATION_MODIFY, 7, 4, 2), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetHill, 4, heightOffsetHillRandom), new TerrainPainter(tGrassSpecific), paintClass(clHill) ], avoidClasses(clWater, 5, clPlayer, 20, clBaseResource, 6, clPyrenneans, 2), scaleByMapSize(5, 35)); 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, 1), [ new LayeredPainter(type, [scaleByMapSize(1, 2), scaleByMapSize(3, 6), scaleByMapSize(3, 6)]), paintClass(clForest) ], avoidClasses(clPlayer, 20, clPyrenneans,0, clForest, 7, clWater, 2), num); Engine.SetProgress(60); 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 ); log("Painting the map..."); for (let x = 0; x < mapSize; ++x) for (let z = 0; z < mapSize; ++z) { let height = getHeight(x, z); let heightDiff = getHeightDifference(x, z); if (getTileClass(clPyrenneans).countInRadius(x, z, 2, true)) { createTerrain(getPyreneansTerrain(height, heightDiff)).place(x, z); if (height >= 30 && heightDiff < 5 && getTileClass(clPass).countInRadius(x, z, 2, true)) createTerrain(tPass).place(x,z); } let terrainShore = getShoreTerrain(height, heightDiff, x, z); if (terrainShore) createTerrain(terrainShore).place(x, z); } function getPyreneansTerrain(height, heightDiff) { if (height < 6) return heightDiff < 5 ? tGrass : tMidRangeCliffs; if (height < 18) return heightDiff < 8 ? tGrassMidRange : tMidRangeCliffs; if (height < 30) return heightDiff < 8 ? tGrassHighRange : tMidRangeCliffs; if (height < MountainHeight - 20) return heightDiff < 8 ? tHighRocks : tHighRangeCliffs; if (height < MountainHeight - 10) return heightDiff < 7 ? tSnowedRocks : tHighRangeCliffs; return heightDiff < 6 ? tTopSnowOnly : tTopSnow; } function getShoreTerrain(height, heightDiff, x, z) { if (height <= -14) return tWater; if (height <= -2 && getTileClass(clWater).countInRadius(x, z, 2, true)) return heightDiff < 2.5 ? tSand : tMidRangeCliffs; if (height <= 0 && getTileClass(clWater).countInRadius(x, z, 3, true)) return heightDiff < 2.5 ? tSandTransition : tMidRangeCliffs; return undefined; } 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), paintClass(clDirt) ], avoidClasses(clWater, 3, clForest, 0, clPyrenneans,5, clHill, 0, clDirt, 5, clPlayer, 6), scaleByMapSize(15, 45)); 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 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); 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); 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); log("Creating stone mines..."); group = new SimpleGroup([new SimpleObject(oStoneSmall, 0,2, 0,4), new SimpleObject(oStoneLarge, 1,1, 0,4)], true, clRock); createObjectGroupsDeprecated(group, 0, avoidClasses(clWater, 3, clForest, 1, clPlayer, 20, clRock, 8, clPyrenneans, 1), scaleByMapSize(4,16), 100 ); 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, 8, clPyrenneans, 1), scaleByMapSize(4,16), 100 ); 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, 8, clRock, 5, clPyrenneans, 1), scaleByMapSize(4,16), 100 ); Engine.SetProgress(85); 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 ); 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); 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 ); 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 ); 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); 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); setTerrainAmbientColor(0.45,0.45,0.50); setUnitsAmbientColor(0.4,0.4,0.4); setWaterColor(0.263, 0.353, 0.616); setWaterTint(0.104, 0.172, 0.563); setWaterWaviness(5.0); setWaterType("ocean"); setWaterMurkiness(0.83); ExportMap(); function getNeighborsHeight(x1, z1) { var toCheck = [ [-1,-1], [-1,0], [-1,1], [0,1], [1,1], [1,0], [1,-1], [0,-1] ]; var height = 0; for (var i in toCheck) { var xx = x1 + toCheck[i][0]; var zz = z1 + toCheck[i][1]; height += getHeight(Math.round(xx), Math.round(zz)); } height /= 8; return height; } // no need for preliminary rounding function getHeightDifference(x1, z1) { x1 = Math.round(x1); z1 = Math.round(z1); var height = getHeight(x1,z1); if (!g_Map.inMapBounds(x1,z1)) return 0; // I wanna store the height difference with any neighbor var toCheck = [ [-1,-1], [-1,0], [-1,1], [0,1], [1,1], [1,0], [1,-1], [0,-1] ]; var diff = 0; var todiv = 0; for (var i in toCheck) { var xx = Math.round(x1 + toCheck[i][0]); var zz = Math.round(z1 + toCheck[i][1]); if (g_Map.inMapBounds(xx,zz)) { diff += Math.abs(getHeight(xx,zz) - height); todiv++; } } if (todiv > 0) diff /= todiv; return diff; } Index: ps/trunk/binaries/data/mods/public/maps/random/river_archipelago.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/river_archipelago.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/river_archipelago.js (revision 20904) @@ -1,488 +1,493 @@ Engine.LoadLibrary("rmgen"); 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/flora_tree_toona"; const oPalm1 = "gaia/flora_tree_palm_tropic"; const oPalm2 = "gaia/flora_tree_palm_tropical"; const oStoneLarge = "gaia/geology_stonemine_tropic_quarry"; const oStoneSmall = "gaia/geology_stone_tropic_a"; const oMetalLarge = "gaia/geology_metal_tropic_slabs"; const oFish = "gaia/fauna_fish"; const oDeer = "gaia/fauna_deer"; const oTiger = "gaia/fauna_tiger"; const oBoar = "gaia/fauna_boar"; const oPeacock = "gaia/fauna_peacock"; const oBush = "gaia/flora_bush_berry"; 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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightSeaGround = -8; +const heightLand = 3; +const heightHill = 25; + +InitMap(heightSeaGround, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); const mapCenter = getMapCenter(); var clPlayer = createTileClass(); var clPlayerTerritory = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clGaia = createTileClass(); var clStrip = []; var connectPlayers = randBool(); // Map layout var stripWidthsLeft = connectPlayers ? [[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); log("Creating strips..."); for (let i = 0; i < stripWidths.length; ++i) { clStrip[i] = createTileClass(); let isPlayerStrip = i == 2 || i == 3; for (let j = 0; j < scaleByMapSize(20, 100); ++j) createArea( new ChainPlacer( 1, Math.floor(scaleByMapSize(3, connectPlayers && isPlayerStrip ? 8 : 7)), Math.floor(scaleByMapSize(30, 60)), 1, Math.floor(fractionToTiles(randFloat(...stripWidths[i]))), Math.floor(fractionToTiles(randFloat(0, 1)))), [ new LayeredPainter([tGrass, tGrass], [2]), - new SmoothElevationPainter(ELEVATION_SET, 3, 3), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 3), paintClass(clStrip[i]) ]); } Engine.SetProgress(20); var [playerIDs, playerPosition] = playerPlacementLine(false, mapCenter, fractionToTiles(1 - stripWidthsLeft[2][0] - stripWidthsLeft[2][1])); // Either left vs right or top vs bottom playerIDs = randBool() ? sortAllPlayers() : primeSortAllPlayers(); 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].x, playerPosition[i].y, 0, [Math.floor(playerRadius)]), [ new LayeredPainter([tGrass, tGrass, tGrass], [1, 4]), - new SmoothElevationPainter(ELEVATION_SET, 3, 4), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), paintClass(clPlayerTerritory) ]); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, + "baseResourceConstraint": stayClasses(clPlayerTerritory, 4), "Walls": "towers", "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad, "radius": playerRadius / 3 }, "Chicken": { "template": oPeacock }, "Berries": { "template": oBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Trees": { "template": oTree, "count": 40 } // No decoratives }); Engine.SetProgress(35); paintTerrainBasedOnHeight(-10, 0, 1, tWater); paintTileClassBasedOnHeight(-10, 0, 1, clWater); paintTerrainBasedOnHeight(1, 2.8, 1, tShoreBlend); paintTerrainBasedOnHeight(0, 1, 1, tShore); Engine.SetProgress(40); if (!isNomad()) { log("Creating gaia..."); for (let i = 0; i < 2; ++i) for (let j = 0; j < scaleByMapSize(1, 8); ++j) createObjectGroupsDeprecated( 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); } 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, 25, 3), + new SmoothElevationPainter(ELEVATION_SET, heightHill, 3), paintClass(clHill) ], [ avoidClasses( clPlayerTerritory, 0, clHill, 5, clGaia, 1, clWater, 2) ], scaleByMapSize(1, 5)); log("Creating bumps..."); createBumps(avoidClasses(clPlayer, 8, clWater, 2), scaleByMapSize(20, 150), 2, 8, 4, 1, 4); Engine.SetProgress(50); 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]), paintClass(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); 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]), paintClass(clDirt) ], avoidClasses( clWater, 8, clForest, 0, clHill, 0, clGaia, 1, clPlayerTerritory, 0, clDirt, 16), scaleByMapSize(20, 80)); 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 LayeredPainter([tPlants, tPlants], [1]), paintClass(clDirt) ], avoidClasses( clWater, 8, clForest, 0, clHill, 0, clGaia, 1, clPlayerTerritory, 0, clDirt, 16), scaleByMapSize(20, 80)); 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, 3, clForest, 1, clPlayerTerritory, 0, clGaia, 1, clRock, 10, clHill, 1), 9 * scaleByMapSize(1, 4), 100); log("Creating small stone mines..."); createObjectGroupsDeprecated( 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), 9 * scaleByMapSize(1, 4), 100); log("Creating metal mines..."); createObjectGroupsDeprecated( 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), 9 * scaleByMapSize(1, 4), 100); log("Creating small decorative rocks..."); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(aRockMedium, 1, 3, 0, 1)], true), 0, avoidClasses( clWater, 2, clForest, 1, clGaia, 1, clPlayer, 8, clBaseResource, 4, clHill, 0), 3 * scaleByMapSize(16, 262), 50); 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, 2, clForest, 1, clGaia, 1, clPlayer, 8, clBaseResource, 4, clHill, 0), 3 * scaleByMapSize(8, 131), 50); log("Creating small grass tufts..."); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(aBush1, 1, 2, 0, 1, -Math.PI / 8, Math.PI / 8)]), 0, avoidClasses( clWater, 4, clHill, 2, clPlayer, 8, clGaia, 1, clBaseResource, 4, clDirt, 0), 8 * scaleByMapSize(13, 200)); Engine.SetProgress(70); log("Creating large grass tufts..."); createObjectGroupsDeprecated( 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), 8 * scaleByMapSize(13, 200)); Engine.SetProgress(85); log("Creating bushes..."); createObjectGroupsDeprecated( 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), 8 * scaleByMapSize(13, 200), 50); log("Creating deer..."); createObjectGroupsDeprecated( 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, 50); log("Creating boar..."); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oBoar, 2, 4, 0, 4)], true, clFood), 0, avoidClasses( clWater, 4, clForest, 0, clPlayerTerritory, 0, clGaia, 1, clHill, 1, clFood, 20), 3 * numPlayers, 50); log("Creating tigers..."); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oTiger, 1, 1, 0, 4)], true, clFood), 0, avoidClasses( clWater, 4, clForest, 0, clPlayerTerritory, 0, clGaia, 1, clHill, 1, clFood, 20), 3 * numPlayers, 50); Engine.SetProgress(95); log("Creating berry bush..."); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oBush, 5, 7, 0, 4)], true, clFood), 0, avoidClasses( clWater, 4, clForest, 0, clPlayerTerritory, 0, clGaia, 1, clHill, 1, clFood, 10), randIntInclusive(1, 4) * numPlayers + 2, 50); log("Creating fish..."); createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(oFish, 2, 3, 0, 2)], true, clFood), 0, [avoidClasses(clFood, 15), stayClasses(clWater, 4)], 200, 100); placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clFood, 2)); 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"); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/rmgen/gaia_terrain.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/rmgen/gaia_terrain.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/rmgen/gaia_terrain.js (revision 20904) @@ -1,609 +1,609 @@ /** * @file These functions are often used to create a landscape, for instance shaping mountains, hills, rivers or grass and dirt patches. */ /** * Bumps add slight, diverse elevation differences to otherwise completely level terrain. */ function createBumps(constraint, count, minSize, maxSize, spread, failFraction = 0, elevation = 2) { log("Creating bumps..."); createAreas( new ChainPlacer( minSize || 1, maxSize || Math.floor(scaleByMapSize(4, 6)), spread || Math.floor(scaleByMapSize(2, 5)), failFraction), new SmoothElevationPainter(ELEVATION_MODIFY, elevation, 2), constraint, count || scaleByMapSize(100, 200)); } /** * Hills are elevated, planar, impassable terrain areas. */ function createHills(terrainset, constraint, tileClass, count, minSize, maxSize, spread, failFraction = 0.5, elevation = 18, elevationSmoothing = 2) { log("Creating hills..."); createAreas( new ChainPlacer( minSize || 1, maxSize || Math.floor(scaleByMapSize(4, 6)), spread || Math.floor(scaleByMapSize(16, 40)), failFraction), [ new LayeredPainter(terrainset, [1, elevationSmoothing]), new SmoothElevationPainter(ELEVATION_SET, elevation, elevationSmoothing), paintClass(tileClass) ], constraint, count || scaleByMapSize(1, 4) * getNumPlayers()); } /** * Mountains are impassable smoothened cones. */ function createMountains(terrain, constraint, tileClass, count, maxHeight, minRadius, maxRadius, numCircles) { log("Creating mountains..."); let mapSize = getMapSize(); for (let i = 0; i < (count || scaleByMapSize(1, 4) * getNumPlayers()); ++i) createMountain( maxHeight !== undefined ? maxHeight : Math.floor(scaleByMapSize(30, 50)), minRadius || Math.floor(scaleByMapSize(3, 4)), maxRadius || Math.floor(scaleByMapSize(6, 12)), numCircles || Math.floor(scaleByMapSize(4, 10)), constraint, randIntExclusive(0, mapSize), randIntExclusive(0, mapSize), terrain, tileClass, 14); } /** * Create a mountain using a technique very similar to ChainPlacer. */ function createMountain(maxHeight, minRadius, maxRadius, numCircles, constraints, x, z, terrain, tileClass, fcc = 0, q = []) { let constraint = new AndConstraint(constraints); if (!g_Map.inMapBounds(x, z) || !constraint.allows(x, z)) return; let mapSize = getMapSize(); let queueEmpty = !q.length; let gotRet = []; for (let i = 0; i < mapSize; ++i) { gotRet[i] = []; for (let j = 0; j < mapSize; ++j) gotRet[i][j] = -1; } --mapSize; minRadius = Math.max(1, Math.min(minRadius, maxRadius)); let edges = [[x, z]]; let circles = []; for (let i = 0; i < numCircles; ++i) { let badPoint = false; let [cx, cz] = pickRandom(edges); let radius; if (queueEmpty) radius = randIntInclusive(minRadius, maxRadius); else { radius = q.pop(); queueEmpty = !q.length; } let sx = Math.max(0, cx - radius); let sz = Math.max(0, cz - radius); let lx = Math.min(cx + radius, mapSize); let lz = Math.min(cz + radius, mapSize); let radius2 = Math.square(radius); for (let ix = sx; ix <= lx; ++ix) { for (let iz = sz; iz <= lz; ++iz) { if (Math.euclidDistance2D(ix, iz, cx, cz) > radius2 || !g_Map.inMapBounds(ix, iz)) continue; if (!constraint.allows(ix, iz)) { badPoint = true; break; } let state = gotRet[ix][iz]; if (state == -1) { gotRet[ix][iz] = -2; } else if (state >= 0) { edges.splice(state, 1); gotRet[ix][iz] = -2; for (let k = state; k < edges.length; ++k) --gotRet[edges[k][0]][edges[k][1]]; } } if (badPoint) break; } if (badPoint) continue; circles.push([cx, cz, radius]); for (let ix = sx; ix <= lx; ++ix) for (let iz = sz; iz <= lz; ++iz) { if (gotRet[ix][iz] != -2 || fcc && (x - ix > fcc || ix - x > fcc || z - iz > fcc || iz - z > fcc) || ix > 0 && gotRet[ix-1][iz] == -1 || iz > 0 && gotRet[ix][iz-1] == -1 || ix < mapSize && gotRet[ix+1][iz] == -1 || iz < mapSize && gotRet[ix][iz+1] == -1) continue; edges.push([ix, iz]); gotRet[ix][iz] = edges.length - 1; } } for (let [cx, cz, radius] of circles) { let sx = Math.max(0, cx - radius); let sz = Math.max(0, cz - radius); let lx = Math.min(cx + radius, mapSize); let lz = Math.min(cz + radius, mapSize); let clumpHeight = radius / maxRadius * maxHeight * randFloat(0.8, 1.2); for (let ix = sx; ix <= lx; ++ix) for (let iz = sz; iz <= lz; ++iz) { let distance = Math.euclidDistance2D(ix, iz, cx, cz); let newHeight = randIntInclusive(0, 2) + Math.round(2/3 * clumpHeight * (Math.sin(Math.PI * 2/3 * (3/4 - distance / radius)) + 0.5)); if (distance > radius) continue; if (getHeight(ix, iz) < newHeight) setHeight(ix, iz, newHeight); else if (getHeight(ix, iz) >= newHeight && getHeight(ix, iz) < newHeight + 4) setHeight(ix, iz, newHeight + 4); if (terrain !== undefined) createTerrain(terrain).place(ix, iz); if (tileClass !== undefined) addToClass(ix, iz, tileClass); } } } /** * Generates a volcano mountain. Smoke and lava are optional. * * @param {number} center - Vector2D location on the tilemap. * @param {number} tileClass - Painted onto every tile that is occupied by the volcano. * @param {string} terrainTexture - The texture painted onto the volcano hill. * @param {array} lavaTextures - Three different textures for the interior, from the outside to the inside. * @param {boolean} smoke - Whether to place smoke particles. * @param {number} elevationType - Elevation painter type, ELEVATION_SET = absolute or ELEVATION_MODIFY = relative. */ function createVolcano(position, tileClass, terrainTexture, lavaTextures, smoke, elevationType) { log("Creating volcano"); let baseSize = getMapArea() / scaleByMapSize(1, 8); let coherence = 0.7; let smoothness = 0.05; let failFraction = 100; let steepness = 3; let clLava = createTileClass(); let layers = [ { "clumps": 0.067, "elevation": 15, "tileClass": tileClass }, { "clumps": 0.05, "elevation": 25, "tileClass": createTileClass() }, { "clumps": 0.02, "elevation": 45, "tileClass": createTileClass() }, { "clumps": 0.011, "elevation": 62, "tileClass": createTileClass() }, { "clumps": 0.003, "elevation": 42, "tileClass": clLava, "painter": lavaTextures && new LayeredPainter([terrainTexture, ...lavaTextures], [1, 1, 1]), "steepness": 1 } ]; for (let i = 0; i < layers.length; ++i) createArea( new ClumpPlacer(baseSize * layers[i].clumps, coherence, smoothness, failFraction, position.x, position.y), [ layers[i].painter || new LayeredPainter([terrainTexture, terrainTexture], [3]), new SmoothElevationPainter(elevationType, layers[i].elevation, layers[i].steepness || steepness), paintClass(layers[i].tileClass) ], i == 0 ? null : stayClasses(layers[i - 1].tileClass, 1)); if (smoke) { let num = Math.floor(baseSize * 0.002); createObjectGroup( new SimpleGroup( [new SimpleObject("actor|particle/smoke.xml", num, num, 0, 7)], false, clLava, position.x, position.y), 0, stayClasses(tileClass, 1)); } } /** * Paint the given terrain texture in the given sizes at random places of the map to diversify monotone land texturing. */ function createPatches(sizes, terrain, constraint, count, tileClass, failFraction = 0.5) { for (let size of sizes) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, failFraction), [ new TerrainPainter(terrain), paintClass(tileClass) ], constraint, count); } /** * Same as createPatches, but each patch consists of a set of textures drawn depending to the distance of the patch border. */ function createLayeredPatches(sizes, terrains, terrainWidths, constraint, count, tileClass, failFraction = 0.5) { for (let size of sizes) createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, failFraction), [ new LayeredPainter(terrains, terrainWidths), paintClass(tileClass) ], constraint, count); } /** * Creates a meandering river at the given location and width. * Optionally calls a function on the affected tiles. * Horizontal locations and widths (including fadeDist, meandering) are fractions of the mapsize. * * @property start - A Vector2D in tile coordinates stating where the river starts. * @property end - A Vector2D in tile coordinates stating where the river ends. * @property parallel - Whether the shorelines should be parallel or meander separately. * @property width - Size between the two shorelines. * @property fadeDist - Size of the shoreline. * @property deviation - Fuzz effect on the shoreline if greater than 0. - * @property waterHeight - Ground height of the riverbed. - * @proeprty landHeight - Ground height of the end of the shoreline. + * @property heightRiverbed - Ground height of the riverbed. + * @proeprty heightLand - Ground height of the end of the shoreline. * @property meanderShort - Strength of frequent meanders. * @property meanderLong - Strength of less frequent meanders. * @property [constraint] - If given, ignores any tiles that don't satisfy the given Constraint. * @property [waterFunc] - Optional function called on tiles within the river. * Provides location on the tilegrid, new elevation and * the location on the axis parallel to the river as a fraction of the river length. * @property [landFunc] - Optional function called on land tiles, providing ix, iz, shoreDist1, shoreDist2. * @property [minHeight] - If given, only changes the elevation below this height while still calling the given functions. */ function paintRiver(args) { log("Creating the river"); // Model the river meandering as the sum of two sine curves. let meanderShort = fractionToTiles(args.meanderShort / scaleByMapSize(35, 160)); let meanderLong = fractionToTiles(args.meanderLong / scaleByMapSize(35, 100)); // Unless the river is parallel, each riverside will receive an own random seed and starting angle. let seed1 = randFloat(2, 3); let seed2 = randFloat(2, 3); let startingAngle1 = randFloat(0, 1); let startingAngle2 = randFloat(0, 1); // Computes the deflection of the river at a given point. let riverCurve = (riverFraction, startAngle, seed) => meanderShort * rndRiver(startAngle + fractionToTiles(riverFraction) / 128, seed) + meanderLong * rndRiver(startAngle + fractionToTiles(riverFraction) / 256, seed); // Describe river location in vectors. let riverLength = args.start.distanceTo(args.end); let unitVecRiver = Vector2D.sub(args.start, args.end).normalize(); // Describe river boundaries. let riverMinX = Math.min(args.start.x, args.end.x); let riverMinZ = Math.min(args.start.y, args.end.y); let riverMaxX = Math.max(args.start.x, args.end.x); let riverMaxZ = Math.max(args.start.y, args.end.y); let mapSize = getMapSize(); for (let ix = 0; ix < mapSize; ++ix) for (let iz = 0; iz < mapSize; ++iz) { if (args.constraint && !args.constraint.allows(ix, iz)) continue; let vecPoint = new Vector2D(ix, iz); // Compute the shortest distance to the river. let distanceToRiver = distanceOfPointFromLine(args.start, args.end, vecPoint); // Closest point on the river (i.e the foot of the perpendicular). let river = Vector2D.sub(vecPoint, unitVecRiver.perpendicular().mult(distanceToRiver)); // Only process points that actually are perpendicular with the river. if (river.x < riverMinX || river.x > riverMaxX || river.y < riverMinZ || river.y > riverMaxZ) continue; // Coordinate between 0 and 1 on the axis parallel to the river. let riverFraction = river.distanceTo(args.start) / riverLength; // Amplitude of the river at this location. let riverCurve1 = riverCurve(riverFraction, startingAngle1, seed1); let riverCurve2 = args.parallel ? riverCurve1 : riverCurve(riverFraction, startingAngle2, seed2); // Add noise. let deviation = args.deviation * randFloat(-1, 1); // Compute the distance to the shoreline. let sign = Math.sign(distanceToRiver || 1); let shoreDist1 = sign * riverCurve1 + Math.abs(distanceToRiver) - deviation - args.width / 2; let shoreDist2 = sign * riverCurve2 + Math.abs(distanceToRiver) - deviation + args.width / 2; // Create the elevation for the water and the slopy shoreline and call the user functions. if (shoreDist1 < 0 && shoreDist2 > 0) { - let height = args.waterHeight; + let height = args.heightRiverbed; if (shoreDist1 > -args.fadeDist) - height += (args.landHeight - args.waterHeight) * (1 + shoreDist1 / args.fadeDist); + height += (args.heightLand - args.heightRiverbed) * (1 + shoreDist1 / args.fadeDist); else if (shoreDist2 < args.fadeDist) - height += (args.landHeight - args.waterHeight) * (1 - shoreDist2 / args.fadeDist); + height += (args.heightLand - args.heightRiverbed) * (1 - shoreDist2 / args.fadeDist); if (args.minHeight === undefined || height < args.minHeight) setHeight(ix, iz, height); if (args.waterFunc) args.waterFunc(ix, iz, height, riverFraction); } else if (args.landFunc) args.landFunc(ix, iz, shoreDist1, shoreDist2); } } /** * Helper function to create a meandering river. * It works the same as sin or cos function with the difference that it's period is 1 instead of 2 pi. */ function rndRiver(f, seed) { let rndRw = seed; for (let i = 0; i <= f; ++i) rndRw = 10 * (rndRw % 1); let rndRr = f % 1; let retVal = (Math.floor(f) % 2 ? -1 : 1) * rndRr * (rndRr - 1); let rndRe = Math.floor(rndRw) % 5; if (rndRe == 0) retVal *= 2.3 * (rndRr - 0.5) * (rndRr - 0.5); else if (rndRe == 1) retVal *= 2.6 * (rndRr - 0.3) * (rndRr - 0.7); else if (rndRe == 2) retVal *= 22 * (rndRr - 0.2) * (rndRr - 0.3) * (rndRr - 0.3) * (rndRr - 0.8); else if (rndRe == 3) retVal *= 180 * (rndRr - 0.2) * (rndRr - 0.2) * (rndRr - 0.4) * (rndRr - 0.6) * (rndRr - 0.6) * (rndRr - 0.8); else if (rndRe == 4) retVal *= 2.6 * (rndRr - 0.5) * (rndRr - 0.7); return retVal; } /** * Add small rivers with shallows starting at a central river ending at the map border, if the given Constraint is met. */ -function createTributaryRivers(horizontal, riverCount, riverWidth, waterHeight, heightRange, maxAngle, tributaryRiverTileClass, shallowTileClass, constraint) +function createTributaryRivers(horizontal, riverCount, riverWidth, heightRiverbed, heightRange, maxAngle, tributaryRiverTileClass, shallowTileClass, constraint) { log("Creating tributary rivers..."); let waviness = 0.4; let smoothness = scaleByMapSize(3, 12); let offset = 0.1; let tapering = 0.05; - let shallowHeight = -2; + let heightShallow = -2; let riverAngle = horizontal ? 0 : Math.PI / 2; let mapSize = getMapSize(); let mapCenter = getMapCenter(); let riverConstraint = avoidClasses(tributaryRiverTileClass, 3); if (shallowTileClass) riverConstraint = new AndConstraint([riverConstraint, avoidClasses(shallowTileClass, 2)]); for (let i = 0; i < riverCount; ++i) { // Determining tributary river location let searchCenter = new Vector2D(randFloat(tapering, 1 - tapering), 0.5); let sign = randBool() ? 1 : -1; let distanceVec = new Vector2D(0, sign * tapering); let searchStart = Vector2D.add(searchCenter, distanceVec).mult(mapSize).rotateAround(riverAngle, mapCenter); let searchEnd = Vector2D.sub(searchCenter, distanceVec).mult(mapSize).rotateAround(riverAngle, mapCenter); let start = findLocationInDirectionBasedOnHeight(searchStart, searchEnd, heightRange[0], heightRange[1], 4); if (!start) continue; start.round(); let end = Vector2D.add(mapCenter, new Vector2D(mapSize, 0).rotate(riverAngle - sign * randFloat(maxAngle, 2 * Math.PI - maxAngle))).round(); // Create river if (!createArea( new PathPlacer( start.x, start.y, end.x, end.y, riverWidth, waviness, smoothness, offset, tapering), [ - new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), + new SmoothElevationPainter(ELEVATION_SET, heightRiverbed, 4), paintClass(tributaryRiverTileClass) ], new AndConstraint([constraint, riverConstraint]))) continue; // Create small puddles at the map border to ensure players being separated createArea( new ClumpPlacer(Math.floor(diskArea(riverWidth / 2)), 0.95, 0.6, 10, end.x, end.y), - new SmoothElevationPainter(ELEVATION_SET, waterHeight, 3), + new SmoothElevationPainter(ELEVATION_SET, heightRiverbed, 3), constraint); } // Create shallows if (shallowTileClass) for (let z of [0.25, 0.75]) createPassage({ "start": new Vector2D(0, z).mult(mapSize).rotateAround(riverAngle, mapCenter), "end": new Vector2D(1, z).mult(mapSize).rotateAround(riverAngle, mapCenter), "startWidth": scaleByMapSize(8, 12), "endWidth": scaleByMapSize(8, 12), "smoothWidth": 2, - "startHeight": shallowHeight, - "endHeight": shallowHeight, - "maxHeight": shallowHeight, + "startHeight": heightShallow, + "endHeight": heightShallow, + "maxHeight": heightShallow, "tileClass": shallowTileClass }); } /** * Creates a smooth, passable path between between start and end with the given startWidth and endWidth. * Paints the given tileclass and terrain. * * @property {Vector2D} start - Location of the passage. * @property {Vector2D} end * @property {number} startWidth - Size of the passage (perpendicular to the direction of the passage). * @property {number} endWidth * @property {number} [startHeight] - Fixed height to be used if the height at the location shouldn't be used. * @property {number} [endHeight] * @property {number} [maxHeight] - If given, do not touch any terrain above this height. * @property {number} smoothWidth - Number of tiles at the passage border to apply height interpolation. * @property {number} [tileClass] - Marks the passage with this tile class. * @property {string} [terrain] - Texture to be painted on the passage area. * @property {string} [edgeTerrain] - Texture to be painted on the borders of the passage. */ function createPassage(args) { let bound = x => Math.max(0, Math.min(Math.round(x), getMapSize())); let startHeight = args.startHeight !== undefined ? args.startHeight : getHeight(bound(args.start.x), bound(args.start.y)); let endHeight = args.endHeight !== undefined ? args.endHeight : getHeight(bound(args.end.x), bound(args.end.y)); let passageVec = Vector2D.sub(args.end, args.start); let widthDirection = passageVec.perpendicular().normalize(); let lengthStep = 1 / (2 * passageVec.length()); for (let lengthFraction = 0; lengthFraction <= 1; lengthFraction += lengthStep) { let locationLength = Vector2D.add(args.start, Vector2D.mult(passageVec, lengthFraction)); let halfPassageWidth = (args.startWidth + (args.endWidth - args.startWidth) * lengthFraction) / 2; let passageHeight = startHeight + (endHeight - startHeight) * lengthFraction; for (let stepWidth = -halfPassageWidth; stepWidth <= halfPassageWidth; stepWidth += 0.5) { let location = Vector2D.add(locationLength, Vector2D.mult(widthDirection, stepWidth)).round(); if (!g_Map.inMapBounds(location.x, location.y) || args.maxHeight !== undefined && getHeight(location.x, location.y) > args.maxHeight) continue; let smoothDistance = args.smoothWidth + Math.abs(stepWidth) - halfPassageWidth; g_Map.setHeight( location.x, location.y, smoothDistance > 0 ? (getHeight(location.x, location.y) * smoothDistance + passageHeight / smoothDistance) / (smoothDistance + 1 / smoothDistance) : passageHeight); if (args.tileClass !== undefined) addToClass(location.x, location.y, args.tileClass); if (args.edgeTerrain && smoothDistance > 0) createTerrain(args.edgeTerrain).place(location.x, location.y); else if (args.terrain) createTerrain(args.terrain).place(location.x, location.y); } } } /** * Returns the first location between startPoint and endPoint that lies within the given heightrange. */ function findLocationInDirectionBasedOnHeight(startPoint, endPoint, minHeight, maxHeight, offset = 0) { let stepVec = Vector2D.sub(endPoint, startPoint); let distance = Math.ceil(stepVec.length()); stepVec.normalize(); for (let i = 0; i < distance; ++i) { let pos = Vector2D.add(startPoint, Vector2D.mult(stepVec, i)); let ipos = pos.clone().round(); if (g_Map.validH(ipos.x, ipos.y) && getHeight(ipos.x, ipos.y) >= minHeight && getHeight(ipos.x, ipos.y) <= maxHeight) return pos.add(stepVec.mult(offset)); } return undefined; } Index: ps/trunk/binaries/data/mods/public/maps/random/sahel.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/sahel.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/sahel.js (revision 20904) @@ -1,242 +1,245 @@ Engine.LoadLibrary("rmgen"); 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/flora_tree_baobab"; const oBerryBush = "gaia/flora_bush_berry"; 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/geology_stone_savanna_small"; const oMetalLarge = "gaia/geology_metal_savanna_slabs"; const aBush = "actor|props/flora/bush_medit_sm_dry.xml"; const aRock = "actor|geology/stone_savanna_med.xml"; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightSeaGround = -5; +const heightLand = 1; + +InitMap(heightLand, g_MapSettings.BaseTerrain); var numPlayers = getNumPlayers(); var mapSize = getMapSize(); var clPlayer = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); placePlayerBases({ "PlayerPlacement": playerPlacementCircle(fractionToTiles(0.35)), "PlayerTileClass": clPlayer, "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tCityTiles, "innerTerrain": tCityTiles }, "Chicken": { }, "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); 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)), 1), new TerrainPainter(patches[i]), avoidClasses(clPlayer, 10), scaleByMapSize(5, 20)); 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, 1), new TerrainPainter(patch), avoidClasses(clPlayer, 12), scaleByMapSize(4, 15)); log("Creating water holes..."); createAreas( new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), Math.floor(scaleByMapSize(20, 60)), 1), [ new LayeredPainter([tShore, tWater], [1]), - new SmoothElevationPainter(ELEVATION_SET, -5, 7), + new SmoothElevationPainter(ELEVATION_SET, heightSeaGround, 7), paintClass(clWater) ], avoidClasses(clPlayer, 24), scaleByMapSize(1, 3)); Engine.SetProgress(55); var playerConstraint = new AvoidTileClassConstraint(clPlayer, 30); var minesConstraint = new AvoidTileClassConstraint(clRock, 25); var waterConstraint = new AvoidTileClassConstraint(clWater, 10); log("Creating stone mines..."); for (var i = 0; i < scaleByMapSize(12,30); ++i) { var mX = randIntExclusive(0, mapSize); var mZ = randIntExclusive(0, mapSize); if (playerConstraint.allows(mX, mZ) && minesConstraint.allows(mX, mZ) && waterConstraint.allows(mX, mZ)) { createStoneMineFormation(mX, mZ, oStoneSmall, tDirt4); addToClass(mX, mZ, clRock); } } 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); 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); 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 ); 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 ); 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 ); 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 ); 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 ); 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)); 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); setUnitsAmbientColor(0.57, 0.58, 0.55); setTerrainAmbientColor(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); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/schwarzwald.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/schwarzwald.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/schwarzwald.js (revision 20904) @@ -1,322 +1,325 @@ Engine.LoadLibrary('rmgen'); Engine.LoadLibrary("heightmap"); log('Initializing map...'); -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightLand = 1; +const heightOffsetPath = -0.1; + +InitMap(heightLand, g_MapSettings.BaseTerrain); setSkySet("fog"); setFogFactor(0.35); setFogThickness(0.19); setWaterColor(0.501961, 0.501961, 0.501961); setWaterTint(0.25098, 0.501961, 0.501961); setWaterWaviness(0.5); setWaterType("clap"); setWaterMurkiness(0.75); setPPSaturation(0.37); setPPContrast(0.4); setPPBrightness(0.4); setPPEffect("hdr"); setPPBloom(0.4); var clPlayer = createTileClass(); var clPath = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clMetal = createTileClass(); var clRock = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clOpen = createTileClass(); var templateStoneMine = 'gaia/geology_stonemine_alpine_quarry'; var templateMetalMine = 'gaia/geology_metal_alpine_slabs'; 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'; var aReeds = 'actor|props/flora/reeds_pond_lush_b.xml'; var oFish = "gaia/fauna_fish"; var terrainWood = ['alpine_forrestfloor|gaia/flora_tree_oak', 'alpine_forrestfloor|gaia/flora_tree_pine']; var terrainWoodBorder = ['new_alpine_grass_mossy|gaia/flora_tree_oak', 'alpine_forrestfloor|gaia/flora_tree_pine', 'temp_grass_long|gaia/flora_bush_temperate', 'temp_grass_clovers|gaia/flora_bush_berry', 'temp_grass_clovers_2|gaia/flora_bush_grapes', 'temp_grass_plants|gaia/fauna_deer', 'temp_grass_plants|gaia/fauna_rabbit', 'new_alpine_grass_dirt_a']; var terrainBase = ['temp_plants_bog', 'temp_grass_plants', 'temp_grass_d', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_d', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_d', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_d', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_d', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_d', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_plants', 'temp_grass_plants|gaia/fauna_sheep']; var terrainBaseBorder = ['temp_plants_bog', 'temp_grass_plants', 'temp_grass_d', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_d', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_d', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_d', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_d', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_d', 'temp_grass_plants', 'temp_plants_bog', 'temp_grass_plants', 'temp_grass_plants']; var baseTex = ['temp_road', 'temp_road_overgrown']; var terrainPath = ['temp_road', 'temp_road_overgrown']; var tWater = ['dirt_brown_d']; var tWaterBorder = ['dirt_brown_d']; var mapSize = getMapSize(); var mapArea = getMapArea(); var mapCenter = getMapCenter(); var mapRadius = mapSize/2; var numPlayers = getNumPlayers(); var baseRadius = 15; var minPlayerRadius = Math.min(mapRadius - 1.5 * baseRadius, 5/8 * mapRadius); var maxPlayerRadius = Math.min(mapRadius - baseRadius, 3/4 * mapRadius); var playerPosition = []; var playerAngleStart = randomAngle(); var playerAngleAddAvrg = 2 * Math.PI / numPlayers; var playerAngleMaxOff = playerAngleAddAvrg/4; var resourceRadius = fractionToTiles(1/3); // Setup woods // For large maps there are memory errors with too many trees. A density of 256*192/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) / mapArea, 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 // Set height limits and water level by map size // Set target min and max height depending on map size to make average steepness about the same on all map sizes var heightRange = {'min': MIN_HEIGHT * (g_Map.size + 512) / 8192, 'max': MAX_HEIGHT * (g_Map.size + 512) / 8192, 'avg': (MIN_HEIGHT * (g_Map.size + 512) +MAX_HEIGHT * (g_Map.size + 512))/16384}; // Set average water coverage var averageWaterCoverage = 1/5; // NOTE: Since erosion is not predictable actual water coverage might vary much with the same values -var waterHeight = -MIN_HEIGHT + heightRange.min + averageWaterCoverage * (heightRange.max - heightRange.min); -var waterHeightAdjusted = waterHeight + MIN_HEIGHT; -setWaterHeight(waterHeight); +var heightSeaGround = -MIN_HEIGHT + heightRange.min + averageWaterCoverage * (heightRange.max - heightRange.min); +var heightSeaGroundAdjusted = heightSeaGround + MIN_HEIGHT; +setWaterHeight(heightSeaGround); // Setting a 3x3 Grid as initial heightmap var initialReliefmap = [[heightRange.max, heightRange.max, heightRange.max], [heightRange.max, heightRange.min, heightRange.max], [heightRange.max, heightRange.max, heightRange.max]]; setBaseTerrainDiamondSquare(heightRange.min, heightRange.max, initialReliefmap); for (var i = 0; i < 5; i++) globalSmoothHeightmap(); rescaleHeightmap(heightRange.min, heightRange.max); var heighLimits = [ - heightRange.min + 1/3 * (waterHeightAdjusted - heightRange.min), // 0 Deep water - heightRange.min + 2/3 * (waterHeightAdjusted - heightRange.min), // 1 Medium Water - heightRange.min + (waterHeightAdjusted - heightRange.min), // 2 Shallow water - waterHeightAdjusted + 1/8 * (heightRange.max - waterHeightAdjusted), // 3 Shore - waterHeightAdjusted + 2/8 * (heightRange.max - waterHeightAdjusted), // 4 Low ground - waterHeightAdjusted + 3/8 * (heightRange.max - waterHeightAdjusted), // 5 Player and path height - waterHeightAdjusted + 4/8 * (heightRange.max - waterHeightAdjusted), // 6 High ground - waterHeightAdjusted + 5/8 * (heightRange.max - waterHeightAdjusted), // 7 Lower forest border - waterHeightAdjusted + 6/8 * (heightRange.max - waterHeightAdjusted), // 8 Forest - waterHeightAdjusted + 7/8 * (heightRange.max - waterHeightAdjusted), // 9 Upper forest border - waterHeightAdjusted + (heightRange.max - waterHeightAdjusted)]; // 10 Hilltop + heightRange.min + 1/3 * (heightSeaGroundAdjusted - heightRange.min), // 0 Deep water + heightRange.min + 2/3 * (heightSeaGroundAdjusted - heightRange.min), // 1 Medium Water + heightRange.min + (heightSeaGroundAdjusted - heightRange.min), // 2 Shallow water + heightSeaGroundAdjusted + 1/8 * (heightRange.max - heightSeaGroundAdjusted), // 3 Shore + heightSeaGroundAdjusted + 2/8 * (heightRange.max - heightSeaGroundAdjusted), // 4 Low ground + heightSeaGroundAdjusted + 3/8 * (heightRange.max - heightSeaGroundAdjusted), // 5 Player and path height + heightSeaGroundAdjusted + 4/8 * (heightRange.max - heightSeaGroundAdjusted), // 6 High ground + heightSeaGroundAdjusted + 5/8 * (heightRange.max - heightSeaGroundAdjusted), // 7 Lower forest border + heightSeaGroundAdjusted + 6/8 * (heightRange.max - heightSeaGroundAdjusted), // 8 Forest + heightSeaGroundAdjusted + 7/8 * (heightRange.max - heightSeaGroundAdjusted), // 9 Upper forest border + heightSeaGroundAdjusted + (heightRange.max - heightSeaGroundAdjusted)]; // 10 Hilltop var startLocations = getStartLocationsByHeightmap({'min': heighLimits[4], 'max': heighLimits[5]}); var playerHeight = (heighLimits[4] + heighLimits[5]) / 2; for (let i = 0; i < numPlayers; ++i) { playerPosition[i] = Vector2D.add( mapCenter, new Vector2D(randFloat(minPlayerRadius, maxPlayerRadius), 0).rotate( -((playerAngleStart + i * playerAngleAddAvrg + randFloat(0, playerAngleMaxOff)) % (2 * Math.PI)))).round(); rectangularSmoothToHeight(playerPosition[i], 20, 20, playerHeight, 0.8); } placePlayerBases({ "PlayerPlacement": [sortAllPlayers(), playerPosition], "BaseResourceClass": clBaseResource, "Walls": false, // player class painted below "CityPatch": { "radius": 0.8 * baseRadius, "smoothness": 1/8, "painters": [ new TerrainPainter([baseTex], [baseRadius/4, baseRadius/4]), paintClass(clPlayer) ] }, // No chicken "Berries": { "template": "gaia/flora_bush_berry", "minCount": 2, "maxCount": 2, "minDist": 10, "maxDist": 10 }, "Mines": { "types": [ { "template": templateMetalMine }, { "template": templateStoneMine } ], "distance": 15, "minAngle": Math.PI / 2, "maxAngle": Math.PI }, "Trees": { "template": "gaia/flora_tree_oak_large", "count": 2 } }); log("Creating mines..."); for (let [minHeight, maxHeight] of [[heighLimits[3], (heighLimits[4] + heighLimits[3]) / 2], [(heighLimits[5] + heighLimits[6]) / 2, heighLimits[7]]]) for (let [template, tileClass] of [[templateStoneMine, clRock], [templateMetalMine, clMetal]]) createObjectGroups( new SimpleGroup([new SimpleObject(template, 1, 1, 0, 4)], true, tileClass), 0, [ new HeightConstraint(minHeight, maxHeight), avoidClasses(clForest, 4, clPlayer, 20, clMetal, 40, clRock, 40) ], scaleByMapSize(2, 8), 100, false); Engine.SetProgress(50); log("Painting textures..."); var betweenShallowAndShore = (heighLimits[3] + heighLimits[2]) / 2; createArea( new HeightPlacer(Elevation_IncludeMin_IncludeMax, heighLimits[2], betweenShallowAndShore), new LayeredPainter([terrainBase, terrainBaseBorder], [5])); paintTileClassBasedOnHeight(heighLimits[2], betweenShallowAndShore, 1, clOpen); createArea( new HeightPlacer(Elevation_IncludeMin_IncludeMax, heightRange.min, heighLimits[2]), new LayeredPainter([tWaterBorder, tWater], [2])); paintTileClassBasedOnHeight(heightRange.min, heighLimits[2], 1, clWater); Engine.SetProgress(60); 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.75, baseRadius / 2, pathBlending), [ new TerrainPainter(terrainPath), - new SmoothElevationPainter(ELEVATION_MODIFY, -0.1, 1), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetPath, 1), paintClass(clPath) ], avoidClasses(clPath, 0, clOpen, 0 ,clWater, 4, clBaseResource, 4)); } Engine.SetProgress(75); log("Creating decoration..."); 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)] ], [ scaleByMapSize(16, 262), scaleByMapSize(8, 131), scaleByMapSize(13, 200), scaleByMapSize(13, 200), scaleByMapSize(13, 200) ], avoidClasses(clForest, 1, clPlayer, 0, clPath, 3, clWater, 3)); Engine.SetProgress(80); log("Growing fish..."); createFood( [ [new SimpleObject(oFish, 2, 3, 0, 2)] ], [ 100 * numPlayers ], [avoidClasses(clFood, 5), stayClasses(clWater, 4)], clFood); Engine.SetProgress(85); log("Planting reeds..."); var types = [aReeds]; for (let type of types) createObjectGroupsDeprecated( new SimpleGroup([new SimpleObject(type, 1, 1, 0, 0)], true), 0, borderClasses(clWater, 0, 6), scaleByMapSize(1, 2) * 1000, 1000); Engine.SetProgress(90); log("Planting trees..."); for (var x = 0; x < mapSize; x++) for (var z = 0;z < mapSize;z++) { if (!g_Map.validT(x, z)) continue; // The 0.5 is a correction for the entities placed on the center of tiles var radius = Math.euclidDistance2D(x + 0.5, z + 0.5, mapCenter.x, mapCenter.y); var minDistToSL = mapSize; for (var i=0; i < numPlayers; i++) minDistToSL = Math.min(minDistToSL, Math.euclidDistance2D(x, z, playerPosition[i].x, playerPosition[i].x)); // Woods tile based var tDensFactSL = Math.max(Math.min((minDistToSL - baseRadius) / baseRadius, 1), 0); var tDensFactRad = Math.abs((resourceRadius - radius) / resourceRadius); var tDensActual = (maxTreeDensity * tDensFactSL * tDensFactRad)*0.75; if (!randBool(tDensActual)) continue; let border = tDensActual < randFloat(0, bushChance * maxTreeDensity); createArea( new RectPlacer(x, z, x, z), [ new TerrainPainter(border ? terrainWoodBorder : terrainWood), paintClass(clForest) ], border ? avoidClasses(clPath, 1, clOpen, 2, clWater, 3, clMetal, 4, clRock, 4) : avoidClasses(clPath, 2, clOpen, 3, clWater, 4, clMetal, 4, clRock, 4)); } placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clFood, 2, clMetal, 4, clRock, 4)); Engine.SetProgress(100); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/stronghold.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/stronghold.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/stronghold.js (revision 20904) @@ -1,257 +1,259 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmgen2"); Engine.LoadLibrary("rmbiome"); setSelectedBiome(); -InitMap(g_MapSettings.BaseHeight, g_Terrains.mainTerrain); +const heightLand = 30; + +InitMap(heightLand, g_Terrains.mainTerrain); initTileClasses(); createArea( new MapBoundsPlacer(), paintClass(g_TileClasses.land)); Engine.SetProgress(20); addBases("stronghold", fractionToTiles(randFloat(0.2, 0.35)), fractionToTiles(randFloat(0.05, 0.1)), randomAngle()); Engine.SetProgress(30); addElements(shuffleArray([ { "func": addBluffs, - "baseHeight": getMapBaseHeight(), + "baseHeight": heightLand, "avoid": [ g_TileClasses.bluff, 20, g_TileClasses.hill, 5, g_TileClasses.mountain, 20, g_TileClasses.plateau, 20, g_TileClasses.player, 30, g_TileClasses.valley, 5, g_TileClasses.water, 7 ], "sizes": ["big", "huge"], "mixes": g_AllMixes, "amounts": g_AllAmounts }, { "func": addHills, "avoid": [ g_TileClasses.bluff, 5, g_TileClasses.hill, 15, g_TileClasses.mountain, 2, g_TileClasses.plateau, 2, g_TileClasses.player, 20, g_TileClasses.valley, 2, g_TileClasses.water, 2 ], "sizes": ["normal", "big"], "mixes": g_AllMixes, "amounts": g_AllAmounts }, { "func": addMountains, "avoid": [ g_TileClasses.bluff, 20, g_TileClasses.mountain, 25, g_TileClasses.plateau, 20, g_TileClasses.player, 20, g_TileClasses.valley, 10, g_TileClasses.water, 15 ], "sizes": ["big", "huge"], "mixes": g_AllMixes, "amounts": g_AllAmounts }, { "func": addPlateaus, "avoid": [ g_TileClasses.bluff, 20, g_TileClasses.mountain, 25, g_TileClasses.plateau, 25, g_TileClasses.player, 40, g_TileClasses.valley, 10, g_TileClasses.water, 15 ], "sizes": ["big", "huge"], "mixes": g_AllMixes, "amounts": g_AllAmounts }, { "func": addValleys, - "baseHeight": getMapBaseHeight(), + "baseHeight": heightLand, "avoid": [ g_TileClasses.bluff, 5, g_TileClasses.hill, 5, g_TileClasses.mountain, 25, g_TileClasses.plateau, 10, g_TileClasses.player, 40, g_TileClasses.valley, 15, g_TileClasses.water, 10 ], "sizes": ["normal", "big"], "mixes": g_AllMixes, "amounts": g_AllAmounts } ])); Engine.SetProgress(60); addElements([ { "func": addLayeredPatches, "avoid": [ g_TileClasses.bluff, 2, g_TileClasses.dirt, 5, g_TileClasses.forest, 2, g_TileClasses.mountain, 2, g_TileClasses.plateau, 2, g_TileClasses.player, 12, g_TileClasses.valley, 5, g_TileClasses.water, 3 ], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["normal"] }, { "func": addDecoration, "avoid": [ g_TileClasses.bluff, 2, g_TileClasses.forest, 2, g_TileClasses.mountain, 2, g_TileClasses.plateau, 2, g_TileClasses.player, 12, g_TileClasses.water, 3 ], "sizes": ["normal"], "mixes": ["normal"], "amounts": ["normal"] } ]); Engine.SetProgress(70); addElements(shuffleArray([ { "func": addMetal, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.bluff, 5, g_TileClasses.forest, 3, g_TileClasses.mountain, 2, g_TileClasses.plateau, 2, g_TileClasses.player, 30, g_TileClasses.rock, 10, g_TileClasses.metal, 20, g_TileClasses.water, 3 ], "sizes": ["normal"], "mixes": ["same"], "amounts": g_AllAmounts }, { "func": addStone, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.bluff, 5, g_TileClasses.forest, 3, g_TileClasses.mountain, 2, g_TileClasses.plateau, 2, g_TileClasses.player, 30, g_TileClasses.rock, 20, g_TileClasses.metal, 10, g_TileClasses.water, 3 ], "sizes": ["normal"], "mixes": ["same"], "amounts": g_AllAmounts }, { "func": addForests, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.bluff, 5, g_TileClasses.forest, 18, g_TileClasses.metal, 3, g_TileClasses.mountain, 5, g_TileClasses.plateau, 5, g_TileClasses.player, 20, g_TileClasses.rock, 3, g_TileClasses.water, 2 ], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": ["few", "normal", "many", "tons"] } ])); Engine.SetProgress(80); addElements(shuffleArray([ { "func": addBerries, "avoid": [ g_TileClasses.berries, 30, g_TileClasses.bluff, 5, g_TileClasses.forest, 5, g_TileClasses.metal, 10, g_TileClasses.mountain, 2, g_TileClasses.plateau, 2, g_TileClasses.player, 20, g_TileClasses.rock, 10, g_TileClasses.spine, 2, g_TileClasses.water, 3 ], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": g_AllAmounts }, { "func": addAnimals, "avoid": [ g_TileClasses.animals, 20, g_TileClasses.bluff, 5, g_TileClasses.forest, 2, g_TileClasses.metal, 2, g_TileClasses.mountain, 1, g_TileClasses.plateau, 2, g_TileClasses.player, 20, g_TileClasses.rock, 2, g_TileClasses.spine, 2, g_TileClasses.water, 3 ], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": g_AllAmounts }, { "func": addStragglerTrees, "avoid": [ g_TileClasses.berries, 5, g_TileClasses.bluff, 5, g_TileClasses.forest, 7, g_TileClasses.metal, 2, g_TileClasses.mountain, 1, g_TileClasses.plateau, 2, g_TileClasses.player, 12, g_TileClasses.rock, 2, g_TileClasses.spine, 2, g_TileClasses.water, 5 ], "sizes": g_AllSizes, "mixes": g_AllMixes, "amounts": g_AllAmounts } ])); Engine.SetProgress(90); placePlayersNomad( g_TileClasses.player, avoidClasses( g_TileClasses.bluff, 4, g_TileClasses.plateau, 4, g_TileClasses.forest, 1, g_TileClasses.metal, 4, g_TileClasses.rock, 4, g_TileClasses.mountain, 4, g_TileClasses.animals, 2)); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/syria.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/syria.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/syria.js (revision 20904) @@ -1,274 +1,278 @@ Engine.LoadLibrary("rmgen"); 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/flora_tree_tamarix"; const oPalm = "gaia/flora_tree_date_palm"; const oPine = "gaia/flora_tree_aleppo_pine"; const oBush = "gaia/flora_bush_grapes"; const oCamel = "gaia/fauna_camel"; const oGazelle = "gaia/fauna_gazelle"; const oLion = "gaia/fauna_lion"; const oStoneLarge = "gaia/geology_stonemine_desert_quarry"; const oStoneSmall = "gaia/geology_stone_desert_small"; const oMetalLarge = "gaia/geology_metal_desert_slabs"; 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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightLand = 1; +const heightHill = 22; +const heightOffsetBump = 2; + +InitMap(heightLand, g_MapSettings.BaseTerrain); const mapCenter = getMapCenter(); const numPlayers = getNumPlayers(); var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clGrass = createTileClass(); var [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); for (let i = 0; i < numPlayers; ++i) { log("Marking player territory larger than the city patch..."); if (!isNomad()) createArea( new ClumpPlacer(diskArea(defaultPlayerBaseRadius()), 0.9, 0.5, 10, playerPosition[i].x, playerPosition[i].y), paintClass(clPlayer)); log("Creating big grass patches surrounding the city patches..."); createArea( new ChainPlacer( 2, Math.floor(scaleByMapSize(5, 12)), Math.floor(scaleByMapSize(25, 60)) / (isNomad() ? 2 : 1), 1, playerPosition[i].x, playerPosition[i].y, 0, [Math.floor(scaleByMapSize(16, 30))]), [ new LayeredPainter([tGrassSands, tGrass], [3]), paintClass(clGrass) ]); } Engine.SetProgress(10); placePlayerBases({ "PlayerPlacement": [playerIDs, playerPosition], // PlayerTileClass marked above "BaseResourceClass": clBaseResource, "CityPatch": { "outerTerrain": tRoadWild, "innerTerrain": tRoad, "radius": 10, "width": 3 }, "Chicken": { }, "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); log("Creating bumps..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1), - new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), avoidClasses(clPlayer, 13), scaleByMapSize(300, 800)); 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, 22, 2), + new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), paintClass(clHill) ], avoidClasses(clPlayer, 3, clGrass, 1, clHill, 10), scaleByMapSize(1, 3) * numPlayers * 3); Engine.SetProgress(25); 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]), paintClass(clForest) ], avoidClasses(clPlayer, 1, clGrass, 1, clForest, 10, clHill, 1), num); Engine.SetProgress(40); 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); 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); log("Creating stone mines..."); var group = new SimpleGroup([new SimpleObject(oStoneSmall, 0, 2, 0, 4), new SimpleObject(oStoneLarge, 1, 1, 0,4), 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 ); log("Creating small stone quarries..."); 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 ); 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 ); 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 ); 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); 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 ); 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 ); 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); ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/the_unknown/unknown_common.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/the_unknown/unknown_common.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/the_unknown/unknown_common.js (revision 20904) @@ -1,1062 +1,1066 @@ /** * @file This library is used to generate different map variations on the map Unknown, Unknown Land and Unknown Nomad. */ /** * True if all players should be connected via land and false if river or islands can split some if not all the players. */ var g_AllowNaval; 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/special_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]; -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightSeaGround = -5; +const heightLand = 3; +const heightCliff = 3.12; +const heightHill = 18; +const heightOffsetBump = 2; + +InitMap(heightSeaGround, g_MapSettings.BaseTerrain); const numPlayers = getNumPlayers(); const mapSize = getMapSize(); const mapCenter = getMapCenter(); const mapBounds = getMapBounds(); var clPlayer = createTileClass(); var clPlayerTerritory = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); var clFood = createTileClass(); var clPeninsulaSteam = createTileClass(); var clBaseResource = createTileClass(); var clLand = createTileClass(); var clShallow = createTileClass(); -var landHeight = 3; -var cliffHeight = 3.12; -var landElevationPainter = new SmoothElevationPainter(ELEVATION_SET, landHeight, 4); +var landElevationPainter = new SmoothElevationPainter(ELEVATION_SET, heightLand, 4); var unknownMapFunctions = { "land": [ "Continent", "CentralSea", "CentralRiver", "EdgeSeas", "Gulf", "Lakes", "Passes", "Lowlands", "Mainland" ], "naval": [ "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() { let funcs = unknownMapFunctions.land; if (g_AllowNaval) funcs = funcs.concat(unknownMapFunctions.naval); global["unknown" + pickRandom(funcs)](); 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"); } log("Creating islands..."); let islandSize = diskArea(scaleByMapSize(17, 29)); for (let i = 0; i < numPlayers; ++i) createArea( new ClumpPlacer(islandSize, 0.8, 0.1, 10, islandPosition[i].x, islandPosition[i].y), landElevationPainter); let type = isNomad() ? randIntInclusive(1, 2) : randIntInclusive(1, 3); if (type == 1) { log("Creating archipelago..."); createAreas( new ClumpPlacer(Math.floor(islandSize * randFloat(0.8, 1.2)), 0.8, 0.1, 10), [ landElevationPainter, paintClass(clLand) ], null, scaleByMapSize(2, 5) * randIntInclusive(8, 14)); log("Creating shore jaggedness with small puddles..."); createAreas( new ClumpPlacer(scaleByMapSize(15, 80), 0.2, 0.1, 1), [ - new SmoothElevationPainter(ELEVATION_SET, landHeight, 4), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 4), paintClass(clLand) ], borderClasses(clLand, 6, 3), scaleByMapSize(12, 130) * 2, 150); } else if (type == 2) { log("Creating islands..."); createAreas( new ClumpPlacer(Math.floor(islandSize * randFloat(0.6, 1.4)), 0.8, 0.1, randFloat(0.0, 0.2)), [ landElevationPainter, paintClass(clLand) ], avoidClasses(clLand, 3, clPlayerTerritory, 3), scaleByMapSize(6, 10) * randIntInclusive(8, 14)); log("Creating small islands..."); createAreas( new ClumpPlacer(Math.floor(islandSize * randFloat(0.3, 0.7)), 0.8, 0.1, 0.07), [ - new SmoothElevationPainter(ELEVATION_SET, landHeight, 6), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 6), paintClass(clLand) ], avoidClasses(clLand, 3, clPlayerTerritory, 3), scaleByMapSize(2, 6) * randIntInclusive(6, 15), 25); } else if (type == 3) { log("Creating tight islands..."); createAreas( new ClumpPlacer(Math.floor(islandSize * randFloat(0.8, 1.2)), 0.8, 0.1, 10), [ landElevationPainter, paintClass(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()) { 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)), 1, playerPosition[i].x, playerPosition[i].y, 0, [Math.floor(scaleByMapSize(23, 50))]), [ landElevationPainter, paintClass(clLand) ]); } log("Creating continent..."); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.38)), 0.9, 0.09, 10, mapCenter.x, mapCenter.y), [ landElevationPainter, paintClass(clLand) ]); if (randBool(1/3)) { 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, 10, peninsulaPosition1.x, peninsulaPosition1.y), [ landElevationPainter, paintClass(clLand) ]); 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, 10, peninsulaPosition2.x, peninsulaPosition2.y), paintClass(clPeninsulaSteam)); } createShoreJaggedness(waterHeight, clLand, 7); } /** * Creates a huge central river, possibly connecting the riversides with a narrow piece of land. */ function unknownCentralSea() { let waterHeight = -3; let horizontal = randBool(); let [riverStart, riverEnd] = centralRiverCoordinates(horizontal); paintRiver({ "parallel": false, "start": riverStart, "end": riverEnd, "width": fractionToTiles(scaleByMapSize(0.27, 0.42) + randFloat(0, 0.08)), "fadeDist": scaleByMapSize(3, 12), "deviation": 0, - "waterHeight": waterHeight, - "landHeight": landHeight, + "heightRiverbed": waterHeight, + "heightLand": heightLand, "meanderShort": 20, "meanderLong": 0, "waterFunc": (ix, iz, height, riverFraction) => { if (height < 0) addToClass(ix, iz, clWater); }, "landFunc": (ix, iz, shoreDist1, shoreDist2) => { setHeight(ix, iz, 3.1); addToClass(ix, iz, clLand); } }); if (!isNomad()) { [playerIDs, playerPosition] = playerPlacementRiver(horizontal ? Math.PI / 2 : 0, fractionToTiles(0.6)); markPlayerArea("small"); } if (!g_AllowNaval || randBool()) { log("Creating isthmus (i.e. connecting the two riversides with a big land passage)..."); let [isthmusStart, isthmusEnd] = centralRiverCoordinates(!horizontal); createArea( new PathPlacer( isthmusStart.x, isthmusStart.y, isthmusEnd.x, isthmusEnd.y, scaleByMapSize(randIntInclusive(16, 24), randIntInclusive(100, 140)), 0.5, 3 * scaleByMapSize(1, 4), 0.1, 0.01), [ landElevationPainter, paintClass(clLand), unPaintClass(clWater) ]); } createExtensionsOrIslands(); // Don't createShoreJaggedness since it doesn't fit artistically here } /** * Creates a very small central river. */ function unknownCentralRiver() { let waterHeight = -4; - let shallowHeight = -2; + let heightShallow = -2; createArea( new MapBoundsPlacer(), - new ElevationPainter(landHeight)); + new ElevationPainter(heightLand)); let horizontal = randBool(); let riverAngle = horizontal ? 0 : Math.PI / 2; if (!isNomad()) { [playerIDs, playerPosition] = playerPlacementRiver(horizontal ? Math.PI / 2 : 0, fractionToTiles(0.5)); markPlayerArea("large"); } log("Creating the main river..."); let [coord1, coord2] = centralRiverCoordinates(horizontal); createArea( new PathPlacer(coord1.x, coord1.y, coord2.x, coord2.y, scaleByMapSize(14, 24), 0.5, scaleByMapSize(3, 12), 0.1, 0.01), new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), avoidClasses(clPlayerTerritory, 4)); log("Creating small water spots at the map border to ensure separation of players..."); for (let coord of [coord1, coord2]) createArea( new ClumpPlacer(Math.floor(diskArea(scaleByMapSize(5, 10))), 0.95, 0.6, 10, coord.x, coord.y), new SmoothElevationPainter(ELEVATION_SET, waterHeight, 2), avoidClasses(clPlayerTerritory, 8)); if (!g_AllowNaval || randBool()) { log("Creating the shallows of the main river..."); for (let i = 0; i <= randIntInclusive(1, scaleByMapSize(4, 8)); ++i) { let location = randFloat(0.15, 0.85); createPassage({ "start": new Vector2D(location, 0).mult(mapSize).rotateAround(riverAngle, mapCenter), "end": new Vector2D(location, 1).mult(mapSize).rotateAround(riverAngle, mapCenter), "startWidth": scaleByMapSize(8, 12), "endWidth": scaleByMapSize(8, 12), "smoothWidth": 2, - "startHeight": shallowHeight, - "endHeight": shallowHeight, - "maxHeight": shallowHeight, + "startHeight": heightShallow, + "endHeight": heightShallow, + "maxHeight": heightShallow, "tileClass": clShallow }); } } if (randBool(2/3)) createTributaryRivers( horizontal, 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(landHeight)); + 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) { log("Creating lake..."); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.17)), 0.7, 0.1, 10, mapCenter.x, mapCenter.y), [ new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), paintClass(clWater) ]); createShoreJaggedness(waterHeight, clWater, 3); } // Don't do this on nomad because the imbalances on the different islands are too drastic if (!isNomad() && (!lake || randBool(1/3))) { 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.x, mapCenter.y, river.x, river.y, scaleByMapSize(14, 24), 0.4, 3 * scaleByMapSize(1, 3), 0.2, 0.05), [ new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), paintClass(clWater) ], avoidClasses(clPlayer, 5)); createArea( new ClumpPlacer(Math.floor(diskArea(scaleByMapSize(10, 50)) / 5), 0.95, 0.6, 10, river.x, river.y), [ new SmoothElevationPainter(ELEVATION_SET, waterHeight, 0), paintClass(clWater) ], avoidClasses(clPlayer, 5)); } log("Creating lake..."); createArea( new ClumpPlacer(Math.square(mapSize) * 0.005, 0.7, 0.1, 10, mapCenter.x, mapCenter.y), [ new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), paintClass(clWater) ]); } if (!isNomad && lake && randBool()) { log("Creating small central island..."); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.05)), 0.7, 0.1, 10, mapCenter.x, mapCenter.y), [ landElevationPainter, paintClass(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(landHeight)); + new ElevationPainter(heightLand)); let horizontal = randBool(); if (!isNomad()) { [playerIDs, playerPosition] = playerPlacementLine(horizontal, 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]])) { let angle = side + (horizontal ? 0 : Math.PI / 2); paintRiver({ "parallel": true, "start": new Vector2D(mapBounds.left, mapBounds.top).rotateAround(angle, mapCenter), "end": new Vector2D(mapBounds.left, mapBounds.bottom).rotateAround(angle, mapCenter), "width": scaleByMapSize(80, randFloat(270, 320)), "fadeDist": scaleByMapSize(2, 8), "deviation": 0, - "waterHeight": waterHeight, - "landHeight": landHeight, + "heightRiverbed": waterHeight, + "heightLand": heightLand, "meanderShort": 20, "meanderLong": 0 }); } createExtensionsOrIslands(); - paintTileClassBasedOnHeight(0, cliffHeight, 1, clLand); + 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(landHeight)); + new ElevationPainter(heightLand)); let startAngle = randomAngle(); if (!isNomad()) { 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, 10, position.x, position.y), [ new SmoothElevationPainter(ELEVATION_SET, waterHeight, 4), paintClass(clWater) ], avoidClasses(clPlayerTerritory, defaultPlayerBaseRadius())); } } /** * Mainland style with some small random lakes. */ function unknownLakes() { let waterHeight = -5; createArea( new MapBoundsPlacer(), - new ElevationPainter(landHeight)); + new ElevationPainter(heightLand)); if (!isNomad()) { [playerIDs, playerPosition] = playerPlacementCircle(fractionToTiles(0.35)); markPlayerArea("large"); } log("Creating lakes..."); createAreas( new ClumpPlacer(scaleByMapSize(160, 700), 0.2, 0.1, 1), [ new SmoothElevationPainter(ELEVATION_SET, waterHeight, 5), paintClass(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 mountainHeight = 24; + let heightMountain = 24; let waterHeight = -4; createArea( new MapBoundsPlacer(), - new ElevationPainter(landHeight)); + new ElevationPainter(heightLand)); let playerAngle; let startAngle; if (!isNomad()) { [playerIDs, playerPosition, playerAngle, startAngle] = playerPlacementCircle(fractionToTiles(0.35)); markPlayerArea("small"); } else startAngle = randomAngle(); for (let mountain of distributePointsOnCircle(numPlayers, startAngle + Math.PI / numPlayers, fractionToTiles(0.5), mapCenter)[0]) { log("Creating a mountain range between neighboring players..."); createArea( new PathPlacer(mapCenter.x, mapCenter.y, mountain.x, mountain.y, 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, mountainHeight, 1), + new SmoothElevationPainter(ELEVATION_SET, heightMountain, 1), paintClass(clWater) ], avoidClasses(clPlayer, 5)); log("Creating small mountain at the map border between the players to ensure separation of players..."); createArea( new ClumpPlacer(Math.floor(diskArea(scaleByMapSize(10, 50)) / 5), 0.95, 0.6, 10, mountain.x, mountain.y), - new SmoothElevationPainter(ELEVATION_SET, mountainHeight, 0), + new SmoothElevationPainter(ELEVATION_SET, heightMountain, 0), avoidClasses(clPlayer, 5)); } let passes = distributePointsOnCircle(numPlayers * 2, startAngle, fractionToTiles(0.35), mapCenter)[0]; for (let i = 0; i < numPlayers; ++i) { log("Create passages between neighboring players..."); createArea( new PathPlacer( passes[2 * i].x, passes[2 * i].y, passes[2 * ((i + 1) % numPlayers)].x, passes[2 * ((i + 1) % numPlayers)].y, scaleByMapSize(14, 24), 0.4, 3 * scaleByMapSize(1, 3), 0.2, 0.05), - new SmoothElevationPainter(ELEVATION_SET, landHeight, 2)); + new SmoothElevationPainter(ELEVATION_SET, heightLand, 2)); } if (randBool(2/5)) { log("Create central lake..."); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.1)), 0.7, 0.1, 10, mapCenter.x, mapCenter.y), [ new SmoothElevationPainter(ELEVATION_SET, waterHeight, 3), paintClass(clWater) ]); } else { log("Fill area between the paths..."); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.05)), 0.7, 0.1, 10, mapCenter.x, mapCenter.y), [ - new SmoothElevationPainter(ELEVATION_SET, mountainHeight, 4), + new SmoothElevationPainter(ELEVATION_SET, heightMountain, 4), paintClass(clWater) ]); } } /** * Land enclosed by a hill that leaves small areas for civic centers and large central place. */ function unknownLowlands() { - let mountainHeight = 30; + let heightMountain = 30; log("Creating mountain that is going to separate players..."); createArea( new MapBoundsPlacer(), - new ElevationPainter(mountainHeight)); + new ElevationPainter(heightMountain)); let playerAngle; let startAngle; if (!isNomad()) { [playerIDs, playerPosition, playerAngle, startAngle] = playerPlacementCircle(fractionToTiles(0.35)); markPlayerArea("small"); } else startAngle = randomAngle(); 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; for (let valley of distributePointsOnCircle(valleys, startAngle, fractionToTiles(0.35), mapCenter)[0]) { log("Creating player valley..."); createArea( new ClumpPlacer(diskArea(scaleByMapSize(18, 32)), 0.65, 0.1, 10, valley.x, valley.y), [ - new SmoothElevationPainter(ELEVATION_SET, landHeight, 2), + new SmoothElevationPainter(ELEVATION_SET, heightLand, 2), paintClass(clLand) ]); log("Creating passes from player areas to the center..."); createArea( new PathPlacer(mapCenter.x, mapCenter.y, valley.x, valley.y, scaleByMapSize(14, 24), 0.4, 3 * scaleByMapSize(1, 3), 0.2, 0.05), [ landElevationPainter, paintClass(clWater) ]); } log("Creating the big central area..."); createArea( new ClumpPlacer(diskArea(fractionToTiles(0.18)), 0.7, 0.1, 10, mapCenter.x, mapCenter.y), [ landElevationPainter, paintClass(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(horizontal) { return [ new Vector2D(mapBounds.left + 1, mapCenter.y), new Vector2D(mapBounds.right - 1, mapCenter.y) ].map(v => v.rotateAround(horizontal ? 0 : Math.PI / 2, mapCenter)); } function createShoreJaggedness(waterHeight, borderClass, shoreDist, inwards = true) { log("Creating shore jaggedness..."); for (let i = 0; i < 2; ++i) if (i || inwards) createAreas( new ChainPlacer(2, Math.floor(scaleByMapSize(4, 6)), 15, 1), [ - new SmoothElevationPainter(ELEVATION_SET, i ? landHeight : waterHeight, 4), + new SmoothElevationPainter(ELEVATION_SET, i ? heightLand : waterHeight, 4), i ? paintClass(clLand) : unPaintClass(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) { log("Creating islands..."); createAreas( new ClumpPlacer(Math.square(randIntInclusive(scaleByMapSize(8, 15), scaleByMapSize(15, 23))), 0.8, 0.1, randFloat(0, 0.2)), [ landElevationPainter, paintClass(clLand) ], avoidClasses(clLand, 3, clPlayer, 3), scaleByMapSize(2, 5) * randIntInclusive(8, 14)); } else if (rnd == 2) { log("Creating extentions..."); createAreas( new ChainPlacer(Math.floor(scaleByMapSize(4, 7)), Math.floor(scaleByMapSize(7, 10)), Math.floor(scaleByMapSize(16, 40)), 0.07), [ landElevationPainter, paintClass(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, 10, playerPosition[i].x, playerPosition[i].y), paintClass(clPlayerTerritory)); } } function paintUnknownMapBasedOnHeight() { - paintTerrainBasedOnHeight(cliffHeight, 40, 1, tCliff); - paintTerrainBasedOnHeight(3, cliffHeight, 1, tMainTerrain); + paintTerrainBasedOnHeight(heightCliff, 40, 1, tCliff); + paintTerrainBasedOnHeight(3, heightCliff, 1, tMainTerrain); paintTerrainBasedOnHeight(1, 3, 1, tShore); paintTerrainBasedOnHeight(-8, 1, 2, tWater); - unPaintTileClassBasedOnHeight(0, cliffHeight, 1, clWater); + unPaintTileClassBasedOnHeight(0, heightCliff, 1, clWater); unPaintTileClassBasedOnHeight(-6, 0, 1, clLand); paintTileClassBasedOnHeight(-6, 0, 1, clWater); - paintTileClassBasedOnHeight(0, cliffHeight, 1, clLand); - paintTileClassBasedOnHeight(cliffHeight, 40, 1, clHill); + paintTileClassBasedOnHeight(0, heightCliff, 1, clLand); + paintTileClassBasedOnHeight(heightCliff, 40, 1, clHill); } /** * Place resources and decoratives after the player territory was marked. */ function createUnknownObjects() { log("Creating bumps..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1), - new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), [avoidClasses(clWater, 2, clPlayer, 10), stayClasses(clLand, 3)], randIntInclusive(0, scaleByMapSize(1, 2) * 200)); log("Creating hills..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 150), 0.2, 0.1, 1), [ new LayeredPainter([tCliff, tHill], [2]), - new SmoothElevationPainter(ELEVATION_SET, 18, 2), + new SmoothElevationPainter(ELEVATION_SET, heightHill, 2), paintClass(clHill) ], [avoidClasses(clPlayer, 15, clHill, randIntInclusive(6, 18)), stayClasses(clLand, 0)], randIntInclusive(0, scaleByMapSize(4, 8))*randIntInclusive(1, scaleByMapSize(4, 9)) ); Engine.SetProgress(50); 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, 1), [ new LayeredPainter(type, [2]), paintClass(clForest) ], [avoidClasses(clPlayer, 20, clForest, randIntInclusive(5, 15), clHill, 2), stayClasses(clLand, 4)], num); Engine.SetProgress(50); log("Creating dirt patches..."); let patchCount = (currentBiome() == "savanna" ? 3 : 1) * scaleByMapSize(15, 45); 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]), paintClass(clDirt) ], [avoidClasses(clForest, 0, clHill, 2, clDirt, 5, clPlayer, 7), stayClasses(clLand, 4)], patchCount); 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); 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(clForest, 1, clPlayer, 10, clRock, 10, clHill, 2), stayClasses(clLand, 3)], randIntInclusive(scaleByMapSize(2, 9), scaleByMapSize(9, 40)), 100); 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); 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); 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); 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); 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); 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); 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); 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); 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() == "tropic" ? 8 : 1; 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); 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); 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); 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": [ paintClass(clPlayer) ] }, "Chicken": { }, "Berries": { "template": oFruitBush }, "Mines": { "types": [ { "template": oMetalLarge }, { "template": oStoneLarge } ] }, "Treasures": { "types": [ { "template": oWoodTreasure, "count": g_StartingTreasures ? 14 : 0 } ] }, "Trees": { "template": oTree1 }, "Decoratives": { "template": aGrassShort } }); } Index: ps/trunk/binaries/data/mods/public/maps/random/volcanic_lands.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/volcanic_lands.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/volcanic_lands.json (revision 20904) @@ -1,11 +1,10 @@ { "settings" : { "Name" : "Volcanic Lands", "Script" : "volcanic_lands.js", "Description" : "A charred dead land where players start around a smoking volcano.", "BaseTerrain" : "ocean_rock_a", - "BaseHeight" : 1, "CircularMap" : true, "Preview" : "volcanic_lands.png" } -} \ No newline at end of file +} Index: ps/trunk/binaries/data/mods/public/maps/random/wild_lake.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/wild_lake.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/wild_lake.js (revision 20904) @@ -1,634 +1,636 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmbiome"); Engine.LoadLibrary("heightmap"); -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +const heightLand = 0; + +InitMap(heightLand, g_MapSettings.BaseTerrain); /** * 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] } ]; var mercenaryCampGuards = { "temperate": [ { "Template" : "structures/merc_camp_egyptian" }, { "Template" : "units/mace_infantry_javelinist_b", "Count" : 4 }, { "Template" : "units/mace_cavalry_spearman_e", "Count" : 3 }, { "Template" : "units/mace_infantry_archer_a", "Count" : 4 }, { "Template" : "units/mace_champion_infantry_a", "Count" : 3 } ], "snowy": [ { "Template" : "structures/ptol_mercenary_camp" }, { "Template" : "units/brit_infantry_javelinist_b", "Count" : 4 }, { "Template" : "units/brit_cavalry_swordsman_e", "Count" : 3 }, { "Template" : "units/brit_infantry_slinger_a", "Count" : 4 }, { "Template" : "units/brit_champion_infantry", "Count" : 3 } ], "desert": [ { "Template" : "structures/ptol_mercenary_camp" }, { "Template" : "units/pers_infantry_javelinist_b", "Count" : 4 }, { "Template" : "units/pers_cavalry_swordsman_e", "Count" : 3 }, { "Template" : "units/pers_infantry_archer_a", "Count" : 4 }, { "Template" : "units/pers_champion_infantry", "Count" : 3 } ], "alpine": [ { "Template" : "structures/ptol_mercenary_camp" }, { "Template" : "units/rome_infantry_swordsman_b", "Count" : 4 }, { "Template" : "units/rome_cavalry_spearman_e", "Count" : 3 }, { "Template" : "units/rome_infantry_javelinist_a", "Count" : 4 }, { "Template" : "units/rome_champion_infantry", "Count" : 3 } ], "mediterranean": [ { "Template" : "structures/merc_camp_egyptian" }, { "Template" : "units/iber_infantry_javelinist_b", "Count" : 4 }, { "Template" : "units/iber_cavalry_spearman_e", "Count" : 3 }, { "Template" : "units/iber_infantry_slinger_a", "Count" : 4 }, { "Template" : "units/iber_champion_infantry", "Count" : 3 } ], "savanna": [ { "Template" : "structures/merc_camp_egyptian" }, { "Template" : "units/sele_infantry_javelinist_b", "Count" : 4 }, { "Template" : "units/sele_cavalry_spearman_merc_e", "Count" : 3 }, { "Template" : "units/sele_infantry_spearman_a", "Count" : 4 }, { "Template" : "units/sele_champion_infantry_swordsman", "Count" : 3 } ], "tropic": [ { "Template" : "structures/merc_camp_egyptian" }, { "Template" : "units/ptol_infantry_javelinist_b", "Count" : 4 }, { "Template" : "units/ptol_cavalry_archer_e", "Count" : 3 }, { "Template" : "units/ptol_infantry_slinger_a", "Count" : 4 }, { "Template" : "units/ptol_champion_infantry_pikeman", "Count" : 3 } ], "autumn": [ { "Template" : "structures/ptol_mercenary_camp" }, { "Template" : "units/gaul_infantry_javelinist_b", "Count" : 4 }, { "Template" : "units/gaul_cavalry_swordsman_e", "Count" : 3 }, { "Template" : "units/gaul_infantry_slinger_a", "Count" : 4 }, { "Template" : "units/gaul_champion_infantry", "Count" : 3 } ] }; /** * Resource spots and other points of interest */ // Mines function placeMine(point, centerEntity, decorativeActors = [ g_Decoratives.grass, g_Decoratives.grassShort, g_Decoratives.rockLarge, g_Decoratives.rockMedium, g_Decoratives.bushMedium, g_Decoratives.bushSmall ] ) { placeObject(point.x, point.y, centerEntity, 0, randomAngle()); let quantity = randIntInclusive(11, 23); 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); placeObject(point.x + dist * Math.cos(angle), point.y + dist * Math.sin(angle), pickRandom(decorativeActors), 0, randomAngle()); } } // Groves, only Wood let groveActors = [g_Decoratives.grass, g_Decoratives.rockMedium, g_Decoratives.bushMedium]; let clGrove = 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) ) { placeObject(point.x, point.y, pickRandom(["structures/gaul_outpost", "gaia/flora_tree_oak_new"]), 0, 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 x = point.x + dist * Math.cos(angle); let y = point.y + dist * Math.sin(angle); placeObject(x, y, pickRandom(objectList), 0, randomAngle()); if (groveTileClass) createArea(new ClumpPlacer(5, 1, 1, 1, Math.floor(x), Math.floor(y)), [new TerrainPainter(groveTerrainTexture), paintClass(groveTileClass)]); else createArea(new ClumpPlacer(5, 1, 1, 1, Math.floor(x), Math.floor(y)), [new TerrainPainter(groveTerrainTexture)]); } } var farmEntities = { "temperate": { "building": "structures/mace_farmstead", "animal": "gaia/fauna_pig" }, "snowy": { "building": "structures/brit_farmstead", "animal": "gaia/fauna_sheep" }, "desert": { "building": "structures/pers_farmstead", "animal": "gaia/fauna_camel" }, "alpine": { "building": "structures/rome_farmstead", "animal": "gaia/fauna_sheep" }, "mediterranean": { "building": "structures/iber_farmstead", "animal": "gaia/fauna_pig" }, "savanna": { "building": "structures/sele_farmstead", "animal": "gaia/fauna_horse" }, "tropic": { "building": "structures/ptol_farmstead", "animal": "gaia/fauna_camel" }, "autumn": { "building": "structures/gaul_farmstead", "animal": "gaia/fauna_horse" } }; g_WallStyles.other = { "overlap": 0, "fence": readyWallElement("other/fence_long", "gaia"), "fence_short": readyWallElement("other/fence_short", "gaia"), "bench": { "angle": Math.PI / 2, "length": 1.5, "indent": 0, "bend": 0, "templateName": "other/bench" }, "foodBin": { "angle": Math.PI / 2, "length": 1.5, "indent": 0, "bend": 0, "templateName": "gaia/special_treasure_food_bin" }, "animal": { "angle": 0, "length": 0, "indent": 0.75, "bend": 0, "templateName": farmEntities[currentBiome()].animal }, "farmstead": { "angle": Math.PI, "length": 0, "indent": -3, "bend": 0, "templateName": farmEntities[currentBiome()].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(point, centerEntity = "actor|props/special/eyecandy/campfire.xml", otherEntities = ["gaia/special_treasure_metal", "gaia/special_treasure_standing_stone", "units/brit_infantry_slinger_b", "units/brit_infantry_javelinist_b", "units/gaul_infantry_slinger_b", "units/gaul_infantry_javelinist_b", "units/gaul_champion_fanatic", "actor|props/special/common/waypoint_flag.xml", "actor|props/special/eyecandy/barrel_a.xml", "actor|props/special/eyecandy/basket_celt_a.xml", "actor|props/special/eyecandy/crate_a.xml", "actor|props/special/eyecandy/dummy_a.xml", "actor|props/special/eyecandy/handcart_1.xml", "actor|props/special/eyecandy/handcart_1_broken.xml", "actor|props/special/eyecandy/sack_1.xml", "actor|props/special/eyecandy/sack_1_rough.xml" ] ) { placeObject(point.x, point.y, centerEntity, 0, 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); placeObject(point.x + dist * Math.cos(angle), point.y + dist * Math.sin(angle), pickRandom(otherEntities), 0, randomAngle()); } } function placeStartLocationResources( point, foodEntities = [g_Gaia.fruitBush, g_Gaia.chicken], 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({ "x": point.x + averageDistToCC * Math.cos(angle), "y": point.y + averageDistToCC * Math.sin(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 x = point.x + dist * Math.cos(angle); let y = point.y + dist * Math.sin(angle); placeObject(x, y, pickRandom(objectList), 0, randomAngle()); createArea(new ClumpPlacer(5, 1, 1, 1, Math.floor(x), Math.floor(y)), [new TerrainPainter(groveTerrainTexture), paintClass(clGrove)]); currentAngle += dAngle; } // Metal dAngle = 4/9 * Math.PI; angle = currentAngle + randFloat(dAngle / 4, 3 * dAngle / 4); placeMine({ "x": point.x + averageDistToCC * Math.cos(angle), "y": point.y + averageDistToCC * Math.sin(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(); placeObject(point.x + dist * Math.cos(angle), point.y + dist * Math.sin(angle), pickRandom(foodEntities), 0, randomAngle()); currentAngle += dAngle; } } /** * Base terrain shape generation and settings */ // Height range by map size let heightScale = (g_Map.size + 256) / 768 / 4; 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 waterHeight = -MIN_HEIGHT + heightRange.min + averageWaterCoverage * (heightRange.max - heightRange.min); // Water height in environment and the engine -let waterHeightAdjusted = waterHeight + MIN_HEIGHT; // Water height as terrain height -setWaterHeight(waterHeight); +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); // Apply simple erosion for (let i = 0; i < 5; ++i) splashErodeMap(0.1); globalSmoothHeightmap(); // Final rescale rescaleHeightmap(heightRange.min, heightRange.max); Engine.SetProgress(25); /** * Prepare terrain texture placement */ let heighLimits = [ - heightRange.min + 3/4 * (waterHeightAdjusted - heightRange.min), // 0 Deep water - waterHeightAdjusted, // 1 Shallow water - waterHeightAdjusted + 2/8 * (heightRange.max - waterHeightAdjusted), // 2 Shore - waterHeightAdjusted + 3/8 * (heightRange.max - waterHeightAdjusted), // 3 Low ground - waterHeightAdjusted + 4/8 * (heightRange.max - waterHeightAdjusted), // 4 Player and path height - waterHeightAdjusted + 6/8 * (heightRange.max - waterHeightAdjusted), // 5 High ground - waterHeightAdjusted + 7/8 * (heightRange.max - waterHeightAdjusted), // 6 Lower forest border + 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 log("Chosing starting locations..."); let [playerIDs, startLocations] = sortPlayersByLocation(getStartLocationsByHeightmap(playerHeightRange, 1000, 30)); Engine.SetProgress(30); /** * Smooth Start Locations before height region calculation */ let playerBaseRadius = 35; if (g_Map.size < 256) playerBaseRadius = 25; for (let p = 0; p < playerIDs.length; ++p) rectangularSmoothToHeight(startLocations[p], playerBaseRadius, playerBaseRadius, playerHeight, 0.7); /** * 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(); /** * Add paths (If any) */ let clPath = createTileClass(); /** * Divide tiles in areas by height and avoid paths */ let areas = []; for (let h = 0; h < heighLimits.length; ++h) areas.push([]); for (let x = 0; x < tchm.length; ++x) for (let y = 0; y < tchm[0].length; ++y) { if (g_Map.tileClasses[clPath].inclusionCount[x][y] > 0) // Avoid paths continue; 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({ "x": x, "y": y }); break; } else minHeight = heighLimits[h]; } } /** * Get max slope of each area */ let slopeMap = getSlopeMap(); let minSlope = []; let maxSlope = []; for (let h = 0; h < heighLimits.length; ++h) { minSlope[h] = Infinity; maxSlope[h] = 0; for (let t = 0; t < areas[h].length; ++t) { let x = areas[h][t].x; let y = areas[h][t].y; let slope = slopeMap[x][y]; if (slope > maxSlope[h]) maxSlope[h] = slope; if (slope < minSlope[h]) minSlope[h] = slope; } } /** * Paint areas by height and slope */ for (let h = 0; h < heighLimits.length; ++h) for (let t = 0; t < areas[h].length; ++t) { let x = areas[h][t].x; let y = areas[h][t].y; let actor; let texture = pickRandom(wildLakeBiome[h].texture); if (slopeMap[x][y] < 0.5 * (minSlope[h] + maxSlope[h])) { 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.texture[x][y] = g_Map.getTextureID(texture); if (actor) placeObject(randFloat(x, x + 1), randFloat(y, y + 1), actor, 0, randomAngle()); } Engine.SetProgress(80); log("Placing resources..."); let avoidPoints = clone(startLocations); for (let i = 0; i < avoidPoints.length; ++i) avoidPoints[i].dist = 30; let resourceSpots = getPointsByHeight(resourceSpotHeightRange, avoidPoints, clPath); Engine.SetProgress(55); log("Placing players..."); if (isNomad()) placePlayersNomad(createTileClass(), new HeightConstraint(playerHeightRange.min, playerHeightRange.max)); else for (let p = 0; p < playerIDs.length; ++p) { let point = startLocations[p]; placeCivDefaultStartingEntities(point, playerIDs[p], g_Map.size > 192); placeStartLocationResources(point); } let mercenaryCamps = isNomad() ? 0 : Math.ceil(g_Map.size / 256); log("Maximum number of mercenary camps: " + mercenaryCamps); for (let i = 0; i < resourceSpots.length; ++i) { let choice = i % 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]); rectangularSmoothToHeight(resourceSpots[i], 5, 5, g_Map.height[resourceSpots[i].x][resourceSpots[i].y] - 10, 0.5); } if (choice == 4) { if (mercenaryCamps) { placeStartingEntities(resourceSpots[i], 0, mercenaryCampGuards[currentBiome()]); rectangularSmoothToHeight(resourceSpots[i], 15, 15, g_Map.height[resourceSpots[i].x][resourceSpots[i].y], 0.5); --mercenaryCamps; } else { placeCustomFortress(resourceSpots[i].x, resourceSpots[i].y, pickRandom(fences), "other", 0, randomAngle()); rectangularSmoothToHeight(resourceSpots[i], 10, 10, g_Map.height[resourceSpots[i].x][resourceSpots[i].y], 0.5); } } } ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/wall_demo.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/wall_demo.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/wall_demo.json (revision 20904) @@ -1,15 +1,14 @@ { "settings" : { "Name" : "Wall Demo", "GameType" : "endless", "Script" : "wall_demo.js", "Description" : "A demonstration of wall placement methods/code in random maps. Giant map size is recommended!", "BaseTerrain" : ["grass1"], - "BaseHeight" : 0, "Keywords": ["demo"], "CircularMap" : false, "TriggerScripts" : [ "random/wall_demo_triggers.js" ] } } Index: ps/trunk/binaries/data/mods/public/maps/random/wall_demo.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/wall_demo.js (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/wall_demo.js (revision 20904) @@ -1,330 +1,330 @@ Engine.LoadLibrary("rmgen"); -InitMap(g_MapSettings.BaseHeight, g_MapSettings.BaseTerrain); +InitMap(0, g_MapSettings.BaseTerrain); /** * Demonstration code for wall placement. * * Some notes/reminders: * - All angles (orientation) are in radians. * - When looking at the map, with the x-axis being horizontal and the y-axis vertical: * -- The origin point (0,0) of the map is in the bottom-left corner, * -- A wall orientated at 0 has its "outside" facing right and its "inside" facing left. * -- A wall orientated at Pi is reversed (obviously). * -- A wall orientated at Pi/2 has its "outside" facing down and its "inside" facing up. * - As a general rule, walls are drawn in a anti-clockwise direction. * * Some general notes concerning the arguments: * * - The first two arguments for most placement functions are x/y co-ordinates needed to position the wall. These are received via separate arguments, like in placeObject(), and their exact meaning differs between methods, but should be mostly self explanatory. The exception to this is placeLinearWall(), where the first four arguments are co-ordinates. However, whether two argument or four, the initial x/y co-ordinates are required parameters. * * - For some functions, the next argument is radius, indicating how far from a central point the wall should be drawn. The functions that use this are marked as doing so below. * * - The next argument is usually an array containing wall element type strings. (See the block comment for getWallElement() for a list of accepted type strings.) The exception to this is placeFortress(), which accepts a string here instead, identifying which of the predefined fortresses designs you wish to use. (See the example provided below for details.) * * Most functions will ask that you do not include "bending" wall elements in your array ("cornerIn", "cornerOut", "turn_{x}") and will complain if you attempt to do so. The ones that do this are clearly marked below. * * The array will generally look like: * ["start", "medium", "tower", "gate", "tower", "medium", "end"] * * Remember that walls are drawn in an anti-clockwise direction. Thus, when looking at a wall element in-game, with the "outside" facing up, then the *next* wall element will be drawn to the left of *this* element. * * This argument is optional, and each function has a different default value. * * - The next argument is a string denoting the style of the wall. These are derived from the names of wallsets defined in 0ad: for example "athen_wallset_stone" becomes "athen_stone", and "rome_wallset_seige" becomes "rome_seige". (A full list can be found stored as the keys of the global constant g_WallStyles.) This argument is optional, and if not set, the civ's basic stone wallset will be used. * * - The next argument is the player-id of the player that is to own the wall. This argument is optional, and defaults to 0 (gaia). * * - The next argument is an angle defining the angle of orientation of the wall. The exact use differs slightly between functions, but hopefully the comments on the examples below should help. Also see the notes above about wall orientation. This argument is optional, and defaults to 0. * * - Any remaining arguments differ from function to function, but are all optional. Please read the comments below, and also the block comment of the function in wall_builder.js for further details. * * And have fun! */ var mapSize = getMapSize(); /** * General wall placement setup */ const distToMapBorder = 5; const distToOtherWalls = 10; var buildableMapSize = mapSize - 2 * distToMapBorder; var actualX = distToMapBorder; var actualY = distToMapBorder; var playerID = 0; const wallStyleList = Object.keys(g_WallStyles); /** * Custom wall placement (element based). * * Like most wall placement functions, we have to supply an x/y position. * In this case, the x/y position marks the start of the wall. * * For this function, orientation indicates the angle at which the first * wall element should be drawn. (The direction that the outside of the * first wall element faces towards.) * * This function permits bending wall elements. */ for (let styleIndex in wallStyleList) { let x = actualX + styleIndex * buildableMapSize / wallStyleList.length; let y = actualY; let wall = ['start', 'long', 'tower', 'tower', 'tower', 'medium', 'outpost', 'medium', 'cornerOut', 'medium', 'cornerIn', 'medium', 'house', 'end', 'entryTower', 'start', 'short', 'barracks', 'gate', 'tower', 'medium', 'fort', 'medium', 'end']; let style = wallStyleList[styleIndex]; let orientation = Math.PI / 16 * Math.sin(styleIndex * Math.PI / 4); placeWall(x, y, wall, style, playerID, orientation); } // Prep for next set of walls actualX = distToMapBorder; actualY += 80 + distToOtherWalls; /** * Default fortress placement (chosen by fortress type string) * * The x/y position in this case marks the center point of the fortress. * To make it clearer, we add an obilisk as a visual marker. * * This is the only wall placement function that does not take an array * of elements as an argument. Instead, we provide a "type" that identifies * a predefined design to draw. The list of possible types are: "tiny", * "small", "medium", "normal", "large", "veryLarge", and "giant". * * For this function, orientation is the direction in which the main gate * is facing. */ var fortressRadius = 15; // The space the fortresses take in average. Just for design of this map. Not passed to the function. for (let styleIndex in wallStyleList) { let x = actualX + fortressRadius + styleIndex * buildableMapSize / wallStyleList.length; let y = actualY + fortressRadius; let type = "tiny"; let style = wallStyleList[styleIndex]; let orientation = styleIndex * Math.PI / 32; placeObject(x, y, "other/obelisk", playerID, orientation); placeFortress(x, y, type, style, playerID, orientation); } // Prep for next set of walls actualX = distToMapBorder; actualY += 2 * fortressRadius + distToOtherWalls; /** * 'Generic' fortress placement (iberian wall circuit code) * * The function used here is unusual in that the owner and style arguments * are swapped. It is also unusual in that we do not supply an orientation. * * The x/y position in this case marks the center point of the fortress. * To make it clearer, we add an obilisk as a visual marker. * * We also supply a radius value to dictate how wide the circuit of walls should be. */ var radius = Math.min((mapSize - actualY - distToOtherWalls) / 3, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); for (let styleIndex in wallStyleList) { let centerX = actualX + radius + styleIndex * buildableMapSize / wallStyleList.length; let centerY = actualY + radius; let style = wallStyleList[styleIndex]; placeObject(centerX, centerY, 'other/obelisk', playerID, 0); placeGenericFortress(centerX, centerY, radius, playerID, style); } // Prep for next set of walls actualX = distToMapBorder; actualY += 2 * radius + distToOtherWalls; /** * Circular wall placement * * It is possible with this function to draw complete circles, or arcs. * Each side of the wall consists of the contents of the provided wall * array, with the code calculating the number and angle of turns and * sides automatically based on the calculated length of each side and * the given radius. * * This function does not permit the use of bending wall elements. * * In this case, the x/y co-ordinates are the center point around which * to draw the walls. To make this clearer, we add an obelisk as a visual * marker. * * We also provide a radius to define the distance between the center * point and the walls. * * For this function, orientation is the direction that the opening of an * arc faces. If the wall is to be a complete circle, then this is used as * the orientation of the first wall piece. */ radius = Math.min((mapSize - actualY - distToOtherWalls) / 3, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); for (let styleIndex in wallStyleList) { let centerX = actualX + radius + styleIndex * buildableMapSize / wallStyleList.length; let centerY = actualY + radius; let wallPart = ['tower', 'medium', 'house']; let style = wallStyleList[styleIndex]; let orientation = styleIndex * Math.PI / 16; // maxAngle is how far the wall should circumscribe the center. // If equal to Pi * 2, then the wall will be a full circle. // If less than Pi * 2, then the wall will be an arc. let maxAngle = Math.PI / 2 * (styleIndex % 3 + 2); placeObject(centerX, centerY, 'other/obelisk', playerID, orientation); placeCircularWall(centerX, centerY, radius, wallPart, style, playerID, orientation, maxAngle); } // Prep for next set of walls. actualX = distToMapBorder; actualY += 2 * radius + distToOtherWalls; /** * Regular Polygonal wall placement * * This function draws a regular polygonal wall around a given point. All * the sides follow the same pattern, and the (automatically calculated) * angles at the corners are identical. We define how many corners we want. * * This function does not permit the use of bending wall elements. * * In this case, the x/y co-ordinates are the center point around which * to draw the walls. To make this clearer, we add an obelisk as a visual * marker. * * We also provide a radius to define the distance between the center * point and the walls. * * After the usual array of wall elements to use, and before the style * argument, we provide the name of a single wall element to use as a * corner piece. * * In this function, orientation is the direction the first wall has its * outward side facing or, if the `skipFirstWall` argument is true, the * opening in the wall. */ radius = Math.min((mapSize - actualY - distToOtherWalls) / 2, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); for (let styleIndex in wallStyleList) { let centerX = actualX + radius + styleIndex * buildableMapSize / wallStyleList.length; let centerY = actualY + radius; let wallParts = ['medium', 'tower']; // Function default: ['long', 'tower'] // Which wall element to use for the corners of the polygon let cornerWallElement = 'tower'; let style = wallStyleList[styleIndex]; let orientation = styleIndex * Math.PI / 16; // How many corners the polygon should have: let numCorners = styleIndex % 6 + 3; // If true, the first side will not be drawn, leaving the wall open. let skipFirstWall = true; placeObject(centerX, centerY, 'other/obelisk', playerID, orientation); placePolygonalWall(centerX, centerY, radius, wallParts, cornerWallElement, style, playerID, orientation, numCorners, skipFirstWall); } // Prep for next set of walls. actualX = distToMapBorder; actualY += 2 * radius + distToOtherWalls; /** * Irregular Polygonal wall placement * * This function draws an irregular polygonal wall around a given point. * Each side of the wall is different, each element used selected at * pesudo-random from an assortment. The angles at the corners also differ. * We can control this randomness by changing the irregularity argument. * * This function does not permit the use of bending wall elements. * * In this case, the x/y co-ordinates are the center point around which * to draw the walls. To make this clearer, we add an obelisk as a visual * marker. * * We also provide a radius to define the distance between the center * point and the walls. * * The usual array of wall elements is left out here, instead we provide * the name of a single wall element to use as a corner piece. * * In this function, orientation is the direction the first wall has its * outward side facing or, if the `skipFirstWall` argument is true, the * opening in the wall. * * The very last argument is the collection of wallparts used to build * the wall. It is not defined in this example (so as to use the defaults) * as it is not easy to comprehend. */ radius = Math.min((mapSize - actualY - distToOtherWalls) / 2, (buildableMapSize / wallStyleList.length - distToOtherWalls) / 2); // The radius of wall polygons for (let styleIndex in wallStyleList) { let centerX = actualX + radius + styleIndex * buildableMapSize / wallStyleList.length; let centerY = actualY + radius; // Which wall element type will be used for the corners of the polygon. let cornerWallElement = 'tower'; let style = wallStyleList[styleIndex]; let orientation = styleIndex * Math.PI / 16; // How many corners the polygon will have let numCorners = styleIndex % 6 + 3; // Irregularity of the polygon. let irregularity = 0.5; // If true, the first side will not be drawn, leaving the wall open. let skipFirstWall = true; placeObject(centerX, centerY, 'other/obelisk', playerID, orientation); placeIrregularPolygonalWall(centerX, centerY, radius, cornerWallElement, style, playerID, orientation, numCorners, irregularity, skipFirstWall); } // Prep for next set of walls. actualX = distToMapBorder; actualY += 2 * radius + distToOtherWalls; /** * Linear wall placement * * This function draws a straight wall between two given points. * * This function does not permit the use of bending wall elements. * * This function has no orientation parameter, the wall pieces are angled * automatically. Remember: each piece is placed to the left of the * previous piece. Thus, if the start point is at the right-hand side of * the screen and the end point is at the left-hand side, the "outside" * of the walls is facing the top of the screen. */ // Two vars, just for this map; firstly how long the longest wall will be. var maxWallLength = (mapSize - actualY - distToMapBorder - distToOtherWalls); // And secondly, how many walls of the same style will be placed. var numWallsPerStyle = Math.floor(buildableMapSize / distToOtherWalls / wallStyleList.length); for (let styleIndex in wallStyleList) for (let wallIndex = 0; wallIndex < numWallsPerStyle; ++wallIndex) { // Start point. let startX = actualX + (styleIndex * numWallsPerStyle + wallIndex) * buildableMapSize / wallStyleList.length / numWallsPerStyle; let startY = actualY; // End point. let endX = startX; let endY = actualY + (wallIndex + 1) * maxWallLength / numWallsPerStyle; let wallPart = ['tower', 'medium']; let style = wallStyleList[styleIndex]; placeLinearWall(startX, startY, endX, endY, wallPart, style, playerID); } ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/wild_lake.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/wild_lake.json (revision 20903) +++ ps/trunk/binaries/data/mods/public/maps/random/wild_lake.json (revision 20904) @@ -1,13 +1,12 @@ { "settings" : { "Name" : "Wild Lake", "Script" : "wild_lake.js", "Preview" : "wild_lake.png", "Description" : "A lake surrounded by hills.", "CircularMap" : true, "BaseTerrain" : "whiteness", "Keywords": [], - "BaseHeight" : 0, "SupportedBiomes": true } }