Page 1 of 1

[JGRPP] Manipulate Town zones

Posted: 25 Mar 2024 17:15
by BW89
Hello!
I am trying to make a simple GRF that creates scaled towns (ie a 2000 Town only gets small houses instead of big blocks...) -> see attached image.
towns_planned.png
(516.17 KiB) Not downloaded yet
As a first attempt in manipulating town zones i want to try to force zones at different populations (<1000 = zone 0; 1000-2500 = zone 1,...).
The GRF compiles, but nothing happenes. I am shure that i miss something, but i do not know what.

Code: Select all

grf {
	grfid: "BW\01\01";
	name: string(STR_GRF_NAME);
	desc: string(STR_GRF_DESCRIPTION);
	version: 0;
	min_compatible_version: 0;
}
if (!extended_feature_test("town_zone_callback")) {
	error(FATAL, string(STR_UNSUPPORTED_VERSION));
}

switch (FEAT_TOWN, SELF, townTest, population_uncapped){
	0..1000: return 0x100;
	1000..2500: return 0x101;
	2500..3000: return 0x102;
	3000..5000: return 0x103;
	return 0x104;
}
item (FEAT_TOWN, town_cb, GENERIC_CALLBACK) {
	graphics{
		town_zone: townTest;
	}
}
		
I created this based on the syntax example from here and the NML wiki.

What am i doing wrong?

Thank you for any help!

Re: [JGRPP] Manipulate Town zones

Posted: 25 Mar 2024 23:12
by Eddi
where is that callback documented?

because it doesn't make sense that it works like you think it does.

Re: [JGRPP] Manipulate Town zones

Posted: 25 Mar 2024 23:52
by peter1138
The return value of the callback is the version of the result format returned by the callback.
Currently only version 0 is defined.
The callback must store the values of the town zone radii into registers: 0x100 to 0x104, for zones 0 to 4 respectively, using STORE_TEMP.
You need to store into registers 0x100 to 0x104, and return 0, not return a value from 0x100 to 0x104.

Re: [JGRPP] Manipulate Town zones

Posted: 26 Mar 2024 07:37
by Eddi
so, your callback should probably look more like this:
(pseudocode)

Code: Select all

switch(calc_village, [
    STORE_TEMP(0x100, R0),  // replace the placeholders R0..R4 with some sane calculation
    STORE_TEMP(0x101, R1),
    STORE_TEMP(0x102, R2),
    STORE_TEMP(0x103, R3),
    STORE_TEMP(0x104, R4),
    0]) { // <-- this 0 is the return value "format version"
        return;
    }

// snip //

switch(calc_radius, population) {
    0..500: calc_village;
    501..5000: calc_town;
    5001..50000: calc_city;
    default: calc_metropolis;
}
note that using "population" instead of "houses" here is probably a desync hazard, as the population of a house changes during its lifetime (by default it starts at 0, and only gets its full population after all the construction phases finished)

to resolve this, the callback result needs to be stored in the savegame, instead of being recalculated on game load