Index: ps/trunk/binaries/data/mods/public/gui/common/tooltips.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/common/tooltips.js (revision 27504)
+++ ps/trunk/binaries/data/mods/public/gui/common/tooltips.js (revision 27505)
@@ -1,1242 +1,1242 @@
var g_TooltipTextFormats = {
"unit": { "font": "sans-10", "color": "orange" },
"header": { "font": "sans-bold-13" },
"body": { "font": "sans-13" },
"objection": { "font": "sans-bold-13", "color": "red" },
"comma": { "font": "sans-12" },
"namePrimaryBig": { "font": "sans-bold-16" },
"namePrimarySmall": { "font": "sans-bold-12" },
"nameSecondary": { "font": "sans-bold-16" }
};
var g_SpecificNamesPrimary = Engine.ConfigDB_GetValue("user", "gui.session.howtoshownames") == 0 || Engine.ConfigDB_GetValue("user", "gui.session.howtoshownames") == 2;
var g_ShowSecondaryNames = Engine.ConfigDB_GetValue("user", "gui.session.howtoshownames") == 0 || Engine.ConfigDB_GetValue("user", "gui.session.howtoshownames") == 1;
function initDisplayedNames()
{
registerConfigChangeHandler(changes => {
if (changes.has("gui.session.howtoshownames"))
updateDisplayedNames();
});
}
/**
* String of four spaces to be used as indentation in gui strings.
*/
var g_Indent = " ";
var g_DamageTypesMetadata = new DamageTypesMetadata();
var g_StatusEffectsMetadata = new StatusEffectsMetadata();
/**
* If true, always shows whether the splash damage deals friendly fire.
* Otherwise display the friendly fire tooltip only if it does.
*/
var g_AlwaysDisplayFriendlyFire = false;
function getCostTypes()
{
return g_ResourceData.GetCodes().concat(["population", "time"]);
}
function resourceIcon(resource)
{
return '[icon="icon_' + resource + '"]';
}
function resourceNameFirstWord(type)
{
return translateWithContext("firstWord", g_ResourceData.GetNames()[type]);
}
function resourceNameWithinSentence(type)
{
return translateWithContext("withinSentence", g_ResourceData.GetNames()[type]);
}
/**
* Format resource amounts to proper english and translate (for example: "200 food, 100 wood and 300 metal").
*/
function getLocalizedResourceAmounts(resources)
{
let amounts = g_ResourceData.GetCodes()
.filter(type => !!resources[type])
.map(type => sprintf(translate("%(amount)s %(resourceType)s"), {
"amount": resources[type],
"resourceType": resourceNameWithinSentence(type)
}));
if (amounts.length < 2)
return amounts.join();
let lastAmount = amounts.pop();
return sprintf(translate("%(previousAmounts)s and %(lastAmount)s"), {
// Translation: This comma is used for separating first to penultimate elements in an enumeration.
"previousAmounts": amounts.join(translate(", ")),
"lastAmount": lastAmount
});
}
function bodyFont(text)
{
return setStringTags(text, g_TooltipTextFormats.body);
}
function objectionFont(text)
{
return setStringTags(text, g_TooltipTextFormats.objection);
}
function headerFont(text)
{
return setStringTags(text, g_TooltipTextFormats.header);
}
function unitFont(text)
{
return setStringTags(text, g_TooltipTextFormats.unit);
}
function commaFont(text)
{
return setStringTags(text, g_TooltipTextFormats.comma);
}
function getSecondsString(seconds)
{
return sprintf(translatePlural("%(time)s %(second)s", "%(time)s %(second)s", seconds), {
"time": seconds,
"second": unitFont(translatePlural("second", "seconds", seconds))
});
}
/**
* Entity templates have a `Tooltip` tag in the Identity component.
* (The contents of which are copied to a `tooltip` attribute in globalscripts.)
*
* Technologies have a `tooltip` attribute.
*/
function getEntityTooltip(template)
{
if (!template.tooltip)
return "";
return bodyFont(template.tooltip);
}
/**
* Technologies have a `description` attribute, and Auras have an `auraDescription`
* attribute, which becomes `description`.
*
* (For technologies, this happens in globalscripts.)
*
* (For auras, this happens either in the Auras component (for session gui) or
* reference/common/load.js (for Reference Suite gui))
*/
function getDescriptionTooltip(template)
{
if (!template.description)
return "";
return bodyFont(template.description);
}
/**
* Entity templates have a `History` tag in the Identity component.
* (The contents of which are copied to a `history` attribute in globalscripts.)
*/
function getHistoryTooltip(template)
{
if (!template.history)
return "";
return bodyFont(template.history);
}
function getHealthTooltip(template)
{
if (!template.health)
return "";
return sprintf(translate("%(label)s %(details)s"), {
"label": headerFont(translate("Health:")),
"details": template.health
});
}
function getCurrentHealthTooltip(entState, label)
{
if (!entState.maxHitpoints)
return "";
return sprintf(translate("%(healthLabel)s %(current)s / %(max)s"), {
"healthLabel": headerFont(label || translate("Health:")),
"current": Math.round(entState.hitpoints),
"max": Math.round(entState.maxHitpoints)
});
}
function getCurrentCaptureTooltip(entState, label)
{
if (!entState.maxCapturePoints)
return "";
return sprintf(translate("%(captureLabel)s %(current)s / %(max)s"), {
"captureLabel": headerFont(label || translate("Capture points:")),
"current": Math.round(entState.capturePoints[entState.player]),
"max": Math.round(entState.maxCapturePoints)
});
}
/**
* Converts an resistance level into the actual reduction percentage.
*/
function resistanceLevelToPercentageString(level)
{
return sprintf(translate("%(percentage)s%%"), {
"percentage": (100 - Math.round(Math.pow(0.9, level) * 100))
});
}
function getResistanceTooltip(template)
{
if (!template.resistance)
return "";
let details = [];
if (template.resistance.Damage)
details.push(getDamageResistanceTooltip(template.resistance.Damage));
if (template.resistance.Capture)
details.push(getCaptureResistanceTooltip(template.resistance.Capture));
if (template.resistance.ApplyStatus)
details.push(getStatusEffectsResistanceTooltip(template.resistance.ApplyStatus));
return details.length ? sprintf(translate("%(label)s\n%(details)s"), {
"label": headerFont(translate("Resistance:")),
"details": g_Indent + details.join("\n" + g_Indent)
}) : "";
}
function getDamageResistanceTooltip(resistanceTypeTemplate)
{
if (!resistanceTypeTemplate)
return "";
return sprintf(translate("%(label)s %(details)s"), {
"label": headerFont(translate("Damage:")),
"details":
g_DamageTypesMetadata.sort(Object.keys(resistanceTypeTemplate)).map(
dmgType => sprintf(translate("%(damage)s %(damageType)s %(resistancePercentage)s"), {
"damage": resistanceTypeTemplate[dmgType].toFixed(1),
"damageType": unitFont(translateWithContext("damage type", g_DamageTypesMetadata.getName(dmgType))),
"resistancePercentage":
'[font="sans-10"]' +
sprintf(translate("(%(resistancePercentage)s)"), {
"resistancePercentage": resistanceLevelToPercentageString(resistanceTypeTemplate[dmgType])
}) + '[/font]'
})
).join(commaFont(translate(", ")))
});
}
function getCaptureResistanceTooltip(resistanceTypeTemplate)
{
if (!resistanceTypeTemplate)
return "";
return sprintf(translate("%(label)s %(details)s"), {
"label": headerFont(translate("Capture:")),
"details":
sprintf(translate("%(damage)s %(damageType)s %(resistancePercentage)s"), {
"damage": resistanceTypeTemplate.toFixed(1),
"damageType": unitFont(translateWithContext("damage type", "Capture")),
"resistancePercentage":
'[font="sans-10"]' +
sprintf(translate("(%(resistancePercentage)s)"), {
"resistancePercentage": resistanceLevelToPercentageString(resistanceTypeTemplate)
}) + '[/font]'
})
});
}
function getStatusEffectsResistanceTooltip(resistanceTypeTemplate)
{
if (!resistanceTypeTemplate)
return "";
return sprintf(translate("%(label)s %(details)s"), {
"label": headerFont(translate("Status Effects:")),
"details":
Object.keys(resistanceTypeTemplate).map(
statusEffect => {
if (resistanceTypeTemplate[statusEffect].blockChance == 1)
return sprintf(translate("Blocks %(name)s"), {
"name": unitFont(translateWithContext("status effect", g_StatusEffectsMetadata.getName(statusEffect)))
});
if (resistanceTypeTemplate[statusEffect].blockChance == 0)
return sprintf(translate("%(name)s %(details)s"), {
"name": unitFont(translateWithContext("status effect", g_StatusEffectsMetadata.getName(statusEffect))),
"details": sprintf(translate("Duration reduction: %(durationReduction)s%%"), {
"durationReduction": (100 - resistanceTypeTemplate[statusEffect].duration * 100)
})
});
if (resistanceTypeTemplate[statusEffect].duration == 1)
return sprintf(translate("%(name)s %(details)s"), {
"name": unitFont(translateWithContext("status effect", g_StatusEffectsMetadata.getName(statusEffect))),
"details": sprintf(translate("Blocks: %(blockPercentage)s%%"), {
"blockPercentage": resistanceTypeTemplate[statusEffect].blockChance * 100
})
});
return sprintf(translate("%(name)s %(details)s"), {
"name": unitFont(translateWithContext("status effect", g_StatusEffectsMetadata.getName(statusEffect))),
"details": sprintf(translate("Blocks: %(blockPercentage)s%%, Duration reduction: %(durationReduction)s%%"), {
"blockPercentage": resistanceTypeTemplate[statusEffect].blockChance * 100,
"durationReduction": (100 - resistanceTypeTemplate[statusEffect].duration * 100)
})
});
}
).join(commaFont(translate(", ")))
});
}
function attackRateDetails(interval, projectiles)
{
if (!interval)
return "";
if (projectiles === 0)
return translate("Garrison to fire arrows");
let attackRateString = getSecondsString(interval / 1000);
let header = headerFont(translate("Interval:"));
if (projectiles && +projectiles > 1)
{
header = headerFont(translate("Rate:"));
let projectileString = sprintf(translatePlural("%(projectileCount)s %(projectileName)s", "%(projectileCount)s %(projectileName)s", projectiles), {
"projectileCount": projectiles,
"projectileName": unitFont(translatePlural("arrow", "arrows", projectiles))
});
attackRateString = sprintf(translate("%(projectileString)s / %(attackRateString)s"), {
"projectileString": projectileString,
"attackRateString": attackRateString
});
}
return sprintf(translate("%(label)s %(details)s"), {
"label": header,
"details": attackRateString
});
}
function rangeDetails(attackTypeTemplate)
{
if (!attackTypeTemplate.maxRange)
return "";
let rangeTooltipString = {
"relative": {
// Translation: For example: Range: 2 to 10 (+2) meters
"minRange": translate("%(rangeLabel)s %(minRange)s to %(maxRange)s (%(relativeRange)s) %(rangeUnit)s"),
// Translation: For example: Range: 10 (+2) meters
"no-minRange": translate("%(rangeLabel)s %(maxRange)s (%(relativeRange)s) %(rangeUnit)s"),
},
"non-relative": {
// Translation: For example: Range: 2 to 10 meters
"minRange": translate("%(rangeLabel)s %(minRange)s to %(maxRange)s %(rangeUnit)s"),
// Translation: For example: Range: 10 meters
"no-minRange": translate("%(rangeLabel)s %(maxRange)s %(rangeUnit)s"),
}
};
let minRange = Math.round(attackTypeTemplate.minRange);
let maxRange = Math.round(attackTypeTemplate.maxRange);
let realRange = attackTypeTemplate.elevationAdaptedRange;
let relativeRange = realRange ? Math.round(realRange - maxRange) : 0;
return sprintf(rangeTooltipString[relativeRange ? "relative" : "non-relative"][minRange ? "minRange" : "no-minRange"], {
"rangeLabel": headerFont(translate("Range:")),
"minRange": minRange,
"maxRange": maxRange,
"relativeRange": relativeRange > 0 ? sprintf(translate("+%(number)s"), { "number": relativeRange }) : relativeRange,
"rangeUnit":
unitFont(minRange || relativeRange ?
// Translation: For example "0.5 to 1 meters", "1 (+1) meters" or "1 to 2 (+3) meters"
translate("meters") :
translatePlural("meter", "meters", maxRange))
});
}
function damageDetails(damageTemplate)
{
if (!damageTemplate)
return "";
return g_DamageTypesMetadata.sort(Object.keys(damageTemplate).filter(dmgType => damageTemplate[dmgType])).map(
dmgType => sprintf(translate("%(damage)s %(damageType)s"), {
"damage": (+damageTemplate[dmgType]).toFixed(1),
"damageType": unitFont(translateWithContext("damage type", g_DamageTypesMetadata.getName(dmgType)))
})).join(commaFont(translate(", ")));
}
function captureDetails(captureTemplate)
{
if (!captureTemplate)
return "";
return sprintf(translate("%(amount)s %(name)s"), {
"amount": (+captureTemplate).toFixed(1),
"name": unitFont(translateWithContext("damage type", "Capture"))
});
}
function splashDetails(splashTemplate)
{
let splashLabel = sprintf(headerFont(translate("%(splashShape)s Splash")), {
"splashShape": translate(splashTemplate.shape)
});
let splashDamageTooltip = sprintf(translate("%(label)s: %(effects)s"), {
"label": splashLabel,
"effects": attackEffectsDetails(splashTemplate)
});
if (g_AlwaysDisplayFriendlyFire || splashTemplate.friendlyFire)
splashDamageTooltip += commaFont(translate(", ")) + sprintf(translate("Friendly Fire: %(enabled)s"), {
"enabled": splashTemplate.friendlyFire ? translate("Yes") : translate("No")
});
return splashDamageTooltip;
}
function applyStatusDetails(applyStatusTemplate)
{
if (!applyStatusTemplate)
return "";
return sprintf(translate("gives %(name)s"), {
"name": Object.keys(applyStatusTemplate).map(x =>
unitFont(translateWithContext("status effect", g_StatusEffectsMetadata.getName(x)))
).join(commaFont(translate(", "))),
});
}
function attackEffectsDetails(attackTypeTemplate)
{
if (!attackTypeTemplate)
return "";
let effects = [
captureDetails(attackTypeTemplate.Capture || undefined),
damageDetails(attackTypeTemplate.Damage || undefined),
applyStatusDetails(attackTypeTemplate.ApplyStatus || undefined)
];
return effects.filter(effect => effect).join(commaFont(translate(", ")));
}
function getAttackTooltip(template)
{
if (!template.attack)
return "";
let tooltips = [];
for (let attackType in template.attack)
{
// Slaughter is used to kill animals, so do not show it.
if (attackType == "Slaughter")
continue;
let attackTypeTemplate = template.attack[attackType];
let attackLabel = sprintf(headerFont(translate("%(attackType)s")), {
"attackType": translateWithContext(attackTypeTemplate.attackName.context || "Name of an attack, usually the weapon.", attackTypeTemplate.attackName.name)
});
let projectiles;
// Use either current rate from simulation or default count if the sim is not running.
// TODO: This ought to be extended to include units which fire multiple projectiles.
if (template.buildingAI)
projectiles = template.buildingAI.arrowCount || template.buildingAI.defaultArrowCount;
let splashTemplate = attackTypeTemplate.splash;
// Show the effects of status effects below.
let statusEffectsDetails = [];
if (attackTypeTemplate.ApplyStatus)
for (let status in attackTypeTemplate.ApplyStatus)
statusEffectsDetails.push("\n" + g_Indent + g_Indent + getStatusEffectsTooltip(status, attackTypeTemplate.ApplyStatus[status], true));
statusEffectsDetails = statusEffectsDetails.join("");
tooltips.push(sprintf(translate("%(attackLabel)s: %(effects)s, %(range)s, %(rate)s%(statusEffects)s%(splash)s"), {
"attackLabel": attackLabel,
"effects": attackEffectsDetails(attackTypeTemplate),
"range": rangeDetails(attackTypeTemplate),
"rate": attackRateDetails(attackTypeTemplate.repeatTime, projectiles),
"splash": splashTemplate ? "\n" + g_Indent + g_Indent + splashDetails(splashTemplate) : "",
"statusEffects": statusEffectsDetails
}));
}
return sprintf(translate("%(label)s\n%(details)s"), {
"label": headerFont(translate("Attack:")),
"details": g_Indent + tooltips.join("\n" + g_Indent)
});
}
/**
* @param applier - if true, return the tooltip for the Applier. If false, Receiver is returned.
*/
function getStatusEffectsTooltip(statusCode, template, applier)
{
let tooltipAttributes = [];
let statusData = g_StatusEffectsMetadata.getData(statusCode);
if (template.Damage || template.Capture)
tooltipAttributes.push(attackEffectsDetails(template));
if (template.Interval)
tooltipAttributes.push(attackRateDetails(+template.Interval));
if (template.Duration)
tooltipAttributes.push(getStatusEffectDurationTooltip(template));
if (applier && statusData.applierTooltip)
tooltipAttributes.push(translateWithContext("status effect", statusData.applierTooltip));
else if (!applier && statusData.receiverTooltip)
tooltipAttributes.push(translateWithContext("status effect", statusData.receiverTooltip));
if (applier)
return sprintf(translate("%(statusName)s: %(statusInfo)s %(stackability)s"), {
"statusName": headerFont(translateWithContext("status effect", statusData.statusName)),
"statusInfo": tooltipAttributes.join(commaFont(translate(", "))),
"stackability": getStatusEffectStackabilityTooltip(template)
});
return sprintf(translate("%(statusName)s: %(statusInfo)s"), {
"statusName": headerFont(translateWithContext("status effect", statusData.statusName)),
"statusInfo": tooltipAttributes.join(commaFont(translate(", ")))
});
}
function getStatusEffectDurationTooltip(template)
{
if (!template.Duration)
return "";
return sprintf(translate("%(durName)s: %(duration)s"), {
"durName": headerFont(translate("Duration")),
"duration": getSecondsString((template._timeElapsed ?
+template.Duration - template._timeElapsed :
+template.Duration) / 1000)
});
}
function getStatusEffectStackabilityTooltip(template)
{
if (!template.Stackability || template.Stackability == "Ignore")
return "";
let stackabilityString = "";
if (template.Stackability === "Extend")
stackabilityString = translateWithContext("status effect stackability", "(extends)");
else if (template.Stackability === "Replace")
stackabilityString = translateWithContext("status effect stackability", "(replaces)");
else if (template.Stackability === "Stack")
stackabilityString = translateWithContext("status effect stackability", "(stacks)");
return sprintf(translate("%(stackability)s"), {
"stackability": stackabilityString
});
}
function getGarrisonTooltip(template)
{
let tooltips = [];
if (template.garrisonHolder)
{
tooltips.push (
sprintf(translate("%(label)s: %(garrisonLimit)s"), {
"label": headerFont(translate("Garrison Limit")),
"garrisonLimit": template.garrisonHolder.capacity
})
);
if (template.garrisonHolder.buffHeal)
tooltips.push(
sprintf(translate("%(healRateLabel)s %(value)s %(health)s / %(second)s"), {
"healRateLabel": headerFont(translate("Heal:")),
"value": Math.round(template.garrisonHolder.buffHeal),
"health": unitFont(translateWithContext("garrison tooltip", "Health")),
"second": unitFont(translate("second")),
})
);
tooltips.join(commaFont(translate(", ")));
}
if (template.garrisonable)
{
let extraSize;
if (template.garrisonHolder)
extraSize = template.garrisonHolder.occupiedSlots;
if (template.garrisonable.size > 1 || extraSize)
tooltips.push (
sprintf(translate("%(label)s: %(garrisonSize)s %(extraSize)s"), {
"label": headerFont(translate("Garrison Size")),
"garrisonSize": template.garrisonable.size,
"extraSize": extraSize ?
translateWithContext("nested garrison", "+ ") + extraSize : ""
})
);
}
return tooltips.join("\n");
}
function getTurretsTooltip(template)
{
if (!template.turretHolder)
return "";
return sprintf(translate("%(label)s: %(turretsLimit)s"), {
"label": headerFont(translate("Turret Positions")),
"turretsLimit": Object.keys(template.turretHolder.turretPoints).length
});
}
function getProjectilesTooltip(template)
{
if (!template.garrisonHolder || !template.buildingAI)
return "";
let limit = Math.min(
template.buildingAI.maxArrowCount || Infinity,
template.buildingAI.defaultArrowCount +
Math.round(template.buildingAI.garrisonArrowMultiplier *
template.garrisonHolder.capacity)
);
if (!limit)
return "";
return [
sprintf(translate("%(label)s: %(value)s"), {
"label": headerFont(translate("Projectile Limit")),
"value": limit
}),
sprintf(translate("%(label)s: %(value)s"), {
"label": headerFont(translateWithContext("projectiles", "Default")),
"value": template.buildingAI.defaultArrowCount
}),
sprintf(translate("%(label)s: %(value)s"), {
"label": headerFont(translateWithContext("projectiles", "Per Unit")),
"value": +template.buildingAI.garrisonArrowMultiplier.toFixed(2)
})
].join(commaFont(translate(", ")));
}
function getRepairTimeTooltip(entState)
{
let result = [];
result.push(sprintf(translate("%(label)s %(details)s"), {
"label": headerFont(translate("Number of repairers:")),
"details": entState.repairable.numBuilders
}));
if (entState.repairable.numBuilders)
{
result.push(sprintf(translate("%(label)s %(details)s"), {
"label": headerFont(translate("Remaining repair time:")),
"details": getSecondsString(Math.floor(entState.repairable.buildTime.timeRemaining))
}));
let timeReduction = Math.round(entState.repairable.buildTime.timeRemaining - entState.repairable.buildTime.timeRemainingNew);
result.push(sprintf(translatePlural(
"Add another worker to speed up the repairs by %(second)s second.",
"Add another worker to speed up the repairs by %(second)s seconds.",
timeReduction),
{
"second": timeReduction
}));
}
else
result.push(sprintf(translatePlural(
"Add a worker to finish the repairs in %(second)s second.",
"Add a worker to finish the repairs in %(second)s seconds.",
Math.round(entState.repairable.buildTime.timeRemainingNew)),
{
"second": Math.round(entState.repairable.buildTime.timeRemainingNew)
}));
return result.join("\n");
}
function getBuildTimeTooltip(entState)
{
let result = [];
result.push(sprintf(translate("%(label)s %(details)s"), {
"label": headerFont(translate("Number of builders:")),
"details": entState.foundation.numBuilders
}));
if (entState.foundation.numBuilders)
{
result.push(sprintf(translate("%(label)s %(details)s"), {
"label": headerFont(translate("Remaining build time:")),
"details": getSecondsString(Math.floor(entState.foundation.buildTime.timeRemaining))
}));
let timeReduction = Math.round(entState.foundation.buildTime.timeRemaining - entState.foundation.buildTime.timeRemainingNew);
result.push(sprintf(translatePlural(
"Add another worker to speed up the construction by %(second)s second.",
"Add another worker to speed up the construction by %(second)s seconds.",
timeReduction),
{
"second": timeReduction
}));
}
else
result.push(sprintf(translatePlural(
"Add a worker to finish the construction in %(second)s second.",
"Add a worker to finish the construction in %(second)s seconds.",
Math.round(entState.foundation.buildTime.timeRemainingNew)),
{
"second": Math.round(entState.foundation.buildTime.timeRemainingNew)
}));
return result.join("\n");
}
/**
* Multiplies the costs for a template by a given batch size.
*/
function multiplyEntityCosts(template, trainNum)
{
let totalCosts = {};
for (let r of getCostTypes())
if (template.cost[r])
totalCosts[r] = Math.floor(template.cost[r] * trainNum);
return totalCosts;
}
/**
* Helper function for getEntityCostTooltip.
*/
function getEntityCostComponentsTooltipString(template, entity, buildingsCountToTrainFullBatch = 1, fullBatchSize = 1, remainderBatch = 0)
{
if (!template.cost)
return [];
let totalCosts = multiplyEntityCosts(template, buildingsCountToTrainFullBatch * fullBatchSize + remainderBatch);
if (template.cost.time)
totalCosts.time = Math.ceil(template.cost.time * (entity ? Engine.GuiInterfaceCall("GetBatchTime", {
"entity": entity,
"batchSize": buildingsCountToTrainFullBatch > 0 ? fullBatchSize : remainderBatch
}) : 1));
let costs = [];
for (let type of getCostTypes())
if (totalCosts[type])
costs.push(sprintf(translate("%(component)s %(cost)s"), {
"component": resourceIcon(type),
"cost": totalCosts[type]
}));
return costs;
}
function getGatherTooltip(template)
{
if (!template.resourceGatherRates)
return "";
let rates = {};
for (let resource of g_ResourceData.GetResources())
{
let types = [resource.code];
for (let subtype in resource.subtypes)
{
// We ignore ruins as those are not that common
if (subtype == "ruins")
continue;
let rate = template.resourceGatherRates[resource.code + "." + subtype];
if (rate > 0)
rates[resource.code + "_" + subtype] = rate;
}
}
if (!Object.keys(rates).length)
return "";
return sprintf(translate("%(label)s %(details)s"), {
"label": headerFont(translate("Gather Rates:")),
"details":
Object.keys(rates).map(
type => sprintf(translate("%(resourceIcon)s %(rate)s"), {
"resourceIcon": resourceIcon(type),
"rate": rates[type].toFixed(2)
})
).join(" ")
});
}
/**
* Returns the resources this entity supplies in the specified entity's tooltip
*/
function getResourceSupplyTooltip(template)
{
if (!template.supply)
return "";
let supply = template.supply;
// Translation: Label in tooltip showing the resource type and quantity of a given resource supply.
return sprintf(translate("%(label)s %(component)s %(amount)s"), {
"label": headerFont(translate("Resource Supply:")),
"component": resourceIcon(supply.type[0]),
// Translation: Marks that a resource supply entity has an unending, infinite, supply of its resource.
"amount": Number.isFinite(+supply.amount) ? supply.amount : translate("∞")
});
}
/**
* @param {Object} template - The entity's template.
* @return {string} - The resources this entity rewards to a collecter.
*/
function getTreasureTooltip(template)
{
if (!template.treasure)
return "";
let resources = {};
for (let resource of g_ResourceData.GetResources())
{
let type = resource.code;
if (template.treasure.resources[type])
resources[type] = template.treasure.resources[type];
}
let resourceNames = Object.keys(resources);
if (!resourceNames.length)
return "";
return sprintf(translate("%(label)s %(details)s"), {
"label": headerFont(translate("Reward:")),
"details":
resourceNames.map(
type => sprintf(translate("%(resourceIcon)s %(reward)s"), {
"resourceIcon": resourceIcon(type),
"reward": resources[type]
})
).join(" ")
});
}
function getResourceTrickleTooltip(template)
{
if (!template.resourceTrickle)
return "";
let resCodes = g_ResourceData.GetCodes().filter(res => !!template.resourceTrickle.rates[res]);
if (!resCodes.length)
return "";
return sprintf(translate("%(label)s %(details)s"), {
"label": headerFont(translate("Resource Trickle:")),
"details": sprintf(translate("%(resources)s / %(time)s"), {
"resources":
resCodes.map(
res => sprintf(translate("%(resourceIcon)s %(rate)s"), {
"resourceIcon": resourceIcon(res),
"rate": template.resourceTrickle.rates[res]
})
).join(" "),
"time": getSecondsString(template.resourceTrickle.interval / 1000)
})
});
}
function getUpkeepTooltip(template)
{
if (!template.upkeep)
return "";
let resCodes = g_ResourceData.GetCodes().filter(res => !!template.upkeep.rates[res]);
if (!resCodes.length)
return "";
return sprintf(translate("%(label)s %(details)s"), {
"label": headerFont(translate("Upkeep:")),
"details": sprintf(translate("%(resources)s / %(time)s"), {
"resources":
resCodes.map(
res => sprintf(translate("%(resourceIcon)s %(rate)s"), {
"resourceIcon": resourceIcon(res),
"rate": template.upkeep.rates[res]
})
).join(" "),
"time": getSecondsString(template.upkeep.interval / 1000)
})
});
}
/**
* Returns an array of strings for a set of wall pieces. If the pieces share
* resource type requirements, output will be of the form '10 to 30 Stone',
* otherwise output will be, e.g. '10 Stone, 20 Stone, 30 Stone'.
*/
function getWallPieceTooltip(wallTypes)
{
let out = [];
let resourceCount = {};
for (let resource of getCostTypes())
if (wallTypes[0].cost[resource])
resourceCount[resource] = [wallTypes[0].cost[resource]];
let sameTypes = true;
for (let i = 1; i < wallTypes.length; ++i)
{
for (let resource in wallTypes[i].cost)
// Break out of the same-type mode if this wall requires
// resource types that the first didn't.
if (wallTypes[i].cost[resource] && !resourceCount[resource])
{
sameTypes = false;
break;
}
for (let resource in resourceCount)
if (wallTypes[i].cost[resource])
resourceCount[resource].push(wallTypes[i].cost[resource]);
else
{
sameTypes = false;
break;
}
}
if (sameTypes)
for (let resource in resourceCount)
// Translation: This string is part of the resources cost string on
// the tooltip for wall structures.
out.push(sprintf(translate("%(resourceIcon)s %(minimum)s to %(resourceIcon)s %(maximum)s"), {
"resourceIcon": resourceIcon(resource),
"minimum": Math.min.apply(Math, resourceCount[resource]),
"maximum": Math.max.apply(Math, resourceCount[resource])
}));
else
for (let i = 0; i < wallTypes.length; ++i)
out.push(getEntityCostComponentsTooltipString(wallTypes[i]).join(", "));
return out;
}
/**
* Returns the cost information to display in the specified entity's construction button tooltip.
*/
function getEntityCostTooltip(template, player, entity, buildingsCountToTrainFullBatch, fullBatchSize, remainderBatch)
{
// Entities with a wallset component are proxies for initiating wall placement and as such do not have a cost of
// their own; the individual wall pieces within it do.
if (template.wallSet)
{
let templateLong = GetTemplateData(template.wallSet.templates.long, player);
let templateMedium = GetTemplateData(template.wallSet.templates.medium, player);
let templateShort = GetTemplateData(template.wallSet.templates.short, player);
let templateTower = GetTemplateData(template.wallSet.templates.tower, player);
let wallCosts = getWallPieceTooltip([templateShort, templateMedium, templateLong]);
let towerCosts = getEntityCostComponentsTooltipString(templateTower);
return sprintf(translate("Walls: %(costs)s"), { "costs": wallCosts.join(" ") }) + "\n" +
sprintf(translate("Towers: %(costs)s"), { "costs": towerCosts.join(" ") });
}
if (template.cost)
{
let costs = getEntityCostComponentsTooltipString(template, entity, buildingsCountToTrainFullBatch, fullBatchSize, remainderBatch).join(" ");
if (costs)
// Translation: Label in tooltip showing cost of a unit, structure or technology.
return sprintf(translate("%(label)s %(costs)s"), {
"label": headerFont(translate("Cost:")),
"costs": costs
});
}
return "";
}
function getRequirementsTooltip(enabled, requirements, civ)
{
if (enabled)
return "";
// Simple requirements (one tech) can be translated on the fly.
- if ("Techs" in requirements && !requirements.Techs.includes(" "))
+ if ("Techs" in requirements && !requirements.Techs._string.includes(" "))
return objectionFont(sprintf(translate("Requires %(technology)s"), {
- "technology": getEntityNames(GetTechnologyData(requirements.Techs, civ))
+ "technology": getEntityNames(GetTechnologyData(requirements.Techs._string, civ))
}));
return objectionFont(translate(requirements.Tooltip));
}
/**
* Returns the population bonus information to display in the specified entity's construction button tooltip.
*/
function getPopulationBonusTooltip(template)
{
if (!template.population || !template.population.bonus)
return "";
return sprintf(translate("%(label)s %(bonus)s"), {
"label": headerFont(translate("Population Bonus:")),
"bonus": template.population.bonus
});
}
/**
* Returns a message with the amount of each resource needed to create an entity.
*/
function getNeededResourcesTooltip(resources)
{
if (!resources)
return "";
let formatted = [];
for (let resource in resources)
formatted.push(sprintf(translate("%(component)s %(cost)s"), {
"component": '[font="sans-12"]' + resourceIcon(resource) + '[/font]',
"cost": Math.ceil(resources[resource])
}));
return objectionFont(translate("Insufficient resources:")) +
" " + formatted.join(" ");
}
function getSpeedTooltip(template)
{
if (!template.speed)
return "";
const walk = template.speed.walk.toFixed(1);
const run = template.speed.run.toFixed(1);
if (walk == 0 && run == 0)
return "";
const acceleration = template.speed.acceleration.toFixed(1);
return sprintf(translate("%(label)s %(speeds)s"), {
"label": headerFont(translate("Speed:")),
"speeds":
sprintf(translate("%(speed)s %(movementType)s"), {
"speed": walk,
"movementType": unitFont(translate("Walk"))
}) +
commaFont(translate(", ")) +
sprintf(translate("%(speed)s %(movementType)s"), {
"speed": run,
"movementType": unitFont(translate("Run"))
}) +
commaFont(translate(", ")) +
sprintf(translate("%(speed)s %(movementType)s"), {
"speed": acceleration,
"movementType": unitFont(translate("Acceleration"))
})
});
}
function getHealerTooltip(template)
{
if (!template.heal)
return "";
let health = +(template.heal.health.toFixed(1));
let range = +(template.heal.range.toFixed(0));
let interval = +((template.heal.interval / 1000).toFixed(1));
return [
sprintf(translatePlural("%(label)s %(val)s %(unit)s", "%(label)s %(val)s %(unit)s", health), {
"label": headerFont(translate("Heal:")),
"val": health,
"unit": unitFont(translatePlural("Health", "Health", health))
}),
sprintf(translatePlural("%(label)s %(val)s %(unit)s", "%(label)s %(val)s %(unit)s", range), {
"label": headerFont(translate("Range:")),
"val": range,
"unit": unitFont(translatePlural("meter", "meters", range))
}),
sprintf(translatePlural("%(label)s %(val)s %(unit)s", "%(label)s %(val)s %(unit)s", interval), {
"label": headerFont(translate("Interval:")),
"val": interval,
"unit": unitFont(translatePlural("second", "seconds", interval))
})
].join(translate(", "));
}
function getAurasTooltip(template)
{
let auras = template.auras || template.wallSet && GetTemplateData(template.wallSet.templates.long).auras;
if (!auras)
return "";
let tooltips = [];
for (let auraID in auras)
{
let tooltip = sprintf(translate("%(auralabel)s %(aurainfo)s"), {
"auralabel": headerFont(sprintf(translate("%(auraname)s:"), {
"auraname": getEntityNames(auras[auraID])
})),
"aurainfo": bodyFont(translate(auras[auraID].description))
});
let radius = +auras[auraID].radius;
if (radius)
tooltip += " " + sprintf(translatePlural("%(label)s %(val)s %(unit)s", "%(label)s %(val)s %(unit)s", radius), {
"label": translateWithContext("aura", "Range:"),
"val": radius,
"unit": unitFont(translatePlural("meter", "meters", radius))
});
tooltips.push(tooltip);
}
return tooltips.join("\n");
}
function getEntityNames(template)
{
if (!template.name.specific)
return template.name.generic;
if (template.name.specific == template.name.generic)
return template.name.specific;
let primaryName = g_SpecificNamesPrimary ? template.name.specific : template.name.generic;
let secondaryName;
if (g_ShowSecondaryNames)
secondaryName = g_SpecificNamesPrimary ? template.name.generic : template.name.specific;
if (secondaryName)
return sprintf(translate("%(primaryName)s (%(secondaryName)s)"), {
"primaryName": primaryName,
"secondaryName": secondaryName
});
return sprintf(translate("%(primaryName)s"), {
"primaryName": primaryName
});
}
function getEntityNamesFormatted(template)
{
if (!template.name.specific)
return setStringTags(template.name.generic, g_TooltipTextFormats.namePrimaryBig);
let primaryName = g_SpecificNamesPrimary ? template.name.specific : template.name.generic;
let secondaryName;
if (g_ShowSecondaryNames)
secondaryName = g_SpecificNamesPrimary ? template.name.generic : template.name.specific;
if (!secondaryName || primaryName == secondaryName)
return sprintf(translate("%(primaryName)s"), {
"primaryName":
setStringTags(primaryName[0], g_TooltipTextFormats.namePrimaryBig) +
setStringTags(primaryName.slice(1).toUpperCase(), g_TooltipTextFormats.namePrimarySmall)
});
// Translation: Example: "Epibátēs Athēnaîos [font="sans-bold-16"](Athenian Marine)[/font]"
return sprintf(translate("%(primaryName)s (%(secondaryName)s)"), {
"primaryName":
setStringTags(primaryName[0], g_TooltipTextFormats.namePrimaryBig) +
setStringTags(primaryName.slice(1).toUpperCase(), g_TooltipTextFormats.namePrimarySmall),
"secondaryName": setStringTags(secondaryName, g_TooltipTextFormats.nameSecondary)
});
}
function getEntityPrimaryNameFormatted(template)
{
let primaryName = g_SpecificNamesPrimary ? template.name.specific : template.name.generic;
if (!primaryName)
return setStringTags(g_SpecificNamesPrimary ? template.name.generic : template.name.specific, g_TooltipTextFormats.namePrimaryBig);
return setStringTags(primaryName[0], g_TooltipTextFormats.namePrimaryBig) +
setStringTags(primaryName.slice(1).toUpperCase(), g_TooltipTextFormats.namePrimarySmall);
}
function getVisibleEntityClassesFormatted(template)
{
if (!template.visibleIdentityClasses || !template.visibleIdentityClasses.length)
return "";
return headerFont(translate("Classes:")) + ' ' +
bodyFont(template.visibleIdentityClasses.map(c => translate(c)).join(translate(", ")));
}
function getLootTooltip(template)
{
if (!template.loot && !template.resourceCarrying)
return "";
let resourcesCarried = [];
if (template.resourceCarrying)
resourcesCarried = calculateCarriedResources(
template.resourceCarrying,
template.trader && template.trader.goods
);
let lootLabels = [];
for (let type of g_ResourceData.GetCodes().concat(["xp"]))
{
let loot =
(template.loot && template.loot[type] || 0) +
(resourcesCarried[type] || 0);
if (!loot)
continue;
// Translation: %(component) will be the icon for the loot type and %(loot) will be the value.
lootLabels.push(sprintf(translate("%(component)s %(loot)s"), {
"component": resourceIcon(type),
"loot": loot
}));
}
if (!lootLabels.length)
return "";
return sprintf(translate("%(label)s %(details)s"), {
"label": headerFont(translate("Loot:")),
"details": lootLabels.join(" ")
});
}
function getResourceDropsiteTooltip(template)
{
if (!template || !template.resourceDropsite || !template.resourceDropsite.types)
return "";
return sprintf(translate("%(label)s %(icons)s"), {
"label": headerFont(translate("Dropsite for:")),
"icons": template.resourceDropsite.types.map(type => resourceIcon(type)).join(" ")
});
}
function showTemplateViewerOnRightClickTooltip()
{
// Translation: Appears in a tooltip to indicate that right-clicking the corresponding GUI element will open the Template Details GUI page.
return translate("Right-click to view more information.");
}
function showTemplateViewerOnClickTooltip()
{
// Translation: Appears in a tooltip to indicate that clicking the corresponding GUI element will open the Template Details GUI page.
return translate("Click to view more information.");
}
/**
* @param {number} number - A number to shorten using SI prefix.
*/
function abbreviateLargeNumbers(number)
{
if (number >= 1e6)
return Math.floor(number / 1e6) + translateWithContext("One letter abbreviation for million", 'M');
if (number >= 1e5)
return Math.floor(number / 1e3) + translateWithContext("One letter abbreviation for thousand", 'k');
if (number >= 1e4)
return (number / 1e3).toFixed(1).replace(/\.0$/, '') + translateWithContext("One letter abbreviation for thousand", 'k');
return number;
}
Index: ps/trunk/binaries/data/mods/public/gui/reference/common/TemplateParser.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/reference/common/TemplateParser.js (revision 27504)
+++ ps/trunk/binaries/data/mods/public/gui/reference/common/TemplateParser.js (revision 27505)
@@ -1,407 +1,419 @@
/**
* This class parses and stores parsed template data.
*/
class TemplateParser
{
constructor(TemplateLoader)
{
this.TemplateLoader = TemplateLoader;
/**
* Parsed Data Stores
*/
this.auras = {};
this.entities = {};
this.techs = {};
this.phases = {};
this.modifiers = {};
this.players = {};
this.phaseList = [];
}
getAura(auraName)
{
if (auraName in this.auras)
return this.auras[auraName];
if (!AuraTemplateExists(auraName))
return null;
let template = this.TemplateLoader.loadAuraTemplate(auraName);
let parsed = GetAuraDataHelper(template);
if (template.civ)
parsed.civ = template.civ;
let affectedPlayers = template.affectedPlayers || this.AuraAffectedPlayerDefault;
parsed.affectsTeam = this.AuraTeamIndicators.some(indicator => affectedPlayers.includes(indicator));
parsed.affectsSelf = this.AuraSelfIndicators.some(indicator => affectedPlayers.includes(indicator));
this.auras[auraName] = parsed;
return this.auras[auraName];
}
/**
* Load and parse a structure, unit, resource, etc from its entity template file.
*
* @param {string} templateName
* @param {string} civCode
* @return {(object|null)} Sanitized object about the requested template or null if entity template doesn't exist.
*/
getEntity(templateName, civCode)
{
if (!(civCode in this.entities))
this.entities[civCode] = {};
else if (templateName in this.entities[civCode])
return this.entities[civCode][templateName];
if (!Engine.TemplateExists(templateName))
return null;
let template = this.TemplateLoader.loadEntityTemplate(templateName, civCode);
const parsed = GetTemplateDataHelper(template, null, this.TemplateLoader.auraData, g_ResourceData, this.modifiers[civCode] || {});
parsed.name.internal = templateName;
parsed.history = template.Identity.History;
parsed.production = this.TemplateLoader.deriveProduction(template, civCode);
if (template.Builder)
parsed.builder = this.TemplateLoader.deriveBuildQueue(template, civCode);
// Set the minimum phase that this entity is available.
// For gaia objects, this is meaningless.
// Complex requirements are too difficult to process for now, so assume the first phase.
if (!parsed.requirements?.Techs)
parsed.phase = this.phaseList[0];
else
{
let highestPhaseIndex = 0;
- for (const tech of parsed.requirements.Techs.split(" "))
+ for (const tech of parsed.requirements.Techs._string.split(" "))
{
if (tech[0] === "!")
continue;
const phaseIndex = this.phaseList.indexOf(
this.TemplateLoader.isPhaseTech(tech) ? this.getActualPhase(tech) :
this.getPhaseOfTechnology(tech, civCode));
if (phaseIndex > highestPhaseIndex)
highestPhaseIndex = phaseIndex;
}
parsed.phase = this.phaseList[highestPhaseIndex];
}
if (template.Identity.Rank)
parsed.promotion = {
"current_rank": template.Identity.Rank,
"entity": template.Promotion && template.Promotion.Entity
};
if (template.ResourceSupply)
parsed.supply = {
"type": template.ResourceSupply.Type.split("."),
"amount": template.ResourceSupply.Max,
};
if (parsed.upgrades)
parsed.upgrades = this.getActualUpgradeData(parsed.upgrades, civCode);
if (parsed.wallSet)
{
parsed.wallset = {};
if (!parsed.upgrades)
parsed.upgrades = [];
// Note: An assumption is made here that wall segments all have the same resistance and auras
let struct = this.getEntity(parsed.wallSet.templates.long, civCode);
parsed.resistance = struct.resistance;
parsed.auras = struct.auras;
// For technology cost multiplier, we need to use the tower
struct = this.getEntity(parsed.wallSet.templates.tower, civCode);
parsed.techCostMultiplier = struct.techCostMultiplier;
let health;
for (let wSegm in parsed.wallSet.templates)
{
if (wSegm == "fort" || wSegm == "curves")
continue;
let wPart = this.getEntity(parsed.wallSet.templates[wSegm], civCode);
parsed.wallset[wSegm] = wPart;
for (let research of wPart.production.techs)
parsed.production.techs.push(research);
if (wPart.upgrades)
Array.prototype.push.apply(parsed.upgrades, wPart.upgrades);
if (["gate", "tower"].indexOf(wSegm) != -1)
continue;
if (!health)
{
health = { "min": wPart.health, "max": wPart.health };
continue;
}
health.min = Math.min(health.min, wPart.health);
health.max = Math.max(health.max, wPart.health);
}
if (parsed.wallSet.templates.curves)
for (let curve of parsed.wallSet.templates.curves)
{
let wPart = this.getEntity(curve, civCode);
health.min = Math.min(health.min, wPart.health);
health.max = Math.max(health.max, wPart.health);
}
if (health.min == health.max)
parsed.health = health.min;
else
parsed.health = sprintf(translate("%(health_min)s to %(health_max)s"), {
"health_min": health.min,
"health_max": health.max
});
}
this.entities[civCode][templateName] = parsed;
return parsed;
}
/**
* Load and parse technology from json template.
*
* @param {string} technologyName
* @param {string} civCode
* @return {Object} Sanitized data about the requested technology.
*/
getTechnology(technologyName, civCode)
{
if (!TechnologyTemplateExists(technologyName))
return null;
if (this.TemplateLoader.isPhaseTech(technologyName) && technologyName in this.phases)
return this.phases[technologyName];
if (!(civCode in this.techs))
this.techs[civCode] = {};
else if (technologyName in this.techs[civCode])
return this.techs[civCode][technologyName];
let template = this.TemplateLoader.loadTechnologyTemplate(technologyName);
const tech = GetTechnologyDataHelper(template, civCode, g_ResourceData, this.modifiers[civCode] || {});
tech.name.internal = technologyName;
if (template.pair !== undefined)
{
tech.pair = template.pair;
tech.reqs = this.mergeRequirements(tech.reqs, this.TemplateLoader.loadTechnologyPairTemplate(template.pair).reqs);
}
if (this.TemplateLoader.isPhaseTech(technologyName))
{
tech.actualPhase = technologyName;
if (tech.replaces !== undefined)
tech.actualPhase = tech.replaces[0];
this.phases[technologyName] = tech;
}
else
this.techs[civCode][technologyName] = tech;
return tech;
}
/**
* @param {string} phaseCode
* @param {string} civCode
* @return {Object} Sanitized object containing phase data
*/
getPhase(phaseCode, civCode)
{
return this.getTechnology(phaseCode, civCode);
}
/**
* Load and parse the relevant player_{civ}.xml template.
*/
getPlayer(civCode)
{
if (civCode in this.players)
return this.players[civCode];
let template = this.TemplateLoader.loadPlayerTemplate(civCode);
let parsed = {
"civbonuses": [],
"teambonuses": [],
};
if (template.Auras)
for (let auraTemplateName of template.Auras._string.split(/\s+/))
if (AuraTemplateExists(auraTemplateName))
if (this.getAura(auraTemplateName).affectsTeam)
parsed.teambonuses.push(auraTemplateName);
else
parsed.civbonuses.push(auraTemplateName);
this.players[civCode] = parsed;
return parsed;
}
/**
* Provided with an array containing basic information about possible
* upgrades, such as that generated by globalscript's GetTemplateDataHelper,
* this function loads the actual template data of the upgrades, overwrites
* certain values within, then passes an array containing the template data
* back to caller.
*/
getActualUpgradeData(upgradesInfo, civCode)
{
let newUpgrades = [];
for (let upgrade of upgradesInfo)
{
upgrade.entity = upgrade.entity.replace(/\{(civ|native)\}/g, civCode);
const data = GetTemplateDataHelper(this.TemplateLoader.loadEntityTemplate(upgrade.entity, civCode), null, this.TemplateLoader.auraData, g_ResourceData, this.modifiers[civCode] || {});
data.name.internal = upgrade.entity;
data.cost = upgrade.cost;
data.icon = upgrade.icon || data.icon;
data.tooltip = upgrade.tooltip || data.tooltip;
data.requirements = upgrade.requirements || data.requirements;
- if (!data.requirements)
+ if (!data.requirements?.Techs)
data.phase = this.phaseList[0];
- else if (this.TemplateLoader.isPhaseTech(data.requirements.Techs))
- data.phase = this.getActualPhase(data.requirements.Techs);
else
- data.phase = this.getPhaseOfTechnology(data.requirements.Techs, civCode);
+ {
+ let highestPhaseIndex = 0;
+ for (const tech of data.requirements.Techs._string.split(" "))
+ {
+ if (tech[0] === "!")
+ continue;
+
+ const phaseIndex = this.phaseList.indexOf(
+ this.TemplateLoader.isPhaseTech(tech) ? this.getActualPhase(tech) :
+ this.getPhaseOfTechnology(tech, civCode));
+ if (phaseIndex > highestPhaseIndex)
+ highestPhaseIndex = phaseIndex;
+ }
+ data.phase = this.phaseList[highestPhaseIndex];
+ }
newUpgrades.push(data);
}
return newUpgrades;
}
/**
* Determines and returns the phase in which a given technology can be
* first researched. Works recursively through the given tech's
* pre-requisite and superseded techs if necessary.
*
* @param {string} techName - The Technology's name
* @param {string} civCode
* @return The name of the phase the technology belongs to, or false if
* the current civ can't research this tech
*/
getPhaseOfTechnology(techName, civCode)
{
let phaseIdx = -1;
if (basename(techName).startsWith("phase"))
{
if (!this.phases[techName].reqs)
return false;
phaseIdx = this.phaseList.indexOf(this.getActualPhase(techName));
if (phaseIdx > 0)
return this.phaseList[phaseIdx - 1];
}
let techReqs = this.getTechnology(techName, civCode).reqs;
if (!techReqs)
return false;
for (let option of techReqs)
if (option.techs)
for (let tech of option.techs)
{
if (basename(tech).startsWith("phase"))
return tech;
if (basename(tech).startsWith("pair"))
continue;
phaseIdx = Math.max(phaseIdx, this.phaseList.indexOf(this.getPhaseOfTechnology(tech, civCode)));
}
return this.phaseList[phaseIdx] || false;
}
/**
* Returns the actual phase a certain phase tech represents or stands in for.
*
* For example, passing `phase_city_athen` would result in `phase_city`.
*
* @param {string} phaseName
* @return {string}
*/
getActualPhase(phaseName)
{
if (this.phases[phaseName])
return this.phases[phaseName].actualPhase;
warn("Unrecognized phase (" + phaseName + ")");
return this.phaseList[0];
}
getModifiers(civCode)
{
return this.modifiers[civCode];
}
deriveModifications(civCode)
{
const player = this.getPlayer(civCode);
const auraList = clone(player.civbonuses);
for (const bonusname of player.teambonuses)
if (this.getAura(bonusname).affectsSelf)
auraList.push(bonusname);
this.modifiers[civCode] = this.TemplateLoader.deriveModifications(civCode, auraList);
}
derivePhaseList(technologyList, civCode)
{
// Load all of a civ's specific phase technologies
for (let techcode of technologyList)
if (this.TemplateLoader.isPhaseTech(techcode))
this.getTechnology(techcode, civCode);
this.phaseList = UnravelPhases(this.phases);
// Make sure all required generic phases are loaded and parsed
for (let phasecode of this.phaseList)
this.getTechnology(phasecode, civCode);
}
mergeRequirements(reqsA, reqsB)
{
if (!reqsA || !reqsB)
return false;
let finalReqs = clone(reqsA);
for (let option of reqsB)
for (let type in option)
for (let opt in finalReqs)
{
if (!finalReqs[opt][type])
finalReqs[opt][type] = [];
Array.prototype.push.apply(finalReqs[opt][type], option[type]);
}
return finalReqs;
}
}
// Default affected player token list to use if an aura doesn't explicitly give one.
// Keep in sync with simulation/components/Auras.js
TemplateParser.prototype.AuraAffectedPlayerDefault =
["Player"];
// List of tokens that, if found in an aura's "affectedPlayers" attribute, indicate
// that the aura applies to team members.
TemplateParser.prototype.AuraTeamIndicators =
["MutualAlly", "ExclusiveMutualAlly"];
// List of tokens that, if found in an aura's "affectedPlayers" attribute, indicate
// that the aura applies to the aura's owning civ.
TemplateParser.prototype.AuraSelfIndicators =
["Player", "Ally", "MutualAlly"];
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_embassy.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_embassy.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_embassy.xml (revision 27505)
@@ -1,58 +1,58 @@
Embassy
150
12.0
6
Support Infantry Cavalry
2000
decay|rubble/rubble_stone_3x3
Embassy
template_structure_military_embassy
Town Embassy
- phase_town
+ phase_town
30
interface/complete/building/complete_gymnasium.xml
25
0.8
24
structures/fndn_4x4.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_range.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_range.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_range.xml (revision 27505)
@@ -1,63 +1,63 @@
120
200
12.0
10
Infantry
2000
decay|rubble/rubble_stone_5x5
Practice Range
template_structure_military_range
Train Ranged Infantry and research technologies.
Village Range
structures/range.png
- phase_village
+ phase_village
40
interface/complete/building/complete_range.xml
0.8
units/{civ}/infantry_javelineer_b
units/{civ}/infantry_slinger_b
units/{civ}/infantry_archer_b
units/{civ}/infantry_crossbowman_b
units/{civ}/champion_infantry_javelineer
units/{civ}/champion_infantry_slinger
units/{civ}/champion_infantry_archer
units/{civ}/champion_infantry_crossbowman
32
structures/fndn_7x7.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_special.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_special.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_special.xml (revision 27505)
@@ -1,40 +1,40 @@
8.0
5
0.1
Unit
Support Infantry Cavalry
0
2
decay|rubble/rubble_stone_6x6
Special Structure
City
- phase_city
+ phase_city
20
30
3
structures/fndn_5x5.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_defensive_tower_sentry.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_defensive_tower_sentry.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_defensive_tower_sentry.xml (revision 27505)
@@ -1,73 +1,73 @@
0
9
0
4
40
100
9.0
3
400
Sentry Tower
template_structure_defensive_tower_sentry
Garrison Infantry for additional arrows. Needs the “Murder Holes” technology to protect its foot.
SentryTower
structures/sentry_tower.png
- phase_village
+ phase_village
20
tower_watch
false
16
30000
structures/{civ}/defense_tower
Reinforce with stone and upgrade to a defense tower.
50
100
upgrading
- phase_town
+ phase_town
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_defensive_wall.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_defensive_wall.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_defensive_wall.xml (revision 27505)
@@ -1,38 +1,38 @@
land-shore
Wall
8.0
Wall
template_structure_defensive_wall
Wall off your town for a stout defense.
Wall
structures/wall.png
- phase_town
+ phase_town
4.5
interface/complete/building/complete_wall.xml
false
20
65535
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_economic_market.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_economic_market.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_economic_market.xml (revision 27505)
@@ -1,78 +1,78 @@
Trader+!Ship
-1
-1
100
150
300
8.0
1500
decay|rubble/rubble_stone_5x5
Market
template_structure_economic_market
Barter resources. Establish trade routes. Train Traders and research trade and barter technologies.
Barter
Trade Town Market
structures/market.png
- phase_town
+ phase_town
60
land
0.2
trader_health
trade_gain_01
trade_gain_02
trade_commercial_treaty
interface/complete/building/complete_market.xml
interface/alarm/alarm_alert_0.xml
interface/alarm/alarm_alert_1.xml
false
40
30000
0.7
units/{civ}/support_trader
32
structures/fndn_8x8.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_arsenal.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_arsenal.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_arsenal.xml (revision 27505)
@@ -1,78 +1,78 @@
structures/arsenal_repair
180
300
12.0
5
Siege
2000
decay|rubble/rubble_stone_6x6
Arsenal
template_structure_military_arsenal
Train Champion Infantry Crossbowmen, construct Siege Engines, and research Siege Engine technologies.
City Arsenal
structures/siege_workshop.png
- phase_city
+ phase_city
60
siege_attack
siege_cost_time
siege_health
siege_pack_unpack
siege_bolt_accuracy
interface/complete/building/complete_barracks.xml
38
0.7
units/{civ}/champion_infantry_crossbowman
units/{civ}/siege_scorpio_packed
units/{civ}/siege_polybolos_packed
units/{civ}/siege_oxybeles_packed
units/{civ}/siege_lithobolos_packed
units/{civ}/siege_ballista_packed
units/{civ}/siege_ram
units/{civ}/siege_tower
40
structures/fndn_8x8.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_elephant_stable.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_elephant_stable.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_elephant_stable.xml (revision 27505)
@@ -1,66 +1,66 @@
structures/xp_trickle
180
200
200
8.0
5
Elephant
3000
decay|rubble/rubble_stone_6x6
Elephant Stable
template_structure_military_elephant_stable
Train Elephants and research Elephant technologies.
City ElephantStable
structures/stable_elephant.png
- phase_city
+ phase_city
40
40
interface/complete/building/complete_elephant_stable.xml
38
0.7
units/{civ}/support_elephant
units/{civ}/elephant_archer_b
units/{civ}/champion_elephant
40
structures/fndn_9x8.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_fortress.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_fortress.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_fortress.xml (revision 27505)
@@ -1,114 +1,114 @@
Bow
10
60
1200
2000
100
1.5
50
false
Human
outline_border.png
outline_border_mask.png
0.175
Fortress
Fortress
80
4
1
Soldier
8
10.0
450
300
600
8.0
20
0.075
Support Infantry Cavalry Siege
6
5200
decay|rubble/rubble_stone_6x6
Fortress
template_structure_military_fortress
Garrison Soldiers for additional arrows.
GarrisonFortress
Defensive Fortress
structures/fortress.png
- phase_city
+ phase_city
60
120
attack_soldiers_will
art_of_war
poison_arrows
poison_blades
interface/complete/building/complete_fortress.xml
attack/weapon/bow_attack.xml
attack/impact/arrow_impact.xml
2
80
0.8
90
structures/fndn_8x8.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_resource_corral.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_resource_corral.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_resource_corral.xml (revision 27505)
@@ -1,86 +1,86 @@
50
100
5.0
8
0.5
Animal
Animal
1
4
500
decay|rubble/rubble_stone_3x3
Corral
template_structure_resource_corral
Raise Domestic Animals for food. Garrison animals to gain a trickle of food.
Economic Village Corral
structures/corral.png
- phase_village
+ phase_village
0
5000
20
gather_animals_stockbreeding
20
interface/complete/building/complete_corral.xml
false
20
30000
0.7
gaia/fauna_goat_trainable
gaia/fauna_sheep_trainable
gaia/fauna_pig_trainable
gaia/fauna_cattle_cow_trainable
20
structures/fndn_3x3.xml
Index: ps/trunk/binaries/data/mods/public/simulation/helpers/Requirements.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/helpers/Requirements.js (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/helpers/Requirements.js (revision 27505)
@@ -1,164 +1,167 @@
function RequirementsHelper() {}
RequirementsHelper.prototype.DEFAULT_RECURSION_DEPTH = 1;
RequirementsHelper.prototype.EntityRequirementsSchema =
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"";
RequirementsHelper.prototype.TechnologyRequirementsSchema =
"" +
+ "" +
+ "tokens" +
+ "" +
"" +
"";
/**
* @param {number} recursionDepth - How deep we recurse.
* @return {string} - A RelaxRNG schema for requirements.
*/
RequirementsHelper.prototype.RequirementsSchema = function(recursionDepth)
{
return "" +
"" +
this.ChoicesSchema(--recursionDepth) +
"";
};
/**
* @param {number} recursionDepth - How deep we recurse.
* @return {string} - A RelaxRNG schema for chosing requirements.
*/
RequirementsHelper.prototype.ChoicesSchema = function(recursionDepth)
{
const allAnySchema = recursionDepth > 0 ? "" +
"" +
this.RequirementsSchema(recursionDepth) +
"" +
"" +
this.RequirementsSchema(recursionDepth) +
"" : "";
return "" +
"" +
allAnySchema +
this.EntityRequirementsSchema +
this.TechnologyRequirementsSchema +
"";
};
/**
* @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 "" +
"" +
"" +
this.ChoicesSchema(recursionDepth) +
"" +
"" +
"" +
"" +
"" +
"" +
"";
};
/**
* @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 cmpTechManager && 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 (requirementType === "Techs" && requirement._string)
+ for (const tech of requirement._string.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 (requirementType === "Techs" && requirement._string)
+ for (const tech of requirement._string.split(" "))
if (tech[0] === "!" ? !cmpTechManager.IsTechnologyResearched(tech.substring(1)) :
cmpTechManager.IsTechnologyResearched(tech))
return true;
}
return false;
};
Engine.RegisterGlobal("RequirementsHelper", new RequirementsHelper());
Index: ps/trunk/binaries/data/mods/public/simulation/helpers/tests/test_Requirements.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/helpers/tests/test_Requirements.js (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/helpers/tests/test_Requirements.js (revision 27505)
@@ -1,718 +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"
+ "Techs": { "_string": "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"
+ "Techs": { "_string": "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"
+ "Techs": { "_string": "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"
+ "Techs": { "_string": "phase_city" }
}
};
notMet();
template = {
"All": {
- "Techs": "phase_town phase_city"
+ "Techs": { "_string": "phase_town phase_city" }
}
};
notMet();
AddMock(playerEnt, IID_TechnologyManager, {
"IsTechnologyResearched": (tech) => tech === "phase_town" || tech === "phase_city"
});
met();
template = {
"All": {
- "Techs": "!phase_city"
+ "Techs": { "_string": "!phase_city" }
}
};
notMet();
template = {
"All": {
- "Techs": "!phase_town phase_city"
+ "Techs": { "_string": "!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"
+ "Techs": { "_string": "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"
+ "Techs": { "_string": "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"
+ "Techs": { "_string": "phase_town phase_city" }
}
};
AddMock(playerEnt, IID_TechnologyManager, {
"IsTechnologyResearched": (tech) => tech === "phase_city"
});
met();
template = {
"Any": {
- "Techs": "!phase_town"
+ "Techs": { "_string": "!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"
+ "Techs": { "_string": "!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"
+ "Techs": { "_string": "!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"
+ "Techs": { "_string": "!phase_town" }
},
"Any": {
"Entities": {
"class_1": {
"Count": 3,
"Variants": 2
}
},
- "Techs": "phase_city"
+ "Techs": { "_string": "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"
+ "Techs": { "_string": "!phase_town" }
},
"Any": {
"Entities": {
"class_1": {
"Count": 3,
"Variants": 2
}
},
- "Techs": "phase_city"
+ "Techs": { "_string": "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",
+ "Techs": { "_string": "cartography phase_imperial" }
},
"Entities": {
"class_1": {
"Count": 3,
"Variants": 2
}
},
- "Techs": "phase_city"
+ "Techs": { "_string": "phase_city" }
},
- "Techs": "!phase_town"
+ "Techs": { "_string": "!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();
Index: ps/trunk/binaries/data/mods/public/simulation/templates/gaia/fauna_pig_trainable.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/gaia/fauna_pig_trainable.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/gaia/fauna_pig_trainable.xml (revision 27505)
@@ -1,12 +1,12 @@
- phase_town
+ phase_town
false
Index: ps/trunk/binaries/data/mods/public/simulation/templates/special/spy.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/special/spy.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/special/spy.xml (revision 27505)
@@ -1,28 +1,28 @@
0
0
0
0
0
500
gaia
Spy
Spy
technologies/spy_trader.png
true
- unlock_spies
+ unlock_spies
false
15
0.25
Index: ps/trunk/binaries/data/mods/public/simulation/templates/structures/brit/crannog.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/structures/brit/crannog.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/structures/brit/crannog.xml (revision 27505)
@@ -1,54 +1,54 @@
own ally neutral
shore
8.0
brit
Island Settlement
Cranogion
Build upon a shoreline in own, neutral, or allied territory. Acquire large tracts of territory. Territory root. Train Citizens, construct Ships, and research technologies. Garrison Soldiers for additional arrows.
CivSpecific
Naval
structures/crannog.png
- phase_town
+ phase_town
true
0.0
ship
-phase_town_{civ}
-hellenistic_metropolis
units/{civ}/infantry_spearman_b
units/{civ}/infantry_slinger_b
units/{civ}/cavalry_javelineer_b
units/{civ}/ship_fishing
units/{civ}/ship_merchant
units/{civ}/ship_bireme
units/{civ}/ship_trireme
structures/britons/crannog.xml
structures/fndn_8x8.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/structures/cart/wallset_short.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/structures/cart/wallset_short.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/structures/cart/wallset_short.xml (revision 27505)
@@ -1,20 +1,20 @@
cart
Low Wall
structures/palisade_wall.png
- phase_village
+ phase_village
structures/cart/s_wall_tower
structures/cart/s_wall_gate
structures/cart/s_wall_long
structures/cart/s_wall_medium
structures/cart/s_wall_short
Index: ps/trunk/binaries/data/mods/public/simulation/templates/structures/gaul/assembly.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/structures/gaul/assembly.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/structures/gaul/assembly.xml (revision 27505)
@@ -1,80 +1,80 @@
200
400
10.0
20
0.1
Unit
Support Infantry Cavalry
0
2
2000
decay|rubble/rubble_stone_6x6
gaul
Assembly of Princes
Remogantion
Train Champion Trumpeters and Heroes.
ConquestCritical CivSpecific
City Council
structures/tholos.png
- phase_city
+ phase_city
80
20
30
3
interface/complete/building/complete_iber_monument.xml
false
40
40000
0.7
units/{civ}/champion_infantry_trumpeter
units/{civ}/hero_brennus
units/{civ}/hero_viridomarus
units/{civ}/hero_vercingetorix
40
structures/gauls/theater.xml
structures/fndn_6x6.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/structures/gaul/tavern.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/structures/gaul/tavern.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/structures/gaul/tavern.xml (revision 27505)
@@ -1,51 +1,51 @@
200
100
100
5.0
1500
decay|rubble/rubble_stone_4x4
gaul
Tavern
Taberna
-Village Town
structures/embassy_celtic.png
- phase_town
+ phase_town
20
20
10
interface/complete/building/complete_broch.xml
30
structures/celts/tavern.xml
structures/fndn_6x6.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/structures/han/civil_centre.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/structures/han/civil_centre.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/structures/han/civil_centre.xml (revision 27505)
@@ -1,49 +1,49 @@
8.0
Minister
han
Guān Shǔ
-unlock_spies
-spy_counter
units/{civ}/infantry_spearman_b
units/{civ}/infantry_crossbowman_b
units/{civ}/cavalry_swordsman_b
structures/{civ}/civil_centre_court
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.
300
300
upgrading
- phase_city
+ phase_city
structures/fndn_8x8.xml
structures/han/civil_centre.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/structures/han/civil_centre_court.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/structures/han/civil_centre_court.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/structures/han/civil_centre_court.xml (revision 27505)
@@ -1,46 +1,46 @@
ImperialCourt
1.5
1.5
1.5
han
Imperial Court
Cháotíng
Defensive ImperialCourt City
CivCentre CivSpecific
structures/military_settlement.png
- phase_city
+ phase_city
30
-phase_town_{civ}
0.5
units/{civ}/hero_han_xin_horse
units/{civ}/hero_liu_bang_horse
units/{civ}/hero_wei_qing_chariot
structures/han/imperial_court.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/structures/han/defense_tower.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/structures/han/defense_tower.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/structures/han/defense_tower.xml (revision 27505)
@@ -1,37 +1,37 @@
15.0
Minister
han
Fángyù Tǎ
22.0
structures/{civ}/defense_tower_great
This tower has greater range, greater attack, greater health, and is twice as difficult to capture.
200
upgrading
- phase_city
+ phase_city
structures/han/tower_large.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/structures/han/laozigate.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/structures/han/laozigate.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/structures/han/laozigate.xml (revision 27505)
@@ -1,63 +1,63 @@
120
100
200
12.0
1200
decay|rubble/rubble_stone_4x2
han
LaoziGate
Lǎozǐ Mén
CivSpecific
LaoziGate Town
structures/paifang.png
- phase_town
+ phase_town
20
20
false
false
20
30
3
interface/complete/building/complete_iber_monument.xml
structures/han/shrine.xml
structures/fndn_6x2.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/structures/han/ministry.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/structures/han/ministry.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/structures/han/ministry.xml (revision 27505)
@@ -1,93 +1,93 @@
ImperialMinistry
3000
5.0
200
0
200
200
8.0
9
0
Unit
Support Minister Infantry
1
1
3000
decay|rubble/rubble_stone_6x6
han
Imperial Ministry
Gōngdiàn
CivSpecific
ImperialMinistry Town
Train the Nine Ministers. Territory root. Research a powerful suite of Administrative technologies.
structures/imperial_ministry.png
- phase_town
+ phase_town
200
40
40
20
pair_unlock_civil_engineering_han
pair_unlock_civil_service_han
unlock_spies
spy_counter
0.0
0.1
0.1
0.1
2000
true
60
30000
0.8
units/{civ}/support_minister
80
structures/fndn_8x8.xml
structures/han/imperial_ministry.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/structures/iber/monument.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/structures/iber/monument.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/structures/iber/monument.xml (revision 27505)
@@ -1,71 +1,71 @@
structures/iber_monument
Monument
Monument
150
120
100
100
8.0
1200
decay|rubble/rubble_stone_2x2
iber
Revered Monument
Gur Oroigarri
CivSpecific
Monument Town
structures/iberian_bull.png
- phase_town
+ phase_town
20
20
20
30
3
interface/complete/building/complete_iber_monument.xml
structures/iberians/sb_1.xml
structures/fndn_2x2.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/structures/kush/pyramid_large.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/structures/kush/pyramid_large.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/structures/kush/pyramid_large.xml (revision 27505)
@@ -1,66 +1,66 @@
structures/kush_pyramids_military
PyramidLarge
300
450
150
20.0
3000
decay|rubble/rubble_stone_6x6
kush
Large Pyramid
mr ʿȝ
-ConquestCritical CivSpecific
City Pyramid
structures/kush_pyramid_big.png
- phase_city
+ phase_city
90
30
interface/complete/building/complete_iber_monument.xml
15.0
false
40
40000
40
structures/kushites/pyramid_large.xml
structures/fndn_5x7.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/structures/kush/pyramid_small.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/structures/kush/pyramid_small.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/structures/kush/pyramid_small.xml (revision 27505)
@@ -1,60 +1,60 @@
structures/kush_pyramids_economic
120
150
75
15.0
2000
decay|rubble/rubble_stone_4x4
kush
Small Pyramid
mr
-ConquestCritical CivSpecific
Village Pyramid
structures/kush_pyramid_small.png
- phase_village
+ phase_village
30
15
interface/complete/building/complete_iber_monument.xml
false
30
30000
30
structures/kushites/pyramid_small.xml
structures/fndn_4x5.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/structures/rome/army_camp.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/structures/rome/army_camp.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/structures/rome/army_camp.xml (revision 27505)
@@ -1,130 +1,130 @@
Bow
10
60
1200
2000
100
1.5
50
false
Human
outline_border.png
outline_border_mask.png
0.175
neutral enemy
ArmyCamp
ArmyCamp
80
3
15
1
Soldier
3
10.0
1
250
400
150
12.0
20
0.1
Unit
Support Infantry Cavalry Siege
0
6
1750
decay|rubble/rubble_rome_sb
rome
Army Camp
Castra
Build in neutral or enemy territory. Train Advanced Melee Infantry. Construct Rams. Garrison Soldiers for additional arrows.
ConquestCritical CivSpecific
Town ArmyCamp
structures/roman_camp.png
- phase_town
+ phase_town
80
30
15
35
3
interface/complete/building/complete_broch.xml
attack/weapon/bow_attack.xml
attack/impact/arrow_impact.xml
2
0.7
units/{civ}/infantry_axeman_a
units/{civ}/infantry_swordsman_a
units/{civ}/infantry_spearman_a
units/{civ}/infantry_pikeman_a
units/{civ}/siege_ram
90
structures/romans/camp.xml
structures/fndn_8x8.xml
29.5
8
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre_military_colony.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre_military_colony.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_civic_civil_centre_military_colony.xml (revision 27505)
@@ -1,56 +1,56 @@
own neutral
Colony
CivilCentre
120
1
300
200
200
150
2000
decay|rubble/rubble_stone_5x5
Military Colony
template_structure_civic_civil_centre_military_colony
Colony
structures/military_settlement.png
- phase_town
+ phase_town
40
40
30
-phase_town_{civ}
-phase_city_{civ}
-hellenistic_metropolis
interface/complete/building/complete_gymnasium.xml
75
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_civic_house.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_civic_house.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_civic_house.xml (revision 27505)
@@ -1,77 +1,77 @@
30
75
5.0
3
0
0.1
Unit
Support+!Elephant
1
800
decay|rubble/rubble_stone_2x2
House
template_structure_civic_house
Village House
structures/house.png
- phase_village
+ phase_village
15
5
health_females_01
pop_house_01
pop_house_02
unlock_females_house
interface/complete/building/complete_house.xml
8.0
false
16
65535
units/{civ}/support_female_citizen_house
20
structures/fndn_3x3.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_civic_stoa.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_civic_stoa.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_civic_stoa.xml (revision 27505)
@@ -1,54 +1,54 @@
150
100
150
10.0
10
0.1
Unit
Support Infantry Cavalry
0
2
2500
decay|rubble/rubble_stone_6x4
Stoa
template_structure_civic_stoa
-ConquestCritical
Town Stoa
structures/stoa.png
- phase_town
+ phase_town
20
30
false
40
65535
40
structures/fndn_8x4.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_civic_temple.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_civic_temple.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_civic_temple.xml (revision 27505)
@@ -1,78 +1,78 @@
structures/temple_heal
200
300
12.0
20
0.1
Unit
Support Infantry Cavalry
3
2
2000
decay|rubble/rubble_stone_4x6
Temple
template_structure_civic_temple
Train Healers and research healing technologies.
Town Temple
structures/temple.png
- phase_town
+ phase_town
60
heal_range
heal_range_2
heal_rate
heal_rate_2
garrison_heal
health_regen_units
interface/complete/building/complete_temple.xml
false
40
30000
0.8
units/{civ}/support_healer_b
40
structures/fndn_4x6.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_defensive_tower_artillery.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_defensive_tower_artillery.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_defensive_tower_artillery.xml (revision 27505)
@@ -1,86 +1,86 @@
Stone
90
0
80
40
0
15
0
4500
5000
40
6
9.81
false
props/units/weapons/tower_artillery_projectile.xml
props/units/weapons/tower_artillery_projectile_impact.xml
0.3
-Human !Organic
1
0
200
200
200
15.0
5
1400
Artillery Tower
template_structure_defensive_tower_artillery
ArtilleryTower
structures/tower_artillery.png
- phase_city
+ phase_city
40
40
tower_health
attack/impact/siegeprojectilehit.xml
attack/siege/ballist_attack.xml
false
32
30000
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_defensive_tower_bolt.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_defensive_tower_bolt.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_defensive_tower_bolt.xml (revision 27505)
@@ -1,83 +1,83 @@
Bolt
100
90
30
0
15
0
500
4000
150
1
9.81
false
props/units/weapons/tower_artillery_projectile_impact.xml
0.1
1
0
200
200
100
15.0
5
1400
Bolt Tower
template_structure_defensive_tower_bolt
BoltTower
structures/tower_bolt.png
- phase_city
+ phase_city
40
20
tower_health
attack/weapon/arrowfly.xml
attack/impact/arrow_metal.xml
false
32
30000
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_defensive_tower_stone.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_defensive_tower_stone.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_defensive_tower_stone.xml (revision 27505)
@@ -1,61 +1,61 @@
0
15
0
150
100
100
15.0
5
1000
Stone Tower
template_structure_defensive_tower_stone
Garrison Infantry for additional arrows. Needs the “Murder Holes” technology to protect its foot.
StoneTower
structures/defense_tower.png
- phase_town
+ phase_town
20
20
tower_watch
tower_crenellations
tower_range
tower_murderholes
tower_health
false
32
30000
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_economic_farmstead.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_economic_farmstead.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_economic_farmstead.xml (revision 27505)
@@ -1,76 +1,76 @@
FemaleCitizen
50
100
100
300
45
100
8.0
900
decay|rubble/rubble_stone_4x4
Farmstead
template_structure_economic_farmstead
Research food gathering technologies.
DropsiteFood
Village Farmstead
structures/farmstead.png
- phase_village
+ phase_village
20
gather_wicker_baskets
gather_farming_plows
gather_farming_training
gather_farming_fertilizer
gather_farming_seed_drill
gather_farming_water_weeding
gather_farming_chain_pump
gather_farming_harvester
food
true
interface/complete/building/complete_farmstead.xml
interface/alarm/alarm_alert_0.xml
interface/alarm/alarm_alert_1.xml
false
20
30000
20
structures/fndn_5x5.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_economic_storehouse.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_economic_storehouse.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_economic_storehouse.xml (revision 27505)
@@ -1,81 +1,81 @@
FemaleCitizen
50
100
100
40
100
8.0
800
decay|rubble/rubble_stone_3x3
Storehouse
template_structure_economic_storehouse
Research gathering technologies.
DropsiteWood DropsiteMetal DropsiteStone
Village Storehouse
structures/storehouse.png
- phase_village
+ phase_village
20
gather_lumbering_ironaxes
gather_lumbering_strongeraxes
gather_lumbering_sharpaxes
gather_mining_servants
gather_mining_serfs
gather_mining_slaves
gather_mining_wedgemallet
gather_mining_shaftmining
gather_mining_silvermining
gather_capacity_basket
gather_capacity_wheelbarrow
gather_capacity_carts
wood stone metal
true
interface/complete/building/complete_storehouse.xml
interface/alarm/alarm_alert_0.xml
interface/alarm/alarm_alert_1.xml
false
20
30000
20
structures/fndn_3x3.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_barracks.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_barracks.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_barracks.xml (revision 27505)
@@ -1,83 +1,83 @@
structures/xp_trickle
150
200
100
12.0
10
Infantry
2000
decay|rubble/rubble_stone_4x4
Barracks
template_structure_military_barracks
Train Infantry and research Infantry technologies.
Village Barracks
structures/barracks.png
- phase_village
+ phase_village
40
20
barracks_batch_training
unlock_champion_infantry
pair_unlock_champions_sele
interface/complete/building/complete_barracks.xml
0.8
units/{civ}/infantry_spearman_b
units/{civ}/infantry_pikeman_b
units/{civ}/infantry_maceman_b
units/{civ}/infantry_axeman_b
units/{civ}/infantry_swordsman_b
units/{civ}/infantry_javelineer_b
units/{civ}/infantry_slinger_b
units/{civ}/infantry_archer_b
units/{civ}/champion_infantry_spearman
units/{civ}/champion_infantry_pikeman
units/{civ}/champion_infantry_maceman
units/{civ}/champion_infantry_axeman
units/{civ}/champion_infantry_swordsman
units/{civ}/champion_infantry_javelineer
units/{civ}/champion_infantry_slinger
units/{civ}/champion_infantry_archer
32
structures/fndn_6x6.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_forge.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_forge.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_forge.xml (revision 27505)
@@ -1,73 +1,73 @@
120
200
12.0
1
Infantry Healer
2000
decay|rubble/rubble_stone_4x4
Forge
template_structure_military_forge
Research attack damage and damage resistance technologies.
-ConquestCritical
Town Forge
structures/blacksmith.png
- phase_town
+ phase_town
40
soldier_attack_melee_01
soldier_attack_melee_02
soldier_attack_melee_03
soldier_attack_melee_03_variant
soldier_attack_ranged_01
soldier_attack_ranged_02
soldier_attack_ranged_03
soldier_resistance_hack_01
soldier_resistance_hack_02
soldier_resistance_hack_03
soldier_resistance_pierce_01
soldier_resistance_pierce_02
soldier_resistance_pierce_03
archer_attack_spread
interface/complete/building/complete_forge.xml
38
30000
32
structures/fndn_5x5.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_stable.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_stable.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_military_stable.xml (revision 27505)
@@ -1,79 +1,79 @@
structures/xp_trickle
120
200
50
12.0
10
Cavalry
2000
decay|rubble/rubble_stone_5x5
Stable
template_structure_military_stable
Train Cavalry and research Cavalry technologies.
Village Stable
structures/stable_01.png
- phase_village
+ phase_village
40
10
stable_batch_training
cavalry_movement_speed
cavalry_health
nisean_horses
unlock_champion_cavalry
unlock_champion_chariots
interface/complete/building/complete_stable.xml
0.8
units/{civ}/cavalry_axeman_b
units/{civ}/cavalry_swordsman_b
units/{civ}/cavalry_spearman_b
units/{civ}/cavalry_javelineer_b
units/{civ}/cavalry_archer_b
units/{civ}/champion_cavalry
units/{civ}/champion_cavalry_spearman
units/{civ}/champion_cavalry_swordsman
units/{civ}/champion_cavalry_javelineer
units/{civ}/champion_cavalry_archer
units/{civ}/champion_chariot
units/{civ}/war_dog
32
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_champion_cavalry.xml (revision 27505)
@@ -1,67 +1,67 @@
25
150
80
100
6.0
240
FastMoving
Cavalry
Champion Cavalry
- unlock_champion_cavalry
+ -phase_city unlock_champion_cavalry
200
15
8
10
5
7
5
20
actor/mounted/movement/walk.xml
actor/mounted/movement/walk.xml
actor/fauna/death/death_horse.xml
interface/alarm/alarm_create_cav.xml
7.0
special/formations/wedge
2
1.4
80
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_champion.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_champion.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_champion.xml (revision 27505)
@@ -1,41 +1,41 @@
Capture
5
4
1000
Field Palisade Wall
Human
Soldier Champion
Champion Unit
- phase_city
+ phase_city
8
256x256/arrow.png
256x256/arrow_mask.png
voice/{lang}/civ/civ_{phenotype}_attack.xml
voice/{lang}/civ/civ_{phenotype}_attack.xml
voice/{lang}/civ/civ_{phenotype}_garrison.xml
voice/{lang}/civ/civ_{phenotype}_gather.xml
voice/{lang}/civ/civ_{phenotype}_walk.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship_fire.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship_fire.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship_fire.xml (revision 27505)
@@ -1,65 +1,65 @@
Fire
20
12
50
100
!Ship
30
300
Circular
30
true
600
500
-6
0.85
0.65
0.35
Fire Ship
Unrepairable. Gradually loses health. Can only attack Ships.
Melee Warship Fireship
- phase_town
+ phase_town
128x256/cartouche.png
128x256/cartouche_mask.png
ship-small
1.6
1.6
60
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_wonder.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_wonder.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure_wonder.xml (revision 27505)
@@ -1,101 +1,101 @@
structures/wonder_population_cap
Wonder
4
1000
1000
1500
1000
10.0
50
0.1
Unit
Support Soldier
5
2
5000
decay|rubble/rubble_stone_6x6
Wonder
template_structure_wonder
Bring glory to your civilization and add large tracts of land to your empire.
ConquestCritical
City Wonder
structures/wonder.png
- phase_city
+ phase_city
200
300
200
structure
wonder.png
wonder_population_cap
15
25
3
1.0
1.0
1.0
1.0
2000
interface/complete/building/complete_wonder.xml
true
100
65535
72
structures/fndn_stonehenge.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_hero.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_hero.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_hero.xml (revision 27505)
@@ -1,72 +1,72 @@
Capture
10
4
1000
Field Palisade Wall
units/heroes/hero_garrison
0
50
100
250
Human
Soldier Hero
Hero
technologies/laurel_wreath.png
- phase_city
+ phase_city
400
10
0
0
25
hero
256x256/star.png
256x256/star_mask.png
voice/{lang}/civ/civ_{phenotype}_attack.xml
voice/{lang}/civ/civ_{phenotype}_attack.xml
voice/{lang}/civ/civ_{phenotype}_garrison.xml
voice/{lang}/civ/civ_{phenotype}_gather.xml
voice/{lang}/civ/civ_{phenotype}_walk.xml
interface/alarm/alarm_create_infantry.xml
actor/human/movement/walk.xml
actor/human/movement/walk.xml
actor/human/death/{phenotype}_death.xml
Hero
1
100
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_fauna_herd_domestic_cattle.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_fauna_herd_domestic_cattle.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_fauna_herd_domestic_cattle.xml (revision 27505)
@@ -1,21 +1,21 @@
- phase_city
+ phase_city
actor/fauna/animal/cattle_order.xml
actor/fauna/animal/cattle_death.xml
actor/fauna/animal/cattle_trained.xml
0.4
1.4
0.4
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship_merchant.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship_merchant.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship_merchant.xml (revision 27505)
@@ -1,60 +1,60 @@
20
100
15
Support Cavalry
240
Merchantman
template_unit_ship_merchant
Trade between docks. Garrison a Trader aboard for additional profit (+20% for each garrisoned). Gather profitable aquatic treasures.
-ConquestCritical
Trader Bribable
- phase_town
+ phase_town
20
128x256/ellipse.png
128x256/ellipse_mask.png
0.75
0.2
12
passive
false
false
ship-small
1.35
1.6
50
true
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_siege.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_siege.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_siege.xml (revision 27505)
@@ -1,76 +1,76 @@
3
0.0
0.0
2.0
true
-Organic
Siege
Siege
- phase_city
+ phase_city
pitch-roll
4
4.0
0.0
1
1
25
5
128x256/rounded_rectangle.png
128x256/rounded_rectangle_mask.png
attack/siege/ram_move.xml
attack/siege/ram_move.xml
attack/siege/ram_move.xml
attack/siege/ram_trained.xml
4.0
0.5
false
large
1
0.75
0.15
5.0
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/athen/infantry_javelineer_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/athen/infantry_javelineer_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/athen/infantry_javelineer_b.xml (revision 27505)
@@ -1,18 +1,18 @@
units/athen/infantry_javelineer_b
Thracian Peltast
Peltastḗs Thrâx
units/athen/infantry_javelinist.png
- phase_town
+ phase_town
units/athen/infantry_javelineer_a
units/athenians/infantry_javelinist_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/brit/infantry_javelineer_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/brit/infantry_javelineer_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/brit/infantry_javelineer_b.xml (revision 27505)
@@ -1,25 +1,25 @@
0.80
0.50
0.20
brit
units/brit/infantry_javelineer_b
Adretos
units/brit/infantry_javelinist.png
- phase_town
+ phase_town
units/brit/infantry_javelineer_a
units/britons/infantry_javelinist_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/cavalry_swordsman_iber_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/cavalry_swordsman_iber_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/cavalry_swordsman_iber_b.xml (revision 27505)
@@ -1,24 +1,24 @@
Sword
cart
Iberian Heavy Cavalry
Ḥayyāl Ḥerev Raḫūv
units/cart/cavalry_swordsman_iber_b
units/cart/cavalry_swordsman.png
- phase_town
+ phase_town
units/cart/cavalry_swordsman_iber_a
units/iberians/cavalry_swordsman_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/infantry_swordsman_ital_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/infantry_swordsman_ital_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/infantry_swordsman_ital_b.xml (revision 27505)
@@ -1,27 +1,27 @@
structures/{civ}/super_dock
structures/{civ}/embassy_celtic
structures/{civ}/embassy_iberian
structures/{civ}/embassy_italic
cart
Samnite Swordsman
Seḫīr Romaḥ
units/cart/infantry_swordsman_ital_b
units/cart/infantry_swordsman_2.png
- phase_town
+ phase_town
units/cart/infantry_swordsman_ital_a
units/carthaginians/infantry_swordsman_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/champion_fanatic.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/champion_fanatic.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/champion_fanatic.xml (revision 27505)
@@ -1,39 +1,39 @@
120
100
0
gaul
Naked Fanatic
Bariogaisatos
units/gaul/champion_fanatic.png
- phase_town
+ phase_town
12
10
0
-3
-4
1.4
1.4
units/gauls/infantry_spearman_c.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/han/cavalry_crossbowman_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/han/cavalry_crossbowman_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/han/cavalry_crossbowman_b.xml (revision 27505)
@@ -1,18 +1,18 @@
han
units/han/cavalry_crossbowman_b
Han Cavalry Crossbowman
units/han/cavalry_crossbowman.png
- phase_town
+ phase_town
units/han/cavalry_crossbowman_a
units/han/cavalry_crossbowman_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/han/champion_infantry_archer_academy.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/han/champion_infantry_archer_academy.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/han/champion_infantry_archer_academy.xml (revision 27505)
@@ -1,16 +1,13 @@
han
Palace Guard Archer
Yǔ Lín
units/han/champion_infantry_archer
units/han/champion_infantry_archer.png
-
- phase_city
-
units/han/infantry_archer_c.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/han/infantry_pikeman_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/han/infantry_pikeman_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/han/infantry_pikeman_b.xml (revision 27505)
@@ -1,46 +1,46 @@
Ji
1
1
-structures/wallset_palisade
han
units/han/infantry_pikeman_b
Halberdier
Jǐ Bīng
units/han/infantry_halberdman.png
- phase_town
+ phase_town
units/han/infantry_pikeman_a
-2
-2
special/formations/anti_cavalry
units/han/infantry_halberdman_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship_warship_medium.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship_warship_medium.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship_warship_medium.xml (revision 27505)
@@ -1,46 +1,46 @@
3
13
3
25
200
100
30
Siege
1400
Medium Warship
Garrison units for transport and to increase firepower. Deals triple damage against Ships.
Medium
Trireme
- phase_town
+ phase_town
140
40
20
4
1.8
1.8
90
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/athen/cavalry_swordsman_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/athen/cavalry_swordsman_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/athen/cavalry_swordsman_b.xml (revision 27505)
@@ -1,23 +1,23 @@
Sword
units/athen/cavalry_swordsman_b
Greek Cavalry
Hippeús
units/athen/cavalry_swordsman.png
- phase_town
+ phase_town
units/athen/cavalry_swordsman_a
units/athenians/cavalry_swordsman_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/brit/cavalry_swordsman_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/brit/cavalry_swordsman_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/brit/cavalry_swordsman_b.xml (revision 27505)
@@ -1,19 +1,19 @@
brit
units/brit/cavalry_swordsman_b
Eporedos
Celtic Cavalry
units/brit/cavalry_swordsman.png
- phase_town
+ phase_town
units/brit/cavalry_swordsman_a
units/britons/cavalry_swordsman_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/cavalry_swordsman_gaul_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/cavalry_swordsman_gaul_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/cavalry_swordsman_gaul_b.xml (revision 27505)
@@ -1,19 +1,19 @@
cart
Gallic Mercenary Cavalry
Ḥayyāl Ḥerev Raḫūv
units/cart/cavalry_swordsman_gaul_b
units/cart/cavalry_swordsman_2.png
- phase_town
+ phase_town
units/cart/cavalry_swordsman_gaul_a
units/gauls/cavalry_swordsman_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/infantry_swordsman_gaul_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/infantry_swordsman_gaul_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/infantry_swordsman_gaul_b.xml (revision 27505)
@@ -1,27 +1,27 @@
structures/{civ}/super_dock
structures/{civ}/embassy_celtic
structures/{civ}/embassy_iberian
structures/{civ}/embassy_italic
cart
Gallic Mercenary Swordsman
Seḫīr Ḥerev
units/cart/infantry_swordsman_gaul_b
units/cart/infantry_swordsman.png
- phase_town
+ phase_town
units/cart/infantry_swordsman_gaul_a
units/gauls/infantry_swordsman_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/cavalry_swordsman_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/cavalry_swordsman_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/cavalry_swordsman_b.xml (revision 27505)
@@ -1,18 +1,18 @@
gaul
units/gaul/cavalry_swordsman_b
Eporedos
units/gaul/cavalry_swordsman.png
- phase_town
+ phase_town
units/gaul/cavalry_swordsman_a
units/gauls/cavalry_swordsman_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/han/cavalry_archer_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/han/cavalry_archer_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/han/cavalry_archer_b.xml (revision 27505)
@@ -1,18 +1,18 @@
han
units/han/cavalry_archer_b
Gōng Qíbīng
units/han/cavalry_archer.png
- phase_town
+ phase_town
units/han/cavalry_archer_a
units/han/cavalry_archer_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/han/champion_chariot_academy.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/han/champion_chariot_academy.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/han/champion_chariot_academy.xml (revision 27505)
@@ -1,20 +1,20 @@
5.0
han
Han War Chariot
Zhanche
Chariot
units/han/chariot.png
- phase_city
+ -unlock_champion_cavalry phase_city
units/han/chariot_archer_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/han/infantry_archer_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/han/infantry_archer_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/han/infantry_archer_b.xml (revision 27505)
@@ -1,23 +1,23 @@
-structures/wallset_palisade
han
units/han/infantry_archer_b
Shè Shǒu
units/han/infantry_archer.png
- phase_town
+ phase_town
units/han/infantry_archer_a
units/han/infantry_archer_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship_warship_light.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship_warship_light.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship_warship_light.xml (revision 27505)
@@ -1,41 +1,41 @@
2
10
2
20
120
60
20
800
Light Warship
Light
Bireme
- phase_town
+ phase_town
80
24
12
1.55
1.55
90
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_wallset.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_wallset.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_wallset.xml (revision 27505)
@@ -1,28 +1,28 @@
gaia
Wall
Wall off an area.
Wall
structures/wall.png
true
- phase_town
+ phase_town
false
false
false
false
0.85
0.05
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/athen/support_female_citizen_house.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/athen/support_female_citizen_house.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/athen/support_female_citizen_house.xml (revision 27505)
@@ -1,11 +1,11 @@
30
- unlock_females_house
+ unlock_females_house
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/cavalry_spearman_ital_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/cavalry_spearman_ital_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/cavalry_spearman_ital_b.xml (revision 27505)
@@ -1,19 +1,19 @@
cart
Italic Cavalry
Ḥayyāl Romaḥ Raḫūv
units/cart/cavalry_spearman_ital_b
units/cart/cavalry_spearman.png
- phase_town
+ phase_town
units/cart/cavalry_spearman_ital_a
units/carthaginians/cavalry_spearman_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/infantry_slinger_iber_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/infantry_slinger_iber_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/infantry_slinger_iber_b.xml (revision 27505)
@@ -1,27 +1,27 @@
structures/{civ}/super_dock
structures/{civ}/embassy_celtic
structures/{civ}/embassy_iberian
structures/{civ}/embassy_italic
cart
Balearic Slinger
Qallāʿ Ibušimi
units/cart/infantry_slinger_iber_b
units/cart/infantry_slinger.png
- phase_town
+ phase_town
units/cart/infantry_slinger_iber_a
units/iberians/infantry_slinger_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/support_female_citizen_house.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/support_female_citizen_house.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/support_female_citizen_house.xml (revision 27505)
@@ -1,11 +1,11 @@
30
- unlock_females_house
+ unlock_females_house
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/support_female_citizen_house.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/support_female_citizen_house.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/support_female_citizen_house.xml (revision 27505)
@@ -1,11 +1,11 @@
30
- unlock_females_house
+ unlock_females_house
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/han/champion_cavalry_spearman_academy.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/han/champion_cavalry_spearman_academy.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/han/champion_cavalry_spearman_academy.xml (revision 27505)
@@ -1,15 +1,15 @@
han
Wu Wei Yin Cao Cao Guard
units/han/champion_cavalry
units/han/champion_cavalry_spearman.png
- phase_city
+ -unlock_champion_cavalry phase_city
units/han/cavalry_spearman_c_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/han/champion_infantry_spearman_academy.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/han/champion_infantry_spearman_academy.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/han/champion_infantry_spearman_academy.xml (revision 27505)
@@ -1,16 +1,13 @@
han
Palace Guard Spearman
Hǔ Bēn
units/han/champion_infantry_spearman
units/han/champion_infantry_swordsman.png
-
- phase_city
-
units/han/infantry_spearman_c.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship_warship_heavy.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship_warship_heavy.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_ship_warship_heavy.xml (revision 27505)
@@ -1,81 +1,81 @@
Stone
150
100
40
2000
5000
40
6
20
false
Ship Structure
outline_border.png
outline_border_mask.png
0.175
1
10
StoneThrower
5
30
600
300
10.0
50
Support Soldier Siege
2000
Heavy Warship
Garrison units for transport. Garrison Stone Throwers to increase firepower.
Heavy
Quinquereme
- phase_city
+ phase_city
200
120
60
4
attack/siege/ballist_attack.xml
1.8
1.8
110
Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_support_healer.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_support_healer.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit_support_healer.xml (revision 27505)
@@ -1,60 +1,60 @@
15
100
25
12
heal_overlay_range.png
heal_overlay_range_mask.png
0.35
5
2000
Human
85
-ConquestCritical
Healer
Healer
template_unit_support_healer
Basic
Heal units.
- phase_town
+ phase_town
8
25
150
128x128/plus.png
128x128/plus_mask.png
voice/{lang}/civ/civ_{phenotype}_heal.xml
interface/alarm/alarm_create_priest.xml
30
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/athen/infantry_marine_archer_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/athen/infantry_marine_archer_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/athen/infantry_marine_archer_b.xml (revision 27505)
@@ -1,18 +1,18 @@
units/athen/infantry_marine_archer_b
Cretan Mercenary Archer
Toxótēs Krētikós
units/mace/infantry_archer.png
- iphicratean_reforms
+ iphicratean_reforms
units/athen/infantry_marine_archer_a
units/athenians/infantry_archer_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/brit/support_female_citizen_house.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/brit/support_female_citizen_house.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/brit/support_female_citizen_house.xml (revision 27505)
@@ -1,11 +1,11 @@
30
- unlock_females_house
+ unlock_females_house
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/infantry_javelineer_iber_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/infantry_javelineer_iber_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/infantry_javelineer_iber_b.xml (revision 27505)
@@ -1,27 +1,27 @@
structures/{civ}/super_dock
structures/{civ}/embassy_celtic
structures/{civ}/embassy_iberian
structures/{civ}/embassy_italic
cart
Iberian Mercenary Skirmisher
Sǝḫīr Kidōn
units/cart/infantry_javelineer_iber_b
units/cart/infantry_javelinist.png
- phase_town
+ phase_town
units/cart/infantry_javelineer_iber_a
units/iberians/infantry_javelinist_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/ship_merchant.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/ship_merchant.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/cart/ship_merchant.xml (revision 27505)
@@ -1,30 +1,30 @@
8.0
cart
Seḥer
Trade between docks. Garrison a Trader aboard for additional profit (+20% for each garrisoned). Gather profitable aquatic treasures. Carthaginians have +25% sea trading bonus.
units/cart/ship_merchant.png
- phase_village
+ -phase_town phase_village
128x512/ellipse.png
128x512/ellipse_mask.png
1.25
structures/carthaginians/merchant_ship.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/infantry_slinger_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/infantry_slinger_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/gaul/infantry_slinger_b.xml (revision 27505)
@@ -1,23 +1,23 @@
structures/gaul/assembly
gaul
units/gaul/infantry_slinger_b
Talmoris
units/gaul/infantry_slinger.png
- phase_town
+ phase_town
units/gaul/infantry_slinger_a
units/gauls/infantry_slinger_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/han/cavalry_spearman_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/han/cavalry_spearman_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/han/cavalry_spearman_b.xml (revision 27505)
@@ -1,18 +1,18 @@
han
units/han/cavalry_spearman_b
Máo Qíbīng
units/han/cavalry_spearman.png
- phase_town
+ phase_town
units/han/cavalry_spearman_a
units/han/cavalry_spearman_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/han/champion_infantry_crossbowman_academy.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/han/champion_infantry_crossbowman_academy.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/han/champion_infantry_crossbowman_academy.xml (revision 27505)
@@ -1,14 +1,11 @@
han
Juezhang
units/han/champion_infantry_crossbowman.png
-
- phase_city
-
units/han/infantry_crossbowman_c.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/han/infantry_swordsman_special_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/han/infantry_swordsman_special_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/han/infantry_swordsman_special_b.xml (revision 27505)
@@ -1,23 +1,23 @@
-structures/wallset_palisade
han
units/han/infantry_swordsman_b
Dāo Bīng
units/han/infantry_swordsman.png
- phase_town
+ phase_town
units/han/infantry_swordsman_special_a
units/han/infantry_swordsman_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/iber/cavalry_spearman_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/iber/cavalry_spearman_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/iber/cavalry_spearman_b.xml (revision 27505)
@@ -1,18 +1,18 @@
iber
units/iber/cavalry_spearman_b
Lantzari
units/iber/cavalry_spearman.png
- phase_town
+ phase_town
units/iber/cavalry_spearman_a
units/iberians/cavalry_spearman_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/han/support_minister.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/han/support_minister.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/han/support_minister.xml (revision 27505)
@@ -1,109 +1,109 @@
Capture
8
4
1000
Field Palisade Wall
Sword
10
3
500
1000
Unit+!Ship
units/han_minister_garrison
units/han_minister_gathering
units/han_minister_building
units/han_minister_garrison_ministry
1
15
100
100
200
han
Imperial Minister
Guānlì
Use to boost the efficiency of nearby units and buildings. Garrison within a building to boost the efficiency of its production queue. Only Han buildings can garrison ministers.
Organic Human
Minister
units/han/minister.png
- phase_town
+ phase_town
150
10
10
hero
8
2
4
6
128x128/octagram.png
128x128/octagram_mask.png
attack/weapon/sword_attack.xml
resource/construction/con_wood.xml
actor/human/death/{phenotype}_death.xml
voice/{lang}/civ/civ_{phenotype}_attack.xml
voice/{lang}/civ/civ_{phenotype}_attack.xml
voice/{lang}/civ/civ_{phenotype}_garrison.xml
voice/{lang}/civ/civ_{phenotype}_gather.xml
voice/{lang}/civ/civ_{phenotype}_repair.xml
voice/{lang}/civ/civ_{phenotype}_walk.xml
actor/human/movement/run.xml
interface/alarm/alarm_create_infantry.xml
actor/human/movement/walk.xml
Minister
40
units/han/minister.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/han/support_female_citizen_house.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/han/support_female_citizen_house.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/han/support_female_citizen_house.xml (revision 27505)
@@ -1,11 +1,11 @@
30
- unlock_females_house
+ unlock_females_house
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/iber/infantry_slinger_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/iber/infantry_slinger_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/iber/infantry_slinger_b.xml (revision 27505)
@@ -1,23 +1,23 @@
structures/iber/monument
iber
units/iber/infantry_slinger_b
Habailari
units/iber/infantry_slinger.png
- phase_town
+ phase_town
units/iber/infantry_slinger_a
units/iberians/infantry_slinger_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/iber/champion_infantry_swordsman.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/iber/champion_infantry_swordsman.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/iber/champion_infantry_swordsman.xml (revision 27505)
@@ -1,19 +1,19 @@
Sword
iber
Leial Ezpatari
units/iber/champion_infantry.png
- unlock_champion_infantry
+ unlock_champion_infantry
units/iberians/infantry_swordsman_c.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/iber/support_female_citizen_house.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/iber/support_female_citizen_house.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/iber/support_female_citizen_house.xml (revision 27505)
@@ -1,11 +1,11 @@
30
- unlock_females_house
+ unlock_females_house
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/infantry_archer_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/infantry_archer_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/infantry_archer_b.xml (revision 27505)
@@ -1,28 +1,28 @@
structures/kush/pyramid_large
structures/kush/temple_amun
structures/kush/camp_blemmye
structures/kush/camp_noba
kush
napatan
units/kush/infantry_archer_b
Nubian Archer
Pdty Nhsyw
units/kush/infantry_archer.png
- phase_village
+ phase_village
units/kush/infantry_archer_a
units/kushites/infantry_archer_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/infantry_spearman_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/infantry_spearman_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/infantry_spearman_b.xml (revision 27505)
@@ -1,28 +1,28 @@
structures/kush/pyramid_large
structures/kush/temple_amun
structures/kush/camp_blemmye
structures/kush/camp_noba
kush
napatan
units/kush/infantry_spearman_b
Nubian Spearman
iry-rdwy Nhsyw
units/kush/infantry_spearman.png
- phase_village
+ phase_village
units/kush/infantry_spearman_a
units/kushites/infantry_spearman_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/mace/champion_infantry_spearman.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/mace/champion_infantry_spearman.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/mace/champion_infantry_spearman.xml (revision 27505)
@@ -1,21 +1,21 @@
mace
greek
Macedonian Shield Bearer
Hypaspistḗs
units/mace/champion_infantry_spearman
units/mace/hypaspist.png
- unlock_champion_infantry
+ unlock_champion_infantry
units/mace/champion_infantry_spearman_02
2000
units/macedonians/infantry_spearman_c_a.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/maur/cavalry_swordsman_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/maur/cavalry_swordsman_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/maur/cavalry_swordsman_b.xml (revision 27505)
@@ -1,19 +1,19 @@
maur
units/maur/cavalry_swordsman_b
Indian Raiding Cavalry
Aśvārohagaṇaḥ
units/maur/cavalry_swordsman.png
- phase_town
+ phase_town
units/maur/cavalry_swordsman_a
units/mauryas/cavalry_swordsman_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/maur/support_female_citizen_house.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/maur/support_female_citizen_house.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/maur/support_female_citizen_house.xml (revision 27505)
@@ -1,11 +1,11 @@
30
- unlock_females_house
+ unlock_females_house
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_axeman_b_trireme.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_axeman_b_trireme.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_axeman_b_trireme.xml (revision 27505)
@@ -1,11 +1,11 @@
- equine_transports
+ -phase_town equine_transports
units/pers/cavalry_axeman_a_trireme
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_javelineer_e_trireme.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_javelineer_e_trireme.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_javelineer_e_trireme.xml (revision 27505)
@@ -1,8 +1,8 @@
- equine_transports
+ equine_transports
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/cavalry_archer_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/cavalry_archer_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/cavalry_archer_b.xml (revision 27505)
@@ -1,40 +1,40 @@
7.5
ptol
Camel
units/ptol/cavalry_archer
Nabataean Camel Archer
Mutsābiq Gamal Nabatu
units/ptol/camel_archer.png
- phase_village
+ phase_village
units/ptol/cavalry_archer_a
actor/fauna/movement/camel_order.xml
actor/fauna/death/death_camel.xml
8.5
units/ptolemies/camel_archer_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/infantry_archer_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/infantry_archer_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/infantry_archer_b.xml (revision 27505)
@@ -1,25 +1,25 @@
structures/ptol/lighthouse
structures/ptol/library
ptol
units/ptol/infantry_archer_b
Cretan Mercenary Archer
Toxótēs Krētikós
units/mace/infantry_archer.png
- phase_town
+ phase_town
units/ptol/infantry_archer_a
units/ptolemies/infantry_archer_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/iber/infantry_spearman_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/iber/infantry_spearman_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/iber/infantry_spearman_b.xml (revision 27505)
@@ -1,23 +1,23 @@
structures/iber/monument
iber
units/iber/infantry_spearman_b
Ezkutari
units/iber/infantry_spearman.png
- phase_town
+ phase_town
units/iber/infantry_spearman_a
units/iberians/infantry_spearman_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/cavalry_spearman_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/cavalry_spearman_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/cavalry_spearman_b.xml (revision 27505)
@@ -1,20 +1,20 @@
kush
napatan
units/kush/cavalry_spearman_b
Meroitic Heavy Cavalry
Htr
units/kush/cavalry_spearman.png
- phase_town
+ phase_town
units/kush/cavalry_spearman_a
units/kushites/cavalry_spearman_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/infantry_pikeman_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/infantry_pikeman_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/infantry_pikeman_b.xml (revision 27505)
@@ -1,28 +1,28 @@
structures/kush/pyramid_large
structures/kush/temple_amun
structures/kush/camp_blemmye
structures/kush/camp_noba
kush
napatan
units/kush/infantry_pikeman_b
Meroitic Pikeman
siȝwrd
units/kush/infantry_pikeman.png
- phase_town
+ phase_town
units/kush/infantry_pikeman_a
units/kushites/infantry_pikeman_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/mace/cavalry_javelineer_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/mace/cavalry_javelineer_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/mace/cavalry_javelineer_b.xml (revision 27505)
@@ -1,20 +1,20 @@
mace
greek
units/mace/cavalry_javelineer_b
Odrysian Skirmish Cavalry
Hippakontistḕs Odrysós
units/mace/cavalry_javelinist.png
- phase_town
+ phase_town
units/mace/cavalry_javelineer_a
units/macedonians/cavalry_javelinist_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/mace/support_female_citizen_house.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/mace/support_female_citizen_house.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/mace/support_female_citizen_house.xml (revision 27505)
@@ -1,11 +1,11 @@
30
- unlock_females_house
+ unlock_females_house
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/maur/infantry_swordsman_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/maur/infantry_swordsman_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/maur/infantry_swordsman_b.xml (revision 27505)
@@ -1,30 +1,30 @@
Sword
structures/maur/palace
structures/maur/pillar_ashoka
maur
units/maur/infantry_swordsman_b
Indian Swordsman
Khadagdhari
units/maur/infantry_swordsman.png
- phase_town
+ phase_town
units/maur/infantry_swordsman_a
units/mauryas/infantry_swordsman_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_axeman_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_axeman_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_axeman_b.xml (revision 27505)
@@ -1,20 +1,20 @@
pers
persian
units/pers/cavalry_axeman_b
Hyrcanian Cavalry
Asabāra Varkaniya
units/pers/cavalry_axeman.png
- phase_town
+ phase_town
units/pers/cavalry_axeman_a
units/persians/cavalry_axeman_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_javelineer_b_trireme.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_javelineer_b_trireme.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_javelineer_b_trireme.xml (revision 27505)
@@ -1,11 +1,11 @@
- equine_transports
+ equine_transports
units/pers/cavalry_javelineer_a_trireme
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/support_female_citizen_house.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/support_female_citizen_house.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/support_female_citizen_house.xml (revision 27505)
@@ -1,11 +1,11 @@
30
- unlock_females_house
+ unlock_females_house
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/champion_infantry_pikeman.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/champion_infantry_pikeman.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/champion_infantry_pikeman.xml (revision 27505)
@@ -1,16 +1,16 @@
ptol
greek
Royal Guard Infantry
Phalangitès Agema
units/ptol/champion_infantry.png
- unlock_champion_infantry
+ unlock_champion_infantry
units/ptolemies/infantry_pikeman_c.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/cavalry_javelineer_merc_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/cavalry_javelineer_merc_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/cavalry_javelineer_merc_b.xml (revision 27505)
@@ -1,41 +1,41 @@
7.5
kush
napatan
units/kush/cavalry_javelineer_merc_b
Blemmye Desert Raider
nhw Bulahau gml
Camel
units/kush/camel_javelinist.png
- phase_town
+ phase_town
units/kush/cavalry_javelineer_merc_a
actor/fauna/movement/camel_order.xml
actor/fauna/death/death_camel.xml
8.5
units/kushites/camel_javelinist_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/infantry_maceman_merc_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/infantry_maceman_merc_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/infantry_maceman_merc_b.xml (revision 27505)
@@ -1,28 +1,28 @@
structures/kush/pyramid_large
structures/kush/temple_amun
structures/kush/camp_blemmye
structures/kush/camp_noba
kush
napatan
units/kush/infantry_maceman_b
Noba Maceman
nhw Noba
units/kush/infantry_maceman.png
- phase_town
+ phase_town
units/kush/infantry_maceman_merc_a
units/kushites/infantry_maceman_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/support_female_citizen_house.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/support_female_citizen_house.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/support_female_citizen_house.xml (revision 27505)
@@ -1,11 +1,11 @@
30
- unlock_females_house
+ unlock_females_house
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/mace/infantry_slinger_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/mace/infantry_slinger_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/mace/infantry_slinger_b.xml (revision 27505)
@@ -1,20 +1,20 @@
mace
greek
units/mace/infantry_slinger_b
Rhodian Slinger
Sphendonḗtēs Rhódios
units/mace/infantry_slinger.png
- phase_town
+ phase_town
units/mace/infantry_slinger_a
units/macedonians/infantry_slinger_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/maur/hero_chandragupta_infantry.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/maur/hero_chandragupta_infantry.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/maur/hero_chandragupta_infantry.xml (revision 27505)
@@ -1,26 +1,26 @@
maur
Chandragupta Maurya
Chandragupta Maurya
units/maur/hero_chandragupta.png
units/maur/hero_chandragupta
This gives Chandragupta Maurya his War Elephant.
200
200
- phase_city
+ phase_city
units/mauryas/hero_infantry_swordsman_chandragupta.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_axeman_a_trireme.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_axeman_a_trireme.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_axeman_a_trireme.xml (revision 27505)
@@ -1,11 +1,11 @@
- equine_transports
+ -phase_town equine_transports
units/pers/cavalry_axeman_e_trireme
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_javelineer_a_trireme.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_javelineer_a_trireme.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_javelineer_a_trireme.xml (revision 27505)
@@ -1,11 +1,11 @@
- equine_transports
+ equine_transports
units/pers/cavalry_javelineer_e_trireme
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/infantry_javelineer_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/infantry_javelineer_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/infantry_javelineer_b.xml (revision 27505)
@@ -1,20 +1,20 @@
pers
persian
units/pers/infantry_javelineer_b
Lydian Auxiliary
Pastiš Spardiya
units/pers/infantry_javelinist.png
- phase_town
+ phase_town
units/pers/infantry_javelineer_a
units/persians/infantry_javelinist_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/cavalry_spearman_merc_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/cavalry_spearman_merc_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/cavalry_spearman_merc_b.xml (revision 27505)
@@ -1,19 +1,19 @@
ptol
units/ptol/cavalry_spearman_merc_b
Macedonian Settler Cavalry
Hippeús Makedonikós
units/ptol/cavalry_spearman.png
- phase_town
+ phase_town
units/ptol/cavalry_spearman_merc_a
units/ptolemies/cavalry_spearman_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/cavalry_javelineer_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/cavalry_javelineer_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/cavalry_javelineer_b.xml (revision 27505)
@@ -1,20 +1,20 @@
kush
napatan
units/kush/cavalry_javelineer_b
iry hr ssmwtt
Napatan Light Cavalry
units/kush/cavalry_javelinist.png
- phase_village
+ phase_village
units/kush/cavalry_javelineer_a
units/kushites/cavalry_javelinist_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/infantry_javelineer_merc_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/infantry_javelineer_merc_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/infantry_javelineer_merc_b.xml (revision 27505)
@@ -1,28 +1,28 @@
structures/kush/pyramid_large
structures/kush/temple_amun
structures/kush/camp_blemmye
structures/kush/camp_noba
kush
napatan
units/kush/infantry_javelineer_merc_b
Noba Skirmisher
nhw ʿhȝw Noba
units/kush/infantry_javelinist.png
- phase_town
+ phase_town
units/kush/infantry_javelineer_merc_a
units/kushites/infantry_javelinist_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/infantry_swordsman_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/infantry_swordsman_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/kush/infantry_swordsman_b.xml (revision 27505)
@@ -1,28 +1,28 @@
structures/kush/pyramid_large
structures/kush/temple_amun
structures/kush/camp_blemmye
structures/kush/camp_noba
kush
napatan
units/kush/infantry_swordsman_b
Meroitic Swordsman
knw hps
units/kush/infantry_swordsman.png
- phase_town
+ phase_town
units/kush/infantry_swordsman_a
units/kushites/infantry_swordsman_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/mace/infantry_archer_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/mace/infantry_archer_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/mace/infantry_archer_b.xml (revision 27505)
@@ -1,20 +1,20 @@
mace
greek
units/mace/infantry_archer_b
Cretan Mercenary Archer
Toxótēs Krētikós
units/mace/infantry_archer.png
- phase_town
+ phase_town
units/mace/infantry_archer_a
units/macedonians/infantry_archer_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/maur/elephant_archer_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/maur/elephant_archer_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/maur/elephant_archer_b.xml (revision 27505)
@@ -1,19 +1,19 @@
maur
Elephant Archer
Vachii Gaja
units/maur/elephant_archer_b
units/maur/elephant_archer.png
- phase_town
+ phase_town
units/maur/elephant_archer_a
units/mauryas/elephantry_archer_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_archer_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_archer_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_archer_b.xml (revision 27505)
@@ -1,20 +1,20 @@
pers
persian
units/pers/cavalry_archer_b
Parthian Horse Archer
Asabāra Parθava
units/pers/cavalry_archer.png
- phase_town
+ phase_town
units/pers/cavalry_archer_a
units/persians/cavalry_archer_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_axeman_e_trireme.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_axeman_e_trireme.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_axeman_e_trireme.xml (revision 27505)
@@ -1,8 +1,8 @@
- equine_transports
+ -phase_town equine_transports
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_spearman_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_spearman_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/pers/cavalry_spearman_b.xml (revision 27505)
@@ -1,20 +1,20 @@
pers
persian
units/pers/cavalry_spearman_b
Cappadocian Cavalry
Asabāra Katpatuka
units/pers/cavalry_spearman.png
- phase_town
+ phase_town
units/pers/cavalry_spearman_a
units/persians/cavalry_spearman_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/cavalry_javelineer_merc_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/cavalry_javelineer_merc_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/cavalry_javelineer_merc_b.xml (revision 27505)
@@ -1,19 +1,19 @@
ptol
units/ptol/cavalry_javelineer_merc_b
Tarantine Settler Cavalry
Hippeús Tarantînos
units/hele/tarentine_cavalry_e.png
- phase_town
+ phase_town
units/ptol/cavalry_javelineer_merc_a
units/ptolemies/cavalry_javelinist_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/infantry_javelineer_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/infantry_javelineer_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/infantry_javelineer_b.xml (revision 27505)
@@ -1,25 +1,25 @@
structures/ptol/lighthouse
structures/ptol/library
ptol
units/ptol/infantry_javelineer_b
Mercenary Thureos Skirmisher
Thureophóros Akrobolistḗs
units/ptol/infantry_javelinist_merc.png
- phase_town
+ phase_town
units/ptol/infantry_javelineer_a
units/ptolemies/infantry_javelinist_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/infantry_swordsman_merc_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/infantry_swordsman_merc_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/infantry_swordsman_merc_b.xml (revision 27505)
@@ -1,25 +1,25 @@
structures/ptol/lighthouse
structures/ptol/library
ptol
Gallic Mercenary Swordsman
Gallikós Mistophorós
units/ptol/infantry_swordsman_merc_b
units/cart/infantry_swordsman.png
- phase_town
+ phase_town
units/ptol/infantry_swordsman_merc_a
units/ptolemies/infantry_swordsman_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/infantry_spearman_merc_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/infantry_spearman_merc_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/infantry_spearman_merc_b.xml (revision 27505)
@@ -1,25 +1,25 @@
structures/ptol/lighthouse
structures/ptol/library
ptol
units/ptol/infantry_spearman_merc_b
Mercenary Thureos Spearman
Thureophóros Misthophóros
units/ptol/infantry_spearman_2.png
- phase_town
+ phase_town
units/ptol/infantry_spearman_merc_a
units/ptolemies/infantry_spearman_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/infantry_slinger_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/infantry_slinger_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/infantry_slinger_b.xml (revision 27505)
@@ -1,25 +1,25 @@
structures/ptol/lighthouse
structures/ptol/library
ptol
units/ptol/infantry_slinger_b
Judean Slinger
Hebraikós Sphendonḗtēs
units/ptol/infantry_slinger.png
- phase_village
+ phase_village
units/ptol/infantry_slinger_a
units/ptolemies/infantry_slinger_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/rome/cavalry_javelineer_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/rome/cavalry_javelineer_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/rome/cavalry_javelineer_b.xml (revision 27505)
@@ -1,20 +1,20 @@
rome
latin
Allied Cavalry
Eques Socius
units/rome/cavalry_javelineer_b
units/rome/cavalry_javelinist.png
- phase_town
+ phase_town
units/rome/cavalry_javelineer_a
units/romans/cavalry_javelinist_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/support_female_citizen_house.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/support_female_citizen_house.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/ptol/support_female_citizen_house.xml (revision 27505)
@@ -1,11 +1,11 @@
30
- unlock_females_house
+ unlock_females_house
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/rome/champion_infantry_sword_gladiator.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/rome/champion_infantry_sword_gladiator.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/rome/champion_infantry_sword_gladiator.xml (revision 27505)
@@ -1,50 +1,50 @@
structures/rome/army_camp
structures/rome/temple_vesta
-10
20
5
Gladiator
rome
latin
Gladiator Swordsman
Murmillo
Elite
units/rome/champion_infantry_gladiator_sword.png
- phase_town
+ phase_town
-1
-1
Gladiator
1.4
1.4
0.5
units/romans/infantry_gladiator_swordsman.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/cavalry_spearman_merc_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/cavalry_spearman_merc_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/cavalry_spearman_merc_b.xml (revision 27505)
@@ -1,20 +1,20 @@
sele
greek
units/sele/cavalry_spearman_merc_b
Companion Cavalry
Hippos Hetairike
units/sele/cavalry_spearman_merc.png
- phase_town
+ phase_town
units/sele/cavalry_spearman_merc_a
units/seleucids/cavalry_spearman_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/infantry_javelineer_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/infantry_javelineer_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/infantry_javelineer_b.xml (revision 27505)
@@ -1,20 +1,20 @@
sele
greek
units/sele/infantry_javelineer_b
Arab Javelineer
Pezakontistès Aravikós
units/sele/infantry_javelinist.png
- phase_village
+ phase_village
units/sele/infantry_javelineer_a
units/seleucids/infantry_javelinist_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/spart/champion_infantry_swordsman.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/spart/champion_infantry_swordsman.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/spart/champion_infantry_swordsman.xml (revision 27505)
@@ -1,32 +1,32 @@
structures/spart/syssiton
-structures/{civ}/wallset_stone
25
spart
greek
Skiritai Commando
Ékdromos Skirítēs
Elite
units/spart/champion_infantry_sword.png
- phase_town
+ phase_town
3
units/spartans/infantry_swordsman_c.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/rome/champion_infantry_spear_gladiator.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/rome/champion_infantry_spear_gladiator.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/rome/champion_infantry_spear_gladiator.xml (revision 27505)
@@ -1,49 +1,49 @@
structures/rome/army_camp
structures/rome/temple_vesta
-10
20
5
Gladiator
rome
latin
Gladiator Spearman
Hoplomachus
Elite
units/rome/champion_infantry_gladiator_spear.png
- phase_town
+ phase_town
-2
Gladiator
1.5
1.5
0.5
units/romans/infantry_gladiator_spearman.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/cavalry_archer_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/cavalry_archer_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/cavalry_archer_b.xml (revision 27505)
@@ -1,20 +1,20 @@
sele
greek
units/sele/cavalry_archer_b
Dahae Horse Archer
Hippotoxotès Dahae
units/pers/cavalry_archer.png
- phase_town
+ phase_town
units/sele/cavalry_archer_a
units/persians/cavalry_archer_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/infantry_archer_merc_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/infantry_archer_merc_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/infantry_archer_merc_b.xml (revision 27505)
@@ -1,20 +1,20 @@
sele
greek
units/sele/infantry_archer_merc_b
Syrian Archer
Toxótēs Syrías
units/sele/infantry_archer.png
- phase_town
+ phase_town
units/sele/infantry_archer_merc_a
units/seleucids/infantry_archer_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/spart/cavalry_spearman_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/spart/cavalry_spearman_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/spart/cavalry_spearman_b.xml (revision 27505)
@@ -1,20 +1,20 @@
spart
greek
units/spart/cavalry_spearman_b
Greek Allied Cavalry
Hippeús Symmakhikós
units/spart/cavalry_spearman.png
- phase_town
+ phase_town
units/spart/cavalry_spearman_a
units/spartans/cavalry_spearman_b_m.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/rome/support_female_citizen_house.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/rome/support_female_citizen_house.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/rome/support_female_citizen_house.xml (revision 27505)
@@ -1,11 +1,11 @@
30
- unlock_females_house
+ unlock_females_house
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/champion_infantry_swordsman.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/champion_infantry_swordsman.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/champion_infantry_swordsman.xml (revision 27505)
@@ -1,16 +1,16 @@
sele
greek
Romanized Heavy Swordsman
Thorakitès Rhomaïkós
units/sele/champion_swordsman.png
- reformed_army_sele
+ -phase_city reformed_army_sele
units/seleucids/infantry_swordsman_c.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/support_female_citizen_house.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/support_female_citizen_house.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/support_female_citizen_house.xml (revision 27505)
@@ -1,11 +1,11 @@
30
- unlock_females_house
+ unlock_females_house
Index: ps/trunk/source/tools/entity/checkrefs.py
===================================================================
--- ps/trunk/source/tools/entity/checkrefs.py (revision 27504)
+++ ps/trunk/source/tools/entity/checkrefs.py (revision 27505)
@@ -1,685 +1,686 @@
#!/usr/bin/env python3
from argparse import ArgumentParser
from io import BytesIO
from json import load, loads
from pathlib import Path
from re import split, match
from struct import unpack, calcsize
from os.path import sep, exists, basename
from xml.etree import ElementTree
import sys
from scriptlib import SimulTemplateEntity, find_files
from logging import WARNING, getLogger, StreamHandler, INFO, Formatter, Filter
class SingleLevelFilter(Filter):
def __init__(self, passlevel, reject):
self.passlevel = passlevel
self.reject = reject
def filter(self, record):
if self.reject:
return (record.levelno != self.passlevel)
else:
return (record.levelno == self.passlevel)
class CheckRefs:
def __init__(self):
# list of relative root file:str
self.files = []
# list of relative file:str
self.roots = []
# list of tuple (parent_file:str, dep_file:str)
self.deps = []
self.vfs_root = Path(__file__).resolve().parents[3] / 'binaries' / 'data' / 'mods'
self.supportedTextureFormats = ('dds', 'png')
self.supportedMeshesFormats = ('pmd', 'dae')
self.supportedAnimationFormats = ('psa', 'dae')
self.supportedAudioFormats = ('ogg')
self.mods = []
self.__init_logger
@property
def __init_logger(self):
logger = getLogger(__name__)
logger.setLevel(INFO)
# create a console handler, seems nicer to Windows and for future uses
ch = StreamHandler(sys.stdout)
ch.setLevel(INFO)
ch.setFormatter(Formatter('%(levelname)s - %(message)s'))
f1 = SingleLevelFilter(INFO, False)
ch.addFilter(f1)
logger.addHandler(ch)
errorch = StreamHandler(sys.stderr)
errorch.setLevel(WARNING)
errorch.setFormatter(Formatter('%(levelname)s - %(message)s'))
logger.addHandler(errorch)
self.logger = logger
def main(self):
ap = ArgumentParser(description="Checks the game files for missing dependencies, unused files,"
" and for file integrity.")
ap.add_argument('-u', '--check-unused', action='store_true',
help="check for all the unused files in the given mods and their dependencies."
" Implies --check-map-xml. Currently yields a lot of false positives.")
ap.add_argument('-x', '--check-map-xml', action='store_true',
help="check maps for missing actor and templates.")
ap.add_argument('-a', '--validate-actors', action='store_true',
help="run the validator.py script to check if the actors files have extra or missing textures."
" This currently only works for the public mod.")
ap.add_argument('-t', '--validate-templates', action='store_true',
help="run the validator.py script to check if the xml files match their (.rng) grammar file.")
ap.add_argument('-m', '--mods', metavar="MOD", dest='mods', nargs='+', default=['public'],
help="specify which mods to check. Default to public.")
args = ap.parse_args()
# force check_map_xml if check_unused is used to avoid false positives.
args.check_map_xml |= args.check_unused
# ordered uniq mods (dict maintains ordered keys from python 3.6)
self.mods = list(dict.fromkeys([*args.mods, *self.get_mod_dependencies(*args.mods), 'mod']).keys())
self.logger.info(f"Checking {'|'.join(args.mods)}'s integrity.")
self.logger.info(f"The following mods will be loaded: {'|'.join(self.mods)}.")
if args.check_map_xml:
self.add_maps_xml()
self.add_maps_pmp()
self.add_entities()
self.add_actors()
self.add_variants()
self.add_art()
self.add_materials()
self.add_particles()
self.add_soundgroups()
self.add_audio()
self.add_gui_xml()
self.add_gui_data()
self.add_civs()
self.add_rms()
self.add_techs()
self.add_terrains()
self.add_auras()
self.add_tips()
self.check_deps()
if args.check_unused:
self.check_unused()
if args.validate_templates:
sys.path.append("../xmlvalidator/")
from validate_grammar import RelaxNGValidator
validate = RelaxNGValidator(self.vfs_root, self.mods)
validate.run()
if args.validate_actors:
sys.path.append("../xmlvalidator/")
from validator import Validator
validator = Validator(self.vfs_root, self.mods)
validator.run()
def get_mod_dependencies(self, *mods):
modjsondeps = []
for mod in mods:
mod_json_path = self.vfs_root / mod / 'mod.json'
if not exists(mod_json_path):
continue
with open(mod_json_path, encoding='utf-8') as f:
modjson = load(f)
# 0ad's folder isn't named like the mod.
modjsondeps.extend(['public' if '0ad' in dep else dep for dep in modjson.get('dependencies', [])])
return modjsondeps
def vfs_to_relative_to_mods(self, vfs_path):
for dep in self.mods:
fn = Path(dep) / vfs_path
if (self.vfs_root / fn).exists():
return fn
return None
def vfs_to_physical(self, vfs_path):
fn = self.vfs_to_relative_to_mods(vfs_path)
return self.vfs_root / fn
def find_files(self, vfs_path, *ext_list):
return find_files(self.vfs_root, self.mods, vfs_path, *ext_list)
def add_maps_xml(self):
self.logger.info("Loading maps XML...")
mapfiles = self.find_files('maps/scenarios', 'xml')
mapfiles.extend(self.find_files('maps/skirmishes', 'xml'))
mapfiles.extend(self.find_files('maps/tutorials', 'xml'))
actor_prefix = 'actor|'
resource_prefix = 'resource|'
for (fp, ffp) in sorted(mapfiles):
self.files.append(str(fp))
self.roots.append(str(fp))
et_map = ElementTree.parse(ffp).getroot()
entities = et_map.find('Entities')
used = {entity.find('Template').text.strip() for entity in entities.findall('Entity')} if entities is not None else {}
for template in used:
if template.startswith(actor_prefix):
self.deps.append((str(fp), f'art/actors/{template[len(actor_prefix):]}'))
elif template.startswith(resource_prefix):
self.deps.append((str(fp), f'simulation/templates/{template[len(resource_prefix):]}.xml'))
else:
self.deps.append((str(fp), f'simulation/templates/{template}.xml'))
# Map previews
settings = loads(et_map.find('ScriptSettings').text)
if settings.get('Preview', None):
self.deps.append((str(fp), f'art/textures/ui/session/icons/mappreview/{settings["Preview"]}'))
def add_maps_pmp(self):
self.logger.info("Loading maps PMP...")
# Need to generate terrain texture filename=>relative path lookup first
terrains = dict()
for (fp, ffp) in self.find_files('art/terrains', 'xml'):
name = fp.stem
# ignore terrains.xml
if name != 'terrains':
if name in terrains:
self.logger.warning(f"Duplicate terrain name '{name}' (from '{terrains[name]}' and '{ffp}')")
terrains[name] = str(fp)
mapfiles = self.find_files('maps/scenarios', 'pmp')
mapfiles.extend(self.find_files('maps/skirmishes', 'pmp'))
for (fp, ffp) in sorted(mapfiles):
self.files.append(str(fp))
self.roots.append(str(fp))
with open(ffp, 'rb') as f:
expected_header = b'PSMP'
header = f.read(len(expected_header))
if header != expected_header:
raise ValueError(f"Invalid PMP header {header} in '{ffp}'")
int_fmt = ' 0:
recursionDepth -= 1
allReqTag = req.find('All')
if allReqTag is not None:
parse_requirements(allReqTag, recursionDepth)
anyReqTag = req.find('Any')
if anyReqTag is not None:
parse_requirements(anyReqTag, recursionDepth)
parse_requirements(reqTag)
cmp_researcher = entity.find('Researcher')
if cmp_researcher is not None:
techString = cmp_researcher.find('Technologies')
if techString is not None:
for tech in split(r'\s+', techString.text):
if not tech:
continue
if tech.startswith('-'):
continue
if '{civ}' in tech and cmp_identity is not None and cmp_identity.find('Civ') is not None:
civ = cmp_identity.find('Civ').text
# Fallback for non specific phase techs.
if tech.startswith('phase') and not bool([phase_tech for phase_tech in custom_phase_techs if (tech.replace('{civ}', civ) + ".json") == phase_tech]) :
civ = 'generic'
tech = tech.replace('{civ}', civ)
self.deps.append((str(fp), f'simulation/data/technologies/{tech}.json'))
def append_variant_dependencies(self, variant, fp):
variant_file = variant.get('file')
mesh = variant.find('mesh')
particles = variant.find('particles')
texture_files = [tex.get('file') for tex in variant.find('textures').findall('texture')] \
if variant.find('textures') is not None else []
prop_actors = [prop.get('actor') for prop in variant.find('props').findall('prop')] \
if variant.find('props') is not None else []
animation_files = [anim.get('file') for anim in variant.find('animations').findall('animation')] \
if variant.find('animations') is not None else []
if variant_file:
self.deps.append((str(fp), f'art/variants/{variant_file}'))
if mesh is not None and mesh.text:
self.deps.append((str(fp), f'art/meshes/{mesh.text}'))
if particles is not None and particles.get('file'):
self.deps.append((str(fp), f'art/particles/{particles.get("file")}'))
for texture_file in [x for x in texture_files if x]:
self.deps.append((str(fp), f'art/textures/skins/{texture_file}'))
for prop_actor in [x for x in prop_actors if x]:
self.deps.append((str(fp), f'art/actors/{prop_actor}'))
for animation_file in [x for x in animation_files if x]:
self.deps.append((str(fp), f'art/animation/{animation_file}'))
def append_actor_dependencies(self, actor, fp):
for group in actor.findall('group'):
for variant in group.findall('variant'):
self.append_variant_dependencies(variant, fp)
material = actor.find('material')
if material is not None and material.text:
self.deps.append((str(fp), f'art/materials/{material.text}'))
def add_actors(self):
self.logger.info("Loading actors...")
for (fp, ffp) in sorted(self.find_files('art/actors', 'xml')):
self.files.append(str(fp))
self.roots.append(str(fp))
root = ElementTree.parse(ffp).getroot()
if root.tag == 'actor':
self.append_actor_dependencies(root, fp)
# model has lods
elif root.tag == 'qualitylevels':
qualitylevels = root
for actor in qualitylevels.findall('actor'):
self.append_actor_dependencies(actor, fp)
for actor in qualitylevels.findall('inline'):
self.append_actor_dependencies(actor, fp)
def add_variants(self):
self.logger.info("Loading variants...")
for (fp, ffp) in sorted(self.find_files('art/variants', 'xml')):
self.files.append(str(fp))
self.roots.append(str(fp))
variant = ElementTree.parse(ffp).getroot()
self.append_variant_dependencies(variant, fp)
def add_art(self):
self.logger.info("Loading art files...")
self.files.extend([str(fp) for (fp, ffp) in self.find_files('art/textures/particles', *self.supportedTextureFormats)])
self.files.extend([str(fp) for (fp, ffp) in self.find_files('art/textures/terrain', *self.supportedTextureFormats)])
self.files.extend([str(fp) for (fp, ffp) in self.find_files('art/textures/skins', *self.supportedTextureFormats)])
self.files.extend([str(fp) for (fp, ffp) in self.find_files('art/meshes', *self.supportedMeshesFormats)])
self.files.extend([str(fp) for (fp, ffp) in self.find_files('art/animation', *self.supportedAnimationFormats)])
def add_materials(self):
self.logger.info("Loading materials...")
for (fp, ffp) in sorted(self.find_files('art/materials', 'xml')):
self.files.append(str(fp))
material_elem = ElementTree.parse(ffp).getroot()
for alternative in material_elem.findall('alternative'):
material = alternative.get('material')
if material:
self.deps.append((str(fp), f'art/materials/{material}'))
def add_particles(self):
self.logger.info("Loading particles...")
for (fp, ffp) in sorted(self.find_files('art/particles', 'xml')):
self.files.append(str(fp))
self.roots.append(str(fp))
particle = ElementTree.parse(ffp).getroot()
texture = particle.find('texture')
if texture:
self.deps.append((str(fp), texture.text))
def add_soundgroups(self):
self.logger.info("Loading sound groups...")
for (fp, ffp) in sorted(self.find_files('audio', 'xml')):
self.files.append(str(fp))
self.roots.append(str(fp))
sound_group = ElementTree.parse(ffp).getroot()
path = sound_group.find('Path').text.rstrip('/')
for sound in sound_group.findall('Sound'):
self.deps.append((str(fp), f'{path}/{sound.text}'))
def add_audio(self):
self.logger.info("Loading audio files...")
self.files.extend([str(fp) for (fp, ffp) in self.find_files('audio/', self.supportedAudioFormats)])
def add_gui_object_repeat(self, obj, fp):
for repeat in obj.findall('repeat'):
for sub_obj in repeat.findall('object'):
# TODO: look at sprites, styles, etc
self.add_gui_object_include(sub_obj, fp)
for sub_obj in repeat.findall('objects'):
# TODO: look at sprites, styles, etc
self.add_gui_object_include(sub_obj, fp)
self.add_gui_object_include(repeat, fp)
def add_gui_object_include(self, obj, fp):
for include in obj.findall('include'):
included_file = include.get('file')
if included_file:
self.deps.append((str(fp), f'{included_file}'))
def add_gui_object(self, parent, fp):
if parent is None:
return
for obj in parent.findall('object'):
# TODO: look at sprites, styles, etc
self.add_gui_object_repeat(obj, fp)
self.add_gui_object_include(obj, fp)
self.add_gui_object(obj, fp)
for obj in parent.findall('objects'):
# TODO: look at sprites, styles, etc
self.add_gui_object_repeat(obj, fp)
self.add_gui_object_include(obj, fp)
self.add_gui_object(obj, fp)
def add_gui_xml(self):
self.logger.info("Loading GUI XML...")
for (fp, ffp) in sorted(self.find_files('gui', 'xml')):
self.files.append(str(fp))
# GUI page definitions are assumed to be named page_[something].xml and alone in that.
if match(r".*[\\\/]page(_[^.\/\\]+)?\.xml$", str(fp)):
self.roots.append(str(fp))
root_xml = ElementTree.parse(ffp).getroot()
for include in root_xml.findall('include'):
# If including an entire directory, find all the *.xml files
if include.text.endswith('/'):
self.deps.extend([(str(fp), str(sub_fp)) for (sub_fp, sub_ffp) in self.find_files(f'gui/{include.text}', 'xml')])
else:
self.deps.append((str(fp), f'gui/{include.text}'))
else:
xml = ElementTree.parse(ffp)
root_xml = xml.getroot()
name = root_xml.tag
self.roots.append(str(fp))
if name in ('objects', 'object'):
for script in root_xml.findall('script'):
if script.get('file'):
self.deps.append((str(fp), script.get('file')))
if script.get('directory'):
# If including an entire directory, find all the *.js files
self.deps.extend([(str(fp), str(sub_fp)) for (sub_fp, sub_ffp) in self.find_files(script.get('directory'), 'js')])
self.add_gui_object(root_xml, fp)
elif name == 'setup':
# TODO: look at sprites, styles, etc
pass
elif name == 'styles':
for style in root_xml.findall('style'):
if(style.get('sound_opened')):
self.deps.append((str(fp), f"{style.get('sound_opened')}"))
if(style.get('sound_closed')):
self.deps.append((str(fp), f"{style.get('sound_closed')}"))
if(style.get('sound_selected')):
self.deps.append((str(fp), f"{style.get('sound_selected')}"))
if(style.get('sound_disabled')):
self.deps.append((str(fp), f"{style.get('sound_disabled')}"))
# TODO: look at sprites, styles, etc
pass
elif name == 'sprites':
for sprite in root_xml.findall('sprite'):
for image in sprite.findall('image'):
if image.get('texture'):
self.deps.append((str(fp), f"art/textures/ui/{image.get('texture')}"))
else:
bio = BytesIO()
xml.write(bio)
bio.seek(0)
raise ValueError(f"Unexpected GUI XML root element '{name}':\n{bio.read().decode('ascii')}")
def add_gui_data(self):
self.logger.info("Loading GUI data...")
self.files.extend([str(fp) for (fp, ffp) in self.find_files('gui', 'js')])
self.files.extend([str(fp) for (fp, ffp) in self.find_files('gamesettings', 'js')])
self.files.extend([str(fp) for (fp, ffp) in self.find_files('autostart', 'js')])
self.roots.extend([str(fp) for (fp, ffp) in self.find_files('autostart', 'js')])
self.files.extend([str(fp) for (fp, ffp) in self.find_files('art/textures/ui', *self.supportedTextureFormats)])
self.files.extend([str(fp) for (fp, ffp) in self.find_files('art/textures/selection', *self.supportedTextureFormats)])
def add_civs(self):
self.logger.info("Loading civs...")
for (fp, ffp) in sorted(self.find_files('simulation/data/civs', 'json')):
self.files.append(str(fp))
self.roots.append(str(fp))
with open(ffp, encoding='utf-8') as f:
civ = load(f)
for music in civ.get('Music', []):
self.deps.append((str(fp), f"audio/music/{music['File']}"))
def add_tips(self):
self.logger.info("Loading tips...")
for (fp, ffp) in sorted(self.find_files('gui/text/tips', 'txt')):
relative_path = str(fp)
self.files.append(relative_path)
self.roots.append(relative_path)
self.deps.append((relative_path, f"art/textures/ui/loading/tips/{basename(relative_path).split('.')[0]}.png"))
def add_rms(self):
self.logger.info("Loading random maps...")
self.files.extend([str(fp) for (fp, ffp) in self.find_files('maps/random', 'js')])
for (fp, ffp) in sorted(self.find_files('maps/random', 'json')):
if str(fp).startswith('maps/random/rmbiome'):
continue
self.files.append(str(fp))
self.roots.append(str(fp))
with open(ffp, encoding='utf-8') as f:
randmap = load(f)
settings = randmap.get('settings', {})
if settings.get('Script', None):
self.deps.append((str(fp), f"maps/random/{settings['Script']}"))
# Map previews
if settings.get('Preview', None):
self.deps.append((str(fp), f'art/textures/ui/session/icons/mappreview/{settings["Preview"]}'))
def add_techs(self):
self.logger.info("Loading techs...")
for (fp, ffp) in sorted(self.find_files('simulation/data/technologies', 'json')):
self.files.append(str(fp))
with open(ffp, encoding='utf-8') as f:
tech = load(f)
if tech.get('autoResearch', None):
self.roots.append(str(fp))
if tech.get('icon', None):
self.deps.append((str(fp), f"art/textures/ui/session/portraits/technologies/{tech['icon']}"))
if tech.get('supersedes', None):
self.deps.append((str(fp), f"simulation/data/technologies/{tech['supersedes']}.json"))
if tech.get('top', None):
self.deps.append((str(fp), f"simulation/data/technologies/{tech['top']}.json"))
if tech.get('bottom', None):
self.deps.append((str(fp), f"simulation/data/technologies/{tech['bottom']}.json"))
def add_terrains(self):
self.logger.info("Loading terrains...")
for (fp, ffp) in sorted(self.find_files('art/terrains', 'xml')):
# ignore terrains.xml
if str(fp).endswith('terrains.xml'):
continue
self.files.append(str(fp))
self.roots.append(str(fp))
terrain = ElementTree.parse(ffp).getroot()
for texture in terrain.find('textures').findall('texture'):
if texture.get('file'):
self.deps.append((str(fp), f"art/textures/terrain/{texture.get('file')}"))
if terrain.find('material') is not None:
material = terrain.find('material').text
self.deps.append((str(fp), f"art/materials/{material}"))
def add_auras(self):
self.logger.info("Loading auras...")
for (fp, ffp) in sorted(self.find_files('simulation/data/auras', 'json')):
self.files.append(str(fp))
with open(ffp, encoding='utf-8') as f:
aura = load(f)
if aura.get('overlayIcon', None):
self.deps.append((str(fp), aura['overlayIcon']))
range_overlay = aura.get('rangeOverlay', {})
for prop in ('lineTexture', 'lineTextureMask'):
if range_overlay.get(prop, None):
self.deps.append((str(fp), f"art/textures/selection/{range_overlay[prop]}"))
def check_deps(self):
self.logger.info("Looking for missing files...")
uniq_files = set(self.files)
uniq_files = [r.replace(sep, '/') for r in uniq_files]
lower_case_files = {f.lower(): f for f in uniq_files}
reverse_deps = dict()
for parent, dep in self.deps:
if sep != '/':
parent = parent.replace(sep, '/')
dep = dep.replace(sep, '/')
if dep not in reverse_deps:
reverse_deps[dep] = {parent}
else:
reverse_deps[dep].add(parent)
for dep in sorted(reverse_deps.keys()):
if "simulation/templates" in dep and (
dep.replace("templates/", "template/special/filter/") in uniq_files or
dep.replace("templates/", "template/mixins/") in uniq_files
):
continue
if dep in uniq_files:
continue
callers = [str(self.vfs_to_relative_to_mods(ref)) for ref in reverse_deps[dep]]
self.logger.warning(f"Missing file '{dep}' referenced by: {', '.join(sorted(callers))}")
if dep.lower() in lower_case_files:
self.logger.warning(f"### Case-insensitive match (found '{lower_case_files[dep.lower()]}')")
def check_unused(self):
self.logger.info("Looking for unused files...")
deps = dict()
for parent, dep in self.deps:
if sep != '/':
parent = parent.replace(sep, '/')
dep = dep.replace(sep, '/')
if parent not in deps:
deps[parent] = {dep}
else:
deps[parent].add(dep)
uniq_files = set(self.files)
uniq_files = [r.replace(sep, '/') for r in uniq_files]
reachable = list(set(self.roots))
reachable = [r.replace(sep, '/') for r in reachable]
while True:
new_reachable = []
for r in reachable:
new_reachable.extend([x for x in deps.get(r, {}) if x not in reachable])
if new_reachable:
reachable.extend(new_reachable)
else:
break
for f in sorted(uniq_files):
if any((
f in reachable,
'art/terrains/' in f,
'maps/random/' in f,
)):
continue
self.logger.warning(f"Unused file '{str(self.vfs_to_relative_to_mods(f))}'")
if __name__ == '__main__':
check_ref = CheckRefs()
check_ref.main()
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/rome/infantry_spearman_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/rome/infantry_spearman_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/rome/infantry_spearman_b.xml (revision 27505)
@@ -1,38 +1,38 @@
structures/rome/army_camp
structures/rome/temple_vesta
0.85
0.45
rome
latin
units/rome/infantry_spearman_b
Veteran Spearman
Triārius
units/rome/infantry_spearman.png
- phase_town
+ phase_town
Elite rank Spearmen can be promoted to champion Centurions.
units/rome/infantry_spearman_a
special/formations/anti_cavalry
units/romans/infantry_spearman_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/champion_infantry_pikeman.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/champion_infantry_pikeman.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/champion_infantry_pikeman.xml (revision 27505)
@@ -1,16 +1,16 @@
sele
greek
Silver Shield
Argyraspis
units/sele/champion_pikeman.png
- traditional_army_sele
+ -phase_city traditional_army_sele
units/seleucids/infantry_pikeman_c.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/infantry_swordsman_merc_b.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/infantry_swordsman_merc_b.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/sele/infantry_swordsman_merc_b.xml (revision 27505)
@@ -1,25 +1,25 @@
Rhomphaia
sele
greek
units/sele/infantry_swordsman_merc_b
Thracian Mercenary Swordsman
Rhomphaiaphoros Thrakikós
units/sele/infantry_swordsman.png
- phase_town
+ phase_town
units/sele/infantry_swordsman_merc_a
units/seleucids/infantry_swordsman_b.xml
Index: ps/trunk/binaries/data/mods/public/simulation/templates/units/spart/support_female_citizen_house.xml
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/templates/units/spart/support_female_citizen_house.xml (revision 27504)
+++ ps/trunk/binaries/data/mods/public/simulation/templates/units/spart/support_female_citizen_house.xml (revision 27505)
@@ -1,11 +1,11 @@
30
- unlock_females_house
+ unlock_females_house