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 @@ -285,15 +285,23 @@ // persistent corpse retaining the ResourceSupply element of the parent. let cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); let templateName = cmpTemplateManager.GetCurrentTemplateName(this.entity); - let corpse; + let entCorpse; if (leaveResources) - corpse = Engine.AddEntity("resource|" + templateName); + { + let cmpResourceSupply = Engine.QueryInterface(this.entity, IID_ResourceSupply); + if (cmpResourceSupply) + { + entCorpse = Engine.AddEntity("resource|" + templateName); + let cmpResourceSupplyCorpse = Engine.QueryInterface(entCorpse, IID_ResourceSupply); + cmpResourceSupplyCorpse.SetAmount(cmpResourceSupply.GetCurrentAmount()); + } + } else - corpse = Engine.AddLocalEntity("corpse|" + templateName); + entCorpse = Engine.AddLocalEntity("corpse|" + templateName); // Copy various parameters so it looks just like us - let cmpCorpsePosition = Engine.QueryInterface(corpse, IID_Position); + let cmpCorpsePosition = Engine.QueryInterface(entCorpse, IID_Position); let pos = cmpPosition.GetPosition(); cmpCorpsePosition.JumpTo(pos.x, pos.z); let rot = cmpPosition.GetRotation(); @@ -301,17 +309,17 @@ cmpCorpsePosition.SetXZRotation(rot.x, rot.z); let cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership); - let cmpCorpseOwnership = Engine.QueryInterface(corpse, IID_Ownership); + let cmpCorpseOwnership = Engine.QueryInterface(entCorpse, IID_Ownership); cmpCorpseOwnership.SetOwner(cmpOwnership.GetOwner()); let cmpVisual = Engine.QueryInterface(this.entity, IID_Visual); - let cmpCorpseVisual = Engine.QueryInterface(corpse, IID_Visual); + let cmpCorpseVisual = Engine.QueryInterface(entCorpse, IID_Visual); cmpCorpseVisual.SetActorSeed(cmpVisual.GetActorSeed()); // Make it fall over cmpCorpseVisual.SelectAnimation("death", true, 1.0); - return corpse; + return entCorpse; }; Health.prototype.CreateDeathSpawnedEntity = function() Index: binaries/data/mods/public/simulation/components/ResourceSupply.js =================================================================== --- binaries/data/mods/public/simulation/components/ResourceSupply.js +++ binaries/data/mods/public/simulation/components/ResourceSupply.js @@ -8,6 +8,23 @@ "false" + "25" + "0.8" + + "" + + "" + + "2" + + "1000" + + "" + + "" + + "Alive" + + "2" + + "1000" + + "" + + "" + + "Dead" + + "-1" + + "1000" + + "500" + + "" + + "" + "" + "" + "" + @@ -25,12 +42,52 @@ "" + "" + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "Alive" + + "Dead" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + ""; ResourceSupply.prototype.Init = function() { // Current resource amount (non-negative) - this.amount = this.GetMaxAmount(); + this.amount = +this.template.Amount; + + if (this.template.Change && !this.infinite) + { + for (let changeKey in this.template.Change) + if (this.template.Change[changeKey].Limit !== undefined && this.template.Change[changeKey].Value > 0) + this.maxAmount = Math.max(this.amount, +this.template.Change[changeKey].Limit); + + for (let changeKey in this.template.Change) + this.AddTimer(changeKey); + } // List of IDs for each player this.gatherers = []; @@ -54,7 +111,14 @@ ResourceSupply.prototype.GetMaxAmount = function() { - return +this.template.Amount; + return this.maxAmount !== undefined ? this.maxAmount : +this.template.Amount; +}; + +ResourceSupply.prototype.SetAmount = function(newAmount) +{ + let oldAmount = this.amount; + this.amount = Math.min(Math.max(newAmount, 0), this.GetMaxAmount()); + this.UpdateSupplyStatus(oldAmount); }; ResourceSupply.prototype.GetCurrentAmount = function() @@ -124,17 +188,10 @@ if (this.IsInfinite()) return { "amount": amount, "exhausted": false }; - let oldAmount = this.GetCurrentAmount(); - this.amount = Math.max(0, oldAmount - amount); - - let isExhausted = this.GetCurrentAmount() == 0; - // Remove entities that have been exhausted - if (isExhausted) - Engine.DestroyEntity(this.entity); - - Engine.PostMessage(this.entity, MT_ResourceSupplyChanged, { "from": oldAmount, "to": this.GetCurrentAmount() }); + let oldAmount = this.amount; + this.SetAmount(oldAmount - amount); - return { "amount": oldAmount - this.GetCurrentAmount(), "exhausted": isExhausted }; + return { "amount": oldAmount - this.amount, "exhausted": this.amount == 0 }; }; /** @@ -182,4 +239,71 @@ Engine.PostMessage(this.entity, MT_ResourceSupplyNumGatherersChanged, { "to": this.GetNumGatherers() }); }; +/** + * @param {string} changeKey the name of the Change to apply to the entity. + */ +ResourceSupply.prototype.AddTimer = function(changeKey) +{ + let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); + if (!this.timers) + this.timers = {}; + + let change = this.template.Change[changeKey]; + let interval = ApplyValueModificationsToEntity("ResourceSupply/Change/" + changeKey + "/Interval", +change.Interval, this.entity); + this.timers[changeKey] = cmpTimer.SetTimeout(this.entity, IID_ResourceSupply, "ApplyChanges", interval, changeKey); +}; + +/** + * @param {string} changeKey the name of the change to apply to the entity. + * @param {number} lateness how late the timer was executed after the specified time. + */ +ResourceSupply.prototype.ApplyChanges = function(changeKey, lateness) +{ + let change = this.template.Change[changeKey]; + let cmpHealth = Engine.QueryInterface(this.entity, IID_Health); + if (change.Constraint && + (change.Constraint == "Alive" && !cmpHealth || + change.Constraint == "Dead" && cmpHealth)) + return; + + let newAmount = ApplyValueModificationsToEntity("ResourceSupply/Change/" + changeKey + "/Value", +change.Value, this.entity); + let finalAmount = this.amount + newAmount; + + if (change.Limit !== undefined) + if (newAmount > 0 && finalAmount > +change.Limit || + newAmount < 0 && finalAmount < +change.Limit) + finalAmount = +change.Limit; + + this.SetAmount(finalAmount); + this.AddTimer(changeKey); +}; + +/** + * Notify the other components the resource amoun has changed. + * @param {number} oldAmount the previous amount in the resource supply. + */ +ResourceSupply.prototype.UpdateSupplyStatus = function(oldAmount) +{ + // Remove entities that have been exhausted. + if (this.amount == 0) + Engine.DestroyEntity(this.entity); + + // Do not send messages if the resource count didn't change. + if (oldAmount != this.amount) + Engine.PostMessage(this.entity, MT_ResourceSupplyChanged, { + "from": oldAmount, + "to": this.amount + }); +}; + +ResourceSupply.prototype.OnDestroy = function() +{ + if (!this.timers) + return; + + let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer); + for (let changeKey in this.timers) + cmpTimer.CancelTimer(this.timers[changeKey]); +}; + Engine.RegisterComponentType(IID_ResourceSupply, "ResourceSupply", ResourceSupply); Index: binaries/data/mods/public/simulation/templates/special/filter/resource.xml =================================================================== --- binaries/data/mods/public/simulation/templates/special/filter/resource.xml +++ binaries/data/mods/public/simulation/templates/special/filter/resource.xml @@ -2,6 +2,7 @@ +