Index: binaries/data/mods/public/simulation/components/Builder.js
===================================================================
--- binaries/data/mods/public/simulation/components/Builder.js
+++ binaries/data/mods/public/simulation/components/Builder.js
@@ -95,6 +95,17 @@
if (!this.CanRepair(target))
return false;
+ // check if it's a rebuildable foundation and can be payed for (and do so).
+ const cmpFoundation = Engine.QueryInterface(target, IID_Foundation);
+ if (cmpFoundation && cmpFoundation.IsRebuildable() && !cmpFoundation.IsRebuildPayed())
+ {
+ const cmpPlayer = QueryOwnerInterface(target, IID_Player);
+ if (cmpPlayer.TrySubtractResources(cmpFoundation.GetRebuildCost()))
+ cmpFoundation.SetRebuildPayed();
+ else
+ return false;
+ }
+
let cmpBuilderList = QueryBuilderListInterface(target);
if (cmpBuilderList)
cmpBuilderList.AddBuilder(this.entity);
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
@@ -21,6 +21,8 @@
this.buildTimeModifier = +this.template.BuildTimeModifier;
this.previewEntity = INVALID_ENTITY;
+
+ this.rebuildFoundation;
};
Foundation.prototype.Serialize = function()
@@ -59,6 +61,59 @@
};
/**
+ * This mainly concerns engine spawned entities, because they aren't payed for.
+ * @param {number} ent - Use an alive entity to grab some info from it.
+ * @returns
+ */
+Foundation.prototype.SetRebuildableFromEnt = function(ent)
+{
+ const cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
+ const cmpCost = Engine.QueryInterface(ent, IID_Cost);
+ if (!cmpCost)
+ {
+ warn('invalid entity, has no cmpCost');
+ return;
+ }
+
+ this.rebuildFoundation =
+ {
+ "Rebuildable": true,
+ "Template": cmpTemplateManager.GetCurrentTemplateName(ent),
+ "Cost": cmpCost.GetResourceCosts(),
+ "Payed": false
+ };
+};
+
+Foundation.prototype.IsRebuildable = function()
+{
+ if (this.rebuildFoundation)
+ return this.rebuildFoundation.Rebuildable;
+
+ return false;
+};
+
+Foundation.prototype.GetRebuildCost = function()
+{
+ return this.rebuildFoundation.Cost;
+};
+
+Foundation.prototype.GetRebuildTemplate = function()
+{
+ return this.rebuildFoundation.Template;
+};
+
+Foundation.prototype.SetRebuildPayed = function()
+{
+ this.rebuildFoundation.Payed = true;
+ this.InitialiseConstruction(this.GetRebuildTemplate()); // only initialise if we payed, otherwise we are getting free resources if we destroy it.
+};
+
+Foundation.prototype.IsRebuildPayed = function()
+{
+ return this.rebuildFoundation.Payed;
+};
+
+/**
* Moving the revelation logic from Build to here makes the building sink if
* it is attacked.
*/
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
@@ -284,8 +284,12 @@
PlaySound("death", this.entity);
if (this.template.SpawnEntityOnDeath)
- this.CreateDeathSpawnedEntity();
+ this.CreateEntitiesOnLocation([this.template.SpawnEntityOnDeath]);
+ const cmpRepairable = Engine.QueryInterface(this.entity, IID_Repairable);
+ if (cmpRepairable && cmpRepairable.template.Rebuildable === 'true')
+ this.CreateEntitiesOnLocation(["foundation|" + Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager).GetCurrentTemplateName(this.entity)]);
+
switch (this.template.DeathType)
{
case "corpse":
@@ -401,7 +405,12 @@
});
};
-Health.prototype.CreateDeathSpawnedEntity = function()
+/**
+ * Create entities on the position and at the rotation of this.entity.
+ * @param {array} templates - The templates to spawn
+ * @returns {array} spawnedEntities - Containing the array of the created entity id's.
+ */
+Health.prototype.CreateEntitiesOnLocation = function(templates)
{
// If the unit died while not in the world, don't spawn a death entity for it
// since there's nowhere for it to be placed
@@ -409,23 +418,39 @@
if (!cmpPosition.IsInWorld())
return INVALID_ENTITY;
- // Create SpawnEntityOnDeath entity
- let spawnedEntity = Engine.AddLocalEntity(this.template.SpawnEntityOnDeath);
+ const spawnedEntities = [];
+ for (const template of templates)
+ {
+ const spawnedEntity = template.includes('decay') ? Engine.AddLocalEntity(template) : Engine.AddEntity(template);
- // Move to same position
- let cmpSpawnedPosition = Engine.QueryInterface(spawnedEntity, IID_Position);
- let pos = cmpPosition.GetPosition();
- cmpSpawnedPosition.JumpTo(pos.x, pos.z);
- let rot = cmpPosition.GetRotation();
- cmpSpawnedPosition.SetYRotation(rot.y);
- cmpSpawnedPosition.SetXZRotation(rot.x, rot.z);
+ /**
+ * Initialize some info of the rebuildable foundation.
+ * Engine spawned foundations aren't payed for, this handles that.
+ */
+ if (template.includes('foundation'))
+ {
+ const cmpFoundation = Engine.QueryInterface(spawnedEntity, IID_Foundation);
+ cmpFoundation.SetRebuildableFromEnt(this.entity); // use the still alive entity to fill in some information to be able to rebuild it.
+ }
- let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
- let cmpSpawnedOwnership = Engine.QueryInterface(spawnedEntity, IID_Ownership);
- if (cmpOwnership && cmpSpawnedOwnership)
- cmpSpawnedOwnership.SetOwner(cmpOwnership.GetOwner());
+ // Move to same position
+ let cmpSpawnedPosition = Engine.QueryInterface(spawnedEntity, IID_Position);
+ let pos = cmpPosition.GetPosition();
+ cmpSpawnedPosition.JumpTo(pos.x, pos.z);
+ let rot = cmpPosition.GetRotation();
+ cmpSpawnedPosition.SetYRotation(rot.y);
+ cmpSpawnedPosition.SetXZRotation(rot.x, rot.z);
- return spawnedEntity;
+ let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
+ let cmpSpawnedOwnership = Engine.QueryInterface(spawnedEntity, IID_Ownership);
+ if (cmpOwnership && cmpSpawnedOwnership)
+ cmpSpawnedOwnership.SetOwner(cmpOwnership.GetOwner());
+
+ spawnedEntities.push(spawnedEntity);
+ }
+
+ return spawnedEntities;
+
};
Health.prototype.UpdateActor = function()
Index: binaries/data/mods/public/simulation/components/Repairable.js
===================================================================
--- binaries/data/mods/public/simulation/components/Repairable.js
+++ binaries/data/mods/public/simulation/components/Repairable.js
@@ -4,10 +4,16 @@
"Deals with repairable structures and units." +
"" +
"2.0" +
+ "true" +
"" +
"" +
"" +
- "";
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "";
Repairable.prototype.Init = function()
{
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
@@ -9,6 +9,8 @@
Engine.LoadComponentScript("interfaces/Health.js");
Engine.LoadComponentScript("Health.js");
+Engine.LoadComponentScript("interfaces/Repairable.js");
+
const entity_id = 5;
const corpse_id = entity_id + 1;
Index: binaries/data/mods/public/simulation/templates/template_structure.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_structure.xml
+++ binaries/data/mods/public/simulation/templates/template_structure.xml
@@ -92,6 +92,7 @@
2.0
+ true