Index: binaries/data/mods/public/simulation/components/Foundation.js
===================================================================
--- binaries/data/mods/public/simulation/components/Foundation.js
+++ binaries/data/mods/public/simulation/components/Foundation.js
@@ -1,7 +1,19 @@
function Foundation() {}
Foundation.prototype.Schema =
- "";
+ "Defines the spot on top of which a building can be built." +
+ "" +
+ ""
+ "1.0" +
+ ""
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ ""
+ "" +
+ "";
Foundation.prototype.Init = function()
{
@@ -18,6 +30,9 @@
this.buildTimePenalty = 0.7; // Penalty for having multiple builders
this.previewEntity = INVALID_ENTITY;
+
+ if (this.template.AutoBuild)
+ this.StartTimer();
};
Foundation.prototype.InitialiseConstruction = function(owner, template)
@@ -124,7 +139,16 @@
if (this.builders.has(builderEnt))
return;
- this.builders.set(builderEnt, Engine.QueryInterface(builderEnt, IID_Builder).GetRate());
+ let rate = 0;
+ let cmpBuilder = Engine.QueryInterface(builderEnt, IID_Builder);
+ if (cmpBuilder)
+ rate = cmpBuilder.GetRate();
+ else if(this.template.AutoBuild)
+ rate = this.GetAutoBuildRate();
+ else
+ return;
+
+ this.builders.set(builderEnt, rate);
this.totalBuilderRate += this.builders.get(builderEnt);
this.SetBuildMultiplier();
@@ -421,5 +445,36 @@
return cmpHealth.GetMaxHitpoints() / cmpCost.GetBuildTime();
};
+Foundation.prototype.StartTimer = function()
+{
+ if (this.timer)
+ return;
+
+ this.AddBuilder(this.entity);
+ let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+ this.timer = cmpTimer.SetInterval(this.entity, IID_Foundation, "AutoBuild", 0, 1000, undefined);
+};
+
+Foundation.prototype.CancelTimer = function()
+{
+ if (!this.timer)
+ return;
+
+ this.RemoveBuilder(this.entity);
+ let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+ cmpTimer.CancelTimer(this.timer);
+ delete this.timer;
+};
+
+Foundation.prototype.GetAutoBuildRate = function()
+{
+ return ApplyValueModificationsToEntity("Foundation/AutoBuild/Rate", this.template.AutoBuild ? +this.template.AutoBuild.Rate : 0, this.entity);
+};
+
+Foundation.prototype.AutoBuild = function()
+{
+ this.Build(this.entity, this.GetAutoBuildRate());
+};
+
Engine.RegisterComponentType(IID_Foundation, "Foundation", Foundation);
Index: binaries/data/mods/public/simulation/components/tests/test_Foundation.js
===================================================================
--- binaries/data/mods/public/simulation/components/tests/test_Foundation.js
+++ binaries/data/mods/public/simulation/components/tests/test_Foundation.js
@@ -1,24 +1,27 @@
Engine.LoadHelperScript("Player.js");
+Engine.LoadHelperScript("ValueModification.js");
Engine.LoadComponentScript("interfaces/Builder.js");
Engine.LoadComponentScript("interfaces/Cost.js");
Engine.LoadComponentScript("interfaces/Foundation.js");
Engine.LoadComponentScript("interfaces/Health.js");
+Engine.LoadComponentScript("interfaces/ModifiersManager.js");
Engine.LoadComponentScript("interfaces/StatisticsTracker.js");
Engine.LoadComponentScript("interfaces/TerritoryDecay.js");
Engine.LoadComponentScript("interfaces/Trigger.js");
+Engine.LoadComponentScript("interfaces/Timer.js");
Engine.LoadComponentScript("Foundation.js");
-
+Engine.LoadComponentScript("Timer.js");
let player = 1;
let playerEnt = 3;
let foundationEnt = 20;
let previewEnt = 21;
let newEnt = 22;
+let finalTemplate = "structures/athen_civil_centre.xml";
function testFoundation(...mocks)
{
ResetState();
- let finalTemplate = "structures/athen_civil_centre.xml";
let foundationHP = 1;
let maxHP = 100;
let rot = new Vector3D(1, 2, 3);
@@ -177,6 +180,7 @@
TS_ASSERT_EQUALS(foundationHP, 1 + work * cmpFoundation.GetBuildRate() * cmpFoundation.buildMultiplier);
TS_ASSERT_EQUALS(cmpFoundation.maxProgress, foundationHP / maxHP);
TS_ASSERT_EQUALS(cmpFoundation.totalBuilderRate, 5);
+ TS_ASSERT_EQUALS(cmpFoundation.GetAutoBuildRate(), 0);
// FINISH CONSTRUCTION
Engine.AddEntity = function(template) {
@@ -209,3 +213,44 @@
},
}]);
+// Test autobuild feature.
+const foundationEnt2 = 42;
+let turnLength = 0.2;
+let currentFoundationHP = 1;
+let cmpTimer = ConstructComponent(SYSTEM_ENTITY, "Timer");
+const cmpAutoBuildingFoundation = ConstructComponent(foundationEnt2, "Foundation", { "AutoBuild": { "Rate": "1.0" } });
+AddMock(foundationEnt2, IID_Cost, {
+ "GetBuildTime": () => 50,
+ "GetResourceCosts": () => ({ "wood": 100 }),
+});
+AddMock(foundationEnt2, IID_Health, {
+ "GetHitpoints": () => currentFoundationHP,
+ "GetMaxHitpoints": () => 100,
+ "Increase": hp => {
+ currentFoundationHP = Math.min(currentFoundationHP + hp, 100);
+ cmpAutoBuildingFoundation.OnHealthChanged();
+ },
+});
+cmpAutoBuildingFoundation.InitialiseConstruction(player, finalTemplate);
+
+// We start at 3 cause there is no delay on the first run.
+cmpTimer.OnUpdate({ "turnLength": turnLength });
+
+for (let i = 0; i < 10; ++i)
+{
+ if (i == 8)
+ {
+ cmpAutoBuildingFoundation.CancelTimer();
+ TS_ASSERT_EQUALS(cmpAutoBuildingFoundation.GetNumBuilders(), 0);
+ }
+
+ let currentPercentage = cmpAutoBuildingFoundation.GetBuildPercentage()
+ cmpTimer.OnUpdate({ "turnLength": turnLength * 5});
+ let newPercentage = cmpAutoBuildingFoundation.GetBuildPercentage();
+
+ if(i >= 8)
+ TS_ASSERT_EQUALS(currentPercentage, newPercentage);
+ else
+ // Rate * Max Health / Cost.
+ TS_ASSERT_EQUALS(currentPercentage + 2, newPercentage);
+}