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,19 @@ 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.isRebuildFoundation) + { + const cmpPlayer = QueryOwnerInterface(target, IID_Player); + if (!cmpFoundation.rebuildFoundationPayed && cmpPlayer.TrySubtractResources(cmpFoundation.rebuildFoundationCost)) + cmpFoundation.rebuildFoundationPayed = true + else if (cmpFoundation.rebuildFoundationPayed) + cmpFoundation.InitialiseConstruction(cmpFoundation.rebuildFoundationTemplate); + 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,11 @@ this.buildTimeModifier = +this.template.BuildTimeModifier; this.previewEntity = INVALID_ENTITY; + + this.isRebuildFoundation = false; + this.rebuildFoundationTemplate; + this.rebuildFoundationCost; + this.rebuildFoundationPayed = false; }; Foundation.prototype.Serialize = function() 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.rebuildable) + 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,41 @@ 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 = Engine.AddLocalEntity(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 init handles that. + */ + if (template.includes('foundation')) + { + const cmpFoundation = Engine.QueryInterface(spawnedEntity, IID_Foundation); + cmpFoundation.isRebuildFoundation = true; + cmpFoundation.rebuildFoundationCost = Engine.QueryInterface(this.entity, IID_Cost).GetResourceCosts(); + cmpFoundation.rebuildFoundationTemplate = template.replace('foundation|', ''); + } - 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() { @@ -16,6 +22,8 @@ this.buildMultiplier = 1; // Multiplier for the amount of work builders do this.buildTimePenalty = 0.7; // Penalty for having multiple builders this.repairTimeRatio = +this.template.RepairTimeRatio; + + this.rebuildable = this.template.Rebuildable === 'true'; }; /** 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