Index: ps/trunk/binaries/data/mods/public/gui/credits/texts/art.json =================================================================== --- ps/trunk/binaries/data/mods/public/gui/credits/texts/art.json +++ ps/trunk/binaries/data/mods/public/gui/credits/texts/art.json @@ -48,6 +48,7 @@ {"nick": "howlingflute"}, {"nick": "mmayfield45", "name": "Michael Mayfield"}, {"nick": "niektb", "name": "Niek ten Brinke"}, + {"nick": "smiley", "name": "M. L."}, {"nick": "Spahbod", "name": "Omid Davoodi"}, {"nick": "wraitii", "name": "Lancelot de Ferrière le Vayer"} ] Index: ps/trunk/binaries/data/mods/public/maps/random/aethiopia.js =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/aethiopia.js +++ ps/trunk/binaries/data/mods/public/maps/random/aethiopia.js @@ -0,0 +1,362 @@ +Engine.LoadLibrary("rmgen"); +Engine.LoadLibrary("rmgen-common"); + +const tMainDirt = ["savanna_dirt_b", "savanna_dirt_rocks_a"]; +const tForestFloor = "savanna_forestfloor_b"; +const tSecondaryDirt = "savanna_dirt_a"; +const tDirt = "savanna_dirt_rocks_c"; +const tRoad = "savanna_tile_a"; +const tRoadWild = "desert_city_tile"; +const tRiverBank = "savanna_riparian_wet"; +const tLush = "desert_grass_a"; +const tSLush = "desert_grass_a_sand"; +const tFarmland = "desert_farmland"; + +const oBaobab = "gaia/flora_tree_baobab"; +const oAcacia = "gaia/flora_tree_acacia"; +const oDatePalm = "gaia/flora_tree_date_palm"; +const oSDatePalm = "gaia/flora_tree_cretan_date_palm_short"; +const oBush = "gaia/flora_bush_grapes"; +const oGazelle = "gaia/fauna_gazelle"; +const oGiraffe = "gaia/fauna_giraffe"; +const oLion = "gaia/fauna_lion"; +const oFish = "gaia/fauna_fish"; +const oHawk = "gaia/fauna_hawk"; +const oStoneSmall = "gaia/geology_stone_savanna_small"; +const oMetalLarge = "gaia/geology_metal_savanna_slabs"; + +const oHouse = "structures/kush_house"; +const oFarmstead = "structures/kush_farmstead"; +const oField = "structures/kush_field"; +const oPyramid = "structures/kush_pyramid_small"; +const oPyramidLarge = "structures/kush_pyramid_large"; +const oKushSoldiers = "units/kush_infantry_javelinist_merc_e"; + +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 aReeds = "actor|props/flora/reeds_pond_lush_a.xml"; + +const pForestP = [tForestFloor + TERRAIN_SEPARATOR + oAcacia, tForestFloor]; + +const heightSeaGround = -4; +const heightReedsDepth = -2.5; +const heightShore = 1; +const heightLand = 2; +const heightDunes = 11; +const heightOffsetBump = 1.4; + +const g_Map = new RandomMap(heightLand, tMainDirt); + +const numPlayers = getNumPlayers(); +const mapCenter = g_Map.getCenter(); +const mapBounds = g_Map.getBounds(); + +var clPlayer = g_Map.createTileClass(); +var clKushiteVillages = g_Map.createTileClass(); +var clRiver = g_Map.createTileClass(); +var clShore = g_Map.createTileClass(); +var clDunes = g_Map.createTileClass(); +var clForest = g_Map.createTileClass(); +var clRock = g_Map.createTileClass(); +var clMetal = g_Map.createTileClass(); +var clFood = g_Map.createTileClass(); +var clBaseResource = g_Map.createTileClass(); + +var kushVillageBuildings = { + "houseA": { "template": oHouse, "offset": new Vector2D(5, 5) }, + "houseB": { "template": oHouse, "offset": new Vector2D(5, 0) }, + "houseC": { "template": oHouse, "offset": new Vector2D(5, -5) }, + "farmstead": { "template": oFarmstead, "offset": new Vector2D(-5, 0) }, + "fieldA": { "template": oField, "offset": new Vector2D(-5, 5) }, + "fieldB": { "template": oField, "offset": new Vector2D(-5, -5) }, + "pyramid": { "template": oPyramid, "offset": new Vector2D(0, -5) } +}; + +const riverTextures = [ + { + "left": fractionToTiles(0), + "right": fractionToTiles(0.04), + "terrain": tLush, + "tileClass": clShore + }, + { + "left": fractionToTiles(0.04), + "right": fractionToTiles(0.06), + "terrain": tSLush, + "tileClass": clShore + } +]; + +const riverAngle = Math.PI/5; + +g_Map.log("Creating Nile"); +paintRiver({ + "parallel": false, + "start": new Vector2D(fractionToTiles(0.25), mapBounds.top).rotateAround(riverAngle, mapCenter), + "end": new Vector2D(fractionToTiles(0.25), mapBounds.bottom).rotateAround(riverAngle, mapCenter), + "width": scaleByMapSize(12, 36), + "fadeDist": scaleByMapSize(3, 12), + "deviation": 1, + "heightRiverbed": heightSeaGround, + "heightLand": heightShore, + "meanderShort": 14, + "meanderLong": 18, + "waterFunc": (position, height, z) => { + clRiver.add(position); + createTerrain(tRiverBank).place(position); + }, + "landFunc": (position, shoreDist1, shoreDist2) => { + for (let riv of riverTextures) + if (riv.left < +shoreDist1 && +shoreDist1 < riv.right || riv.left < -shoreDist2 && -shoreDist2 < riv.right) + { + riv.tileClass.add(position); + if (riv.terrain) + createTerrain(riv.terrain).place(position); + } + } +}); +Engine.SetProgress(10); + +var [playerIDs, playerPosition] = playerPlacementRandom(sortAllPlayers(), avoidClasses(clRiver, 15, clPlayer, 30)); +placePlayerBases({ + "PlayerPlacement": [playerIDs, playerPosition], + "BaseResourceClass": clBaseResource, + "CityPatch": { + "outerTerrain": tRoadWild, + "innerTerrain": tRoad, + "radius": 10, + "width": 3, + "painters": [new TileClassPainter(clPlayer)] + }, + "Chicken": { + }, + "Berries": { + "template": oBush + }, + "Mines": { + "types": [ + { "template": oMetalLarge }, + { + "type": "stone_formation", + "template": oStoneSmall, + "terrain": tSecondaryDirt + } + ], + "groupElements": [new RandomObject(aBushes, 2, 4, 2, 3)] + }, + "Trees": { + "template": pickRandom([oBaobab, oAcacia]), + "count": 3 + } +}); +Engine.SetProgress(15); + +g_Map.log("Getting random coordinates for Kushite settlements"); +var kushiteTownPositions = []; +for (let retryCount = 0; retryCount < scaleByMapSize(3, 10); ++retryCount) +{ + let coordinate = g_Map.randomCoordinate(true); + if (new AndConstraint(avoidClasses(clPlayer, 40, clForest, 5, clKushiteVillages, 50, clRiver, 10)).allows(coordinate)) + { + kushiteTownPositions.push(coordinate); + createArea( + new ClumpPlacer(40, 0.6, 0.3, Infinity, coordinate), + [ + new TerrainPainter(tRoad), + new TileClassPainter(clKushiteVillages) + ]); + } +} + +g_Map.log("Placing the Kushite buildings"); +for (let coordinate of kushiteTownPositions) +{ + for (let building in kushVillageBuildings) + g_Map.placeEntityPassable(kushVillageBuildings[building].template, 0, Vector2D.add(coordinate, kushVillageBuildings[building].offset), Math.PI); + + createObjectGroup(new SimpleGroup([new SimpleObject(oKushSoldiers, 5, 7, 1, 2)], true, clKushiteVillages, coordinate), 0); +} + +g_Map.log("Creating kushite pyramids"); +createObjectGroups( + new SimpleGroup([new SimpleObject(oPyramidLarge, 1, 1, 0, 1)], true, clKushiteVillages), + 0, + avoidClasses(clPlayer, 20, clForest, 5, clKushiteVillages, 30, clRiver, 10), + scaleByMapSize(1, 7), + 200); +Engine.SetProgress(20); + +g_Map.log("Creating bumps"); +createAreas( + new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1), + new SmoothElevationPainter(ELEVATION_MODIFY, heightOffsetBump, 2), + new StaticConstraint(avoidClasses(clPlayer, 5, clKushiteVillages, 10, clRiver, 20)), + scaleByMapSize(300, 800)); + +g_Map.log("Creating dunes"); +createAreas( + new ChainPlacer(1, Math.floor(scaleByMapSize(4, 6)), Math.floor(scaleByMapSize(5, 15)), 0.5), + [ + new SmoothElevationPainter(ELEVATION_SET, heightDunes, 2), + new TileClassPainter(clDunes) + ], + avoidClasses(clPlayer, 3, clRiver, 20, clDunes, 10, clKushiteVillages, 10), + scaleByMapSize(1, 3) * numPlayers * 3); + +Engine.SetProgress(25); + +var [forestTrees, stragglerTrees] = getTreeCounts(400, 2000, 0.7); +createForests( + [tMainDirt[0], tForestFloor, tForestFloor, pForestP, pForestP], + avoidClasses(clPlayer, 20, clForest, 20, clDunes, 2, clRiver, 20, clKushiteVillages, 10), + clForest, + forestTrees); +Engine.SetProgress(40); + +g_Map.log("Creating dirt patches"); +for (let size of [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)]) + createAreas( + new ChainPlacer(1, Math.floor(scaleByMapSize(3, 5)), size, 0.5), + new LayeredPainter([tSecondaryDirt, tDirt], [1]), + avoidClasses(clDunes, 0, clForest, 0, clPlayer, 5, clRiver, 10), + scaleByMapSize(50, 90)); + +g_Map.log("Creating patches of farmland"); +for (let size of [scaleByMapSize(30, 40), scaleByMapSize(35, 50)]) + createAreas( + new ClumpPlacer(size, 0.4, 0.6), + new TerrainPainter(tFarmland), + avoidClasses(clDunes, 3, clForest, 3, clPlayer, 5, clKushiteVillages, 5, clRiver, 10), + scaleByMapSize(1, 10)); +Engine.SetProgress(60); + +g_Map.log("Creating stone mines"); +createObjectGroups( + new SimpleGroup([new SimpleObject(oStoneSmall, 1, 1, 0, 4), new RandomObject(aBushes, 2, 4, 0, 2)], true, clRock), + 0, + [avoidClasses(clForest, 1, clPlayer, 10, clRock, 10, clDunes, 1, clRiver, 15, clKushiteVillages, 10)], + scaleByMapSize(2, 8), + 100); + +g_Map.log("Creating small stone quarries"); +createObjectGroups( + new SimpleGroup([new SimpleObject(oStoneSmall, 2, 5, 1, 3), new RandomObject(aBushes, 2, 4, 0, 2)], true, clRock), + 0, + [avoidClasses(clForest, 1, clPlayer, 10, clRock, 10, clDunes, 1, clRiver, 15, clKushiteVillages, 10)], + scaleByMapSize(2, 8), + 100); + +g_Map.log("Creating metal mines"); +createObjectGroups( + new SimpleGroup([new SimpleObject(oMetalLarge, 1, 1, 0, 4), new RandomObject(aBushes, 2, 4, 0, 2)], true, clMetal), + 0, + [avoidClasses(clForest, 1, clPlayer, 10, clMetal, 10, clRock, 5, clDunes, 1, clRiver, 15, clKushiteVillages, 10)], + scaleByMapSize(2, 8), + 100); +Engine.SetProgress(70); + +g_Map.log("Creating gazelle"); +createObjectGroups( + new SimpleGroup([new SimpleObject(oGazelle, 4, 6, 1, 4)], true, clFood), + 0, + avoidClasses(clForest, 0, clKushiteVillages, 10, clPlayer, 5, clDunes, 1, clFood, 25, clRiver, 2), + 2 * numPlayers, + 50); + +g_Map.log("Creating giraffe"); +createObjectGroups( + new SimpleGroup([new SimpleObject(oGiraffe, 4, 6, 1, 4)], true, clFood), + 0, + avoidClasses(clForest, 0, clKushiteVillages, 10, clPlayer, 5, clDunes, 1, clFood, 25, clRiver, 2), + 2 * numPlayers, + 50); + +g_Map.log("Creating lions"); +if (!isNomad()) + createObjectGroups( + new SimpleGroup([new SimpleObject(oLion, 2, 3, 0, 2)], true, clFood), + 0, + avoidClasses(clForest, 0, clKushiteVillages, 10, clPlayer, 5, clDunes, 1, clFood, 25, clRiver, 2), + 3 * numPlayers, + 50); + +g_Map.log("Creating hawk"); +for (let i = 0; i < scaleByMapSize(1, 3); ++i) + g_Map.placeEntityAnywhere(oHawk, 0, mapCenter, randomAngle()); + +g_Map.log("Creating fish"); +createObjectGroups( + new SimpleGroup([new SimpleObject(oFish, 1, 2, 0, 1)], true, clFood), + 0, + [stayClasses(clRiver, 4), avoidClasses(clFood, 16)], + scaleByMapSize(15, 80), + 50); +Engine.SetProgress(80); + +createStragglerTrees( + [oBaobab, oAcacia], + avoidClasses(clForest, 3, clFood, 1, clDunes, 1, clPlayer, 1, clMetal, 6, clRock, 6, clRiver, 15, clKushiteVillages, 15), + clForest, + stragglerTrees); + +createStragglerTrees( + [oBaobab, oAcacia], + avoidClasses(clForest, 1, clFood, 1, clDunes, 3, clPlayer, 1, clMetal, 6, clRock, 6, clRiver, 15, clKushiteVillages, 15), + clForest, + stragglerTrees * (isNomad() ? 3 : 1)); + +createStragglerTrees( + [oDatePalm, oSDatePalm], + [avoidClasses(clPlayer, 5, clFood, 1), stayClasses(clShore, 2)], + clForest, + stragglerTrees * 10); + +Engine.SetProgress(90); + +g_Map.log("Creating reeds on the shore."); +createObjectGroups( + new SimpleGroup([new SimpleObject(aReeds, 3, 5, 0, 1)], true), + 0, + new HeightConstraint(heightReedsDepth, heightShore), + scaleByMapSize(500, 1000), + 50); + +g_Map.log("Creating small decorative rocks"); +createObjectGroups( + new SimpleGroup([new SimpleObject(aRock, 1, 3, 0, 1)], true), + 0, + avoidClasses(clForest, 0, clPlayer, 0, clDunes, 0), + scaleByMapSize(16, 262), + 50); + +g_Map.log("Creating bushes"); +createObjectGroups( + new SimpleGroup([new SimpleObject(aBushB, 1, 2, 0, 1), new SimpleObject(aBushA, 1, 3, 0, 2)], true), + 0, + avoidClasses(clForest, 0, clPlayer, 0, clDunes, 0, clRiver, 15), + scaleByMapSize(50, 500), + 50); +Engine.SetProgress(95); + +placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clKushiteVillages, 18, clMetal, 4, clRock, 4, clDunes, 4, clFood, 2, clRiver, 5)); + +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.2); + +setPPEffect("hdr"); +setPPContrast(0.65); +setPPSaturation(0.42); +setPPBloom(0.6); + +g_Map.ExportMap(); Index: ps/trunk/binaries/data/mods/public/maps/random/aethiopia.json =================================================================== --- ps/trunk/binaries/data/mods/public/maps/random/aethiopia.json +++ ps/trunk/binaries/data/mods/public/maps/random/aethiopia.json @@ -0,0 +1,10 @@ +{ + "settings" : { + "Name" : "Aethiopia", + "Script" : "aethiopia.js", + "Description" : "Aethiopia, land of the Kushites. Arid and hostile as the terrain might look, the region is surprisingly lush. The presence of several life-bringing oases serve to make this a prized haven for man and beast alike.", + "Preview" : "aethiopia.png", + "Keywords": ["new"], + "CircularMap" : true + } +}