Index: binaries/data/mods/public/simulation/components/Damage.js =================================================================== --- binaries/data/mods/public/simulation/components/Damage.js +++ binaries/data/mods/public/simulation/components/Damage.js @@ -236,7 +236,7 @@ * @param {Object} data - the data passed by the caller. * @param {Object} data.strengths - data in the form of { 'hack': number, 'pierce': number, 'crush': number }. * @param {number} data.target - the entity id of the target. - * @param {number} data.attacker - the entity id og the attacker. + * @param {number} data.attacker - the entity id of the attacker. * @param {number} data.multiplier - the damage multiplier. * @param {string} data.type - the type of damage. * @param {number} data.attackerOwner - the player id of the attacker. @@ -258,6 +258,11 @@ if (targetState.killed) this.TargetKilled(data.attacker, data.target, data.attackerOwner); + // do the status change, eg. poisoning + let cmpStatus = Engine.QueryInterface(data.target, IID_Status); + if (cmpStatus) + cmpStatus.StartEffect(data.attacker); + Engine.PostMessage(data.target, MT_Attacked, { "attacker": data.attacker, "target": data.target, "type": data.type, "damage": -targetState.change, "attackerOwner": data.attackerOwner }); }; Index: binaries/data/mods/public/simulation/components/Status.js =================================================================== --- binaries/data/mods/public/simulation/components/Status.js +++ binaries/data/mods/public/simulation/components/Status.js @@ -0,0 +1,42 @@ +function Status() {} + +Status.prototype.Init = function() +{ + this.isPoisoned = false; +} + +Status.prototype.StartEffect = function(attacker) +{ + let cmpStatusEffects = Engine.QueryInterface(attacker, IID_StatusEffects); + + if (!cmpStatusEffects || !cmpStatusEffects.poison) + return; + + // TODO: multiple poision attacks may reset the duration + if (this.isPoisoned) + return; + + this.isPoisoned = true; + + let poison = cmpStatusEffects.poison; + this.duration = poison.duration; + this.damage = poison.damage; + + let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); + this.timer = cmpTimer.SetInterval(this.entity, IID_Status, "ExecuteEffect", 0, poison.interval, null); +} + +Status.prototype.ExecuteEffect = function() +{ + let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); + if (cmpTimer.GetTime(this.timer) > this.duration) + { + cmpTimer.CancelTimer(this.timer); + return; + } + + let cmpHealth = Engine.QueryInterface(this.entity, IID_Health); + cmpHealth.Reduce(this.damage); +}; + +Engine.RegisterComponentType(IID_Status, "Status", Status); Index: binaries/data/mods/public/simulation/components/StatusEffects.js =================================================================== --- binaries/data/mods/public/simulation/components/StatusEffects.js +++ binaries/data/mods/public/simulation/components/StatusEffects.js @@ -0,0 +1,30 @@ +function StatusEffects() {} + +StatusEffects.prototype.Schema = + "Handling effects like poisioning or burning attached to an entity." + + "" + + "" + + "2000" + + "200" + + "5" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + +StatusEffects.prototype.Init = function() +{ + this.poison = {}; + this.poison.duration = +this.template.Poison.Duration; + this.poison.interval = +this.template.Poison.Interval; + this.poison.damage = +this.template.Poison.Damage; +}; + +Engine.RegisterComponentType(IID_StatusEffects, "StatusEffects", StatusEffects); Index: binaries/data/mods/public/simulation/components/interfaces/Status.js =================================================================== --- binaries/data/mods/public/simulation/components/interfaces/Status.js +++ binaries/data/mods/public/simulation/components/interfaces/Status.js @@ -0,0 +1 @@ +Engine.RegisterInterface("Status"); Index: binaries/data/mods/public/simulation/components/interfaces/StatusEffects.js =================================================================== --- binaries/data/mods/public/simulation/components/interfaces/StatusEffects.js +++ binaries/data/mods/public/simulation/components/interfaces/StatusEffects.js @@ -0,0 +1 @@ +Engine.RegisterInterface("StatusEffects"); Index: binaries/data/mods/public/simulation/components/tests/test_Damage.js =================================================================== --- binaries/data/mods/public/simulation/components/tests/test_Damage.js +++ binaries/data/mods/public/simulation/components/tests/test_Damage.js @@ -12,6 +12,7 @@ Engine.LoadComponentScript("interfaces/Loot.js"); Engine.LoadComponentScript("interfaces/Player.js"); Engine.LoadComponentScript("interfaces/Promotion.js"); +Engine.LoadComponentScript("interfaces/Status.js"); Engine.LoadComponentScript("interfaces/TechnologyManager.js"); Engine.LoadComponentScript("interfaces/Timer.js"); Engine.LoadComponentScript("Attack.js"); Index: binaries/data/mods/public/simulation/components/tests/test_Status.js =================================================================== --- binaries/data/mods/public/simulation/components/tests/test_Status.js +++ binaries/data/mods/public/simulation/components/tests/test_Status.js @@ -0,0 +1,50 @@ +Engine.LoadComponentScript("interfaces/Health.js"); +Engine.LoadComponentScript("interfaces/Status.js"); +Engine.LoadComponentScript("interfaces/Timer.js"); +Engine.LoadComponentScript("interfaces/StatusEffects.js"); + +Engine.LoadComponentScript("Status.js"); +Engine.LoadComponentScript("Timer.js"); +Engine.LoadComponentScript("StatusEffects.js"); + +function testStatusChange() +{ + let target = 42; + let attacker = 43; + + let cmpStatus = ConstructComponent(target, "Status"); + let cmpTimer = ConstructComponent(SYSTEM_ENTITY, "Timer"); + let cmpStatusEffects = ConstructComponent(attacker, "StatusEffects", { + "Poison": { + "Duration": 20000, + "Interval": 10000, + "Damage": 1 + } + }); + + let health = 10; + + AddMock(target, IID_Health, { + "Reduce": (amount) => { health -= amount; } + }); + + // damage scheduled: 0 sec, 10 sec, 20 sec + cmpStatus.StartEffect(attacker); + + cmpTimer.OnUpdate({ turnLength: 1 }); + TS_ASSERT_EQUALS(health, 9); // 1 sec + + cmpTimer.OnUpdate({ turnLength: 8 }); + TS_ASSERT_EQUALS(health, 9); // 9 sec + + cmpTimer.OnUpdate({ turnLength: 1 }); + TS_ASSERT_EQUALS(health, 8); // 10 sec + + cmpTimer.OnUpdate({ turnLength: 10 }); + TS_ASSERT_EQUALS(health, 7); // 20 sec + + cmpTimer.OnUpdate({ turnLength: 10 }); + TS_ASSERT_EQUALS(health, 7); // 30 sec +} + +testStatusChange(); Index: binaries/data/mods/public/simulation/templates/template_unit.xml =================================================================== --- binaries/data/mods/public/simulation/templates/template_unit.xml +++ binaries/data/mods/public/simulation/templates/template_unit.xml @@ -1,5 +1,13 @@ + + + + 5000 + 1000 + 1 + + 1