Index: ps/trunk/binaries/data/mods/public/globalscripts/AttackEffects.js
===================================================================
--- ps/trunk/binaries/data/mods/public/globalscripts/AttackEffects.js
+++ ps/trunk/binaries/data/mods/public/globalscripts/AttackEffects.js
@@ -1,5 +1,5 @@
// TODO: could be worth putting this in json files someday
-const g_EffectTypes = ["Damage", "Capture", "GiveStatus"];
+const g_EffectTypes = ["Damage", "Capture", "ApplyStatus"];
const g_EffectReceiver = {
"Damage": {
"IID": "IID_Health",
@@ -9,8 +9,8 @@
"IID": "IID_Capturable",
"method": "Capture"
},
- "GiveStatus": {
+ "ApplyStatus": {
"IID": "IID_StatusEffectsReceiver",
- "method": "GiveStatus"
+ "method": "ApplyStatus"
}
};
Index: ps/trunk/binaries/data/mods/public/globalscripts/ModificationTemplates.js
===================================================================
--- ps/trunk/binaries/data/mods/public/globalscripts/ModificationTemplates.js
+++ ps/trunk/binaries/data/mods/public/globalscripts/ModificationTemplates.js
@@ -43,3 +43,160 @@
global.AuraTemplates = new ModificationTemplates("simulation/data/auras/");
global.TechnologyTemplates = new ModificationTemplates("simulation/data/technologies/");
}
+
+/**
+ * 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 {};
+
+ let techMods = {};
+ let techAffects = [];
+ if (techTemplate.affects && techTemplate.affects.length)
+ techAffects = techTemplate.affects.map(affected => affected.split(/\s+/));
+ else
+ techAffects.push([]);
+
+ for (let mod of techTemplate.modifications)
+ {
+ let affects = techAffects.slice();
+ if (mod.affects)
+ {
+ let specAffects = mod.affects.split(/\s+/);
+ for (let a in affects)
+ affects[a] = affects[a].concat(specAffects);
+ }
+
+ let newModifier = { "affects": affects };
+ for (let idx in mod)
+ 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 {};
+
+ let derivedModifiers = {};
+ for (let technology of techsDataArray)
+ {
+ if (!technology.reqs)
+ continue;
+
+ let modifiers = DeriveModificationsFromTech(technology);
+ for (let modPath in modifiers)
+ {
+ 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 =
+"" +
+ "" +
+ "" +
+ "tokens" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "tokens" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+"";
+
+const ModificationsSchema =
+"" +
+ "" +
+ "" +
+ "" +
+ ModificationSchema +
+ "" +
+ "" +
+"";
+
+/**
+ * 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)
+{
+ let effect = {};
+ 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/) : [];
+
+ let ret = {};
+ for (let path of template.Paths._string.split(/\s/))
+ {
+ 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)
+{
+ let ret = {};
+ for (let name in template)
+ {
+ let modification = DeriveModificationFromXMLTemplate(template[name]);
+ for (let path in modification)
+ {
+ if (!ret[path])
+ ret[path] = [];
+ ret[path].push(modification[path][0]);
+ }
+ }
+ return ret;
+}
Index: ps/trunk/binaries/data/mods/public/globalscripts/Technologies.js
===================================================================
--- ps/trunk/binaries/data/mods/public/globalscripts/Technologies.js
+++ ps/trunk/binaries/data/mods/public/globalscripts/Technologies.js
@@ -40,74 +40,6 @@
}
/**
- * Derives modifications (to be applied to entities) from a given technology.
- *
- * @param {Object} techTemplate - The technology template to derive the modifications from.
- * @return {Object} containing the relevant modifications.
- */
-function DeriveModificationsFromTech(techTemplate)
-{
- if (!techTemplate.modifications)
- return {};
-
- let techMods = {};
- let techAffects = [];
- if (techTemplate.affects && techTemplate.affects.length)
- for (let affected of techTemplate.affects)
- techAffects.push(affected.split(/\s+/));
- else
- techAffects.push([]);
-
- for (let mod of techTemplate.modifications)
- {
- let affects = techAffects.slice();
- if (mod.affects)
- {
- let specAffects = mod.affects.split(/\s+/);
- for (let a in affects)
- affects[a] = affects[a].concat(specAffects);
- }
-
- let newModifier = { "affects": affects };
- for (let idx in mod)
- 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 technology template data.
- *
- * @param {array} techsDataArray
- * @return {object} containing the combined relevant modifications of all
- * the technologies.
- */
-function DeriveModificationsFromTechnologies(techsDataArray)
-{
- let derivedModifiers = {};
- for (let technology of techsDataArray)
- {
- if (!technology.reqs)
- continue;
-
- let modifiers = DeriveModificationsFromTech(technology);
- for (let modPath in modifiers)
- {
- if (!derivedModifiers[modPath])
- derivedModifiers[modPath] = [];
- derivedModifiers[modPath] = derivedModifiers[modPath].concat(modifiers[modPath]);
- }
- }
- return derivedModifiers;
-}
-
-/**
* Returns whether the given modification applies to the entity containing the given class list
*/
function DoesModificationApply(modification, classes)
Index: ps/trunk/binaries/data/mods/public/globalscripts/Templates.js
===================================================================
--- ps/trunk/binaries/data/mods/public/globalscripts/Templates.js
+++ ps/trunk/binaries/data/mods/public/globalscripts/Templates.js
@@ -180,7 +180,9 @@
effects.Damage[damageType] = getEntityValue(path + "/Damage/" + damageType);
}
- // TODO: status effects
+ if (temp.ApplyStatus)
+ effects.ApplyStatus = temp.ApplyStatus;
+
return effects;
};
Index: ps/trunk/binaries/data/mods/public/gui/common/tooltips.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/common/tooltips.js
+++ ps/trunk/binaries/data/mods/public/gui/common/tooltips.js
@@ -275,13 +275,13 @@
});
}
-function giveStatusDetails(giveStatusTemplate)
+function applyStatusDetails(applyStatusTemplate)
{
- if (!giveStatusTemplate)
+ if (!applyStatusTemplate)
return "";
return sprintf(translate("gives %(name)s"), {
- "name": Object.keys(giveStatusTemplate).map(x => unitFont(translateWithContext("status effect", x))).join(', '),
+ "name": Object.keys(applyStatusTemplate).map(x => unitFont(translateWithContext("status effect", applyStatusTemplate[x].Name))).join(commaFont(translate(", "))),
});
}
@@ -293,7 +293,7 @@
let effects = [
captureDetails(attackTypeTemplate.Capture || undefined),
damageDetails(attackTypeTemplate.Damage || undefined),
- giveStatusDetails(attackTypeTemplate.GiveStatus || undefined)
+ applyStatusDetails(attackTypeTemplate.ApplyStatus || undefined)
];
return effects.filter(effect => effect).join(commaFont(translate(", ")));
}
@@ -323,9 +323,9 @@
// Show the effects of status effects below
let statusEffectsDetails = [];
- if (attackTypeTemplate.GiveStatus)
- for (let status in attackTypeTemplate.GiveStatus)
- statusEffectsDetails.push("\n " + getStatusEffectsTooltip(status, attackTypeTemplate.GiveStatus[status]));
+ if (attackTypeTemplate.ApplyStatus)
+ for (let status in attackTypeTemplate.ApplyStatus)
+ statusEffectsDetails.push("\n " + getStatusEffectsTooltip(attackTypeTemplate.ApplyStatus[status]));
statusEffectsDetails = statusEffectsDetails.join("");
tooltips.push(sprintf(translate("%(attackLabel)s: %(effects)s, %(range)s, %(rate)s%(statusEffects)s"), {
@@ -371,20 +371,48 @@
return tooltips.join("\n");
}
-function getStatusEffectsTooltip(name, template)
+function getStatusEffectsTooltip(template)
{
+ let tooltipAttributes = [];
+ let tooltipString = "";
+ if (template.Tooltip)
+ {
+ tooltipAttributes.push("%(tooltip)s");
+ tooltipString = translate(template.Tooltip);
+ }
+
+ let attackEffectsString = "";
+ if (template.Damage || template.Capture)
+ {
+ tooltipAttributes.push("%(effects)s");
+ attackEffectsString = attackEffectsDetails(template);
+ }
+
+ let intervalString = "";
+ if (template.Interval)
+ {
+ tooltipAttributes.push("%(rate)s");
+ intervalString = sprintf(translate("%(interval)s"), {
+ "interval": attackRateDetails(+template.Interval)
+ });
+ }
+
let durationString = "";
if (template.Duration)
- durationString = sprintf(translate(", %(durName)s: %(duration)s"), {
+ {
+ tooltipAttributes.push("%(duration)s");
+ durationString = sprintf(translate("%(durName)s: %(duration)s"), {
"durName": headerFont(translate("Duration")),
- "duration": getSecondsString((template.TimeElapsed ? +template.Duration - template.TimeElapsed : +template.Duration) / 1000),
+ "duration": getSecondsString((template._timeElapsed ? +template.Duration - template._timeElapsed : +template.Duration) / 1000),
});
+ }
- return sprintf(translate("%(statusName)s: %(effects)s, %(rate)s%(durationString)s"), {
- "statusName": headerFont(translateWithContext("status effect", name)),
- "effects": attackEffectsDetails(template),
- "rate": attackRateDetails(+template.Interval),
- "durationString": durationString
+ return sprintf(translate("%(statusName)s: " + tooltipAttributes.join(translate(commaFont(", ")))), {
+ "statusName": headerFont(translateWithContext("status effect", template.Name)),
+ "tooltip": tooltipString,
+ "effects": attackEffectsString,
+ "rate": intervalString,
+ "duration": durationString
});
}
Index: ps/trunk/binaries/data/mods/public/gui/session/selection_details.js
===================================================================
--- ps/trunk/binaries/data/mods/public/gui/session/selection_details.js
+++ ps/trunk/binaries/data/mods/public/gui/session/selection_details.js
@@ -94,14 +94,16 @@
if (entState.statusEffects)
{
- let statusIcons = Engine.GetGUIObjectByName("statusEffectsIcons").children;
+ let statusEffectsSection = Engine.GetGUIObjectByName("statusEffectsIcons");
+ statusEffectsSection.hidden = false;
+ let statusIcons = statusEffectsSection.children;
let i = 0;
for (let effectName in entState.statusEffects)
{
let effect = entState.statusEffects[effectName];
statusIcons[i].hidden = false;
statusIcons[i].sprite = "stretched:session/icons/status_effects/" + (effect.Icon || "default") + ".png";
- statusIcons[i].tooltip = getStatusEffectsTooltip(effectName, effect);
+ statusIcons[i].tooltip = getStatusEffectsTooltip(effect);
let size = statusIcons[i].size;
size.top = i * 18;
size.bottom = i * 18 + 16;
@@ -111,6 +113,8 @@
for (; i < statusIcons.length; ++i)
statusIcons[i].hidden = true;
}
+ else
+ Engine.GetGUIObjectByName("statusEffectsIcons").hidden = true;
let showHealth = entState.hitpoints;
let showResource = entState.resourceSupply;
Index: ps/trunk/binaries/data/mods/public/simulation/components/StatusEffectsReceiver.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/components/StatusEffectsReceiver.js
+++ ps/trunk/binaries/data/mods/public/simulation/components/StatusEffectsReceiver.js
@@ -1,69 +1,145 @@
function StatusEffectsReceiver() {}
+StatusEffectsReceiver.prototype.DefaultInterval = 1000;
+
+/**
+ * Initialises the status effects.
+ */
StatusEffectsReceiver.prototype.Init = function()
{
this.activeStatusEffects = {};
};
+/**
+ * Which status effects are active on this entity.
+ *
+ * @return {Object} - An object containing the status effects which currently affect the entity.
+ */
StatusEffectsReceiver.prototype.GetActiveStatuses = function()
{
return this.activeStatusEffects;
};
-// Called by attacking effects.
-StatusEffectsReceiver.prototype.GiveStatus = function(effectData, attacker, attackerOwner, bonusMultiplier)
+/**
+ * Called by Attacking effects. Adds status effects for each entry in the effectData.
+ *
+ * @param {Object} effectData - An object containing the status effects to give to the entity.
+ * @param {number} attacker - The entity ID of the attacker.
+ * @param {number} attackerOwner - The player ID of the attacker.
+ * @param {number} bonusMultiplier - A value to multiply the damage with (not implemented yet for SE).
+ *
+ * @return {Object} - The names of the status effects which were processed.
+ */
+StatusEffectsReceiver.prototype.ApplyStatus = function(effectData, attacker, attackerOwner, bonusMultiplier)
{
+ let attackerData = { "entity": attacker, "owner": attackerOwner };
for (let effect in effectData)
- this.AddStatus(effect, effectData[effect]);
+ this.AddStatus(effect, effectData[effect], attackerData);
// TODO: implement loot / resistance.
return { "inflictedStatuses": Object.keys(effectData) };
};
-StatusEffectsReceiver.prototype.AddStatus = function(statusName, data)
+/**
+ * Adds a status effect to the entity.
+ *
+ * @param {string} statusName - The name of the status effect.
+ * @param {object} data - The various effects and timings.
+ */
+StatusEffectsReceiver.prototype.AddStatus = function(statusName, data, attackerData)
{
if (this.activeStatusEffects[statusName])
+ {
+ // TODO: implement different behaviour when receiving the same status multiple times.
+ // For now, these are ignored.
return;
+ }
this.activeStatusEffects[statusName] = {};
let status = this.activeStatusEffects[statusName];
Object.assign(status, data);
- status.Interval = +data.Interval;
- status.TimeElapsed = 0;
- status.FirstTime = true;
+
+ if (status.Modifiers)
+ {
+ let modifications = DeriveModificationsFromXMLTemplate(status.Modifiers);
+ let cmpModifiersManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ModifiersManager);
+ cmpModifiersManager.AddModifiers(statusName, modifications, this.entity);
+ }
+
+ // With neither an interval nor a duration, there is no point in starting a timer.
+ if (!status.Duration && !status.Interval)
+ return;
+
+ // We need this to prevent Status Effects from giving XP
+ // to the entity that applied them.
+ status.StatusEffect = true;
+
+ // We want an interval to update the GUI to show how much time of the status effect
+ // is left even if the status effect itself has no interval.
+ if (!status.Interval)
+ status._interval = this.DefaultInterval;
+
+ status._timeElapsed = 0;
+ status._firstTime = true;
+ status.source = attackerData;
let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
- status.Timer = cmpTimer.SetInterval(this.entity, IID_StatusEffectsReceiver, "ExecuteEffect", 0, +status.Interval, statusName);
+ status._timer = cmpTimer.SetInterval(this.entity, IID_StatusEffectsReceiver, "ExecuteEffect", 0, +(status.Interval || status._interval), statusName);
};
+/**
+ * Removes a status effect from the entity.
+ *
+ * @param {string} statusName - The status effect to be removed.
+ */
StatusEffectsReceiver.prototype.RemoveStatus = function(statusName)
{
- if (!this.activeStatusEffects[statusName])
+ let statusEffect = this.activeStatusEffects[statusName];
+ if (!statusEffect)
return;
- let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
- cmpTimer.CancelTimer(this.activeStatusEffects[statusName].Timer);
+ if (statusEffect.Modifiers)
+ {
+ let cmpModifiersManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ModifiersManager);
+ cmpModifiersManager.RemoveAllModifiers(statusName, this.entity);
+ }
+
+ if (statusEffect._timer)
+ {
+ let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+ cmpTimer.CancelTimer(statusEffect._timer);
+ }
delete this.activeStatusEffects[statusName];
};
+/**
+ * Called by the timers. Executes a status effect.
+ *
+ * @param {string} statusName - The name of the status effect to be executed.
+ * @param {number} lateness - The delay between the calling of the function and the actual execution (turn time?).
+ */
StatusEffectsReceiver.prototype.ExecuteEffect = function(statusName, lateness)
{
let status = this.activeStatusEffects[statusName];
if (!status)
return;
- if (status.FirstTime)
+ if (status.Damage || status.Capture)
+ Attacking.HandleAttackEffects(statusName, status, this.entity, status.source.entity, status.source.owner);
+
+ if (!status.Duration)
+ return;
+
+ if (status._firstTime)
{
- status.FirstTime = false;
- status.TimeElapsed += lateness;
+ status._firstTime = false;
+ status._timeElapsed += lateness;
}
else
- status.TimeElapsed += status.Interval + lateness;
-
- Attacking.HandleAttackEffects(statusName, status, this.entity, -1, -1);
+ status._timeElapsed += +(status.Interval || status._interval) + lateness;
- if (status.Duration && status.TimeElapsed >= +status.Duration)
+ if (status._timeElapsed >= +status.Duration)
this.RemoveStatus(statusName);
};
Index: ps/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
+++ ps/trunk/binaries/data/mods/public/simulation/components/UnitAI.js
@@ -4099,6 +4099,9 @@
UnitAI.prototype.OnAttacked = function(msg)
{
+ if (msg.fromStatusEffect)
+ return;
+
this.UnitFsm.ProcessMessage(this, {"type": "Attacked", "data": msg});
};
Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Damage.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Damage.js
+++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Damage.js
@@ -103,7 +103,16 @@
Engine.PostMessage = function(ent, iid, message)
{
- TS_ASSERT_UNEVAL_EQUALS({ "type": type, "target": target, "attacker": attacker, "attackerOwner": attackerOwner, "damage": damage, "capture": 0, "statusEffects": [] }, message);
+ TS_ASSERT_UNEVAL_EQUALS({
+ "type": type,
+ "target": target,
+ "attacker": attacker,
+ "attackerOwner": attackerOwner,
+ "damage": damage,
+ "capture": 0,
+ "statusEffects": [],
+ "fromStatusEffect": false
+ }, message);
};
AddMock(target, IID_Footprint, {
Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Pack.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Pack.js
+++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_Pack.js
@@ -11,6 +11,7 @@
Engine.LoadComponentScript("interfaces/Player.js");
Engine.LoadComponentScript("interfaces/Promotion.js");
Engine.LoadComponentScript("interfaces/ResourceGatherer.js");
+Engine.LoadComponentScript("interfaces/StatusEffectsReceiver.js");
Engine.LoadComponentScript("interfaces/Timer.js");
Engine.LoadComponentScript("interfaces/UnitAI.js");
Engine.LoadComponentScript("Pack.js");
Index: ps/trunk/binaries/data/mods/public/simulation/components/tests/test_StatusEffectsReceiver.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/components/tests/test_StatusEffectsReceiver.js
+++ ps/trunk/binaries/data/mods/public/simulation/components/tests/test_StatusEffectsReceiver.js
@@ -7,6 +7,8 @@
var cmpStatusReceiver;
var cmpTimer;
var dealtDamage;
+var enemyEntity = 4;
+var enemy = 2;
function setup()
{
@@ -31,6 +33,10 @@
"Damage": {
[statusName]: 1
}
+ },
+ {
+ "entity": enemyEntity,
+ "owner": enemy,
});
cmpTimer.OnUpdate({ "turnLength": 1 });
@@ -63,7 +69,7 @@
Engine.RegisterGlobal("Attacking", Attacking);
// damage scheduled: 0, 1, 2, 10 sec
- cmpStatusReceiver.GiveStatus({
+ cmpStatusReceiver.ApplyStatus({
"Burn": {
"Duration": 20000,
"Interval": 10000,
@@ -111,6 +117,10 @@
"Damage": {
[statusName]: 1
}
+ },
+ {
+ "entity": enemyEntity,
+ "owner": enemy,
});
cmpTimer.OnUpdate({ "turnLength": 1 });
Index: ps/trunk/binaries/data/mods/public/simulation/helpers/Attacking.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/helpers/Attacking.js
+++ ps/trunk/binaries/data/mods/public/simulation/helpers/Attacking.js
@@ -3,50 +3,70 @@
*/
function Attacking() {}
+const DirectEffectsSchema =
+ "" +
+ "" +
+ "" +
+ "" +
+ // Armour requires Foundation to not be a damage type.
+ "Foundation" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "";
+
+const StatusEffectsSchema =
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ DirectEffectsSchema +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ ModificationsSchema +
+ "" +
+ "" +
+ "" +
+ "" +
+ "";
+
/**
* Builds a RelaxRNG schema of possible attack effects.
* See globalscripts/AttackEffects.js for possible elements.
* Attacks may also have a "Bonuses" element.
*
- * @return {string} - RelaxNG schema string
+ * @return {string} - RelaxNG schema string.
*/
-const DamageSchema = "" +
- "" +
- "" +
- "" +
- // Armour requires Foundation to not be a damage type.
- "Foundation" +
- "" +
- "" +
- "" +
- "";
-
Attacking.prototype.BuildAttackEffectsSchema = function()
{
return "" +
"" +
"" +
- "" +
- DamageSchema +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" +
- "" + DamageSchema + "" +
- "" +
- "" +
- "" +
- "" +
+ DirectEffectsSchema +
+ StatusEffectsSchema +
"" +
"" +
"" +
@@ -85,8 +105,8 @@
if (template.Capture)
ret.Capture = ApplyValueModificationsToEntity(valueModifRoot + "/Capture", +(template.Capture || 0), entity);
- if (template.GiveStatus)
- ret.GiveStatus = template.GiveStatus;
+ if (template.ApplyStatus)
+ ret.ApplyStatus = template.ApplyStatus;
if (template.Bonuses)
ret.Bonuses = template.Bonuses;
@@ -250,10 +270,6 @@
Object.assign(targetState, cmpReceiver[receiver.method](attackData[effectType], attacker, attackerOwner, bonusMultiplier));
}
- let cmpPromotion = Engine.QueryInterface(attacker, IID_Promotion);
- if (cmpPromotion && targetState.xp)
- cmpPromotion.IncreaseXp(targetState.xp);
-
if (targetState.killed)
this.TargetKilled(attacker, target, attackerOwner);
@@ -265,7 +281,16 @@
"damage": -(targetState.HPchange || 0),
"capture": targetState.captureChange || 0,
"statusEffects": targetState.inflictedStatuses || [],
+ "fromStatusEffect": !!attackData.StatusEffect,
});
+
+ // We do not want an entity to get XP from active Status Effects.
+ if (!!attackData.StatusEffect)
+ return;
+
+ let cmpPromotion = Engine.QueryInterface(attacker, IID_Promotion);
+ if (cmpPromotion && targetState.xp)
+ cmpPromotion.IncreaseXp(targetState.xp);
};
/**
Index: ps/trunk/binaries/data/mods/public/simulation/helpers/Transform.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/helpers/Transform.js
+++ ps/trunk/binaries/data/mods/public/simulation/helpers/Transform.js
@@ -110,6 +110,20 @@
}
}
+ let cmpStatusEffectsReceiver = Engine.QueryInterface(oldEnt, IID_StatusEffectsReceiver);
+ let cmpNewStatusEffectsReceiver = Engine.QueryInterface(newEnt, IID_StatusEffectsReceiver);
+ if (cmpStatusEffectsReceiver && cmpNewStatusEffectsReceiver)
+ {
+ let activeStatus = cmpStatusEffectsReceiver.GetActiveStatuses();
+ for (let status in activeStatus)
+ {
+ let newStatus = activeStatus[status];
+ if (newStatus.Duration)
+ newStatus.Duration -= newStatus._timeElapsed;
+ cmpNewStatusEffectsReceiver.ApplyStatus({ [status]: newStatus }, newStatus.source.entity, newStatus.source.owner);
+ }
+ }
+
TransferGarrisonedUnits(oldEnt, newEnt);
Engine.PostMessage(oldEnt, MT_EntityRenamed, { "entity": oldEnt, "newentity": newEnt });