Index: binaries/data/mods/public/gui/common/settings.js =================================================================== --- binaries/data/mods/public/gui/common/settings.js +++ binaries/data/mods/public/gui/common/settings.js @@ -36,6 +36,7 @@ "GameSpeeds": loadSettingValuesFile("game_speeds.json"), "MapTypes": loadMapTypes(), "MapSizes": loadSettingValuesFile("map_sizes.json"), + "Biomes": loadSettingValuesFile("biomes.json"), "PlayerDefaults": loadPlayerDefaults(), "PopulationCapacities": loadPopulationCapacities(), "StartingResources": loadSettingValuesFile("starting_resources.json"), Index: binaries/data/mods/public/gui/gamesetup/gamesetup.js =================================================================== --- binaries/data/mods/public/gui/gamesetup/gamesetup.js +++ binaries/data/mods/public/gui/gamesetup/gamesetup.js @@ -203,6 +203,11 @@ var g_MapFilterList; /** + * This contains only filters that spam spam spam + */ +var g_BiomeList; + +/** * Whether this is a single- or multiplayer match. */ var g_IsNetworked; @@ -356,6 +361,7 @@ }, "more": { "Dropdown": [ + "biome", "gameSpeed", "victoryCondition", "relicCount", @@ -479,6 +485,19 @@ "hidden": () => g_GameAttributes.mapType != "random", "autocomplete": 0, }, + "biome": { + "title": () => translate("Biome"), + "tooltip": (hoverIdx) => g_BiomeList && hoverIdx != -1 ? g_BiomeList.Description[hoverIdx] : translate("Select the flora and fauna."), + "labels": () => g_BiomeList ? g_BiomeList.Title : [], + "ids": () => g_BiomeList ? g_BiomeList.Id : [], + "default": () => 0, + "defined": () => g_GameAttributes.settings.Biome !== undefined, + "get": () => g_GameAttributes.settings.Biome, + "select": (idx) => { + g_GameAttributes.settings.Biome = g_BiomeList && g_BiomeList.Id[idx]; + }, + "hidden": () => !g_BiomeList, + }, "numPlayers": { "title": () => translate("Number of Players"), "tooltip": (hoverIdx) => translate("Select number of players."), @@ -1449,6 +1468,35 @@ initDropdown("mapSelection"); } +function reloadBiomeList() +{ + let biomeList; + + if (g_GameAttributes.mapType == "random" && g_GameAttributes.settings.SupportedBiomes) + { + if (g_GameAttributes.settings.SupportedBiomes === true) + biomeList = g_Settings.Biomes; + else + { + biomeList = g_Settings.Biomes.filter( + biome => g_GameAttributes.settings.SupportedBiomes.indexOf(biome.Id) != -1); + + for (let biome of g_GameAttributes.settings.SupportedBiomes) + if (g_Settings.Biomes.every(bio => bio.Id != biome)) + warn("Map '" + g_GameAttributes.map + "' contains unknown biome '" + biome + "'") + } + } + + g_BiomeList = biomeList && prepareForDropdown( + [{ + "Id": "random", + "Title": translateWithContext("biome", "Random"), + "Description": translate("Pick a biome at random.") + }].concat(biomeList)); + + initDropdown("biome"); +} + function loadMapData(name) { if (!name || !g_MapPath[g_GameAttributes.mapType]) @@ -1514,6 +1562,7 @@ // Reload, as the maptype or mapfilter might have changed reloadMapFilterList(); + reloadBiomeList(); g_GameAttributes.settings.RatingEnabled = Engine.HasXmppClient(); Engine.SetRankedGame(g_GameAttributes.settings.RatingEnabled); @@ -1649,7 +1698,7 @@ function selectMap(name) { // Reset some map specific properties which are not necessarily redefined on each map - for (let prop of ["TriggerScripts", "CircularMap", "Garrison", "DisabledTemplates"]) + for (let prop of ["TriggerScripts", "CircularMap", "Garrison", "DisabledTemplates", "Biome", "SupportedBiomes"]) g_GameAttributes.settings[prop] = undefined; let mapData = loadMapData(name); @@ -1680,6 +1729,7 @@ for (let prop in mapSettings) g_GameAttributes.settings[prop] = mapSettings[prop]; + reloadBiomeList(); unassignInvalidPlayers(g_GameAttributes.settings.PlayerData.length); supplementDefaults(); } @@ -1801,6 +1851,9 @@ g_GameAttributes.settings.GameType = gameTypeSelected; } + if (g_GameAttributes.settings.Biome == "random") + g_GameAttributes.settings.Biome = pickRandom(g_GameAttributes.settings.SupportedBiomes); + g_GameAttributes.settings.TriggerScripts = g_GameAttributes.settings.VictoryScripts.concat(g_GameAttributes.settings.TriggerScripts || []); // Prevent reseting the readystate Index: binaries/data/mods/public/l10n/messages.json =================================================================== --- binaries/data/mods/public/l10n/messages.json +++ binaries/data/mods/public/l10n/messages.json @@ -565,6 +565,7 @@ { "extractor": "json", "filemasks": [ + "simulation/data/settings/biomes.json", "simulation/data/settings/victory_conditions/*.json" ], "options": { Index: binaries/data/mods/public/maps/random/amazon.js =================================================================== --- binaries/data/mods/public/maps/random/amazon.js +++ binaries/data/mods/public/maps/random/amazon.js @@ -7,7 +7,7 @@ InitMap(); log("Initializing tile classes..."); -setBiome(7); +setBiome(g_BiomeTropic); initMapSettings(); initTileClasses(); Index: binaries/data/mods/public/maps/random/ambush.js =================================================================== --- binaries/data/mods/public/maps/random/ambush.js +++ binaries/data/mods/public/maps/random/ambush.js @@ -3,7 +3,7 @@ InitMap(); -randomizeBiome(); +setSelectedBiome(); initMapSettings(); initTileClasses(); Index: binaries/data/mods/public/maps/random/ambush.json =================================================================== --- binaries/data/mods/public/maps/random/ambush.json +++ binaries/data/mods/public/maps/random/ambush.json @@ -5,7 +5,8 @@ "Description" : "High bluffs overlook the terrain below. Bountiful resources await on the cliffs, but beware of enemies planning an ambush.", "BaseTerrain" : ["medit_sea_depths"], "BaseHeight" : 2, - "Preview" : "ambush.png", + "Preview" : "ambush.png", + "SupportedBiomes": true, "CircularMap" : true } } Index: binaries/data/mods/public/maps/random/bahrain.js =================================================================== --- binaries/data/mods/public/maps/random/bahrain.js +++ binaries/data/mods/public/maps/random/bahrain.js @@ -7,7 +7,7 @@ InitMap(); log("Initializing tile classes..."); -setBiome(3); +setBiome(g_BiomeDesert); initMapSettings(); initTileClasses(["island"]); Index: binaries/data/mods/public/maps/random/flood.js =================================================================== --- binaries/data/mods/public/maps/random/flood.js +++ binaries/data/mods/public/maps/random/flood.js @@ -1,6 +1,6 @@ RMS.LoadLibrary("rmgen"); -let random_terrain = randomizeBiome([g_BiomeSavanna]); +setSelectedBiome(); const tMainTerrain = rBiomeT1(); const tForestFloor1 = rBiomeT2(); @@ -17,7 +17,7 @@ let tHill = rBiomeT8(); let tDirt = rBiomeT9(); -if (random_terrain == g_BiomeTemperate) +if (currentBiome() == g_BiomeTemperate) { tDirt = ["medit_shrubs_a", "grass_field"]; tHill = ["grass_field", "peat_temp"]; @@ -306,7 +306,7 @@ [avoidClasses(clPlayer, 25, clForest, 10, clBaseResource, 3, clMetal, 6, clRock, 3, clMountain, 2), stayClasses(clHill, 6)], clForest, 0.7, - random_terrain + currentBiome() ); log("Creating straggeler trees..."); @@ -317,7 +317,7 @@ log("Creating dirt patches..."); let sizes = [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)]; -let numb = random_terrain == g_BiomeSavanna ? 3 : 1; +let numb = currentBiome() == g_BiomeSavanna ? 3 : 1; for (let i = 0; i < sizes.length; ++i) { @@ -378,7 +378,7 @@ createStragglerTrees(types, avoidClasses(clWater, 5, clForest, 7, clMountain, 1, clPlayer, 30, clMetal, 6, clRock, 3)); log("Creating decoration..."); -let planetm = random_terrain == g_BiomeTropic ? 8 : 1; +let planetm = currentBiome() == g_BiomeTropic ? 8 : 1; createDecoration ( [ @@ -404,7 +404,7 @@ avoidClasses(clPlayer, 30, clHill, 10, clFood, 5), clForest, 0.1, - random_terrain + currentBiome() ); log("Creating small grass tufts..."); Index: binaries/data/mods/public/maps/random/flood.json =================================================================== --- binaries/data/mods/public/maps/random/flood.json +++ binaries/data/mods/public/maps/random/flood.json @@ -5,6 +5,15 @@ "Description" : "A great flood has moved across the valley enabling ships and troops to battle in chest deep waters.", "BaseTerrain" : ["medit_sand_wet"], "BaseHeight" : -2, + "SupportedBiomes": [ + "temperate", + "snowy", + "desert", + "alpine", + "mediterranean", + "tropic", + "autumn" + ], "Keywords": [], "Preview" : "flood.png", "CircularMap" : true Index: binaries/data/mods/public/maps/random/howe_sound.js =================================================================== --- binaries/data/mods/public/maps/random/howe_sound.js +++ binaries/data/mods/public/maps/random/howe_sound.js @@ -7,7 +7,7 @@ InitMap(); log("Initializing tile classes..."); -setBiome(2); +setBiome(g_BiomeSnowy); initMapSettings(); initTileClasses(["island"]); Index: binaries/data/mods/public/maps/random/island_stronghold.js =================================================================== --- binaries/data/mods/public/maps/random/island_stronghold.js +++ binaries/data/mods/public/maps/random/island_stronghold.js @@ -18,7 +18,7 @@ const g_InitialMineDistance = 14; const g_InitialTrees = 50; -let random_terrain = randomizeBiome([g_BiomeSavanna]); +setSelectedBiome(); const tMainTerrain = rBiomeT1(); const tForestFloor1 = rBiomeT2(); @@ -374,7 +374,7 @@ [avoidClasses(clPlayer, 10, clForest, 20, clHill, 10, clBaseResource, 5, clRock, 6, clMetal, 6), stayClasses(clLand, 3)], clForest, 1.0, - random_terrain + currentBiome() ); log("Creating hills..."); @@ -416,7 +416,7 @@ [avoidClasses(clForest, 0, clPlayer, 15, clHill, 1, clFood, 4, clRock, 6, clMetal, 6), stayClasses(clLand, 2)] ); -if (random_terrain == g_BiomeDesert) +if (currentBiome() == g_BiomeDesert) { log("Creating obelisks"); let group = new SimpleGroup( @@ -432,7 +432,7 @@ log("Creating dirt patches..."); let sizes = [scaleByMapSize(3, 6), scaleByMapSize(5, 10), scaleByMapSize(8, 21)]; -let numb = random_terrain == g_BiomeSavanna ? 3 : 1; +let numb = currentBiome() == g_BiomeSavanna ? 3 : 1; for (let i = 0; i < sizes.length; ++i) { @@ -528,7 +528,7 @@ placeDefaultDecoratives(fx, fz, aGrassShort, clBaseResource, radius, [stayClasses(clLand, 5)]); log("Creating small grass tufts..."); -let planetm = random_terrain == 7 ? 8 : 1; +let planetm = currentBiome() == 7 ? 8 : 1; group = new SimpleGroup( [new SimpleObject(aGrassShort, 1, 2, 0, 1, -PI / 8, PI / 8)] ); Index: binaries/data/mods/public/maps/random/island_stronghold.json =================================================================== --- binaries/data/mods/public/maps/random/island_stronghold.json +++ binaries/data/mods/public/maps/random/island_stronghold.json @@ -1,12 +1,21 @@ { - "settings" : { - "Name" : "Island Stronghold", - "Script" : "island_stronghold.js", - "Description" : "Teams start off with nearly adjacent civic centers on a small island, offering a fortified base from which to expand.", - "BaseTerrain" : ["medit_sand_wet"], - "BaseHeight" : -10, - "Keywords": ["naval"], - "Preview" : "island_stronghold.png", - "CircularMap" : true - } + "settings" : { + "Name" : "Island Stronghold", + "Script" : "island_stronghold.js", + "Description" : "Teams start off with nearly adjacent civic centers on a small island, offering a fortified base from which to expand.", + "BaseTerrain" : ["medit_sand_wet"], + "BaseHeight" : -10, + "Keywords": ["naval"], + "Preview" : "island_stronghold.png", + "SupportedBiomes": [ + "temperate", + "snowy", + "desert", + "alpine", + "mediterranean", + "tropic", + "autumn" + ], + "CircularMap" : true + } } Index: binaries/data/mods/public/maps/random/marmara.js =================================================================== --- binaries/data/mods/public/maps/random/marmara.js +++ binaries/data/mods/public/maps/random/marmara.js @@ -7,7 +7,7 @@ InitMap(); log("Initializing tile classes..."); -setBiome(5); +setBiome(g_BiomeMediterranean); initMapSettings(); initTileClasses(); Index: binaries/data/mods/public/maps/random/mediterranean.js =================================================================== --- binaries/data/mods/public/maps/random/mediterranean.js +++ binaries/data/mods/public/maps/random/mediterranean.js @@ -7,7 +7,7 @@ InitMap(); log("Initializing environment..."); -setBiome(1); +setBiome(g_BiomeTemperate); initMapSettings(); initTileClasses(["autumn", "desert", "medit", "polar", "steppe", "temp"]); Index: binaries/data/mods/public/maps/random/ngorongoro.js =================================================================== --- binaries/data/mods/public/maps/random/ngorongoro.js +++ binaries/data/mods/public/maps/random/ngorongoro.js @@ -7,7 +7,7 @@ InitMap(); log("Initializing tile classes..."); -setBiome(6); +setBiome(g_BiomeSavanna); initMapSettings(); initTileClasses(["eden", "highlands"]); Index: binaries/data/mods/public/maps/random/pompeii.js =================================================================== --- binaries/data/mods/public/maps/random/pompeii.js +++ binaries/data/mods/public/maps/random/pompeii.js @@ -7,7 +7,7 @@ InitMap(); log("Initializing tile classes..."); -setBiome(5); +setBiome(g_BiomeMediterranean); initMapSettings(); initTileClasses(["decorative", "lava"]); Index: binaries/data/mods/public/maps/random/ratumacos.js =================================================================== --- binaries/data/mods/public/maps/random/ratumacos.js +++ binaries/data/mods/public/maps/random/ratumacos.js @@ -7,7 +7,7 @@ InitMap(); log("Initializing tile classes..."); -setBiome(4); +setBiome(g_BiomeAlpine); initMapSettings(); initTileClasses(["shallowWater"]); Index: binaries/data/mods/public/maps/random/red_sea.js =================================================================== --- binaries/data/mods/public/maps/random/red_sea.js +++ binaries/data/mods/public/maps/random/red_sea.js @@ -7,7 +7,7 @@ InitMap(); log("Initializing biome..."); -setBiome(3); +setBiome(g_BiomeDesert); initMapSettings(); initTileClasses(); Index: binaries/data/mods/public/maps/random/rmgen/randombiome.js =================================================================== --- binaries/data/mods/public/maps/random/rmgen/randombiome.js +++ binaries/data/mods/public/maps/random/rmgen/randombiome.js @@ -1,11 +1,25 @@ -const g_BiomeTemperate = 1; -const g_BiomeSnowy = 2; -const g_BiomeDesert = 3; -const g_BiomeAlpine = 4; -const g_BiomeMediterranean = 5; -const g_BiomeSavanna = 6; -const g_BiomeTropic = 7; -const g_BiomeAutumn = 8; +/** + * Use constants as biome identifiers, so that we get reference errors if there is a typo. + */ +const g_BiomeTemperate = "temperate"; +const g_BiomeSnowy = "snowy"; +const g_BiomeDesert = "desert"; +const g_BiomeAlpine = "alpine"; +const g_BiomeMediterranean = "mediterranean"; +const g_BiomeSavanna = "savanna"; +const g_BiomeTropic = "tropic"; +const g_BiomeAutumn = "autumn"; + +const g_Biomes = [ + g_BiomeTemperate, + g_BiomeSnowy, + g_BiomeDesert, + g_BiomeAlpine, + g_BiomeMediterranean, + g_BiomeSavanna, + g_BiomeTropic, + g_BiomeAutumn +]; var g_BiomeID = g_BiomeTemperate; @@ -55,23 +69,35 @@ "tree": "actor|flora/trees/oak.xml" }; -/** - * Randomizes environment, optionally excluding some biome IDs. - */ -function randomizeBiome(avoid = []) +function currentBiome() { - let biomeIndex; - do - biomeIndex = randIntInclusive(1, 8); - while (avoid.indexOf(biomeIndex) != -1); + return g_BiomeID; +} - setBiome(biomeIndex); +function setSelectedBiome() +{ + if (g_Biomes.indexOf(g_MapSettings.Biome) == -1) + { + error("Can't set biome '" + g_MapSettings.Biome + "'"); + return; + } + + setBiome(g_MapSettings.Biome); +} - return biomeIndex; +function randomizeBiome() +{ + setBiome(pickRandom(g_Biomes)); + return g_BiomeID; } -function setBiome(biomeIndex) +function setBiome(biomeID) { + if (g_Biomes.indexOf(biomeID) == -1) + warn("Unknown biome: '" + biomeID + "'"); + else + g_BiomeID = biomeID; + setSkySet(pickRandom(["cirrus", "cumulus", "sunny"])); setSunRotation(randFloat(0, TWO_PI)); @@ -80,8 +106,6 @@ setUnitsAmbientColor(0.57, 0.58, 0.55); setTerrainAmbientColor(0.447059, 0.509804, 0.54902); - g_BiomeID = biomeIndex; - if (g_BiomeID == g_BiomeTemperate) { // temperate ocean blue, a bit too deep and saturated perhaps but it looks nicer. Index: binaries/data/mods/public/simulation/data/settings/biomes.json =================================================================== --- /dev/null +++ binaries/data/mods/public/simulation/data/settings/biomes.json @@ -0,0 +1,47 @@ +{ + "TranslatedKeys": ["Title", "Description"], + "Data": + [ + { + "Id": "temperate", + "Title": "Temperate", + "Description": "Temperate biome usually features a pleasant environment filled with deer, goats and other animals." + }, + { + "Id": "snowy", + "Title": "Snowy", + "Description": "Snowy biome features - as its name implies - lots of snow and the main vegetation to be found comprises of conifers. Such fauna as may be found here are wolves, muskox and walruses." + }, + { + "Id": "desert", + "Title": "Desert", + "Description": "Desert biome features dry terrain sporting abundant clumps of palms and herds of camels." + }, + { + "Id": "alpine", + "Title": "Alpine", + "Description": "Alpine biome usually features magnificent snow-covered peaks and its vegetation comprises mostly of the dominant coniferous forests but may feature some broadleaf deciduous forest." + }, + { + "Id": "mediterranean", + "Title": "Mediterranean", + "Description": "Meditterranean biome is a mix of Temperate and Desert biomes with additional trees such as cypresses, firs, pines and oaks. It boasts the same wildlife living in temperate zones." + }, + { + "Id": "savanna", + "Title": "Savanna", + "Description": "Savanna biome features the large but sparse Baobab trees and its wildlife may include zebras, wildebeest, giraffes and elephants." + }, + + { + "Id": "tropic", + "Title": "Tropic", + "Description": "Tropical biome usually features a lush green environment with tropical hardwood trees and the occasional tiger.." + }, + { + "Id": "autumn", + "Title": "Autumn", + "Description": "This biome is a variant of the Temperate biome and features a warm, inviting and colourful environment. Fallen leaves carpet the ground and make this a truly amazing place to play at." + } + ] +}