Ticket #1973: regenerative-resources.patch

File regenerative-resources.patch, 7.5 KB (added by alpha123, 11 years ago)
  • binaries/data/mods/public/simulation/components/ResourceSupply.js

     
    3030            "<value>treasure.food</value>" +
    3131        "</choice>" +
    3232    "</element>" +
     33    "<optional>" +
     34        "<element name='Regeneration' a:help='Controls whether this resource can regenerate its remaining amount.'>" +
     35            "<interleave>" +
     36                "<element name='Rate' a:help='Optional regeneration rate. Resources/second if the growth is linear or the rate of population growth if the growith is exponential.'>" +
     37                    "<data type='decimal'/>" +
     38                "</element>" +
     39                "<element name='Delay' a:help='Seconds between when the number of gatherers hit 0 and the resource starts regenerating.'>" +
     40                    "<data type='nonNegativeInteger'/>" +
     41                "</element>" +
     42                "<element name='Growth' a:help='Growth formula for regeneration. Either linear or exponential. Linear continually adds the rate, while exponential uses it as the rate in the standard population growth formula.'>" +
     43                    "<choice>" +
     44                        "<value>linear</value>" +
     45                        "<value>exponential</value>" +
     46                    "</choice>" +
     47                "</element>" +
     48            "</interleave>" +
     49        "</element>" +
     50    "</optional>" +
    3351    "<element name='MaxGatherers' a:help='Amount of gatherers who can gather resources from this entity at the same time'>" +
    3452        "<data type='nonNegativeInteger'/>" +
    3553    "</element>";
     
    3856{
    3957    // Current resource amount (non-negative)
    4058    this.amount = this.GetMaxAmount();
    41     this.gatherers = [];    // list of IDs
     59    this.gatherers = [];    // list of IDs
     60    if (this.template.Regeneration !== undefined) {
     61        this.regenRate = +this.template.Regeneration.Rate;
     62        this.regenDelay = +this.template.Regeneration.Delay;
     63        this.regenGrowth = this.template.Regeneration.Growth;
     64        this.RegenerateResources({rate: 0});
     65    }
     66    else {
     67        this.regenRate = 0;
     68        this.regenDelay = 0;
     69        this.regenGrowth = "";
     70    }
    4271};
    4372
    4473ResourceSupply.prototype.GetKillBeforeGather = function()
     
    75104    var change = old - this.amount;
    76105
    77106    // Remove entities that have been exhausted
    78     if (this.amount == 0)
     107    if (this.amount == 0 && !this.IsRegenerative())
    79108        Engine.DestroyEntity(this.entity);
    80109
    81110    Engine.PostMessage(this.entity, MT_ResourceSupplyChanged, { "from": old, "to": this.amount });
    82111
    83     return { "amount": change, "exhausted": (this.amount == 0) };
     112    return { "amount": change, "exhausted": this.amount == 0 };
    84113};
    85114
     115ResourceSupply.prototype.RegenerateResources = function(data, lateness) {
     116    var max = this.GetMaxAmount();
     117    if (this.gatherers.length == 0 && !this.regenDelayTimer && this.amount < max) {
     118        var old = this.amount;
     119        if (this.regenTime == null)
     120            this.regenTime == 0;
     121        if (this.regenGrowth == "linear")
     122            this.amount = Math.min(max, this.amount + data.rate);
     123        else
     124            this.amount = Math.min(max, Math.round(this.amount * Math.pow(Math.E, data.rate / 100 * this.regenTime)));
     125        ++this.regenTime;
     126        Engine.PostMessage(this.entity, MT_ResourceSupplyChanged, { "from": old, "to": this.amount });
     127    }
     128    if (this.amount == max)
     129        this.regenTime = null;
     130    var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
     131    var regenRate = this.GetRegenerationRate();
     132    var absRegen = Math.abs(regenRate);
     133    if (Math.floor(regenRate) == regenRate || this.regenGrowth == "exponential")
     134        cmpTimer.SetTimeout(this.entity, IID_ResourceSupply, "RegenerateResources", 1000, { "rate": regenRate });
     135    else
     136        cmpTimer.SetTimeout(this.entity, IID_ResourceSupply, "RegenerateResources", 1000 / absRegen,
     137                { "rate": absRegen == regenRate ? 1 : -1 });
     138};
     139
     140ResourceSupply.prototype.StartRegenerationDelayTimer = function() {
     141    var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
     142    this.regenDelayTimer = cmpTimer.SetTimeout(this.entity, IID_ResourceSupply, "CancelRegenerationDelayTimer", this.GetRegenerationDelay() * 1000, null);
     143};
     144
     145ResourceSupply.prototype.CancelRegenerationDelayTimer = function() {
     146    var cmpTimer = Engine.QueryInterface(SYSTEM_ENTITY, IID_Timer);
     147    cmpTimer.CancelTimer(this.regenDelayTimer);
     148    this.regenDelayTimer = null;
     149};
     150
    86151ResourceSupply.prototype.GetType = function()
    87152{
    88153    // All resources must have both type and subtype
     
    98163    return false;
    99164};
    100165
     166ResourceSupply.prototype.IsRegenerative = function() {
     167    return this.GetRegenerationRate() != 0;
     168};
     169
     170ResourceSupply.prototype.GetTerritoryOwner = function () {
     171    var cmpPlayerManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager);
     172    var cmpTerritoryManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_TerritoryManager);
     173    var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
     174    if (!(cmpPosition && cmpPosition.IsInWorld()))
     175        return 0;  // Something's wrong, just say we're in neutral territory.
     176    var pos = cmpPosition.GetPosition2D();
     177    return cmpPlayerManager.GetPlayerByID(cmpTerritoryManager.GetOwner(pos.x, pos.y));
     178};
     179
     180ResourceSupply.prototype.GetRegenerationRate = function() {
     181    return ApplyTechModificationsToPlayer("ResourceSupply/Regeneration/Rate", this.regenRate, this.GetTerritoryOwner());
     182};
     183
     184ResourceSupply.prototype.GetRegenerationDelay = function() {
     185    return ApplyTechModificationsToPlayer("ResourcesSupply/Regeneration/Delay", this.regenDelay, this.GetTerritoryOwner());
     186};
     187
    101188ResourceSupply.prototype.AddGatherer = function(gathererID)
    102189{
    103190    if (!this.IsAvailable(gathererID))
     
    106193    if (this.gatherers.indexOf(gathererID) === -1)
    107194    {
    108195        this.gatherers.push(gathererID);
     196        this.CancelRegenerationDelayTimer();
    109197        // broadcast message, mainly useful for the AIs.
    110198        Engine.PostMessage(this.entity, MT_ResourceSupplyGatherersChanged, { "to": this.gatherers });
    111199    }
     
    122210        // broadcast message, mainly useful for the AIs.
    123211        Engine.PostMessage(this.entity, MT_ResourceSupplyGatherersChanged, { "to": this.gatherers });
    124212    }
     213    if (this.gatherers.length == 0)
     214        this.StartRegenerationDelayTimer();
    125215};
    126216
    127217Engine.RegisterComponentType(IID_ResourceSupply, "ResourceSupply", ResourceSupply);
  • binaries/data/mods/public/simulation/templates/template_gaia_flora_bush_berry.xml

     
    1919    <KillBeforeGather>false</KillBeforeGather>
    2020    <Amount>200</Amount>
    2121    <Type>food.fruit</Type>
    22     <MaxGatherers>8</MaxGatherers>
     22    <MaxGatherers>8</MaxGatherers>
     23    <Regeneration>
     24      <Rate>10</Rate>
     25      <Delay>10</Delay>
     26      <Growth>linear</Growth>
     27    </Regeneration>
    2328  </ResourceSupply>
    2429  <Selectable>
    2530    <EditorOnly disable=""/>
  • binaries/data/mods/public/simulation/templates/template_unit_fauna_fish.xml

     
    2222    <KillBeforeGather>false</KillBeforeGather>
    2323    <Amount>1000</Amount>
    2424    <Type>food.fish</Type>
    25     <MaxGatherers>4</MaxGatherers>
     25    <MaxGatherers>4</MaxGatherers>
     26    <Regeneration>
     27      <Rate>1.68</Rate>
     28      <Delay>5</Delay>
     29      <Growth>exponential</Growth>
     30    </Regeneration>
    2631  </ResourceSupply>
    2732  <Selectable>
    2833    <Overlay>