NML House with check road position complete example??

Discussions about the technical aspects of graphics development, including NewGRF tools and utilities.

Moderator: Graphics Moderators

Eddi
Tycoon
Tycoon
Posts: 7783
Joined: 17 Jan 2007 00:14

Re: NML House with check road position complete example??

Post by Eddi »

ok, let's try a longer explanation

Code: Select all

switch (FEAT_HOUSES, SELF, switch_combined,
    nearby_tile_class( 0, -1) == TILE_CLASS_ROAD |      // this line has value 1 if true, 0 if false
    nearby_tile_class(-1,  0) == TILE_CLASS_ROAD << 1 | // this line has value 2 if true, 0 if false
    nearby_tile_class( 0,  1) == TILE_CLASS_ROAD << 2 | // this line has value 4 if true, 0 if false 
    nearby_tile_class( 1,  0) == TILE_CLASS_ROAD << 3   // this line has value 8 if true, 0 if false
) 
the "|" operator adds up all the values of the above 4 lines. the summary of these lines will be checked below

Code: Select all

{
	0: <insert target jump here, i'll omit those in the next lines> // this jump will be taken if none of the checks were true
	1: // this jump will be taken if the first check was the only one that is true
	2: // this jump will be taken if the second check was the only one that is true
	4: // this jump will be taken if the third check was the only one that is true
	8: // this jump will be taken if the fourth check was the only one that is true
	3:  // 3=1+2,  this jump will be taken if the first and second check were true
	5:  // 5=1+4,  this jump will be taken if the first and third check were true
	6:  // 6=2+4,  this jump will be taken if the second and third check were true
	9:  // 9=1+8,  this jump will be taken if the first and fourth check were true
	10: // 10=2+8, this jump will be taken if the second and fourth check were true
	12: // 12=4+8, this jump will be taken if the third and fourth check were true
	7:  // 7=1+2+4,  this jump will be taken if the first, second and third check were true
	11: // 11=1+2+8, this jump will be taken if the first, second and fourth check were true
	13: // 13=1+4+8, this jump will be taken if the first, third and fourth check were true
	14: // 14=2+4+8, this jump will be taken if the second, third and fourth check were true
	15: // 15=1+2+4+8,  this jump will be taken if all the checks were true
}
You might not exactly be interested in Ferion, but if you are, have fun :)
temporal8
Traffic Manager
Traffic Manager
Posts: 130
Joined: 17 May 2019 14:15

Re: NML House with check road position complete example??

Post by temporal8 »

There is no case, we can spend more days on this same path and it will be the same. I can understand a code doing reverse engineering, I can understand certain things, but this is beyond me. I want to spend my time doing 3d things for the game, not fighting against code. :D

Code: Select all

grf {
	grfid: "NML\44";
	name: string(STR_REALHOUSETOWN_NAME);
	desc: string(STR_REALHOUSETOWN_DESC);
	version: 0;
	min_compatible_version: 0;
}

cargotable { 
	PASS, MAIL, GOOD, FOOD , RCYC
		
}

/*Road North East*/
spriteset (spriteset_realhousetown_northeast, "realhousetown.png") {
	[98, 8, 44, 36, -22, 0, NOCROP]
}
alternative_sprites (spriteset_realhousetown_northeast, ZOOM_LEVEL_IN_4X, BIT_DEPTH_32BPP, "realhousetown_32.png") { 
  	[0, 0, 256, 256, -109, -154, NOCROP]
}

spritelayout spritelayout_realhousetown_northeast {
	ground {
		sprite: GROUNDSPRITE_NORMAL;
	}
	building {
		sprite: spriteset_realhousetown_northeast;
		recolour_mode: RECOLOUR_REMAP;
		palette: PALETTE_USE_DEFAULT;
		xextent: 8;
		yextent: 16;
		zextent: 27;
		xoffset: 4;
		yoffset: 2;
		zoffset: 0;
		hide_sprite: 0;
	}
}
/*Road South East*/

spriteset (spriteset_realhousetown_southeast, "realhousetown.png") {
	[98, 8, 44, 36, -22, 0, NOCROP]
}
alternative_sprites (spriteset_realhousetown_southeast, ZOOM_LEVEL_IN_4X, BIT_DEPTH_32BPP, "realhousetown_32.png") { 
  	[259, 0, 256, 256, -109, -154, NOCROP]
}

spritelayout spritelayout_realhousetown_southeast {
	ground {
		sprite: GROUNDSPRITE_NORMAL;
	}
	building {
		sprite: spriteset_realhousetown_southeast;
		recolour_mode: RECOLOUR_REMAP;
		palette: PALETTE_USE_DEFAULT;
		xextent: 8;
		yextent: 16;
		zextent: 27;
		xoffset: 4;
		yoffset: 2;
		zoffset: 0;
		hide_sprite: 0;
	}
}
/*Road South West*/

spriteset (spriteset_realhousetown_southwest, "realhousetown.png") {
	[98, 8, 44, 36, -22, 0, NOCROP]
}
alternative_sprites (spriteset_realhousetown_southwest, ZOOM_LEVEL_IN_4X, BIT_DEPTH_32BPP, "realhousetown_32.png") { 
  	[518, 0, 256, 256, -109, -154, NOCROP]
}

spritelayout spritelayout_realhousetown_southwest{
	ground {
		sprite: GROUNDSPRITE_NORMAL;
	}
	building {
		sprite: spriteset_realhousetown_southwest;
		recolour_mode: RECOLOUR_REMAP;
		palette: PALETTE_USE_DEFAULT;
		xextent: 8;
		yextent: 16;
		zextent: 27;
		xoffset: 4;
		yoffset: 2;
		zoffset: 0;
		hide_sprite: 0;
	}
}
/*Road North West*/

spriteset (spriteset_realhousetown_northwest, "realhousetown.png") {
	[98, 8, 44, 36, -22, 0, NOCROP]
}
alternative_sprites (spriteset_realhousetown_northwest, ZOOM_LEVEL_IN_4X, BIT_DEPTH_32BPP, "realhousetown_32.png") { 
  	[777, 0, 256, 256, -109, -154, NOCROP]
}

spritelayout spritelayout_realhousetown_northwest {
	ground {
		sprite: GROUNDSPRITE_NORMAL;
	}
	building {
		sprite: spriteset_realhousetown_northwest;
		recolour_mode: RECOLOUR_REMAP;
		palette: PALETTE_USE_DEFAULT;
		xextent: 8;
		yextent: 16;
		zextent: 27;
		xoffset: 4;
		yoffset: 2;
		zoffset: 0;
		hide_sprite: 0;
	}
}

/* North, South... */

/* North Corner */
spriteset (spriteset_realhousetown_northcorner, "realhousetown.png") {
	[98, 8, 44, 36, -22, 0, NOCROP]
}
alternative_sprites (spriteset_realhousetown_northcorner, ZOOM_LEVEL_IN_4X, BIT_DEPTH_32BPP, "realhousetown_32.png") { 
  	[0, 259, 256, 256, -109, -154, NOCROP]
}

spritelayout spritelayout_realhousetown_northcorner {
	ground {
		sprite: GROUNDSPRITE_NORMAL;
	}
	building {
		sprite: spriteset_realhousetown_northcorner;
		recolour_mode: RECOLOUR_REMAP;
		palette: PALETTE_USE_DEFAULT;
		xextent: 8;
		yextent: 16;
		zextent: 27;
		xoffset: 4;
		yoffset: 2;
		zoffset: 0;
		hide_sprite: 0;
	}
}
/* East Corner */

spriteset (spriteset_realhousetown_eastcorner, "realhousetown.png") {
	[98, 8, 44, 36, -22, 0, NOCROP]
}
alternative_sprites (spriteset_realhousetown_eastcorner, ZOOM_LEVEL_IN_4X, BIT_DEPTH_32BPP, "realhousetown_32.png") { 
  	[259, 259, 256, 256, -109, -154, NOCROP]
}

spritelayout spritelayout_realhousetown_eastcorner {
	ground {
		sprite: GROUNDSPRITE_NORMAL;
	}
	building {
		sprite: spriteset_realhousetown_eastcorner;
		recolour_mode: RECOLOUR_REMAP;
		palette: PALETTE_USE_DEFAULT;
		xextent: 8;
		yextent: 16;
		zextent: 27;
		xoffset: 4;
		yoffset: 2;
		zoffset: 0;
		hide_sprite: 0;
	}
}
/* South Corner */

spriteset (spriteset_realhousetown_southcorner, "realhousetown.png") {
	[98, 8, 44, 36, -22, 0, NOCROP]
}
alternative_sprites (spriteset_realhousetown_southcorner, ZOOM_LEVEL_IN_4X, BIT_DEPTH_32BPP, "realhousetown_32.png") { 
  	[518, 259, 256, 256, -109, -154, NOCROP]
}

spritelayout spritelayout_realhousetown_southcorner{
	ground {
		sprite: GROUNDSPRITE_NORMAL;
	}
	building {
		sprite: spriteset_realhousetown_southcorner;
		recolour_mode: RECOLOUR_REMAP;
		palette: PALETTE_USE_DEFAULT;
		xextent: 8;
		yextent: 16;
		zextent: 27;
		xoffset: 4;
		yoffset: 2;
		zoffset: 0;
		hide_sprite: 0;
	}
}
/* West Corner */

spriteset (spriteset_realhousetown_westcorner, "realhousetown.png") {
	[98, 8, 44, 36, -22, 0, NOCROP]
}
alternative_sprites (spriteset_realhousetown_westcorner, ZOOM_LEVEL_IN_4X, BIT_DEPTH_32BPP, "realhousetown_32.png") { 
  	[777, 259, 256, 256, -109, -154, NOCROP]
}

spritelayout spritelayout_realhousetown_westcorner {
	ground {
		sprite: GROUNDSPRITE_NORMAL;
	}
	building {
		sprite: spriteset_realhousetown_westcorner;
		recolour_mode: RECOLOUR_REMAP;
		palette: PALETTE_USE_DEFAULT;
		xextent: 8;
		yextent: 16;
		zextent: 27;
		xoffset: 4;
		yoffset: 2;
		zoffset: 0;
		hide_sprite: 0;
	}
}



/* Switches */

switch (FEAT_HOUSES, SELF, switch_combined, animation_frame,
    nearby_tile_class( 0, -1) == TILE_CLASS_ROAD |      // this line has value 1 if true, 0 if false
    nearby_tile_class(-1,  0) == TILE_CLASS_ROAD << 1 | // this line has value 2 if true, 0 if false
    nearby_tile_class( 0,  1) == TILE_CLASS_ROAD << 2 | // this line has value 4 if true, 0 if false 
    nearby_tile_class( 1,  0) == TILE_CLASS_ROAD << 3   // this line has value 8 if true, 0 if false
) 

{
	0: spritelayout_realhousetown_northcorner;
	1: spritelayout_realhousetown_northwest;
	2: spritelayout_realhousetown_northeast;
	4: spritelayout_realhousetown_southeast; 
	8: spritelayout_realhousetown_southwest;
	3: spritelayout_realhousetown_northcorner; 
	5: spritelayout_realhousetown_southeast; 
	6: spritelayout_realhousetown_eastcorner; 
	9: spritelayout_realhousetown_westcorner;
	10: spritelayout_realhousetown_southwest; 
	12: spritelayout_realhousetown_southcorner;
	7:  spritelayout_realhousetown_northeast; 
	11: spritelayout_realhousetown_northwest; 
	13: spritelayout_realhousetown_southwest; 
	14: spritelayout_realhousetown_southeast;
	15: spritelayout_realhousetown_southeast; 
}


/* Switches End */

item (FEAT_HOUSES, item_realhousetown, -1, HOUSE_SIZE_1X1) {
	property {
		substitute: 2;
		override: 2;
		population:                 90;
		mail_multiplier:            30;
		accepted_cargos:            [[PASS, 4], [MAIL, 3], [GOOD, 3]];
		probability: 10;
		years_available:            [1855, 2050];
		name: string(STR_REALHOUSETOWN_HOUSE);
                availability_mask: [ALL_TOWNZONES, ALL_CLIMATES];
		building_flags    : bitmask(HOUSE_FLAG_ANIMATE);
		animation_info    : [ANIMATION_LOOPING, 1];
	}
	graphics {
    default: switch_combined;
    anim_control: switch_combined;
	}
}
User avatar
super_dan
Engineer
Engineer
Posts: 10
Joined: 01 Jun 2015 14:25

Re: NML House with check road position complete example??

Post by super_dan »

Hey there, I am currently also experimenting with road detection in order to create a typical Central European town landscape (my planned set: viewtopic.php?t=73137).

As mentioned before in this topic, I use the construction_check-callback for 8 different house items for all directions. My question is: apart from having a slightly longer list of sprite layouts and items, is there any other disadvantage to this method?
User avatar
Andrew350
Chief Executive
Chief Executive
Posts: 733
Joined: 19 Dec 2011 07:54
Location: Washington State, USA
Contact:

Re: NML House with check road position complete example??

Post by Andrew350 »

It means you will use 8x the number of house IDs than you really need, and since you can only have 255, that may be a problem depending on how many houses you want.

If you are comfortable using a not-yet-official version of NML, there is a pull request open on GitHub which would allow you to access town storage and do this properly without houses flipping around: https://github.com/OpenTTD/nml/pull/173
User avatar
super_dan
Engineer
Engineer
Posts: 10
Joined: 01 Jun 2015 14:25

Re: NML House with check road position complete example??

Post by super_dan »

Thanks for the hint. I'll try figure that out.

Summing up the information in this thread, I now understand that I can use that not-yet-official version of NML to bind the graphics to the anim_next_frame-callback rather than using anim_control which would not allow for non-flipping buildings. Right? :?:

There is another reason I want to bind my graphics not to the default-callback: As my mission is to save as many item slots as possible I want to get rid of the availability-years property as a way of introducing different graphics for different historical eras. I've already successfully implemented a function to govern which set of spritelayouts should be used for different time slots. However, binding them to the anim_control callback (the way shown in this thread) makes them still change when the predefined starting years for the respective historical eras are reached.

Would using the version of NML you pointed me to allow for solving this problem?
User avatar
Andrew350
Chief Executive
Chief Executive
Posts: 733
Joined: 19 Dec 2011 07:54
Location: Washington State, USA
Contact:

Re: NML House with check road position complete example??

Post by Andrew350 »

super_dan wrote: 15 May 2021 10:05 Summing up the information in this thread, I now understand that I can use that not-yet-official version of NML to bind the graphics to the anim_next_frame-callback rather than using anim_control which would not allow for non-flipping buildings. Right? :?:
Actually no, I was very wrong with that statement. I overlooked a very simple solution and jumped to an erroneous conclusion which wouldn't in fact solve anything. Apologies :oops:

The easy way to make this work, or at least the way I solved it, is by simply checking for a "dummy" frame before the switch which checks for road position:

Code: Select all

switch (FEAT_HOUSES, SELF, switch_check_road_final, animation_frame) {
	1:  spritelayout_house_1;
	2:  spritelayout_house_2;
	3:  spritelayout_house_3;
	4:  spritelayout_house_4;
	spritelayout_house_0;
}
switch (FEAT_HOUSES, SELF, switch_check_road_northeast, nearby_tile_class(-1, 0)) {
	TILE_CLASS_ROAD:  4;
	CB_RESULT_DO_NOTHING;
}
switch (FEAT_HOUSES, SELF, switch_check_road_southeast, nearby_tile_class(0, 1)) {
	TILE_CLASS_ROAD:  3;
	switch_check_road_northeast;
}
switch (FEAT_HOUSES, SELF, switch_check_road_southwest, nearby_tile_class(1, 0)) {
	TILE_CLASS_ROAD:  2;
	switch_check_road_southeast;
}
switch (FEAT_HOUSES, SELF, switch_check_road_northwest, nearby_tile_class(0, -1)) {
	TILE_CLASS_ROAD:  1;
	switch_check_road_southwest;
}
switch (FEAT_HOUSES, SELF, switch_check_road_initial, animation_frame) {
	0:  switch_check_road_northwest;
	CB_RESULT_DO_NOTHING;
}
switch_check_road_initial is called by the "anim_control" callback, and switch_check_road_final is called by the "default" callback.

In this simplified example I'm only checking in four directions, so frames 1..4 are my actual rotated house sprites. Frame 0 in this case should never be used as long as I cover all cases in the following switch(es). So the first switch in this chain only allows the callback to continue if currently on frame 0 and simply does nothing further if it encounters a different frame (which indicates it has been called before). This simple change will successfully prevent houses from flipping directions when the road changes, and the same tactic should work for your other issue as well :)


Again, apologies for my misdirection here, but hopefully this should finally give a (basic) answer to the original question. There are probably other ways to solve it as well, but this has worked for me :)
temporal8
Traffic Manager
Traffic Manager
Posts: 130
Joined: 17 May 2019 14:15

Re: NML House with check road position complete example??

Post by temporal8 »

Hi, it's been 8 months since the last time and I want to see if I can get this to work to finally release it.

The last time I reached a point where I could not continue anymore since I am not a coder and there are things that I do not understand.

I need help so that the code shows the corners correctly, the last time I tried the code it detected the 4 directions correctly but not the corners.

Andrew350 or Eddi can you give me a hand with this? your names will be present in the newgrf credits of course.

Thanks in advance.
temporal8
Traffic Manager
Traffic Manager
Posts: 130
Joined: 17 May 2019 14:15

Re: NML House with check road position complete example??

Post by temporal8 »

Finally I was able to advance in the code and I managed to detect the corners and some different situations, I still need to fix a few things but I am closer.

Thanks Eddi, I re-read the explanations you gave me in 2020 and finally understood the Pseudo code.
Post Reply

Return to “NewGRF Technical Discussions”

Who is online

Users browsing this forum: No registered users and 3 guests