forked from 0ad/0ad
304 lines
9.8 KiB
JavaScript
304 lines
9.8 KiB
JavaScript
/**
|
|
* Gets an array of all classes for this identity template
|
|
*/
|
|
function GetIdentityClasses(template)
|
|
{
|
|
var classList = [];
|
|
if (template.Classes && template.Classes._string)
|
|
classList = classList.concat(template.Classes._string.split(/\s+/));
|
|
|
|
if (template.VisibleClasses && template.VisibleClasses._string)
|
|
classList = classList.concat(template.VisibleClasses._string.split(/\s+/));
|
|
|
|
if (template.Rank)
|
|
classList = classList.concat(template.Rank);
|
|
return classList;
|
|
}
|
|
|
|
/**
|
|
* Gets an array with all classes for this identity template
|
|
* that should be shown in the GUI
|
|
*/
|
|
function GetVisibleIdentityClasses(template)
|
|
{
|
|
if (template.VisibleClasses && template.VisibleClasses._string)
|
|
return template.VisibleClasses._string.split(/\s+/);
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* Check if the classes given in the identity template
|
|
* match a list of classes
|
|
* @param classes List of the classes to check against
|
|
* @param match Either a string in the form
|
|
* "Class1 Class2+Class3"
|
|
* where spaces are handled as OR and '+'-signs as AND,
|
|
* Or a list in the form
|
|
* [["Class1"], ["Class2", "Class3"]]
|
|
* where the outer list is combined as OR, and the inner lists are AND-ed
|
|
* Or a hybrid format containing a list of strings, where the list is
|
|
* combined as OR, and the strings are split by space and '+' and AND-ed
|
|
*
|
|
* @return undefined if there are no classes or no match object
|
|
* true if the the logical combination in the match object matches the classes
|
|
* false otherwise
|
|
*/
|
|
function MatchesClassList(classes, match)
|
|
{
|
|
if (!match || !classes)
|
|
return undefined;
|
|
// transform the string to an array
|
|
if (typeof match == "string")
|
|
match = match.split(/\s+/);
|
|
|
|
for (var sublist of match)
|
|
{
|
|
// if the elements are still strings, split them by space or by '+'
|
|
if (typeof sublist == "string")
|
|
sublist = sublist.split(/[+\s]+/);
|
|
if (sublist.every(function(c) { return classes.indexOf(c) != -1; }))
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Get information about a template with or without technology modifications.
|
|
* @param template A valid template as returned by the template loader.
|
|
* @param player An optional player id to get the technology modifications
|
|
* of properties.
|
|
*/
|
|
function GetTemplateDataHelper(template, player)
|
|
{
|
|
var ret = {};
|
|
|
|
var func;
|
|
if (player)
|
|
func = ApplyValueModificationsToTemplate;
|
|
else
|
|
func = function(a, val, c, d) { return val; }
|
|
|
|
if (template.Armour)
|
|
{
|
|
ret.armour = {
|
|
"hack": func("Armour/Hack", +template.Armour.Hack, player, template),
|
|
"pierce": func("Armour/Pierce", +template.Armour.Pierce, player, template),
|
|
"crush": func("Armour/Crush", +template.Armour.Crush, player, template),
|
|
};
|
|
}
|
|
|
|
if (template.Attack)
|
|
{
|
|
ret.attack = {};
|
|
for (var type in template.Attack)
|
|
{
|
|
ret.attack[type] = {
|
|
"hack": func("Attack/"+type+"/Hack", +(template.Attack[type].Hack || 0), player, template),
|
|
"pierce": func("Attack/"+type+"/Pierce", +(template.Attack[type].Pierce || 0), player, template),
|
|
"crush": func("Attack/"+type+"/Crush", +(template.Attack[type].Crush || 0), player, template),
|
|
"minRange": func("Attack/"+type+"/MinRange", +(template.Attack[type].MinRange || 0), player, template),
|
|
"maxRange": func("Attack/"+type+"/MaxRange", +template.Attack[type].MaxRange, player, template),
|
|
"elevationBonus": func("Attack/"+type+"/ElevationBonus", +(template.Attack[type].ElevationBonus || 0), player, template),
|
|
"repeatTime": +(template.Attack[type].RepeatTime || 0),
|
|
};
|
|
}
|
|
}
|
|
|
|
if (template.Auras)
|
|
{
|
|
ret.auras = {};
|
|
for each (var aura in template.Auras)
|
|
if (aura.AuraName)
|
|
ret.auras[aura.AuraName] = aura.AuraDescription || null;
|
|
}
|
|
|
|
if (template.BuildRestrictions)
|
|
{
|
|
// required properties
|
|
ret.buildRestrictions = {
|
|
"placementType": template.BuildRestrictions.PlacementType,
|
|
"territory": template.BuildRestrictions.Territory,
|
|
"category": template.BuildRestrictions.Category,
|
|
};
|
|
|
|
// optional properties
|
|
if (template.BuildRestrictions.Distance)
|
|
{
|
|
ret.buildRestrictions.distance = {
|
|
"fromCategory": template.BuildRestrictions.Distance.FromCategory,
|
|
};
|
|
if (template.BuildRestrictions.Distance.MinDistance) ret.buildRestrictions.distance.min = +template.BuildRestrictions.Distance.MinDistance;
|
|
if (template.BuildRestrictions.Distance.MaxDistance) ret.buildRestrictions.distance.max = +template.BuildRestrictions.Distance.MaxDistance;
|
|
}
|
|
}
|
|
|
|
if (template.TrainingRestrictions)
|
|
{
|
|
ret.trainingRestrictions = {
|
|
"category": template.TrainingRestrictions.Category,
|
|
};
|
|
}
|
|
|
|
if (template.Cost)
|
|
{
|
|
ret.cost = {};
|
|
if (template.Cost.Resources.food) ret.cost.food = func("Cost/Resources/food", +template.Cost.Resources.food, player, template);
|
|
if (template.Cost.Resources.wood) ret.cost.wood = func("Cost/Resources/wood", +template.Cost.Resources.wood, player, template);
|
|
if (template.Cost.Resources.stone) ret.cost.stone = func("Cost/Resources/stone", +template.Cost.Resources.stone, player, template);
|
|
if (template.Cost.Resources.metal) ret.cost.metal = func("Cost/Resources/metal", +template.Cost.Resources.metal, player, template);
|
|
if (template.Cost.Population) ret.cost.population = func("Cost/Population", +template.Cost.Population, player, template);
|
|
if (template.Cost.PopulationBonus) ret.cost.populationBonus = func("Cost/PopulationBonus", +template.Cost.PopulationBonus, player, template);
|
|
if (template.Cost.BuildTime) ret.cost.time = func("Cost/BuildTime", +template.Cost.BuildTime, player, template);
|
|
}
|
|
|
|
if (template.Footprint)
|
|
{
|
|
ret.footprint = {"height": template.Footprint.Height};
|
|
|
|
if (template.Footprint.Square)
|
|
ret.footprint.square = {"width": +template.Footprint.Square["@width"], "depth": +template.Footprint.Square["@depth"]};
|
|
else if (template.Footprint.Circle)
|
|
ret.footprint.circle = {"radius": +template.Footprint.Circle["@radius"]};
|
|
else
|
|
warn("GetTemplateDataHelper(): Unrecognized Footprint type");
|
|
}
|
|
|
|
if (template.Obstruction)
|
|
{
|
|
ret.obstruction = {
|
|
"active": ("" + template.Obstruction.Active == "true"),
|
|
"blockMovement": ("" + template.Obstruction.BlockMovement == "true"),
|
|
"blockPathfinding": ("" + template.Obstruction.BlockPathfinding == "true"),
|
|
"blockFoundation": ("" + template.Obstruction.BlockFoundation == "true"),
|
|
"blockConstruction": ("" + template.Obstruction.BlockConstruction == "true"),
|
|
"disableBlockMovement": ("" + template.Obstruction.DisableBlockMovement == "true"),
|
|
"disableBlockPathfinding": ("" + template.Obstruction.DisableBlockPathfinding == "true"),
|
|
"shape": {}
|
|
};
|
|
|
|
if (template.Obstruction.Static)
|
|
{
|
|
ret.obstruction.shape.type = "static";
|
|
ret.obstruction.shape.width = +template.Obstruction.Static["@width"];
|
|
ret.obstruction.shape.depth = +template.Obstruction.Static["@depth"];
|
|
}
|
|
else if (template.Obstruction.Unit)
|
|
{
|
|
ret.obstruction.shape.type = "unit";
|
|
ret.obstruction.shape.radius = +template.Obstruction.Unit["@radius"];
|
|
}
|
|
else
|
|
{
|
|
ret.obstruction.shape.type = "cluster";
|
|
}
|
|
}
|
|
|
|
if (template.Pack)
|
|
{
|
|
ret.pack = {
|
|
"state": template.Pack.State,
|
|
"time": func("Pack/Time", +template.Pack.Time, player, template),
|
|
};
|
|
}
|
|
|
|
if (template.Health)
|
|
ret.health = Math.round(func("Health/Max", +template.Health.Max, player, template));
|
|
|
|
if (template.Identity)
|
|
{
|
|
ret.selectionGroupName = template.Identity.SelectionGroupName;
|
|
ret.name = {
|
|
"specific": (template.Identity.SpecificName || template.Identity.GenericName),
|
|
"generic": template.Identity.GenericName
|
|
};
|
|
ret.icon = template.Identity.Icon;
|
|
ret.tooltip = template.Identity.Tooltip;
|
|
ret.gateConversionTooltip = template.Identity.GateConversionTooltip;
|
|
ret.requiredTechnology = template.Identity.RequiredTechnology;
|
|
ret.visibleIdentityClasses = GetVisibleIdentityClasses(template.Identity);
|
|
}
|
|
|
|
if (template.UnitMotion)
|
|
{
|
|
ret.speed = {
|
|
"walk": func("UnitMotion/WalkSpeed", +template.UnitMotion.WalkSpeed, player, template),
|
|
};
|
|
if (template.UnitMotion.Run)
|
|
ret.speed.run = func("UnitMotion/Run/Speed", +template.UnitMotion.Run.Speed, player, template);
|
|
}
|
|
|
|
if (template.Trader)
|
|
ret.trader = template.Trader;
|
|
|
|
if (template.WallSet)
|
|
{
|
|
ret.wallSet = {
|
|
"templates": {
|
|
"tower": template.WallSet.Templates.Tower,
|
|
"gate": template.WallSet.Templates.Gate,
|
|
"long": template.WallSet.Templates.WallLong,
|
|
"medium": template.WallSet.Templates.WallMedium,
|
|
"short": template.WallSet.Templates.WallShort,
|
|
},
|
|
"maxTowerOverlap": +template.WallSet.MaxTowerOverlap,
|
|
"minTowerOverlap": +template.WallSet.MinTowerOverlap,
|
|
};
|
|
}
|
|
|
|
if (template.WallPiece)
|
|
ret.wallPiece = {"length": +template.WallPiece.Length};
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* Get information about a technology template.
|
|
* @param template A valid template as obtained by loading the tech JSON file.
|
|
* @param civ Civilization for which the specific name should be returned.
|
|
*/
|
|
function GetTechnologyDataHelper(template, civ)
|
|
{
|
|
var ret = {};
|
|
|
|
// Get specific name for this civ or else the generic specific name
|
|
var specific = undefined;
|
|
if (template.specificName)
|
|
{
|
|
if (template.specificName[civ])
|
|
specific = template.specificName[civ];
|
|
else
|
|
specific = template.specificName['generic'];
|
|
}
|
|
|
|
ret.name = {
|
|
"specific": specific,
|
|
"generic": template.genericName,
|
|
};
|
|
|
|
if (template.icon)
|
|
ret.icon = "technologies/" + template.icon;
|
|
else
|
|
ret.icon = null;
|
|
ret.cost = {
|
|
"food": template.cost ? (+template.cost.food) : 0,
|
|
"wood": template.cost ? (+template.cost.wood) : 0,
|
|
"metal": template.cost ? (+template.cost.metal) : 0,
|
|
"stone": template.cost ? (+template.cost.stone) : 0,
|
|
"time": template.researchTime ? (+template.researchTime) : 0,
|
|
}
|
|
ret.tooltip = template.tooltip;
|
|
|
|
if (template.requirementsTooltip)
|
|
ret.requirementsTooltip = template.requirementsTooltip;
|
|
else
|
|
ret.requirementsTooltip = "";
|
|
|
|
if (template.requirements && template.requirements.class)
|
|
ret.classRequirements = {"class": template.requirements.class, "number": template.requirements.number};
|
|
|
|
ret.description = template.description;
|
|
|
|
return ret;
|
|
}
|