2012-11-07 09:56:14 -08:00
|
|
|
/**
|
2014-05-22 03:20:02 -07:00
|
|
|
* Gets an array of all classes for this identity template
|
2012-11-07 09:56:14 -08:00
|
|
|
*/
|
2014-05-22 03:20:02 -07:00
|
|
|
function GetIdentityClasses(template)
|
2012-11-07 09:56:14 -08:00
|
|
|
{
|
2014-05-22 03:20:02 -07:00
|
|
|
var classList = [];
|
|
|
|
|
if (template.Classes && template.Classes._string)
|
|
|
|
|
classList = classList.concat(template.Classes._string.split(/\s+/));
|
|
|
|
|
|
|
|
|
|
if (template.VisibleClasses && template.VisibleClasses._string)
|
2014-05-22 09:20:36 -07:00
|
|
|
classList = classList.concat(template.VisibleClasses._string.split(/\s+/));
|
2014-05-22 03:20:02 -07:00
|
|
|
|
|
|
|
|
if (template.Rank)
|
|
|
|
|
classList = classList.concat(template.Rank);
|
|
|
|
|
return classList;
|
2012-11-07 09:56:14 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2014-05-22 03:20:02 -07:00
|
|
|
* Gets an array with all classes for this identity template
|
|
|
|
|
* that should be shown in the GUI
|
2012-11-07 09:56:14 -08:00
|
|
|
*/
|
2014-05-22 03:20:02 -07:00
|
|
|
function GetVisibleIdentityClasses(template)
|
2012-11-07 09:56:14 -08:00
|
|
|
{
|
2014-05-22 03:20:02 -07:00
|
|
|
if (template.VisibleClasses && template.VisibleClasses._string)
|
|
|
|
|
return template.VisibleClasses._string.split(/\s+/);
|
|
|
|
|
return [];
|
2012-11-07 09:56:14 -08:00
|
|
|
}
|
|
|
|
|
|
2014-06-05 02:39:36 -07:00
|
|
|
/**
|
|
|
|
|
* Check if the classes given in the identity template
|
|
|
|
|
* match a list of classes
|
|
|
|
|
* @param classes List of the classes to check against
|
2016-05-21 09:20:27 -07:00
|
|
|
* @param match Either a string in the form
|
2014-06-05 02:39:36 -07:00
|
|
|
* "Class1 Class2+Class3"
|
|
|
|
|
* where spaces are handled as OR and '+'-signs as AND,
|
2015-11-29 07:59:52 -08:00
|
|
|
* and ! is handled as NOT, thus Class1+!Class2 = Class1 AND NOT Class2
|
2014-06-05 02:39:36 -07:00
|
|
|
* 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+/);
|
2015-01-08 11:55:10 -08:00
|
|
|
|
2014-06-05 02:39:36 -07:00
|
|
|
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]+/);
|
2015-11-29 07:59:52 -08:00
|
|
|
if (sublist.every(c => (c[0] == "!" && classes.indexOf(c.substr(1)) == -1)
|
2015-11-29 08:13:13 -08:00
|
|
|
|| (c[0] != "!" && classes.indexOf(c) != -1)))
|
2014-06-05 02:39:36 -07:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2012-11-07 09:56:14 -08:00
|
|
|
|
2015-01-08 11:55:10 -08:00
|
|
|
/**
|
|
|
|
|
* Get information about a template with or without technology modifications.
|
2016-07-04 15:16:35 -07:00
|
|
|
*
|
|
|
|
|
* NOTICE: The data returned here should have the same structure as
|
|
|
|
|
* the object returned by GetEntityState and GetExtendedEntityState!
|
|
|
|
|
*
|
2015-01-08 11:55:10 -08:00
|
|
|
* @param template A valid template as returned by the template loader.
|
2016-04-04 11:55:44 -07:00
|
|
|
* @param player An optional player id to get the technology modifications
|
2015-01-08 11:55:10 -08:00
|
|
|
* of properties.
|
2016-04-09 09:00:42 -07:00
|
|
|
* @param auraTemplates An object in the form of {key: {auraName: "", auraDescription: ""}}
|
2016-11-19 06:29:45 -08:00
|
|
|
* @param resources An instance of the Resources prototype
|
2015-01-08 11:55:10 -08:00
|
|
|
*/
|
2016-11-19 06:29:45 -08:00
|
|
|
function GetTemplateDataHelper(template, player, auraTemplates, resources)
|
2015-01-08 11:55:10 -08:00
|
|
|
{
|
2016-07-04 15:16:35 -07:00
|
|
|
// Return data either from template (in tech tree) or sim state (ingame)
|
2016-06-29 19:12:26 -07:00
|
|
|
let getEntityValue = function(tech_type) {
|
|
|
|
|
|
|
|
|
|
let current_value = template;
|
|
|
|
|
for (let property of tech_type.split("/"))
|
|
|
|
|
current_value = current_value[property] || 0;
|
|
|
|
|
current_value = +current_value;
|
|
|
|
|
|
|
|
|
|
if (!player)
|
|
|
|
|
return current_value;
|
|
|
|
|
|
|
|
|
|
return ApplyValueModificationsToTemplate(tech_type, current_value, player, template);
|
|
|
|
|
};
|
2015-01-08 11:55:10 -08:00
|
|
|
|
2016-06-29 19:12:26 -07:00
|
|
|
let ret = {};
|
2015-01-08 11:55:10 -08:00
|
|
|
|
|
|
|
|
if (template.Armour)
|
|
|
|
|
ret.armour = {
|
2016-06-29 19:12:26 -07:00
|
|
|
"hack": getEntityValue("Armour/Hack"),
|
|
|
|
|
"pierce": getEntityValue("Armour/Pierce"),
|
|
|
|
|
"crush": getEntityValue("Armour/Crush")
|
2015-01-08 11:55:10 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (template.Attack)
|
|
|
|
|
{
|
|
|
|
|
ret.attack = {};
|
2015-04-20 00:45:45 -07:00
|
|
|
for (let type in template.Attack)
|
2015-01-08 11:55:10 -08:00
|
|
|
{
|
2016-07-02 21:08:52 -07:00
|
|
|
let getAttackStat = function(stat) {
|
|
|
|
|
return getEntityValue("Attack/" + type + "/" + stat);
|
|
|
|
|
};
|
|
|
|
|
|
2015-04-20 00:45:45 -07:00
|
|
|
if (type == "Capture")
|
|
|
|
|
ret.attack.Capture = {
|
2016-07-02 21:08:52 -07:00
|
|
|
"value": getAttackStat("Value")
|
2015-04-20 00:45:45 -07:00
|
|
|
};
|
|
|
|
|
else
|
2016-10-23 05:25:55 -07:00
|
|
|
{
|
2015-04-20 00:45:45 -07:00
|
|
|
ret.attack[type] = {
|
2016-07-02 21:08:52 -07:00
|
|
|
"hack": getAttackStat("Hack"),
|
|
|
|
|
"pierce": getAttackStat("Pierce"),
|
|
|
|
|
"crush": getAttackStat("Crush"),
|
|
|
|
|
"minRange": getAttackStat("MinRange"),
|
|
|
|
|
"maxRange": getAttackStat("MaxRange"),
|
|
|
|
|
"elevationBonus": getAttackStat("ElevationBonus")
|
|
|
|
|
};
|
2016-10-23 05:25:55 -07:00
|
|
|
ret.attack[type].elevationAdaptedRange = Math.sqrt(ret.attack[type].maxRange *
|
|
|
|
|
(2 * ret.attack[type].elevationBonus + ret.attack[type].maxRange));
|
|
|
|
|
}
|
2016-07-02 21:08:52 -07:00
|
|
|
ret.attack[type].repeatTime = getAttackStat("RepeatTime");
|
|
|
|
|
|
|
|
|
|
if (template.Attack[type].Splash)
|
|
|
|
|
ret.attack[type].splash = {
|
|
|
|
|
"hack": getAttackStat("Splash/Hack"),
|
|
|
|
|
"pierce": getAttackStat("Splash/Pierce"),
|
|
|
|
|
"crush": getAttackStat("Splash/Crush"),
|
|
|
|
|
// true if undefined
|
|
|
|
|
"friendlyFire": template.Attack[type].Splash.FriendlyFire != "false"
|
2015-04-20 00:45:45 -07:00
|
|
|
};
|
2015-01-08 11:55:10 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (template.Auras)
|
|
|
|
|
{
|
|
|
|
|
ret.auras = {};
|
2016-04-09 09:00:42 -07:00
|
|
|
for (let auraID of template.Auras._string.split(/\s+/))
|
2016-01-13 11:32:17 -08:00
|
|
|
{
|
2016-04-09 09:00:42 -07:00
|
|
|
let aura = auraTemplates[auraID];
|
2016-04-04 11:55:44 -07:00
|
|
|
if (aura.auraName)
|
2016-01-13 11:32:17 -08:00
|
|
|
ret.auras[auraID] = {
|
2016-07-04 15:16:35 -07:00
|
|
|
"name": aura.auraName,
|
2016-04-04 11:55:44 -07:00
|
|
|
"description": aura.auraDescription || null
|
2016-01-13 11:32:17 -08:00
|
|
|
};
|
|
|
|
|
}
|
2015-01-08 11:55:10 -08:00
|
|
|
}
|
|
|
|
|
|
2016-06-29 18:31:40 -07:00
|
|
|
if (template.BuildingAI)
|
2016-07-04 15:16:35 -07:00
|
|
|
ret.buildingAI = {
|
|
|
|
|
"defaultArrowCount": getEntityValue("BuildingAI/DefaultArrowCount"),
|
|
|
|
|
"garrisonArrowMultiplier": getEntityValue("BuildingAI/GarrisonArrowMultiplier"),
|
|
|
|
|
"maxArrowCount": getEntityValue("BuildingAI/MaxArrowCount")
|
|
|
|
|
};
|
2016-06-29 18:31:40 -07:00
|
|
|
|
2015-01-08 11:55:10 -08:00
|
|
|
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 = {
|
2016-05-11 02:35:52 -07:00
|
|
|
"fromClass": template.BuildRestrictions.Distance.FromClass,
|
2015-01-08 11:55:10 -08:00
|
|
|
};
|
2016-06-29 19:12:26 -07:00
|
|
|
|
|
|
|
|
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;
|
2015-01-08 11:55:10 -08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (template.TrainingRestrictions)
|
|
|
|
|
ret.trainingRestrictions = {
|
|
|
|
|
"category": template.TrainingRestrictions.Category,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (template.Cost)
|
|
|
|
|
{
|
|
|
|
|
ret.cost = {};
|
2016-11-19 06:29:45 -08:00
|
|
|
for (let resCode of resources.GetCodes())
|
|
|
|
|
if (template.Cost.Resources[resCode])
|
|
|
|
|
ret.cost[resCode] = getEntityValue("Cost/Resources/" + resCode);
|
2016-06-29 19:12:26 -07:00
|
|
|
|
|
|
|
|
if (template.Cost.Population)
|
|
|
|
|
ret.cost.population = getEntityValue("Cost/Population");
|
|
|
|
|
|
|
|
|
|
if (template.Cost.PopulationBonus)
|
|
|
|
|
ret.cost.populationBonus = getEntityValue("Cost/PopulationBonus");
|
|
|
|
|
|
|
|
|
|
if (template.Cost.BuildTime)
|
|
|
|
|
ret.cost.time = getEntityValue("Cost/BuildTime");
|
2015-01-08 11:55:10 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (template.Footprint)
|
|
|
|
|
{
|
2016-06-29 19:12:26 -07:00
|
|
|
ret.footprint = { "height": template.Footprint.Height };
|
2015-01-08 11:55:10 -08:00
|
|
|
|
|
|
|
|
if (template.Footprint.Square)
|
2016-06-29 19:12:26 -07:00
|
|
|
ret.footprint.square = {
|
|
|
|
|
"width": +template.Footprint.Square["@width"],
|
|
|
|
|
"depth": +template.Footprint.Square["@depth"]
|
|
|
|
|
};
|
2015-01-08 11:55:10 -08:00
|
|
|
else if (template.Footprint.Circle)
|
2016-06-29 19:12:26 -07:00
|
|
|
ret.footprint.circle = { "radius": +template.Footprint.Circle["@radius"] };
|
2015-01-08 11:55:10 -08:00
|
|
|
else
|
|
|
|
|
warn("GetTemplateDataHelper(): Unrecognized Footprint type");
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-29 18:31:40 -07:00
|
|
|
if (template.GarrisonHolder)
|
|
|
|
|
{
|
2016-07-19 06:19:37 -07:00
|
|
|
ret.garrisonHolder = {
|
|
|
|
|
"buffHeal": getEntityValue("GarrisonHolder/BuffHeal")
|
|
|
|
|
};
|
|
|
|
|
|
2016-06-29 18:31:40 -07:00
|
|
|
if (template.GarrisonHolder.Max)
|
2016-10-09 08:53:23 -07:00
|
|
|
ret.garrisonHolder.capacity = getEntityValue("GarrisonHolder/Max");
|
2016-06-29 18:31:40 -07:00
|
|
|
}
|
|
|
|
|
|
2016-07-01 06:32:34 -07:00
|
|
|
if (template.Heal)
|
|
|
|
|
ret.heal = {
|
|
|
|
|
"hp": getEntityValue("Heal/HP"),
|
|
|
|
|
"range": getEntityValue("Heal/Range"),
|
|
|
|
|
"rate": getEntityValue("Heal/Rate")
|
|
|
|
|
};
|
|
|
|
|
|
2016-09-18 18:21:09 -07:00
|
|
|
if (template.Loot)
|
|
|
|
|
{
|
|
|
|
|
ret.loot = {};
|
|
|
|
|
for (let type in template.Loot)
|
|
|
|
|
ret.loot[type] = getEntityValue("Loot/"+ type);
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-08 11:55:10 -08:00
|
|
|
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,
|
2016-06-29 19:12:26 -07:00
|
|
|
"time": getEntityValue("Pack/Time"),
|
2015-01-08 11:55:10 -08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if (template.Health)
|
2016-06-29 19:12:26 -07:00
|
|
|
ret.health = Math.round(getEntityValue("Health/Max"));
|
2015-01-08 11:55:10 -08:00
|
|
|
|
|
|
|
|
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.requiredTechnology = template.Identity.RequiredTechnology;
|
|
|
|
|
ret.visibleIdentityClasses = GetVisibleIdentityClasses(template.Identity);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (template.UnitMotion)
|
|
|
|
|
{
|
|
|
|
|
ret.speed = {
|
2016-06-29 19:12:26 -07:00
|
|
|
"walk": getEntityValue("UnitMotion/WalkSpeed"),
|
2015-01-08 11:55:10 -08:00
|
|
|
};
|
|
|
|
|
if (template.UnitMotion.Run)
|
2016-06-29 19:12:26 -07:00
|
|
|
ret.speed.run = getEntityValue("UnitMotion/Run/Speed");
|
2015-01-08 11:55:10 -08:00
|
|
|
}
|
|
|
|
|
|
2016-05-25 23:28:23 -07:00
|
|
|
if (template.ProductionQueue)
|
|
|
|
|
{
|
|
|
|
|
ret.techCostMultiplier = {};
|
|
|
|
|
for (let res in template.ProductionQueue.TechCostMultiplier)
|
2016-06-29 19:12:26 -07:00
|
|
|
ret.techCostMultiplier[res] = getEntityValue("ProductionQueue/TechCostMultiplier/" + res);
|
2016-05-25 23:28:23 -07:00
|
|
|
}
|
|
|
|
|
|
2015-01-08 11:55:10 -08:00
|
|
|
if (template.Trader)
|
2015-07-17 12:27:15 -07:00
|
|
|
ret.trader = {
|
2016-06-29 19:12:26 -07:00
|
|
|
"GainMultiplier": getEntityValue("Trader/GainMultiplier")
|
2015-07-17 12:27:15 -07:00
|
|
|
};
|
2016-05-21 09:20:27 -07:00
|
|
|
|
2015-01-08 11:55:10 -08:00
|
|
|
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)
|
2016-06-29 19:12:26 -07:00
|
|
|
ret.wallPiece = { "length": +template.WallPiece.Length };
|
2015-01-08 11:55:10 -08:00
|
|
|
|
|
|
|
|
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.
|
2016-11-19 06:29:45 -08:00
|
|
|
* @param resources An instance of the Resources prototype.
|
2015-01-08 11:55:10 -08:00
|
|
|
*/
|
2016-11-19 06:29:45 -08:00
|
|
|
function GetTechnologyDataHelper(template, civ, resources)
|
2015-01-08 11:55:10 -08:00
|
|
|
{
|
|
|
|
|
var ret = {};
|
|
|
|
|
|
2016-05-21 09:20:27 -07:00
|
|
|
// Get specific name for this civ or else the generic specific name
|
2016-06-29 19:12:26 -07:00
|
|
|
var specific;
|
2015-01-08 11:55:10 -08:00
|
|
|
if (template.specificName)
|
|
|
|
|
{
|
|
|
|
|
if (template.specificName[civ])
|
|
|
|
|
specific = template.specificName[civ];
|
|
|
|
|
else
|
|
|
|
|
specific = template.specificName['generic'];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret.name = {
|
|
|
|
|
"specific": specific,
|
|
|
|
|
"generic": template.genericName,
|
|
|
|
|
};
|
|
|
|
|
|
2016-06-29 19:12:26 -07:00
|
|
|
ret.icon = template.icon ? "technologies/" + template.icon : null;
|
|
|
|
|
|
2016-11-19 06:29:45 -08:00
|
|
|
ret.cost = { "time": template.researchTime ? +template.researchTime : 0 }
|
|
|
|
|
for (let type of resources.GetCodes())
|
|
|
|
|
ret.cost[type] = template.cost ? +template.cost[type] : 0;
|
2015-01-08 11:55:10 -08:00
|
|
|
|
2016-06-29 19:12:26 -07:00
|
|
|
ret.tooltip = template.tooltip;
|
|
|
|
|
ret.requirementsTooltip = template.requirementsTooltip || "";
|
2015-01-08 11:55:10 -08:00
|
|
|
|
2016-10-21 04:30:25 -07:00
|
|
|
// TODO: This doesn't handle all types of requirements
|
2015-01-08 11:55:10 -08:00
|
|
|
if (template.requirements && template.requirements.class)
|
2016-06-29 19:12:26 -07:00
|
|
|
ret.classRequirements = {
|
|
|
|
|
"class": template.requirements.class,
|
|
|
|
|
"number": template.requirements.number
|
|
|
|
|
};
|
2016-10-21 04:30:25 -07:00
|
|
|
else if (template.requirements && template.requirements.all)
|
|
|
|
|
for (let req of template.requirements.all)
|
|
|
|
|
if (req.class)
|
|
|
|
|
ret.classRequirements = {
|
|
|
|
|
"class": req.class,
|
|
|
|
|
"number": req.number
|
|
|
|
|
};
|
2015-01-08 11:55:10 -08:00
|
|
|
|
|
|
|
|
ret.description = template.description;
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
2016-09-18 18:21:09 -07:00
|
|
|
|
|
|
|
|
function calculateCarriedResources(carriedResources, tradingGoods)
|
|
|
|
|
{
|
|
|
|
|
var resources = {};
|
|
|
|
|
|
|
|
|
|
if (carriedResources)
|
|
|
|
|
for (let resource of carriedResources)
|
|
|
|
|
resources[resource.type] = (resources[resource.type] || 0) + resource.amount;
|
|
|
|
|
|
|
|
|
|
if (tradingGoods && tradingGoods.amount)
|
|
|
|
|
resources[tradingGoods.type] =
|
|
|
|
|
(resources[tradingGoods.type] || 0) +
|
|
|
|
|
(tradingGoods.amount.traderGain || 0) +
|
|
|
|
|
(tradingGoods.amount.market1Gain || 0) +
|
|
|
|
|
(tradingGoods.amount.market2Gain || 0);
|
|
|
|
|
|
|
|
|
|
return resources;
|
|
|
|
|
}
|
|
|
|
|
|