Capture The Relic gamemode.

Patch By: Sandarac
Differential Revision: https://code.wildfiregames.com/D152
This was SVN commit r19345.
This commit is contained in:
elexis 2017-03-25 07:01:07 +00:00
parent 27f37ccd21
commit 35377c51a7
15 changed files with 305 additions and 38 deletions

View File

@ -195,10 +195,22 @@ function getGameDescription(extended = false)
"victory condition",
"Wonder (%(min)s minute)",
"Wonder (%(min)s minutes)",
g_GameAttributes.settings.WonderDuration
g_GameAttributes.settings.VictoryDuration
),
{ "min": g_GameAttributes.settings.WonderDuration }
{ "min": g_GameAttributes.settings.VictoryDuration }
);
else if (g_VictoryConditions.Name[victoryIdx] == "capture_the_relic")
title = sprintf(
translatePluralWithContext(
"victory condition",
"Capture The Relic (%(min)s minute)",
"Capture The Relic (%(min)s minutes)",
g_GameAttributes.settings.VictoryDuration
),
{ "min": g_GameAttributes.settings.VictoryDuration }
);
titles.push({
"label": title,
"value": g_VictoryConditions.Description[victoryIdx]

View File

@ -32,7 +32,7 @@ function loadSettingsValues()
"AIDescriptions": loadAIDescriptions(),
"AIDifficulties": loadAIDifficulties(),
"Ceasefire": loadCeasefire(),
"WonderDurations": loadWonderDuration(),
"VictoryDurations": loadVictoryDuration(),
"GameSpeeds": loadSettingValuesFile("game_speeds.json"),
"MapTypes": loadMapTypes(),
"MapSizes": loadSettingValuesFile("map_sizes.json"),
@ -132,11 +132,11 @@ function loadAIDifficulties()
}
/**
* Loads available wonder-victory times
* Loads available victory times for victory conditions like Wonder and Capture The Relic.
*/
function loadWonderDuration()
function loadVictoryDuration()
{
var jsonFile = "wonder_times.json";
var jsonFile = "victory_times.json";
var json = Engine.ReadJSONFile(g_SettingsDirectory + jsonFile);
if (!json || json.Default === undefined || !json.Times || !Array.isArray(json.Times))
@ -148,7 +148,7 @@ function loadWonderDuration()
return json.Times.map(duration => ({
"Duration": duration,
"Default": duration == json.Default,
"Title": sprintf(translatePluralWithContext("wonder victory", "%(min)s minute", "%(min)s minutes", duration), { "min": duration })
"Title": sprintf(translatePluralWithContext("victory duration", "%(min)s minute", "%(min)s minutes", duration), { "min": duration })
}));
}

View File

@ -8,7 +8,7 @@ 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_WonderDurations = prepareForDropdown(g_Settings && g_Settings.WonderDurations);
const g_VictoryDurations = prepareForDropdown(g_Settings && g_Settings.VictoryDurations);
/**
* All selectable playercolors except gaia.
@ -306,8 +306,8 @@ function initGUIObjects()
initPopulationCaps();
initStartingResources();
initCeasefire();
initWonderDurations();
initVictoryConditions();
initVictoryDurations();
initMapSizes();
initRadioButtons();
}
@ -380,7 +380,7 @@ function saveSPTipsSetting()
}
/**
* Remove empty space in case of hidden options (like cheats, rating or wonder duration)
* Remove empty space in case of hidden options (like cheats, rating or victory duration)
*/
function resizeMoreOptionsWindow()
{
@ -501,19 +501,19 @@ function initVictoryConditions()
victoryConditions.selected = g_VictoryConditions.Default;
}
function initWonderDurations()
function initVictoryDurations()
{
let wonderConditions = Engine.GetGUIObjectByName("wonderDuration");
wonderConditions.list = g_WonderDurations.Title;
wonderConditions.list_data = g_WonderDurations.Duration;
wonderConditions.onSelectionChange = function()
let victoryDurationsConditions = Engine.GetGUIObjectByName("victoryDuration");
victoryDurationsConditions.list = g_VictoryDurations.Title;
victoryDurationsConditions.list_data = g_VictoryDurations.Duration;
victoryDurationsConditions.onSelectionChange = function()
{
if (this.selected != -1)
g_GameAttributes.settings.WonderDuration = g_WonderDurations.Duration[this.selected];
g_GameAttributes.settings.VictoryDuration = g_VictoryDurations.Duration[this.selected];
updateGameAttributes();
};
wonderConditions.selected = g_WonderDurations.Default;
victoryDurationsConditions.selected = g_VictoryDurations.Default;
}
function initMapSizes()
@ -1261,7 +1261,7 @@ function selectMap(name)
if (g_GameAttributes.mapType == "scenario")
{
delete g_GameAttributes.settings.WonderDuration;
delete g_GameAttributes.settings.VictoryDuration;
delete g_GameAttributes.settings.LastManStanding;
}
@ -1401,7 +1401,7 @@ function updateGUIObjects()
// These dropdowns might set the default (as they ignore g_IsInGuiUpdate)
let mapSizeIdx = mapSettings.Size !== undefined ? g_MapSizes.Tiles.indexOf(mapSettings.Size) : g_MapSizes.Default;
let victoryIdx = mapSettings.GameType !== undefined ? g_VictoryConditions.Name.indexOf(mapSettings.GameType) : g_VictoryConditions.Default;
let wonderDurationIdx = mapSettings.WonderDuration !== undefined ? g_WonderDurations.Duration.indexOf(mapSettings.WonderDuration) : g_WonderDurations.Default;
let victoryDurationIdx = mapSettings.VictoryDuration !== undefined ? g_VictoryDurations.Duration.indexOf(mapSettings.VictoryDuration) : g_VictoryDurations.Default;
let popIdx = mapSettings.PopulationCap !== undefined ? g_PopulationCapacities.Population.indexOf(mapSettings.PopulationCap) : g_PopulationCapacities.Default;
let startingResIdx = mapSettings.StartingResources !== undefined ? g_StartingResources.Resources.indexOf(mapSettings.StartingResources) : g_StartingResources.Default;
let ceasefireIdx = mapSettings.Ceasefire !== undefined ? g_Ceasefire.Duration.indexOf(mapSettings.Ceasefire) : g_Ceasefire.Default;
@ -1415,7 +1415,7 @@ function updateGUIObjects()
Engine.GetGUIObjectByName("mapSize").selected = mapSizeIdx;
Engine.GetGUIObjectByName("numPlayers").selected = numPlayers - 1;
Engine.GetGUIObjectByName("victoryCondition").selected = victoryIdx;
Engine.GetGUIObjectByName("wonderDuration").selected = wonderDurationIdx;
Engine.GetGUIObjectByName("victoryDuration").selected = victoryDurationIdx;
Engine.GetGUIObjectByName("populationCap").selected = popIdx;
Engine.GetGUIObjectByName("gameSpeed").selected = gameSpeedIdx;
Engine.GetGUIObjectByName("ceasefire").selected = ceasefireIdx;
@ -1433,7 +1433,7 @@ function updateGUIObjects()
Engine.GetGUIObjectByName("mapSizeText").caption = g_GameAttributes.mapType == "random" ? g_MapSizes.Name[mapSizeIdx] : translateWithContext("map size", "Default");
Engine.GetGUIObjectByName("numPlayersText").caption = numPlayers;
Engine.GetGUIObjectByName("victoryConditionText").caption = g_VictoryConditions.Title[victoryIdx];
Engine.GetGUIObjectByName("wonderDurationText").caption = g_WonderDurations.Title[wonderDurationIdx];
Engine.GetGUIObjectByName("victoryDurationText").caption = g_VictoryDurations.Title[victoryDurationIdx];
Engine.GetGUIObjectByName("populationCapText").caption = g_PopulationCapacities.Title[popIdx];
Engine.GetGUIObjectByName("startingResourcesText").caption = g_StartingResources.Title[startingResIdx];
Engine.GetGUIObjectByName("ceasefireText").caption = g_Ceasefire.Title[ceasefireIdx];
@ -1448,9 +1448,9 @@ function updateGUIObjects()
setGUIBoolean("lastManStanding", "lastManStandingText", !!mapSettings.LastManStanding);
setGUIBoolean("enableRating", "enableRatingText", !!mapSettings.RatingEnabled);
Engine.GetGUIObjectByName("optionWonderDuration").hidden =
Engine.GetGUIObjectByName("optionVictoryDuration").hidden =
g_GameAttributes.settings.GameType &&
g_GameAttributes.settings.GameType != "wonder";
g_GameAttributes.settings.GameType != "wonder" && g_GameAttributes.settings.GameType != "capture_the_relic";
Engine.GetGUIObjectByName("cheatWarningText").hidden = !g_IsNetworked || !mapSettings.CheatsEnabled;
@ -1467,7 +1467,7 @@ function updateGUIObjects()
let notScenario = g_GameAttributes.mapType != "scenario" && g_IsController ;
for (let ctrl of ["victoryCondition", "wonderDuration", "populationCap",
for (let ctrl of ["victoryCondition", "victoryDuration", "populationCap",
"startingResources", "ceasefire", "revealMap",
"exploreMap", "disableTreasures", "disableSpies", "lockTeams", "lastManStanding"])
hideControl(ctrl, ctrl + "Text", notScenario);

View File

@ -337,13 +337,13 @@
</object>
</object>
<object name="optionWonderDuration" size="14 188 94% 216">
<object name="optionVictoryDuration" size="14 188 94% 216">
<object size="0 0 40% 28" type="text" style="ModernRightLabelText">
<translatableAttribute id="caption">Wonder Victory:</translatableAttribute>
<translatableAttribute id="caption">Victory Duration:</translatableAttribute>
</object>
<object name="wonderDurationText" size="40% 0 100% 100%" type="text" style="ModernLeftLabelText"/>
<object name="wonderDuration" size="40%+10 0 100% 28" type="dropdown" style="ModernDropDown" hidden="true" tooltip_style="onscreenToolTip">
<translatableAttribute id="tooltip">Number of minutes that the player has to keep the wonder in order to win.</translatableAttribute>
<object name="victoryDurationText" size="40% 0 100% 100%" type="text" style="ModernLeftLabelText"/>
<object name="victoryDuration" size="40%+10 0 100% 28" type="dropdown" style="ModernDropDown" hidden="true" tooltip_style="onscreenToolTip">
<translatableAttribute id="tooltip">Number of minutes until the player has won.</translatableAttribute>
</object>
</object>

View File

@ -7,7 +7,7 @@ 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_WonderDurations = prepareForDropdown(g_Settings && g_Settings.WonderDurations);
const g_VictoryDurations = prepareForDropdown(g_Settings && g_Settings.VictoryDurations);
/**
* Colors to flash when pop limit reached.

View File

@ -0,0 +1,180 @@
let g_CatafalqueTemplate = "other/special_catafalque";
Trigger.prototype.InitCaptureTheRelic = function()
{
// Attempt to spawn relics using gaia entities in neutral territory
// If there are none, try to spawn using gaia entities in non-neutral territory
let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
let cmpWaterManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_WaterManager);
let cmpTerritoryManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager);
let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
let potentialGaiaSpawnPoints = [];
let potentialSpawnPoints = cmpRangeManager.GetEntitiesByPlayer(0).filter(entity => {
let cmpPosition = Engine.QueryInterface(entity, IID_Position);
if (!cmpPosition || !cmpPosition.IsInWorld())
return false;
let cmpIdentity = Engine.QueryInterface(entity, IID_Identity);
if (!cmpIdentity)
return false;
let templateName = cmpTemplateManager.GetCurrentTemplateName(entity);
if (!templateName)
return false;
let template = cmpTemplateManager.GetTemplate(templateName);
if (!template || template.UnitMotionFlying)
return false;
let pos = cmpPosition.GetPosition();
if (pos.y <= cmpWaterManager.GetWaterLevel(pos.x, pos.z))
return false;
if (cmpTerritoryManager.GetOwner(pos.x, pos.z) == 0)
potentialGaiaSpawnPoints.push(entity);
return true;
});
if (potentialGaiaSpawnPoints.length)
potentialSpawnPoints = potentialGaiaSpawnPoints;
let numSpawnedRelics = Math.ceil(TriggerHelper.GetNumberOfPlayers() / 2);
this.playerRelicsCount = new Array(TriggerHelper.GetNumberOfPlayers()).fill(0, 1);
this.playerRelicsCount[0] = numSpawnedRelics;
for (let i = 0; i < numSpawnedRelics; ++i)
{
this.relics[i] = TriggerHelper.SpawnUnits(pickRandom(potentialSpawnPoints), g_CatafalqueTemplate, 1, 0)[0];
let cmpDamageReceiver = Engine.QueryInterface(this.relics[i], IID_DamageReceiver);
cmpDamageReceiver.SetInvulnerability(true);
let cmpPositionRelic = Engine.QueryInterface(this.relics[i], IID_Position);
cmpPositionRelic.SetYRotation(randFloat(0, 2 * Math.PI));
}
};
Trigger.prototype.CheckCaptureTheRelicVictory = function(data)
{
let cmpIdentity = Engine.QueryInterface(data.entity, IID_Identity);
if (!cmpIdentity || !cmpIdentity.HasClass("Relic") || data.from == -1)
return;
if (data.to == -1)
{
error("Relic entity " + data.entity + " has been destroyed");
return;
}
--this.playerRelicsCount[data.from];
++this.playerRelicsCount[data.to];
this.CheckCaptureTheRelicCountdown();
};
/**
* Check if an individual player or team has acquired all relics.
* Also check if the countdown needs to be stopped if a player/team no longer has all relics.
*/
Trigger.prototype.CheckCaptureTheRelicCountdown = function()
{
let cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
for (let playerID = 1; playerID < TriggerHelper.GetNumberOfPlayers(); ++playerID)
{
let playerAndAllies = cmpEndGameManager.GetAlliedVictory() ?
QueryPlayerIDInterface(playerID).GetMutualAllies() : [playerID];
let teamRelicsOwned = 0;
for (let ally of playerAndAllies)
teamRelicsOwned += this.playerRelicsCount[ally];
if (teamRelicsOwned == this.relics.length)
{
this.StartCaptureTheRelicCountdown(playerAndAllies);
return;
}
}
this.DeleteCaptureTheRelicVictoryMessages();
};
Trigger.prototype.DeleteCaptureTheRelicVictoryMessages = function()
{
let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
cmpTimer.CancelTimer(this.relicsVictoryTimer);
let cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
cmpGuiInterface.DeleteTimeNotification(this.ownRelicsVictoryMessage);
cmpGuiInterface.DeleteTimeNotification(this.othersRelicsVictoryMessage);
};
Trigger.prototype.StartCaptureTheRelicCountdown = function(playerAndAllies)
{
let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
let cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
if (this.relicsVictoryTimer)
{
cmpTimer.CancelTimer(this.relicsVictoryTimer);
cmpGuiInterface.DeleteTimeNotification(this.ownRelicsVictoryMessage);
cmpGuiInterface.DeleteTimeNotification(this.othersRelicsVictoryMessage);
}
let others = [-1];
for (let playerID = 1; playerID < TriggerHelper.GetNumberOfPlayers(); ++playerID)
{
let cmpPlayer = QueryPlayerIDInterface(playerID);
if (cmpPlayer.GetState() == "won")
return;
if (playerAndAllies.indexOf(playerID) == -1)
others.push(playerID);
}
let cmpPlayer = QueryOwnerInterface(this.relics[0], IID_Player);
let cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
let captureTheRelicDuration = cmpEndGameManager.GetGameTypeSettings().victoryDuration || 0;
let isTeam = playerAndAllies.length > 1;
this.ownRelicsVictoryMessage = cmpGuiInterface.AddTimeNotification({
"message": isTeam ?
markForTranslation("%(player)s's team has captured all relics and will have won in %(time)s") :
markForTranslation("%(player)s has captured all relics and will have won in %(time)s"),
"players": others,
"parameters": {
"player": cmpPlayer.GetName()
},
"translateMessage": true,
"translateParameters": []
}, captureTheRelicDuration);
this.othersRelicsVictoryMessage = cmpGuiInterface.AddTimeNotification({
"message": isTeam ?
markForTranslation("Your team has captured all relics and will have won in %(time)s") :
markForTranslation("You have captured all relics and will have won in %(time)s"),
"players": playerAndAllies,
"translateMessage": true
}, captureTheRelicDuration);
this.relicsVictoryTimer = cmpTimer.SetTimeout(SYSTEM_ENTITY, IID_EndGameManager,
"MarkPlayerAsWon", captureTheRelicDuration, playerAndAllies[0]);
};
{
let cmpTrigger = Engine.QueryInterface(SYSTEM_ENTITY, IID_Trigger);
cmpTrigger.relics = [];
cmpTrigger.playerRelicsCount = [];
cmpTrigger.relicsVictoryTimer = undefined;
cmpTrigger.ownRelicsVictoryMessage = undefined;
cmpTrigger.othersRelicsVictoryMessage = undefined;
cmpTrigger.DoAfterDelay(0, "InitCaptureTheRelic", {});
cmpTrigger.RegisterTrigger("OnDiplomacyChanged", "CheckCaptureTheRelicCountdown", { "enabled": true });
cmpTrigger.RegisterTrigger("OnOwnershipChanged", "CheckCaptureTheRelicVictory", { "enabled": true });
cmpTrigger.RegisterTrigger("OnPlayerWon", "DeleteCaptureTheRelicVictoryMessages", { "enabled": true });
}

View File

@ -38,7 +38,7 @@ Trigger.prototype.CheckWonderVictory = function(data)
let cmpPlayer = QueryOwnerInterface(ent, IID_Player);
let cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
let wonderDuration = cmpEndGameManager.GetGameTypeSettings().wonderDuration || 0;
let wonderDuration = cmpEndGameManager.GetGameTypeSettings().victoryDuration || 0;
messages.otherMessage = cmpGuiInterface.AddTimeNotification({
"message": markForTranslation("%(_player_)s will have won in %(time)s"),

View File

@ -62,7 +62,7 @@ Identity.prototype.Schema =
"</element>" +
"</optional>" +
"<optional>" +
"<element name='VisibleClasses' a:help='Optional list of space-separated classes applying to this entity. These classes will also be visible in various GUI elements. If the classes need spaces, underscores will be replaced with spaces. Choices include: Archer, Barracks, Blacksmith, BoltShooter, Camel, Catapult, Cavalry, Champion, Chariot, Citizen, City, Civic, CivilCentre, Corral, DefenseTower, Dock, Dog, Economic, Elephant, Embassy, Farmstead, Field, Fireship, Healer, Hero, House, Infantry, Javelin, Market, Mechanical, Melee, Mercenary, Military, Outpost, Pike, Ram, Ranged, Resource, SentryTower, Ship, Shipyard, Siege, SiegeTower, Slave, Sling, Soldier, Spear, Stables, Storehouse, Support, Sword, Temple, Town, Trader, Village, Warship, Wonder, Worker'>" +
"<element name='VisibleClasses' a:help='Optional list of space-separated classes applying to this entity. These classes will also be visible in various GUI elements. If the classes need spaces, underscores will be replaced with spaces. Choices include: Archer, Barracks, Blacksmith, BoltShooter, Camel, Catapult, Cavalry, Champion, Chariot, Citizen, City, Civic, CivilCentre, Corral, DefenseTower, Dock, Dog, Economic, Elephant, Embassy, Farmstead, Field, Fireship, Healer, Hero, House, Infantry, Javelin, Market, Mechanical, Melee, Mercenary, Military, Outpost, Pike, Ram, Ranged, Relic, Resource, SentryTower, Ship, Shipyard, Siege, SiegeTower, Slave, Sling, Soldier, Spear, Stables, Storehouse, Support, Sword, Temple, Town, Trader, Village, Warship, Wonder, Worker'>" +
"<attribute name='datatype'>" +
"<value>tokens</value>" +
"</attribute>" +

View File

@ -11,6 +11,7 @@ Trigger.prototype.eventNames =
"CinemaPathEnded",
"CinemaQueueEnded",
"ConstructionStarted",
"DiplomacyChanged",
"InitGame",
"Interval",
"OwnershipChanged",
@ -271,6 +272,11 @@ Trigger.prototype.OnGlobalPlayerWon = function(msg)
this.CallEvent("PlayerWon", msg);
};
Trigger.prototype.OnGlobalDiplomacyChanged = function(msg)
{
this.CallEvent("DiplomacyChanged", msg);
};
/**
* Execute a function after a certain delay.
*

View File

@ -4,7 +4,7 @@ Engine.LoadComponentScript("EndGameManager.js");
let cmpEndGameManager = ConstructComponent(SYSTEM_ENTITY, "EndGameManager");
let playerEnt1 = 1;
let wonderDuration = 2 * 60 * 1000;
let victoryDuration = 2 * 60 * 1000;
AddMock(SYSTEM_ENTITY, IID_PlayerManager, {
"GetNumPlayers": () => 4
@ -23,7 +23,7 @@ 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.SetGameType("wonder", { "victoryDuration": victoryDuration });
TS_ASSERT_EQUALS(cmpEndGameManager.skipAlliedVictoryCheck, false);
TS_ASSERT(cmpEndGameManager.GetGameType() == "wonder");
TS_ASSERT_EQUALS(cmpEndGameManager.GetGameTypeSettings().wonderDuration, wonderDuration);
TS_ASSERT_EQUALS(cmpEndGameManager.GetGameTypeSettings().victoryDuration, victoryDuration);

View File

@ -0,0 +1,15 @@
{
"TranslatedKeys": ["Title", "Description"],
"Data":
{
"Title": "Capture The Relic",
"Description": "Capture all relics spread across the map and keep them for a certain time to win the game.",
"Scripts":
[
"scripts/TriggerHelper.js",
"scripts/ConquestCommon.js",
"scripts/Conquest.js",
"scripts/CaptureTheRelic.js"
]
}
}

View File

@ -45,8 +45,8 @@ function LoadMapSettings(settings)
let cmpEndGameManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager);
let gameTypeSettings = {};
if (settings.WonderDuration)
gameTypeSettings.wonderDuration = settings.WonderDuration * 60 * 1000;
if (settings.VictoryDuration)
gameTypeSettings.victoryDuration = settings.VictoryDuration * 60 * 1000;
if (settings.GameType)
cmpEndGameManager.SetGameType(settings.GameType, gameTypeSettings);

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<Entity parent="template_unit">
<Capturable>
<CapturePoints>250</CapturePoints>
<GarrisonRegenRate>0</GarrisonRegenRate>
<RegenRate>10</RegenRate>
</Capturable>
<Cost>
<Population>0</Population>
</Cost>
<Footprint replace="">
<Height>2.0</Height>
<Square width="5.0" depth="12.0"/>
</Footprint>
<Health>
<Undeletable>true</Undeletable>
</Health>
<Identity>
<Civ>gaia</Civ>
<Classes datatype="tokens">-ConquestCritical</Classes>
<Formations disable=""/>
<GenericName>Catafalque</GenericName>
<Icon>units/catafalque.png</Icon>
<Tooltip>A catafalque that holds the remains of a great leader.</Tooltip>
<VisibleClasses datatype="tokens">Relic</VisibleClasses>
</Identity>
<Minimap>
<Color r="148" g="0" b="211"/>
</Minimap>
<ResourceGatherer disable=""/>
<Sound>
<SoundGroups>
<order_walk>actor/singlesteps/steps_grass.xml</order_walk>
<run>actor/singlesteps/steps_grass.xml</run>
<select>attack/siege/siege_select.xml</select>
<walk>actor/singlesteps/steps_grass.xml</walk>
</SoundGroups>
</Sound>
<UnitAI>
<DefaultStance>standground</DefaultStance>
<CanGuard>false</CanGuard>
</UnitAI>
<UnitMotion>
<PassabilityClass>large</PassabilityClass>
<Run>
<Speed>8</Speed>
</Run>
<WalkSpeed>5</WalkSpeed>
</UnitMotion>
<VisualActor>
<Actor>units/global/catafalque.xml</Actor>
</VisualActor>
</Entity>

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2016 Wildfire Games.
/* Copyright (C) 2017 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -149,6 +149,7 @@ void MapSettingsControl::CreateWidgets()
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);