Health.js cleanup: add tests, add an "IsInjured" function, use this.hitpoints everywhere
Continuation of D1769. Differential Revision: https://code.wildfiregames.com/D1828 This was SVN commit r22298.
This commit is contained in:
parent
01a8138780
commit
ea208f19a3
@ -254,7 +254,7 @@ GuiInterface.prototype.GetEntityState = function(player, ent)
|
||||
{
|
||||
ret.hitpoints = cmpHealth.GetHitpoints();
|
||||
ret.maxHitpoints = cmpHealth.GetMaxHitpoints();
|
||||
ret.needsRepair = cmpHealth.IsRepairable() && cmpHealth.GetHitpoints() < cmpHealth.GetMaxHitpoints();
|
||||
ret.needsRepair = cmpHealth.IsRepairable() && cmpHealth.IsInjured();
|
||||
ret.needsHeal = !cmpHealth.IsUnhealable();
|
||||
}
|
||||
|
||||
|
@ -78,6 +78,14 @@ Health.prototype.GetMaxHitpoints = function()
|
||||
return this.maxHitpoints;
|
||||
};
|
||||
|
||||
/**
|
||||
* @return {boolean} Whether the units are injured. Dead units are not considered injured.
|
||||
*/
|
||||
Health.prototype.IsInjured = function()
|
||||
{
|
||||
return this.hitpoints > 0 && this.hitpoints < this.GetMaxHitpoints();
|
||||
};
|
||||
|
||||
Health.prototype.SetHitpoints = function(value)
|
||||
{
|
||||
// If we're already dead, don't allow resurrection
|
||||
@ -94,7 +102,7 @@ Health.prototype.SetHitpoints = function(value)
|
||||
|
||||
let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
|
||||
if (cmpRangeManager)
|
||||
cmpRangeManager.SetEntityFlag(this.entity, "injured", this.hitpoints < this.GetMaxHitpoints());
|
||||
cmpRangeManager.SetEntityFlag(this.entity, "injured", this.IsInjured());
|
||||
|
||||
this.RegisterHealthChanged(old);
|
||||
};
|
||||
@ -107,8 +115,7 @@ Health.prototype.IsRepairable = function()
|
||||
Health.prototype.IsUnhealable = function()
|
||||
{
|
||||
return this.template.Unhealable == "true" ||
|
||||
this.GetHitpoints() <= 0 ||
|
||||
this.GetHitpoints() >= this.GetMaxHitpoints();
|
||||
this.hitpoints <= 0 || !this.IsInjured();
|
||||
};
|
||||
|
||||
Health.prototype.GetIdleRegenRate = function()
|
||||
@ -144,8 +151,8 @@ Health.prototype.CheckRegenTimer = function()
|
||||
{
|
||||
// check if we need a timer
|
||||
if (this.GetRegenRate() == 0 && this.GetIdleRegenRate() == 0 ||
|
||||
this.GetHitpoints() == this.GetMaxHitpoints() && this.GetRegenRate() >= 0 && this.GetIdleRegenRate() >= 0 ||
|
||||
this.GetHitpoints() == 0)
|
||||
!this.IsInjured() && this.GetRegenRate() >= 0 && this.GetIdleRegenRate() >= 0 ||
|
||||
this.hitpoints == 0)
|
||||
{
|
||||
// we don't need a timer, disable if one exists
|
||||
if (this.regenTimer)
|
||||
@ -199,7 +206,7 @@ Health.prototype.Reduce = function(amount)
|
||||
}
|
||||
|
||||
// If we are not marked as injured, do it now
|
||||
if (this.hitpoints == this.GetMaxHitpoints())
|
||||
if (!this.IsInjured())
|
||||
{
|
||||
let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
|
||||
if (cmpRangeManager)
|
||||
@ -256,7 +263,7 @@ Health.prototype.Increase = function(amount)
|
||||
if (cmpFogging)
|
||||
cmpFogging.Activate();
|
||||
|
||||
if (this.hitpoints == this.GetMaxHitpoints())
|
||||
if (!this.IsInjured())
|
||||
return { "old": this.hitpoints, "new": this.hitpoints };
|
||||
|
||||
// If we're already dead, don't allow resurrection
|
||||
@ -266,7 +273,7 @@ Health.prototype.Increase = function(amount)
|
||||
let old = this.hitpoints;
|
||||
this.hitpoints = Math.min(this.hitpoints + amount, this.GetMaxHitpoints());
|
||||
|
||||
if (this.hitpoints == this.GetMaxHitpoints())
|
||||
if (!this.IsInjured())
|
||||
{
|
||||
let cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
|
||||
if (cmpRangeManager)
|
||||
@ -350,7 +357,7 @@ Health.prototype.UpdateActor = function()
|
||||
{
|
||||
if (!this.template.DamageVariants)
|
||||
return;
|
||||
let ratio = this.GetHitpoints() / this.GetMaxHitpoints();
|
||||
let ratio = this.hitpoints / this.GetMaxHitpoints();
|
||||
let newDamageVariant = "alive";
|
||||
if (ratio > 0)
|
||||
{
|
||||
@ -386,7 +393,7 @@ Health.prototype.OnValueModification = function(msg)
|
||||
let newMaxHitpoints = ApplyValueModificationsToEntity("Health/Max", +this.template.Max, this.entity);
|
||||
if (oldMaxHitpoints != newMaxHitpoints)
|
||||
{
|
||||
let newHitpoints = this.GetHitpoints() * newMaxHitpoints/oldMaxHitpoints;
|
||||
let newHitpoints = this.hitpoints * newMaxHitpoints/oldMaxHitpoints;
|
||||
this.maxHitpoints = newMaxHitpoints;
|
||||
this.SetHitpoints(newHitpoints);
|
||||
}
|
||||
|
@ -1426,7 +1426,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
||||
var cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity);
|
||||
var cmpHealth = Engine.QueryInterface(this.isGuardOf, IID_Health);
|
||||
if (cmpIdentity && cmpIdentity.HasClass("Support") &&
|
||||
cmpHealth && cmpHealth.GetHitpoints() < cmpHealth.GetMaxHitpoints())
|
||||
cmpHealth && cmpHealth.IsInjured())
|
||||
{
|
||||
if (this.CanHeal(this.isGuardOf))
|
||||
this.PushOrderFront("Heal", { "target": this.isGuardOf, "force": false });
|
||||
@ -1716,7 +1716,7 @@ UnitAI.prototype.UnitFsmSpec = {
|
||||
{
|
||||
// if nothing better to do, check if the guarded needs to be healed or repaired
|
||||
var cmpHealth = Engine.QueryInterface(this.isGuardOf, IID_Health);
|
||||
if (cmpHealth && (cmpHealth.GetHitpoints() < cmpHealth.GetMaxHitpoints()))
|
||||
if (cmpHealth && cmpHealth.IsInjured())
|
||||
{
|
||||
if (this.CanHeal(this.isGuardOf))
|
||||
this.PushOrderFront("Heal", { "target": this.isGuardOf, "force": false });
|
||||
|
150
binaries/data/mods/public/simulation/components/tests/test_Health.js
Executable file
150
binaries/data/mods/public/simulation/components/tests/test_Health.js
Executable file
@ -0,0 +1,150 @@
|
||||
Engine.LoadComponentScript("interfaces/TechnologyManager.js");
|
||||
Engine.LoadComponentScript("interfaces/AuraManager.js");
|
||||
Engine.LoadHelperScript("Player.js");
|
||||
Engine.LoadHelperScript("ValueModification.js");
|
||||
|
||||
Engine.LoadHelperScript("Sound.js");
|
||||
Engine.LoadComponentScript("interfaces/DeathDamage.js");
|
||||
|
||||
Engine.LoadComponentScript("interfaces/Health.js");
|
||||
Engine.LoadComponentScript("Health.js");
|
||||
|
||||
const entity_id = 5;
|
||||
const corpse_id = entity_id + 1;
|
||||
|
||||
const health_template = {
|
||||
"Max": 50,
|
||||
"RegenRate": 0,
|
||||
"IdleRegenRate": 0,
|
||||
"DeathType": "corpse",
|
||||
"Unhealable": false
|
||||
};
|
||||
|
||||
|
||||
var injured_flag = false;
|
||||
var corpse_entity;
|
||||
|
||||
function setEntityUp()
|
||||
{
|
||||
let cmpHealth = ConstructComponent(entity_id, "Health", health_template);
|
||||
|
||||
AddMock(entity_id, IID_DeathDamage, {
|
||||
"CauseDeathDamage": () => {}
|
||||
});
|
||||
AddMock(entity_id, IID_Position, {
|
||||
"IsInWorld": () => true,
|
||||
"GetPosition": () => ({ "x": 0, "z": 0 }),
|
||||
"GetRotation": () => ({ "x": 0, "y": 0, "z": 0 })
|
||||
});
|
||||
AddMock(entity_id, IID_Ownership, {
|
||||
"GetOwner": () => 1
|
||||
});
|
||||
AddMock(entity_id, IID_Visual, {
|
||||
"GetActorSeed": () => 1
|
||||
});
|
||||
AddMock(SYSTEM_ENTITY, IID_TemplateManager, {
|
||||
"GetCurrentTemplateName": () => "test"
|
||||
});
|
||||
|
||||
AddMock(SYSTEM_ENTITY, IID_RangeManager, {
|
||||
"SetEntityFlag": (ent, flag, value) => (injured_flag = value)
|
||||
});
|
||||
|
||||
return cmpHealth;
|
||||
}
|
||||
|
||||
var cmpHealth = setEntityUp();
|
||||
|
||||
TS_ASSERT_EQUALS(cmpHealth.GetHitpoints(), 50);
|
||||
TS_ASSERT_EQUALS(cmpHealth.GetMaxHitpoints(), 50);
|
||||
TS_ASSERT_EQUALS(cmpHealth.IsInjured(), false);
|
||||
TS_ASSERT_EQUALS(cmpHealth.IsUnhealable(), true);
|
||||
|
||||
var change = cmpHealth.Reduce(25);
|
||||
TS_ASSERT_EQUALS(injured_flag, true);
|
||||
|
||||
TS_ASSERT_EQUALS(change.killed, false);
|
||||
TS_ASSERT_EQUALS(change.change, -25);
|
||||
TS_ASSERT_EQUALS(cmpHealth.GetHitpoints(), 25);
|
||||
TS_ASSERT_EQUALS(cmpHealth.GetMaxHitpoints(), 50);
|
||||
TS_ASSERT_EQUALS(cmpHealth.IsInjured(), true);
|
||||
TS_ASSERT_EQUALS(cmpHealth.IsUnhealable(), false);
|
||||
|
||||
change = cmpHealth.Increase(25);
|
||||
TS_ASSERT_EQUALS(injured_flag, false);
|
||||
|
||||
TS_ASSERT_EQUALS(change.new, 50);
|
||||
TS_ASSERT_EQUALS(cmpHealth.GetHitpoints(), 50);
|
||||
TS_ASSERT_EQUALS(cmpHealth.GetMaxHitpoints(), 50);
|
||||
TS_ASSERT_EQUALS(cmpHealth.IsInjured(), false);
|
||||
TS_ASSERT_EQUALS(cmpHealth.IsUnhealable(), true);
|
||||
|
||||
// Check death.
|
||||
Engine.AddLocalEntity = function(template) {
|
||||
corpse_entity = template;
|
||||
|
||||
AddMock(corpse_id, IID_Position, {
|
||||
"JumpTo": () => {},
|
||||
"SetYRotation": () => {},
|
||||
"SetXZRotation": () => {},
|
||||
});
|
||||
AddMock(corpse_id, IID_Ownership, {
|
||||
"SetOwner": () => {},
|
||||
});
|
||||
AddMock(corpse_id, IID_Visual, {
|
||||
"SetActorSeed": () => {},
|
||||
"SelectAnimation": () => {},
|
||||
});
|
||||
return corpse_id;
|
||||
};
|
||||
|
||||
change = cmpHealth.Reduce(50);
|
||||
|
||||
// Assert we create a corpse with the proper template.
|
||||
TS_ASSERT_EQUALS(corpse_entity, "corpse|test");
|
||||
|
||||
// Check that we are not marked as injured.
|
||||
TS_ASSERT_EQUALS(injured_flag, false);
|
||||
|
||||
TS_ASSERT_EQUALS(change.killed, true);
|
||||
TS_ASSERT_EQUALS(change.change, -50);
|
||||
TS_ASSERT_EQUALS(cmpHealth.GetHitpoints(), 0);
|
||||
TS_ASSERT_EQUALS(cmpHealth.GetMaxHitpoints(), 50);
|
||||
TS_ASSERT_EQUALS(cmpHealth.IsInjured(), false);
|
||||
|
||||
// Check that we can't be revived once dead.
|
||||
change = cmpHealth.Increase(25);
|
||||
TS_ASSERT_EQUALS(change.new, 0);
|
||||
TS_ASSERT_EQUALS(cmpHealth.GetHitpoints(), 0);
|
||||
TS_ASSERT_EQUALS(cmpHealth.GetMaxHitpoints(), 50);
|
||||
TS_ASSERT_EQUALS(cmpHealth.IsInjured(), false);
|
||||
|
||||
// Check that we can't die twice.
|
||||
change = cmpHealth.Reduce(50);
|
||||
TS_ASSERT_EQUALS(change.killed, false);
|
||||
TS_ASSERT_EQUALS(change.change, 0);
|
||||
TS_ASSERT_EQUALS(cmpHealth.GetHitpoints(), 0);
|
||||
TS_ASSERT_EQUALS(cmpHealth.GetMaxHitpoints(), 50);
|
||||
TS_ASSERT_EQUALS(cmpHealth.IsInjured(), false);
|
||||
|
||||
cmpHealth = setEntityUp();
|
||||
|
||||
// Check that we still die with > Max HP of damage.
|
||||
change = cmpHealth.Reduce(60);
|
||||
TS_ASSERT_EQUALS(change.killed, true);
|
||||
TS_ASSERT_EQUALS(change.change, -50);
|
||||
TS_ASSERT_EQUALS(cmpHealth.GetHitpoints(), 0);
|
||||
TS_ASSERT_EQUALS(cmpHealth.GetMaxHitpoints(), 50);
|
||||
TS_ASSERT_EQUALS(cmpHealth.IsInjured(), false);
|
||||
|
||||
cmpHealth = setEntityUp();
|
||||
|
||||
// Check that increasing by more than required puts us at the max HP
|
||||
change = cmpHealth.Reduce(30);
|
||||
change = cmpHealth.Increase(30);
|
||||
TS_ASSERT_EQUALS(injured_flag, false);
|
||||
TS_ASSERT_EQUALS(change.new, 50);
|
||||
TS_ASSERT_EQUALS(cmpHealth.GetHitpoints(), 50);
|
||||
TS_ASSERT_EQUALS(cmpHealth.GetMaxHitpoints(), 50);
|
||||
TS_ASSERT_EQUALS(cmpHealth.IsInjured(), false);
|
||||
TS_ASSERT_EQUALS(cmpHealth.IsUnhealable(), true);
|
Loading…
Reference in New Issue
Block a user