2017-12-30 17:02:21 -08:00
|
|
|
/**
|
|
|
|
|
* @file This provides a cache for Aura and Technology templates.
|
|
|
|
|
* They may not be serialized, otherwise rejoined clients would refer
|
|
|
|
|
* to different objects, triggering an Out-of-sync error.
|
|
|
|
|
*/
|
|
|
|
|
function ModificationTemplates(path)
|
|
|
|
|
{
|
2025-05-06 05:16:13 -07:00
|
|
|
const suffix = ".json";
|
2017-12-30 17:02:21 -08:00
|
|
|
|
|
|
|
|
this.names = deepfreeze(listFiles(path, suffix, true));
|
|
|
|
|
|
|
|
|
|
this.templates = {};
|
|
|
|
|
|
2025-05-06 05:16:13 -07:00
|
|
|
for (const name of this.names)
|
2017-12-30 17:02:21 -08:00
|
|
|
this.templates[name] = Engine.ReadJSONFile(path + name + suffix);
|
|
|
|
|
|
|
|
|
|
deepfreeze(this.templates);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ModificationTemplates.prototype.GetNames = function()
|
|
|
|
|
{
|
|
|
|
|
return this.names;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ModificationTemplates.prototype.Has = function(name)
|
|
|
|
|
{
|
|
|
|
|
return this.names.indexOf(name) != -1;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ModificationTemplates.prototype.Get = function(name)
|
|
|
|
|
{
|
|
|
|
|
return this.templates[name];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ModificationTemplates.prototype.GetAll = function()
|
|
|
|
|
{
|
|
|
|
|
return this.templates;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function LoadModificationTemplates()
|
|
|
|
|
{
|
|
|
|
|
global.AuraTemplates = new ModificationTemplates("simulation/data/auras/");
|
|
|
|
|
global.TechnologyTemplates = new ModificationTemplates("simulation/data/technologies/");
|
|
|
|
|
}
|
2020-01-27 08:51:25 -08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Derives modifications (to be applied to entities) from a given aura/technology.
|
|
|
|
|
*
|
|
|
|
|
* @param {Object} techTemplate - The aura/technology template to derive the modifications from.
|
|
|
|
|
* @return {Object} - An object containing the relevant modifications.
|
|
|
|
|
*/
|
|
|
|
|
function DeriveModificationsFromTech(techTemplate)
|
|
|
|
|
{
|
|
|
|
|
if (!techTemplate.modifications)
|
|
|
|
|
return {};
|
|
|
|
|
|
2025-05-06 05:16:13 -07:00
|
|
|
const techMods = {};
|
2020-01-27 08:51:25 -08:00
|
|
|
let techAffects = [];
|
|
|
|
|
if (techTemplate.affects && techTemplate.affects.length)
|
|
|
|
|
techAffects = techTemplate.affects.map(affected => affected.split(/\s+/));
|
|
|
|
|
else
|
|
|
|
|
techAffects.push([]);
|
|
|
|
|
|
2025-05-06 05:16:13 -07:00
|
|
|
for (const mod of techTemplate.modifications)
|
2020-01-27 08:51:25 -08:00
|
|
|
{
|
2025-05-06 05:16:13 -07:00
|
|
|
const affects = techAffects.slice();
|
2020-01-27 08:51:25 -08:00
|
|
|
if (mod.affects)
|
|
|
|
|
{
|
2025-05-06 05:16:13 -07:00
|
|
|
const specAffects = mod.affects.split(/\s+/);
|
|
|
|
|
for (const a in affects)
|
2020-01-27 08:51:25 -08:00
|
|
|
affects[a] = affects[a].concat(specAffects);
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-06 05:16:13 -07:00
|
|
|
const newModifier = { "affects": affects };
|
|
|
|
|
for (const idx in mod)
|
2020-01-27 08:51:25 -08:00
|
|
|
if (idx !== "value" && idx !== "affects")
|
|
|
|
|
newModifier[idx] = mod[idx];
|
|
|
|
|
|
|
|
|
|
if (!techMods[mod.value])
|
|
|
|
|
techMods[mod.value] = [];
|
|
|
|
|
techMods[mod.value].push(newModifier);
|
|
|
|
|
}
|
|
|
|
|
return techMods;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Derives modifications (to be applied to entities) from a provided array
|
|
|
|
|
* of aura/technology template data.
|
|
|
|
|
*
|
|
|
|
|
* @param {Object[]} techsDataArray
|
|
|
|
|
* @return {Object} - The combined relevant modifications of all the technologies.
|
|
|
|
|
*/
|
|
|
|
|
function DeriveModificationsFromTechnologies(techsDataArray)
|
|
|
|
|
{
|
|
|
|
|
if (!techsDataArray.length)
|
|
|
|
|
return {};
|
|
|
|
|
|
2025-05-06 05:16:13 -07:00
|
|
|
const derivedModifiers = {};
|
|
|
|
|
for (const technology of techsDataArray)
|
2020-01-27 08:51:25 -08:00
|
|
|
{
|
2021-06-08 16:35:44 -07:00
|
|
|
// Auras don't have a "reqs" property
|
|
|
|
|
if ('reqs' in technology && !technology.reqs)
|
2020-01-27 08:51:25 -08:00
|
|
|
continue;
|
|
|
|
|
|
2025-05-06 05:16:13 -07:00
|
|
|
const modifiers = DeriveModificationsFromTech(technology);
|
|
|
|
|
for (const modPath in modifiers)
|
2020-01-27 08:51:25 -08:00
|
|
|
{
|
|
|
|
|
if (!derivedModifiers[modPath])
|
|
|
|
|
derivedModifiers[modPath] = [];
|
|
|
|
|
derivedModifiers[modPath] = derivedModifiers[modPath].concat(modifiers[modPath]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return derivedModifiers;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Common definition of the XML schema for in-template modifications.
|
|
|
|
|
*/
|
|
|
|
|
const ModificationSchema =
|
2025-12-30 00:57:37 -08:00
|
|
|
"<interleave>" +
|
|
|
|
|
"<element name='Paths' a:help='Space separated value paths to modify.'>" +
|
|
|
|
|
"<attribute name='datatype'>" +
|
|
|
|
|
"<value>tokens</value>" +
|
|
|
|
|
"</attribute>" +
|
|
|
|
|
"<text/>" +
|
2020-01-27 08:51:25 -08:00
|
|
|
"</element>" +
|
2025-12-30 00:57:37 -08:00
|
|
|
"<element name='Affects' a:help='An array of classes to affect.'>" +
|
|
|
|
|
"<attribute name='datatype'>" +
|
|
|
|
|
"<value>tokens</value>" +
|
|
|
|
|
"</attribute>" +
|
2020-01-27 08:51:25 -08:00
|
|
|
"<text/>" +
|
|
|
|
|
"</element>" +
|
2025-12-30 00:57:37 -08:00
|
|
|
"<choice>" +
|
|
|
|
|
"<element name='Add'>" +
|
|
|
|
|
"<data type='decimal' />" +
|
|
|
|
|
"</element>" +
|
|
|
|
|
"<element name='Multiply'>" +
|
|
|
|
|
"<data type='decimal' />" +
|
|
|
|
|
"</element>" +
|
|
|
|
|
"<element name='Replace'>" +
|
|
|
|
|
"<text/>" +
|
|
|
|
|
"</element>" +
|
|
|
|
|
"</choice>" +
|
|
|
|
|
"</interleave>";
|
2020-01-27 08:51:25 -08:00
|
|
|
|
|
|
|
|
const ModificationsSchema =
|
2025-12-30 00:57:37 -08:00
|
|
|
"<element name='Modifiers' a:help='List of modifiers.'>" +
|
|
|
|
|
"<oneOrMore>" +
|
|
|
|
|
"<element>" +
|
|
|
|
|
"<anyName />" +
|
|
|
|
|
ModificationSchema +
|
|
|
|
|
"</element>" +
|
|
|
|
|
"</oneOrMore>" +
|
|
|
|
|
"</element>";
|
2020-01-27 08:51:25 -08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Derives a single modification (to be applied to entities) from a given XML template.
|
|
|
|
|
*
|
|
|
|
|
* @param {Object} techTemplate - The XML template node to derive the modification from.
|
|
|
|
|
* @return {Object} containing the relevant modification.
|
|
|
|
|
*/
|
|
|
|
|
function DeriveModificationFromXMLTemplate(template)
|
|
|
|
|
{
|
2025-05-06 05:16:13 -07:00
|
|
|
const effect = {};
|
2020-01-27 08:51:25 -08:00
|
|
|
if (template.Add)
|
|
|
|
|
effect.add = +template.Add;
|
|
|
|
|
if (template.Multiply)
|
|
|
|
|
effect.multiply = +template.Multiply;
|
|
|
|
|
if (template.Replace)
|
|
|
|
|
effect.replace = template.Replace;
|
|
|
|
|
effect.affects = template.Affects ? template.Affects._string.split(/\s/) : [];
|
|
|
|
|
|
2025-05-06 05:16:13 -07:00
|
|
|
const ret = {};
|
|
|
|
|
for (const path of template.Paths._string.split(/\s/))
|
2020-01-27 08:51:25 -08:00
|
|
|
{
|
|
|
|
|
ret[path] = [effect];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Derives all modifications (to be applied to entities) from a given XML template.
|
|
|
|
|
*
|
|
|
|
|
* @param {Object} techTemplate - The XML template node to derive the modifications from.
|
|
|
|
|
* @return {Object} containing the combined modifications.
|
|
|
|
|
*/
|
|
|
|
|
function DeriveModificationsFromXMLTemplate(template)
|
|
|
|
|
{
|
2025-05-06 05:16:13 -07:00
|
|
|
const ret = {};
|
|
|
|
|
for (const name in template)
|
2020-01-27 08:51:25 -08:00
|
|
|
{
|
2025-05-06 05:16:13 -07:00
|
|
|
const modification = DeriveModificationFromXMLTemplate(template[name]);
|
|
|
|
|
for (const path in modification)
|
2020-01-27 08:51:25 -08:00
|
|
|
{
|
|
|
|
|
if (!ret[path])
|
|
|
|
|
ret[path] = [];
|
|
|
|
|
ret[path].push(modification[path][0]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|