Allow toggling repairability.

Useful for trigger maps.

Differential Revision: https://code.wildfiregames.com/D3901
This was SVN commit r25393.
This commit is contained in:
wraitii
2021-05-06 14:25:33 +00:00
parent 8b08f4ae7a
commit e0800bc092
4 changed files with 158 additions and 74 deletions
@@ -75,7 +75,7 @@ Builder.prototype.CanRepair = function(target)
{ {
let cmpFoundation = QueryMiragedInterface(target, IID_Foundation); let cmpFoundation = QueryMiragedInterface(target, IID_Foundation);
let cmpRepairable = QueryMiragedInterface(target, IID_Repairable); let cmpRepairable = QueryMiragedInterface(target, IID_Repairable);
if (!cmpFoundation && !cmpRepairable) if (!cmpFoundation && (!cmpRepairable || !cmpRepairable.IsRepairable()))
return false; return false;
let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
@@ -109,7 +109,8 @@ Health.prototype.SetHitpoints = function(value)
Health.prototype.IsRepairable = function() Health.prototype.IsRepairable = function()
{ {
return Engine.QueryInterface(this.entity, IID_Repairable) != null; let cmpRepairable = Engine.QueryInterface(this.entity, IID_Repairable);
return cmpRepairable && cmpRepairable.IsRepairable();
}; };
Health.prototype.IsUnhealable = function() Health.prototype.IsUnhealable = function()
@@ -33,6 +33,19 @@ Repairable.prototype.GetBuildProgress = function()
return hitpoints / maxHitpoints; return hitpoints / maxHitpoints;
}; };
/**
* @return whether this entity can be repaired (this does not account for health).
*/
Repairable.prototype.IsRepairable = function()
{
return !this.unrepairable;
};
Repairable.prototype.SetRepairability = function(repairable)
{
this.unrepairable = !repairable;
};
/** /**
* Returns the current builders. * Returns the current builders.
* *
@@ -1,10 +1,14 @@
Engine.LoadHelperScript("Player.js"); Engine.LoadHelperScript("Player.js");
Engine.LoadComponentScript("interfaces/Builder.js"); Engine.LoadComponentScript("interfaces/Builder.js");
Engine.LoadComponentScript("interfaces/Cost.js");
Engine.LoadComponentScript("interfaces/Foundation.js"); Engine.LoadComponentScript("interfaces/Foundation.js");
Engine.LoadComponentScript("interfaces/Health.js");
Engine.LoadComponentScript("interfaces/Repairable.js"); Engine.LoadComponentScript("interfaces/Repairable.js");
Engine.LoadComponentScript("interfaces/Timer.js"); Engine.LoadComponentScript("interfaces/Timer.js");
Engine.LoadComponentScript("interfaces/UnitAI.js"); Engine.LoadComponentScript("interfaces/UnitAI.js");
Engine.LoadComponentScript("Builder.js"); Engine.LoadComponentScript("Builder.js");
Engine.LoadComponentScript("Health.js");
Engine.LoadComponentScript("Repairable.js");
Engine.LoadComponentScript("Timer.js"); Engine.LoadComponentScript("Timer.js");
const builderId = 6; const builderId = 6;
@@ -22,99 +26,165 @@ AddMock(SYSTEM_ENTITY, IID_TemplateManager, {
Engine.RegisterGlobal("ApplyValueModificationsToEntity", (prop, oVal, ent) => oVal); Engine.RegisterGlobal("ApplyValueModificationsToEntity", (prop, oVal, ent) => oVal);
function testEntitiesList()
{
let cmpBuilder = ConstructComponent(builderId, "Builder", {
"Rate": "1.0",
"Entities": { "_string": "structures/{civ}/barracks structures/{civ}/civil_centre structures/{native}/house" }
});
let cmpBuilder = ConstructComponent(builderId, "Builder", { TS_ASSERT_UNEVAL_EQUALS(cmpBuilder.GetEntitiesList(), []);
"Rate": "1.0",
"Entities": { "_string": "structures/{civ}/barracks structures/{civ}/civil_centre structures/{native}/house" }
});
TS_ASSERT_UNEVAL_EQUALS(cmpBuilder.GetEntitiesList(), []); AddMock(SYSTEM_ENTITY, IID_PlayerManager, {
"GetPlayerByID": id => playerEntityID
});
AddMock(SYSTEM_ENTITY, IID_PlayerManager, { AddMock(playerEntityID, IID_Player, {
"GetPlayerByID": id => playerEntityID "GetCiv": () => "iber",
}); "GetDisabledTemplates": () => ({}),
"GetPlayerID": () => playerId
});
AddMock(playerEntityID, IID_Player, { AddMock(builderId, IID_Ownership, {
"GetCiv": () => "iber", "GetOwner": () => playerId
"GetDisabledTemplates": () => ({}), });
"GetPlayerID": () => playerId
});
AddMock(builderId, IID_Ownership, { AddMock(builderId, IID_Identity, {
"GetOwner": () => playerId "GetCiv": () => "iber"
}); });
AddMock(builderId, IID_Identity, { TS_ASSERT_UNEVAL_EQUALS(cmpBuilder.GetEntitiesList(), ["structures/iber/barracks", "structures/iber/civil_centre", "structures/iber/house"]);
"GetCiv": () => "iber"
});
TS_ASSERT_UNEVAL_EQUALS(cmpBuilder.GetEntitiesList(), ["structures/iber/barracks", "structures/iber/civil_centre", "structures/iber/house"]); AddMock(SYSTEM_ENTITY, IID_TemplateManager, {
"TemplateExists": name => name == "structures/iber/civil_centre"
});
AddMock(SYSTEM_ENTITY, IID_TemplateManager, { TS_ASSERT_UNEVAL_EQUALS(cmpBuilder.GetEntitiesList(), ["structures/iber/civil_centre"]);
"TemplateExists": name => name == "structures/iber/civil_centre"
});
TS_ASSERT_UNEVAL_EQUALS(cmpBuilder.GetEntitiesList(), ["structures/iber/civil_centre"]); AddMock(SYSTEM_ENTITY, IID_TemplateManager, {
"TemplateExists": () => true
});
AddMock(SYSTEM_ENTITY, IID_TemplateManager, { AddMock(playerEntityID, IID_Player, {
"TemplateExists": () => true "GetCiv": () => "iber",
}); "GetDisabledTemplates": () => ({ "structures/athen/barracks": true }),
"GetPlayerID": () => playerId
});
AddMock(playerEntityID, IID_Player, { TS_ASSERT_UNEVAL_EQUALS(cmpBuilder.GetEntitiesList(), ["structures/iber/barracks", "structures/iber/civil_centre", "structures/iber/house"]);
"GetCiv": () => "iber",
"GetDisabledTemplates": () => ({ "structures/athen/barracks": true }),
"GetPlayerID": () => playerId
});
TS_ASSERT_UNEVAL_EQUALS(cmpBuilder.GetEntitiesList(), ["structures/iber/barracks", "structures/iber/civil_centre", "structures/iber/house"]); AddMock(playerEntityID, IID_Player, {
"GetCiv": () => "iber",
"GetDisabledTemplates": () => ({ "structures/iber/barracks": true }),
"GetPlayerID": () => playerId
});
AddMock(playerEntityID, IID_Player, { TS_ASSERT_UNEVAL_EQUALS(cmpBuilder.GetEntitiesList(), ["structures/iber/civil_centre", "structures/iber/house"]);
"GetCiv": () => "iber",
"GetDisabledTemplates": () => ({ "structures/iber/barracks": true }),
"GetPlayerID": () => playerId
});
TS_ASSERT_UNEVAL_EQUALS(cmpBuilder.GetEntitiesList(), ["structures/iber/civil_centre", "structures/iber/house"]); AddMock(playerEntityID, IID_Player, {
"GetCiv": () => "athen",
"GetDisabledTemplates": () => ({ "structures/athen/barracks": true }),
"GetPlayerID": () => playerId
});
AddMock(playerEntityID, IID_Player, { TS_ASSERT_UNEVAL_EQUALS(cmpBuilder.GetEntitiesList(), ["structures/athen/civil_centre", "structures/iber/house"]);
"GetCiv": () => "athen",
"GetDisabledTemplates": () => ({ "structures/athen/barracks": true }),
"GetPlayerID": () => playerId
});
TS_ASSERT_UNEVAL_EQUALS(cmpBuilder.GetEntitiesList(), ["structures/athen/civil_centre", "structures/iber/house"]); TS_ASSERT_UNEVAL_EQUALS(cmpBuilder.GetRange(), { "max": 2, "min": 0 });
TS_ASSERT_UNEVAL_EQUALS(cmpBuilder.GetRange(), { "max": 2, "min": 0 }); AddMock(builderId, IID_Obstruction, {
"GetSize": () => 1
});
AddMock(builderId, IID_Obstruction, { TS_ASSERT_UNEVAL_EQUALS(cmpBuilder.GetRange(), { "max": 3, "min": 0 });
"GetSize": () => 1 }
}); testEntitiesList();
TS_ASSERT_UNEVAL_EQUALS(cmpBuilder.GetRange(), { "max": 3, "min": 0 }); function testBuildingFoundation()
{
let cmpBuilder = ConstructComponent(builderId, "Builder", {
"Rate": "1.0",
"Entities": { "_string": "" }
});
// Test repairing. AddMock(playerEntityID, IID_Player, {
AddMock(playerEntityID, IID_Player, { "IsAlly": (p) => p == playerId
"IsAlly": (p) => p == playerId });
});
AddMock(target, IID_Ownership, { AddMock(target, IID_Ownership, {
"GetOwner": () => playerId "GetOwner": () => playerId
}); });
let increased = false; let increased = false;
AddMock(target, IID_Foundation, { AddMock(target, IID_Foundation, {
"Build": (entity, amount) => { "Build": (entity, amount) => {
increased = true; increased = true;
TS_ASSERT_EQUALS(amount, 1); TS_ASSERT_EQUALS(amount, 1);
}, },
"AddBuilder": () => {} "AddBuilder": () => {}
}); });
let cmpTimer = ConstructComponent(SYSTEM_ENTITY, "Timer"); let cmpTimer = ConstructComponent(SYSTEM_ENTITY, "Timer");
TS_ASSERT(cmpBuilder.StartRepairing(target)); TS_ASSERT(cmpBuilder.StartRepairing(target));
cmpTimer.OnUpdate({ "turnLength": 1 }); cmpTimer.OnUpdate({ "turnLength": 1 });
TS_ASSERT(increased); TS_ASSERT(increased);
increased = false; increased = false;
cmpTimer.OnUpdate({ "turnLength": 2 }); cmpTimer.OnUpdate({ "turnLength": 2 });
TS_ASSERT(increased); TS_ASSERT(increased);
}
testBuildingFoundation();
function testRepairing()
{
AddMock(playerEntityID, IID_Player, {
"IsAlly": (p) => p == playerId
});
let cmpBuilder = ConstructComponent(builderId, "Builder", {
"Rate": "1.0",
"Entities": { "_string": "" }
});
AddMock(target, IID_Ownership, {
"GetOwner": () => playerId
});
AddMock(target, IID_Cost, {
"GetBuildTime": () => 100
});
let cmpTargetHealth = ConstructComponent(target, "Health", {
"Max": 100,
"RegenRate": 0,
"IdleRegenRate": 0,
"DeathType": "vanish",
"Unhealable": false
});
cmpTargetHealth.SetHitpoints(50);
DeleteMock(target, IID_Foundation);
let cmpTargetRepairable = ConstructComponent(target, "Repairable", {
"RepairTimeRatio": 1,
});
let cmpTimer = ConstructComponent(SYSTEM_ENTITY, "Timer");
TS_ASSERT(cmpTargetRepairable.IsRepairable());
TS_ASSERT(cmpBuilder.StartRepairing(target));
cmpTimer.OnUpdate({ "turnLength": 1 });
TS_ASSERT_EQUALS(cmpTargetHealth.GetHitpoints(), 51);
cmpTimer.OnUpdate({ "turnLength": 1 });
TS_ASSERT_EQUALS(cmpTargetHealth.GetHitpoints(), 52);
cmpTargetRepairable.SetRepairability(false);
cmpTimer.OnUpdate({ "turnLength": 1 });
TS_ASSERT_EQUALS(cmpTargetHealth.GetHitpoints(), 52);
cmpTargetRepairable.SetRepairability(true);
// Check that we indeed stopped - shouldn't restart on its own.
cmpTimer.OnUpdate({ "turnLength": 1 });
TS_ASSERT_EQUALS(cmpTargetHealth.GetHitpoints(), 52);
TS_ASSERT(cmpBuilder.StartRepairing(target));
cmpTimer.OnUpdate({ "turnLength": 1 });
TS_ASSERT_EQUALS(cmpTargetHealth.GetHitpoints(), 53);
}
testRepairing();