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 codes of the status effects which were processed. */ StatusEffectsReceiver.prototype.ApplyStatus = function(effectData, attacker, attackerOwner) { for (const effect in effectData) this.AddStatus(effect, effectData[effect], attacker, attackerOwner); // TODO: implement loot? return { "inflictedStatuses": Object.keys(effectData) }; }; /** * Adds a status effect to the entity. * * @param {string} statusCode - The code of the status effect. * @param {Object} data - The various effects and timings. * @param {number} attacker - optional, the entity ID of the attacker. * @param {number} attackerOwner - optional, the player ID of the attacker. */ StatusEffectsReceiver.prototype.AddStatus = function(baseCode, data, attacker = INVALID_ENTITY, attackerOwner = INVALID_PLAYER) { let statusCode = baseCode; if (this.activeStatusEffects[statusCode]) { if (data.Stackability == "Ignore") return; if (data.Stackability == "Extend") { this.activeStatusEffects[statusCode].Duration += data.Duration; return; } if (data.Stackability == "Replace") this.RemoveStatus(statusCode); else if (data.Stackability == "Stack") { let i = 0; let temp; do temp = statusCode + "_" + i++; while (this.activeStatusEffects[temp]); statusCode = temp; } } this.activeStatusEffects[statusCode] = { "baseCode": baseCode }; const status = this.activeStatusEffects[statusCode]; Object.assign(status, data); if (status.Modifiers) { const modifications = DeriveModificationsFromXMLTemplate(status.Modifiers); const cmpModifiersManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ModifiersManager); cmpModifiersManager.AddModifiers(statusCode, 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 = { "entity": attacker, "owner": attackerOwner }; const cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); status._timer = cmpTimer.SetInterval(this.entity, IID_StatusEffectsReceiver, "ExecuteEffect", 0, +(status.Interval || status._interval), statusCode); }; /** * Removes a status effect from the entity. * * @param {string} statusCode - The status effect to be removed. */ StatusEffectsReceiver.prototype.RemoveStatus = function(statusCode) { const statusEffect = this.activeStatusEffects[statusCode]; if (!statusEffect) return; if (statusEffect.Modifiers) { const cmpModifiersManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ModifiersManager); cmpModifiersManager.RemoveAllModifiers(statusCode, this.entity); } if (statusEffect._timer) { const cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); cmpTimer.CancelTimer(statusEffect._timer); } delete this.activeStatusEffects[statusCode]; }; /** * Called by the timers. Executes a status effect. * * @param {string} statusCode - 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(statusCode, lateness) { const status = this.activeStatusEffects[statusCode]; if (!status) return; if (status.Damage || status.Capture) AttackHelper.HandleAttackEffects(this.entity, { "type": statusCode, "attackData": status, "attacker": status.source.entity, "attackerOwner": 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(statusCode); }; Engine.RegisterComponentType(IID_StatusEffectsReceiver, "StatusEffectsReceiver", StatusEffectsReceiver);