1
0
forked from 0ad/0ad

Add Requirements helper.

Allows more flexibility in e.g. the Identity requirements and unifies
the checking of requirements.
One can use the script at https://code.wildfiregames.com/P265 to fix
templates.

Differential revision: https://code.wildfiregames.com/D4514
Comments by: @elexis, @Stan
Fixes #6421

This was SVN commit r27245.
This commit is contained in:
Freagarach 2022-11-24 11:20:11 +00:00
parent 42fe39d35c
commit 9bb9ff8b16
187 changed files with 1616 additions and 389 deletions

View File

@ -441,7 +441,7 @@ function GetTemplateDataHelper(template, player, auraTemplates, resources, modif
};
ret.icon = template.Identity.Icon;
ret.tooltip = template.Identity.Tooltip;
ret.requiredTechnology = template.Identity.RequiredTechnology;
ret.requirements = template.Identity.Requirements;
ret.visibleIdentityClasses = GetVisibleIdentityClasses(template.Identity);
ret.nativeCiv = template.Identity.Civ;
}
@ -476,8 +476,8 @@ function GetTemplateDataHelper(template, player, auraTemplates, resources, modif
"entity": upgrade.Entity,
"tooltip": upgrade.Tooltip,
"cost": cost,
"icon": upgrade.Icon || undefined,
"requiredTechnology": upgrade.RequiredTechnology || undefined
"icon": upgrade.Icon,
"requirements": upgrade.Requirements
});
}
}

View File

@ -956,14 +956,17 @@ function getEntityCostTooltip(template, player, entity, buildingsCountToTrainFul
return "";
}
function getRequiredTechnologyTooltip(technologyEnabled, requiredTechnology, civ)
function getRequirementsTooltip(enabled, requirements, civ)
{
if (technologyEnabled)
if (enabled)
return "";
return sprintf(translate("Requires %(technology)s"), {
"technology": getEntityNames(GetTechnologyData(requiredTechnology, civ))
});
// Simple requirements (one tech) can be translated on the fly.
if ("Techs" in requirements && !requirements.Techs.includes(" "))
return sprintf(translate("Requires %(technology)s"), {
"technology": getEntityNames(GetTechnologyData(requirements.Techs, civ))
});
return translate(requirements.Tooltip);
}
/**

View File

@ -293,8 +293,8 @@ class TemplateLoader
if (parentTemplate.Upgrade[upgrade].Entity)
return [inheritedVariance[0], TemplateVariant.upgrade, upgrade.toLowerCase()];
if (template.Identity.RequiredTechnology)
return [inheritedVariance[0], TemplateVariant.unlockedByTechnology, template.Identity.RequiredTechnology];
if (template.Identity.Requirements?.Techs)
return [inheritedVariance[0], TemplateVariant.unlockedByTechnology, template.Identity.Requirements?.Techs];
if (parentTemplate.Cost)
for (let res in parentTemplate.Cost.Resources)

View File

@ -71,12 +71,12 @@ class TemplateParser
// Set the minimum phase that this entity is available.
// For gaia objects, this is meaningless.
if (!parsed.requiredTechnology)
if (!parsed.requirements)
parsed.phase = this.phaseList[0];
else if (this.TemplateLoader.isPhaseTech(parsed.requiredTechnology))
parsed.phase = this.getActualPhase(parsed.requiredTechnology);
else if (this.TemplateLoader.isPhaseTech(parsed.requirements.Techs))
parsed.phase = this.getActualPhase(parsed.requirements.Techs);
else
parsed.phase = this.getPhaseOfTechnology(parsed.requiredTechnology, civCode);
parsed.phase = this.getPhaseOfTechnology(parsed.requirements.Techs, civCode);
if (template.Identity.Rank)
parsed.promotion = {
@ -256,14 +256,14 @@ class TemplateParser
data.cost = upgrade.cost;
data.icon = upgrade.icon || data.icon;
data.tooltip = upgrade.tooltip || data.tooltip;
data.requiredTechnology = upgrade.requiredTechnology || data.requiredTechnology;
data.requirements = upgrade.requirements || data.requirements;
if (!data.requiredTechnology)
if (!data.requirements)
data.phase = this.phaseList[0];
else if (this.TemplateLoader.isPhaseTech(data.requiredTechnology))
data.phase = this.getActualPhase(data.requiredTechnology);
else if (this.TemplateLoader.isPhaseTech(data.requirements.Techs))
data.phase = this.getActualPhase(data.requirements.Techs);
else
data.phase = this.getPhaseOfTechnology(data.requiredTechnology, civCode);
data.phase = this.getPhaseOfTechnology(data.requirements.Techs, civCode);
newUpgrades.push(data);
}

View File

@ -65,15 +65,15 @@ DiplomacyDialogPlayerControl.prototype.SpyRequestButton = class
let tooltip = translate(this.Tooltip);
if (template.requiredTechnology &&
!Engine.GuiInterfaceCall("IsTechnologyResearched", {
"tech": template.requiredTechnology,
if (template.requirements &&
!Engine.GuiInterfaceCall("AreRequirementsMet", {
"requirements": template.requirements,
"player": g_ViewedPlayer
}))
{
tooltip += "\n" + getRequiredTechnologyTooltip(
tooltip += "\n" + getRequirementsTooltip(
false,
template.requiredTechnology,
template.requirements,
GetSimState().players[g_ViewedPlayer].civ);
this.diplomacySpyRequest.enabled = false;

View File

@ -166,8 +166,8 @@ g_SelectionPanels.Construction = {
if (!template)
return false;
let technologyEnabled = Engine.GuiInterfaceCall("IsTechnologyResearched", {
"tech": template.requiredTechnology,
const requirementsMet = Engine.GuiInterfaceCall("AreRequirementsMet", {
"requirements": template.requirements,
"player": data.player
});
@ -203,13 +203,13 @@ g_SelectionPanels.Construction = {
tooltips.push(
formatLimitString(limits.entLimit, limits.entCount, limits.entLimitChangers),
formatMatchLimitString(limits.matchLimit, limits.matchCount, limits.type),
getRequiredTechnologyTooltip(technologyEnabled, template.requiredTechnology, GetSimState().players[data.player].civ),
getRequirementsTooltip(requirementsMet, template.requirements, GetSimState().players[data.player].civ),
getNeededResourcesTooltip(neededResources));
data.button.tooltip = tooltips.filter(tip => tip).join("\n");
let modifier = "";
if (!technologyEnabled || limits.canBeAddedCount == 0)
if (!requirementsMet || limits.canBeAddedCount == 0)
{
data.button.enabled = false;
modifier += "color:0 0 0 127:grayscale:";
@ -990,8 +990,8 @@ g_SelectionPanels.Training = {
if (!template)
return false;
let technologyEnabled = Engine.GuiInterfaceCall("IsTechnologyResearched", {
"tech": template.requiredTechnology,
const requirementsMet = Engine.GuiInterfaceCall("AreRequirementsMet", {
"requirements": template.requirements,
"player": data.player
});
@ -1048,13 +1048,13 @@ g_SelectionPanels.Training = {
tooltips.push(showTemplateViewerOnRightClickTooltip());
tooltips.push(
formatBatchTrainingString(buildingsCountToTrainFullBatch, fullBatchSize, remainderBatch),
getRequiredTechnologyTooltip(technologyEnabled, template.requiredTechnology, GetSimState().players[data.player].civ),
getRequirementsTooltip(requirementsMet, template.requirements, GetSimState().players[data.player].civ),
getNeededResourcesTooltip(neededResources));
data.button.tooltip = tooltips.filter(tip => tip).join("\n");
let modifier = "";
if (!technologyEnabled || limits.canBeAddedCount == 0)
if (!requirementsMet || limits.canBeAddedCount == 0)
{
data.button.enabled = false;
modifier = "color:0 0 0 127:grayscale:";
@ -1106,11 +1106,9 @@ g_SelectionPanels.Upgrade = {
let progressOverlay = Engine.GetGUIObjectByName("unitUpgradeProgressSlider[" + data.i + "]");
progressOverlay.hidden = true;
let technologyEnabled = true;
if (data.item.requiredTechnology)
technologyEnabled = Engine.GuiInterfaceCall("IsTechnologyResearched", {
"tech": data.item.requiredTechnology,
const requirementsMet = !data.item.requirements ||
Engine.GuiInterfaceCall("AreRequirementsMet", {
"requirements": data.item.requirements,
"player": data.player
});
@ -1167,7 +1165,7 @@ g_SelectionPanels.Upgrade = {
getEntityCostTooltip(data.item, undefined, undefined, data.unitEntStates.length),
formatLimitString(limits.entLimit, limits.entCount, limits.entLimitChangers),
formatMatchLimitString(limits.matchLimit, limits.matchCount, limits.type),
getRequiredTechnologyTooltip(technologyEnabled, data.item.requiredTechnology, GetSimState().players[data.player].civ),
getRequirementsTooltip(requirementsMet, data.item.requirements, GetSimState().players[data.player].civ),
getNeededResourcesTooltip(neededResources),
showTemplateViewerOnRightClickTooltip());
@ -1179,7 +1177,7 @@ g_SelectionPanels.Upgrade = {
upgradableEntStates.map(state => state.id));
};
if (!technologyEnabled || limits.canBeAddedCount == 0 &&
if (!requirementsMet || limits.canBeAddedCount == 0 &&
!upgradableEntStates.some(state => hasSameRestrictionCategory(data.item.entity, state.template)))
{
data.button.enabled = false;

View File

@ -73,29 +73,13 @@ m.Template = m.Class({
return this._classes && MatchesClassList(this._classes, array);
},
"requiredTech": function() { return this.get("Identity/RequiredTechnology"); },
"available": function(gameState) {
let techRequired = this.requiredTech();
if (!techRequired)
return true;
return gameState.isResearched(techRequired);
"requirements": function() {
return this.get("Identity/Requirements");
},
// specifically
"phase": function() {
let techRequired = this.requiredTech();
if (!techRequired)
return 0;
if (techRequired == "phase_village")
return 1;
if (techRequired == "phase_town")
return 2;
if (techRequired == "phase_city")
return 3;
if (techRequired.startsWith("phase_"))
return 4;
return 0;
"available": function(gameState) {
const requirements = this.requirements();
return !requirements || Sim.RequirementsHelper.AreRequirementsMet(requirements, PlayerID);
},
"cost": function(productionQueue) {

View File

@ -1897,7 +1897,7 @@ PETRA.HQ.prototype.canBuild = function(gameState, structure)
if (!template.available(gameState))
{
this.buildManager.setUnbuildable(gameState, type, 30, "tech");
this.buildManager.setUnbuildable(gameState, type, 30, "requirements");
return false;
}

View File

@ -25,7 +25,7 @@ PETRA.ConstructionPlan.prototype.canStart = function(gameState)
if (!this.isGo(gameState))
return false;
if (this.template.requiredTech() && !gameState.isResearched(this.template.requiredTech()))
if (!this.template.available(gameState))
return false;
return gameState.ai.HQ.buildManager.hasBuilder(this.type);

View File

@ -661,16 +661,10 @@ GuiInterface.prototype.GetTemplateData = function(player, data)
return GetTemplateDataHelper(template, owner, aurasTemplate, Resources);
};
GuiInterface.prototype.IsTechnologyResearched = function(player, data)
GuiInterface.prototype.AreRequirementsMet = function(player, data)
{
if (!data.tech)
return true;
let cmpTechnologyManager = QueryPlayerIDInterface(data.player !== undefined ? data.player : player, IID_TechnologyManager);
if (!cmpTechnologyManager)
return false;
return cmpTechnologyManager.IsTechnologyResearched(data.tech);
return !data.requirements || RequirementsHelper.AreRequirementsMet(data.requirements,
data.player !== undefined ? data.player : player);
};
/**
@ -2076,7 +2070,7 @@ let exposedFunctions = {
"GetMultipleEntityStates": 1,
"GetAverageRangeForBuildings": 1,
"GetTemplateData": 1,
"IsTechnologyResearched": 1,
"AreRequirementsMet": 1,
"CheckTechnologyRequirements": 1,
"GetStartedResearch": 1,
"GetBattleState": 1,

View File

@ -76,9 +76,7 @@ Identity.prototype.Schema =
"<text/>" +
"</element>" +
"<optional>" +
"<element name='RequiredTechnology' a:help='Optional name of a technology which must be researched before the entity can be produced.'>" +
"<text/>" +
"</element>" +
RequirementsHelper.BuildSchema() +
"</optional>" +
"<optional>" +
"<element name='Controllable' a:help='Whether players can control this entity. Defaults to true.'>" +

View File

@ -276,8 +276,8 @@ TechnologyManager.prototype.CanProduce = function(templateName)
var cmpTempManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
var template = cmpTempManager.GetTemplate(templateName);
if (template.Identity && template.Identity.RequiredTechnology)
return this.IsTechnologyResearched(template.Identity.RequiredTechnology);
if (template.Identity?.Requirements)
return RequirementsHelper.AreRequirementsMet(template.Identity.Requirements, Engine.QueryInterface(this.entity, IID_Player).GetPlayerID());
// If there is no required technology then this entity can be produced
return true;
};

View File

@ -40,12 +40,7 @@ Upgrade.prototype.Schema =
"</element>" +
"</optional>" +
"<optional>" +
"<element name='RequiredTechnology' a:help='Define what technology is required for this upgrade'>" +
"<choice>" +
"<text/>" +
"<empty/>" +
"</choice>" +
"</element>" +
RequirementsHelper.BuildSchema() +
"</optional>" +
"<optional>" +
"<element name='CheckPlacementRestrictions' a:help='Upgrading will check for placement restrictions (nb:GUI only)'><empty/></element>" +
@ -153,7 +148,7 @@ Upgrade.prototype.GetUpgrades = function()
"icon": choice.Icon || undefined,
"cost": hasCost ? cost : undefined,
"tooltip": choice.Tooltip || undefined,
"requiredTechnology": this.GetRequiredTechnology(option),
"requirements": this.GetRequirements(option),
});
}
@ -189,14 +184,14 @@ Upgrade.prototype.WillCheckPlacementRestrictions = function(template)
return "CheckPlacementRestrictions" in this.template[this.upgradeTemplates[template]];
};
Upgrade.prototype.GetRequiredTechnology = function(templateArg)
Upgrade.prototype.GetRequirements = function(templateArg)
{
let choice = this.upgradeTemplates[templateArg] || templateArg;
if (this.template[choice].RequiredTechnology)
return this.template[choice].RequiredTechnology;
if (this.template[choice].Requirements)
return this.template[choice].Requirements;
if (!("RequiredTechnology" in this.template[choice]))
if (!("Requirements" in this.template[choice]))
return undefined;
let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
@ -207,7 +202,7 @@ Upgrade.prototype.GetRequiredTechnology = function(templateArg)
entType = entType.replace(/\{civ\}/g, cmpIdentity.GetCiv());
let template = cmpTemplateManager.GetTemplate(entType);
return template.Identity.RequiredTechnology || undefined;
return template.Identity.Requirements || undefined;
};
Upgrade.prototype.GetResourceCosts = function(template)

View File

@ -1,3 +1,4 @@
Engine.LoadHelperScript("Requirements.js");
Engine.LoadComponentScript("Identity.js");
let cmpIdentity = ConstructComponent(5, "Identity", {
@ -32,7 +33,9 @@ cmpIdentity = ConstructComponent(6, "Identity", {
"Classes": { "_string": "CitizenSoldier Human Organic" },
"VisibleClasses": { "_string": "Javelineer" },
"Icon": "units/iber_infantry_javelineer.png",
"RequiredTechnology": "phase_town"
"Requirements": {
"Techs": "phase_town"
}
});
TS_ASSERT_EQUALS(cmpIdentity.GetCiv(), "iber");

View File

@ -1,4 +1,5 @@
Engine.LoadHelperScript("Player.js");
Engine.LoadHelperScript("Requirements.js");
Engine.LoadHelperScript("ValueModification.js");
Resources = {
"BuildSchema": type => {

View File

@ -783,10 +783,7 @@ var g_Commands = {
continue;
}
let cmpTechnologyManager = QueryOwnerInterface(ent, IID_TechnologyManager);
let requiredTechnology = cmpUpgrade.GetRequiredTechnology(cmd.template);
if (requiredTechnology && (!cmpTechnologyManager || !cmpTechnologyManager.IsTechnologyResearched(requiredTechnology)))
if (!RequirementsHelper.AreRequirementsMet(cmpUpgrade.GetRequirements(cmd.template), player))
{
if (g_DebugCommands)
warn("Invalid command: upgrading is not possible for this player or requires unresearched technology: " + uneval(cmd));

View File

@ -0,0 +1,164 @@
function RequirementsHelper() {}
RequirementsHelper.prototype.DEFAULT_RECURSION_DEPTH = 1;
RequirementsHelper.prototype.EntityRequirementsSchema =
"<element name='Entities' a:help='Entities that need to be controlled.'>" +
"<oneOrMore>" +
"<element a:help='Class of entity that needs to be controlled.'>" +
"<anyName/>" +
"<oneOrMore>" +
"<choice>" +
"<element name='Count' a:help='Number of entities required.'>" +
"<data type='nonNegativeInteger'/>" +
"</element>" +
"<element name='Variants' a:help='Number of different entities of this class required.'>" +
"<data type='nonNegativeInteger'/>" +
"</element>" +
"</choice>" +
"</oneOrMore>" +
"</element>" +
"</oneOrMore>" +
"</element>";
RequirementsHelper.prototype.TechnologyRequirementsSchema =
"<element name='Techs' a:help='White-space separated list of technologies that need to be researched. ! negates a tech.'>" +
"<text/>" +
"</element>";
/**
* @param {number} recursionDepth - How deep we recurse.
* @return {string} - A RelaxRNG schema for requirements.
*/
RequirementsHelper.prototype.RequirementsSchema = function(recursionDepth)
{
return "" +
"<oneOrMore>" +
this.ChoicesSchema(--recursionDepth) +
"</oneOrMore>";
};
/**
* @param {number} recursionDepth - How deep we recurse.
* @return {string} - A RelaxRNG schema for chosing requirements.
*/
RequirementsHelper.prototype.ChoicesSchema = function(recursionDepth)
{
const allAnySchema = recursionDepth > 0 ? "" +
"<element name='All' a:help='Requires all of the conditions to be met.'>" +
this.RequirementsSchema(recursionDepth) +
"</element>" +
"<element name='Any' a:help='Requires at least one of the following conditions met.'>" +
this.RequirementsSchema(recursionDepth) +
"</element>" : "";
return "" +
"<choice>" +
allAnySchema +
this.EntityRequirementsSchema +
this.TechnologyRequirementsSchema +
"</choice>";
};
/**
* @param {number} recursionDepth - How deeply recursive we build the schema.
* @return {string} - A RelaxRNG schema for requirements.
*/
RequirementsHelper.prototype.BuildSchema = function(recursionDepth = this.DEFAULT_RECURSION_DEPTH)
{
return "" +
"<element name='Requirements' a:help='The requirements that ought to be met before this entity can be produced.'>" +
"<optional>" +
this.ChoicesSchema(recursionDepth) +
"</optional>" +
"<optional>" +
"<element name='Tooltip' a:help='A tooltip explaining the requirements.'>" +
"<text/>" +
"</element>" +
"</optional>" +
"</element>";
};
/**
* @param {Object} template - The requirements template as defined above.
* @param {number} playerID -
* @return {boolean} -
*/
RequirementsHelper.prototype.AreRequirementsMet = function(template, playerID)
{
if (!template || !Object.keys(template).length)
return true;
const cmpTechManager = QueryPlayerIDInterface(playerID, IID_TechnologyManager);
return this.AllRequirementsMet(template, cmpTechManager);
};
/**
* @param {Object} template - The requirements template for "all".
* @param {component} cmpTechManager -
* @return {boolean} -
*/
RequirementsHelper.prototype.AllRequirementsMet = function(template, cmpTechManager)
{
for (const requirementType in template)
{
const requirement = template[requirementType];
if (requirementType === "All" && !this.AllRequirementsMet(requirement, cmpTechManager))
return false;
if (requirementType === "Any" && !this.AnyRequirementsMet(requirement, cmpTechManager))
return false;
if (requirementType === "Entities")
{
for (const className in requirement)
{
const entReq = requirement[className];
if ("Count" in entReq && (!(className in cmpTechManager.classCounts) || cmpTechManager.classCounts[className] < entReq.Count))
return false;
if ("Variants" in entReq && (!(className in cmpTechManager.typeCountsByClass) || Object.keys(cmpTechManager.typeCountsByClass[className]).length < entReq.Variants))
return false;
}
}
if (requirementType === "Techs")
for (const tech of requirement.split(" "))
if (tech[0] === "!" ? cmpTechManager.IsTechnologyResearched(tech.substring(1)) :
!cmpTechManager.IsTechnologyResearched(tech))
return false;
}
return true;
};
/**
* @param {Object} template - The requirements template for "any".
* @param {component} cmpTechManager -
* @return {boolean} -
*/
RequirementsHelper.prototype.AnyRequirementsMet = function(template, cmpTechManager)
{
for (const requirementType in template)
{
const requirement = template[requirementType];
if (requirementType === "All" && this.AllRequirementsMet(requirement, cmpTechManager))
return true;
if (requirementType === "Any" && this.AnyRequirementsMet(requirement, cmpTechManager))
return true;
if (requirementType === "Entities")
{
for (const className in requirement)
{
const entReq = requirement[className];
if ("Count" in entReq && className in cmpTechManager.classCounts && cmpTechManager.classCounts[className] >= entReq.Count)
return true;
if ("Variants" in entReq && className in cmpTechManager.typeCountsByClass && Object.keys(cmpTechManager.typeCountsByClass[className]).length >= entReq.Variants)
return true;
}
}
if (requirementType === "Techs")
for (const tech of requirement.split(" "))
if (tech[0] === "!" ? !cmpTechManager.IsTechnologyResearched(tech.substring(1)) :
cmpTechManager.IsTechnologyResearched(tech))
return true;
}
return false;
};
Engine.RegisterGlobal("RequirementsHelper", new RequirementsHelper());

View File

@ -0,0 +1,718 @@
Engine.LoadComponentScript("interfaces/PlayerManager.js");
Engine.LoadComponentScript("interfaces/TechnologyManager.js");
Engine.LoadHelperScript("Player.js");
Engine.LoadHelperScript("Requirements.js");
const playerID = 1;
const playerEnt = 11;
AddMock(SYSTEM_ENTITY, IID_PlayerManager, {
"GetPlayerByID": () => playerEnt
});
// First test no requirements.
let template = {
};
const met = () => TS_ASSERT(RequirementsHelper.AreRequirementsMet(template, playerID));
const notMet = () => TS_ASSERT(!RequirementsHelper.AreRequirementsMet(template, playerID));
met();
// Simple requirements are assumed to be additive.
template = {
"Techs": "phase_city"
};
AddMock(playerEnt, IID_TechnologyManager, {
"IsTechnologyResearched": (tech) => false
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"IsTechnologyResearched": (tech) => tech === "phase_town"
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"IsTechnologyResearched": (tech) => tech === "phase_town" || tech === "phase_city"
});
met();
template = {
"Techs": "cartography phase_city"
};
AddMock(playerEnt, IID_TechnologyManager, {
"IsTechnologyResearched": (tech) => false
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"IsTechnologyResearched": (tech) => tech === "phase_town"
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"IsTechnologyResearched": (tech) => tech === "phase_town" || tech === "phase_city"
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"IsTechnologyResearched": (tech) => tech === "cartography" || tech === "phase_town"
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"IsTechnologyResearched": (tech) => tech === "cartography" || tech === "phase_city"
});
met();
// Additive requirements (all should to be met).
// Entity requirements.
template = {
"All": {
"Entities": {
"class_1": {
"Count": 1
}
}
}
};
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {},
"typeCountsByClass": {}
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 0
},
"typeCountsByClass": {}
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_2": 1
},
"typeCountsByClass": {}
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 1
},
"typeCountsByClass": {}
});
met();
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 1
},
"typeCountsByClass": {
"class_1": {
"template_1": 1
}
}
});
met();
template = {
"All": {
"Entities": {
"class_1": {
"Variants": 2
}
}
}
};
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 2
},
"typeCountsByClass": {
"class_1": {
"template_1": 2
}
}
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 2
},
"typeCountsByClass": {
"class_1": {
"template_1": 1,
"template_2": 1
}
}
});
met();
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 1
},
"typeCountsByClass": {
"class_1": {
"template_1": 1
}
}
});
notMet();
template = {
"All": {
"Entities": {
"class_1": {
"Count": 1,
"Variants": 2
}
}
}
};
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 1
},
"typeCountsByClass": {
"class_1": {
"template_1": 1
}
}
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 2
},
"typeCountsByClass": {
"class_1": {
"template_1": 1,
"template_2": 1
}
}
});
met();
template = {
"All": {
"Entities": {
"class_1": {
"Count": 3,
"Variants": 2
}
}
}
};
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 2
},
"typeCountsByClass": {
"class_1": {
"template_1": 1,
"template_2": 1
}
}
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 3
},
"typeCountsByClass": {
"class_1": {
"template_1": 2,
"template_2": 1
}
}
});
met();
// Technology requirements.
template = {
"All": {
"Techs": "phase_town"
}
};
AddMock(playerEnt, IID_TechnologyManager, {
"IsTechnologyResearched": (tech) => false
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"IsTechnologyResearched": (tech) => tech === "phase_town"
});
met();
template = {
"All": {
"Techs": "phase_city"
}
};
notMet();
template = {
"All": {
"Techs": "phase_town phase_city"
}
};
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"IsTechnologyResearched": (tech) => tech === "phase_town" || tech === "phase_city"
});
met();
template = {
"All": {
"Techs": "!phase_city"
}
};
notMet();
template = {
"All": {
"Techs": "!phase_town phase_city"
}
};
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"IsTechnologyResearched": (tech) => tech === "phase_city"
});
met();
// Combination of Entity and Technology requirements.
template = {
"All": {
"Entities": {
"class_1": {
"Count": 3,
"Variants": 2
}
},
"Techs": "phase_town"
}
};
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 3
},
"IsTechnologyResearched": (tech) => false,
"typeCountsByClass": {
"class_1": {
"template_1": 2,
"template_2": 1
}
}
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 3
},
"IsTechnologyResearched": (tech) => tech === "phase_town",
"typeCountsByClass": {
"class_1": {
"template_1": 2,
"template_2": 1
}
}
});
met();
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 3
},
"IsTechnologyResearched": (tech) => tech === "phase_city",
"typeCountsByClass": {
"class_1": {
"template_1": 2,
"template_2": 1
}
}
});
notMet();
// Choice requirements (at least one needs to be met).
// Entity requirements.
template = {
"Any": {
"Entities": {
"class_1": {
"Count": 1,
}
},
}
};
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 0
}
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 1
}
});
met();
template = {
"Any": {
"Entities": {
"class_1": {
"Count": 5,
"Variants": 2
}
},
}
};
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 3
},
"typeCountsByClass": {
"class_1": {
"template_1": 3,
}
}
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 3
},
"typeCountsByClass": {
"class_1": {
"template_1": 2,
"template_2": 1
}
}
});
met();
// Technology requirements.
template = {
"Any": {
"Techs": "phase_town"
}
};
AddMock(playerEnt, IID_TechnologyManager, {
"IsTechnologyResearched": (tech) => tech === "phase_city"
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"IsTechnologyResearched": (tech) => tech === "phase_town"
});
met();
template = {
"Any": {
"Techs": "phase_town phase_city"
}
};
AddMock(playerEnt, IID_TechnologyManager, {
"IsTechnologyResearched": (tech) => tech === "phase_city"
});
met();
template = {
"Any": {
"Techs": "!phase_town"
}
};
AddMock(playerEnt, IID_TechnologyManager, {
"IsTechnologyResearched": (tech) => tech === "phase_town"
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"IsTechnologyResearched": (tech) => tech === "phase_city"
});
met();
template = {
"Any": {
"Techs": "!phase_town phase_city"
}
};
AddMock(playerEnt, IID_TechnologyManager, {
"IsTechnologyResearched": (tech) => tech === "phase_town" || tech === "phase_city"
});
met();
// Combinational requirements of entities and technologies.
template = {
"Any": {
"Entities": {
"class_1": {
"Count": 3,
"Variants": 2
}
},
"Techs": "!phase_town"
}
};
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 3
},
"IsTechnologyResearched": (tech) => tech === "phase_town",
"typeCountsByClass": {
"class_1": {
"template_1": 3
}
}
});
met();
// Nested requirements.
template = {
"All": {
"All": {
"Techs": "!phase_town"
},
"Any": {
"Entities": {
"class_1": {
"Count": 3,
"Variants": 2
}
},
"Techs": "phase_city"
}
}
};
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 3
},
"IsTechnologyResearched": (tech) => tech === "phase_town",
"typeCountsByClass": {
"class_1": {
"template_1": 3
}
}
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 3
},
"IsTechnologyResearched": (tech) => tech === "phase_town" || tech === "phase_city",
"typeCountsByClass": {
"class_1": {
"template_1": 3
}
}
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 2
},
"IsTechnologyResearched": (tech) => tech === "phase_city",
"typeCountsByClass": {
"class_1": {
"template_1": 2
}
}
});
met();
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 2
},
"IsTechnologyResearched": (tech) => false,
"typeCountsByClass": {
"class_1": {
"template_1": 1,
"template_2": 1
}
}
});
met();
template = {
"Any": {
"All": {
"Techs": "!phase_town"
},
"Any": {
"Entities": {
"class_1": {
"Count": 3,
"Variants": 2
}
},
"Techs": "phase_city"
}
}
};
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 2
},
"IsTechnologyResearched": (tech) => tech === "phase_town",
"typeCountsByClass": {
"class_1": {
"template_1": 2
}
}
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 3
},
"IsTechnologyResearched": (tech) => tech === "phase_town" || tech === "phase_city",
"typeCountsByClass": {
"class_1": {
"template_1": 3
}
}
});
met();
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 2
},
"IsTechnologyResearched": (tech) => tech === "phase_city",
"typeCountsByClass": {
"class_1": {
"template_1": 2
}
}
});
met();
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 2
},
"IsTechnologyResearched": (tech) => false,
"typeCountsByClass": {
"class_1": {
"template_1": 1,
"template_2": 1
}
}
});
met();
// Two levels deep nested.
template = {
"All": {
"Any": {
"All": {
"Techs": "cartography phase_imperial",
},
"Entities": {
"class_1": {
"Count": 3,
"Variants": 2
}
},
"Techs": "phase_city"
},
"Techs": "!phase_town"
}
};
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 2
},
"IsTechnologyResearched": (tech) => tech === "phase_town",
"typeCountsByClass": {
"class_1": {
"template_1": 2
}
}
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 2
},
"IsTechnologyResearched": (tech) => tech === "phase_city",
"typeCountsByClass": {
"class_1": {
"template_1": 2
}
}
});
met();
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 2
},
"IsTechnologyResearched": (tech) => tech === "phase_imperial",
"typeCountsByClass": {
"class_1": {
"template_1": 2
}
}
});
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"classCounts": {
"class_1": 2
},
"IsTechnologyResearched": (tech) => tech === "cartography" || tech === "phase_imperial",
"typeCountsByClass": {
"class_1": {
"template_1": 2
}
}
});
met();

View File

@ -1,9 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<Entity parent="gaia/fauna_pig">
<Loot disable=""/>
<Identity>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Loot disable=""/>
<Visibility>
<RetainInFog>false</RetainInFog>
</Visibility>

View File

@ -15,8 +15,10 @@
<Classes datatype="tokens">Spy</Classes>
<GenericName>Spy</GenericName>
<Icon>technologies/spy_trader.png</Icon>
<RequiredTechnology>unlock_spies</RequiredTechnology>
<Undeletable>true</Undeletable>
<Requirements>
<Techs>unlock_spies</Techs>
</Requirements>
</Identity>
<VisionSharing>
<Bribable>false</Bribable>

View File

@ -25,7 +25,9 @@
<Classes datatype="tokens">ConquestCritical CivSpecific</Classes>
<VisibleClasses datatype="tokens">Gymnasium -City Town</VisibleClasses>
<Icon>structures/gymnasium.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Loot>
<stone>40</stone>

View File

@ -16,7 +16,9 @@
<Classes datatype="tokens">CivSpecific</Classes>
<VisibleClasses datatype="tokens">Naval</VisibleClasses>
<Icon>structures/crannog.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Obstruction>
<Static width="29" depth="29"/>

View File

@ -25,7 +25,9 @@
<Classes datatype="tokens">CivSpecific</Classes>
<VisibleClasses datatype="tokens">-Village Town</VisibleClasses>
<Icon>structures/apartment.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Loot>
<wood op="add">10</wood>
@ -37,11 +39,11 @@
<Population>
<Bonus op="add">10</Bonus>
</Population>
<TerritoryDecay>
<DecayRate op="mul">2</DecayRate>
</TerritoryDecay>
<VisualActor>
<FoundationActor>structures/carthaginians/fndn_house.xml</FoundationActor>
<Actor>structures/carthaginians/apartment.xml</Actor>
</VisualActor>
<TerritoryDecay>
<DecayRate op="mul">2</DecayRate>
</TerritoryDecay>
</Entity>

View File

@ -3,8 +3,10 @@
<Identity>
<Civ>cart</Civ>
<SpecificName>Low Wall</SpecificName>
<RequiredTechnology>phase_village</RequiredTechnology>
<Icon>structures/palisade_wall.png</Icon>
<Requirements>
<Techs>phase_village</Techs>
</Requirements>
</Identity>
<WallSet>
<Templates>

View File

@ -30,7 +30,9 @@
<Classes datatype="tokens">ConquestCritical CivSpecific</Classes>
<VisibleClasses datatype="tokens">City Council</VisibleClasses>
<Icon>structures/tholos.png</Icon>
<RequiredTechnology>phase_city</RequiredTechnology>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</Identity>
<Loot>
<wood>80</wood>

View File

@ -21,7 +21,9 @@
<SpecificName>Taberna</SpecificName>
<VisibleClasses datatype="tokens">-Village Town</VisibleClasses>
<Icon>structures/embassy_celtic.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Loot>
<wood>20</wood>

View File

@ -30,7 +30,9 @@
<Tooltip>Train Champions and research their technologies.</Tooltip>
<VisibleClasses datatype="tokens">-Village City Academy</VisibleClasses>
<Icon>structures/embassy_italic.png</Icon>
<RequiredTechnology>phase_city</RequiredTechnology>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</Identity>
<Obstruction>
<Static depth="22.0" width="22.0"/>

View File

@ -31,13 +31,15 @@
<ImperialCourt>
<Entity>structures/{civ}/civil_centre_court</Entity>
<Tooltip>This greatly increases the health, capture resistance, and garrison capacity of this specific Civic Center. Unlock training of Heroes here and reduce its research and batch training times by half.</Tooltip>
<RequiredTechnology>phase_city</RequiredTechnology>
<Cost>
<stone>300</stone>
<wood>300</wood>
</Cost>
<Time>40</Time>
<Variant>upgrading</Variant>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</ImperialCourt>
</Upgrade>
<VisualActor>

View File

@ -18,8 +18,10 @@
<SpecificName>Cháotíng</SpecificName>
<VisibleClasses datatype="tokens">Defensive ImperialCourt City</VisibleClasses>
<Classes datatype="tokens">CivCentre CivSpecific</Classes>
<RequiredTechnology>phase_city</RequiredTechnology>
<Icon>structures/military_settlement.png</Icon>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</Identity>
<Population>
<Bonus>30</Bonus>

View File

@ -11,24 +11,26 @@
<Civ>han</Civ>
<SpecificName>Fángyù Tǎ</SpecificName>
</Identity>
<Upgrade>
<GreatArcheryTower>
<Entity>structures/{civ}/defense_tower_great</Entity>
<Tooltip>This tower has greater range, greater attack, greater health, and is twice as difficult to capture.</Tooltip>
<RequiredTechnology>phase_city</RequiredTechnology>
<Cost>
<stone>200</stone>
</Cost>
<Time>40</Time>
<Variant>upgrading</Variant>
</GreatArcheryTower>
</Upgrade>
<Obstruction>
<Static depth="8.0" width="7.0"/>
</Obstruction>
<StatusBars>
<HeightOffset>22.0</HeightOffset>
</StatusBars>
<Upgrade>
<GreatArcheryTower>
<Entity>structures/{civ}/defense_tower_great</Entity>
<Tooltip>This tower has greater range, greater attack, greater health, and is twice as difficult to capture.</Tooltip>
<Cost>
<stone>200</stone>
</Cost>
<Time>40</Time>
<Variant>upgrading</Variant>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</GreatArcheryTower>
</Upgrade>
<VisualActor>
<Actor>structures/han/tower_large.xml</Actor>
</VisualActor>

View File

@ -23,7 +23,9 @@
<Classes datatype="tokens">CivSpecific</Classes>
<VisibleClasses datatype="tokens">LaoziGate Town</VisibleClasses>
<Icon>structures/paifang.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Loot>
<stone>20</stone>

View File

@ -38,8 +38,10 @@
<Classes datatype="tokens">CivSpecific</Classes>
<VisibleClasses datatype="tokens">ImperialMinistry Town</VisibleClasses>
<Tooltip>Train the Nine Ministers. Territory root. Research a powerful suite of Administrative technologies.</Tooltip>
<RequiredTechnology>phase_town</RequiredTechnology>
<Icon>structures/imperial_ministry.png</Icon>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Loot>
<xp>200</xp>

View File

@ -6,7 +6,9 @@
<Tooltip>Wall off an area. Build in own or neutral territory.</Tooltip>
<VisibleClasses datatype="tokens">-Wall Palisade</VisibleClasses>
<Icon>structures/palisade_wall.png</Icon>
<RequiredTechnology>phase_village</RequiredTechnology>
<Requirements>
<Techs>phase_village</Techs>
</Requirements>
</Identity>
<WallSet>
<MaxTowerOverlap>0.95</MaxTowerOverlap>

View File

@ -33,7 +33,9 @@
<Classes datatype="tokens">CivSpecific</Classes>
<VisibleClasses datatype="tokens">Monument Town</VisibleClasses>
<Icon>structures/iberian_bull.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Loot>
<stone>20</stone>

View File

@ -27,8 +27,10 @@
<SpecificName>mr ʿȝ</SpecificName>
<Classes datatype="tokens">-ConquestCritical CivSpecific</Classes>
<VisibleClasses datatype="tokens">City Pyramid</VisibleClasses>
<RequiredTechnology>phase_city</RequiredTechnology>
<Icon>structures/kush_pyramid_big.png</Icon>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</Identity>
<Loot>
<stone>90</stone>

View File

@ -24,8 +24,10 @@
<SpecificName>mr</SpecificName>
<Classes datatype="tokens">-ConquestCritical CivSpecific</Classes>
<VisibleClasses datatype="tokens">Village Pyramid</VisibleClasses>
<RequiredTechnology>phase_village</RequiredTechnology>
<Icon>structures/kush_pyramid_small.png</Icon>
<Requirements>
<Techs>phase_village</Techs>
</Requirements>
</Identity>
<Loot>
<stone>30</stone>

View File

@ -30,7 +30,9 @@
<Classes datatype="tokens">CivSpecific</Classes>
<VisibleClasses datatype="tokens">-Town City TempleOfAmun</VisibleClasses>
<Icon>structures/temple_epic.png</Icon>
<RequiredTechnology>phase_city</RequiredTechnology>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</Identity>
<Loot>
<stone op="mul">2</stone>

View File

@ -3,9 +3,11 @@
<Identity>
<Civ>maur</Civ>
<SpecificName>Vāraṇaśālā</SpecificName>
<RequiredTechnology>phase_town</RequiredTechnology>
<Classes datatype="tokens">CivSpecific</Classes>
<VisibleClasses datatype="tokens">-City Town</VisibleClasses>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<VisualActor>
<Actor>structures/mauryas/stable_elephant.xml</Actor>

View File

@ -18,7 +18,9 @@
<Tooltip>Higher health tower with ramparts for up to 16 archers. Visibly garrisoned archers recieve a range and armor bonus. Only archers can garrison. Needs the murder holes tech to protect its foot.</Tooltip>
<Civ>maur</Civ>
<SpecificName>Udarka</SpecificName>
<RequiredTechnology>phase_city</RequiredTechnology>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</Identity>
<Loot>
<stone>40</stone>
@ -29,52 +31,84 @@
<TurretHolder>
<TurretPoints>
<Archer1>
<X>2</X><Y>12.5</Y><Z>0</Z>
<X>2</X>
<Y>12.5</Y>
<Z>0</Z>
</Archer1>
<Archer2>
<X>2</X><Y>12.5</Y><Z>2</Z>
<X>2</X>
<Y>12.5</Y>
<Z>2</Z>
</Archer2>
<Archer3>
<X>2</X><Y>12.5</Y><Z>-2</Z>
<X>2</X>
<Y>12.5</Y>
<Z>-2</Z>
</Archer3>
<Archer4>
<X>0</X><Y>12.5</Y><Z>2</Z>
<X>0</X>
<Y>12.5</Y>
<Z>2</Z>
</Archer4>
<Archer5>
<X>0</X><Y>12.5</Y><Z>-2</Z>
<X>0</X>
<Y>12.5</Y>
<Z>-2</Z>
</Archer5>
<Archer6>
<X>-2</X><Y>12.5</Y><Z>0</Z>
<X>-2</X>
<Y>12.5</Y>
<Z>0</Z>
</Archer6>
<Archer7>
<X>-2</X><Y>12.5</Y><Z>2</Z>
<X>-2</X>
<Y>12.5</Y>
<Z>2</Z>
</Archer7>
<Archer8>
<X>-2</X><Y>12.5</Y><Z>-2</Z>
<X>-2</X>
<Y>12.5</Y>
<Z>-2</Z>
</Archer8>
<Archer9>
<X>2.1</X><Y>18.0</Y><Z>0</Z>
<X>2.1</X>
<Y>18.0</Y>
<Z>0</Z>
</Archer9>
<Archer10>
<X>2.1</X><Y>18.0</Y><Z>2.1</Z>
<X>2.1</X>
<Y>18.0</Y>
<Z>2.1</Z>
</Archer10>
<Archer11>
<X>2.1</X><Y>18.0</Y><Z>-2.1</Z>
<X>2.1</X>
<Y>18.0</Y>
<Z>-2.1</Z>
</Archer11>
<Archer12>
<X>0</X><Y>18.0</Y><Z>2.1</Z>
<X>0</X>
<Y>18.0</Y>
<Z>2.1</Z>
</Archer12>
<Archer13>
<X>0</X><Y>18.0</Y><Z>-2.1</Z>
<X>0</X>
<Y>18.0</Y>
<Z>-2.1</Z>
</Archer13>
<Archer14>
<X>-2.1</X><Y>18.0</Y><Z>0</Z>
<X>-2.1</X>
<Y>18.0</Y>
<Z>0</Z>
</Archer14>
<Archer15>
<X>-2.1</X><Y>18.0</Y><Z>2.1</Z>
<X>-2.1</X>
<Y>18.0</Y>
<Z>2.1</Z>
</Archer15>
<Archer16>
<X>-2.1</X><Y>18.0</Y><Z>-2.1</Z>
<X>-2.1</X>
<Y>18.0</Y>
<Z>-2.1</Z>
</Archer16>
</TurretPoints>
</TurretHolder>

View File

@ -30,7 +30,9 @@
<Classes datatype="tokens">MercenaryCamp</Classes>
<Tooltip>Capture this structure to train mercenaries from Hellenistic Egypt.</Tooltip>
<Icon>structures/military_settlement.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Loot>
<wood>20</wood>

View File

@ -1,72 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<Entity parent="template_structure_special">
<BuildRestrictions>
<Territory>own</Territory>
<Category>Yakhchal</Category>
</BuildRestrictions>
<Cost>
<BuildTime>60</BuildTime>
<Resources>
<stone>100</stone>
<wood>100</wood>
</Resources>
</Cost>
<Footprint replace="">
<Circle radius="10.0"/>
<Height>12.0</Height>
</Footprint>
<GarrisonHolder disable=""/>
<Health>
<Max>800</Max>
<SpawnEntityOnDeath>decay|rubble/rubble_stone_3x3</SpawnEntityOnDeath>
</Health>
<Identity>
<Civ>pers</Civ>
<GenericName>Ice House</GenericName>
<SpecificName>Yakhchāl</SpecificName>
<VisibleClasses datatype="tokens">-City Village IceHouse</VisibleClasses>
<Classes datatype="tokens">
CivSpecific
</Classes>
<RequiredTechnology>phase_village</RequiredTechnology>
<Icon>structures/yakhchal.png</Icon>
</Identity>
<Loot>
<stone>20</stone>
<wood>20</wood>
</Loot>
<Obstruction>
<Static width="16.0" depth="16.0"/>
</Obstruction>
<ProductionQueue/>
<Researcher>
<Technologies datatype="tokens">
subterranean_aqueducts
</Technologies>
</Researcher>
<ResourceTrickle>
<Rates>
<food>1.0</food>
</Rates>
<Interval>2000</Interval>
</ResourceTrickle>
<Sound>
<SoundGroups>
<select>interface/select/building/sel_farmstead.xml</select>
<constructed>interface/complete/building/complete_farmstead.xml</constructed>
<death>attack/destruction/building_collapse_large.xml</death>
</SoundGroups>
</Sound>
<TerritoryInfluence>
<Root>false</Root>
<Radius>20</Radius>
<Weight>30000</Weight>
</TerritoryInfluence>
<Vision>
<Range>20</Range>
</Vision>
<VisualActor>
<Actor>structures/persians/ice_house.xml</Actor>
<FoundationActor>structures/fndn_4x4.xml</FoundationActor>
</VisualActor>
</Entity>
<?xml version="1.0" encoding="utf-8"?>
<Entity parent="template_structure_special">
<BuildRestrictions>
<Territory>own</Territory>
<Category>Yakhchal</Category>
</BuildRestrictions>
<Cost>
<BuildTime>60</BuildTime>
<Resources>
<stone>100</stone>
<wood>100</wood>
</Resources>
</Cost>
<Footprint replace="">
<Circle radius="10.0"/>
<Height>12.0</Height>
</Footprint>
<GarrisonHolder disable=""/>
<Health>
<Max>800</Max>
<SpawnEntityOnDeath>decay|rubble/rubble_stone_3x3</SpawnEntityOnDeath>
</Health>
<Identity>
<Civ>pers</Civ>
<GenericName>Ice House</GenericName>
<SpecificName>Yakhchāl</SpecificName>
<VisibleClasses datatype="tokens">-City Village IceHouse</VisibleClasses>
<Classes datatype="tokens">
CivSpecific
</Classes>
<Icon>structures/yakhchal.png</Icon>
<Requirements>
<Techs>phase_village</Techs>
</Requirements>
</Identity>
<Loot>
<stone>20</stone>
<wood>20</wood>
</Loot>
<Obstruction>
<Static width="16.0" depth="16.0"/>
</Obstruction>
<ProductionQueue/>
<Researcher>
<Technologies datatype="tokens">
subterranean_aqueducts
</Technologies>
</Researcher>
<ResourceTrickle>
<Rates>
<food>1.0</food>
</Rates>
<Interval>2000</Interval>
</ResourceTrickle>
<Sound>
<SoundGroups>
<select>interface/select/building/sel_farmstead.xml</select>
<constructed>interface/complete/building/complete_farmstead.xml</constructed>
<death>attack/destruction/building_collapse_large.xml</death>
</SoundGroups>
</Sound>
<TerritoryInfluence>
<Root>false</Root>
<Radius>20</Radius>
<Weight>30000</Weight>
</TerritoryInfluence>
<Vision>
<Range>20</Range>
</Vision>
<VisualActor>
<Actor>structures/persians/ice_house.xml</Actor>
<FoundationActor>structures/fndn_4x4.xml</FoundationActor>
</VisualActor>
</Entity>

View File

@ -29,7 +29,9 @@
<Classes datatype="tokens">MercenaryCamp</Classes>
<Tooltip>Cheap Barracks-like structure that is buildable in neutral territory, but casts no territory influence. Train Mercenaries.</Tooltip>
<Icon>structures/mercenary_camp.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Loot>
<wood>20</wood>

View File

@ -75,7 +75,9 @@
<Classes datatype="tokens">ConquestCritical CivSpecific</Classes>
<VisibleClasses datatype="tokens">City ArmyCamp</VisibleClasses>
<Icon>structures/roman_camp.png</Icon>
<RequiredTechnology>phase_city</RequiredTechnology>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</Identity>
<Loot>
<wood>100</wood>

View File

@ -12,7 +12,9 @@
<GenericName>Temple of Mars</GenericName>
<SpecificName>Aedēs Mārtiālis</SpecificName>
<VisibleClasses datatype="tokens">-Town City TempleOfMars</VisibleClasses>
<RequiredTechnology>phase_city</RequiredTechnology>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</Identity>
<Obstruction>
<Static width="20.0" depth="40.0"/>

View File

@ -8,7 +8,9 @@
<Classes datatype="tokens">CivSpecific</Classes>
<VisibleClasses datatype="tokens">SiegeWall</VisibleClasses>
<Icon>structures/siege_wall.png</Icon>
<RequiredTechnology>phase_city</RequiredTechnology>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</Identity>
<WallSet>
<Templates>

View File

@ -5,7 +5,9 @@
<Tooltip>Wall off an area. Build in own or neutral territory.</Tooltip>
<VisibleClasses datatype="tokens">-Wall Palisade</VisibleClasses>
<Icon>structures/palisade_wall.png</Icon>
<RequiredTechnology>phase_village</RequiredTechnology>
<Requirements>
<Techs>phase_village</Techs>
</Requirements>
</Identity>
<WallSet>
<Templates>

View File

@ -28,7 +28,9 @@
<SelectionGroupName>template_structure_civic_civil_centre_military_colony</SelectionGroupName>
<VisibleClasses datatype="tokens">Colony</VisibleClasses>
<Icon>structures/military_settlement.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Loot>
<wood>40</wood>

View File

@ -27,7 +27,9 @@
<SelectionGroupName>template_structure_civic_house</SelectionGroupName>
<VisibleClasses datatype="tokens">Village House</VisibleClasses>
<Icon>structures/house.png</Icon>
<RequiredTechnology>phase_village</RequiredTechnology>
<Requirements>
<Techs>phase_village</Techs>
</Requirements>
</Identity>
<Loot>
<wood>15</wood>

View File

@ -29,7 +29,9 @@
<Classes datatype="tokens">-ConquestCritical</Classes>
<VisibleClasses datatype="tokens">Town Stoa</VisibleClasses>
<Icon>structures/stoa.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Loot>
<stone>20</stone>

View File

@ -31,7 +31,9 @@
<Tooltip>Train Healers and research healing technologies.</Tooltip>
<VisibleClasses datatype="tokens">Town Temple</VisibleClasses>
<Icon>structures/temple.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Loot>
<stone>60</stone>

View File

@ -55,7 +55,9 @@
<SelectionGroupName>template_structure_defensive_tower_artillery</SelectionGroupName>
<VisibleClasses datatype="tokens">ArtilleryTower</VisibleClasses>
<Icon>structures/tower_artillery.png</Icon>
<RequiredTechnology>phase_city</RequiredTechnology>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</Identity>
<Loot>
<wood>40</wood>

View File

@ -52,7 +52,9 @@
<SelectionGroupName>template_structure_defensive_tower_bolt</SelectionGroupName>
<VisibleClasses datatype="tokens">BoltTower</VisibleClasses>
<Icon>structures/tower_bolt.png</Icon>
<RequiredTechnology>phase_city</RequiredTechnology>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</Identity>
<Loot>
<stone>40</stone>

View File

@ -34,7 +34,9 @@
<Tooltip>Garrison Infantry for additional arrows. Needs the “Murder Holes” technology to protect its foot.</Tooltip>
<VisibleClasses datatype="tokens">SentryTower</VisibleClasses>
<Icon>structures/sentry_tower.png</Icon>
<RequiredTechnology>phase_village</RequiredTechnology>
<Requirements>
<Techs>phase_village</Techs>
</Requirements>
</Identity>
<Loot>
<wood>20</wood>
@ -57,13 +59,15 @@
<Tower>
<Entity>structures/{civ}/defense_tower</Entity>
<Tooltip>Reinforce with stone and upgrade to a defense tower.</Tooltip>
<RequiredTechnology>phase_town</RequiredTechnology>
<Cost>
<wood>50</wood>
<stone>100</stone>
</Cost>
<Variant>upgrading</Variant>
<Time>100</Time>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Tower>
</Upgrade>
</Entity>

View File

@ -32,7 +32,9 @@
<Tooltip>Garrison Infantry for additional arrows. Needs the “Murder Holes” technology to protect its foot.</Tooltip>
<VisibleClasses datatype="tokens">StoneTower</VisibleClasses>
<Icon>structures/defense_tower.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Loot>
<wood>20</wood>

View File

@ -14,7 +14,9 @@
<Tooltip>Wall off your town for a stout defense.</Tooltip>
<VisibleClasses datatype="tokens">Wall</VisibleClasses>
<Icon>structures/wall.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Obstruction>
<Static width="6.0" depth="6.0"/>

View File

@ -29,7 +29,9 @@
<Classes datatype="tokens">DropsiteFood</Classes>
<VisibleClasses datatype="tokens">Village Farmstead</VisibleClasses>
<Icon>structures/farmstead.png</Icon>
<RequiredTechnology>phase_village</RequiredTechnology>
<Requirements>
<Techs>phase_village</Techs>
</Requirements>
</Identity>
<Loot>
<wood>20</wood>

View File

@ -27,7 +27,9 @@
<Classes datatype="tokens">Barter</Classes>
<VisibleClasses datatype="tokens">Trade Town Market</VisibleClasses>
<Icon>structures/market.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Loot>
<wood>60</wood>

View File

@ -27,7 +27,9 @@
<Classes datatype="tokens">DropsiteWood DropsiteMetal DropsiteStone</Classes>
<VisibleClasses datatype="tokens">Village Storehouse</VisibleClasses>
<Icon>structures/storehouse.png</Icon>
<RequiredTechnology>phase_village</RequiredTechnology>
<Requirements>
<Techs>phase_village</Techs>
</Requirements>
</Identity>
<Loot>
<wood>20</wood>

View File

@ -27,7 +27,9 @@
<Tooltip>Train Champion Infantry Crossbowmen, construct Siege Engines, and research Siege Engine technologies.</Tooltip>
<VisibleClasses datatype="tokens">City Arsenal</VisibleClasses>
<Icon>structures/siege_workshop.png</Icon>
<RequiredTechnology>phase_city</RequiredTechnology>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</Identity>
<Loot>
<wood>60</wood>

View File

@ -28,7 +28,9 @@
<Tooltip>Train Infantry and research Infantry technologies.</Tooltip>
<VisibleClasses datatype="tokens">Village Barracks</VisibleClasses>
<Icon>structures/barracks.png</Icon>
<RequiredTechnology>phase_village</RequiredTechnology>
<Requirements>
<Techs>phase_village</Techs>
</Requirements>
</Identity>
<Loot>
<wood>40</wood>

View File

@ -27,8 +27,10 @@
<SelectionGroupName>template_structure_military_elephant_stable</SelectionGroupName>
<Tooltip>Train Elephants and research Elephant technologies.</Tooltip>
<VisibleClasses datatype="tokens">City ElephantStable</VisibleClasses>
<RequiredTechnology>phase_city</RequiredTechnology>
<Icon>structures/stable_elephant.png</Icon>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</Identity>
<Loot>
<wood>40</wood>

View File

@ -22,7 +22,9 @@
<GenericName>Embassy</GenericName>
<SelectionGroupName>template_structure_military_embassy</SelectionGroupName>
<VisibleClasses datatype="tokens">Town Embassy</VisibleClasses>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Obstruction>
<Static width="16.0" depth="16.0"/>

View File

@ -25,7 +25,9 @@
<Classes datatype="tokens">-ConquestCritical</Classes>
<VisibleClasses datatype="tokens">Town Forge</VisibleClasses>
<Icon>structures/blacksmith.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Loot>
<wood>40</wood>

View File

@ -68,7 +68,9 @@
<Classes datatype="tokens">GarrisonFortress</Classes>
<VisibleClasses datatype="tokens">Defensive Fortress</VisibleClasses>
<Icon>structures/fortress.png</Icon>
<RequiredTechnology>phase_city</RequiredTechnology>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</Identity>
<Loot>
<wood>60</wood>

View File

@ -24,7 +24,9 @@
<Tooltip>Train Ranged Infantry and research technologies.</Tooltip>
<VisibleClasses datatype="tokens">Village Range</VisibleClasses>
<Icon>structures/range.png</Icon>
<RequiredTechnology>phase_village</RequiredTechnology>
<Requirements>
<Techs>phase_village</Techs>
</Requirements>
</Identity>
<Loot>
<wood>40</wood>

View File

@ -28,7 +28,9 @@
<Tooltip>Train Cavalry and research Cavalry technologies.</Tooltip>
<VisibleClasses datatype="tokens">Village Stable</VisibleClasses>
<Icon>structures/stable_01.png</Icon>
<RequiredTechnology>phase_village</RequiredTechnology>
<Requirements>
<Techs>phase_village</Techs>
</Requirements>
</Identity>
<Loot>
<wood>40</wood>

View File

@ -31,7 +31,9 @@
<Tooltip>Raise Domestic Animals for immediate slaughter, or garrison them instead to gain a free trickle of food.</Tooltip>
<VisibleClasses datatype="tokens">Economic Village Corral</VisibleClasses>
<Icon>structures/corral.png</Icon>
<RequiredTechnology>phase_village</RequiredTechnology>
<Requirements>
<Techs>phase_village</Techs>
</Requirements>
</Identity>
<Loot>
<wood>20</wood>

View File

@ -18,7 +18,9 @@
<Identity>
<GenericName>Special Structure</GenericName>
<VisibleClasses datatype="tokens">City</VisibleClasses>
<RequiredTechnology>phase_city</RequiredTechnology>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</Identity>
<Obstruction>
<Static width="24.0" depth="24.0"/>

View File

@ -40,7 +40,9 @@
<Classes datatype="tokens">ConquestCritical</Classes>
<VisibleClasses datatype="tokens">City Wonder</VisibleClasses>
<Icon>structures/wonder.png</Icon>
<RequiredTechnology>phase_city</RequiredTechnology>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</Identity>
<Loot>
<wood>200</wood>

View File

@ -13,7 +13,9 @@
<Classes datatype="tokens">Human</Classes>
<VisibleClasses datatype="tokens">Soldier Champion</VisibleClasses>
<GenericName>Champion Unit</GenericName>
<RequiredTechnology>phase_city</RequiredTechnology>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</Identity>
<Position>
<TurnRate>8</TurnRate>

View File

@ -19,7 +19,9 @@
<Classes datatype="tokens">FastMoving</Classes>
<VisibleClasses datatype="tokens">Cavalry</VisibleClasses>
<GenericName>Champion Cavalry</GenericName>
<RequiredTechnology>unlock_champion_cavalry</RequiredTechnology>
<Requirements>
<Techs>unlock_champion_cavalry</Techs>
</Requirements>
</Identity>
<Loot>
<xp>200</xp>

View File

@ -1,7 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<Entity parent="template_unit_fauna_herd_domestic">
<Identity>
<RequiredTechnology>phase_city</RequiredTechnology>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</Identity>
<ResourceTrickle>
<Interval>2000</Interval>

View File

@ -25,7 +25,9 @@
<VisibleClasses datatype="tokens">Soldier Hero</VisibleClasses>
<GenericName>Hero</GenericName>
<Icon>technologies/laurel_wreath.png</Icon>
<RequiredTechnology>phase_city</RequiredTechnology>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</Identity>
<Loot>
<xp>400</xp>

View File

@ -50,7 +50,9 @@
<GenericName>Light Warship</GenericName>
<Tooltip>Garrison units for transport and to increase firepower. Deals triple damage against Ships.</Tooltip>
<VisibleClasses datatype="tokens">Ranged Warship Bireme</VisibleClasses>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Loot>
<xp>80</xp>

View File

@ -40,7 +40,9 @@
<GenericName>Fire Ship</GenericName>
<Tooltip>Unrepairable. Gradually loses health. Can only attack Ships.</Tooltip>
<VisibleClasses datatype="tokens">Melee Warship Fireship</VisibleClasses>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Loot disable=""/>
<Repairable disable=""/>

View File

@ -19,7 +19,9 @@
<Tooltip>Trade between docks. Garrison a Trader aboard for additional profit (+20% for each garrisoned). Gather profitable aquatic treasures.</Tooltip>
<Classes datatype="tokens">-ConquestCritical</Classes>
<VisibleClasses datatype="tokens">Trader Bribable</VisibleClasses>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Loot>
<metal>20</metal>

View File

@ -54,7 +54,9 @@
<GenericName>Heavy Warship</GenericName>
<Tooltip>Garrison units for transport and to increase firepower.</Tooltip>
<VisibleClasses datatype="tokens">Ranged Warship Quinquereme</VisibleClasses>
<RequiredTechnology>phase_city</RequiredTechnology>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</Identity>
<Loot>
<xp>200</xp>

View File

@ -50,7 +50,9 @@
<GenericName>Medium Warship</GenericName>
<Tooltip>Garrison units for transport and to increase firepower. Deals triple damage against Ships.</Tooltip>
<VisibleClasses datatype="tokens">Ranged Warship Trireme</VisibleClasses>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Loot>
<xp>140</xp>

View File

@ -15,7 +15,9 @@
<Classes datatype="tokens">-Organic</Classes>
<VisibleClasses datatype="tokens">Siege</VisibleClasses>
<GenericName>Siege</GenericName>
<RequiredTechnology>phase_city</RequiredTechnology>
<Requirements>
<Techs>phase_city</Techs>
</Requirements>
</Identity>
<Position>
<Anchor>pitch-roll</Anchor>

View File

@ -27,8 +27,10 @@
<GenericName>Healer</GenericName>
<SelectionGroupName>template_unit_support_healer</SelectionGroupName>
<Rank>Basic</Rank>
<RequiredTechnology>phase_town</RequiredTechnology>
<Tooltip>Heal units.</Tooltip>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Loot>
<xp>8</xp>

View File

@ -10,8 +10,10 @@
<Tooltip>Wall off an area.</Tooltip>
<VisibleClasses datatype="tokens">Wall</VisibleClasses>
<Icon>structures/wall.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Undeletable>true</Undeletable>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Visibility>
<RetainInFog>false</RetainInFog>

View File

@ -10,7 +10,9 @@
<GenericName>Greek Cavalry</GenericName>
<SpecificName>Hippeús</SpecificName>
<Icon>units/athen/cavalry_swordsman.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Promotion>
<Entity>units/athen/cavalry_swordsman_a</Entity>

View File

@ -4,7 +4,9 @@
<GenericName>Athenian Marine</GenericName>
<SpecificName>Epibátēs Athēnaîos</SpecificName>
<Icon>units/athen/champion_marine.png</Icon>
<RequiredTechnology>iphicratean_reforms</RequiredTechnology>
<Requirements>
<Techs>iphicratean_reforms</Techs>
</Requirements>
</Identity>
<VisualActor>
<Actor>units/athenians/infantry_swordsman_c.xml</Actor>

View File

@ -5,7 +5,9 @@
<GenericName>Thracian Peltast</GenericName>
<SpecificName>Peltastḗs Thrâx</SpecificName>
<Icon>units/athen/infantry_javelinist.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Promotion>
<Entity>units/athen/infantry_javelineer_a</Entity>

View File

@ -5,7 +5,9 @@
<GenericName>Cretan Mercenary Archer</GenericName>
<SpecificName>Toxótēs Krētikós</SpecificName>
<Icon>units/mace/infantry_archer.png</Icon>
<RequiredTechnology>iphicratean_reforms</RequiredTechnology>
<Requirements>
<Techs>iphicratean_reforms</Techs>
</Requirements>
</Identity>
<Promotion>
<Entity>units/athen/infantry_marine_archer_a</Entity>

View File

@ -4,6 +4,8 @@
<BuildTime>30</BuildTime>
</Cost>
<Identity>
<RequiredTechnology>unlock_females_house</RequiredTechnology>
<Requirements>
<Techs>unlock_females_house</Techs>
</Requirements>
</Identity>
</Entity>

View File

@ -6,7 +6,9 @@
<SpecificName>Eporedos</SpecificName>
<GenericName>Celtic Cavalry</GenericName>
<Icon>units/brit/cavalry_swordsman.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Promotion>
<Entity>units/brit/cavalry_swordsman_a</Entity>

View File

@ -11,7 +11,9 @@
<SelectionGroupName>units/brit/champion_chariot</SelectionGroupName>
<VisibleClasses datatype="tokens">Chariot</VisibleClasses>
<Icon>units/brit/champion_chariot.png</Icon>
<RequiredTechnology>unlock_champion_chariots</RequiredTechnology>
<Requirements>
<Techs>unlock_champion_chariots</Techs>
</Requirements>
</Identity>
<VisualActor>
<Actor>units/britons/chariot_javelinist_c_m.xml</Actor>

View File

@ -5,7 +5,9 @@
<GenericName>Brythonic Champion</GenericName>
<SpecificName>Argos</SpecificName>
<Icon>units/brit/champion_infantry.png</Icon>
<RequiredTechnology>unlock_champion_infantry</RequiredTechnology>
<Requirements>
<Techs>unlock_champion_infantry</Techs>
</Requirements>
</Identity>
<VisualActor>
<Actor>units/britons/infantry_swordsman_c.xml</Actor>

View File

@ -12,7 +12,9 @@
<SelectionGroupName>units/brit/infantry_javelineer_b</SelectionGroupName>
<SpecificName>Adretos</SpecificName>
<Icon>units/brit/infantry_javelinist.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Promotion>
<Entity>units/brit/infantry_javelineer_a</Entity>

View File

@ -4,6 +4,8 @@
<BuildTime>30</BuildTime>
</Cost>
<Identity>
<RequiredTechnology>unlock_females_house</RequiredTechnology>
<Requirements>
<Techs>unlock_females_house</Techs>
</Requirements>
</Identity>
</Entity>

View File

@ -6,7 +6,9 @@
<SpecificName>Ḥayyāl Romaḥ Raḫūv</SpecificName>
<SelectionGroupName>units/cart/cavalry_spearman_ital_b</SelectionGroupName>
<Icon>units/cart/cavalry_spearman.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Promotion>
<Entity>units/cart/cavalry_spearman_ital_a</Entity>

View File

@ -6,7 +6,9 @@
<SpecificName>Ḥayyāl Ḥerev Raḫūv</SpecificName>
<SelectionGroupName>units/cart/cavalry_swordsman_gaul_b</SelectionGroupName>
<Icon>units/cart/cavalry_swordsman_2.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Promotion>
<Entity>units/cart/cavalry_swordsman_gaul_a</Entity>

View File

@ -11,7 +11,9 @@
<SpecificName>Ḥayyāl Ḥerev Raḫūv</SpecificName>
<SelectionGroupName>units/cart/cavalry_swordsman_iber_b</SelectionGroupName>
<Icon>units/cart/cavalry_swordsman.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Promotion>
<Entity>units/cart/cavalry_swordsman_iber_a</Entity>

View File

@ -14,7 +14,9 @@
<SpecificName>Sǝḫīr Kidōn</SpecificName>
<SelectionGroupName>units/cart/infantry_javelineer_iber_b</SelectionGroupName>
<Icon>units/cart/infantry_javelinist.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Promotion>
<Entity>units/cart/infantry_javelineer_iber_a</Entity>

View File

@ -14,7 +14,9 @@
<SpecificName>Qallāʿ Ibušimi</SpecificName>
<SelectionGroupName>units/cart/infantry_slinger_iber_b</SelectionGroupName>
<Icon>units/cart/infantry_slinger.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Promotion>
<Entity>units/cart/infantry_slinger_iber_a</Entity>

View File

@ -14,7 +14,9 @@
<SpecificName>Seḫīr Ḥerev</SpecificName>
<SelectionGroupName>units/cart/infantry_swordsman_gaul_b</SelectionGroupName>
<Icon>units/cart/infantry_swordsman.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Promotion>
<Entity>units/cart/infantry_swordsman_gaul_a</Entity>

View File

@ -14,7 +14,9 @@
<SpecificName>Seḫīr Romaḥ</SpecificName>
<SelectionGroupName>units/cart/infantry_swordsman_ital_b</SelectionGroupName>
<Icon>units/cart/infantry_swordsman_2.png</Icon>
<RequiredTechnology>phase_town</RequiredTechnology>
<Requirements>
<Techs>phase_town</Techs>
</Requirements>
</Identity>
<Promotion>
<Entity>units/cart/infantry_swordsman_ital_a</Entity>

View File

@ -9,7 +9,9 @@
<SpecificName>Seḥer</SpecificName>
<Tooltip>Trade between docks. Garrison a Trader aboard for additional profit (+20% for each garrisoned). Gather profitable aquatic treasures. Carthaginians have +25% sea trading bonus.</Tooltip>
<Icon>units/cart/ship_merchant.png</Icon>
<RequiredTechnology>phase_village</RequiredTechnology>
<Requirements>
<Techs>phase_village</Techs>
</Requirements>
</Identity>
<Selectable>
<Overlay>

View File

@ -4,6 +4,8 @@
<BuildTime>30</BuildTime>
</Cost>
<Identity>
<RequiredTechnology>unlock_females_house</RequiredTechnology>
<Requirements>
<Techs>unlock_females_house</Techs>
</Requirements>
</Identity>
</Entity>

Some files were not shown because too many files have changed in this diff Show More