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,70 @@
"" +
"" +
"" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
"";
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.growsWhenAliveOnly = "GrowsWhenAliveOnly" in this.template.Growth;
+ this.growthRate = ApplyValueModificationsToEntity("ResourceSupply/GrowthRate", +this.template.Growth.Rate, this.entity);
+ this.growthInterval = +this.template.Growth.Interval;
+ this.AddGrowthTimer();
+ }
+
+ if (this.template.Decay && !this.infinite)
+ {
+ this.decaysWhenDeadOnly = "DecaysWhenDeadOnly" in this.template.Decay;
+ this.decayRate = ApplyValueModificationsToEntity("ResourceSupply/DecayRate", +this.template.Decay.Rate, this.entity);
+ this.decayInterval = +this.template.Decay.Interval;
+ this.AddDecayTimer();
+ }
// 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 +121,7 @@
ResourceSupply.prototype.GetMaxAmount = function()
{
- return +this.template.Amount;
+ return this.maxAmount;
};
ResourceSupply.prototype.GetCurrentAmount = function()
@@ -74,6 +139,16 @@
return this.gatherers.reduce((a, b) => a + b.length, 0);
};
+
+Health.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,12 +159,19 @@
{
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.SetAmount = function(newAmount)
+{
+ var oldAmount = this.GetCurrentAmount();
+ this.amount = Math.min(Math.max(newAmount, 0), this.GetMaxAmount());
+ this.UpdateSupplyStatus(oldAmount);
+};
+
ResourceSupply.prototype.TakeResources = function(rate)
{
// Before changing the amount, activate Fogging if necessary to hide changes
@@ -100,19 +182,10 @@
if (this.infinite)
return { "amount": rate, "exhausted": false };
- // 'rate' should be a non-negative integer
-
- 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 });
+ let oldAmount = this.GetCurrentAmount();
+ this.SetAmount(oldAmount - rate);
- return { "amount": change, "exhausted": (this.amount === 0) };
+ return { "amount": oldAmount - this.GetCurrentAmount(), "exhausted": this.GetCurrentAmount() === 0 };
};
ResourceSupply.prototype.GetType = function()
@@ -138,29 +211,99 @@
Engine.PostMessage(this.entity, MT_ResourceSupplyNumGatherersChanged, { "to": this.GetNumGatherers() });
}
+ if (this.growthTimer)
+ {
+ Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer).CancelTimer(this.growthTimer);
+ this.growthTimer = null;
+ }
+
+ if (this.decayTimer)
+ {
+ Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer).CancelTimer(this.decayTimer);
+ this.decayTimer = null;
+ }
+
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)
- {
- for (var i = 0; i < this.gatherers.length; ++i)
- this.RemoveGatherer(gathererID, i);
- }
- else
+ if (player != undefined && player != INVALID_PLAYER)
{
var 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 (var 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.AddGrowthTimer();
+
+ if (this.template.Decay && !this.decayTimer)
+ this.AddDecayTimer();
+};
+
+ResourceSupply.prototype.AddGrowthTimer = function()
+{
+ let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+ this.growthTimer = cmpTimer.SetInterval(this.entity, IID_ResourceSupply, "GrowSupply", this.growthInterval, this.growthInterval, undefined);
+};
+
+ResourceSupply.prototype.AddDecayTimer = function()
+{
+ let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
+ this.decayTimer = cmpTimer.SetInterval(this.entity, IID_ResourceSupply, "DecaySupply", this.decayInterval, this.decayInterval, undefined);
+};
+
+ResourceSupply.prototype.GrowSupply = function()
+{
+ if (this.growsWhenAliveOnly)
+ {
+ let cmpHealth = Engine.QueryInterface(this.entity, IID_Health);
+ if (!cmpHealth)
+ return;
+ }
+
+ this.SetAmount(this.GetCurrentAmount() + this.growthRate);
+};
+
+ResourceSupply.prototype.DecaySupply = function()
+{
+ if (this.decaysWhenDeadOnly)
+ {
+ 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
+