Page 1 of 1

NML Industries and persistent storage

Posted: 08 May 2025 20:24
by Uwe
Hi all,

I'm toying around with an industry NewGRF which borrows a feature from dSPI, namely the idea of handling "electricity" by having a power plant store it's production value in the persistent storage of the town as related parent object of the industry. I looked into the sources of dSPI how this is achieved and now I'm trying to copy it - but I fail to get it working. The sources for dSPI mention that this is somewhat tricky and finicky with jumping between SELF and PARENT, as well as somehow requiring STORE_TEMP and STORE_PERM beforehand, so I'm a bit confused on the details here.

The industry itself works and produces "electricity", which can also be stored in the persistent storage of the industry itself. But I completely fail to set a value of produced "electricity" in the persistent storage of the town. In some cases I do not even get to see any persistent registers for the town in the info window within the game, and I have not yet figured out which piece of my code changes that behavior.

Relevant code snippet:

Code: Select all

switch(FEAT_INDUSTRIES, PARENT, set_power_for_city, power,
    [STORE_PERM(power, 5)]
{ return; }

switch(FEAT_INDUSTRIES, SELF, power_plant_switch_produce, 
    [ // check incoming_cargo_waiting, calculate how much to produce, ...
      // power_produced is some calculated value based on incoming_cargo_waiting
      STORE_TEMP(power_produced, 0),
      // store in persistent storage of industry, this works
      STORE_PERM(LOAD_TEMP(0), 0),
      // try storing in persistent storage of town, this does not do anything
      // I also tried other forms of calling that switch, which did not change anything
      set_power_for_city(LOAD_TEMP(0))
    ])
{
    power_plant_produce; // this is the actual produce block where the production happens
}
// ...
item(FEAT_INDUSTRIES, ...) {
    graphics {
        produce_256_ticks: power_plant_switch_produce;
    }
}
Funnily enough, an industry that requires "electricity" can successfully access persistent storage of the same town to store how much "electricity" it requires to be available:

Code: Select all

switch(FEAT_INDUSTRIES, PARENT, add_power_demand, demand, 
    [
         STORE_PERM(LOAD_PERM(3) + demand, 3)
    ])
{
	return;
}

switch(FEAT_INDUSTRIES, SELF, factory_switch_produce,
    [
    // check incoming_cargo_waiting, calculate amount of electricity needed
    // for maximum production
    STORE_TEMP(electricity_needed, 2),
    // store value in persistent storage of town, this works, weirdly enough
    add_power_demand(LOAD_TEMP(2)),
    // further calculation of production amount based on available electricity
    // since the persistent storage is not updated correctly by the power plant,
    // production is calculated to be zero here
    ])
{
    factory_produce;
}
So where am I going wrong? I think I understood the basic idea just fine, and partially it works, but I've already spent two evenings trying to figure out why the power plant does not do what I want it to do.

Regards,
Uwe

Re: NML Industries and persistent storage

Posted: 09 May 2025 00:33
by ChillCore
I dunno but your parameters for setting, storing, loading and using seem f*** up ...
one time you are using 1 parameter and the other time two ????

like I have no clue about all this stuffs but yeah ....

I did check brackets and those seem fine ... ;)

Re: NML Industries and persistent storage

Posted: 09 May 2025 00:44
by ChillCore
like ... I could be spewing crap ...

but ye

add some debug code that dispays values along the way? .... both stored and loaded ... that will help

Re: NML Industries and persistent storage

Posted: 09 May 2025 07:48
by Auge
Hello

i don't know the specifics of NML industry code but you switch-block looks a bit odd to me. Let me provide a very simple code example ...

Code: Select all

//switch based on terrain type in arctic climate
switch(FEAT_ROADTYPES, SELF, underlay_precinct, terrain_type) {
    TILETYPE_SNOW: precinct_underlay_snow;
    default: precinct_underlay;
}
... and a second from the NML tutorial.

Code: Select all

switch (FEAT_TRAINS, PARENT, some_vehicle_switch, (position_in_consist + param[1]) % 4) {
    0..2: return string(STRING_FOO_BAR); //return a text message
    3: return; //return the computed value
    5..300: return 42; //42 is always a good answer
    400: other_switch; //chain to some other switch block
    401: return num_vehs_in_consist + 1; //return a value with a variable access
    CB_FAILED; //return a failure result as default
}
Your code handles everything inside the square brackets block inside the round brackets behind the keyword switch but inside the curly brackets there is only one instruction.

Code: Select all

switch(
    FEAT_INDUSTRIES,
    SELF,
    power_plant_switch_produce, 
    [ // check incoming_cargo_waiting, calculate how much to produce, ...
      // power_produced is some calculated value based on incoming_cargo_waiting
      STORE_TEMP(power_produced, 0),
      // store in persistent storage of industry, this works
      STORE_PERM(LOAD_TEMP(0), 0),
      // try storing in persistent storage of town, this does not do anything
      // I also tried other forms of calling that switch, which did not change anything
      set_power_for_city(LOAD_TEMP(0))
    ]) {
    power_plant_produce; // this is the actual produce block where the production happens
}
In contrast to your code in both of my examples the decision what to do is stored in the curly brackets but not inside the round brackets block. To me it looks, like you used a broken syntax (but as I said, I have no clue about the specifics of industry code).

Tschö, Auge

Re: NML Industries and persistent storage

Posted: 20 May 2025 15:00
by Uwe
I finally got it to work properly. The relevant logic seems to have to look something like this:

Code: Select all

switch(FEAT_INDUSTRIES, PARENT, set_power_for_city, power,
    [STORE_PERM(LOAD_TEMP(0), 5)]
{ power_plant_produce; }

switch(FEAT_INDUSTRIES, SELF, power_plant_switch_produce, 
    [ // check incoming_cargo_waiting, calculate how much to produce, ...
      // power_produced is some calculated value based on incoming_cargo_waiting
      STORE_TEMP(power_produced, 0)
    ])
{
    set_power_for_city;
}
// ...
item(FEAT_INDUSTRIES, ...) {
    graphics {
        produce_256_ticks: power_plant_switch_produce;
    }
}
So in the end, the chain goes through the industry, the parent object (the city) and then to the produce-block. Similarly for the other side (the users of the stored "electricity"). Not sure whether this is the only way to make it work, but at least it works now :-).