diff --git a/binaries/data/mods/public/simulation/components/AuraManager.js b/binaries/data/mods/public/simulation/components/AuraManager.js
new file mode 100644
index 0000000000..b546a9f535
--- /dev/null
+++ b/binaries/data/mods/public/simulation/components/AuraManager.js
@@ -0,0 +1,179 @@
+function AuraManager() {}
+
+AuraManager.prototype.Schema =
+ "";
+
+AuraManager.prototype.Init = function()
+{
+ this.modificationsCache = {};
+ this.modifications = {};
+ this.templateModificationsCache = {};
+ this.templateModifications = {};
+};
+
+AuraManager.prototype.ensureExists = function(name, value, id, key, defaultData)
+{
+ if (!this[name][value])
+ {
+ this[name][value] = {};
+ this[name+'Cache'][value] = {};
+ }
+
+ if (!this[name][value][id])
+ {
+ this[name][value][id] = {};
+ this[name+'Cache'][value][id] = defaultData;
+ }
+
+ if (!this[name][value][id][key])
+ this[name][value][id][key] = [];
+}
+
+AuraManager.prototype.ApplyBonus = function(value, ent, data, key)
+{
+ this.ensureExists("modifications", value, ent, key, {"add":0, "multiply":1});
+
+ this.modifications[value][ent][key].push(data);
+
+ if (this.modifications[value][ent][key].length > 1)
+ return;
+ // first time added this aura
+ if (data.multiply)
+ this.modificationsCache[value][ent].multiply *= data.multiply;
+
+ if (data.add)
+ this.modificationsCache[value][ent].add += data.add;
+
+ // post message to the entity to notify it about the change
+ // TODO MT_TechnologyModification expects a player ID, so we have to provide something.
+ // Use -1 until this is changed not to require one.
+ // This player info is not needed, as the message gets send to the correct entities immediately
+ // A better way of handling this would be to remove the player info from the message data.
+ var component = value.split("/")[0];
+ Engine.PostMessage(ent, MT_TechnologyModification, { "component": component, "player": -1 });
+};
+
+AuraManager.prototype.ApplyTemplateBonus = function(value, player, classes, data, key)
+{
+ this.ensureExists("templateModifications", value, player, key, {});
+
+ this.templateModifications[value][player][key].push(data);
+
+ if (this.templateModifications[value][player][key].length > 1)
+ return;
+
+ // first time added this aura
+ for each (var c in classes)
+ {
+ if (!this.templateModificationsCache[value][player][c])
+ this.templateModificationsCache[value][player][c] = [];
+
+ if (!this.templateModificationsCache[value][player][c][key])
+ this.templateModificationsCache[value][player][c][key] = { "add": 0, "multiply": 1};
+
+ if (data.multiply)
+ this.templateModificationsCache[value][player][c][key].multiply *= data.multiply;
+
+ if (data.add)
+ this.templateModificationsCache[value][player][c][key].add += data.add;
+
+ }
+
+ // post message to notify about the change
+ var component = value.split("/")[0];
+ Engine.BroadcastMessage(MT_TechnologyModification, { "component": component, "player": player});
+};
+
+AuraManager.prototype.RemoveBonus = function(value, ent, key)
+{
+ if (!this.modifications[value] ||
+ !this.modifications[value][ent] ||
+ !this.modifications[value][ent][key] ||
+ !this.modifications[value][ent][key].length)
+ return;
+
+ // get the applied data to remove again
+ var data = this.modifications[value][ent][key].pop();
+
+ if (this.modifications[value][ent][key].length > 0)
+ return;
+
+ // out of last aura of this kind, remove modifications
+ if (data.add)
+ this.modificationsCache[value][ent].add -= data.add;
+
+ if (data.multiply)
+ this.modificationsCache[value][ent].multiply /= data.multiply;
+
+ // post message to the entity to notify it about the change
+ // TODO MT_TechnologyModification expects a player ID, so we have to provide something.
+ // Use -1 until this is changed not to require one.
+ // This player info is not needed, as the message gets send to the correct entities immediately
+ // A better way of handling this would be to remove the player info from the message data.
+ var component = value.split("/")[0];
+ Engine.PostMessage(ent, MT_TechnologyModification, { "component": component, "player": -1 });
+};
+
+AuraManager.prototype.RemoveTemplateBonus = function(value, player, classes, key)
+{
+ if (!this.templateModifications[value] ||
+ !this.templateModifications[value][player] ||
+ !this.templateModifications[value][player][key] ||
+ !this.templateModifications[value][player][key].length)
+ return;
+
+ this.templateModifications[value][player][key].pop();
+
+ if (this.templateModifications[value][player][key].length > 0)
+ return;
+
+ for each (var c in classes)
+ {
+ this.templateModificationsCache[value][player][c][key].multiply = 1;
+ this.templateModificationsCache[value][player][c][key].add = 0;
+ }
+
+ // post message to notify about the change
+ var component = value.split("/")[0];
+ Engine.BroadcastMessage(MT_TechnologyModification, { "component": component, "player": player });
+};
+
+AuraManager.prototype.ApplyModifications = function(valueName, value, ent)
+{
+ if (!this.modificationsCache[valueName] || !this.modificationsCache[valueName][ent])
+ return value;
+
+ value *= this.modificationsCache[valueName][ent].multiply;
+ value += this.modificationsCache[valueName][ent].add;
+ return value;
+};
+
+AuraManager.prototype.ApplyTemplateModifications = function(valueName, value, player, template)
+{
+ if (!this.templateModificationsCache[valueName] || !this.templateModificationsCache[valueName][player])
+ return value;
+
+ var classes = template.Identity.Classes._string.split(/\s+/);
+
+ var keyList = [];
+
+ for (var c in this.templateModificationsCache[valueName][player])
+ {
+ if (classes.indexOf(c) == -1)
+ continue;
+
+ for (var key in this.templateModificationsCache[valueName][player][c])
+ {
+ // don't add an aura with the same key twice
+ if (keyList.indexOf(key) != -1)
+ continue;
+
+ value *= this.templateModificationsCache[valueName][player][c][key].multiply;
+ value += this.templateModificationsCache[valueName][player][c][key].add;
+ keyList.push(key);
+ }
+ }
+ return value;
+};
+
+Engine.RegisterComponentType(IID_AuraManager, "AuraManager", AuraManager);
diff --git a/binaries/data/mods/public/simulation/components/Auras.js b/binaries/data/mods/public/simulation/components/Auras.js
index ab64d10c95..9cecb8132d 100644
--- a/binaries/data/mods/public/simulation/components/Auras.js
+++ b/binaries/data/mods/public/simulation/components/Auras.js
@@ -2,41 +2,362 @@ function Auras() {}
Auras.prototype.Schema =
"" +
- "" +
- "" +
- "Allure" +
- "Infidelity" +
- "Heal" +
- "Courage" +
- "Fear" +
- "" +
- "" +
- "" +
+ "" +
+ "" +
+ "" +
+ "" +
"" +
"" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
+ "" +
+ "" +
+ "" +
+ "formation" +
+ "range" +
+ "garrison" +
+ "global" +
+ "" +
+ "" +
"" +
"";
-/*
- * TODO: this all needs to be designed and implemented
- */
+Auras.prototype.Init = function()
+{
+ var cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
+ this.templateName = cmpTemplateManager.GetCurrentTemplateName(this.entity);
+ var auraNames = this.GetAuraNames();
+ this.auras = {};
+ var cmpTechnologyTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TechnologyTemplateManager);
+ for each (var name in auraNames)
+ this.auras[name] = cmpTechnologyTemplateManager.GetAuraTemplate(name);
+};
-Auras.prototype.Serialize = null; // we have no dynamic state to save
+Auras.prototype.GetAuraNames = function()
+{
+ return Object.keys(this.template);
+};
+
+Auras.prototype.GetRange = function(name)
+{
+ if (!this.IsRangeAura(name))
+ return undefined;
+ if (this.IsGlobalAura(name))
+ return -1; // -1 is infinite range
+ return +this.template[name].Radius;
+};
+
+Auras.prototype.GetClasses = function(name)
+{
+ return this.auras[name].affects;
+};
+
+Auras.prototype.GetModifications = function(name)
+{
+ return this.auras[name].modifications;
+};
+
+Auras.prototype.GetAffectedPlayers = function(name)
+{
+ if (this.auras[name].affectedPlayers)
+ var affectedPlayers = this.auras[name].affectedPlayers;
+ else
+ var affectedPlayers = ["Player"];
+
+ var ret = [];
+
+ var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
+
+ if (!cmpPlayer)
+ return ret;
+
+ var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
+ var numPlayers = cmpPlayerManager.GetNumPlayers();
+
+ for (var i = 0; i < numPlayers; ++i)
+ {
+ for each (var p in affectedPlayers)
+ {
+ if (p == "Player" ? cmpPlayer.GetPlayerID() == i : cmpPlayer["Is" + p](i))
+ {
+ ret.push(i);
+ break;
+ }
+ }
+ }
+ return ret;
+};
+
+Auras.prototype.HasFormationAura = function()
+{
+ return this.GetAuraNames().some(this.IsFormationAura.bind(this));
+};
+
+Auras.prototype.HasGarrisonAura = function()
+{
+ return this.GetAuraNames().some(this.IsGarrisonAura.bind(this));
+};
+
+Auras.prototype.GetType = function(name)
+{
+ return this.template[name].Type;
+};
+
+Auras.prototype.IsFormationAura = function(name)
+{
+ return this.GetType(name) == "Formation";
+};
+
+Auras.prototype.IsGarrisonAura = function(name)
+{
+ return this.GetType(name) == "GarrisoningStructure";
+};
+
+Auras.prototype.IsRangeAura = function(name)
+{
+ // A global aura is also treated as a range aura with infinite range.
+ return ["range", "global"].indexOf(this.GetType(name)) != -1;
+};
+
+Auras.prototype.IsGlobalAura = function(name)
+{
+ return this.GetType(name) == "global";
+};
+
+/**
+ * clean all bonuses. Remove the old ones and re-apply the new ones
+ */
+Auras.prototype.Clean = function()
+{
+ var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
+ var auraNames = this.GetAuraNames();
+ // remove all bonuses
+ for each (var name in auraNames)
+ {
+ if (!this[name])
+ continue;
+
+ if (this.IsGlobalAura(name))
+ this.RemoveTemplateBonus(name);
+
+ for each(var ent in this[name].targetUnits)
+ this.RemoveBonus(name, ent);
+
+ if (this[name].rangeQuery)
+ cmpRangeManager.DestroyActiveQuery(this[name].rangeQuery);
+ }
+
+ for each (var name in auraNames)
+ {
+ // initialise range query
+ this[name] = {};
+ this[name].targetUnits = [];
+ var affectedPlayers = this.GetAffectedPlayers(name);
+
+ if (!affectedPlayers.length)
+ continue;
+
+ if (this.IsGlobalAura(name))
+ this.ApplyTemplateBonus(name, affectedPlayers);
+
+ if (!this.IsRangeAura(name))
+ continue;
+ this[name].rangeQuery = cmpRangeManager.CreateActiveQuery(
+ this.entity,
+ 0,
+ this.GetRange(name),
+ affectedPlayers,
+ IID_Identity,
+ cmpRangeManager.GetEntityFlagMask("normal")
+ );
+ cmpRangeManager.EnableActiveQuery(this[name].rangeQuery);
+ // Add self to your own query for consistency with templates.
+ this.OnRangeUpdate({"tag":this[name].rangeQuery, "added":[this.entity], "removed":[]});
+ }
+};
+
+Auras.prototype.GiveMembersWithValidClass = function(auraName, entityList)
+{
+ var validClasses = this.GetClasses(auraName);
+ var r = [];
+ for each (var ent in entityList)
+ {
+ var cmpIdentity = Engine.QueryInterface(ent, IID_Identity);
+ var targetClasses = cmpIdentity.GetClassesList();
+ for each (var classCollection in validClasses)
+ {
+ if (classCollection.split(/\s+/).every(function(c) {return targetClasses.indexOf(c) > -1}))
+ {
+ r.push(ent);
+ break;
+ }
+ }
+ }
+ return r;
+}
+
+Auras.prototype.OnRangeUpdate = function(msg)
+{
+ var auraNames = this.GetAuraNames();
+ for each (var n in auraNames)
+ {
+ if (msg.tag == this[n].rangeQuery)
+ {
+ var name = n;
+ break;
+ }
+ }
+
+ if (!name)
+ return;
+
+ var targetUnits = this[name].targetUnits;
+ var classes = this.GetClasses(name);
+
+ if (msg.added.length > 0)
+ {
+ var validList = this.GiveMembersWithValidClass(name, msg.added);
+ for each (var e in validList)
+ {
+ targetUnits.push(e);
+ this.ApplyBonus(name, e);
+ }
+ }
+
+ if (msg.removed.length > 0)
+ {
+ for each (var e in msg.removed)
+ {
+ targetUnits.splice(targetUnits.indexOf(e), 1);
+ this.RemoveBonus(name, e);
+ }
+ }
+
+};
+
+Auras.prototype.ApplyFormationBonus = function(memberList)
+{
+ var auraNames = this.GetAuraNames();
+ for each (var name in auraNames)
+ {
+ if (!this.IsFormationAura(name))
+ continue;
+
+ var validList = this.GiveMembersWithValidClass(name, memberList);
+ for each (var ent in validList)
+ {
+ targetUnits.push(e);
+ this.ApplyBonus(name,e);
+ }
+ }
+};
+
+Auras.prototype.ApplyGarrisonBonus = function(structure)
+{
+ var auraNames = this.GetAuraNames();
+ for each (var name in auraNames)
+ {
+ if (!this.IsGarrisonAura(name))
+ continue;
+
+ var validList = this.GiveMembersWithValidClass(name, [structure]);
+ if (validList.length)
+ {
+ targetUnits.push(validList[0]);
+ this.ApplyBonus(name,validList[0]);
+ }
+ }
+};
+
+Auras.prototype.ApplyTemplateBonus = function(name, players)
+{
+ if (!this.IsGlobalAura(name))
+ return;
+ var modifications = this.GetModifications(name);
+ var cmpAuraManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_AuraManager);
+ var classes = this.GetClasses(name);
+
+ for each (var mod in modifications)
+ for each (var player in players)
+ cmpAuraManager.ApplyTemplateBonus(mod.value, player, classes, mod, this.templateName + "/" + name + "/" + mod.value);
+};
+
+Auras.prototype.RemoveFormationBonus = function(memberList)
+{
+ var auraNames = this.GetAuraNames();
+ for each (var name in auraName)
+ {
+ if (!this.IsFormationAura(name))
+ continue;
+
+ for each (var ent in memberList)
+ {
+ this.RemoveBonus(name,ent);
+ this[name].targetUnits.splice(this[name].targetUnits.indexOf(ent), 1);
+ }
+ }
+};
+
+Auras.prototype.RemoveGarrisonBonus = function(structure)
+{
+ var auraNames = this.GetAuraNames();
+ for each (var name in auraNames)
+ {
+ if (!this.IsGarrisonAura(name))
+ continue;
+
+ this.RemoveBonus(name,structure);
+ this[name].targetUnits.splice(this[name].targetUnits.indexOf(structure), 1);
+ }
+};
+
+Auras.prototype.RemoveTemplateBonus = function(name)
+{
+ if (!this.IsGlobalAura(name))
+ return;
+
+ var modifications = this.GetModifications(name);
+ var cmpAuraManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_AuraManager);
+ var classes = this.GetClasses(name);
+
+ for each (var mod in modifications)
+ for each (var player in this.GetAffectedPlayers())
+ cmpAuraManager.RemoveTemplateBonus(mod.value, player, classes, this.templateName + "/" + name + "/" + mod.value);
+};
+
+Auras.prototype.ApplyBonus = function(name, ent)
+{
+ var modifications = this.GetModifications(name);
+ var cmpAuraManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_AuraManager);
+
+ for each (mod in modifications)
+ cmpAuraManager.ApplyBonus(mod.value, ent, mod, this.templateName + "/" + name + "/" + mod.value);
+
+};
+
+Auras.prototype.RemoveBonus = function(name, ent)
+{
+ var modifications = this.GetModifications(name);
+ var cmpAuraManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_AuraManager);
+
+ for each (mod in modifications)
+ cmpAuraManager.RemoveBonus(mod.value, ent, this.templateName + "/" + name + "/" + mod.value);
+};
+
+Auras.prototype.OnOwnershipChanged = function(msg)
+{
+ this.Clean();
+};
+
+Auras.prototype.OnDiplomacyChanged = function(msg)
+{
+ var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
+ if (cmpOwnership && cmpOwnership.GetOwner() == msg.player)
+ this.Clean();
+};
+
+Auras.prototype.OnTechnologyModification = function(msg)
+{
+ if (msg.component =="Auras")
+ this.Clean();
+};
Engine.RegisterComponentType(IID_Auras, "Auras", Auras);
diff --git a/binaries/data/mods/public/simulation/components/Formation.js b/binaries/data/mods/public/simulation/components/Formation.js
index 8f98f3afc5..0378c7d33b 100644
--- a/binaries/data/mods/public/simulation/components/Formation.js
+++ b/binaries/data/mods/public/simulation/components/Formation.js
@@ -12,6 +12,7 @@ Formation.prototype.Init = function()
this.columnar = false; // whether we're travelling in column (vs box) formation
this.formationName = "Line Closed";
this.rearrange = true; // whether we should rearrange all formation members
+ this.formationMemebersWithAura = []; // Members with a formation aura
};
Formation.prototype.GetMemberCount = function()
@@ -86,12 +87,20 @@ Formation.prototype.SetMembers = function(ents)
{
var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
cmpUnitAI.SetFormationController(this.entity);
+
+ var cmpAuras = Engine.QueryInterface(ent, IID_Auras);
+ if (cmpAuras && cmpAuras.HasFormationAura())
+ {
+ this.formationMemebersWithAura.push(ent);
+ cmpAuras.ApplyFormationBonus(ents);
+ }
}
// Locate this formation controller in the middle of its members
this.MoveToMembersCenter();
this.ComputeMotionParameters();
+
};
/**
@@ -109,6 +118,18 @@ Formation.prototype.RemoveMembers = function(ents)
cmpUnitAI.SetFormationController(INVALID_ENTITY);
}
+ for each (var ent in this.formationMemebersWithAura)
+ {
+ var cmpAuras = Engine.QueryInterface(ent, IID_Auras);
+ cmpAuras.RemoveFormationBonus(ents);
+
+ // the unit with the aura is also removed from the formation
+ if (ents.indexOf(ent) !== -1)
+ cmpAuras.RemoveFormationBonus(this.members);
+ }
+
+ this.formationMemebersWithAura = this.formationMemebersWithAura.filter(function(e) { return ents.indexOf(e) == -1; });
+
// If there's nobody left, destroy the formation
if (this.members.length == 0)
{
@@ -155,8 +176,16 @@ Formation.prototype.Disband = function()
cmpUnitAI.SetFormationController(INVALID_ENTITY);
}
+ for each (var ent in this.formationMemebersWithAura)
+ {
+ var cmpAuras = Engine.QueryInterface(ent, IID_Auras);
+ cmpAuras.RemoveFormationBonus(this.members);
+ }
+
+
this.members = [];
this.inPosition = [];
+ this.formationMemebersWithAura = [];
Engine.DestroyEntity(this.entity);
};
diff --git a/binaries/data/mods/public/simulation/components/GarrisonHolder.js b/binaries/data/mods/public/simulation/components/GarrisonHolder.js
index 941875b10e..7093576a3e 100644
--- a/binaries/data/mods/public/simulation/components/GarrisonHolder.js
+++ b/binaries/data/mods/public/simulation/components/GarrisonHolder.js
@@ -185,6 +185,10 @@ GarrisonHolder.prototype.Garrison = function(entity)
if (cmpProductionQueue)
cmpProductionQueue.PauseProduction();
+ var cmpAura = Engine.QueryInterface(entity, IID_Auras);
+ if (cmpAura && cmpAura.HasGarrisonAura())
+ cmpAura.ApplyGarrisonBonus(this.entity);
+
Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, {});
return true;
};
@@ -228,6 +232,11 @@ GarrisonHolder.prototype.Eject = function(entity, forced)
var cmpProductionQueue = Engine.QueryInterface(entity, IID_ProductionQueue);
if (cmpProductionQueue)
cmpProductionQueue.UnpauseProduction();
+
+ var cmpAura = Engine.QueryInterface(entity, IID_Auras);
+ if (cmpAura && cmpAura.HasGarrisonAura())
+ cmpAura.RemoveGarrisonBonus(this.entity);
+
var cmpNewPosition = Engine.QueryInterface(entity, IID_Position);
cmpNewPosition.JumpTo(pos.x, pos.z);
diff --git a/binaries/data/mods/public/simulation/components/TechnologyTemplateManager.js b/binaries/data/mods/public/simulation/components/TechnologyTemplateManager.js
index dff5f1725f..2d29862513 100644
--- a/binaries/data/mods/public/simulation/components/TechnologyTemplateManager.js
+++ b/binaries/data/mods/public/simulation/components/TechnologyTemplateManager.js
@@ -9,6 +9,7 @@ TechnologyTemplateManager.prototype.Schema =
TechnologyTemplateManager.prototype.Init = function()
{
this.allTechs = {};
+ this.allAuras = {};
var techNames = this.ListAllTechs();
for (var i in techNames)
this.GetTemplate(techNames[i]);
@@ -26,6 +27,18 @@ TechnologyTemplateManager.prototype.GetTemplate = function(template)
return this.allTechs[template];
};
+TechnologyTemplateManager.prototype.GetAuraTemplate = function(template)
+{
+ if (!this.allAuras[template])
+ {
+ this.allAuras[template] = Engine.ReadJSONFile("auras/" + template + ".json");
+ if (! this.allAuras[template])
+ error("Failed to load aura \"" + template + "\"");
+ }
+
+ return this.allAuras[template];
+};
+
TechnologyTemplateManager.prototype.ListAllTechs = function()
{
return Engine.FindJSONFiles("technologies", true);
diff --git a/binaries/data/mods/public/simulation/components/interfaces/AuraManager.js b/binaries/data/mods/public/simulation/components/interfaces/AuraManager.js
new file mode 100644
index 0000000000..929a56d0a5
--- /dev/null
+++ b/binaries/data/mods/public/simulation/components/interfaces/AuraManager.js
@@ -0,0 +1 @@
+Engine.RegisterInterface("AuraManager");
diff --git a/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js b/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
index 1d3c0fa3ce..ee322e45ca 100644
--- a/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
+++ b/binaries/data/mods/public/simulation/components/tests/test_UnitAI.js
@@ -2,6 +2,7 @@ Engine.LoadHelperScript("FSM.js");
Engine.LoadHelperScript("Entity.js");
Engine.LoadHelperScript("Player.js");
Engine.LoadComponentScript("interfaces/Attack.js");
+Engine.LoadComponentScript("interfaces/Auras.js");
Engine.LoadComponentScript("interfaces/DamageReceiver.js");
Engine.LoadComponentScript("interfaces/Formation.js");
Engine.LoadComponentScript("interfaces/Heal.js");
diff --git a/binaries/data/mods/public/simulation/data/auras/heal.json b/binaries/data/mods/public/simulation/data/auras/heal.json
new file mode 100644
index 0000000000..c76dd691cd
--- /dev/null
+++ b/binaries/data/mods/public/simulation/data/auras/heal.json
@@ -0,0 +1,5 @@
+{
+ "affects":["Unit"],
+ "affectedPlayers":["Player"],
+ "modifications":[{"value":"Health/RegenRate","add":1}]
+}
diff --git a/binaries/data/mods/public/simulation/helpers/Technology.js b/binaries/data/mods/public/simulation/helpers/Technology.js
index 31f1851318..45a50e1400 100644
--- a/binaries/data/mods/public/simulation/helpers/Technology.js
+++ b/binaries/data/mods/public/simulation/helpers/Technology.js
@@ -3,11 +3,15 @@
function ApplyTechModificationsToEntity(tech_type, current_value, entity)
{
var cmpTechMan = QueryOwnerInterface(entity, IID_TechnologyManager);
+ if (cmpTechMan)
+ var value = cmpTechMan.ApplyModificationsTemplate(tech_type, current_value, entity);
+ else
+ var value = current_value;
- if (!cmpTechMan)
- return current_value;
-
- return cmpTechMan.ApplyModifications(tech_type, current_value, entity);
+ var cmpAuraManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_AuraManager);
+ if (!cmpAuraManager)
+ return value;
+ return cmpAuraManager.ApplyModifications(tech_type, value, entity);
}
function ApplyTechModificationsToPlayer(tech_type, current_value, player_entity)
@@ -23,11 +27,15 @@ function ApplyTechModificationsToPlayer(tech_type, current_value, player_entity)
function ApplyTechModificationsToTemplate(tech_type, current_value, playerID, template)
{
var cmpTechMan = QueryPlayerIDInterface(playerID, IID_TechnologyManager);
+ if (cmpTechMan)
+ var value = cmpTechMan.ApplyModificationsTemplate(tech_type, current_value, template);
+ else
+ var value = current_value;
- if (!cmpTechMan)
- return current_value;
-
- return cmpTechMan.ApplyModificationsTemplate(tech_type, current_value, template);
+ var cmpAuraManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_AuraManager);
+ if (!cmpAuraManager)
+ return value;
+ return cmpAuraManager.ApplyTemplateModifications(tech_type, value, playerID, template);
}
Engine.RegisterGlobal("ApplyTechModificationsToEntity", ApplyTechModificationsToEntity);
diff --git a/binaries/data/mods/public/simulation/templates/campaigns/army_mace_hero_alexander.xml b/binaries/data/mods/public/simulation/templates/campaigns/army_mace_hero_alexander.xml
index 63a0debc12..09cfc010b9 100644
--- a/binaries/data/mods/public/simulation/templates/campaigns/army_mace_hero_alexander.xml
+++ b/binaries/data/mods/public/simulation/templates/campaigns/army_mace_hero_alexander.xml
@@ -8,12 +8,6 @@
7.0
-
-
- 80
- 15
-
-
300
diff --git a/binaries/data/mods/public/simulation/templates/gaia/fauna_chicken.xml b/binaries/data/mods/public/simulation/templates/gaia/fauna_chicken.xml
index 8ac2d267b3..32a6cba706 100644
--- a/binaries/data/mods/public/simulation/templates/gaia/fauna_chicken.xml
+++ b/binaries/data/mods/public/simulation/templates/gaia/fauna_chicken.xml
@@ -15,7 +15,7 @@
40
food.meat
- 5
+ 5
diff --git a/binaries/data/mods/public/simulation/templates/other/celt_tavern.xml b/binaries/data/mods/public/simulation/templates/other/celt_tavern.xml
index bd0faa8e94..73ce748fa2 100644
--- a/binaries/data/mods/public/simulation/templates/other/celt_tavern.xml
+++ b/binaries/data/mods/public/simulation/templates/other/celt_tavern.xml
@@ -1,11 +1,5 @@
-
-
- 30
- 1000
-
-
10
200
diff --git a/binaries/data/mods/public/simulation/templates/structures/gaul_tavern.xml b/binaries/data/mods/public/simulation/templates/structures/gaul_tavern.xml
index 74f861ad88..92e74bcb4d 100644
--- a/binaries/data/mods/public/simulation/templates/structures/gaul_tavern.xml
+++ b/binaries/data/mods/public/simulation/templates/structures/gaul_tavern.xml
@@ -1,11 +1,5 @@
-
-
- 30
- 1000
-
-
10
200
diff --git a/binaries/data/mods/public/simulation/templates/template_structure_civic_temple.xml b/binaries/data/mods/public/simulation/templates/template_structure_civic_temple.xml
index 6a850e9833..fd9371c37e 100644
--- a/binaries/data/mods/public/simulation/templates/template_structure_civic_temple.xml
+++ b/binaries/data/mods/public/simulation/templates/template_structure_civic_temple.xml
@@ -1,10 +1,10 @@
-
+
+ range
40
- 1000
-
+
Temple
@@ -34,7 +34,7 @@
Temple
- Train healers. Garrison up to 20 units to heal them at a quick rate. Research healing and religious improvements.
+ Train healers. Garrison up to 20 units to heal them at a quick rate. Research healing and religious improvements. Heals nearby units, but slower than garrisoned units.
Town
Temple
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_fauna_breed.xml b/binaries/data/mods/public/simulation/templates/template_unit_fauna_breed.xml
index ccec40f8a7..4aa0c5b59e 100644
--- a/binaries/data/mods/public/simulation/templates/template_unit_fauna_breed.xml
+++ b/binaries/data/mods/public/simulation/templates/template_unit_fauna_breed.xml
@@ -1,11 +1,5 @@
-
-
- 20
-
-
-
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_fauna_herd.xml b/binaries/data/mods/public/simulation/templates/template_unit_fauna_herd.xml
index daf7ae86a8..abe15e74fe 100644
--- a/binaries/data/mods/public/simulation/templates/template_unit_fauna_herd.xml
+++ b/binaries/data/mods/public/simulation/templates/template_unit_fauna_herd.xml
@@ -1,11 +1,5 @@
-
-
- 20
-
-
-
remain
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_support_female_citizen.xml b/binaries/data/mods/public/simulation/templates/template_unit_support_female_citizen.xml
index 592508b1fd..9c8348c114 100644
--- a/binaries/data/mods/public/simulation/templates/template_unit_support_female_citizen.xml
+++ b/binaries/data/mods/public/simulation/templates/template_unit_support_female_citizen.xml
@@ -16,15 +16,6 @@
4.0
-
-
- 25
-
-
- 10
-
-
-
1.0
diff --git a/binaries/data/mods/public/simulation/templates/units/athen_hero_iphicrates.xml b/binaries/data/mods/public/simulation/templates/units/athen_hero_iphicrates.xml
index 77e7f6a7be..f44b84beb3 100644
--- a/binaries/data/mods/public/simulation/templates/units/athen_hero_iphicrates.xml
+++ b/binaries/data/mods/public/simulation/templates/units/athen_hero_iphicrates.xml
@@ -1,11 +1,5 @@
-
-
- 20
- 5
-
-
athen
Iphicrates
diff --git a/binaries/data/mods/public/simulation/templates/units/athen_hero_pericles.xml b/binaries/data/mods/public/simulation/templates/units/athen_hero_pericles.xml
index e67c4cc8e4..7fb1fa6709 100644
--- a/binaries/data/mods/public/simulation/templates/units/athen_hero_pericles.xml
+++ b/binaries/data/mods/public/simulation/templates/units/athen_hero_pericles.xml
@@ -1,11 +1,5 @@
-
-
- 20
- 5
-
-
athen
Pericles
diff --git a/binaries/data/mods/public/simulation/templates/units/athen_hero_themistocles.xml b/binaries/data/mods/public/simulation/templates/units/athen_hero_themistocles.xml
index 393e8c9272..e72a3eb405 100644
--- a/binaries/data/mods/public/simulation/templates/units/athen_hero_themistocles.xml
+++ b/binaries/data/mods/public/simulation/templates/units/athen_hero_themistocles.xml
@@ -1,11 +1,5 @@
-
-
- 20
- 5
-
-
athen
Themistocles
diff --git a/binaries/data/mods/public/simulation/templates/units/brit_hero_boudicca.xml b/binaries/data/mods/public/simulation/templates/units/brit_hero_boudicca.xml
index 7e8feece17..3935e443ab 100644
--- a/binaries/data/mods/public/simulation/templates/units/brit_hero_boudicca.xml
+++ b/binaries/data/mods/public/simulation/templates/units/brit_hero_boudicca.xml
@@ -5,12 +5,6 @@
7
8
-
-
- 20
- 5
-
-
4
50
diff --git a/binaries/data/mods/public/simulation/templates/units/brit_hero_boudicca_sword.xml b/binaries/data/mods/public/simulation/templates/units/brit_hero_boudicca_sword.xml
index dcc86f43e5..8acf2ea553 100644
--- a/binaries/data/mods/public/simulation/templates/units/brit_hero_boudicca_sword.xml
+++ b/binaries/data/mods/public/simulation/templates/units/brit_hero_boudicca_sword.xml
@@ -5,12 +5,6 @@
6
6
-
-
- 20
- 5
-
-
brit
Boudicca
diff --git a/binaries/data/mods/public/simulation/templates/units/brit_hero_caratacos.xml b/binaries/data/mods/public/simulation/templates/units/brit_hero_caratacos.xml
index 9742868fad..d6df50ef05 100644
--- a/binaries/data/mods/public/simulation/templates/units/brit_hero_caratacos.xml
+++ b/binaries/data/mods/public/simulation/templates/units/brit_hero_caratacos.xml
@@ -13,12 +13,6 @@
54.0
-
-
- 20
- 5
-
-
brit
Caratacos
diff --git a/binaries/data/mods/public/simulation/templates/units/brit_hero_cynvelin.xml b/binaries/data/mods/public/simulation/templates/units/brit_hero_cynvelin.xml
index 8400f834a1..6d12de3152 100644
--- a/binaries/data/mods/public/simulation/templates/units/brit_hero_cynvelin.xml
+++ b/binaries/data/mods/public/simulation/templates/units/brit_hero_cynvelin.xml
@@ -3,12 +3,6 @@
10
-
-
- 25
- 1000
-
-
brit
Cynvelin
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_hero_boudicca.xml b/binaries/data/mods/public/simulation/templates/units/celt_hero_boudicca.xml
index ee8fcd078c..0a46359540 100644
--- a/binaries/data/mods/public/simulation/templates/units/celt_hero_boudicca.xml
+++ b/binaries/data/mods/public/simulation/templates/units/celt_hero_boudicca.xml
@@ -1,11 +1,5 @@
-
-
- 20
- 5
-
-
4
50
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_hero_brennus.xml b/binaries/data/mods/public/simulation/templates/units/celt_hero_brennus.xml
index baceecb8d9..70cfd60cad 100644
--- a/binaries/data/mods/public/simulation/templates/units/celt_hero_brennus.xml
+++ b/binaries/data/mods/public/simulation/templates/units/celt_hero_brennus.xml
@@ -3,12 +3,6 @@
9
-
-
- 20
- 5
-
-
celt
Brennus
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_hero_britomartus.xml b/binaries/data/mods/public/simulation/templates/units/celt_hero_britomartus.xml
index b14e92fa0e..a9826934b1 100644
--- a/binaries/data/mods/public/simulation/templates/units/celt_hero_britomartus.xml
+++ b/binaries/data/mods/public/simulation/templates/units/celt_hero_britomartus.xml
@@ -3,12 +3,6 @@
9
-
-
- 20
- 5
-
-
celt
Britomartus
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_hero_caratacos.xml b/binaries/data/mods/public/simulation/templates/units/celt_hero_caratacos.xml
index 6a5d99c61a..b0e85ba2d5 100644
--- a/binaries/data/mods/public/simulation/templates/units/celt_hero_caratacos.xml
+++ b/binaries/data/mods/public/simulation/templates/units/celt_hero_caratacos.xml
@@ -8,12 +8,6 @@
54.0
-
-
- 20
- 5
-
-
celt
Caratacos
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_hero_cynvelin.xml b/binaries/data/mods/public/simulation/templates/units/celt_hero_cynvelin.xml
index ca2886e8de..db32c089da 100644
--- a/binaries/data/mods/public/simulation/templates/units/celt_hero_cynvelin.xml
+++ b/binaries/data/mods/public/simulation/templates/units/celt_hero_cynvelin.xml
@@ -1,11 +1,5 @@
-
-
- 25
- 1000
-
-
celt
Cynvelin
diff --git a/binaries/data/mods/public/simulation/templates/units/celt_hero_vercingetorix.xml b/binaries/data/mods/public/simulation/templates/units/celt_hero_vercingetorix.xml
index af17ea15fb..fe8d156f40 100644
--- a/binaries/data/mods/public/simulation/templates/units/celt_hero_vercingetorix.xml
+++ b/binaries/data/mods/public/simulation/templates/units/celt_hero_vercingetorix.xml
@@ -8,12 +8,6 @@
54.0
-
-
- 20
- 5
-
-
260
diff --git a/binaries/data/mods/public/simulation/templates/units/gaul_hero_brennus.xml b/binaries/data/mods/public/simulation/templates/units/gaul_hero_brennus.xml
index adada01a8c..fbc0edffa1 100644
--- a/binaries/data/mods/public/simulation/templates/units/gaul_hero_brennus.xml
+++ b/binaries/data/mods/public/simulation/templates/units/gaul_hero_brennus.xml
@@ -3,12 +3,6 @@
7
-
-
- 20
- 5
-
-
gaul
Brennus
diff --git a/binaries/data/mods/public/simulation/templates/units/gaul_hero_britomartus.xml b/binaries/data/mods/public/simulation/templates/units/gaul_hero_britomartus.xml
index c618d610d3..8669dcacb4 100644
--- a/binaries/data/mods/public/simulation/templates/units/gaul_hero_britomartus.xml
+++ b/binaries/data/mods/public/simulation/templates/units/gaul_hero_britomartus.xml
@@ -3,12 +3,6 @@
9
-
-
- 20
- 5
-
-
gaul
Britomartus
diff --git a/binaries/data/mods/public/simulation/templates/units/gaul_hero_vercingetorix.xml b/binaries/data/mods/public/simulation/templates/units/gaul_hero_vercingetorix.xml
index a0220fea6e..b2e9967497 100644
--- a/binaries/data/mods/public/simulation/templates/units/gaul_hero_vercingetorix.xml
+++ b/binaries/data/mods/public/simulation/templates/units/gaul_hero_vercingetorix.xml
@@ -8,12 +8,6 @@
54.0
-
-
- 20
- 5
-
-
260
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_hero_alexander.xml b/binaries/data/mods/public/simulation/templates/units/hele_hero_alexander.xml
index 9156578f4f..4c71bf641a 100644
--- a/binaries/data/mods/public/simulation/templates/units/hele_hero_alexander.xml
+++ b/binaries/data/mods/public/simulation/templates/units/hele_hero_alexander.xml
@@ -3,12 +3,6 @@
20
-
-
- 80
- 15
-
-
300
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_hero_demetrius.xml b/binaries/data/mods/public/simulation/templates/units/hele_hero_demetrius.xml
index 251bd4d88f..290d5e6e5d 100644
--- a/binaries/data/mods/public/simulation/templates/units/hele_hero_demetrius.xml
+++ b/binaries/data/mods/public/simulation/templates/units/hele_hero_demetrius.xml
@@ -1,11 +1,5 @@
-
-
- 20
- 5
-
-
hele
Demetrius The Besieger
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_hero_leonidas.xml b/binaries/data/mods/public/simulation/templates/units/hele_hero_leonidas.xml
index 7ea6dc3758..9634b0461a 100644
--- a/binaries/data/mods/public/simulation/templates/units/hele_hero_leonidas.xml
+++ b/binaries/data/mods/public/simulation/templates/units/hele_hero_leonidas.xml
@@ -17,12 +17,6 @@
6.0
-
-
- 20
- 5
-
-
225
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_hero_philip.xml b/binaries/data/mods/public/simulation/templates/units/hele_hero_philip.xml
index e3ce0c8376..a9546ae7f1 100644
--- a/binaries/data/mods/public/simulation/templates/units/hele_hero_philip.xml
+++ b/binaries/data/mods/public/simulation/templates/units/hele_hero_philip.xml
@@ -1,11 +1,5 @@
-
-
- 20
- 5
-
-
hele
Philip II of Macedon
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_hero_themistocles.xml b/binaries/data/mods/public/simulation/templates/units/hele_hero_themistocles.xml
index 5ce61eca16..00421aa287 100644
--- a/binaries/data/mods/public/simulation/templates/units/hele_hero_themistocles.xml
+++ b/binaries/data/mods/public/simulation/templates/units/hele_hero_themistocles.xml
@@ -1,11 +1,5 @@
-
-
- 20
- 5
-
-
hele
Themistocles
diff --git a/binaries/data/mods/public/simulation/templates/units/hele_hero_xenophon.xml b/binaries/data/mods/public/simulation/templates/units/hele_hero_xenophon.xml
index 64fca894a1..c0aee5ab9e 100644
--- a/binaries/data/mods/public/simulation/templates/units/hele_hero_xenophon.xml
+++ b/binaries/data/mods/public/simulation/templates/units/hele_hero_xenophon.xml
@@ -1,11 +1,5 @@
-
-
- 20
- 5
-
-
hele
Xenophon
diff --git a/binaries/data/mods/public/simulation/templates/units/mace_hero_alexander.xml b/binaries/data/mods/public/simulation/templates/units/mace_hero_alexander.xml
index c0e1690dec..6574502f5b 100644
--- a/binaries/data/mods/public/simulation/templates/units/mace_hero_alexander.xml
+++ b/binaries/data/mods/public/simulation/templates/units/mace_hero_alexander.xml
@@ -21,12 +21,6 @@
-
-
- 80
- 15
-
-
300
diff --git a/binaries/data/mods/public/simulation/templates/units/mace_hero_craterus.xml b/binaries/data/mods/public/simulation/templates/units/mace_hero_craterus.xml
index 5a4a5fe492..a987c8a552 100644
--- a/binaries/data/mods/public/simulation/templates/units/mace_hero_craterus.xml
+++ b/binaries/data/mods/public/simulation/templates/units/mace_hero_craterus.xml
@@ -1,11 +1,5 @@
-
-
- 20
- 5
-
-
mace
Crateros
diff --git a/binaries/data/mods/public/simulation/templates/units/mace_hero_demetrius.xml b/binaries/data/mods/public/simulation/templates/units/mace_hero_demetrius.xml
index c3905cc636..0cfc0503b3 100644
--- a/binaries/data/mods/public/simulation/templates/units/mace_hero_demetrius.xml
+++ b/binaries/data/mods/public/simulation/templates/units/mace_hero_demetrius.xml
@@ -1,11 +1,5 @@
-
-
- 20
- 5
-
-
mace
Demetrius The Besieger
diff --git a/binaries/data/mods/public/simulation/templates/units/mace_hero_philip.xml b/binaries/data/mods/public/simulation/templates/units/mace_hero_philip.xml
index e72dc1b6f4..5bc0c06497 100644
--- a/binaries/data/mods/public/simulation/templates/units/mace_hero_philip.xml
+++ b/binaries/data/mods/public/simulation/templates/units/mace_hero_philip.xml
@@ -1,11 +1,5 @@
-
-
- 20
- 5
-
-
mace
Philip II of Macedon
diff --git a/binaries/data/mods/public/simulation/templates/units/rome_hero_marcellus.xml b/binaries/data/mods/public/simulation/templates/units/rome_hero_marcellus.xml
index 640798909d..1ccde6e709 100644
--- a/binaries/data/mods/public/simulation/templates/units/rome_hero_marcellus.xml
+++ b/binaries/data/mods/public/simulation/templates/units/rome_hero_marcellus.xml
@@ -1,11 +1,5 @@
-
-
- 20
- 10
-
-
rome
Marcus Claudius Marcellus
diff --git a/binaries/data/mods/public/simulation/templates/units/rome_hero_maximus.xml b/binaries/data/mods/public/simulation/templates/units/rome_hero_maximus.xml
index 01bf5a7cdd..5531a69288 100644
--- a/binaries/data/mods/public/simulation/templates/units/rome_hero_maximus.xml
+++ b/binaries/data/mods/public/simulation/templates/units/rome_hero_maximus.xml
@@ -1,11 +1,5 @@
-
-
- 20
- 10
-
-
rome
Quinctus Fabius Maximus
diff --git a/binaries/data/mods/public/simulation/templates/units/rome_hero_scipio.xml b/binaries/data/mods/public/simulation/templates/units/rome_hero_scipio.xml
index 208d4b9203..9b5f5a870f 100644
--- a/binaries/data/mods/public/simulation/templates/units/rome_hero_scipio.xml
+++ b/binaries/data/mods/public/simulation/templates/units/rome_hero_scipio.xml
@@ -1,11 +1,5 @@
-
-
- 20
- 10
-
-
rome
Scipio Africanus
diff --git a/binaries/data/mods/public/simulation/templates/units/spart_hero_brasidas.xml b/binaries/data/mods/public/simulation/templates/units/spart_hero_brasidas.xml
index f6e1506b53..e42c1612d3 100644
--- a/binaries/data/mods/public/simulation/templates/units/spart_hero_brasidas.xml
+++ b/binaries/data/mods/public/simulation/templates/units/spart_hero_brasidas.xml
@@ -1,11 +1,5 @@
-
-
- 20
- 5
-
-
spart
Brasidas
diff --git a/binaries/data/mods/public/simulation/templates/units/spart_hero_leonidas.xml b/binaries/data/mods/public/simulation/templates/units/spart_hero_leonidas.xml
index 638d229dfd..492d197413 100644
--- a/binaries/data/mods/public/simulation/templates/units/spart_hero_leonidas.xml
+++ b/binaries/data/mods/public/simulation/templates/units/spart_hero_leonidas.xml
@@ -17,12 +17,6 @@
6.0
-
-
- 8
- 5
-
-
spart
Leonidas I
diff --git a/source/simulation2/Simulation2.cpp b/source/simulation2/Simulation2.cpp
index bd93c08a69..d34c3d11b9 100644
--- a/source/simulation2/Simulation2.cpp
+++ b/source/simulation2/Simulation2.cpp
@@ -125,6 +125,7 @@ public:
LOGERROR(L"Can't find component type " L##name); \
componentManager.AddComponent(systemEntity, cid, noParam)
+ LOAD_SCRIPTED_COMPONENT("AuraManager");
LOAD_SCRIPTED_COMPONENT("AIInterface");
LOAD_SCRIPTED_COMPONENT("Barter");
LOAD_SCRIPTED_COMPONENT("EndGameManager");