0ad/binaries/data/mods/public/simulation/components/StatusEffectsReceiver.js
Angen 82a5ab6d19 Allow status effect to apply modifiers and fix 2333b1814e
Status effect can apply modifier to the entity (armour strength, walking
speed, ...)
This is also hiding status effect icons by default in selection detail.
Fixing smaller related bugs.

Differential Revision: https://code.wildfiregames.com/D2281
Patch by: @Freagarach
Comments by: Stan, wraitii
This was SVN commit r23448.
2020-01-27 16:51:25 +00:00

146 lines
4.5 KiB
JavaScript
Executable file

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. 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], attackerData);
// TODO: implement loot / resistance.
return { "inflictedStatuses": Object.keys(effectData) };
};
/**
* 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);
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 || status._interval), statusName);
};
/**
* Removes a status effect from the entity.
*
* @param {string} statusName - The status effect to be removed.
*/
StatusEffectsReceiver.prototype.RemoveStatus = function(statusName)
{
let statusEffect = this.activeStatusEffects[statusName];
if (!statusEffect)
return;
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.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;
}
else
status._timeElapsed += +(status.Interval || status._interval) + lateness;
if (status._timeElapsed >= +status.Duration)
this.RemoveStatus(statusName);
};
Engine.RegisterComponentType(IID_StatusEffectsReceiver, "StatusEffectsReceiver", StatusEffectsReceiver);