mirror of
https://gitea.wildfiregames.com/0ad/0ad
synced 2026-07-09 08:25:48 -07:00
Adds a new component effectively handling negative resource trickles. Prevents resources from going negative and provides an effect for not being able to pay. The effect chosen for 0 A.D. is having the entity not being controllable. Not used in the public mod itself, but it is in quite some mods. Based on an idea of @Nescio Differential revision: D1323 Comments by: @Angen, (@smiley,) @Stan This was SVN commit r25191.
150 lines
3.4 KiB
JavaScript
150 lines
3.4 KiB
JavaScript
function Upkeep() {}
|
|
|
|
Upkeep.prototype.Schema =
|
|
"<a:help>Controls the resource upkeep of an entity.</a:help>" +
|
|
"<element name='Rates' a:help='Upkeep Rates'>" +
|
|
Resources.BuildSchema("nonNegativeDecimal") +
|
|
"</element>" +
|
|
"<element name='Interval' a:help='Number of milliseconds must pass for the player to pay the next upkeep.'>" +
|
|
"<ref name='nonNegativeDecimal'/>" +
|
|
"</element>";
|
|
|
|
Upkeep.prototype.Init = function()
|
|
{
|
|
this.upkeepInterval = +this.template.Interval;
|
|
this.CheckTimer();
|
|
};
|
|
|
|
/**
|
|
* @return {number} - The interval between resource subtractions, in ms.
|
|
*/
|
|
Upkeep.prototype.GetInterval = function()
|
|
{
|
|
return this.upkeepInterval;
|
|
};
|
|
|
|
/**
|
|
* @return {Object} - The upkeep rates in the form of { "resourceName": {number} }.
|
|
*/
|
|
Upkeep.prototype.GetRates = function()
|
|
{
|
|
return this.rates;
|
|
};
|
|
|
|
/**
|
|
* @return {boolean} - Whether this entity has at least one non-zero amount of resources to pay.
|
|
*/
|
|
Upkeep.prototype.ComputeRates = function()
|
|
{
|
|
this.rates = {};
|
|
let hasUpkeep = false;
|
|
for (let resource in this.template.Rates)
|
|
{
|
|
let rate = ApplyValueModificationsToEntity("Upkeep/Rates/" + resource, +this.template.Rates[resource], this.entity);
|
|
if (rate)
|
|
{
|
|
this.rates[resource] = rate;
|
|
hasUpkeep = true;
|
|
}
|
|
}
|
|
|
|
return hasUpkeep;
|
|
};
|
|
|
|
/**
|
|
* Try to subtract the needed resources.
|
|
* Data and lateness are unused.
|
|
*/
|
|
Upkeep.prototype.Pay = function(data, lateness)
|
|
{
|
|
let cmpPlayer = QueryOwnerInterface(this.entity);
|
|
if (!cmpPlayer)
|
|
return;
|
|
|
|
if (!cmpPlayer.TrySubtractResources(this.rates))
|
|
this.HandleInsufficientUpkeep();
|
|
else
|
|
this.HandleSufficientUpkeep();
|
|
};
|
|
|
|
/**
|
|
* E.g. take a hitpoint, reduce CP.
|
|
*/
|
|
Upkeep.prototype.HandleInsufficientUpkeep = function()
|
|
{
|
|
if (this.unpayed)
|
|
return;
|
|
|
|
let cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity);
|
|
if (cmpIdentity)
|
|
cmpIdentity.SetControllable(false);
|
|
this.unpayed = true;
|
|
};
|
|
|
|
/**
|
|
* Reset to the previous stage.
|
|
*/
|
|
Upkeep.prototype.HandleSufficientUpkeep = function()
|
|
{
|
|
if (!this.unpayed)
|
|
return;
|
|
|
|
let cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity);
|
|
if (cmpIdentity)
|
|
cmpIdentity.SetControllable(true);
|
|
delete this.unpayed;
|
|
};
|
|
|
|
Upkeep.prototype.OnValueModification = function(msg)
|
|
{
|
|
if (msg.component != "Upkeep")
|
|
return;
|
|
|
|
this.CheckTimer();
|
|
};
|
|
|
|
/**
|
|
* Recalculate the interval and update the timer accordingly.
|
|
*/
|
|
Upkeep.prototype.CheckTimer = function()
|
|
{
|
|
if (!this.ComputeRates())
|
|
{
|
|
if (!this.timer)
|
|
return;
|
|
|
|
let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
|
|
cmpTimer.CancelTimer(this.timer);
|
|
delete this.timer;
|
|
return;
|
|
}
|
|
|
|
let oldUpkeepInterval = this.upkeepInterval;
|
|
this.upkeepInterval = ApplyValueModificationsToEntity("Upkeep/Interval", +this.template.Interval, this.entity);
|
|
if (this.upkeepInterval < 0)
|
|
{
|
|
let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
|
|
cmpTimer.CancelTimer(this.timer);
|
|
delete this.timer;
|
|
return;
|
|
}
|
|
|
|
if (this.timer)
|
|
{
|
|
if (this.upkeepInterval == oldUpkeepInterval)
|
|
return;
|
|
|
|
// If the timer wasn't invalidated before (interval <= 0), just update it.
|
|
if (oldUpkeepInterval > 0)
|
|
{
|
|
let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
|
|
cmpTimer.UpdateRepeatTime(this.timer, this.upkeepInterval);
|
|
return;
|
|
}
|
|
}
|
|
|
|
let cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
|
|
this.timer = cmpTimer.SetInterval(this.entity, IID_Upkeep, "Pay", this.upkeepInterval, this.upkeepInterval, undefined);
|
|
};
|
|
|
|
Engine.RegisterComponentType(IID_Upkeep, "Upkeep", Upkeep);
|