Index: ps/trunk/binaries/data/mods/public/gui/common/settings.js =================================================================== --- ps/trunk/binaries/data/mods/public/gui/common/settings.js (revision 17053) +++ ps/trunk/binaries/data/mods/public/gui/common/settings.js (revision 17054) @@ -1,258 +1,313 @@ /** * The maximum number of players that the engine supports. * TODO: Maybe we can support more than 8 players sometime. */ const g_MaxPlayers = 8; /** * The maximum number of teams allowed. */ const g_MaxTeams = 4; /** * Directory containing all editable settings. */ const g_SettingsDirectory = "simulation/data/settings/"; /** * An object containing all values given by setting name. * Used by lobby, gamesetup, session, summary screen and replay menu. */ const g_Settings = loadSettingsValues(); /** * Loads and translates all values of all settings which * can be configured by dropdowns in the gamesetup. * * @returns {Object|undefined} */ function loadSettingsValues() { // TODO: move PlayerDefaults and MapSizes from functions_utility.js here var settings = { "AIDescriptions": loadAIDescriptions(), "AIDifficulties": loadAIDifficulties(), "Ceasefire": loadCeasefire(), "GameSpeeds": loadSettingValuesFile("game_speeds.json"), "MapTypes": loadMapTypes(), "PopulationCapacities": loadPopulationCapacities(), "StartingResources": loadSettingValuesFile("starting_resources.json"), "VictoryConditions": loadVictoryConditions() }; if (Object.keys(settings).some(key => settings[key] === undefined)) return undefined; return settings; } /** * Returns an array of objects reflecting all possible values for a given setting. * * @param {string} filename * @see simulation/data/settings/ * @returns {Array|undefined} */ function loadSettingValuesFile(filename) { var json = Engine.ReadJSONFile(g_SettingsDirectory + filename); if (!json || !json.Data) { error("Could not load " + filename + "!"); return undefined; } if (json.TranslatedKeys) translateObjectKeys(json.Data, json.TranslatedKeys); return json.Data; } /** * Loads the descriptions as defined in simulation/ai/.../data.json and loaded by ICmpAIManager.cpp. * * @returns {Array} */ function loadAIDescriptions() { var ais = Engine.GetAIs(); translateObjectKeys(ais, ["name", "description"]); return ais.sort((a, b) => a.data.name.localeCompare(b.data.name)); } /** * Hardcoded, as modding is not supported without major changes. * Notice the AI code parses the difficulty level by the index, not by name. * * @returns {Array} */ function loadAIDifficulties() { return [ { "Name": "sandbox", "Title": translateWithContext("aiDiff", "Sandbox") }, { "Name": "very easy", "Title": translateWithContext("aiDiff", "Very Easy") }, { "Name": "easy", "Title": translateWithContext("aiDiff", "Easy") }, { "Name": "medium", "Title": translateWithContext("aiDiff", "Medium"), "Default": true }, { "Name": "hard", "Title": translateWithContext("aiDiff", "Hard") }, { "Name": "very hard", "Title": translateWithContext("aiDiff", "Very Hard") } ]; } /** * Loads available ceasefire settings. * * @returns {Array|undefined} */ function loadCeasefire() { var json = Engine.ReadJSONFile(g_SettingsDirectory + "ceasefire.json"); if (!json || json.Default === undefined || !json.Times || !Array.isArray(json.Times)) { error("Could not load ceasefire.json"); return undefined; } return json.Times.map(timeout => ({ "Duration": timeout, "Default": timeout == json.Default, "Title": timeout == 0 ? translateWithContext("ceasefire", "No ceasefire") : sprintf(translatePluralWithContext("ceasefire", "%(minutes)s minute", "%(minutes)s minutes", timeout), { "minutes": timeout }) })); } /** * Hardcoded, as modding is not supported without major changes. * * @returns {Array} */ function loadMapTypes() { return [ { "Name": "skirmish", "Title": translateWithContext("map", "Skirmish"), "Default": true }, { "Name": "random", "Title": translateWithContext("map", "Random") }, { "Name": "scenario", "Title": translate("Scenario") // TODO: update the translation (but not shortly before a release) } ]; } /** * Loads available gametypes. * * @returns {Array|undefined} */ function loadVictoryConditions() { const subdir = "victory_conditions/"; const files = Engine.BuildDirEntList(g_SettingsDirectory + subdir, "*.json", false).map( file => file.substr(g_SettingsDirectory.length)); var victoryConditions = files.map(file => { let vc = loadSettingValuesFile(file); if (vc) vc.Name = file.substr(subdir.length, file.length - (subdir + ".json").length); return vc; }); if (victoryConditions.some(vc => vc == undefined)) return undefined; // TODO: We might support enabling victory conditions separately sometime. // Until then, we supplement the endless gametype here. victoryConditions.push({ "Name": "endless", "Title": translate("None"), "Description": translate("Endless Game"), "Scripts": [] }); return victoryConditions; } /** * Loads available population capacities. * * @returns {Array|undefined} */ function loadPopulationCapacities() { var json = Engine.ReadJSONFile(g_SettingsDirectory + "population_capacities.json"); if (!json || json.Default === undefined || !json.PopulationCapacities || !Array.isArray(json.PopulationCapacities)) { error("Could not load population_capacities.json"); return undefined; } return json.PopulationCapacities.map(population => ({ "Population": population, "Default": population == json.Default, "Title": population < 10000 ? population : translate("Unlimited") })); } /** * Creates an object with all values of that property of the given setting and * finds the index of the default value. * * This allows easy copying of setting values to dropdown lists. * * @param settingValues {Array} * @returns {Object|undefined} */ function prepareForDropdown(settingValues) { if (!settingValues) return undefined; var settings = { "Default": 0 }; for (let index in settingValues) { for (let property in settingValues[index]) { if (property == "Default") continue; if (!settings[property]) settings[property] = []; // Switch property and index settings[property][index] = settingValues[index][property]; } // Copy default value if (settingValues[index].Default) settings.Default = +index; } return settings; } + +/** + * Returns title or placeholder. + * + * @param aiName {string} - for example "petra" + */ +function translateAIName(aiName) +{ + var description = g_Settings.AIDescriptions.find(ai => ai.id == aiName); + return description ? translate(description.data.name) : translate("Unknown"); +} + +/** + * Returns title or placeholder. + * + * @param index {Number} - index of AIDifficulties + */ +function translateAIDifficulty(index) +{ + var difficulty = g_Settings.AIDifficulties[index]; + return difficulty ? difficulty.Title : translate("Unknown"); +} + +/** + * Returns title or placeholder. + * + * @param mapType {string} - for example "skirmish" + */ +function translateMapType(mapType) +{ + var type = g_Settings.MapTypes.find(t => t.Name == mapType); + return type ? type.Title : translate("Unknown"); +} + +/** + * Returns title or placeholder. + * + * @param population {Number} - for example 300 + */ +function translatePopulationCapacity(population) +{ + var popCap = g_Settings.PopulationCapacities.find(p => p.Population == population); + return popCap ? popCap.Title : translate("Unknown"); +} + +/** + * Returns title or placeholder. + * + * @param gameType {string} - for example "conquest" + */ +function translateVictoryCondition(gameType) +{ + var vc = g_Settings.VictoryConditions.find(vc => vc.Name == gameType); + return vc ? vc.Title : translate("Unknown"); +} Index: ps/trunk/binaries/data/mods/public/gui/page_replaymenu.xml =================================================================== --- ps/trunk/binaries/data/mods/public/gui/page_replaymenu.xml (nonexistent) +++ ps/trunk/binaries/data/mods/public/gui/page_replaymenu.xml (revision 17054) @@ -0,0 +1,15 @@ + + + common/modern/setup.xml + common/modern/styles.xml + common/modern/sprites.xml + + common/setup.xml + common/sprite1.xml + common/styles.xml + common/common_sprites.xml + common/common_styles.xml + + replaymenu/styles.xml + replaymenu/replay_menu.xml + Index: ps/trunk/binaries/data/mods/public/gui/pregame/mainmenu.xml =================================================================== --- ps/trunk/binaries/data/mods/public/gui/pregame/mainmenu.xml (revision 17053) +++ ps/trunk/binaries/data/mods/public/gui/pregame/mainmenu.xml (revision 17054) @@ -1,618 +1,632 @@