Line data Source code
1 : function StatusEffectsReceiver() {} 2 : 3 1 : StatusEffectsReceiver.prototype.DefaultInterval = 1000; 4 : 5 : /** 6 : * Initialises the status effects. 7 : */ 8 1 : StatusEffectsReceiver.prototype.Init = function() 9 : { 10 1 : this.activeStatusEffects = {}; 11 : }; 12 : 13 : /** 14 : * Which status effects are active on this entity. 15 : * 16 : * @return {Object} - An object containing the status effects which currently affect the entity. 17 : */ 18 1 : StatusEffectsReceiver.prototype.GetActiveStatuses = function() 19 : { 20 7 : return this.activeStatusEffects; 21 : }; 22 : 23 : /** 24 : * Called by Attacking effects. Adds status effects for each entry in the effectData. 25 : * 26 : * @param {Object} effectData - An object containing the status effects to give to the entity. 27 : * @param {number} attacker - The entity ID of the attacker. 28 : * @param {number} attackerOwner - The player ID of the attacker. 29 : * @param {number} bonusMultiplier - A value to multiply the damage with (not implemented yet for SE). 30 : * 31 : * @return {Object} - The codes of the status effects which were processed. 32 : */ 33 1 : StatusEffectsReceiver.prototype.ApplyStatus = function(effectData, attacker, attackerOwner) 34 : { 35 9 : for (let effect in effectData) 36 10 : this.AddStatus(effect, effectData[effect], attacker, attackerOwner); 37 : 38 : // TODO: implement loot? 39 : 40 9 : return { "inflictedStatuses": Object.keys(effectData) }; 41 : }; 42 : 43 : /** 44 : * Adds a status effect to the entity. 45 : * 46 : * @param {string} statusCode - The code of the status effect. 47 : * @param {Object} data - The various effects and timings. 48 : * @param {number} attacker - optional, the entity ID of the attacker. 49 : * @param {number} attackerOwner - optional, the player ID of the attacker. 50 : */ 51 1 : StatusEffectsReceiver.prototype.AddStatus = function(baseCode, data, attacker = INVALID_ENTITY, attackerOwner = INVALID_PLAYER) 52 : { 53 15 : let statusCode = baseCode; 54 15 : if (this.activeStatusEffects[statusCode]) 55 : { 56 4 : if (data.Stackability == "Ignore") 57 1 : return; 58 3 : if (data.Stackability == "Extend") 59 : { 60 1 : this.activeStatusEffects[statusCode].Duration += data.Duration; 61 1 : return; 62 : } 63 2 : if (data.Stackability == "Replace") 64 1 : this.RemoveStatus(statusCode); 65 1 : else if (data.Stackability == "Stack") 66 : { 67 1 : let i = 0; 68 : let temp; 69 1 : do 70 1 : temp = statusCode + "_" + i++; 71 : while (!!this.activeStatusEffects[temp]); 72 1 : statusCode = temp; 73 : } 74 : } 75 : 76 13 : this.activeStatusEffects[statusCode] = { 77 : "baseCode": baseCode 78 : }; 79 13 : let status = this.activeStatusEffects[statusCode]; 80 13 : Object.assign(status, data); 81 : 82 13 : if (status.Modifiers) 83 : { 84 3 : let modifications = DeriveModificationsFromXMLTemplate(status.Modifiers); 85 3 : let cmpModifiersManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ModifiersManager); 86 3 : cmpModifiersManager.AddModifiers(statusCode, modifications, this.entity); 87 : } 88 : 89 : // With neither an interval nor a duration, there is no point in starting a timer. 90 13 : if (!status.Duration && !status.Interval) 91 0 : return; 92 : 93 : // We need this to prevent Status Effects from giving XP 94 : // to the entity that applied them. 95 13 : status.StatusEffect = true; 96 : 97 : // We want an interval to update the GUI to show how much time of the status effect 98 : // is left even if the status effect itself has no interval. 99 13 : if (!status.Interval) 100 3 : status._interval = this.DefaultInterval; 101 : 102 13 : status._timeElapsed = 0; 103 13 : status._firstTime = true; 104 13 : status.source = { "entity": attacker, "owner": attackerOwner }; 105 : 106 13 : let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 107 13 : status._timer = cmpTimer.SetInterval(this.entity, IID_StatusEffectsReceiver, "ExecuteEffect", 0, +(status.Interval || status._interval), statusCode); 108 : }; 109 : 110 : /** 111 : * Removes a status effect from the entity. 112 : * 113 : * @param {string} statusCode - The status effect to be removed. 114 : */ 115 1 : StatusEffectsReceiver.prototype.RemoveStatus = function(statusCode) 116 : { 117 13 : let statusEffect = this.activeStatusEffects[statusCode]; 118 13 : if (!statusEffect) 119 0 : return; 120 : 121 13 : if (statusEffect.Modifiers) 122 : { 123 3 : let cmpModifiersManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_ModifiersManager); 124 3 : cmpModifiersManager.RemoveAllModifiers(statusCode, this.entity); 125 : } 126 : 127 13 : if (statusEffect._timer) 128 : { 129 13 : let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); 130 13 : cmpTimer.CancelTimer(statusEffect._timer); 131 : } 132 13 : delete this.activeStatusEffects[statusCode]; 133 : }; 134 : 135 : /** 136 : * Called by the timers. Executes a status effect. 137 : * 138 : * @param {string} statusCode - The status effect to be executed. 139 : * @param {number} lateness - The delay between the calling of the function and the actual execution (turn time?). 140 : */ 141 1 : StatusEffectsReceiver.prototype.ExecuteEffect = function(statusCode, lateness) 142 : { 143 38 : let status = this.activeStatusEffects[statusCode]; 144 38 : if (!status) 145 0 : return; 146 : 147 38 : if (status.Damage || status.Capture) 148 29 : AttackHelper.HandleAttackEffects(this.entity, { 149 : "type": statusCode, 150 : "attackData": status, 151 : "attacker": status.source.entity, 152 : "attackerOwner": status.source.owner 153 : }); 154 : 155 38 : if (!status.Duration) 156 0 : return; 157 : 158 38 : if (status._firstTime) 159 : { 160 13 : status._firstTime = false; 161 13 : status._timeElapsed += lateness; 162 : } 163 : else 164 25 : status._timeElapsed += +(status.Interval || status._interval) + lateness; 165 : 166 38 : if (status._timeElapsed >= +status.Duration) 167 10 : this.RemoveStatus(statusCode); 168 : }; 169 : 170 1 : Engine.RegisterComponentType(IID_StatusEffectsReceiver, "StatusEffectsReceiver", StatusEffectsReceiver);