Index: binaries/data/mods/public/gui/common/gamedescription.js =================================================================== --- binaries/data/mods/public/gui/common/gamedescription.js +++ binaries/data/mods/public/gui/common/gamedescription.js @@ -216,56 +216,68 @@ function getGameDescription(extended = false) { let titles = []; - - let victoryIdx = g_VictoryConditions.Name.indexOf(g_GameAttributes.settings.GameType || g_VictoryConditions.Default); - if (victoryIdx != -1) + if (!g_GameAttributes.settings.VictoryConditions.length) { - let title = g_VictoryConditions.Title[victoryIdx]; - if (g_VictoryConditions.Name[victoryIdx] == "wonder") - title = sprintf( - translatePluralWithContext( - "victory condition", - "Wonder (%(min)s minute)", - "Wonder (%(min)s minutes)", - g_GameAttributes.settings.WonderDuration - ), - { "min": g_GameAttributes.settings.WonderDuration } - ); - - let isCaptureTheRelic = g_VictoryConditions.Name[victoryIdx] == "capture_the_relic"; - if (isCaptureTheRelic) - title = sprintf( - translatePluralWithContext( - "victory condition", - "Capture the Relic (%(min)s minute)", - "Capture the Relic (%(min)s minutes)", - g_GameAttributes.settings.RelicDuration - ), - { "min": g_GameAttributes.settings.RelicDuration } - ); + let victoryCondition = g_VictoryConditions.find(data => data.Name == "endless"); + if (victoryCondition) + titles.push({ + "label": victoryCondition.Title, + "value": victoryCondition.Description + }); + } - titles.push({ - "label": title, - "value": g_VictoryConditions.Description[victoryIdx] - }); + for (let vc of clone(g_GameAttributes.settings.VictoryConditions).sort((a, b) => a > b ? 1 : a < b ? -1 : 0)) + { + let victoryCondition = g_VictoryConditions.find(data => data.Name == "endless"); + if (victoryCondition) + { + let title = victoryCondition.Title; + if (vc == "wonder") + title = sprintf( + translatePluralWithContext( + "victory condition", + "Wonder (%(min)s minute)", + "Wonder (%(min)s minutes)", + g_GameAttributes.settings.WonderDuration + ), + { "min": g_GameAttributes.settings.WonderDuration } + ); + + let isCaptureTheRelic = vc == "capture_the_relic"; + if (isCaptureTheRelic) + title = sprintf( + translatePluralWithContext( + "victory condition", + "Capture the Relic (%(min)s minute)", + "Capture the Relic (%(min)s minutes)", + g_GameAttributes.settings.RelicDuration + ), + { "min": g_GameAttributes.settings.RelicDuration } + ); - if (isCaptureTheRelic) titles.push({ - "label": translate("Relic Count"), - "value": g_GameAttributes.settings.RelicCount + "label": title, + "value": victoryCondition.Description }); - if (g_VictoryConditions.Name[victoryIdx] == "regicide") - if (g_GameAttributes.settings.RegicideGarrison) - titles.push({ - "label": translate("Hero Garrison"), - "value": translate("Heroes can be garrisoned.") - }); - else + if (isCaptureTheRelic) titles.push({ - "label": translate("Exposed Heroes"), - "value": translate("Heroes cannot be garrisoned, and they are vulnerable to raids.") + "label": translate("Relic Count"), + "value": g_GameAttributes.settings.RelicCount }); + + if (vc == "regicide") + if (g_GameAttributes.settings.RegicideGarrison) + titles.push({ + "label": translate("Hero Garrison"), + "value": translate("Heroes can be garrisoned.") + }); + else + titles.push({ + "label": translate("Exposed Heroes"), + "value": translate("Heroes cannot be garrisoned, and they are vulnerable to raids.") + }); + } } if (g_GameAttributes.settings.RatingEnabled && 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 @@ -247,7 +247,7 @@ } /** - * Loads available gametypes. + * Loads available victoryCondtions from json files. * * @returns {Array|undefined} */ @@ -269,8 +269,8 @@ // Until then, we supplement the endless gametype here. victoryConditions.push({ "Name": "endless", - "Title": translateWithContext("victory condition", "None"), - "Description": translate("Endless game."), + "Title": translateWithContext("victory condition", "Endless"), + "Description": translate("No Victory Condition specfied."), "Scripts": [] }); @@ -428,11 +428,11 @@ /** * Returns title or placeholder. * - * @param {string} gameType - for example "conquest" + * @param {string} victoryCondition - for example "conquest" * @returns {string} */ -function translateVictoryCondition(gameType) +function translateVictoryCondition(victoryCondition) { - let victoryCondition = g_Settings.VictoryConditions.find(vc => vc.Name == gameType); - return victoryCondition ? victoryCondition.Title : translateWithContext("victory condition", "Unknown"); + let victoryConditionData = g_Settings.VictoryConditions.find(vc => vc.Name == victoryCondition); + return victoryConditionData ? victoryConditionData.Title : translateWithContext("victory condition", "Unknown"); } 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 @@ -7,8 +7,9 @@ const g_TriggerDifficulties = prepareForDropdown(g_Settings && g_Settings.TriggerDifficulties); const g_PopulationCapacities = prepareForDropdown(g_Settings && g_Settings.PopulationCapacities); const g_StartingResources = prepareForDropdown(g_Settings && g_Settings.StartingResources); -const g_VictoryConditions = prepareForDropdown(g_Settings && g_Settings.VictoryConditions); const g_VictoryDurations = prepareForDropdown(g_Settings && g_Settings.VictoryDurations); + +const g_VictoryConditions = g_Settings && g_Settings.VictoryConditions || []; var g_GameSpeeds = getGameSpeedChoices(false); /** @@ -289,6 +290,11 @@ var g_GameAttributes = { "settings": {} }; /** + * Identifier if the victory condition array exists, used in the supplementsDefaults function. + */ +var g_VictoryConditionsDefined = false; + +/** * List of translated words that can be used to autocomplete titles of settings * and their values (for example playernames). */ @@ -425,7 +431,12 @@ { "label": translateWithContext("Match settings tab name", "Game Type"), "settings": [ - "victoryCondition", + "conquest", + "conquestUnit", + "conquestStructure", + "captureTheRelic", + "regicide", + "wonder", "relicCount", "relicDuration", "wonderDuration", @@ -632,22 +643,6 @@ "enabled": () => g_GameAttributes.mapType != "scenario", "initOrder": 1000 }, - "victoryCondition": { - "title": () => translate("Victory Condition"), - "tooltip": (hoverIdx) => g_VictoryConditions.Description[hoverIdx] || translate("Select victory condition."), - "labels": () => g_VictoryConditions.Title, - "ids": () => g_VictoryConditions.Name, - "default": () => g_VictoryConditions.Default, - "defined": () => g_GameAttributes.settings.GameType !== undefined, - "get": () => g_GameAttributes.settings.GameType, - "select": (itemIdx) => { - g_GameAttributes.settings.GameType = g_VictoryConditions.Name[itemIdx]; - g_GameAttributes.settings.VictoryScripts = g_VictoryConditions.Scripts[itemIdx]; - }, - "enabled": () => g_GameAttributes.mapType != "scenario", - "autocomplete": 0, - "initOrder": 1000 - }, "relicCount": { "title": () => translate("Relic Count"), "tooltip": (hoverIdx) => translate("Total number of relics spawned on the map. Relic victory is most realistic with only one or two relics. With greater numbers, the relics are important to capture to receive aura bonuses."), @@ -659,7 +654,7 @@ "select": (itemIdx) => { g_GameAttributes.settings.RelicCount = g_RelicCountList[itemIdx]; }, - "hidden": () => g_GameAttributes.settings.GameType != "capture_the_relic", + "hidden": () => g_GameAttributes.settings.VictoryConditions.indexOf("capture_the_relic") == -1, "enabled": () => g_GameAttributes.mapType != "scenario", "initOrder": 1000 }, @@ -674,7 +669,7 @@ "select": (itemIdx) => { g_GameAttributes.settings.RelicDuration = g_VictoryDurations.Duration[itemIdx]; }, - "hidden": () => g_GameAttributes.settings.GameType != "capture_the_relic", + "hidden": () => g_GameAttributes.settings.VictoryConditions.indexOf("capture_the_relic") == -1, "enabled": () => g_GameAttributes.mapType != "scenario", "initOrder": 1000 }, @@ -689,7 +684,7 @@ "select": (itemIdx) => { g_GameAttributes.settings.WonderDuration = g_VictoryDurations.Duration[itemIdx]; }, - "hidden": () => g_GameAttributes.settings.GameType != "wonder", + "hidden": () => g_GameAttributes.settings.VictoryConditions.indexOf("wonder") == -1, "enabled": () => g_GameAttributes.mapType != "scenario", "initOrder": 1000 }, @@ -815,6 +810,36 @@ * Contains the logic of all boolean gamesettings. */ var g_Checkboxes = { + "conquest": getVictoryConditionCheckbox("conquest", { + "default": () => true, + "set": checked => { + if (checked) + { + g_GameAttributes.settings.VictoryConditions.push("conquest"); + g_Checkboxes.conquestUnit.set(false); + g_Checkboxes.conquestStructure.set(false); + } + else + { + let index = g_GameAttributes.settings.VictoryConditions.indexOf("conquest"); + if (index != -1) + g_GameAttributes.settings.VictoryConditions.splice(index, 1) + } + } + }), + "conquestUnit": getVictoryConditionCheckbox("conquest_units", { + "enabled": () => + g_GameAttributes.settings.VictoryConditions.indexOf("conquest") == -1 && + g_GameAttributes.mapType != "scenario" + }), + "conquestStructure": getVictoryConditionCheckbox("conquest_structures", { + "enabled": () => + g_GameAttributes.settings.VictoryConditions.indexOf("conquest") == -1 && + g_GameAttributes.mapType != "scenario" + }), + "captureTheRelic": getVictoryConditionCheckbox("capture_the_relic", {}), + "wonder": getVictoryConditionCheckbox("wonder", {}), + "regicide": getVictoryConditionCheckbox("regicide", {}), "regicideGarrison": { "title": () => translate("Hero Garrison"), "tooltip": () => translate("Toggle whether heroes can be garrisoned."), @@ -824,7 +849,7 @@ "set": checked => { g_GameAttributes.settings.RegicideGarrison = checked; }, - "hidden": () => g_GameAttributes.settings.GameType != "regicide", + "hidden": () => g_GameAttributes.settings.VictoryConditions.indexOf("regicide") == -1, "enabled": () => g_GameAttributes.mapType != "scenario", "initOrder": 1000 }, @@ -1135,6 +1160,8 @@ */ function supplementDefaults() { + g_VictoryConditionsDefined = g_GameAttributes.settings.VictoryConditions != undefined; + g_GameAttributes.settings.VictoryConditions = g_GameAttributes.settings.VictoryConditions || []; for (let dropdown in g_Dropdowns) if (!g_Dropdowns[dropdown].defined()) g_Dropdowns[dropdown].select(g_Dropdowns[dropdown].default()); @@ -1147,6 +1174,8 @@ for (let i = 0; i < g_GameAttributes.settings.PlayerData.length; ++i) if (!isControlArrayElementHidden(i) && !g_PlayerDropdowns[dropdown].defined(i)) g_PlayerDropdowns[dropdown].select(g_PlayerDropdowns[dropdown].default(i), i); + + g_VictoryConditionsDefined = g_GameAttributes.settings.VictoryConditions == undefined; } /** @@ -1589,6 +1618,40 @@ } /** + * Create a default victory condition checkbox object and overwrite with custom values. + */ +function getVictoryConditionCheckbox(victoryCondition, customItems) +{ + if (g_VictoryConditions.map(data => data.Name).indexOf(victoryCondition) == -1) + warn("Unknown victory condition: " + victoryCondition); + + let checkbox = { + "title": () => g_VictoryConditions[g_VictoryConditions.map(data => data.Name).indexOf(victoryCondition)].Title, + "tooltip": () => g_VictoryConditions[g_VictoryConditions.map(data => data.Name).indexOf(victoryCondition)].Description, + "default": () => false, + "defined": () => g_VictoryConditionsDefined, + "get": () => g_GameAttributes.settings.VictoryConditions.indexOf(victoryCondition) != -1, + "set": checked => { + if (checked) + g_GameAttributes.settings.VictoryConditions.push(victoryCondition); + else + { + let index = g_GameAttributes.settings.VictoryConditions.indexOf(victoryCondition); + if (index != -1) + g_GameAttributes.settings.VictoryConditions.splice(index, 1) + } + g_VictoryConditionsDefined = true; + }, + "enabled": () => g_GameAttributes.mapType != "scenario" + }; + + for (let item in customItems) + checkbox[item] = customItems[item]; + + return checkbox; +} + +/** * Doesn't translate, so that lobby clients can do that locally * (even if they don't have that map). */ @@ -1973,14 +2036,8 @@ let mapSettings = mapData && mapData.settings ? clone(mapData.settings) : {}; 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]; - } - if (g_GameAttributes.mapType == "scenario") { delete g_GameAttributes.settings.RelicDuration; @@ -2120,13 +2177,7 @@ // Select random map if (g_GameAttributes.map == "random") - { - let victoryScriptsSelected = g_GameAttributes.settings.VictoryScripts; - let gameTypeSelected = g_GameAttributes.settings.GameType; selectMap(pickRandom(g_Dropdowns.mapSelection.ids().slice(1))); - g_GameAttributes.settings.VictoryScripts = victoryScriptsSelected; - g_GameAttributes.settings.GameType = gameTypeSelected; - } if (g_GameAttributes.settings.Biome == "random") g_GameAttributes.settings.Biome = pickRandom( @@ -2134,6 +2185,11 @@ g_BiomeList.Id.slice(1).filter(biomeID => biomeID.startsWith(g_GameAttributes.settings.SupportedBiomes)) : g_GameAttributes.settings.SupportedBiomes); + let victoryScriptsSelected = []; + for (let vc of g_GameAttributes.settings.VictoryConditions) + victoryScriptsSelected = victoryScriptsSelected.concat(g_VictoryConditions[g_VictoryConditions.map(data => data.Name).indexOf(vc)].Scripts); + + g_GameAttributes.settings.VictoryScripts = victoryScriptsSelected.filter((vc, i) => victoryScriptsSelected.indexOf(vc) == i) g_GameAttributes.settings.TriggerScripts = g_GameAttributes.settings.VictoryScripts.concat(g_GameAttributes.settings.TriggerScripts || []); // Prevent reseting the readystate @@ -2264,7 +2320,6 @@ for (let name in g_MiscControls) updateGUIMiscControl(name); - updateGameDescription(); distributeSettings(); rightAlignCancelButton(); @@ -2626,7 +2681,7 @@ "niceMapName": getMapDisplayName(g_GameAttributes.map), "mapSize": g_GameAttributes.mapType == "random" ? g_GameAttributes.settings.Size : "Default", "mapType": g_GameAttributes.mapType, - "victoryCondition": g_GameAttributes.settings.GameType, + "victoryConditions": g_GameAttributes.settings.VictoryConditions.join(","), "nbp": clients.connectedPlayers, "maxnbp": g_GameAttributes.settings.PlayerData.length, "players": clients.list, Index: binaries/data/mods/public/gui/replaymenu/replay_filters.js =================================================================== --- binaries/data/mods/public/gui/replaymenu/replay_filters.js +++ binaries/data/mods/public/gui/replaymenu/replay_filters.js @@ -243,7 +243,8 @@ // Filter by victory condition let victoryConditionFilter = Engine.GetGUIObjectByName("victoryConditionFilter"); - if (victoryConditionFilter.selected > 0 && replay.attribs.settings.GameType != victoryConditionFilter.list_data[victoryConditionFilter.selected]) + if (victoryConditionFilter.selected > 0 && + replay.attribs.settings.VictoryConditions.indexOf(victoryConditionFilter.list_data[victoryConditionFilter.selected]) == -1) return false; // Filter by rating Index: binaries/data/mods/public/gui/replaymenu/replay_menu.js =================================================================== --- binaries/data/mods/public/gui/replaymenu/replay_menu.js +++ binaries/data/mods/public/gui/replaymenu/replay_menu.js @@ -109,8 +109,9 @@ g_MapNames.push(replay.attribs.settings.Name); // Extract victory conditions - if (replay.attribs.settings.GameType && g_VictoryConditions.indexOf(replay.attribs.settings.GameType) == -1) - g_VictoryConditions.push(replay.attribs.settings.GameType); + for (let vc of replay.attribs.settings.VictoryConditions) + if (g_VictoryConditions.indexOf(vc) == -1) + g_VictoryConditions.push(vc); // Extract playernames for (let playerData of replay.attribs.settings.PlayerData) @@ -182,9 +183,6 @@ if (!attribs.settings.mapType) attribs.settings.mapType = "skirmish"; - if (!attribs.settings.GameType) - attribs.settings.GameType = "conquest"; - // Remove gaia if (attribs.settings.PlayerData.length && attribs.settings.PlayerData[0] == null) attribs.settings.PlayerData.shift(); @@ -276,7 +274,8 @@ Engine.GetGUIObjectByName("sgMapName").caption = translate(replay.attribs.settings.Name); Engine.GetGUIObjectByName("sgMapSize").caption = translateMapSize(replay.attribs.settings.Size); Engine.GetGUIObjectByName("sgMapType").caption = translateMapType(replay.attribs.settings.mapType); - Engine.GetGUIObjectByName("sgVictory").caption = translateVictoryCondition(replay.attribs.settings.GameType); + Engine.GetGUIObjectByName("sgVictory").caption = replay.attribs.settings.VictoryConditions.map(vc => + translateVictoryCondition(vc)).join(", "); Engine.GetGUIObjectByName("sgNbPlayers").caption = sprintf(translate("Players: %(numberOfPlayers)s"), { "numberOfPlayers": replay.attribs.settings.PlayerData.length }); Engine.GetGUIObjectByName("replayFilename").caption = Engine.GetReplayDirectoryName(replay.directory); Index: binaries/data/mods/public/gui/replaymenu/replay_menu.xml =================================================================== --- binaries/data/mods/public/gui/replaymenu/replay_menu.xml +++ binaries/data/mods/public/gui/replaymenu/replay_menu.xml @@ -183,7 +183,7 @@ - + Index: binaries/data/mods/public/gui/session/session.js =================================================================== --- binaries/data/mods/public/gui/session/session.js +++ binaries/data/mods/public/gui/session/session.js @@ -7,8 +7,9 @@ const g_MapTypes = prepareForDropdown(g_Settings && g_Settings.MapTypes); const g_PopulationCapacities = prepareForDropdown(g_Settings && g_Settings.PopulationCapacities); const g_StartingResources = prepareForDropdown(g_Settings && g_Settings.StartingResources); -const g_VictoryConditions = prepareForDropdown(g_Settings && g_Settings.VictoryConditions); const g_VictoryDurations = prepareForDropdown(g_Settings && g_Settings.VictoryDurations); + +const g_VictoryConditions = g_Settings && g_Settings.VictoryConditions || []; var g_GameSpeeds; /** Index: binaries/data/mods/public/maps/random/wall_demo.json =================================================================== --- binaries/data/mods/public/maps/random/wall_demo.json +++ binaries/data/mods/public/maps/random/wall_demo.json @@ -1,13 +1,13 @@ { "settings" : { "Name" : "Wall Demo", - "GameType" : "endless", "Script" : "wall_demo.js", "Description" : "A demonstration of wall placement methods/code in random maps. Giant map size is recommended!", "Keywords": ["demo"], "CircularMap" : false, "TriggerScripts" : [ "random/wall_demo_triggers.js" - ] + ], + "VictoryConditions": [] } } Index: binaries/data/mods/public/maps/scripts/CaptureTheRelic.js =================================================================== --- binaries/data/mods/public/maps/scripts/CaptureTheRelic.js +++ binaries/data/mods/public/maps/scripts/CaptureTheRelic.js @@ -12,7 +12,7 @@ } let cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager); - let numSpawnedRelics = cmpEndGameManager.GetGameTypeSettings().relicCount; + let numSpawnedRelics = cmpEndGameManager.GetGameSettings().relicCount; this.playerRelicsCount = new Array(TriggerHelper.GetNumberOfPlayers()).fill(0, 1); this.playerRelicsCount[0] = numSpawnedRelics; @@ -122,7 +122,7 @@ let cmpPlayer = QueryOwnerInterface(this.relics[0], IID_Player); let cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager); - let captureTheRelicDuration = cmpEndGameManager.GetGameTypeSettings().relicDuration; + let captureTheRelicDuration = cmpEndGameManager.GetGameSettings().relicDuration; let isTeam = playerAndAllies.length > 1; this.ownRelicsVictoryMessage = cmpGuiInterface.AddTimeNotification({ Index: binaries/data/mods/public/maps/scripts/Conquest.js =================================================================== --- binaries/data/mods/public/maps/scripts/Conquest.js +++ binaries/data/mods/public/maps/scripts/Conquest.js @@ -1,5 +1,7 @@ { let cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger); - cmpTrigger.conquestClassFilter = "ConquestCritical"; - cmpTrigger.conquestDefeatReason = markForTranslation("%(player)s has been defeated (lost all critical units and structures)."); + cmpTrigger.conquestData.push({ + "classFilter": "ConquestCritical", + "defeatReason": markForTranslation("%(player)s has been defeated (lost all critical units and structures).") + }); } Index: binaries/data/mods/public/maps/scripts/ConquestCommon.js =================================================================== --- binaries/data/mods/public/maps/scripts/ConquestCommon.js +++ binaries/data/mods/public/maps/scripts/ConquestCommon.js @@ -1,54 +1,59 @@ Trigger.prototype.ConquestOwnershipChanged = function(msg) { - if (!this.conquestDataInit || !this.conquestClassFilter) + if (!this.conquestDataInit) return; - if (!TriggerHelper.EntityMatchesClassList(msg.entity, this.conquestClassFilter)) - return; - - if (msg.to > 0) - this.conquestEntitiesByPlayer[msg.to].push(msg.entity); - - if (msg.from > 0) + for (let i = 0; i < this.conquestData.length; ++i) { - let entities = this.conquestEntitiesByPlayer[msg.from]; - let index = entities.indexOf(msg.entity); - if (index != -1) - entities.splice(index, 1); + if (!TriggerHelper.EntityMatchesClassList(msg.entity, this.conquestData[i].classFilter)) + continue; - if (!entities.length) + if (msg.to > 0) + this.conquestData[i].entitiesByPlayer[msg.to].push(msg.entity); + + if (msg.from > 0) { - let cmpPlayer = QueryPlayerIDInterface(msg.from); - if (cmpPlayer) - cmpPlayer.SetState("defeated", this.conquestDefeatReason); + let entities = this.conquestData[i].entitiesByPlayer[msg.from]; + let index = entities.indexOf(msg.entity); + if (index != -1) + entities.splice(index, 1); + + if (!entities.length) + { + let cmpPlayer = QueryPlayerIDInterface(msg.from); + if (cmpPlayer) + cmpPlayer.SetState("defeated", this.conquestData[i].defeatReason); + } } } }; Trigger.prototype.ConquestStartGameCount = function() { - if (!this.conquestClassFilter) + if (!this.conquestData.length) { - warn("ConquestStartGameCount: conquestClassFilter undefined"); + warn("ConquestStartGameCount: no conquestData set"); return; } let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager); - let numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers(); - for (let i = 1; i < numPlayers; ++i) - this.conquestEntitiesByPlayer[i] = - cmpRangeManager.GetEntitiesByPlayer(i).filter(ent => - TriggerHelper.EntityMatchesClassList(ent, this.conquestClassFilter)); + let entitiesByPlayer = []; + for (let playerID = 1; playerID < numPlayers; ++playerID) + entitiesByPlayer[playerID] = cmpRangeManager.GetEntitiesByPlayer(playerID); + + for (let i = 0; i < this.conquestData.length; ++i) + this.conquestData[i].entitiesByPlayer = entitiesByPlayer.map( + ents => ents.filter( + ent => TriggerHelper.EntityMatchesClassList(ent, this.conquestData[i].classFilter))); this.conquestDataInit = true; }; { let cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger); - cmpTrigger.conquestEntitiesByPlayer = {}; cmpTrigger.conquestDataInit = false; - cmpTrigger.conquestClassFilter = ""; + cmpTrigger.conquestData = []; cmpTrigger.RegisterTrigger("OnOwnershipChanged", "ConquestOwnershipChanged", { "enabled": true }); cmpTrigger.DoAfterDelay(0, "ConquestStartGameCount", null); } Index: binaries/data/mods/public/maps/scripts/ConquestStructures.js =================================================================== --- binaries/data/mods/public/maps/scripts/ConquestStructures.js +++ binaries/data/mods/public/maps/scripts/ConquestStructures.js @@ -1,5 +1,7 @@ { let cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger); - cmpTrigger.conquestClassFilter = "Structure"; - cmpTrigger.conquestDefeatReason = markForTranslation("%(player)s has been defeated (lost all structures)."); + cmpTrigger.conquestData.push({ + "classFilter": "Structure", + "defeatReason": markForTranslation("%(player)s has been defeated (lost all structures).") + }); } Index: binaries/data/mods/public/maps/scripts/ConquestUnits.js =================================================================== --- binaries/data/mods/public/maps/scripts/ConquestUnits.js +++ binaries/data/mods/public/maps/scripts/ConquestUnits.js @@ -1,5 +1,7 @@ { let cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger); - cmpTrigger.conquestClassFilter = "Unit+!Animal"; - cmpTrigger.conquestDefeatReason = markForTranslation("%(player)s has been defeated (lost all units)."); + cmpTrigger.conquestData.push({ + "classFilter": "Unit+!Animal", + "defeatReason": markForTranslation("%(player)s has been defeated (lost all units).") + }); } Index: binaries/data/mods/public/maps/scripts/Regicide.js =================================================================== --- binaries/data/mods/public/maps/scripts/Regicide.js +++ binaries/data/mods/public/maps/scripts/Regicide.js @@ -9,7 +9,7 @@ Trigger.prototype.InitRegicideGame = function(msg) { let cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager); - let regicideGarrison = cmpEndGameManager.GetGameTypeSettings().regicideGarrison; + let regicideGarrison = cmpEndGameManager.GetGameSettings().regicideGarrison; let playersCivs = []; for (let playerID = 1; playerID < TriggerHelper.GetNumberOfPlayers(); ++playerID) Index: binaries/data/mods/public/maps/scripts/WonderVictory.js =================================================================== --- binaries/data/mods/public/maps/scripts/WonderVictory.js +++ binaries/data/mods/public/maps/scripts/WonderVictory.js @@ -54,7 +54,7 @@ let cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface); let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); - let wonderDuration = cmpEndGameManager.GetGameTypeSettings().wonderDuration; + let wonderDuration = cmpEndGameManager.GetGameSettings().wonderDuration; this.wonderVictoryMessages[ent] = { "playerID": player, "allies": new Set(allies), Index: binaries/data/mods/public/maps/tutorials/Introductory_Tutorial.xml =================================================================== --- binaries/data/mods/public/maps/tutorials/Introductory_Tutorial.xml +++ binaries/data/mods/public/maps/tutorials/Introductory_Tutorial.xml @@ -40,7 +40,6 @@ { "CircularMap": true, "Description": "This is a basic tutorial to get you started playing 0 A.D.", - "GameType": "endless", "Keywords": ["demo"], "LockTeams": false, "Name": "Introductory Tutorial", @@ -86,7 +85,8 @@ "scripts/TriggerHelper.js", "scripts/Tutorial.js", "tutorials/Introductory_Tutorial.js" - ] + ], + "VictoryConditions": [] } ]]> Index: binaries/data/mods/public/maps/tutorials/starting_economy_walkthrough.xml =================================================================== --- binaries/data/mods/public/maps/tutorials/starting_economy_walkthrough.xml +++ binaries/data/mods/public/maps/tutorials/starting_economy_walkthrough.xml @@ -48,7 +48,6 @@ ], "CircularMap": true, "Description": "This map will give a rough guide for starting the game effectively. Early in the game the most important thing is to gather resources as fast as possible so you are able to build enough troops later.", - "GameType": "endless", "Keywords": ["trigger"], "LockTeams": false, "Name": "Starting Economy Walkthrough", @@ -71,7 +70,8 @@ "scripts/Tutorial.js", "tutorials/starting_economy_walkthrough.js" ], - "Size": 256 + "Size": 256, + "VictoryConditions": [] } ]]> Index: binaries/data/mods/public/simulation/ai/common-api/shared.js =================================================================== --- binaries/data/mods/public/simulation/ai/common-api/shared.js +++ binaries/data/mods/public/simulation/ai/common-api/shared.js @@ -74,7 +74,7 @@ this.timeElapsed = state.timeElapsed; this.circularMap = state.circularMap; this.mapSize = state.mapSize; - this.victoryConditions = new Set([state.gameType]); + this.victoryConditions = new Set(state.victoryConditions); this.alliedVictory = state.alliedVictory; this.ceasefireActive = state.ceasefireActive; this.ceasefireTimeRemaining = state.ceasefireTimeRemaining / 1000; Index: binaries/data/mods/public/simulation/components/EndGameManager.js =================================================================== --- binaries/data/mods/public/simulation/components/EndGameManager.js +++ binaries/data/mods/public/simulation/components/EndGameManager.js @@ -9,11 +9,9 @@ EndGameManager.prototype.Init = function() { - this.gameType = "conquest"; - // Contains settings specific to the victory condition, // for example wonder victory duration. - this.gameTypeSettings = {}; + this.gameSettings = {}; // Allied victory means allied players can win if victory conditions are met for each of them // False for a "last man standing" game @@ -28,24 +26,23 @@ this.endlessGame = false; }; -EndGameManager.prototype.GetGameType = function() +EndGameManager.prototype.GetGameSettings = function() { - return this.gameType; + return this.gameSettings; }; -EndGameManager.prototype.GetGameTypeSettings = function() +EndGameManager.prototype.GetVictoryConditions = function() { - return this.gameTypeSettings; + return this.gameSettings.victoryConditions; }; -EndGameManager.prototype.SetGameType = function(newGameType, newSettings = {}) +EndGameManager.prototype.SetGameSettings = function(newSettings = {}) { - this.gameType = newGameType; - this.gameTypeSettings = newSettings; + this.gameSettings = newSettings; this.skipAlliedVictoryCheck = false; - this.endlessGame = newGameType == "endless"; + this.endlessGame = !this.gameSettings.victoryConditions.length; - Engine.BroadcastMessage(MT_GameTypeChanged, {}); + Engine.BroadcastMessage(MT_VictoryConditionsChanged, {}); }; /** Index: binaries/data/mods/public/simulation/components/GuiInterface.js =================================================================== --- binaries/data/mods/public/simulation/components/GuiInterface.js +++ binaries/data/mods/public/simulation/components/GuiInterface.js @@ -154,7 +154,7 @@ // Add the game type and allied victory let cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager); - ret.gameType = cmpEndGameManager.GetGameType(); + ret.victoryConditions = cmpEndGameManager.GetVictoryConditions(); ret.alliedVictory = cmpEndGameManager.GetAlliedVictory(); // Add basic statistics to each player Index: binaries/data/mods/public/simulation/components/interfaces/EndGameManager.js =================================================================== --- binaries/data/mods/public/simulation/components/interfaces/EndGameManager.js +++ binaries/data/mods/public/simulation/components/interfaces/EndGameManager.js @@ -4,4 +4,4 @@ * Message of the form {} * sent from EndGameManager component. */ -Engine.RegisterMessageType("GameTypeChanged"); +Engine.RegisterMessageType("VictoryConditionsChanged"); Index: binaries/data/mods/public/simulation/components/tests/test_EndGameManager.js =================================================================== --- binaries/data/mods/public/simulation/components/tests/test_EndGameManager.js +++ binaries/data/mods/public/simulation/components/tests/test_EndGameManager.js @@ -23,7 +23,7 @@ TS_ASSERT_EQUALS(cmpEndGameManager.skipAlliedVictoryCheck, true); cmpEndGameManager.SetAlliedVictory(true); TS_ASSERT_EQUALS(cmpEndGameManager.GetAlliedVictory(), true); -cmpEndGameManager.SetGameType("wonder", { "wonderDuration": wonderDuration }); +cmpEndGameManager.SetGameSettings({ "victoryConditions": ["wonder"], "wonderDuration": wonderDuration }); TS_ASSERT_EQUALS(cmpEndGameManager.skipAlliedVictoryCheck, false); -TS_ASSERT(cmpEndGameManager.GetGameType() == "wonder"); -TS_ASSERT_EQUALS(cmpEndGameManager.GetGameTypeSettings().wonderDuration, wonderDuration); +TS_ASSERT_UNEVAL_EQUALS(cmpEndGameManager.GetVictoryConditions(), ["wonder"]); +TS_ASSERT_EQUALS(cmpEndGameManager.GetGameSettings().wonderDuration, wonderDuration); Index: binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js =================================================================== --- binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js +++ binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js @@ -65,7 +65,7 @@ }); AddMock(SYSTEM_ENTITY, IID_EndGameManager, { - GetGameType: function() { return "conquest"; }, + GetVictoryConditions: function() { return ["conquest", "wonder"]; }, GetAlliedVictory: function() { return false; } }); @@ -365,7 +365,7 @@ ], circularMap: false, timeElapsed: 0, - gameType: "conquest", + victoryConditions: ["conquest", "wonder"], alliedVictory: false }); @@ -518,7 +518,7 @@ ], "circularMap": false, "timeElapsed": 0, - "gameType": "conquest", + "victoryConditions": ["conquest", "wonder"], "alliedVictory": false }); Index: binaries/data/mods/public/simulation/data/settings/victory_conditions/capture_the_relic.json =================================================================== --- binaries/data/mods/public/simulation/data/settings/victory_conditions/capture_the_relic.json +++ binaries/data/mods/public/simulation/data/settings/victory_conditions/capture_the_relic.json @@ -7,8 +7,6 @@ "Scripts": [ "scripts/TriggerHelper.js", - "scripts/ConquestCommon.js", - "scripts/Conquest.js", "scripts/CaptureTheRelic.js" ] } Index: binaries/data/mods/public/simulation/data/settings/victory_conditions/conquest.json =================================================================== --- binaries/data/mods/public/simulation/data/settings/victory_conditions/conquest.json +++ binaries/data/mods/public/simulation/data/settings/victory_conditions/conquest.json @@ -3,7 +3,7 @@ "Data": { "Title": "Conquest", - "Description": "Defeat all opponents to win.", + "Description": "Defeat opponents by killing all their units and destroying all their buildings.", "Scripts": [ "scripts/TriggerHelper.js", Index: binaries/data/mods/public/simulation/data/settings/victory_conditions/conquest_structures.json =================================================================== --- binaries/data/mods/public/simulation/data/settings/victory_conditions/conquest_structures.json +++ binaries/data/mods/public/simulation/data/settings/victory_conditions/conquest_structures.json @@ -3,7 +3,7 @@ "Data": { "Title": "Conquest Structures", - "Description": "Destroy all enemy structures to win.", + "Description": "Defeat opponents by destroying all their structures.", "Scripts": [ "scripts/TriggerHelper.js", Index: binaries/data/mods/public/simulation/data/settings/victory_conditions/conquest_units.json =================================================================== --- binaries/data/mods/public/simulation/data/settings/victory_conditions/conquest_units.json +++ binaries/data/mods/public/simulation/data/settings/victory_conditions/conquest_units.json @@ -3,7 +3,7 @@ "Data": { "Title": "Conquest Units", - "Description": "Kill all enemy units to win.", + "Description": "Defeat opponents by killing all their units.", "Scripts": [ "scripts/TriggerHelper.js", Index: binaries/data/mods/public/simulation/data/settings/victory_conditions/regicide.json =================================================================== --- binaries/data/mods/public/simulation/data/settings/victory_conditions/regicide.json +++ binaries/data/mods/public/simulation/data/settings/victory_conditions/regicide.json @@ -7,8 +7,6 @@ "Scripts": [ "scripts/TriggerHelper.js", - "scripts/ConquestCommon.js", - "scripts/Conquest.js", "scripts/Regicide.js" ] } Index: binaries/data/mods/public/simulation/data/settings/victory_conditions/wonder.json =================================================================== --- binaries/data/mods/public/simulation/data/settings/victory_conditions/wonder.json +++ binaries/data/mods/public/simulation/data/settings/victory_conditions/wonder.json @@ -7,8 +7,6 @@ "Scripts": [ "scripts/TriggerHelper.js", - "scripts/ConquestCommon.js", - "scripts/Conquest.js", "scripts/WonderVictory.js" ] } Index: binaries/data/mods/public/simulation/helpers/Setup.js =================================================================== --- binaries/data/mods/public/simulation/helpers/Setup.js +++ binaries/data/mods/public/simulation/helpers/Setup.js @@ -53,17 +53,19 @@ } let cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager); - let gameTypeSettings = {}; - if (settings.GameType && settings.GameType == "capture_the_relic") - gameTypeSettings.relicCount = settings.RelicCount; - if (settings.GameType && settings.GameType == "capture_the_relic") - gameTypeSettings.relicDuration = settings.RelicDuration * 60 * 1000; - if (settings.GameType && settings.GameType == "wonder") - gameTypeSettings.wonderDuration = settings.WonderDuration * 60 * 1000; - if (settings.GameType && settings.GameType == "regicide") - gameTypeSettings.regicideGarrison = settings.RegicideGarrison; - if (settings.GameType) - cmpEndGameManager.SetGameType(settings.GameType, gameTypeSettings); + let gameSettings = {}; + gameSettings.victoryConditions = settings.VictoryConditions || ["conquest"]; + + if (gameSettings.victoryConditions.indexOf("capture_the_relic") != -1) + { + gameSettings.relicCount = settings.RelicCount; + gameSettings.relicDuration = settings.RelicDuration * 60 * 1000; + } + if (gameSettings.victoryConditions.indexOf("wonder") != -1) + gameSettings.wonderDuration = settings.WonderDuration * 60 * 1000; + if (gameSettings.victoryConditions.indexOf("regicide") != -1) + gameSettings.regicideGarrison = settings.RegicideGarrison; + cmpEndGameManager.SetGameSettings(gameSettings); cmpEndGameManager.SetAlliedVictory(settings.LockTeams || !settings.LastManStanding); if (settings.LockTeams && settings.LastManStanding) Index: source/ps/GameSetup/GameSetup.cpp =================================================================== --- source/ps/GameSetup/GameSetup.cpp +++ source/ps/GameSetup/GameSetup.cpp @@ -1155,7 +1155,7 @@ * -autostart-nonvisual disable any graphics and sounds * -autostart-victory=SCRIPTNAME sets the victory conditions with SCRIPTNAME * located in simulation/data/settings/victory_conditions/ - * (default conquest) + * (default none) * -autostart-wonderduration=NUM sets the victory duration NUM for wonder victory conditions * (default 10 minutes) * -autostart-relicduration=NUM sets the victory duration NUM for relic victory conditions @@ -1464,24 +1464,30 @@ triggerScriptsVector.push_back(nonVisualScript.FromUTF8()); } - CStr victory = "conquest"; + std::vector victoryConditions; if (args.Has("autostart-victory")) - victory = args.Get("autostart-victory"); + victoryConditions = args.GetMultiple("autostart-victory"); - scriptInterface.SetProperty(settings, "GameType", std::string(victory)); + scriptInterface.SetProperty(settings, "VictoryConditions", victoryConditions); - CStrW scriptPath = L"simulation/data/settings/victory_conditions/" + victory.FromUTF8() + L".json"; - JS::RootedValue scriptData(cx); - JS::RootedValue data(cx); - JS::RootedValue victoryScripts(cx); - scriptInterface.ReadJSONFile(scriptPath, &scriptData); - if (!scriptData.isUndefined() && scriptInterface.GetProperty(scriptData, "Data", &data) && !data.isUndefined() - && scriptInterface.GetProperty(data, "Scripts", &victoryScripts) && !victoryScripts.isUndefined()) - { - std::vector victoryScriptsVector; - FromJSVal_vector(cx, victoryScripts, victoryScriptsVector); - triggerScriptsVector.insert(triggerScriptsVector.end(), victoryScriptsVector.begin(), victoryScriptsVector.end()); + for (size_t i = 0; i < victoryConditions.size(); ++i) + { + JS::RootedValue scriptData(cx); + JS::RootedValue data(cx); + JS::RootedValue victoryScripts(cx); + + CStr victory = victoryConditions[i]; + CStrW scriptPath = L"simulation/data/settings/victory_conditions/" + victory.FromUTF8() + L".json"; + scriptInterface.ReadJSONFile(scriptPath, &scriptData); + if (!scriptData.isUndefined() && scriptInterface.GetProperty(scriptData, "Data", &data) && !data.isUndefined() + && scriptInterface.GetProperty(data, "Scripts", &victoryScripts) && !victoryScripts.isUndefined()) + { + std::vector victoryScriptsVector; + FromJSVal_vector(cx, victoryScripts, victoryScriptsVector); + triggerScriptsVector.insert(triggerScriptsVector.end(), victoryScriptsVector.begin(), victoryScriptsVector.end()); + } } + ToJSVal_vector(cx, &triggerScripts, triggerScriptsVector); scriptInterface.SetProperty(settings, "TriggerScripts", triggerScripts); Index: source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Map/Map.cpp =================================================================== --- source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Map/Map.cpp +++ source/tools/atlas/AtlasUI/ScenarioEditor/Sections/Map/Map.cpp @@ -37,6 +37,12 @@ ID_MapTeams, ID_MapKW_Demo, ID_MapKW_Naval, + ID_VC_Conquest, + ID_VC_ConquestUnits, + ID_VC_ConquestStructures, + ID_VC_CaptureTheRelic, + ID_VC_Wonder, + ID_VC_Regicide, ID_RandomScript, ID_RandomSize, ID_RandomNomad, @@ -93,13 +99,17 @@ AtObj UpdateSettingsObject(); private: void SendToEngine(); + void OnConquestChanged(); - void OnEdit(wxCommandEvent& WXUNUSED(evt)) + void OnEdit(wxCommandEvent& evt) { SendToEngine(); + if (evt.GetId() == ID_VC_Conquest) + OnConquestChanged(); } std::set m_MapSettingsKeywords; + std::set m_MapSettingsVictoryConditions; std::vector m_PlayerCivChoices; Observable& m_MapSettings; @@ -142,16 +152,6 @@ sizer->AddSpacer(5); - // TODO: replace by filenames in binaries/data/mods/public/simulation/data/settings/victory_conditions/ - wxArrayString gameTypes; - gameTypes.Add(_T("conquest")); - gameTypes.Add(_T("conquest_structures")); - gameTypes.Add(_T("conquest_units")); - gameTypes.Add(_T("wonder")); - gameTypes.Add(_T("endless")); - gameTypes.Add(_T("regicide")); - gameTypes.Add(_T("capture_the_relic")); - wxFlexGridSizer* gridSizer = new wxFlexGridSizer(2, 5, 5); gridSizer->AddGrowableCol(1); // TODO: have preview selector tool? @@ -161,9 +161,6 @@ gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Reveal map")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT)); gridSizer->Add(Tooltipped(new wxCheckBox(this, ID_MapReveal, wxEmptyString), _("If checked, players won't need to explore"))); - gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Game type")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT)); - gridSizer->Add(Tooltipped(new wxChoice(this, ID_MapType, wxDefaultPosition, wxDefaultSize, gameTypes), - _("Select the game type (or victory condition)")), wxSizerFlags().Expand()); gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Lock teams")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT)); gridSizer->Add(Tooltipped(new wxCheckBox(this, ID_MapTeams, wxEmptyString), _("If checked, teams will be locked"))); @@ -171,6 +168,33 @@ sizer->AddSpacer(5); + // TODO: replace by names in binaries/data/mods/public/simulation/data/settings/victory_conditions/ + wxStaticBoxSizer* victoryConditionSizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Victory Conditions")); + wxFlexGridSizer* vcGridSizer = new wxFlexGridSizer(2, 5, 5); + vcGridSizer->AddGrowableCol(1); + vcGridSizer->Add(new wxStaticText(this, wxID_ANY, _("Conquest")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT)); + vcGridSizer->Add(Tooltipped(new wxCheckBox(this, ID_VC_Conquest, wxEmptyString), + _("Select Conquest victory condition"))); + vcGridSizer->Add(new wxStaticText(this, wxID_ANY, _("Conquest Units")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT)); + vcGridSizer->Add(Tooltipped(new wxCheckBox(this, ID_VC_ConquestUnits, wxEmptyString), + _("Select Conquest Units victory condition"))); + vcGridSizer->Add(new wxStaticText(this, wxID_ANY, _("Conquest Structures")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT)); + vcGridSizer->Add(Tooltipped(new wxCheckBox(this, ID_VC_ConquestStructures, wxEmptyString), + _("Select Conquest Structures victory condition"))); + vcGridSizer->Add(new wxStaticText(this, wxID_ANY, _("Capture the Relic")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT)); + vcGridSizer->Add(Tooltipped(new wxCheckBox(this, ID_VC_CaptureTheRelic, wxEmptyString), + _("Select Capture the Relic victory condition"))); + vcGridSizer->Add(new wxStaticText(this, wxID_ANY, _("Wonder")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT)); + vcGridSizer->Add(Tooltipped(new wxCheckBox(this, ID_VC_Wonder, wxEmptyString), + _("Select Wonder victory condition"))); + vcGridSizer->Add(new wxStaticText(this, wxID_ANY, _("Regicide")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT)); + vcGridSizer->Add(Tooltipped(new wxCheckBox(this, ID_VC_Regicide, wxEmptyString), + _("Select Regicide victory condition"))); + victoryConditionSizer->Add(vcGridSizer); + sizer->Add(victoryConditionSizer, wxSizerFlags().Expand()); + + sizer->AddSpacer(5); + wxStaticBoxSizer* keywordsSizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Keywords")); wxFlexGridSizer* kwGridSizer = new wxFlexGridSizer(4, 5, 5); kwGridSizer->Add(new wxStaticText(this, wxID_ANY, _("Demo")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT)); @@ -205,11 +229,18 @@ // reveal map wxDynamicCast(FindWindow(ID_MapReveal), wxCheckBox)->SetValue(wxString(m_MapSettings["RevealMap"]) == L"true"); - // game type / victory conditions - if (m_MapSettings["GameType"].defined()) - wxDynamicCast(FindWindow(ID_MapType), wxChoice)->SetStringSelection(wxString(m_MapSettings["GameType"])); - else - wxDynamicCast(FindWindow(ID_MapType), wxChoice)->SetSelection(0); + // victory conditions + m_MapSettingsVictoryConditions.clear(); + for (AtIter victoryCondition = m_MapSettings["VictoryConditions"]["item"]; victoryCondition.defined(); ++victoryCondition) + m_MapSettingsVictoryConditions.insert(std::wstring(victoryCondition)); + + wxDynamicCast(FindWindow(ID_VC_Conquest), wxCheckBox)->SetValue(m_MapSettingsVictoryConditions.count(L"conquest") != 0); + wxDynamicCast(FindWindow(ID_VC_ConquestUnits), wxCheckBox)->SetValue(m_MapSettingsVictoryConditions.count(L"conquest_units") != 0); + wxDynamicCast(FindWindow(ID_VC_ConquestStructures), wxCheckBox)->SetValue(m_MapSettingsVictoryConditions.count(L"conquest_structures") != 0); + wxDynamicCast(FindWindow(ID_VC_CaptureTheRelic), wxCheckBox)->SetValue(m_MapSettingsVictoryConditions.count(L"capture_the_relic") != 0); + wxDynamicCast(FindWindow(ID_VC_Wonder), wxCheckBox)->SetValue(m_MapSettingsVictoryConditions.count(L"wonder") != 0); + wxDynamicCast(FindWindow(ID_VC_Regicide), wxCheckBox)->SetValue(m_MapSettingsVictoryConditions.count(L"regicide") != 0); + OnConquestChanged(); // lock teams wxDynamicCast(FindWindow(ID_MapTeams), wxCheckBox)->SetValue(wxString(m_MapSettings["LockTeams"]) == L"true"); @@ -233,6 +264,21 @@ SendToEngine(); } +void MapSettingsControl::OnConquestChanged() +{ + bool conqestEnabled = wxDynamicCast(FindWindow(ID_VC_Conquest), wxCheckBox)->GetValue(); + + wxCheckBox* conquestUnitsCheckbox = wxDynamicCast(FindWindow(ID_VC_ConquestUnits), wxCheckBox); + conquestUnitsCheckbox->Enable(!conqestEnabled); + wxCheckBox* conquestStructuresCheckbox = wxDynamicCast(FindWindow(ID_VC_ConquestStructures), wxCheckBox); + conquestStructuresCheckbox->Enable(!conqestEnabled); + if (conqestEnabled) + { + conquestUnitsCheckbox->SetValue(false); + conquestStructuresCheckbox->SetValue(false); + } +} + AtObj MapSettingsControl::UpdateSettingsObject() { // map name @@ -247,8 +293,42 @@ // reveal map m_MapSettings.setBool("RevealMap", wxDynamicCast(FindWindow(ID_MapReveal), wxCheckBox)->GetValue()); - // game type / victory conditions - m_MapSettings.set("GameType", wxDynamicCast(FindWindow(ID_MapType), wxChoice)->GetStringSelection()); + // victory conditions + if (wxDynamicCast(FindWindow(ID_VC_Conquest), wxCheckBox)->GetValue()) + m_MapSettingsVictoryConditions.insert(L"conquest"); + else + m_MapSettingsVictoryConditions.erase(L"conquest"); + + if (wxDynamicCast(FindWindow(ID_VC_ConquestUnits), wxCheckBox)->GetValue()) + m_MapSettingsVictoryConditions.insert(L"conquest_units"); + else + m_MapSettingsVictoryConditions.erase(L"conquest_units"); + + if (wxDynamicCast(FindWindow(ID_VC_ConquestStructures), wxCheckBox)->GetValue()) + m_MapSettingsVictoryConditions.insert(L"conquest_structures"); + else + m_MapSettingsVictoryConditions.erase(L"conquest_structures"); + + if (wxDynamicCast(FindWindow(ID_VC_CaptureTheRelic), wxCheckBox)->GetValue()) + m_MapSettingsVictoryConditions.insert(L"capture_the_relic"); + else + m_MapSettingsVictoryConditions.erase(L"capture_the_relic"); + + if (wxDynamicCast(FindWindow(ID_VC_Wonder), wxCheckBox)->GetValue()) + m_MapSettingsVictoryConditions.insert(L"wonder"); + else + m_MapSettingsVictoryConditions.erase(L"wonder"); + + if (wxDynamicCast(FindWindow(ID_VC_Regicide), wxCheckBox)->GetValue()) + m_MapSettingsVictoryConditions.insert(L"regicide"); + else + m_MapSettingsVictoryConditions.erase(L"regicide"); + + AtObj victoryConditions; + victoryConditions.set("@array", L""); + for (std::set::iterator it = m_MapSettingsVictoryConditions.begin(); it != m_MapSettingsVictoryConditions.end(); ++it) + victoryConditions.add("item", it->c_str()); + m_MapSettings.set("VictoryConditions", victoryConditions); // keywords {