1
0
forked from 0ad/0ad

Implement combine victory conditions

Excluding the changes to scenario and skirmisch maps
Transform gameType string to victoryCondition array in load/replaymenu
Adapt the gamesetup to use checkboxes for every victory condition and an
array for storing them
Allow multiple queries in conquestCommon
Remove conquest from regicide, wonder and capture the relic
Move the endless gamedescription from settings to gamedescription
Fixing wrong tabulation from a8a29271ce

This commit will break all scenario and skirmisch maps, their "Gametype"
string needs to be transformed in a "VictoryCondition" array as is done
in the tutorial map (counting endless as an empty array). This counts
for mods too!
Old svn replays and savegame will throw warnings/errors as they are
incompatible after this commit. So svn users will need to delete all
those.

Comments on ai and autostart games By: mimo
Comments on Atlas By: Vladislav
Reviewed By: elexis
Differential Revision: https://code.wildfiregames.com/D1240
fixes: #4014

This was SVN commit r21474.
This commit is contained in:
bb 2018-03-09 21:51:18 +00:00
parent b9a53529b9
commit 6d54ab4c1f
34 changed files with 311 additions and 209 deletions

View File

@ -216,12 +216,23 @@ function formatPlayerInfo(playerDataArray, playerStates)
function getGameDescription(extended = false)
{
let titles = [];
if (!g_GameAttributes.settings.VictoryConditions.length)
titles.push({
"label": translateWithContext("victory condition", "Endless Game"),
"value": translate("No winner will be determined, even if everyone is defeated.")
});
let victoryIdx = g_VictoryConditions.Name.indexOf(g_GameAttributes.settings.GameType || g_VictoryConditions.Default);
if (victoryIdx != -1)
let victoryConditions = g_GameAttributes.settings.VictoryConditions.map(victoryConditionName =>
g_VictoryConditions.find(victoryCondition => victoryCondition.Name == victoryConditionName) || {
"Name": victoryConditionName,
"Description": ""
});
for (let victoryCondition of victoryConditions.sort((a, b) =>
a.GUIOrder - b.GUIOrder || (a.Title > b.Title ? 1 : a.Title > b.Title ? -1 : 0)))
{
let title = g_VictoryConditions.Title[victoryIdx];
if (g_VictoryConditions.Name[victoryIdx] == "wonder")
let title = translateVictoryCondition(victoryCondition.Name);
if (victoryCondition.Name == "wonder")
title = sprintf(
translatePluralWithContext(
"victory condition",
@ -232,7 +243,7 @@ function getGameDescription(extended = false)
{ "min": g_GameAttributes.settings.WonderDuration }
);
let isCaptureTheRelic = g_VictoryConditions.Name[victoryIdx] == "capture_the_relic";
let isCaptureTheRelic = victoryCondition.Name == "capture_the_relic";
if (isCaptureTheRelic)
title = sprintf(
translatePluralWithContext(
@ -246,7 +257,7 @@ function getGameDescription(extended = false)
titles.push({
"label": title,
"value": g_VictoryConditions.Description[victoryIdx]
"value": victoryCondition.Description
});
if (isCaptureTheRelic)
@ -255,7 +266,7 @@ function getGameDescription(extended = false)
"value": g_GameAttributes.settings.RelicCount
});
if (g_VictoryConditions.Name[victoryIdx] == "regicide")
if (victoryCondition.Name == "regicide")
if (g_GameAttributes.settings.RegicideGarrison)
titles.push({
"label": translate("Hero Garrison"),
@ -264,7 +275,7 @@ function getGameDescription(extended = false)
else
titles.push({
"label": translate("Exposed Heroes"),
"value": translate("Heroes cannot be garrisoned, and they are vulnerable to raids.")
"value": translate("Heroes cannot be garrisoned and they are vulnerable to raids.")
});
}

View File

@ -247,7 +247,7 @@ function loadBiomes()
}
/**
* Loads available gametypes.
* Loads available victoryCondtions from json files.
*
* @returns {Array|undefined}
*/
@ -256,24 +256,15 @@ function loadVictoryConditions()
let subdir = "victory_conditions/";
let victoryConditions = listFiles(g_SettingsDirectory + subdir, ".json", false).map(victoryScriptName => {
let vc = loadSettingValuesFile(subdir + victoryScriptName + ".json");
if (vc)
vc.Name = victoryScriptName;
return vc;
let victoryCondition = loadSettingValuesFile(subdir + victoryScriptName + ".json");
if (victoryCondition)
victoryCondition.Name = victoryScriptName;
return victoryCondition;
});
if (victoryConditions.some(vc => vc == undefined))
if (victoryConditions.some(victoryCondition => victoryCondition == 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": translateWithContext("victory condition", "None"),
"Description": translate("Endless game."),
"Scripts": []
});
return victoryConditions;
}
@ -428,11 +419,11 @@ function translatePopulationCapacity(population)
/**
* Returns title or placeholder.
*
* @param {string} gameType - for example "conquest"
* @param {string} victoryConditionName - For example "conquest".
* @returns {string}
*/
function translateVictoryCondition(gameType)
function translateVictoryCondition(victoryConditionName)
{
let victoryCondition = g_Settings.VictoryConditions.find(vc => vc.Name == gameType);
return victoryCondition ? victoryCondition.Title : translateWithContext("victory condition", "Unknown");
let victoryCondition = g_Settings.VictoryConditions.find(victoryCondition => victoryCondition.Name == victoryConditionName);
return victoryCondition ? victoryCondition.Title : translate("Unknown Victory Condition");
}

View File

@ -7,8 +7,9 @@ const g_MapTypes = prepareForDropdown(g_Settings && g_Settings.MapTypes);
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);
/**
@ -433,7 +434,7 @@ var g_SettingsTabsGUI = [
{
"label": translateWithContext("Match settings tab name", "Game Type"),
"settings": [
"victoryCondition",
...g_VictoryConditions.map(victoryCondition => victoryCondition.Name),
"relicCount",
"relicDuration",
"wonderDuration",
@ -640,22 +641,6 @@ var g_Dropdowns = {
"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."),
@ -667,7 +652,7 @@ var g_Dropdowns = {
"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
},
@ -682,7 +667,7 @@ var g_Dropdowns = {
"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
},
@ -697,7 +682,7 @@ var g_Dropdowns = {
"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
},
@ -822,7 +807,34 @@ var g_PlayerDropdowns = {
/**
* Contains the logic of all boolean gamesettings.
*/
var g_Checkboxes = {
var g_Checkboxes = Object.assign(
{},
g_VictoryConditions.reduce((obj, victoryCondition) => {
obj[victoryCondition.Name] = {
"title": () => victoryCondition.Title,
"tooltip": () => victoryCondition.Description,
// Defaults are set in supplementDefault directly from g_VictoryConditions since we use an array
"defined": () => true,
"get": () => g_GameAttributes.settings.VictoryConditions.indexOf(victoryCondition.Name) != -1,
"set": checked => {
if (checked)
{
g_GameAttributes.settings.VictoryConditions.push(victoryCondition.Name);
if (victoryCondition.Set)
for (let setting in victoryCondition.ChangeWhenChecked)
g_Checkboxes[setting].set(victoryCondition.ChangeOnChecked[setting]);
}
else
g_GameAttributes.settings.VictoryConditions = g_GameAttributes.settings.VictoryConditions.filter(victoryConditionName => victoryConditionName != victoryCondition.Name);
},
"enabled": () =>
g_GameAttributes.mapType != "scenario" &&
(!victoryCondition.DisabledWhenChecked ||
victoryCondition.DisabledWhenChecked.every(victoryConditionName => g_GameAttributes.settings.VictoryConditions.indexOf(victoryConditionName) == -1))
};
return obj;
}, {}),
{
"regicideGarrison": {
"title": () => translate("Hero Garrison"),
"tooltip": () => translate("Toggle whether heroes can be garrisoned."),
@ -832,7 +844,7 @@ var g_Checkboxes = {
"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
},
@ -968,7 +980,8 @@ var g_Checkboxes = {
},
"initOrder": 1000
},
};
}
);
/**
* For setting up arbitrary GUI objects.
@ -1149,6 +1162,9 @@ function initDefaults()
*/
function supplementDefaults()
{
g_GameAttributes.settings.VictoryConditions = g_GameAttributes.settings.VictoryConditions ||
g_VictoryConditions.filter(victoryCondition => !!victoryCondition.Default).map(victoryCondition => victoryCondition.Name);
for (let dropdown in g_Dropdowns)
if (!g_Dropdowns[dropdown].defined())
g_Dropdowns[dropdown].select(g_Dropdowns[dropdown].default());
@ -1987,14 +2003,8 @@ function selectMap(name)
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;
@ -2134,13 +2144,7 @@ function launchGame()
// 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(
@ -2148,6 +2152,11 @@ function launchGame()
g_BiomeList.Id.slice(1).filter(biomeID => biomeID.startsWith(g_GameAttributes.settings.SupportedBiomes)) :
g_GameAttributes.settings.SupportedBiomes);
g_GameAttributes.settings.VictoryScripts = g_GameAttributes.settings.VictoryConditions.reduce(
(scripts, victoryConditionName) => scripts.concat(g_VictoryConditions[g_VictoryConditions.map(data =>
data.Name).indexOf(victoryConditionName)].Scripts.filter(script => scripts.indexOf(script) == -1)),
[]);
g_GameAttributes.settings.TriggerScripts = g_GameAttributes.settings.VictoryScripts.concat(g_GameAttributes.settings.TriggerScripts || []);
// Prevent reseting the readystate
@ -2640,7 +2649,7 @@ function sendRegisterGameStanzaImmediate()
"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,

View File

@ -113,7 +113,7 @@ function selectionChanged()
Engine.GetGUIObjectByName("savedPlayedTime").caption = timeToString(metadata.gui.timeElapsed ? metadata.gui.timeElapsed : 0);
Engine.GetGUIObjectByName("savedMapType").caption = translateMapType(metadata.initAttributes.mapType);
Engine.GetGUIObjectByName("savedMapSize").caption = translateMapSize(metadata.initAttributes.settings.Size);
Engine.GetGUIObjectByName("savedVictory").caption = translateVictoryCondition(metadata.initAttributes.settings.GameType);
Engine.GetGUIObjectByName("savedVictory").caption = metadata.initAttributes.settings.VictoryConditions.map(victoryConditionName => translateVictoryCondition(victoryConditionName)).join(translate(", "));
let caption = sprintf(translate("Mods: %(mods)s"), { "mods": modsToString(metadata.mods) });
if (!hasSameMods(metadata.mods, Engine.GetEngineInfo().mods))

View File

@ -97,17 +97,17 @@
<translatableAttribute id="caption">Map Size:</translatableAttribute>
</object>
<object name="savedMapSize" size="50% 310 100%-15 330" type="text" style="ModernLeftLabelText" />
<object size="0 330 50% 350" type="text" style="ModernLeftLabelText">
<object size="0 330 50% 370" type="text" style="ModernLeftLabelText">
<translatableAttribute id="caption">Victory:</translatableAttribute>
</object>
<object name="savedVictory" size="50% 330 100%-15 350" type="text" style="ModernLeftLabelText" />
<object name="savedVictory" size="50% 330 100%-15 370" type="text" style="ModernText" font="sans-bold-stroke-14" />
<object size="0 352 100%-15 353" type="image" sprite="ModernWhiteLine" z="25" />
<object size="0 372 100%-15 373" type="image" sprite="ModernWhiteLine" z="25" />
<object name="savedMods" size="0 355 100%-15 395" type="text" style="ModernLeftLabelText" />
<object name="savedMods" size="0 375 100%-15 415" type="text" style="ModernLeftLabelText" />
<object size="0 397 100%-15 398" type="image" sprite="ModernWhiteLine" z="25" />
<object name="savedPlayersNames" size="0 400 100%-10 100%-32" type="text" style="MapPlayerList" />
<object size="0 417 100%-15 418" type="image" sprite="ModernWhiteLine" z="25" />
<object name="savedPlayersNames" size="0 420 100%-10 100%-32" type="text" style="MapPlayerList" />
<object size="0 100%-32 100%-15 100%-31" type="image" sprite="ModernWhiteLine" z="25" />
</object>

View File

@ -152,8 +152,8 @@ function initSingleplayerFilter(filters)
function initVictoryConditionFilter(filters)
{
let victoryConditionFilter = Engine.GetGUIObjectByName("victoryConditionFilter");
victoryConditionFilter.list = [translateWithContext("victory condition", "Any gametype")].concat(g_VictoryConditions.map(vc => translateVictoryCondition(vc)));
victoryConditionFilter.list_data = [""].concat(g_VictoryConditions);
victoryConditionFilter.list = [translate("Any Victory Condition")].concat(g_VictoryConditions.map(victoryCondition => translateVictoryCondition(victoryCondition.Name)));
victoryConditionFilter.list_data = [""].concat(g_VictoryConditions.map(victoryCondition => victoryCondition.Name));
if (filters && filters.victoryCondition)
victoryConditionFilter.selected = victoryConditionFilter.list_data.indexOf(filters.victoryCondition);
@ -243,7 +243,8 @@ function filterReplay(replay)
// 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

View File

@ -36,7 +36,7 @@ var g_MapNames = [];
/**
* Sorted list of the victory conditions occuring in the replays
*/
var g_VictoryConditions = [];
var g_VictoryConditions = g_Settings && g_Settings.VictoryConditions;
/**
* Directory name of the currently selected replay. Used to restore the selection after changing filters.
@ -108,10 +108,6 @@ function loadReplays(replaySelectionData, compareFiles)
if (g_MapNames.indexOf(replay.attribs.settings.Name) == -1 && replay.attribs.settings.Name != "")
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);
// Extract playernames
for (let playerData of replay.attribs.settings.PlayerData)
{
@ -138,7 +134,6 @@ function loadReplays(replaySelectionData, compareFiles)
}
g_MapNames.sort();
g_VictoryConditions.sort();
// Reload filters (since they depend on g_Replays and its derivatives)
initFilters(replaySelectionData && replaySelectionData.filters);
@ -182,9 +177,6 @@ function sanitizeGameAttributes(attribs)
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 +268,8 @@ function displayReplayDetails()
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(victoryConditionName =>
translateVictoryCondition(victoryConditionName)).join(translate(", "));
Engine.GetGUIObjectByName("sgNbPlayers").caption = sprintf(translate("Players: %(numberOfPlayers)s"),
{ "numberOfPlayers": replay.attribs.settings.PlayerData.length });
Engine.GetGUIObjectByName("replayFilename").caption = Engine.GetReplayDirectoryName(replay.directory);

View File

@ -175,22 +175,22 @@
<object size="5 254 100%-5 255" type="image" sprite="ModernWhiteLine" z="25"/>
<!-- Victory Condition Caption -->
<object size="5 255 50% 285" type="image" sprite="ModernItemBackShadeLeft">
<object size="5 255 50% 295" type="image" sprite="ModernItemBackShadeLeft">
<object size="0 0 100%-10 100%" type="text" style="ModernRightLabelText">
<translatableAttribute id="caption">Victory:</translatableAttribute>
</object>
</object>
<!-- Victory Condition Label -->
<object size="50% 255 100%-5 285" type="image" sprite="ModernItemBackShadeRight">
<object name="sgVictory" size="0 0 100% 100%" type="text" style="ModernLeftLabelText"/>
<object size="50% 255 100%-5 295" type="image" sprite="ModernItemBackShadeRight">
<object name="sgVictory" size="0 0 100% 100%" type="text" style="ModernText" font="sans-bold-stroke-14"/>
</object>
<!-- Separator Line -->
<object size="5 284 100%-5 285" type="image" sprite="ModernWhiteLine" z="25"/>
<object size="5 294 100%-5 295" type="image" sprite="ModernWhiteLine" z="25"/>
<!-- Map Description Text -->
<object type="image" sprite="ModernDarkBoxWhite" size="5 290 100%-5 40%+170">
<object type="image" sprite="ModernDarkBoxWhite" size="5 300 100%-5 40%+170">
<object name="sgMapDescription" size="0 1 100% 100%-1" type="text" style="ModernText" font="sans-12"/>
</object>

View File

@ -7,8 +7,9 @@ const g_MapSizes = prepareForDropdown(g_Settings && g_Settings.MapSizes);
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;
/**

View File

@ -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": []
}
}

View File

@ -12,7 +12,7 @@ Trigger.prototype.InitCaptureTheRelic = function()
}
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;
@ -132,7 +132,7 @@ Trigger.prototype.StartCaptureTheRelicCountdown = function(winningPlayers)
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 = winningPlayers.length > 1;
this.ownRelicsVictoryMessage = cmpGuiInterface.AddTimeNotification({

View File

@ -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.ConquestAddVictoryCondition({
"classFilter": "ConquestCritical",
"defeatReason": markForTranslation("%(player)s has been defeated (lost all critical units and structures).")
});
}

View File

@ -1,17 +1,20 @@
Trigger.prototype.ConquestOwnershipChanged = function(msg)
{
if (!this.conquestDataInit || !this.conquestClassFilter)
if (!this.conquestDataInit)
return;
if (!TriggerHelper.EntityMatchesClassList(msg.entity, this.conquestClassFilter))
return;
for (let query of this.conquestQueries)
{
if (!TriggerHelper.EntityMatchesClassList(msg.entity, query.classFilter))
continue;
if (msg.to > 0)
this.conquestEntitiesByPlayer[msg.to].push(msg.entity);
query.entitiesByPlayer[msg.to].push(msg.entity);
if (msg.from > 0)
{
let entities = this.conquestEntitiesByPlayer[msg.from];
if (msg.from <= 0)
continue;
let entities = query.entitiesByPlayer[msg.from];
let index = entities.indexOf(msg.entity);
if (index != -1)
entities.splice(index, 1);
@ -20,35 +23,40 @@ Trigger.prototype.ConquestOwnershipChanged = function(msg)
{
let cmpPlayer = QueryPlayerIDInterface(msg.from);
if (cmpPlayer)
cmpPlayer.SetState("defeated", this.conquestDefeatReason);
cmpPlayer.SetState("defeated", query.defeatReason);
}
}
};
Trigger.prototype.ConquestStartGameCount = function()
{
if (!this.conquestClassFilter)
if (!this.conquestQueries.length)
{
warn("ConquestStartGameCount: conquestClassFilter undefined");
warn("ConquestStartGameCount: no conquestQueries set");
return;
}
let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
let entitiesByPlayer = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetAllPlayers().map(playerID =>
cmpRangeManager.GetEntitiesByPlayer(playerID));
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));
for (let query of this.conquestQueries)
query.entitiesByPlayer = entitiesByPlayer.map(
ents => ents.filter(
ent => TriggerHelper.EntityMatchesClassList(ent, query.classFilter)));
this.conquestDataInit = true;
};
Trigger.prototype.ConquestAddVictoryCondition = function(data)
{
this.conquestQueries.push(data);
};
{
let cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
cmpTrigger.conquestEntitiesByPlayer = {};
cmpTrigger.conquestDataInit = false;
cmpTrigger.conquestClassFilter = "";
cmpTrigger.conquestQueries = [];
cmpTrigger.RegisterTrigger("OnOwnershipChanged", "ConquestOwnershipChanged", { "enabled": true });
cmpTrigger.DoAfterDelay(0, "ConquestStartGameCount", null);
}

View File

@ -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.ConquestAddVictoryCondition({
"classFilter": "Structure",
"defeatReason": markForTranslation("%(player)s has been defeated (lost all structures).")
});
}

View File

@ -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.ConquestAddVictoryCondition({
"classFilter": "Unit+!Animal",
"defeatReason": markForTranslation("%(player)s has been defeated (lost all units).")
});
}

View File

@ -9,7 +9,7 @@ Trigger.prototype.CheckRegicideDefeat = function(data)
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)

View File

@ -54,7 +54,7 @@ Trigger.prototype.WonderVictoryStartTimer = function(ent, player)
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),

Binary file not shown.

View File

@ -74,7 +74,7 @@ m.SharedScript.prototype.init = function(state, deserialization)
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;

View File

@ -1,5 +1,5 @@
/**
* System component to store the gametype, gametype settings and
* System component to store the victory conditions and their settings and
* check for allied victory / last-man-standing.
*/
function EndGameManager() {}
@ -9,11 +9,9 @@ EndGameManager.prototype.Schema =
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 @@ EndGameManager.prototype.Init = function()
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, {});
};
/**

View File

@ -154,7 +154,7 @@ GuiInterface.prototype.GetSimulationState = function()
// 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

View File

@ -4,4 +4,4 @@ Engine.RegisterInterface("EndGameManager");
* Message of the form {}
* sent from EndGameManager component.
*/
Engine.RegisterMessageType("GameTypeChanged");
Engine.RegisterMessageType("VictoryConditionsChanged");

View File

@ -23,7 +23,10 @@ AddMock(playerEnt1, IID_Player, {
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);

View File

@ -65,7 +65,7 @@ AddMock(SYSTEM_ENTITY, IID_Barter, {
});
AddMock(SYSTEM_ENTITY, IID_EndGameManager, {
GetGameType: function() { return "conquest"; },
GetVictoryConditions: () => ["conquest", "wonder"],
GetAlliedVictory: function() { return false; }
});
@ -365,7 +365,7 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetSimulationState(), {
],
circularMap: false,
timeElapsed: 0,
gameType: "conquest",
"victoryConditions": ["conquest", "wonder"],
alliedVictory: false
});
@ -518,7 +518,7 @@ TS_ASSERT_UNEVAL_EQUALS(cmp.GetExtendedSimulationState(), {
],
"circularMap": false,
"timeElapsed": 0,
"gameType": "conquest",
"victoryConditions": ["conquest", "wonder"],
"alliedVictory": false
});

View File

@ -7,9 +7,8 @@
"Scripts":
[
"scripts/TriggerHelper.js",
"scripts/ConquestCommon.js",
"scripts/Conquest.js",
"scripts/CaptureTheRelic.js"
]
],
"GUIOrder": 10
}
}

View File

@ -3,13 +3,18 @@
"Data":
{
"Title": "Conquest",
"Description": "Defeat all opponents to win.",
"Description": "Defeat opponents by killing all their units and destroying all their structures.",
"Scripts":
[
"scripts/TriggerHelper.js",
"scripts/ConquestCommon.js",
"scripts/Conquest.js"
],
"Default": true
"Default": true,
"ChangeOnChecked": {
"conquest_units": false,
"conquest_structures": false
},
"GUIOrder": 0
}
}

View File

@ -3,12 +3,14 @@
"Data":
{
"Title": "Conquest Structures",
"Description": "Destroy all enemy structures to win.",
"Description": "Defeat opponents by destroying all their structures.",
"Scripts":
[
"scripts/TriggerHelper.js",
"scripts/ConquestCommon.js",
"scripts/ConquestStructures.js"
]
],
"DisabledWhenChecked": ["conquest"],
"GUIOrder": 1
}
}

View File

@ -3,12 +3,14 @@
"Data":
{
"Title": "Conquest Units",
"Description": "Kill all enemy units to win.",
"Description": "Defeat opponents by killing all their units.",
"Scripts":
[
"scripts/TriggerHelper.js",
"scripts/ConquestCommon.js",
"scripts/ConquestUnits.js"
]
],
"DisabledWhenChecked": ["conquest"],
"GUIOrder": 1
}
}

View File

@ -7,9 +7,8 @@
"Scripts":
[
"scripts/TriggerHelper.js",
"scripts/ConquestCommon.js",
"scripts/Conquest.js",
"scripts/Regicide.js"
]
],
"GUIOrder": 10
}
}

View File

@ -7,9 +7,8 @@
"Scripts":
[
"scripts/TriggerHelper.js",
"scripts/ConquestCommon.js",
"scripts/Conquest.js",
"scripts/WonderVictory.js"
]
],
"GUIOrder": 10
}
}

View File

@ -53,17 +53,17 @@ function LoadMapSettings(settings)
}
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 = { "victoryConditions": settings.VictoryConditions };
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)

View File

@ -1464,16 +1464,22 @@ bool Autostart(const CmdLineArgs& args)
triggerScriptsVector.push_back(nonVisualScript.FromUTF8());
}
CStr victory = "conquest";
std::vector<CStr> victoryConditions(1, "conquest");
if (args.Has("autostart-victory"))
victory = args.Get("autostart-victory");
victoryConditions = args.GetMultiple("autostart-victory");
scriptInterface.SetProperty(settings, "GameType", std::string(victory));
if (victoryConditions.size() == 1 && victoryConditions[0] == "endless")
victoryConditions.clear();
CStrW scriptPath = L"simulation/data/settings/victory_conditions/" + victory.FromUTF8() + L".json";
scriptInterface.SetProperty(settings, "VictoryConditions", victoryConditions);
for (const CStr& victory : victoryConditions)
{
JS::RootedValue scriptData(cx);
JS::RootedValue data(cx);
JS::RootedValue victoryScripts(cx);
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())
@ -1482,6 +1488,13 @@ bool Autostart(const CmdLineArgs& args)
FromJSVal_vector(cx, victoryScripts, victoryScriptsVector);
triggerScriptsVector.insert(triggerScriptsVector.end(), victoryScriptsVector.begin(), victoryScriptsVector.end());
}
else
{
LOGERROR("Autostart: Error reading victory script '%s'", utf8_from_wstring(scriptPath));
throw PSERROR_Game_World_MapLoadFailed("Error reading victory script.\nCheck application log for details.");
}
}
ToJSVal_vector(cx, &triggerScripts, triggerScriptsVector);
scriptInterface.SetProperty(settings, "TriggerScripts", triggerScripts);

View File

@ -41,6 +41,12 @@ enum
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,
@ -97,13 +103,17 @@ public:
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<std::wstring> m_MapSettingsKeywords;
std::set<std::wstring> m_MapSettingsVictoryConditions;
std::vector<wxChoice*> m_PlayerCivChoices;
Observable<AtObj>& m_MapSettings;
@ -146,31 +156,34 @@ void MapSettingsControl::CreateWidgets()
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?
gridSizer->Add(new wxStaticText(this, wxID_ANY, _("Preview")), wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT));
gridSizer->Add(Tooltipped(new wxTextCtrl(this, ID_MapPreview, wxEmptyString),
_("Texture used for map preview")), wxSizerFlags().Expand());
CREATE_CHECKBOX(this, gridSizer, "Reveal map", "If checked, players won't need to explore", ID_MapReveal);
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());
CREATE_CHECKBOX(this, gridSizer, "Lock teams", "If checked, teams will be locked", ID_MapTeams);
sizer->Add(gridSizer, wxSizerFlags().Expand());
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, 0, 5);
vcGridSizer->AddGrowableCol(1);
CREATE_CHECKBOX(this, vcGridSizer, "Conquest", "Select Conquest victory condition", ID_VC_Conquest);
CREATE_CHECKBOX(this, vcGridSizer, "Conquest Units", "Select Conquest Units victory condition", ID_VC_ConquestUnits);
CREATE_CHECKBOX(this, vcGridSizer, "Conquest Structures", "Select Conquest Structures victory condition", ID_VC_ConquestStructures);
CREATE_CHECKBOX(this, vcGridSizer, "Capture the Relic", "Select Capture the Relic victory condition", ID_VC_CaptureTheRelic);
CREATE_CHECKBOX(this, vcGridSizer, "Wonder", "Select Wonder victory condition", ID_VC_Wonder);
CREATE_CHECKBOX(this, vcGridSizer, "Regicide", "Select Regicide victory condition", ID_VC_Regicide);
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);
CREATE_CHECKBOX(this, kwGridSizer, "Demo", "If checked, map will only be visible using filters in game setup", ID_MapKW_Demo);
@ -201,11 +214,24 @@ void MapSettingsControl::ReadFromEngine()
// 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));
wxWindow* window;
#define INIT_CHECKBOX(ID, mapSettings, value) \
window = FindWindow(ID); \
if (window != nullptr) \
wxDynamicCast(window, wxCheckBox)->SetValue(mapSettings.count(value) != 0);
INIT_CHECKBOX(ID_VC_Conquest, m_MapSettingsVictoryConditions, L"conquest");
INIT_CHECKBOX(ID_VC_ConquestUnits, m_MapSettingsVictoryConditions, L"conquest_units");
INIT_CHECKBOX(ID_VC_ConquestStructures, m_MapSettingsVictoryConditions, L"conquest_structures");
INIT_CHECKBOX(ID_VC_CaptureTheRelic, m_MapSettingsVictoryConditions, L"capture_the_relic");
INIT_CHECKBOX(ID_VC_Wonder, m_MapSettingsVictoryConditions, L"wonder");
INIT_CHECKBOX(ID_VC_Regicide, m_MapSettingsVictoryConditions, L"regicide");
OnConquestChanged();
// lock teams
wxDynamicCast(FindWindow(ID_MapTeams), wxCheckBox)->SetValue(wxString(m_MapSettings["LockTeams"]) == L"true");
@ -216,9 +242,11 @@ void MapSettingsControl::ReadFromEngine()
for (AtIter keyword = m_MapSettings["Keywords"]["item"]; keyword.defined(); ++keyword)
m_MapSettingsKeywords.insert(std::wstring(keyword));
wxDynamicCast(FindWindow(ID_MapKW_Demo), wxCheckBox)->SetValue(m_MapSettingsKeywords.count(L"demo") != 0);
wxDynamicCast(FindWindow(ID_MapKW_Naval), wxCheckBox)->SetValue(m_MapSettingsKeywords.count(L"naval") != 0);
INIT_CHECKBOX(ID_MapKW_Demo, m_MapSettingsKeywords, L"demo");
INIT_CHECKBOX(ID_MapKW_Naval, m_MapSettingsKeywords, L"naval");
}
#undef INIT_CHECKBOX
}
void MapSettingsControl::SetMapSettings(const AtObj& obj)
@ -229,6 +257,22 @@ void MapSettingsControl::SetMapSettings(const AtObj& obj)
SendToEngine();
}
// TODO Use the json data for this
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
@ -243,8 +287,27 @@ AtObj MapSettingsControl::UpdateSettingsObject()
// 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
#define INSERT_VICTORY_CONDITION_CHECKBOX(name, ID) \
if (wxDynamicCast(FindWindow(ID), wxCheckBox)->GetValue()) \
m_MapSettingsVictoryConditions.insert(name); \
else \
m_MapSettingsVictoryConditions.erase(name);
INSERT_VICTORY_CONDITION_CHECKBOX(L"conquest", ID_VC_Conquest);
INSERT_VICTORY_CONDITION_CHECKBOX(L"conquest_units", ID_VC_ConquestUnits);
INSERT_VICTORY_CONDITION_CHECKBOX(L"conquest_structures", ID_VC_ConquestStructures);
INSERT_VICTORY_CONDITION_CHECKBOX(L"capture_the_relic", ID_VC_CaptureTheRelic);
INSERT_VICTORY_CONDITION_CHECKBOX(L"wonder", ID_VC_Wonder);
INSERT_VICTORY_CONDITION_CHECKBOX(L"regicide", ID_VC_Regicide);
#undef INSERT_VICTORY_CONDITION_CHECKBOX
AtObj victoryConditions;
victoryConditions.set("@array", L"");
for (std::set<std::wstring>::iterator it = m_MapSettingsVictoryConditions.begin(); it != m_MapSettingsVictoryConditions.end(); ++it)
victoryConditions.add("item", it->c_str());
m_MapSettings.set("VictoryConditions", victoryConditions);
// keywords
{