diff --git a/binaries/data/mods/public/maps/random/ardennes_forest.js b/binaries/data/mods/public/maps/random/ardennes_forest.js new file mode 100644 index 0000000000..93858a0d7c --- /dev/null +++ b/binaries/data/mods/public/maps/random/ardennes_forest.js @@ -0,0 +1,672 @@ +/* + * Map : Ardennes Forest + * Author : Michael Mayfield + * Version : 1.2 + * + * CHANGES: + * + * 1.2: - Improved hill generation + * - Changed name from Black Forest to Ardennes Forest + * + * 1.1: - Reduces amount and jaggedness of cliffs + * - Improved forest generation - some clumps join together + * - Increased distance between minerals / stones and hills + * - Reduce noise around players bases + * + * 1.0: - Initial release + * + */ + +RMS.LoadLibrary("rmgen"); + +const BUILDING_ANGlE = 0.75*PI; + +// initialize map + +log("Initializing map..."); + +InitMap(); + +var numPlayers = getNumPlayers(); +var mapSize = getMapSize(); + +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 + ]; + +// create tile classes + +var clPlayer = createTileClass(); +var clPath = createTileClass(); +var clHill = createTileClass(); +var clForest = createTileClass(); +var clForestJoin = createTileClass(); +var clWater = createTileClass(); +var clRock = createTileClass(); +var clMetal = createTileClass(); +var clFood = createTileClass(); +var clBaseResource = createTileClass(); +var clPlayable = createTileClass(); +var clHillDeco = createTileClass(); + +// Create central dip +var centerX = fractionToTiles(0.5); +var centerZ = fractionToTiles(0.5); + +var placer = new ClumpPlacer(scaleByMapSize(mapSize * 70, mapSize * 300), 0.94, 0.05, 0.1, centerX, centerZ); +var elevationPainter = new SmoothElevationPainter( + ELEVATION_SET, + 30, + 3 + ); +var painter = new LayeredPainter( + [tCliff, tGrass], // terrains + [3] // widths + ); +createArea(placer, + [painter, elevationPainter], + null); + +RMS.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); + } + } +} + +// randomize player order +var playerIDs = []; +for (var i = 0; i < numPlayers; i++) +{ + playerIDs.push(i+1); +} +playerIDs = shuffleArray(playerIDs); + +// place players + +var playerX = new Array(numPlayers); +var playerZ = new Array(numPlayers); +var playerAngle = new Array(numPlayers); + +var startAngle = randFloat() * 2 * PI; +for (var i=0; i < numPlayers; i++) +{ + playerAngle[i] = startAngle + i*2*PI/numPlayers; + playerX[i] = 0.5 + 0.3*cos(playerAngle[i]); + playerZ[i] = 0.5 + 0.3*sin(playerAngle[i]); +} + +function distanceToPlayers(x, z) +{ + var r = 10000; + for (var i = 0; i < numPlayers; i++) + { + var dx = x - playerX[i]; + var dz = z - playerZ[i]; + r = min(r, dx*dx + dz*dz); + } + return sqrt(r); +} + +function playerNearness(x, z) +{ + var d = fractionToTiles(distanceToPlayers(x,z)); + + if (d < 13) + { + return 0; + } + else if (d < 19) + { + return (d-13)/(19-13); + } + else + { + return 1; + } +} + +RMS.SetProgress(10); + +for (var i=0; i < numPlayers; i++) +{ + var id = playerIDs[i]; + log("Creating base for player " + id + "..."); + + // get the x and z in tiles + var fx = fractionToTiles(playerX[i]); + var fz = fractionToTiles(playerZ[i]); + var ix = round(fx); + var iz = round(fz); + + // get civ specific starting entities + var civEntities = getStartingEntities(id-1); + + // create starting units + createStartingPlayerEntities(fx, fz, id, civEntities, BUILDING_ANGlE) + + var citySize = 250 + + var placer = new ClumpPlacer(citySize, 0.95, 0.3, 0.1, ix, iz); + createArea(placer, [paintClass(clPlayer)], null); + + // Create the city patch + var placer = new ClumpPlacer(citySize * 0.4, 0.6, 0.05, 10, ix, iz); + var painter = new TerrainPainter([tCity]); + createArea(placer, painter, null); + + // Create starter animals + for (var j = 0; j < 2; ++j) + { + var aAngle = randFloat(0, TWO_PI); + var aDist = 7; + var aX = round(fx + aDist * cos(aAngle)); + var aZ = round(fz + aDist * sin(aAngle)); + var group = new SimpleGroup( + [new SimpleObject(oPig, 5,5, 0,3)], + true, clBaseResource, aX, aZ + ); + createObjectGroup(group, 0); + } + + // Create starter berry bushes + var bbAngle = randFloat(0, TWO_PI); + var bbDist = 12; + var bbX = round(fx + bbDist * cos(bbAngle)); + var bbZ = round(fz + bbDist * sin(bbAngle)); + group = new SimpleGroup( + [new SimpleObject(oBerryBush, 3,3, 0,3)], + true, clBaseResource, bbX, bbZ + ); + createObjectGroup(group, 0); + + // Create starter metal mine + var mAngle = bbAngle; + while(abs(mAngle - bbAngle) < PI/3) + { + mAngle = randFloat(0, TWO_PI); + } + var mDist = bbDist + 4; + var mX = round(fx + mDist * cos(mAngle)); + var mZ = round(fz + mDist * sin(mAngle)); + group = new SimpleGroup( + [new SimpleObject(oMetalLarge, 1,1, 0,0)], + true, clBaseResource, mX, mZ + ); + createObjectGroup(group, 0); + + // Create starter stone mines + mAngle += randFloat(PI/8, PI/4); + mX = round(fx + mDist * cos(mAngle)); + mZ = round(fz + mDist * sin(mAngle)); + group = new SimpleGroup( + [new SimpleObject(oStoneLarge, 1,1, 0,2)], + true, clBaseResource, mX, mZ + ); + createObjectGroup(group, 0); + + // Create starter straggler trees + var num = scaleByMapSize(3, 4) + for (var j = 0; j < num; j++) + { + var tAngle = randFloat(0, TWO_PI); + var tDist = randFloat(6, bbDist + 5); + var tX = round(fx + tDist * cos(tAngle)); + var tZ = round(fz + tDist * sin(tAngle)); + group = new SimpleGroup( + [new SimpleObject(oOak, 1,3, 0,2)], + false, clBaseResource, tX, tZ + ); + createObjectGroup(group, 0, avoidClasses(clBaseResource,2)); + } + +} + +RMS.SetProgress(30); + +log("Creating hills..."); +var sizes = [scaleByMapSize(50, 800), scaleByMapSize(50, 400), scaleByMapSize(10, 30), scaleByMapSize(10, 30)]; +for (var i = 0; i < sizes.length; i++) +{ + var placer = new ClumpPlacer(sizes[i], 0.1, 0.2, 0.1); + var painter = new LayeredPainter( + [tCliff, [tForestFloor, tForestFloor, tCliff]], // terrains + [2] // widths + ); + var elevationPainter = new SmoothElevationPainter( + ELEVATION_SET, + 50, + sizes[i] < 50 ? 2 : 4 + ); + + var mountains = createAreas( + placer, + [painter, paintClass(clHill), elevationPainter], + avoidClasses(clPlayer, 8, clBaseResource, 2, clHill, 5), + scaleByMapSize(1, 4) + ); + + + if(sizes[i] > 100 && mountains.length > 0) + { + var placer = new ClumpPlacer(sizes[i] * 0.3, 0.94, 0.05, 0.1); + var elevationPainter = new SmoothElevationPainter( + ELEVATION_MODIFY, + 10, + 3 + ); + var painter = new LayeredPainter( + [tCliff, tForestFloor], // terrains + [2] // widths + ); + + createAreasInAreas( + placer, + [painter, elevationPainter], + stayClasses(clHill, 4), + mountains.length * 2, + 20, + mountains + ); + } + + + var placer = new ClumpPlacer(sizes[i], 0.1, 0.2, 0.1); + + var elevationPainter = new SmoothElevationPainter( + ELEVATION_SET, + 10, + 2 + ); + + var ravine = createAreas( + placer, + [painter, paintClass(clHill), elevationPainter], + avoidClasses(clPlayer, 6, clBaseResource, 2, clHill, 5), + scaleByMapSize(1, 3) + ); + + if(sizes[i] > 150 && ravine.length > 0) + { + // Place huts in ravines + var group = new RandomGroup( + [ + new SimpleObject(aCeltHouse, 0,1, 4,5), + new SimpleObject(aCeltLongHouse, 1,1, 4,5) + ], true, clHillDeco); + createObjectGroupsByAreas( + group, 0, + [avoidClasses(clHillDeco, 3), stayClasses(clHill, 3)], + ravine.length * 5, 20, + ravine + ); + + var group = new RandomGroup( + [ + new SimpleObject(aCeltHomestead, 1,1, 1,1) + ], true, clHillDeco); + createObjectGroupsByAreas( + group, 0, + [avoidClasses(clHillDeco, 5), stayClasses(clHill, 4)], + ravine.length * 2, 100, + ravine + ); + + // Place noise + var placer = new ClumpPlacer(sizes[i] * 0.3, 0.94, 0.05, 0.1); + var elevationPainter = new SmoothElevationPainter( + ELEVATION_SET, + 2, + 2 + ); + var painter = new LayeredPainter( + [tCliff, tForestFloor], // terrains + [2] // widths + ); + + createAreasInAreas( + placer, + [painter, elevationPainter], + [avoidClasses(clHillDeco, 2), stayClasses(clHill, 0)], + ravine.length * 2, + 20, + ravine + ); + + var placer = new ClumpPlacer(sizes[i] * 0.1, 0.3, 0.05, 0.1); + var elevationPainter = new SmoothElevationPainter( + ELEVATION_SET, + 40, + 2 + ); + var painter = new LayeredPainter( + [tCliff, tForestFloor], // terrains + [2] // widths + ); + + createAreasInAreas( + placer, + [painter, paintClass(clHill), elevationPainter], + [avoidClasses(clHillDeco, 2), borderClasses(clHill, 15, 1)], + ravine.length * 2, + 50, + ravine + ); + } + + RMS.SetProgress(30 + (20 * (i / sizes.length))); +} + +RMS.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) + { + var rnd = randFloat(); + if(g_Map.validT(ix, iz) && rnd < 0.1) + { + var i = randInt(aTrees.length); + placeObject(ix+randFloat(), iz+randFloat(), aTrees[i], 0, randFloat(0, TWO_PI)); + } + } + else if(h < 15 && hillDecoClass.countMembersInRadius(ix, iz, 1) == 0) + { + var rnd = randFloat(); + if(g_Map.validT(ix, iz) && rnd < 0.05) + { + var i = randInt(aTrees.length); + placeObject(ix+randFloat(), iz+randFloat(), aTrees[i], 0, randFloat(0, TWO_PI)); + } + } + } +} + +RMS.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)); + } +} + +RMS.SetProgress(60); + +// Calculate desired number of trees for map (based on size) +const MIN_TREES = 400; +const MAX_TREES = 6000; +const P_FOREST = 0.8; +const P_FOREST_JOIN = 0.25; + +var totalTrees = scaleByMapSize(MIN_TREES, MAX_TREES); +var numForest = totalTrees * P_FOREST * (1.0 - P_FOREST_JOIN); +var numForestJoin = totalTrees * P_FOREST * P_FOREST_JOIN; +var numStragglers = totalTrees * (1.0 - P_FOREST); + +// create forests +log("Creating forests..."); +var num = numForest / (scaleByMapSize(6,16) * numPlayers); +placer = new ClumpPlacer(numForest / num, 0.1, 0.1, 1); +painter = new TerrainPainter(pForest); +createAreasInAreas( + placer, + [painter, paintClass(clForest)], + avoidClasses(clPlayer, 5, clBaseResource, 4, clForest, 6, clHill, 4), + num, + 100, + [explorableArea] +); + +var num = numForestJoin / (scaleByMapSize(4,6) * numPlayers); +placer = new ClumpPlacer(numForestJoin / num, 0.1, 0.1, 1); +painter = new TerrainPainter(pForest); +createAreasInAreas( + placer, + [painter, paintClass(clForest), paintClass(clForestJoin)], + [avoidClasses(clPlayer, 5, clBaseResource, 4, clForestJoin, 5, clHill, 4), borderClasses(clForest, 1, 4)], + num, + 100, + [explorableArea] +); + + +RMS.SetProgress(70); + +// create grass patches +log("Creating grass patches..."); +var sizes = [scaleByMapSize(3, 48), scaleByMapSize(5, 84), scaleByMapSize(8, 128)]; +for (var i = 0; i < sizes.length; i++) +{ + placer = new ClumpPlacer(sizes[i], 0.3, 0.06, 0.5); + painter = new LayeredPainter( + [[tGrass,tGrassPatch],[tGrassPatch,tGrass], [tGrass,tGrassPatch]], // terrains + [1,1] // widths + ); + createAreas( + placer, + painter, + avoidClasses(clForest, 0, clHill, 2, clPlayer, 5), + scaleByMapSize(15, 45) + ); +} + +// create chopped forest patches +log("Creating chopped forest patches..."); +var sizes = [scaleByMapSize(20, 120)]; +for (var i = 0; i < sizes.length; i++) +{ + placer = new ClumpPlacer(sizes[i], 0.3, 0.06, 0.5); + painter = new TerrainPainter(tForestFloor); + createAreas( + placer, + painter, + avoidClasses(clForest, 0, clHill, 2, clPlayer, 5), + scaleByMapSize(4, 12) + ); +} + + +RMS.SetProgress(75); + +log("Creating stone mines..."); +// create stone quarries +var group = new SimpleGroup([new SimpleObject(oStoneSmall, 1,2, 0,4), new SimpleObject(oStoneLarge, 0,1, 0,4)], true, clRock); +createObjectGroupsByAreas(group, 0, + [avoidClasses(clHill, 4, clForest, 2, clPlayer, 20, clRock, 10)], + scaleByMapSize(6,20), 100, + [explorableArea] +); + +// create small stone quarries +group = new SimpleGroup([new SimpleObject(oStoneSmall, 2,5, 1,3)], true, clRock); +createObjectGroupsByAreas(group, 0, + [avoidClasses(clHill, 4, clForest, 2, clPlayer, 20, clRock, 10)], + scaleByMapSize(6,20), 100, + [explorableArea] +); + +log("Creating metal mines..."); +// create metal quarries +group = new SimpleGroup([new SimpleObject(oMetalSmall, 1,2, 0,4), new SimpleObject(oMetalLarge, 0,1, 0,4)], true, clMetal); +createObjectGroupsByAreas(group, 0, + [avoidClasses(clHill, 4, clForest, 2, clPlayer, 20, clMetal, 10, clRock, 5)], + scaleByMapSize(6,20), 100, + [explorableArea] +); + +RMS.SetProgress(80); + +// create wildlife +log("Creating wildlife..."); +group = new SimpleGroup( + [new SimpleObject(oDeer, 5,7, 0,4)], + true, clFood +); +createObjectGroupsByAreas(group, 0, + avoidClasses(clHill, 2, clForest, 0, clPlayer, 0, clBaseResource, 20), + 3 * numPlayers, 100, + [explorableArea] +); + +group = new SimpleGroup( + [new SimpleObject(oBoar, 2,3, 0,5)], + true, clFood +); +createObjectGroupsByAreas(group, 0, + avoidClasses(clHill, 2, clForest, 0, clPlayer, 0, clBaseResource, 15), + numPlayers, 50, + [explorableArea] +); + +group = new SimpleGroup( + [new SimpleObject(oBear, 1,1, 0,4)], + false, clFood +); +createObjectGroupsByAreas(group, 0, + avoidClasses(clHill, 2, clForest, 0, clPlayer, 20), + scaleByMapSize(3, 12), 200, + [explorableArea] +); + +RMS.SetProgress(85); + +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 +); +createObjectGroupsByAreas( + group, 0, + avoidClasses(clForest, 0), + scaleByMapSize(5, 50), 50, + [explorableArea] +); + +RMS.SetProgress(90); + +// create straggler trees +log("Creating straggler trees..."); +var types = [oOak, oOakLarge, oPine, oAleppoPine]; // some variation +var num = floor(numStragglers / types.length); +for (var i = 0; i < types.length; ++i) +{ + group = new SimpleGroup( + [new SimpleObject(types[i], 1,1, 0,3)], + true, clForest + ); + + createObjectGroupsByAreas(group, 0, + avoidClasses(clForest, 4, clHill, 5, clPlayer, 10, clBaseResource, 2, clMetal, 5, clRock, 5), + num, 20, + [explorableArea] + ); +} + +RMS.SetProgress(95); + +// create grass tufts +log("Creating grass tufts..."); +group = new SimpleGroup( + [new SimpleObject(aGrassLarge, 1,2, 0,1, -PI/8,PI/8)] +); +createObjectGroupsByAreas(group, 0, + avoidClasses(clHill, 2, clPlayer, 2), + scaleByMapSize(50, 300), 20, + [explorableArea] +); + + +setTerrainAmbientColour(0.44,0.51,0.56); +setUnitsAmbientColour(0.44,0.51,0.56); + +// Export map data +ExportMap(); diff --git a/binaries/data/mods/public/maps/random/ardennes_forest.json b/binaries/data/mods/public/maps/random/ardennes_forest.json new file mode 100644 index 0000000000..cd10fd83a6 --- /dev/null +++ b/binaries/data/mods/public/maps/random/ardennes_forest.json @@ -0,0 +1,14 @@ +{ + "settings" : { + "Name" : "Ardennes Forest", + "Script" : "ardennes_forest.js", + "Description" : "Each player starts deep in the forest.", + "BaseTerrain" : [ + "temp_forestfloor_pine", "temp_forestfloor_pine", "alpine_cliff_c", "alpine_grass_rocky" + ], + "BaseHeight" : 50, + "CircularMap" : true, + "Author" : "Michael Mayfield ", + "Version" : "1.2" + } +} diff --git a/binaries/data/mods/public/maps/random/rivers.js b/binaries/data/mods/public/maps/random/rivers.js index 2b3817d37a..98d57b4e35 100644 --- a/binaries/data/mods/public/maps/random/rivers.js +++ b/binaries/data/mods/public/maps/random/rivers.js @@ -19,6 +19,11 @@ var tGrassPatch = rBiomeT12(); var tShoreBlend = rBiomeT13(); var tShore = rBiomeT14(); var tWater = rBiomeT15(); +if (rt == 2) +{ + tShore = "alpine_shore_rocks_icy"; + tWater = "alpine_shore_rocks"; +} // gaia entities var oOak = rBiomeE1(); @@ -273,7 +278,16 @@ for (var c = 0 ; c < numPlayers ; c++) riverAngle[c] = startAngle + (((2 * c + 1) / (numPlayers * 2)) * TWO_PI ); PX[c] = round(fractionToTiles(0.5 + 0.5 * cos(riverAngle[c]))); PZ[c] = round(fractionToTiles(0.5 + 0.5 * sin(riverAngle[c]))); + log (playerIDs[c], ",,," ,playerIDs[0]); isRiver[c][numPlayers]=1; + /*if ((c == numPlayers-1)&&(!areAllies(playerIDs[c]-1, playerIDs[0]-1))) + { + isRiver[c][numPlayers]=1; + } + else if ((c < numPlayers-1)&&(!areAllies(playerIDs[c]-1, playerIDs[c+1]-1))) + { + isRiver[c][numPlayers]=1; + }*/ } //theta is the start value for rndRiver function. seed implies