diff --git a/binaries/data/mods/public/gui/common/gamedescription.js b/binaries/data/mods/public/gui/common/gamedescription.js index 5884f19631..af4de5ff4c 100644 --- a/binaries/data/mods/public/gui/common/gamedescription.js +++ b/binaries/data/mods/public/gui/common/gamedescription.js @@ -342,6 +342,15 @@ function getGameDescription(extended = false) translate("Sorry, no description available.") }); + if (extended || g_GameAttributes.settings.Nomad) + titles.push({ + "label": g_GameAttributes.settings.Nomad ? translate("Nomad Mode") : translate("Civic Centers"), + "value": + g_GameAttributes.settings.Nomad ? + translate("Players start with only few units and have to find a suitable place to build their city.") : + translate("Players start with a Civic Center.") + }); + if (g_GameAttributes.settings.Biome) { let biome = g_Settings.Biomes.find(b => b.Id == g_GameAttributes.settings.Biome); diff --git a/binaries/data/mods/public/gui/gamesetup/gamesetup.js b/binaries/data/mods/public/gui/gamesetup/gamesetup.js index 1cbe57bbf5..a560684130 100644 --- a/binaries/data/mods/public/gui/gamesetup/gamesetup.js +++ b/binaries/data/mods/public/gui/gamesetup/gamesetup.js @@ -367,6 +367,7 @@ var g_OptionOrderGUI = { "populationCap", "startingResources", "ceasefire", + "nomad", "regicideGarrison", "exploreMap", "revealMap", @@ -768,6 +769,18 @@ var g_Checkboxes = { "enabled": () => g_GameAttributes.mapType != "scenario", "initOrder": 1000 }, + "nomad": { + "title": () => translate("Nomad"), + "tooltip": () => translate("In Nomad mode, players start with only few units and have to find a suitable place to build their city. Ceasefire is recommended."), + "default": () => false, + "defined": () => g_GameAttributes.settings.Nomad !== undefined, + "get": () => g_GameAttributes.settings.Nomad, + "set": checked => { + g_GameAttributes.settings.Nomad = checked; + }, + "hidden": () => g_GameAttributes.mapType != "random", + "initOrder": 1000 + }, "revealMap": { "title": () => // Translation: Make sure to differentiate between the revealed map and explored map options! @@ -1796,9 +1809,10 @@ function selectMap(name) let mapData = loadMapData(name); let mapSettings = mapData && mapData.settings ? clone(mapData.settings) : {}; - // Reset victory conditions if (g_GameAttributes.mapType != "random") { + delete g_GameAttributes.settings.Nomad; + let victoryIdx = g_VictoryConditions.Name.indexOf(mapSettings.GameType || "") != -1 ? g_VictoryConditions.Name.indexOf(mapSettings.GameType) : g_VictoryConditions.Default; g_GameAttributes.settings.GameType = g_VictoryConditions.Name[victoryIdx]; g_GameAttributes.settings.VictoryScripts = g_VictoryConditions.Scripts[victoryIdx]; diff --git a/binaries/data/mods/public/maps/random/aegean_sea.js b/binaries/data/mods/public/maps/random/aegean_sea.js index ec527ca540..1752eea110 100644 --- a/binaries/data/mods/public/maps/random/aegean_sea.js +++ b/binaries/data/mods/public/maps/random/aegean_sea.js @@ -283,6 +283,8 @@ createStragglerTrees( 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); diff --git a/binaries/data/mods/public/maps/random/african_plains.js b/binaries/data/mods/public/maps/random/african_plains.js index 0ac4d3f72b..55f664fdb1 100644 --- a/binaries/data/mods/public/maps/random/african_plains.js +++ b/binaries/data/mods/public/maps/random/african_plains.js @@ -269,6 +269,8 @@ createStragglerTrees( 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); diff --git a/binaries/data/mods/public/maps/random/alpine_lakes.js b/binaries/data/mods/public/maps/random/alpine_lakes.js index 12f2deb9ae..d077f532f5 100644 --- a/binaries/data/mods/public/maps/random/alpine_lakes.js +++ b/binaries/data/mods/public/maps/random/alpine_lakes.js @@ -288,6 +288,8 @@ createStragglerTrees( clForest, stragglerTrees); +placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); + setSkySet(pickRandom(["cirrus", "cumulus", "sunny"])); setSunRotation(randFloat(0, 2 * Math.PI)); setSunElevation(Math.PI * randFloat(1/5, 1/3)); diff --git a/binaries/data/mods/public/maps/random/alpine_valley.js b/binaries/data/mods/public/maps/random/alpine_valley.js index 54bd91dcbd..71734cefb3 100644 --- a/binaries/data/mods/public/maps/random/alpine_valley.js +++ b/binaries/data/mods/public/maps/random/alpine_valley.js @@ -533,6 +533,8 @@ createObjectGroupsDeprecated(group, 0, planetm * scaleByMapSize(13, 200), 50 ); +placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); + setSkySet(pickRandom(["cirrus", "cumulus", "sunny"])); setSunRotation(randFloat(0, 2 * Math.PI)); setSunElevation(Math.PI * randFloat(1/5, 1/3)); diff --git a/binaries/data/mods/public/maps/random/ambush.js b/binaries/data/mods/public/maps/random/ambush.js index 51f61487fd..a3bff2c6b5 100644 --- a/binaries/data/mods/public/maps/random/ambush.js +++ b/binaries/data/mods/public/maps/random/ambush.js @@ -190,4 +190,15 @@ addElements(shuffleArray([ ])); 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(); diff --git a/binaries/data/mods/public/maps/random/anatolian_plateau.js b/binaries/data/mods/public/maps/random/anatolian_plateau.js index 0d9e81272c..73f7181780 100644 --- a/binaries/data/mods/public/maps/random/anatolian_plateau.js +++ b/binaries/data/mods/public/maps/random/anatolian_plateau.js @@ -231,6 +231,8 @@ createObjectGroupsDeprecated(group, 0, scaleByMapSize(13, 200), 50 ); +placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); + setFogThickness(0.1); setFogFactor(0.2); diff --git a/binaries/data/mods/public/maps/random/archipelago.js b/binaries/data/mods/public/maps/random/archipelago.js index 66efc6fb39..48a5115a0c 100644 --- a/binaries/data/mods/public/maps/random/archipelago.js +++ b/binaries/data/mods/public/maps/random/archipelago.js @@ -256,6 +256,12 @@ createStragglerTrees( 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"); diff --git a/binaries/data/mods/public/maps/random/arctic_summer.js b/binaries/data/mods/public/maps/random/arctic_summer.js index ed30b5bcc5..d4b56169b4 100644 --- a/binaries/data/mods/public/maps/random/arctic_summer.js +++ b/binaries/data/mods/public/maps/random/arctic_summer.js @@ -305,6 +305,8 @@ createStragglerTrees( clForest, stragglerTrees); +placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clWater, 4, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); + setSkySet("sunset 1"); setSunRotation(randFloat(0, 2 * Math.PI)); setSunColor(0.8, 0.7, 0.6); diff --git a/binaries/data/mods/public/maps/random/ardennes_forest.js b/binaries/data/mods/public/maps/random/ardennes_forest.js index efc6d2e07b..5391145aed 100644 --- a/binaries/data/mods/public/maps/random/ardennes_forest.js +++ b/binaries/data/mods/public/maps/random/ardennes_forest.js @@ -452,6 +452,8 @@ createObjectGroupsByAreasDeprecated(group, 0, [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); diff --git a/binaries/data/mods/public/maps/random/atlas_mountains.js b/binaries/data/mods/public/maps/random/atlas_mountains.js index c7b9a29cc2..de8725264f 100644 --- a/binaries/data/mods/public/maps/random/atlas_mountains.js +++ b/binaries/data/mods/public/maps/random/atlas_mountains.js @@ -206,6 +206,8 @@ createStragglerTrees( clForest, stragglerTrees / 5); +placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); + setFogFactor(0.2); setFogThickness(0.14); diff --git a/binaries/data/mods/public/maps/random/belgian_uplands.js b/binaries/data/mods/public/maps/random/belgian_uplands.js index 849b86295c..d8d4f3dddb 100644 --- a/binaries/data/mods/public/maps/random/belgian_uplands.js +++ b/binaries/data/mods/public/maps/random/belgian_uplands.js @@ -94,6 +94,8 @@ 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) { @@ -113,8 +115,6 @@ while (!goodStartPositionsFound) 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... - var lowerHeightLimit = textueByHeight[3].upperHeightLimit; - var upperHeightLimit = textueByHeight[6].upperHeightLimit; // Check for valid points by height for (var x = distToBorder + minTerrainDistToBorder; x < mapSize - distToBorder - minTerrainDistToBorder; x++) @@ -369,8 +369,12 @@ for(var x = minTerrainDistToBorder; x < mapSize - minTerrainDistToBorder; x++) 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; diff --git a/binaries/data/mods/public/maps/random/botswanan_haven.js b/binaries/data/mods/public/maps/random/botswanan_haven.js index b909857de2..c84ce11d47 100644 --- a/binaries/data/mods/public/maps/random/botswanan_haven.js +++ b/binaries/data/mods/public/maps/random/botswanan_haven.js @@ -371,6 +371,8 @@ createObjectGroupsDeprecated( 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); diff --git a/binaries/data/mods/public/maps/random/caledonian_meadows.js b/binaries/data/mods/public/maps/random/caledonian_meadows.js index 2f7a76319b..180a3d28c9 100644 --- a/binaries/data/mods/public/maps/random/caledonian_meadows.js +++ b/binaries/data/mods/public/maps/random/caledonian_meadows.js @@ -421,15 +421,16 @@ for (let h = 0; h < heighLimits.length; ++h) } Engine.SetProgress(80); -/** - * Add start locations and resource spots after terrain texture and path painting - */ -for (let p = 0; p < playerIDs.length; ++p) -{ - let point = startLocations[p]; - placeCivDefaultStartingEntities(point.x, point.y, playerIDs[p], "walls"); - placeStartLocationResources(startLocations[p]); -} +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.x, point.y, playerIDs[p], true); + placeStartLocationResources(startLocations[p]); + } log("Placing resources, farmsteads, groves and camps..."); for (let i = 0; i < resourceSpots.length; ++i) diff --git a/binaries/data/mods/public/maps/random/cantabrian_highlands.js b/binaries/data/mods/public/maps/random/cantabrian_highlands.js index e264938b01..4b53068e67 100644 --- a/binaries/data/mods/public/maps/random/cantabrian_highlands.js +++ b/binaries/data/mods/public/maps/random/cantabrian_highlands.js @@ -56,7 +56,7 @@ var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); -var playerHillRadius = defaultPlayerBaseRadius(); +var playerHillRadius = defaultPlayerBaseRadius() / (isNomad() ? 1.5 : 1); var playerHillElevation = 20; var [playerIDs, playerX, playerZ, playerAngle] = playerPlacementCircle(0.35); @@ -259,6 +259,8 @@ createStragglerTrees( 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); diff --git a/binaries/data/mods/public/maps/random/canyon.js b/binaries/data/mods/public/maps/random/canyon.js index b749d95023..2190f4dc7e 100644 --- a/binaries/data/mods/public/maps/random/canyon.js +++ b/binaries/data/mods/public/maps/random/canyon.js @@ -80,9 +80,8 @@ for (let i = 0; i < numPlayers; ++i) [ new LayeredPainter([tMainTerrain, tMainTerrain], [2]), new SmoothElevationPainter(ELEVATION_SET, landHeight, 2), - paintClass(j == 1 ? clLand : clPlayer) - ], - null); + paintClass(j == 1 || isNomad() ? clLand : clPlayer) + ]); log("Creating center area..."); var center = Math.round(fractionToTiles(0.5)); @@ -370,4 +369,8 @@ for (let i = 0; i < randIntInclusive(3, 8); ++i) for (let template of [oFoodTreasure, oWoodTreasure]) placeObject(center + randFloat(-7, 7), center + randFloat(-7, 7), template, 0, randFloat(0, 2 * Math.PI)); +placePlayersNomad( + clPlayer, + [stayClasses(clLand, 4), avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clHill2, 4, clFood, 2)]); + ExportMap(); diff --git a/binaries/data/mods/public/maps/random/continent.js b/binaries/data/mods/public/maps/random/continent.js index 8e14983cf9..e983847910 100644 --- a/binaries/data/mods/public/maps/random/continent.js +++ b/binaries/data/mods/public/maps/random/continent.js @@ -245,6 +245,10 @@ createStragglerTrees( clForest, stragglerTrees); +placePlayersNomad( + clPlayer, + [stayClasses(clLand, 4), avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)]); + setWaterWaviness(1.0); setWaterType("ocean"); diff --git a/binaries/data/mods/public/maps/random/corinthian_isthmus.js b/binaries/data/mods/public/maps/random/corinthian_isthmus.js index ef07fe20f2..ee5038da0d 100644 --- a/binaries/data/mods/public/maps/random/corinthian_isthmus.js +++ b/binaries/data/mods/public/maps/random/corinthian_isthmus.js @@ -252,6 +252,8 @@ createStragglerTrees( 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); diff --git a/binaries/data/mods/public/maps/random/corsica.js b/binaries/data/mods/public/maps/random/corsica.js index fa1923caa4..b8da448a45 100644 --- a/binaries/data/mods/public/maps/random/corsica.js +++ b/binaries/data/mods/public/maps/random/corsica.js @@ -500,6 +500,8 @@ createObjectGroupsDeprecated( 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); diff --git a/binaries/data/mods/public/maps/random/cycladic_archipelago.js b/binaries/data/mods/public/maps/random/cycladic_archipelago.js index 2d73d5b378..8eeeca8f41 100644 --- a/binaries/data/mods/public/maps/random/cycladic_archipelago.js +++ b/binaries/data/mods/public/maps/random/cycladic_archipelago.js @@ -360,6 +360,8 @@ createObjectGroupsDeprecated(group, 0, ); 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); diff --git a/binaries/data/mods/public/maps/random/danubius.js b/binaries/data/mods/public/maps/random/danubius.js index 61671f0071..02386d1f2f 100644 --- a/binaries/data/mods/public/maps/random/danubius.js +++ b/binaries/data/mods/public/maps/random/danubius.js @@ -55,7 +55,8 @@ 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 oTower = "structures/gaul_defense_tower"; +const oSentryTower = "structures/gaul_sentry_tower"; const oOutpost = "structures/gaul_outpost"; const oHut = "other/celt_hut"; @@ -268,7 +269,7 @@ if (gallicCC) 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 ? oTower : oPalisadeTower }; + 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"]) @@ -569,19 +570,20 @@ createFood( clFood); log("Creating violent animals..."); -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); +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); @@ -757,6 +759,8 @@ createObjectGroupsDeprecated( 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 diff --git a/binaries/data/mods/public/maps/random/deep_forest.js b/binaries/data/mods/public/maps/random/deep_forest.js index e59c531743..2106dcda89 100644 --- a/binaries/data/mods/public/maps/random/deep_forest.js +++ b/binaries/data/mods/public/maps/random/deep_forest.js @@ -222,6 +222,7 @@ Engine.SetProgress(60); // Place eyecandy placeObject(mapCenterX, mapCenterZ, templateEC, 0, randFloat(0, 2 * Math.PI)); +addToClass(mapCenterX, mapCenterZ, clBaseResource); createArea( new ClumpPlacer(Math.square(radiusEC), 1/2, 1/8, 1, mapCenterX, mapCenterZ), [ @@ -268,4 +269,6 @@ for (var x = 0; x < mapSize; x++) } Engine.SetProgress(95); +placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clBaseResource, 4)); + ExportMap(); diff --git a/binaries/data/mods/public/maps/random/empire.js b/binaries/data/mods/public/maps/random/empire.js index b4dd0a58ae..21fbce244b 100644 --- a/binaries/data/mods/public/maps/random/empire.js +++ b/binaries/data/mods/public/maps/random/empire.js @@ -216,4 +216,14 @@ addElements(shuffleArray([ ])); 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(); diff --git a/binaries/data/mods/public/maps/random/english_channel.js b/binaries/data/mods/public/maps/random/english_channel.js index 279fa87947..2e2d15bde4 100644 --- a/binaries/data/mods/public/maps/random/english_channel.js +++ b/binaries/data/mods/public/maps/random/english_channel.js @@ -257,4 +257,6 @@ 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(); diff --git a/binaries/data/mods/public/maps/random/extinct_volcano.js b/binaries/data/mods/public/maps/random/extinct_volcano.js index adc399221f..8dceec8fd8 100644 --- a/binaries/data/mods/public/maps/random/extinct_volcano.js +++ b/binaries/data/mods/public/maps/random/extinct_volcano.js @@ -74,34 +74,35 @@ var ccMountainSize = defaultPlayerBaseRadius(); var [playerIDs, playerX, playerZ] = playerPlacementCircle(0.35); log("Creating CC mountains..."); -for (let i = 0; i < numPlayers; ++i) -{ - let ix = Math.round(fractionToTiles(playerX[i])); - let iz = Math.round(fractionToTiles(playerZ[i])); +if (!isNomad()) + for (let i = 0; i < numPlayers; ++i) + { + let ix = Math.round(fractionToTiles(playerX[i])); + let iz = Math.round(fractionToTiles(playerZ[i])); - // This one consists of many bumps, creating an omnidirectional ramp - createMountain( - ccMountainHeight, - Math.floor(scaleByMapSize(15, 15)), - Math.floor(scaleByMapSize(15, 15)), - Math.floor(scaleByMapSize(4, 10)), - avoidClasses(), - ix, - iz, - tHillDark, - clPlayer, - 14); + // This one consists of many bumps, creating an omnidirectional ramp + createMountain( + ccMountainHeight, + ccMountainSize, + ccMountainSize, + Math.floor(scaleByMapSize(4, 10)), + undefined, + ix, + iz, + tHillDark, + clPlayer, + 14); + + // Flatten the initial CC area + createArea( + new ClumpPlacer(diskArea(ccMountainSize), 0.95, 0.6, 10, ix, iz), + [ + new LayeredPainter([tHillVeryDark, tHillMedium1], [ccMountainSize]), + new SmoothElevationPainter(ELEVATION_SET, ccMountainHeight, ccMountainSize), + paintClass(clPlayer) + ]); + } - // Flatten the initial CC area - createArea( - new ClumpPlacer(diskArea(ccMountainSize), 0.95, 0.6, 10, ix, iz), - [ - new LayeredPainter([tHillVeryDark, tHillMedium1], [ccMountainSize]), - new SmoothElevationPainter(ELEVATION_SET, ccMountainHeight, ccMountainSize), - paintClass(clPlayer) - ], - null); -} Engine.SetProgress(8); placePlayerBases({ @@ -277,22 +278,25 @@ createObjectGroupsDeprecated( 100); Engine.SetProgress(65); -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); +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( @@ -445,6 +449,8 @@ createObjectGroupsDeprecated( 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); diff --git a/binaries/data/mods/public/maps/random/flood.js b/binaries/data/mods/public/maps/random/flood.js index 0a4a7c13f2..0b0b590020 100644 --- a/binaries/data/mods/public/maps/random/flood.js +++ b/binaries/data/mods/public/maps/random/flood.js @@ -312,6 +312,12 @@ createObjectGroupsDeprecated( [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); diff --git a/binaries/data/mods/public/maps/random/fortress.js b/binaries/data/mods/public/maps/random/fortress.js index b2d3232b68..c98d9dd84a 100644 --- a/binaries/data/mods/public/maps/random/fortress.js +++ b/binaries/data/mods/public/maps/random/fortress.js @@ -59,6 +59,9 @@ var [playerIDs, playerX, playerZ] = playerPlacementCircle(0.35); for (var i=0; i < numPlayers; i++) { + if (isNomad()) + break; + log("Creating base for player " + playerIDs[i] + "..."); playerX[i] *= mapSize; playerZ[i] *= mapSize; @@ -304,6 +307,8 @@ createStragglerTrees( 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); diff --git a/binaries/data/mods/public/maps/random/frontier.js b/binaries/data/mods/public/maps/random/frontier.js index e8a614104d..3942ad8767 100644 --- a/binaries/data/mods/public/maps/random/frontier.js +++ b/binaries/data/mods/public/maps/random/frontier.js @@ -95,7 +95,7 @@ if (randElevation < 4) g_TileClasses.valley, 10, g_TileClasses.water, 25 ], - "sizes": g_AllSizes, + "sizes": ["small"], "mixes": g_AllMixes, "amounts": g_AllAmounts }); @@ -264,4 +264,16 @@ addElements(shuffleArray([ ])); 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.plateau, 4, + g_TileClasses.animals, 2)); + ExportMap(); diff --git a/binaries/data/mods/public/maps/random/gear.js b/binaries/data/mods/public/maps/random/gear.js index 52a8503233..acb7df679f 100644 --- a/binaries/data/mods/public/maps/random/gear.js +++ b/binaries/data/mods/public/maps/random/gear.js @@ -316,4 +316,6 @@ createStragglerTrees( clForest, stragglerTrees); +placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); + ExportMap(); diff --git a/binaries/data/mods/public/maps/random/guadalquivir_river.js b/binaries/data/mods/public/maps/random/guadalquivir_river.js index 0798f27b72..29c94d0b69 100644 --- a/binaries/data/mods/public/maps/random/guadalquivir_river.js +++ b/binaries/data/mods/public/maps/random/guadalquivir_river.js @@ -260,6 +260,12 @@ createStragglerTrees( 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); diff --git a/binaries/data/mods/public/maps/random/gulf_of_bothnia.js b/binaries/data/mods/public/maps/random/gulf_of_bothnia.js index ac471aeb27..4395bde262 100644 --- a/binaries/data/mods/public/maps/random/gulf_of_bothnia.js +++ b/binaries/data/mods/public/maps/random/gulf_of_bothnia.js @@ -308,6 +308,9 @@ createStragglerTrees( 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(randFloat(0, 2 * Math.PI)); setSunElevation(Math.PI * randFloat(1/6, 1/4)); diff --git a/binaries/data/mods/public/maps/random/harbor.js b/binaries/data/mods/public/maps/random/harbor.js index bdd4d043d3..b597c82d3a 100644 --- a/binaries/data/mods/public/maps/random/harbor.js +++ b/binaries/data/mods/public/maps/random/harbor.js @@ -249,6 +249,19 @@ addElements([ 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() diff --git a/binaries/data/mods/public/maps/random/hells_pass.js b/binaries/data/mods/public/maps/random/hells_pass.js index e505d8af22..2400214c1a 100644 --- a/binaries/data/mods/public/maps/random/hells_pass.js +++ b/binaries/data/mods/public/maps/random/hells_pass.js @@ -222,6 +222,19 @@ addElements(shuffleArray([ ])); 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() @@ -237,7 +250,9 @@ function placeBarriers() if (currentBiome() == "autumn") spineTerrain = g_Terrains.tier4Terrain; - for (let i = 0; i < teamsArray.length; ++i) + let spineCount = isNomad() ? randIntInclusive(1, 4) : teamsArray.length; + + for (let i = 0; i < spineCount; ++i) { var mStartCo = 0.07; var mStopCo = 0.42; @@ -246,14 +261,14 @@ function placeBarriers() var mOffset = 0.5; var mTaper = -1.5; - if (teamsArray.length > 3 || getMapSize() <= 192) + if (spineCount > 3 || getMapSize() <= 192) { mWaviness = 0.2; mOffset = 0.2; mTaper = -1; } - if (teamsArray.length >= 5) + if (spineCount >= 5) { mSize = 4; mWaviness = 0.2; @@ -261,7 +276,7 @@ function placeBarriers() mTaper = -0.7; } - let angle = startAngle + (i + 0.5) * 2 * Math.PI / teamsArray.length; + let angle = startAngle + (i + 0.5) * 2 * Math.PI / spineCount; createArea( new PathPlacer( fractionToTiles(0.5 + mStartCo * Math.cos(angle)), diff --git a/binaries/data/mods/public/maps/random/hyrcanian_shores.js b/binaries/data/mods/public/maps/random/hyrcanian_shores.js index 996c7506b1..22c5e73e41 100644 --- a/binaries/data/mods/public/maps/random/hyrcanian_shores.js +++ b/binaries/data/mods/public/maps/random/hyrcanian_shores.js @@ -320,6 +320,8 @@ createObjectGroupsDeprecated(group, 0, 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); diff --git a/binaries/data/mods/public/maps/random/india.js b/binaries/data/mods/public/maps/random/india.js index 553c30b20a..f4b01b0138 100644 --- a/binaries/data/mods/public/maps/random/india.js +++ b/binaries/data/mods/public/maps/random/india.js @@ -248,6 +248,8 @@ createObjectGroupsDeprecated( 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); diff --git a/binaries/data/mods/public/maps/random/island_stronghold.js b/binaries/data/mods/public/maps/random/island_stronghold.js index a0dab2ec14..ac39c60e1b 100644 --- a/binaries/data/mods/public/maps/random/island_stronghold.js +++ b/binaries/data/mods/public/maps/random/island_stronghold.js @@ -87,7 +87,7 @@ var numTeams = teams.filter(team => team).length; var teamNo = 0; for (let i = 0; i < teams.length; ++i) { - if (!teams[i]) + if (!teams[i] || isNomad()) continue; ++teamNo; @@ -209,7 +209,7 @@ for (let x = 0; x < mapSize; ++x) landAreas.push([x, z]); log("Creating big islands..."); -let numIslands = scaleByMapSize(4, 14); +let numIslands = scaleByMapSize(4, 14) * (isNomad() ? 2 : 1); for (let i = 0; i < numIslands; ++i) { let landAreaLen = landAreas.length; @@ -219,7 +219,14 @@ for (let i = 0; i < numIslands; ++i) let chosenPoint = pickRandom(landAreas); let newIsland = createAreas( - new ChainPlacer(Math.floor(scaleByMapSize(4, 8)), Math.floor(scaleByMapSize(8, 14)), Math.floor(scaleByMapSize(25, 60)), 0.07, chosenPoint[0], chosenPoint[1], scaleByMapSize(30, 70)), + 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), @@ -480,6 +487,8 @@ createObjectGroupsDeprecated(group, 0, paintTerrainBasedOnHeight(1, 2, 0, tShore); paintTerrainBasedOnHeight(getMapBaseHeight(), 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(randFloat(0, 2 * Math.PI)); setSunElevation(randFloat(1/5, 1/3) * Math.PI); diff --git a/binaries/data/mods/public/maps/random/islands.js b/binaries/data/mods/public/maps/random/islands.js index e7140e5282..55d7db1112 100644 --- a/binaries/data/mods/public/maps/random/islands.js +++ b/binaries/data/mods/public/maps/random/islands.js @@ -65,21 +65,24 @@ var playerIslandRadius = scaleByMapSize(20, 29); var [playerIDs, playerX, playerZ, playerAngle] = playerPlacementCircle(0.35); -log("Creating player islands and docks..."); -for (let i = 0; i < numPlayers; i++) +if (!isNomad()) { - let playerPos = new Vector2D(playerX[i], playerZ[i]).mult(mapSize); - createArea( - new ClumpPlacer(diskArea(playerIslandRadius), 0.8, 0.1, 10, playerPos.x, playerPos.y), - [ - new LayeredPainter([tMainTerrain , tMainTerrain, tMainTerrain], [1, 6]), - new SmoothElevationPainter(ELEVATION_SET, landHeight, 6), - paintClass(clLand), - paintClass(clPlayer) - ]); + log("Creating player islands and docks..."); + for (let i = 0; i < numPlayers; i++) + { + let playerPos = new Vector2D(playerX[i], playerZ[i]).mult(mapSize); + createArea( + new ClumpPlacer(diskArea(playerIslandRadius), 0.8, 0.1, 10, playerPos.x, playerPos.y), + [ + new LayeredPainter([tMainTerrain , tMainTerrain, tMainTerrain], [1, 6]), + new SmoothElevationPainter(ELEVATION_SET, landHeight, 6), + paintClass(clLand), + paintClass(clPlayer) + ]); - let dockLocation = findLocationInDirectionBasedOnHeight(playerPos, mapCenter, -3 , landHeight - 0.5, landHeight); - placeObject(dockLocation.x, dockLocation.y, oDock, playerIDs[i], playerAngle[i] + Math.PI); + let dockLocation = findLocationInDirectionBasedOnHeight(playerPos, mapCenter, -3 , landHeight - 0.5, landHeight); + placeObject(dockLocation.x, dockLocation.y, oDock, playerIDs[i], playerAngle[i] + Math.PI); + } } log("Creating big islands..."); @@ -348,6 +351,8 @@ createObjectGroupsDeprecated(group, 0, 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(randFloat(0, 2 * Math.PI)); setSunElevation(randFloat(1/5, 1/3) * Math.PI); diff --git a/binaries/data/mods/public/maps/random/kerala.js b/binaries/data/mods/public/maps/random/kerala.js index 6254f3c454..f4a0c92db5 100644 --- a/binaries/data/mods/public/maps/random/kerala.js +++ b/binaries/data/mods/public/maps/random/kerala.js @@ -308,6 +308,8 @@ createObjectGroupsDeprecated(group, 0, 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); diff --git a/binaries/data/mods/public/maps/random/lake.js b/binaries/data/mods/public/maps/random/lake.js index cf5c56bf26..43cb35d292 100644 --- a/binaries/data/mods/public/maps/random/lake.js +++ b/binaries/data/mods/public/maps/random/lake.js @@ -246,6 +246,8 @@ createStragglerTrees( clForest, stragglerTrees); +placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clHill, 2, clForest, 1, clMetal, 4, clRock, 4, clFood, 2)); + setWaterWaviness(4.0); setWaterType("lake"); diff --git a/binaries/data/mods/public/maps/random/latium.js b/binaries/data/mods/public/maps/random/latium.js index 3e09219e94..37dd30e40d 100644 --- a/binaries/data/mods/public/maps/random/latium.js +++ b/binaries/data/mods/public/maps/random/latium.js @@ -454,6 +454,8 @@ createObjectGroupsDeprecated(group, 0, 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); diff --git a/binaries/data/mods/public/maps/random/lions_den.js b/binaries/data/mods/public/maps/random/lions_den.js index d4d2c22833..578bf6fa06 100644 --- a/binaries/data/mods/public/maps/random/lions_den.js +++ b/binaries/data/mods/public/maps/random/lions_den.js @@ -408,6 +408,17 @@ addElements([ ]); Engine.SetProgress(95); +placePlayersNomad( + g_TileClasses.player, + [ + new HeightConstraint(valleyHeight, pathHeight), + avoidClasses( + g_TileClasses.forest, 1, + g_TileClasses.metal, 4, + g_TileClasses.rock, 4, + g_TileClasses.animals, 2) + ]); + ExportMap(); function createSunkenTerrain() @@ -519,7 +530,7 @@ function createSunkenTerrain() log("Creating the den of the player..."); createArea( - new ClumpPlacer(mapArea * 0.03, 0.9, 0.3, 1, ...playerCoords), + new ClumpPlacer(mapArea * 0.03 / (isNomad() ? 2 : 1), 0.9, 0.3, 1, ...playerCoords), [ new LayeredPainter([g_Terrains.cliff, base], [3]), new SmoothElevationPainter(ELEVATION_SET, denHeight, 3), diff --git a/binaries/data/mods/public/maps/random/lorraine_plain.js b/binaries/data/mods/public/maps/random/lorraine_plain.js index 6f5b9f4e6f..2379beb000 100644 --- a/binaries/data/mods/public/maps/random/lorraine_plain.js +++ b/binaries/data/mods/public/maps/random/lorraine_plain.js @@ -298,6 +298,8 @@ createObjectGroupsDeprecated(group, 0, 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); diff --git a/binaries/data/mods/public/maps/random/mainland.js b/binaries/data/mods/public/maps/random/mainland.js index dcb57aacd0..1dabe182ea 100644 --- a/binaries/data/mods/public/maps/random/mainland.js +++ b/binaries/data/mods/public/maps/random/mainland.js @@ -191,4 +191,6 @@ createStragglerTrees( clForest, stragglerTrees); +placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); + ExportMap(); diff --git a/binaries/data/mods/public/maps/random/migration.js b/binaries/data/mods/public/maps/random/migration.js index 5e640bfa2a..a76180d1a2 100644 --- a/binaries/data/mods/public/maps/random/migration.js +++ b/binaries/data/mods/public/maps/random/migration.js @@ -58,6 +58,7 @@ var clMetal = createTileClass(); var clFood = createTileClass(); var clBaseResource = createTileClass(); var clLand = createTileClass(); +var clIsland = createTileClass(); var landHeight = 3; @@ -79,9 +80,13 @@ for (let i = 0; i < numPlayers; ++i) [ new LayeredPainter([tWater, tShore, tMainTerrain], [1, 4]), new SmoothElevationPainter(ELEVATION_SET, landHeight, 4), - paintClass(clPlayer) + paintClass(clIsland), + paintClass(isNomad() ? clLand : clPlayer) ]); + if (isNomad()) + continue; + let dockLocation = findLocationInDirectionBasedOnHeight(playerPosition, mapCenter, -3 , 2.6, 3); placeObject(dockLocation.x, dockLocation.y, oDock, playerIDs[i], playerAngle[i] + Math.PI); } @@ -130,7 +135,7 @@ createArea( new SmoothElevationPainter(ELEVATION_SET, landHeight, 4), paintClass(clLand) ], - avoidClasses(clPlayer, 8)); + avoidClasses(clIsland, 8)); Engine.SetProgress(20); log("Creating shore jaggedness..."); @@ -143,7 +148,7 @@ createAreas( ], [ borderClasses(clLand, 6, 3), - avoidClasses(clPlayer, 8) + avoidClasses(clIsland, 8) ], scaleByMapSize(2, 15) * 20, 150); @@ -156,7 +161,7 @@ log("Creating bumps..."); createAreas( new ClumpPlacer(scaleByMapSize(20, 50), 0.3, 0.06, 1), new SmoothElevationPainter(ELEVATION_MODIFY, 2, 2), - [avoidClasses(clPlayer, 10), stayClasses(clLand, 3)], + [avoidClasses(clIsland, 10), stayClasses(clLand, 3)], scaleByMapSize(100, 200) ); Engine.SetProgress(30); @@ -169,7 +174,7 @@ createAreas( new SmoothElevationPainter(ELEVATION_SET, 18, 2), paintClass(clHill) ], - [avoidClasses(clPlayer, 10, clHill, 15), stayClasses(clLand, 7)], + [avoidClasses(clIsland, 10, clHill, 15), stayClasses(clLand, 7)], scaleByMapSize(1, 4) * numPlayers ); Engine.SetProgress(34); @@ -211,7 +216,7 @@ for (let size of [scaleByMapSize(3, 48), scaleByMapSize(5, 84), scaleByMapSize(8 clForest, 0, clHill, 0, clDirt, 5, - clPlayer, 0), + clIsland, 0), stayClasses(clLand, 7) ], scaleByMapSize(15, 45)); @@ -223,7 +228,7 @@ for (let size of [scaleByMapSize(2, 32), scaleByMapSize(3, 48), scaleByMapSize(5 createAreas( new ClumpPlacer(size, 0.3, 0.06, 0.5), new TerrainPainter(tTier4Terrain), - [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clPlayer, 0), stayClasses(clLand, 7)], + [avoidClasses(clForest, 0, clHill, 0, clDirt, 5, clIsland, 0), stayClasses(clLand, 7)], scaleByMapSize(15, 45)); Engine.SetProgress(46); @@ -362,4 +367,6 @@ setSunRotation(randFloat(0, 2 * Math.PI)); 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(); diff --git a/binaries/data/mods/public/maps/random/neareastern_badlands.js b/binaries/data/mods/public/maps/random/neareastern_badlands.js index 35b485b0a1..c808fb93ee 100644 --- a/binaries/data/mods/public/maps/random/neareastern_badlands.js +++ b/binaries/data/mods/public/maps/random/neareastern_badlands.js @@ -61,16 +61,17 @@ var hillHeight3 = 16; var [playerIDs, playerX, playerZ] = playerPlacementCircle(0.35); -for (let i = 0; i < numPlayers; ++i) - createArea( - new ClumpPlacer( - diskArea(defaultPlayerBaseRadius()), - 0.9, - 0.5, - 10, - Math.round(fractionToTiles(playerX[i])), - Math.round(fractionToTiles(playerZ[i]))), - paintClass(clPlayer)); +if (!isNomad()) + for (let i = 0; i < numPlayers; ++i) + createArea( + new ClumpPlacer( + diskArea(defaultPlayerBaseRadius()), + 0.9, + 0.5, + 10, + Math.round(fractionToTiles(playerX[i])), + Math.round(fractionToTiles(playerZ[i]))), + paintClass(clPlayer)); placePlayerBases({ "PlayerPlacement": [playerIDs, playerX, playerZ], @@ -350,6 +351,8 @@ createObjectGroupsDeprecated(group, 0, scaleByMapSize(16, 262) ); +placePlayersNomad(clPlayer, avoidClasses(clWater, 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); diff --git a/binaries/data/mods/public/maps/random/new_rms_test.js b/binaries/data/mods/public/maps/random/new_rms_test.js index c2d3a5a506..e627ec8523 100644 --- a/binaries/data/mods/public/maps/random/new_rms_test.js +++ b/binaries/data/mods/public/maps/random/new_rms_test.js @@ -2,8 +2,11 @@ Engine.LoadLibrary("rmgen"); InitMap(); -placePlayerBases({ - "PlayerPlacement": playerPlacementCircle(0.39) -}); +if (isNomad()) + placePlayersNomad(createTileClass()); +else + placePlayerBases({ + "PlayerPlacement": playerPlacementCircle(0.39) + }); ExportMap(); diff --git a/binaries/data/mods/public/maps/random/northern_lights.js b/binaries/data/mods/public/maps/random/northern_lights.js index 25f7628705..5c263e007b 100644 --- a/binaries/data/mods/public/maps/random/northern_lights.js +++ b/binaries/data/mods/public/maps/random/northern_lights.js @@ -35,6 +35,7 @@ var clPlayer = createTileClass(); var clHill = createTileClass(); var clForest = createTileClass(); var clWater = createTileClass(); +var clIsland = createTileClass(); var clDirt = createTileClass(); var clRock = createTileClass(); var clMetal = createTileClass(); @@ -108,6 +109,7 @@ createAreas( [ new LayeredPainter([tSnowA, tSnowA], [3]), new SmoothElevationPainter(ELEVATION_SET, 3, 3), + paintClass(clIsland), unPaintClass(clWater) ], stayClasses(clWater, 7), @@ -264,6 +266,8 @@ createObjectGroupsDeprecated(group, 0, 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); diff --git a/binaries/data/mods/public/maps/random/oasis.js b/binaries/data/mods/public/maps/random/oasis.js index 6a2680dfd1..c66b6f9722 100644 --- a/binaries/data/mods/public/maps/random/oasis.js +++ b/binaries/data/mods/public/maps/random/oasis.js @@ -315,6 +315,8 @@ for (var sandx = 0; sandx < mapSize; sandx += 4) } } +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); diff --git a/binaries/data/mods/public/maps/random/persian_highlands.js b/binaries/data/mods/public/maps/random/persian_highlands.js index 0ee171959d..34e42267c9 100644 --- a/binaries/data/mods/public/maps/random/persian_highlands.js +++ b/binaries/data/mods/public/maps/random/persian_highlands.js @@ -323,4 +323,6 @@ setPPContrast(0.75); setPPSaturation(0.45); setPPBloom(0.3); +placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); + ExportMap(); diff --git a/binaries/data/mods/public/maps/random/phoenician_levant.js b/binaries/data/mods/public/maps/random/phoenician_levant.js index 5b7e301a38..7a19a51eaa 100644 --- a/binaries/data/mods/public/maps/random/phoenician_levant.js +++ b/binaries/data/mods/public/maps/random/phoenician_levant.js @@ -177,7 +177,8 @@ createAreas( [ new LayeredPainter([tShore, tHill], [12]), new SmoothElevationPainter(ELEVATION_SET, 6, 8), - paintClass(clIsland) + paintClass(clIsland), + unPaintClass(clWater) ], [stayClasses (clWater, 8)], 1, @@ -318,4 +319,6 @@ 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(); diff --git a/binaries/data/mods/public/maps/random/polar_sea.js b/binaries/data/mods/public/maps/random/polar_sea.js index 312deb1235..0134671499 100644 --- a/binaries/data/mods/public/maps/random/polar_sea.js +++ b/binaries/data/mods/public/maps/random/polar_sea.js @@ -45,14 +45,19 @@ var clArcticWolf = createTileClass(); var [playerIDs, playerX, playerZ] = playerPlacementCircle(0.35); +var treasures = [{ + "template": oWoodTreasure, + "count": isNomad() ? 16 : 14 +}]; + log("Creating player markets..."); -var marketDist = 12; -for (let i = 0; i < numPlayers; ++i) -{ - let marketPos = Vector2D.add(new Vector2D(playerX[i], playerZ[i]).mult(mapSize), new Vector2D(marketDist, 0).rotate(randFloat(0, 2 * Math.PI))).round(); - placeObject(marketPos.x, marketPos.y, oMarket, playerIDs[i], BUILDING_ORIENTATION); - addCivicCenterAreaToClass(marketPos.x, marketPos.y, clBaseResource); -} +if (!isNomad()) + for (let i = 0; i < numPlayers; ++i) + { + let marketPos = Vector2D.add(new Vector2D(playerX[i], playerZ[i]).mult(mapSize), new Vector2D(12, 0).rotate(randFloat(0, 2 * Math.PI))).round(); + placeObject(marketPos.x, marketPos.y, oMarket, playerIDs[i], BUILDING_ORIENTATION); + addCivicCenterAreaToClass(marketPos.x, marketPos.y, clBaseResource); + } placePlayerBases({ "PlayerPlacement": [playerIDs, playerX, playerZ], @@ -74,12 +79,7 @@ placePlayerBases({ ] }, "Treasures": { - "types": [ - { - "template": oWoodTreasure, - "count": 14 - } - ] + "types": treasures }, }); Engine.SetProgress(30); @@ -216,7 +216,7 @@ Engine.SetProgress(80); createFood( [ [new SimpleObject(oArcticFox, 1, 2, 0, 3)], - [new SimpleObject(oArcticWolf, 4, 6, 0, 4)], + [new SimpleObject(isNomad() ? oArcticFox : oArcticWolf, 4, 6, 0, 4)], [new SimpleObject(oWalrus, 2, 3, 0, 2)], [new SimpleObject(oMuskox, 2, 3, 0, 2)] ], @@ -275,6 +275,22 @@ else setSunElevation(Math.PI * randFloat(1/9, 1/7)); } +if (isNomad()) +{ + let constraint = avoidClasses(clWater, 4, clMetal, 4, clRock, 4, clHill, 4, clFood, 2); + [playerIDs, playerX, playerZ] = placePlayersNomad(clPlayer, constraint); + + for (let i = 0; i < numPlayers; ++i) + placePlayerBaseTreasures({ + "playerID": playerIDs[i], + "playerX": tilesToFraction(playerX[i]), + "playerZ": tilesToFraction(playerZ[i]), + "BaseResourceClass": clBaseResource, + "baseResourceConstraint": constraint, + "types": treasures + }); +} + setSunRotation(randFloat(0, 2 * Math.PI)); setWaterColor(0.3, 0.3, 0.4); diff --git a/binaries/data/mods/public/maps/random/pyrenean_sierra.js b/binaries/data/mods/public/maps/random/pyrenean_sierra.js index 048aaac696..edc847df01 100644 --- a/binaries/data/mods/public/maps/random/pyrenean_sierra.js +++ b/binaries/data/mods/public/maps/random/pyrenean_sierra.js @@ -449,6 +449,8 @@ 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(randFloat(0, 2 * Math.PI)); diff --git a/binaries/data/mods/public/maps/random/rhine_marshlands.js b/binaries/data/mods/public/maps/random/rhine_marshlands.js index 5f08e6dee2..645cc0bf36 100644 --- a/binaries/data/mods/public/maps/random/rhine_marshlands.js +++ b/binaries/data/mods/public/maps/random/rhine_marshlands.js @@ -284,6 +284,8 @@ createObjectGroupsDeprecated( 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 diff --git a/binaries/data/mods/public/maps/random/river_archipelago.js b/binaries/data/mods/public/maps/random/river_archipelago.js index 05f7c8a007..d1ac4cf294 100644 --- a/binaries/data/mods/public/maps/random/river_archipelago.js +++ b/binaries/data/mods/public/maps/random/river_archipelago.js @@ -141,37 +141,40 @@ placePlayerBases({ }); Engine.SetProgress(35); -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); - 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), @@ -463,6 +466,8 @@ createObjectGroupsDeprecated( 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); diff --git a/binaries/data/mods/public/maps/random/rivers.js b/binaries/data/mods/public/maps/random/rivers.js index 7400823600..06ecc5a98f 100644 --- a/binaries/data/mods/public/maps/random/rivers.js +++ b/binaries/data/mods/public/maps/random/rivers.js @@ -116,10 +116,11 @@ createArea( null); log("Creating rivers between opponents..."); -let rivers = distributePointsOnCircle(numPlayers, startAngle + Math.PI / numPlayers, fractionToTiles(0.5), mapCenter)[0]; -for (let i = 0; i < numPlayers; ++i) +let numRivers = isNomad() ? randIntInclusive(4, 8) : numPlayers; +let rivers = distributePointsOnCircle(numPlayers, startAngle + Math.PI / numRivers, fractionToTiles(0.5), mapCenter)[0]; +for (let i = 0; i < numRivers; ++i) { - if (areAllies(playerIDs[i], playerIDs[(i + 1) % numPlayers])) + if (isNomad() ? randBool() : areAllies(playerIDs[i], playerIDs[(i + 1) % numPlayers])) continue; let shallowLocation = randFloat(0.2, 0.7); @@ -291,6 +292,8 @@ createStragglerTrees( clForest, stragglerTrees); +placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clForest, 1, clMetal, 4, clRock, 4, clFood, 2)); + setWaterWaviness(3.0); setWaterType("lake"); diff --git a/binaries/data/mods/public/maps/random/rmgen/library.js b/binaries/data/mods/public/maps/random/rmgen/library.js index 8a047bb72c..b8755de454 100644 --- a/binaries/data/mods/public/maps/random/rmgen/library.js +++ b/binaries/data/mods/public/maps/random/rmgen/library.js @@ -314,6 +314,11 @@ function getMapCenter() return deepfreeze(new Vector2D(g_Map.size / 2, g_Map.size / 2)); } +function isNomad() +{ + return !!g_MapSettings.Nomad; +} + function getNumPlayers() { return g_MapSettings.PlayerData.length - 1; diff --git a/binaries/data/mods/public/maps/random/rmgen/player.js b/binaries/data/mods/public/maps/random/rmgen/player.js index 0dc294be8b..36c3bcd8f3 100644 --- a/binaries/data/mods/public/maps/random/rmgen/player.js +++ b/binaries/data/mods/public/maps/random/rmgen/player.js @@ -2,6 +2,13 @@ * @file These functions locate and place the starting entities of players. */ +var g_NomadTreasureTemplates = { + "food": "gaia/special_treasure_food_jars", + "wood": "gaia/special_treasure_wood", + "stone": "gaia/special_treasure_stone", + "metal": "gaia/special_treasure_metal" +}; + /** * These are identifiers of functions that can generate parts of a player base. * There must be a function starting with placePlayerBase and ending with this name. @@ -106,6 +113,9 @@ function placePlayerBases(playerBaseArgs) */ function placePlayerBase(playerBaseArgs) { + if (isNomad()) + return; + log("Creating base for player " + playerBaseArgs.playerID + "..."); let fx = fractionToTiles(playerBaseArgs.playerX); @@ -400,6 +410,58 @@ function placePlayerBaseDecoratives(args) } } +function placePlayersNomad(playerClass, constraints) +{ + if (!isNomad()) + return; + + let distance = scaleByMapSize(60, 240); + let constraint = new AndConstraint(constraints); + + let numPlayers = getNumPlayers(); + let playerIDs = shuffleArray(sortAllPlayers()); + let playerX = []; + let playerZ = []; + + for (let i = 0; i < numPlayers; ++i) + { + log("Determine starting units for player " + playerIDs[i] + "..."); + let objects = getStartingEntities(playerIDs[i]).filter(ents => ents.Template.startsWith("units/")).map( + ents => new SimpleObject(ents.Template, ents.Count || 1, ents.Count || 1, 1, 3)); + + log("Ensure resources for a civic center..."); + let ccCost = Engine.GetTemplate("structures/" + getCivCode(playerIDs[i]) + "_civil_centre").Cost.Resources; + for (let resourceType in ccCost) + { + let treasureTemplate = g_NomadTreasureTemplates[resourceType]; + + let count = Math.max(0, Math.ceil( + (ccCost[resourceType] - (g_MapSettings.StartingResources || 0)) / + Engine.GetTemplate(treasureTemplate).ResourceSupply.Amount)); + + objects.push(new SimpleObject(treasureTemplate, count, count, 3, 5)); + } + + log("Placing player units..."); + let group = new SimpleGroup(objects, true, playerClass); + let success = false; + for (let distanceFactor of [1, 1/2, 1/4, 0]) + { + if (createObjectGroups(group, playerIDs[i], new AndConstraint([constraint, avoidClasses(playerClass, distance * distanceFactor)]), 1, 200, false)) + { + success = true; + playerX[i] = group.x; + playerZ[i] = group.z; + break; + } + } + if (!success) + throw new Error("Could not place starting units for player " + playerIDs[i] + "!"); + } + + return [playerIDs, playerX, playerZ]; +} + /** * Sorts an array of player IDs by team index. Players without teams come first. * Randomize order for players of the same team. diff --git a/binaries/data/mods/public/maps/random/saharan_oases.js b/binaries/data/mods/public/maps/random/saharan_oases.js index 118cdc4d95..6041df8be0 100644 --- a/binaries/data/mods/public/maps/random/saharan_oases.js +++ b/binaries/data/mods/public/maps/random/saharan_oases.js @@ -224,6 +224,8 @@ createObjectGroupsDeprecated(group, 0, 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); diff --git a/binaries/data/mods/public/maps/random/sahel.js b/binaries/data/mods/public/maps/random/sahel.js index b8de4c46b4..4534cd9449 100644 --- a/binaries/data/mods/public/maps/random/sahel.js +++ b/binaries/data/mods/public/maps/random/sahel.js @@ -219,6 +219,8 @@ createObjectGroupsDeprecated(group, 0, scaleByMapSize(100, 1200) ); +placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clHill, 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); diff --git a/binaries/data/mods/public/maps/random/sahel_watering_holes.js b/binaries/data/mods/public/maps/random/sahel_watering_holes.js index 3cc3246836..6facb5c34f 100644 --- a/binaries/data/mods/public/maps/random/sahel_watering_holes.js +++ b/binaries/data/mods/public/maps/random/sahel_watering_holes.js @@ -372,6 +372,8 @@ createObjectGroupsDeprecated(group, 0, planetm * scaleByMapSize(13, 200), 50 ); +placePlayersNomad(clPlayer, avoidClasses(clWater, 4, clHill, 4, clForest, 1, clMetal, 4, clRock, 4, clFood, 2)); + setSkySet("sunny"); setSunRotation(randFloat(0, 2 * Math.PI)); diff --git a/binaries/data/mods/public/maps/random/schwarzwald.js b/binaries/data/mods/public/maps/random/schwarzwald.js index dabfd9537a..7f10389be0 100644 --- a/binaries/data/mods/public/maps/random/schwarzwald.js +++ b/binaries/data/mods/public/maps/random/schwarzwald.js @@ -405,6 +405,8 @@ for (var x = 0; x < mapSize; x++) 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(); diff --git a/binaries/data/mods/public/maps/random/snowflake_searocks.js b/binaries/data/mods/public/maps/random/snowflake_searocks.js index cec5f843c9..a5ec8924b0 100644 --- a/binaries/data/mods/public/maps/random/snowflake_searocks.js +++ b/binaries/data/mods/public/maps/random/snowflake_searocks.js @@ -214,7 +214,7 @@ log("Creating player islands..."); for (let i = 0; i < numPlayers; ++i) { islandPos[i] = new Vector2D(playerX[i], playerZ[i]).mult(mapSize).round(); - createIsland(i, 1, clPlayer); + createIsland(i, 1, isNomad() ? clLand : clPlayer); } placePlayerBases({ @@ -426,6 +426,13 @@ createObjectGroupsDeprecated(group, 0, 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(randFloat(0, 2 * Math.PI)); setSunElevation(Math.PI * randFloat(1/5, 1/3)); diff --git a/binaries/data/mods/public/maps/random/stronghold.js b/binaries/data/mods/public/maps/random/stronghold.js index 6548367212..8c6f5d3714 100644 --- a/binaries/data/mods/public/maps/random/stronghold.js +++ b/binaries/data/mods/public/maps/random/stronghold.js @@ -239,4 +239,15 @@ addElements(shuffleArray([ ])); 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(); diff --git a/binaries/data/mods/public/maps/random/syria.js b/binaries/data/mods/public/maps/random/syria.js index 9f8de83861..13ee91b40f 100644 --- a/binaries/data/mods/public/maps/random/syria.js +++ b/binaries/data/mods/public/maps/random/syria.js @@ -52,13 +52,22 @@ for (let i = 0; i < numPlayers; ++i) let iz = Math.round(fractionToTiles(playerZ[i])); log("Marking player territory larger than the city patch..."); - createArea( - new ClumpPlacer(diskArea(scaleByMapSize(15, 25)), 0.9, 0.5, 10, ix, iz), - paintClass(clPlayer)); + if (!isNomad()) + createArea( + new ClumpPlacer(diskArea(defaultPlayerBaseRadius()), 0.9, 0.5, 10, ix, iz), + 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)), 1, ix, iz, 0, [Math.floor(scaleByMapSize(16, 30))]), + new ChainPlacer( + 2, + Math.floor(scaleByMapSize(5, 12)), + Math.floor(scaleByMapSize(25, 60)) / (isNomad() ? 2 : 1), + 1, + ix, + iz, + 0, + [Math.floor(scaleByMapSize(16, 30))]), [ new LayeredPainter([tGrassSands, tGrass], [3]), paintClass(clGrass) @@ -243,7 +252,9 @@ createStragglerTrees( [oPalm, oTamarix, oPine], [avoidClasses(clForest, 1, clHill, 1, clPlayer, 1, clMetal, 6, clRock, 6), stayClasses(clGrass, 3)], clForest, - stragglerTrees); + stragglerTrees * (isNomad() ? 3 : 1)); + +placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); setSkySet("sunny"); setSunElevation(Math.PI / 8); diff --git a/binaries/data/mods/public/maps/random/the_nile.js b/binaries/data/mods/public/maps/random/the_nile.js index 1810149e8a..93af799b8f 100644 --- a/binaries/data/mods/public/maps/random/the_nile.js +++ b/binaries/data/mods/public/maps/random/the_nile.js @@ -384,6 +384,8 @@ createObjectGroupsDeprecated( 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); diff --git a/binaries/data/mods/public/maps/random/the_unknown/unknown_common.js b/binaries/data/mods/public/maps/random/the_unknown/unknown_common.js index 169aacaf7f..c3a2cc6657 100644 --- a/binaries/data/mods/public/maps/random/the_unknown/unknown_common.js +++ b/binaries/data/mods/public/maps/random/the_unknown/unknown_common.js @@ -2,11 +2,6 @@ * @file This library is used to generate different map variations on the map Unknown, Unknown Land and Unknown Nomad. */ -/** - * True if city centers should be placed or false for nomad. - */ -var g_PlayerBases; - /** * True if all players should be connected via land and false if river or islands can split some if not all the players. */ @@ -122,7 +117,9 @@ function createUnknownMap() paintUnknownMapBasedOnHeight(); - if (g_PlayerBases) + if (isNomad()) + placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4, clFood, 2)); + else createUnknownPlayerBases(); } @@ -135,7 +132,7 @@ function unknownArchipelago() g_StartingTreasures = true; let [pIDs, islandX, islandZ] = playerPlacementCircle(0.35); - if (g_PlayerBases) + if (!isNomad()) { [playerIDs, playerX, playerZ] = [pIDs, islandX, islandZ]; markPlayerArea("large"); @@ -148,7 +145,7 @@ function unknownArchipelago() new ClumpPlacer(islandSize, 0.8, 0.1, 10, fractionToTiles(islandX[i]), fractionToTiles(islandZ[i])), landElevationPainter); - let type = randIntInclusive(1, 3); + let type = isNomad() ? randIntInclusive(1, 2) : randIntInclusive(1, 3); if (type == 1) { log("Creating archipelago..."); @@ -216,7 +213,7 @@ function unknownContinent() { let waterHeight = -5; - if (g_PlayerBases) + if (!isNomad()) { log("Ensuring player area..."); [playerIDs, playerX, playerZ] = playerPlacementCircle(0.25); @@ -311,7 +308,7 @@ function unknownCentralSea() } }); - if (g_PlayerBases) + if (!isNomad()) { [playerIDs, playerX, playerZ] = playerPlacementRiver(horizontal ? Math.PI / 2 : 0, 0.6); markPlayerArea("small"); @@ -354,7 +351,7 @@ function unknownCentralRiver() let horizontal = randBool(); let riverAngle = horizontal ? 0 : Math.PI / 2; - if (g_PlayerBases) + if (!isNomad()) { [playerIDs, playerX, playerZ] = playerPlacementRiver(horizontal ? Math.PI / 2 : 0, 0.5); markPlayerArea("large"); @@ -416,7 +413,7 @@ function unknownRiversAndLake() initHeight(landHeight); let startAngle; - if (g_PlayerBases) + if (!isNomad()) { let playerAngle; [playerIDs, playerX, playerZ, playerAngle, startAngle] = playerPlacementCircle(0.35); @@ -438,7 +435,7 @@ function unknownRiversAndLake() } // Don't do this on nomad because the imbalances on the different islands are too drastic - if (g_PlayerBases && (!lake || randBool(1/3))) + 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]) @@ -469,7 +466,7 @@ function unknownRiversAndLake() ]); } - if (lake && randBool()) + if (!isNomad && lake && randBool()) { log("Creating small central island..."); createArea( @@ -490,7 +487,7 @@ function unknownEdgeSeas() initHeight(landHeight); let horizontal = randBool(); - if (g_PlayerBases) + if (!isNomad()) { [playerIDs, playerX, playerZ] = playerPlacementLine(horizontal, 0.5, 0.2); // Don't place the shoreline inside the CC, but possibly into the players territory @@ -535,7 +532,7 @@ function unknownGulf() initHeight(landHeight); let startAngle = randFloat(0, 2) * Math.PI; - if (g_PlayerBases) + if (!isNomad()) { log("Determining player locations..."); @@ -573,7 +570,7 @@ function unknownLakes() initHeight(landHeight); - if (g_PlayerBases) + if (!isNomad()) { [playerIDs, playerX, playerZ] = playerPlacementCircle(0.35); markPlayerArea("large"); @@ -601,7 +598,7 @@ function unknownPasses() let playerAngle; let startAngle; - if (g_PlayerBases) + if (!isNomad()) { [playerIDs, playerX, playerZ, playerAngle, startAngle] = playerPlacementCircle(0.35); markPlayerArea("small"); @@ -680,7 +677,7 @@ function unknownLowlands() let playerAngle; let startAngle; - if (g_PlayerBases) + if (!isNomad()) { [playerIDs, playerX, playerZ, playerAngle, startAngle] = playerPlacementCircle(0.35); markPlayerArea("small"); @@ -732,7 +729,7 @@ function unknownMainland() { initHeight(3); - if (g_PlayerBases) + if (!isNomad()) { [playerIDs, playerX, playerZ] = playerPlacementCircle(0.35); markPlayerArea("small"); diff --git a/binaries/data/mods/public/maps/random/unknown.js b/binaries/data/mods/public/maps/random/unknown.js index 9d17727243..e8cd4d9cda 100644 --- a/binaries/data/mods/public/maps/random/unknown.js +++ b/binaries/data/mods/public/maps/random/unknown.js @@ -2,7 +2,6 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmbiome"); Engine.LoadLibrary("the_unknown"); -g_PlayerBases = true; g_AllowNaval = true; createUnknownMap(); diff --git a/binaries/data/mods/public/maps/random/unknown_land.js b/binaries/data/mods/public/maps/random/unknown_land.js index 46042e17d9..b26e4c9dc3 100644 --- a/binaries/data/mods/public/maps/random/unknown_land.js +++ b/binaries/data/mods/public/maps/random/unknown_land.js @@ -2,7 +2,6 @@ Engine.LoadLibrary("rmgen"); Engine.LoadLibrary("rmbiome"); Engine.LoadLibrary("the_unknown"); -g_PlayerBases = true; g_AllowNaval = false; createUnknownMap(); diff --git a/binaries/data/mods/public/maps/random/unknown_nomad.js b/binaries/data/mods/public/maps/random/unknown_nomad.js deleted file mode 100644 index 2112480b72..0000000000 --- a/binaries/data/mods/public/maps/random/unknown_nomad.js +++ /dev/null @@ -1,126 +0,0 @@ -Engine.LoadLibrary("rmgen"); -Engine.LoadLibrary("rmbiome"); -Engine.LoadLibrary("the_unknown"); - -g_PlayerBases = false; -g_AllowNaval = true; - -createUnknownMap(); - -var distmin = Math.square(scaleByMapSize(60, 240)); -playerIDs = sortAllPlayers(); - -for (var i = 0; i < numPlayers; i++) -{ - var placableArea = []; - for (var mx = 0; mx < mapSize; mx++) - { - for (var mz = 0; mz < mapSize; mz++) - { - if (!g_Map.validT(mx, mz, 3)) - continue; - - var placable = true; - for (var c = 0; c < i; c++) - if ((playerX[c] - mx)*(playerX[c] - mx) + (playerZ[c] - mz)*(playerZ[c] - mz) < distmin) - placable = false; - if (!placable) - continue; - - if (g_Map.getHeight(mx, mz) >= 3 && g_Map.getHeight(mx, mz) <= 3.12) - placableArea.push([mx, mz]); - } - } - - if (!placableArea.length) - { - for (var mx = 0; mx < mapSize; ++mx) - { - for (var mz = 0; mz < mapSize; mz++) - { - if (!g_Map.validT(mx, mz, 3)) - continue; - - var placable = true; - for (var c = 0; c < i; c++) - if ((playerX[c] - mx)*(playerX[c] - mx) + (playerZ[c] - mz)*(playerZ[c] - mz) < distmin/4) - placable = false; - if (!placable) - continue; - - if (g_Map.getHeight(mx, mz) >= 3 && g_Map.getHeight(mx, mz) <= 3.12) - placableArea.push([mx, mz]); - } - } - } - - if (!placableArea.length) - for (var mx = 0; mx < mapSize; ++mx) - for (var mz = 0; mz < mapSize; ++mz) - if (g_Map.getHeight(mx, mz) >= 3 && g_Map.getHeight(mx, mz) <= 3.12) - placableArea.push([mx, mz]); - - [playerX[i], playerZ[i]] = pickRandom(placableArea); -} - -for (var i = 0; i < numPlayers; ++i) -{ - var id = playerIDs[i]; - log("Creating units for player " + id + "..."); - - // get the x and z in tiles - var ix = playerX[i]; - var iz = playerZ[i]; - - playerX[i] = tilesToFraction(playerX[i]); - playerZ[i] = tilesToFraction(playerZ[i]); - - var civEntities = getStartingEntities(playerIDs[i]); - var angle = randFloat(0, 2 * Math.PI); - for (var j = 0; j < civEntities.length; ++j) - { - // TODO: Make an rmlib function to get only non-structure starting entities and loop over those - if (!civEntities[j].Template.startsWith("units/")) - continue; - - var count = civEntities[j].Count || 1; - var jx = ix + 2 * Math.cos(angle); - var jz = iz + 2 * Math.sin(angle); - var kAngle = randFloat(0, 2 * Math.PI); - for (var k = 0; k < count; ++k) - placeObject(jx + Math.cos(kAngle + k*2 * Math.PI/count), jz + Math.sin(kAngle + k*2 * Math.PI/count), civEntities[j].Template, id, randFloat(0, 2 * Math.PI)); - angle += 2 * Math.PI / 3; - } - - { - if (g_MapSettings.StartingResources < 500) - { - var loop = (g_MapSettings.StartingResources < 200) ? 2 : 1; - for (let l = 0; l < loop; ++l) - { - var angle = randFloat(0, 2 * Math.PI); - var rad = randFloat(3, 5); - var jx = ix + rad * Math.cos(angle); - var jz = iz + rad * Math.sin(angle); - placeObject(jx, jz, "gaia/special_treasure_wood", 0, randFloat(0, 2 * Math.PI)); - var angle = randFloat(0, 2 * Math.PI); - var rad = randFloat(3, 5); - var jx = ix + rad * Math.cos(angle); - var jz = iz + rad * Math.sin(angle); - placeObject(jx, jz, "gaia/special_treasure_stone", 0, randFloat(0, 2 * Math.PI)); - var angle = randFloat(0, 2 * Math.PI); - var rad = randFloat(3, 5); - var jx = ix + rad * Math.cos(angle); - var jz = iz + rad * Math.sin(angle); - placeObject(jx, jz, "gaia/special_treasure_metal", 0, randFloat(0, 2 * Math.PI)); - } - } - } -} - -// Don't place resources into the starting units -markPlayerArea("small"); - -createUnknownObjects(); - -ExportMap(); diff --git a/binaries/data/mods/public/maps/random/unknown_nomad.json b/binaries/data/mods/public/maps/random/unknown_nomad.json deleted file mode 100644 index f5e6f0305a..0000000000 --- a/binaries/data/mods/public/maps/random/unknown_nomad.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "settings" : { - "Name" : "Unknown Nomad", - "Script" : "unknown_nomad.js", - "Description" : "The unknown. Players start with only some citizen soldiers and female citizens. [color=\"red\"]Warning: The starting resources should be set at least at Medium.[/color]", - "BaseTerrain" : ["medit_sand_wet"], - "BaseHeight" : -5, - "Preview" : "unknown.png", - "SupportedBiomes": true, - "CircularMap" : true - } -} diff --git a/binaries/data/mods/public/maps/random/volcanic_lands.js b/binaries/data/mods/public/maps/random/volcanic_lands.js index 82f8d4d25e..8c00aa02b0 100644 --- a/binaries/data/mods/public/maps/random/volcanic_lands.js +++ b/binaries/data/mods/public/maps/random/volcanic_lands.js @@ -176,4 +176,6 @@ createStragglerTrees( clForest, stragglerTrees); +placePlayersNomad(clPlayer, avoidClasses(clForest, 1, clMetal, 4, clRock, 4, clHill, 4)); + ExportMap(); diff --git a/binaries/data/mods/public/maps/random/wild_lake.js b/binaries/data/mods/public/maps/random/wild_lake.js index 7c579373ee..9a2083128e 100644 --- a/binaries/data/mods/public/maps/random/wild_lake.js +++ b/binaries/data/mods/public/maps/random/wild_lake.js @@ -588,18 +588,19 @@ for (let i = 0; i < avoidPoints.length; ++i) let resourceSpots = getPointsByHeight(resourceSpotHeightRange, avoidPoints, clPath); Engine.SetProgress(55); -/** - * Add start locations and resource spots after terrain texture and path painting - */ -for (let p = 0; p < playerIDs.length; ++p) -{ - let point = startLocations[p]; - placeCivDefaultStartingEntities(point.x, point.y, playerIDs[p], g_Map.size > 192); - placeStartLocationResources(point); -} +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.x, point.y, playerIDs[p], g_Map.size > 192); + placeStartLocationResources(point); + } -let mercenaryCamps = Math.ceil(g_Map.size / 256); -log("Maximum number of mercenary camps: " + uneval(mercenaryCamps)); +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;