Index: binaries/data/mods/public/simulation/components/Health.js =================================================================== --- binaries/data/mods/public/simulation/components/Health.js +++ binaries/data/mods/public/simulation/components/Health.js @@ -181,14 +181,14 @@ * Take damage according to the entity's resistance. * @param {Object} strengths - { "hack": number, "pierce": number, "crush": number } or something like that. * @param {number} bonusMultiplier - the damage multiplier. - * Returns object of the form { "killed": false, "change": -12 }. + * Returns object of the form { "healthChange": -12 }. */ Health.prototype.TakeDamage = function(effectData, attacker, attackerOwner, bonusMultiplier) { let cmpResistance = Engine.QueryInterface(this.entity, IID_Resistance); - if (cmpResistance && cmpResistance.IsInvulnerable()) - return { "killed": false }; + if (!this.hitpoints || cmpResistance && cmpResistance.IsInvulnerable()) + return { "healthChange": 0 }; let total = Attacking.GetTotalAttackEffects(effectData, "Damage", cmpResistance) * bonusMultiplier; @@ -196,15 +196,43 @@ let change = this.Reduce(total); let cmpLoot = Engine.QueryInterface(this.entity, IID_Loot); - if (cmpLoot && cmpLoot.GetXp() > 0 && change.HPchange < 0) - change.xp = cmpLoot.GetXp() * -change.HPchange / this.GetMaxHitpoints(); + if (cmpLoot && cmpLoot.GetXp() > 0 && change.healthChange < 0) + change.xp = cmpLoot.GetXp() * -change.healthChange / this.GetMaxHitpoints(); + + if (!this.hitpoints) + this.TargetKilled(attacker, attackerOwner); return change; }; /** + * Called when an entity kills us. + * @param {number} attacker - The entityID of the killer. + * @param {number} attackerOwner - The playerID of the attacker. + */ +Health.prototype.TargetKilled = function(attacker, attackerOwner) +{ + let cmpAttackerOwnership = Engine.QueryInterface(attacker, IID_Ownership); + let atkOwner = cmpAttackerOwnership && cmpAttackerOwnership.GetOwner() != INVALID_PLAYER ? cmpAttackerOwnership.GetOwner() : attackerOwner; + + // Add to killer statistics. + let cmpKillerPlayerStatisticsTracker = QueryPlayerIDInterface(atkOwner, IID_StatisticsTracker); + if (cmpKillerPlayerStatisticsTracker) + cmpKillerPlayerStatisticsTracker.KilledEntity(this.entity); + // Add to loser statistics. + let cmpTargetPlayerStatisticsTracker = QueryOwnerInterface(this.entity, IID_StatisticsTracker); + if (cmpTargetPlayerStatisticsTracker) + cmpTargetPlayerStatisticsTracker.LostEntity(this.entity); + + // If the killer can collect loot, let's try to collect it. + let cmpLooter = Engine.QueryInterface(attacker, IID_Looter); + if (cmpLooter) + cmpLooter.Collect(this.entity); +}; + +/** * @param {number} amount - The amount of hitpoints to substract. Kills the entity if required. - * @return {{killed:boolean, HPchange:number}} - Number of health points lost and whether the entity was killed. + * @return {{ healthChange:number }} - Number of health points lost. */ Health.prototype.Reduce = function(amount) { @@ -213,7 +241,7 @@ // might get called multiple times) // Likewise if the amount is 0. if (!amount || !this.hitpoints) - return { "killed": false, "HPchange": 0 }; + return { "healthChange": 0 }; // Before changing the value, activate Fogging if necessary to hide changes let cmpFogging = Engine.QueryInterface(this.entity, IID_Fogging); @@ -227,7 +255,7 @@ this.hitpoints = 0; this.RegisterHealthChanged(oldHitpoints); this.HandleDeath(); - return { "killed": true, "HPchange": -oldHitpoints }; + return { "healthChange": -oldHitpoints }; } // If we are not marked as injured, do it now @@ -240,7 +268,7 @@ this.hitpoints -= amount; this.RegisterHealthChanged(oldHitpoints); - return { "killed": false, "HPchange": this.hitpoints - oldHitpoints }; + return { "healthChange": this.hitpoints - oldHitpoints }; }; /** 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 @@ -92,7 +92,7 @@ AddMock(target, IID_Health, { "TakeDamage": (effectData, __, ___, bonusMultiplier) => { damageTaken = true; - return { "killed": false, "HPchange": -bonusMultiplier * effectData.Crush }; + return { "killed": false, "healthChange": -bonusMultiplier * effectData.Crush }; }, }); Index: binaries/data/mods/public/simulation/components/tests/test_Health.js =================================================================== --- binaries/data/mods/public/simulation/components/tests/test_Health.js +++ binaries/data/mods/public/simulation/components/tests/test_Health.js @@ -63,8 +63,7 @@ var change = cmpHealth.Reduce(25); TS_ASSERT_EQUALS(injured_flag, true); -TS_ASSERT_EQUALS(change.killed, false); -TS_ASSERT_EQUALS(change.HPchange, -25); +TS_ASSERT_EQUALS(change.healthChange, -25); TS_ASSERT_EQUALS(cmpHealth.GetHitpoints(), 25); TS_ASSERT_EQUALS(cmpHealth.GetMaxHitpoints(), 50); TS_ASSERT_EQUALS(cmpHealth.IsInjured(), true); @@ -106,8 +105,7 @@ // Check that we are not marked as injured. TS_ASSERT_EQUALS(injured_flag, false); -TS_ASSERT_EQUALS(change.killed, true); -TS_ASSERT_EQUALS(change.HPchange, -50); +TS_ASSERT_EQUALS(change.healthChange, -50); TS_ASSERT_EQUALS(cmpHealth.GetHitpoints(), 0); TS_ASSERT_EQUALS(cmpHealth.GetMaxHitpoints(), 50); TS_ASSERT_EQUALS(cmpHealth.IsInjured(), false); @@ -121,8 +119,7 @@ // Check that we can't die twice. change = cmpHealth.Reduce(50); -TS_ASSERT_EQUALS(change.killed, false); -TS_ASSERT_EQUALS(change.HPchange, 0); +TS_ASSERT_EQUALS(change.healthChange, 0); TS_ASSERT_EQUALS(cmpHealth.GetHitpoints(), 0); TS_ASSERT_EQUALS(cmpHealth.GetMaxHitpoints(), 50); TS_ASSERT_EQUALS(cmpHealth.IsInjured(), false); @@ -131,8 +128,7 @@ // Check that we still die with > Max HP of damage. change = cmpHealth.Reduce(60); -TS_ASSERT_EQUALS(change.killed, true); -TS_ASSERT_EQUALS(change.HPchange, -50); +TS_ASSERT_EQUALS(change.healthChange, -50); TS_ASSERT_EQUALS(cmpHealth.GetHitpoints(), 0); TS_ASSERT_EQUALS(cmpHealth.GetMaxHitpoints(), 50); TS_ASSERT_EQUALS(cmpHealth.IsInjured(), false); Index: binaries/data/mods/public/simulation/helpers/Attacking.js =================================================================== --- binaries/data/mods/public/simulation/helpers/Attacking.js +++ binaries/data/mods/public/simulation/helpers/Attacking.js @@ -326,15 +326,12 @@ if (!Object.keys(targetState).length) return; - if (targetState.killed) - this.TargetKilled(attacker, target, attackerOwner); - Engine.PostMessage(target, MT_Attacked, { "type": attackType, "target": target, "attacker": attacker, "attackerOwner": attackerOwner, - "damage": -(targetState.HPchange || 0), + "damage": -(targetState.healthChange || 0), "capture": targetState.captureChange || 0, "statusEffects": targetState.inflictedStatuses || [], "fromStatusEffect": !!attackData.StatusEffect, @@ -367,31 +364,5 @@ return cmpRangeManager.ExecuteQueryAroundPos(origin, 0, radius, players, itf); }; -/** - * Called when a unit kills something (another unit, building, animal etc). - * @param {number} attacker - The entity id of the killer. - * @param {number} target - The entity id of the target. - * @param {number} attackerOwner - The player id of the attacker. - */ -Attacking.prototype.TargetKilled = function(attacker, target, attackerOwner) -{ - let cmpAttackerOwnership = Engine.QueryInterface(attacker, IID_Ownership); - let atkOwner = cmpAttackerOwnership && cmpAttackerOwnership.GetOwner() != INVALID_PLAYER ? cmpAttackerOwnership.GetOwner() : attackerOwner; - - // Add to killer statistics. - let cmpKillerPlayerStatisticsTracker = QueryPlayerIDInterface(atkOwner, IID_StatisticsTracker); - if (cmpKillerPlayerStatisticsTracker) - cmpKillerPlayerStatisticsTracker.KilledEntity(target); - // Add to loser statistics. - let cmpTargetPlayerStatisticsTracker = QueryOwnerInterface(target, IID_StatisticsTracker); - if (cmpTargetPlayerStatisticsTracker) - cmpTargetPlayerStatisticsTracker.LostEntity(target); - - // If killer can collect loot, let's try to collect it. - let cmpLooter = Engine.QueryInterface(attacker, IID_Looter); - if (cmpLooter) - cmpLooter.Collect(target); -}; - var AttackingInstance = new Attacking(); Engine.RegisterGlobal("Attacking", AttackingInstance); Index: binaries/data/mods/public/simulation/helpers/tests/test_Attacking.js =================================================================== --- binaries/data/mods/public/simulation/helpers/tests/test_Attacking.js +++ binaries/data/mods/public/simulation/helpers/tests/test_Attacking.js @@ -75,7 +75,7 @@ TS_ASSERT_EQUALS(count, 1); AddMock(this.TESTED_ENTITY_ID, IID_Health, { - "TakeDamage": () => ({ "HPchange": 0 }), + "TakeDamage": () => ({ "healthChange": 0 }), }); count = 0; Engine.PostMessage = () => count++;