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 @@
+