Index: ps/trunk/binaries/data/mods/public/simulation/components/ResourceSupply.js
===================================================================
--- ps/trunk/binaries/data/mods/public/simulation/components/ResourceSupply.js (revision 19769)
+++ ps/trunk/binaries/data/mods/public/simulation/components/ResourceSupply.js (revision 19770)
@@ -1,175 +1,165 @@
function ResourceSupply() {}
ResourceSupply.prototype.Schema =
"Provides a supply of one particular type of resource." +
"" +
"1000" +
"food.meat" +
"" +
"" +
"" +
"" +
"" +
"Infinity" +
"" +
"" +
Resources.BuildChoicesSchema(true, true) +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"" +
"";
ResourceSupply.prototype.Init = function()
{
// Current resource amount (non-negative)
this.amount = this.GetMaxAmount();
this.gatherers = []; // list of IDs for each players
let cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager); // system component so that's safe.
let numPlayers = cmpPlayerManager.GetNumPlayers();
for (let i = 0; i <= numPlayers; ++i) // use "<=" because we want Gaia too.
this.gatherers.push([]);
this.infinite = !isFinite(+this.template.Amount);
let [type, subtype] = this.template.Type.split('.');
- let resData = type === "treasure" ?
- { "subtypes": Resources.GetNames() } :
- Resources.GetResource(type);
-
- if (!resData || !resData.subtypes[subtype])
- {
- error("ResourceSupply with invalid resource: " + uneval(resData));
- Engine.DestroyEntity(this.entity);
- }
-
this.cachedType = { "generic": type, "specific": subtype };
};
ResourceSupply.prototype.IsInfinite = function()
{
return this.infinite;
};
ResourceSupply.prototype.GetKillBeforeGather = function()
{
return (this.template.KillBeforeGather == "true");
};
ResourceSupply.prototype.GetMaxAmount = function()
{
return +this.template.Amount;
};
ResourceSupply.prototype.GetCurrentAmount = function()
{
return this.amount;
};
ResourceSupply.prototype.GetMaxGatherers = function()
{
return +this.template.MaxGatherers;
};
ResourceSupply.prototype.GetNumGatherers = function()
{
return this.gatherers.reduce((a, b) => a + b.length, 0);
};
/* The rate of each additionnal gatherer rate follow a geometric sequence, with diminishingReturns as common ratio. */
ResourceSupply.prototype.GetDiminishingReturns = function()
{
if ("DiminishingReturns" in this.template)
{
let diminishingReturns = ApplyValueModificationsToEntity("ResourceSupply/DiminishingReturns", +this.template.DiminishingReturns, this.entity);
if (diminishingReturns)
{
let numGatherers = this.GetNumGatherers();
if (numGatherers > 1)
return diminishingReturns == 1 ? 1 : (1. - Math.pow(diminishingReturns, numGatherers)) / (1. - diminishingReturns) / numGatherers;
}
}
return null;
};
ResourceSupply.prototype.TakeResources = function(rate)
{
// 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 };
// '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 });
return { "amount": change, "exhausted": (this.amount === 0) };
};
ResourceSupply.prototype.GetType = function()
{
// All resources must have both type and subtype
return this.cachedType;
};
ResourceSupply.prototype.IsAvailable = function(player, gathererID)
{
if (this.GetNumGatherers() < this.GetMaxGatherers() || this.gatherers[player].indexOf(gathererID) !== -1)
return true;
return false;
};
ResourceSupply.prototype.AddGatherer = function(player, gathererID)
{
if (!this.IsAvailable(player, gathererID))
return false;
if (this.gatherers[player].indexOf(gathererID) === -1)
{
this.gatherers[player].push(gathererID);
// broadcast message, mainly useful for the AIs.
Engine.PostMessage(this.entity, MT_ResourceSupplyNumGatherersChanged, { "to": this.GetNumGatherers() });
}
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 === -1)
{
for (var i = 0; i < this.gatherers.length; ++i)
this.RemoveGatherer(gathererID, i);
}
else
{
var index = this.gatherers[player].indexOf(gathererID);
if (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;
}
}
};
Engine.RegisterComponentType(IID_ResourceSupply, "ResourceSupply", ResourceSupply);