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
@@ -293,9 +293,17 @@
// persistent corpse retaining the ResourceSupply element of the parent.
var cmpTemplateManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager);
var templateName = cmpTemplateManager.GetCurrentTemplateName(this.entity);
- var corpse;
+ let corpse;
if (leaveResources)
- corpse = Engine.AddEntity("resource|" + templateName);
+ {
+ let cmpResourceSupply = Engine.QueryInterface(this.entity, IID_ResourceSupply);
+ if (cmpResourceSupply)
+ {
+ corpse = Engine.AddEntity("resource|" + templateName);
+ let cmpCorpseResourceSupply = Engine.QueryInterface(corpse, IID_ResourceSupply);
+ cmpCorpseResourceSupply.SetAmount(cmpResourceSupply.GetCurrentAmount());
+ }
+ }
else
corpse = Engine.AddLocalEntity("corpse|" + templateName);
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
@@ -4,10 +4,21 @@
"Provides a supply of one particular type of resource." +
"" +
"1000" +
+ "1500" +
"food.meat" +
"false" +
"25" +
"0.8" +
+ "" +
+ "" +
+ "1" +
+ "500" +
+ "" +
+ "" +
+ "" +
+ "1" +
+ "1000" +
+ "" +
"" +
"" +
"" +
@@ -15,6 +26,11 @@
"" +
"Infinity" +
"" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
"" +
Resources.BuildChoicesSchema(true, true) +
"" +
@@ -25,21 +41,68 @@
"" +
"" +
"" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
"";
ResourceSupply.prototype.Init = function()
{
// Current resource amount (non-negative)
- this.amount = this.GetMaxAmount();
+ this.amount = +this.template.Amount;
+ this.maxAmount = this.amount;
+ if (this.template.MaxAmount && +this.template.MaxAmount > this.amount)
+ this.maxAmount = +this.template.MaxAmount;
+ this.infinite = !isFinite(+this.template.Amount);
+
+ if (this.template.Growth)
+ {
+ this.growthRate = ApplyValueModificationsToEntity("ResourceSupply/GrowthRate", +this.template.Growth.Rate, this.entity);
+ this.growthInterval = +this.template.Growth.Interval;
+ this.AddRegenTimer("growthTimer", "GrowSupply", this.growthInterval);
+ }
+
+ if (this.template.Decay && !this.IsInfinite())
+ {
+ this.decayRate = ApplyValueModificationsToEntity("ResourceSupply/DecayRate", +this.template.Decay.Rate, this.entity);
+ this.decayInterval = +this.template.Decay.Interval;
+ this.AddRegenTimer("decayTimer", "DecaySupply", this.decayInterval);
+ }
+
// List of IDs for each player
this.gatherers = [];
- let numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers()
+ let numPlayers = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager).GetNumPlayers();
for (let i = 0; i < numPlayers; ++i)
this.gatherers.push([]);
- this.infinite = !isFinite(+this.template.Amount);
-
let [type, subtype] = this.template.Type.split('.');
this.cachedType = { "generic": type, "specific": subtype };
};
@@ -56,7 +119,7 @@
ResourceSupply.prototype.GetMaxAmount = function()
{
- return +this.template.Amount;
+ return this.maxAmount;
};
ResourceSupply.prototype.GetCurrentAmount = function()
@@ -74,6 +137,15 @@
return this.gatherers.reduce((a, b) => a + b.length, 0);
};
+ResourceSupply.prototype.OnValueModification = function(msg)
+{
+ if (msg.component != "ResourceSupply")
+ return;
+
+ this.decayRate = ApplyValueModificationsToEntity("ResourceSupply/DecayRate", +this.template.Decay.Rate, this.entity);
+ this.growthRate = ApplyValueModificationsToEntity("ResourceSupply/GrowthRate", +this.template.Growth.Rate, this.entity);
+};
+
/* The rate of each additionnal gatherer rate follow a geometric sequence, with diminishingReturns as common ratio. */
ResourceSupply.prototype.GetDiminishingReturns = function()
{
@@ -84,35 +156,33 @@
{
let numGatherers = this.GetNumGatherers();
if (numGatherers > 1)
- return diminishingReturns == 1 ? 1 : (1. - Math.pow(diminishingReturns, numGatherers)) / (1. - diminishingReturns) / numGatherers;
+ return diminishingReturns == 1 ? 1 : (1 - Math.pow(diminishingReturns, numGatherers)) / (1 - diminishingReturns) / numGatherers;
}
}
return null;
};
-ResourceSupply.prototype.TakeResources = function(rate)
+ResourceSupply.prototype.SetAmount = function(newAmount)
{
+ let oldAmount = this.GetCurrentAmount();
+ this.amount = Math.min(Math.max(newAmount, 0), this.GetMaxAmount());
+ this.UpdateSupplyStatus(oldAmount);
+};
+
+ResourceSupply.prototype.TakeResources = function(amount)
+{
// Before changing the amount, activate Fogging if necessary to hide changes
let cmpFogging = Engine.QueryInterface(this.entity, IID_Fogging);
if (cmpFogging)
cmpFogging.Activate();
if (this.infinite)
- return { "amount": rate, "exhausted": false };
+ return { "amount": amount, "exhausted": false };
- // 'rate' should be a non-negative integer
+ let oldAmount = this.GetCurrentAmount();
+ this.SetAmount(oldAmount - amount);
- var old = this.amount;
- this.amount = Math.max(0, old - rate);
- var change = old - this.amount;
-
- // Remove entities that have been exhausted
- if (this.amount === 0)
- Engine.DestroyEntity(this.entity);
-
- Engine.PostMessage(this.entity, MT_ResourceSupplyChanged, { "from": old, "to": this.amount });
-
- return { "amount": change, "exhausted": (this.amount === 0) };
+ return { "amount": oldAmount - this.GetCurrentAmount(), "exhausted": this.GetCurrentAmount() == 0 };
};
ResourceSupply.prototype.GetType = function()
@@ -138,29 +208,93 @@
Engine.PostMessage(this.entity, MT_ResourceSupplyNumGatherersChanged, { "to": this.GetNumGatherers() });
}
+ if (this.growthTimer)
+ {
+ Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer).CancelTimer(this.growthTimer);
+ this.growthTimer = undefined;
+ }
+
+ if (this.decayTimer)
+ {
+ Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer).CancelTimer(this.decayTimer);
+ this.decayTimer = undefined;
+ }
+
return true;
};
// should this return false if the gatherer didn't gather from said resource?
ResourceSupply.prototype.RemoveGatherer = function(gathererID, player)
{
- // this can happen if the unit is dead
- if (player == undefined || player == INVALID_PLAYER)
+ if (player != undefined && player != INVALID_PLAYER)
{
- for (var i = 0; i < this.gatherers.length; ++i)
- this.RemoveGatherer(gathererID, i);
- }
- else
- {
- var index = this.gatherers[player].indexOf(gathererID);
+ let index = this.gatherers[player].indexOf(gathererID);
if (index !== -1)
{
- this.gatherers[player].splice(index,1);
+ this.gatherers[player].splice(index, 1);
// broadcast message, mainly useful for the AIs.
Engine.PostMessage(this.entity, MT_ResourceSupplyNumGatherersChanged, { "to": this.GetNumGatherers() });
return;
}
}
+ // This can happen if the unit is dead
+ else
+ for (let i = 0; i < this.gatherers.length; ++i)
+ this.RemoveGatherer(gathererID, i);
+
+ let hasGatherers = this.gatherers.some(p => !p.length);
+ if(hasGatherers)
+ return;
+
+ if (this.template.Growth && !this.growthTimer)
+ this.AddRegenTimer("growthTimer", "GrowSupply", this.growthInterval);
+
+ if (this.template.Decay && !this.decayTimer && !this.IsInfinite())
+ this.AddRegenTimer("decayTimer", "DecaySupply", this.decayInterval);
};
+ResourceSupply.prototype.AddRegenTimer = function(name, callbackName, interval)
+{
+ let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+ this[name] = cmpTimer.SetInterval(this.entity, IID_ResourceSupply, callbackName, interval, interval, undefined);
+};
+
+ResourceSupply.prototype.GrowSupply = function()
+{
+ if ("GrowsWhenAliveOnly" in this.template.Growth)
+ {
+ let cmpHealth = Engine.QueryInterface(this.entity, IID_Health);
+ if (!cmpHealth)
+ return;
+ }
+
+ this.SetAmount(this.GetCurrentAmount() + this.growthRate);
+};
+
+ResourceSupply.prototype.DecaySupply = function()
+{
+ if ("DecaysWhenDeadOnly" in this.template.Decay)
+ {
+ let cmpHealth = Engine.QueryInterface(this.entity, IID_Health);
+ if (cmpHealth)
+ return;
+ }
+
+ this.SetAmount(this.GetCurrentAmount() - this.decayRate);
+};
+
+ResourceSupply.prototype.UpdateSupplyStatus = function(oldAmount)
+{
+ // Remove entities that have been exhausted.
+ if (this.GetCurrentAmount() == 0)
+ Engine.DestroyEntity(this.entity);
+
+ // Do not send messages if the resource count didn't change.
+ if (oldAmount == this.GetCurrentAmount())
+ return;
+
+ Engine.PostMessage(this.entity, MT_ResourceSupplyChanged, { "from": oldAmount, "to": this.GetCurrentAmount() });
+};
+
+
Engine.RegisterComponentType(IID_ResourceSupply, "ResourceSupply", ResourceSupply);
Index: binaries/data/mods/public/simulation/templates/gaia/fauna_sheep.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/gaia/fauna_sheep.xml
+++ binaries/data/mods/public/simulation/templates/gaia/fauna_sheep.xml
@@ -12,6 +12,19 @@
pitch
+
+ 200
+
+
+ 2
+ 1000
+
+
+
+ 1
+ 1000
+
+
Index: binaries/data/mods/public/simulation/templates/gaia/flora_tree_dead.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/gaia/flora_tree_dead.xml
+++ binaries/data/mods/public/simulation/templates/gaia/flora_tree_dead.xml
@@ -3,6 +3,13 @@
Dead Tree
+
+
+
+ 0.1
+ 1000
+
+
flora/trees/tree_dead.xml
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
@@ -9,6 +9,7 @@
Instead, create a static, unblocking (see #3530 for why) static obstruction.
TODO: this should probably be generalized as a parameter on entity death or something.
-->
+
true
false
Index: binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt.xml
===================================================================
--- binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt.xml
+++ binaries/data/mods/public/simulation/templates/template_unit_fauna_hunt.xml
@@ -12,5 +12,10 @@
100
food.meat
8
+
+
+ 1
+ 1000
+