Page 1 of 1

NML: Multi-tile houses

Posted: 03 Dec 2021 20:33
by GojkoG
Here’s an example for making multi-tile houses and objects in NML, because it is a different (but easier) from the NFO byte code, where you define the other tiles as own items. (And I was searching for hours to figure it out.) Big thanks to Bad_Brett whose comment was the hint I needed!
[…] for houses, we have the graphics_[north|west|east|south] callbacks.
(viewtopic.php?p=1247851&hilit=multi+tile#p1247851)

Code: Select all

item (FEAT_HOUSES, item_Stadium, 0xC0, HOUSE_SIZE_2X2) {
	property { … }
	graphics {
		graphics_north: sprtLyt_Stadium_N;
		graphics_east: sprtLyt_Stadium_E;
		graphics_west: sprtLyt_Stadium_W;
		graphics_south: sprtLyt_Stadium_S;
	}
}
You use the house callbacks. (And after figuring it out I now see that I could have read it by combining what is written in the NML tutorial and the things on the “NML:Houses” page. But it’s not obvious to see that “house callbacks” refers to the “graphics” block.)

And for objects:

Code: Select all

switch (FEAT_OBJECTS, SELF, switchObj_Stadium_tiles, relative_pos) {
		0x0000: sprtLyt_Stadium_N;
		0x0100: sprtLyt_Stadium_E;
		0x0001: sprtLyt_Stadium_W;
		0x0101: sprtLyt_Stadium_S;
}	

item (FEAT_OBJECTS, item_Stadium, 0xC0) {
	property { … }
	graphics {
		default: switchObj_Stadium_tiles;
	}
}

Re: NML: Multi-tile houses

Posted: 04 Dec 2021 19:52
by temporal8
Thank you very much for your contribution, it is very useful.

Question, how would you add street detection to that example?

I'm working on a town set and I need to figure out how to add street detection to the 2x1 and 2x2 Houses, I only have it working for 1x1.

This is a working code with road detection for 1x1 house:

Code: Select all

// 1x1 HOUSE

/*Road South West*/

spriteset (spriteset_realhousetown_1X1_001_southwest, "realhousetown.png") {
	[98, 8, 44, 36, -22, 0, NOCROP]
}
alternative_sprites (spriteset_realhousetown_1X1_001_southwest, ZOOM_LEVEL_IN_4X, BIT_DEPTH_32BPP, "gfx/realhousetown_32_005.png") { 
  	[0, 0, 256, 256, -107, -154, NOCROP]
}

spritelayout spritelayout_realhousetown_1X1_001_southwest{
	ground {
		sprite: GROUNDSPRITE_NORMAL;
	}
	building {
		sprite: spriteset_realhousetown_1X1_001_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_1X1_001_northwest, "realhousetown.png") {
	[98, 8, 44, 36, -22, 0, NOCROP]
}
alternative_sprites (spriteset_realhousetown_1X1_001_northwest, ZOOM_LEVEL_IN_4X, BIT_DEPTH_32BPP, "gfx/realhousetown_32_005.png") { 
  	[265, 0, 256, 256, -107, -154, NOCROP]
}

spritelayout spritelayout_realhousetown_1X1_001_northwest {
	ground {
		sprite: GROUNDSPRITE_NORMAL;
	}
	building {
		sprite: spriteset_realhousetown_1X1_001_northwest;
		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 East*/
spriteset (spriteset_realhousetown_1X1_001_northeast, "realhousetown.png") {
	[98, 8, 44, 36, -22, 0, NOCROP]
}
alternative_sprites (spriteset_realhousetown_1X1_001_northeast, ZOOM_LEVEL_IN_4X, BIT_DEPTH_32BPP, "gfx/realhousetown_32_005.png") { 
  	[524, 0, 256, 256, -107, -154, NOCROP]
}

spritelayout spritelayout_realhousetown_1X1_001_northeast {
	ground {
		sprite: GROUNDSPRITE_NORMAL;
	}
	building {
		sprite: spriteset_realhousetown_1X1_001_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_1X1_001_southeast, "realhousetown.png") {
	[98, 8, 44, 36, -22, 0, NOCROP]
}
alternative_sprites (spriteset_realhousetown_1X1_001_southeast, ZOOM_LEVEL_IN_4X, BIT_DEPTH_32BPP, "gfx/realhousetown_32_005.png") { 
  	[788, 0, 256, 256, -107, -154, NOCROP]
}

spritelayout spritelayout_realhousetown_1X1_001_southeast {
	ground {
		sprite: GROUNDSPRITE_NORMAL;
	}
	building {
		sprite: spriteset_realhousetown_1X1_001_southeast;
		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_check_road_northeast, nearby_tile_class(-1, 0)) {
	TILE_CLASS_ROAD: 3;
	CB_RESULT_DO_NOTHING;
}

switch (FEAT_HOUSES, SELF, switch_check_road_southeast, nearby_tile_class(0, 1)) {
	TILE_CLASS_ROAD: 2;
	switch_check_road_northeast;
}

switch (FEAT_HOUSES, SELF, switch_check_road_southwest, nearby_tile_class(1, 0)) {
	TILE_CLASS_ROAD: 1;
	switch_check_road_southeast;
}


switch (FEAT_HOUSES, SELF, switch_check_road_northwest, nearby_tile_class(0, -1)) {
	TILE_CLASS_ROAD:  0;
	switch_check_road_southwest;
}

switch (FEAT_HOUSES, SELF, switch_check_road_final, animation_frame) {
	0:  spritelayout_realhousetown_1X1_001_northwest;
	1:  spritelayout_realhousetown_1X1_001_southwest;
	2:  spritelayout_realhousetown_1X1_001_southeast;
	3:  spritelayout_realhousetown_1X1_001_northeast;
	spritelayout_realhousetown_1X1_001_northwest;
}

/* Switches End */

item (FEAT_HOUSES, item_realhousetown_090, -1, HOUSE_SIZE_1X1) {
	property {
		substitute: 24;
		population:                 90;
		mail_multiplier:            30;
		accepted_cargos:            [[PASS, 4], [MAIL, 3], [GOOD, 3]];
		probability: 1;
		years_available:            [1855, 2050];
		name: string(STR_realhousetown_1X1_001_HOUSE);
                availability_mask: [bitmask(TOWNZONE_EDGE, TOWNZONE_OUTSKIRT), bitmask(CLIMATE_TEMPERATE, CLIMATE_ARCTIC, ABOVE_SNOWLINE, CLIMATE_TROPICAL)];
		building_flags    : bitmask(HOUSE_FLAG_ANIMATE);
		animation_info    : [ANIMATION_LOOPING, 1];
	}
	graphics {
    default: switch_check_road_final;
    anim_control: switch_check_road_northwest;
	}
}



How to add the switch to your 2x2 example?


Thanks for sharing.

Re: NML: Multi-tile houses

Posted: 05 Dec 2021 14:23
by GojkoG
Hi Temporal8!
Am I reading correctly that you’re using animation frames to save the street positions? That’s a workaround you don’t need, because you simply could check for the roads on the “way” to the spritelayout and then branch it to your four spritelayouts:

Code: Select all

switch (FEAT_HOUSES, SELF, switch_realhousetown_090_road_check, switch_check_road_northwest) {
	3:  spritelayout_realhousetown_1X1_001_northeast;
	2:  spritelayout_realhousetown_1X1_001_southeast;
	1:  spritelayout_realhousetown_1X1_001_southwest;
	spritelayout_realhousetown_1X1_001_northwest;	// you don’t need the zero, because this is the “else”/default in this switch
}

item (FEAT_HOUSES, item_realhousetown_090, -1, HOUSE_SIZE_1X1) {
	property { … }
	graphics {
		default: switch_realhousetown_090_road_check;
	}
}
You’re using your own switch “switch_check_road_northwest” and the ones called by it like functions in other programming languages.

And to have it for multiple tiles you branch the way before that for every tile:

Code: Select all

switch (FEAT_HOUSES, SELF, switch_realhousetown_090_N_road_check, switch_check_road_northwest) {
	3:  spritelayout_realhousetown_N_001_northeast;
	2:  spritelayout_realhousetown_N_001_southeast;
	1:  spritelayout_realhousetown_N_001_southwest;
	spritelayout_realhousetown_N_001_northwest;
}

[…]

switch (FEAT_HOUSES, SELF, switch_realhousetown_090_S_road_check, switch_check_road_northwest) {
	3:  spritelayout_realhousetown_S_001_northeast;
	2:  spritelayout_realhousetown_S_001_southeast;
	1:  spritelayout_realhousetown_S_001_southwest;
	spritelayout_realhousetown_S_001_northwest;
}

item (FEAT_HOUSES, item_realhousetown_090, -1, HOUSE_SIZE_2X2) {
	property { … }
	graphics {
		graphics_north: switch_realhousetown_090_N_road_check;
		graphics_east: switch_realhousetown_090_E_road_check;
		graphics_west: switch_realhousetown_090_W_road_check;
		graphics_south: switch_realhousetown_090_S_road_check
	}
}
PS: You could use the hide_sprite function and check the road directly in the “building” block of spritelayout. I will test it and write an example in the next post.
PS: The code is better arranged if you have one spriteset for all graphics of your house and refer to labels:

Code: Select all

spriteset (spriteset_realhousetown_1X1_001, "realhousetown.png") {
	southwest:	[98, 8, 44, 36, -22, 0, NOCROP]
	northwest:	[98, 8, 44, 36, -22, 0, NOCROP]
	northeast:	[98, 8, 44, 36, -22, 0, NOCROP]
	southeast:	[98, 8, 44, 36, -22, 0, NOCROP]
}
alternative_sprites (spriteset_realhousetown_1X1_001, ZOOM_LEVEL_IN_4X, BIT_DEPTH_32BPP, "gfx/realhousetown_32_005.png") { 
  	southwest:	[0, 0, 256, 256, -107, -154, NOCROP]
	northwest:	[788, 0, 256, 256, -107, -154, NOCROP]
	northeast:	[524, 0, 256, 256, -107, -154, NOCROP]
	southeast:	[788, 0, 256, 256, -107, -154, NOCROP]
}

spritelayout spritelayout_realhousetown_1X1_001_southwest{
	ground { … }
	building {
		sprite: spriteset_realhousetown_1X1_001( southwest );
		[…]
	}
}

Re: NML: Multi-tile houses

Posted: 05 Dec 2021 14:49
by Eddi
GojkoG wrote: 05 Dec 2021 14:23 Am I reading correctly that you’re using animation frames to save the street positions? That’s a workaround you don’t need, because you simply could check for the roads on the “way” to the spritelayout and then branch it to your four spritelayouts
the point of that is to store the road layout at the moment the building is constructed. so it doesn't magically change shape if roads are removed or built later.

Re: NML: Multi-tile houses

Posted: 05 Dec 2021 14:51
by jfs
Eddi wrote: 05 Dec 2021 14:49the point of that is to store the road layout at the moment the building is constructed. so it doesn't magically change shape if roads are removed or built later.
Additionally, by saving the built orientation, it's faster to draw the building since the game doesn't need to run the NewGRF callback every time the building comes on screen.

Re: NML: Multi-tile houses

Posted: 05 Dec 2021 14:53
by GojkoG
Okay. I see that the NML compiler ignores switch blocks called from within the “building” block as long as they are not referenced from somewhere else.

Here I just want to show other ways to achieve the same, but have less spritelayout blocks:

It could work this way to have less spritelayout blocks. (The switch blocks have to be before that):

Code: Select all

spritelayout sprtLyt_BrickRowHouses {
	ground { … }
	building {	// road northwest
		[…]
		hide_sprite: (switch_check_road_northwest != 0)? 1 : 0;	// hide if result is not "0"
	}
	[…]
	building {	// road northeast
		[…]
		hide_sprite: (switch_check_road_northwest != 3)? 1 : 0;	// hide if result is not "3"
	}
}
You also could save a temp variable and write your road check to that and then check the temp:

Code: Select all

spritelayout spritelayout_realhousetown_S_001{
	ground { … }
	building {	// road northwest
		[…]
		hide_sprite: (LOAD_TEMP(0)!= 0)? 1 : 0;	// hide if value of temp variable 0 is not "0"
	}
	[…]
	building {	// road northeast
		[…]
		hide_sprite: (LOAD_TEMP(0)!= 3)? 1 : 0;	// hide if value of temp variable 0 is not "3"
	}
}

[…]

switch (FEAT_HOUSES, SELF, switch_houses_road_check, [
		STORE_TEMP( switch_check_road_northwest, 0))	// the result of your switch “switch_check_road_northwest” is stored in temp variable 0
	]) {
	spritelayout_realhousetown_S_001;
}

Re: NML: Multi-tile houses

Posted: 07 Dec 2021 20:22
by GojkoG
the point of that is to store the road layout at the moment the building is constructed. so it doesn't magically change shape if roads are removed or built later.
Good point! I didn’t think of that.

Re: NML: Multi-tile houses

Posted: 12 Dec 2021 16:15
by temporal8
Thanks for your reply GojkoG, I understand what you say but I have problems applying it, mostly because I know how to detect the street in 1x1 but the 2x1 or 2x2 modules have extra code to detect the 2 tiles of a 2x1 or the 4 tiles of a 2x2 and that's where I get lost.

This is a working code for a 2x2 object from my Real Houses newgrf (i attached the file below if you want to test ingame):

Code: Select all

// define the newgrf
grf {
    grfid:                  "TEM2";
    name:                   string(STR_GRF_NAME);
    desc:                   string(STR_GRF_DESCRIPTION);
    url : string(STR_GRF_WEBSITE);
    version:                2;
    min_compatible_version: 1;
}

//template for the purchase menu
template template_realhouse_purchase(x,y,filename) {
    [x    , y, 128, 96, -95, -45, filename]
    [x+133, y, 128, 96, -95, -45, filename]
    [x+266, y, 128, 96, -95, -45, filename]
    [x+399, y, 128, 96, -95, -45, filename]
	
}

//template for the purchase menu 32
template template_realhouse_purchase_32(x,y,filename) {
    [x+34, y+7, 519, 387, -345, -247, filename]
    [x+34, y+407, 519, 387, -389, -259, filename]
    [x+34, y+801, 519, 387, -378, -291, filename]
    [x+34, y+1200, 519, 387, -374, -294, filename]	
}

//template for sprite tile.1 (v1.1, v1.2, v1.3, v1.4)
template template_realhouse_t1(x,y,filename) {
    [x+2, y+2, 64, 64, -1, -1, filename]
    [x+2, y+2, 64, 64, -1, -1, filename]
    [x+2, y+2, 64, 64, -1, -1, filename]
    [x+2, y+2, 64, 64, -1, -1, filename]	
}

//template for sprite tile32.1 (v1.1, v1.2, v1.3, v1.4)
template template_realhouse_32_t1(x,y,filename) {
    [x+158, y+3, 264, 264, -130, -135, filename]
    [x+158, y+400, 264, 264, -130, -135, filename]
    [x+158, y+797, 264, 264, -130, -135, filename]
    [x+158, y+1193, 264, 264, -130, -135, filename]	
}

//template for sprite tile.2 
template template_realhouse_t2(x,y,filename) {
    [x+2, y+2, 64, 64, -1, -1, filename]
    [x+2, y+2, 64, 64, -1, -1, filename]
    [x+2, y+2, 64, 64, -1, -1, filename]
    [x+2, y+2, 64, 64, -1, -1, filename]
}

//template for sprite tile32.2 (v2.1, v2.2, v2.3, v2.4)
template template_realhouse_32_t2(x,y,filename) {
    [x+287, y+65, 264, 264, -129, -137, filename]
    [x+287, y+462, 264, 264, -129, -137, filename]
    [x+287, y+859, 264, 264, -129, -137, filename]
    [x+287, y+1255, 264, 264, -129, -137, filename]	
}

//template for sprite tile.3
template template_realhouse_t3(x,y,filename) {
    [x+2, y+2, 64, 64, -1, -1, filename]
    [x+2, y+2, 64, 64, -1, -1, filename]
    [x+2, y+2, 64, 64, -1, -1, filename]
    [x+2, y+2, 64, 64, -1, -1, filename]
}

//template for sprite tile32.3  (v3.1, v3.2, v3.3, v3.4)
template template_realhouse_32_t3(x,y,filename) {
    [x+33, y+65, 264, 264, -127, -137, filename]
    [x+33, y+462, 264, 264, -127, -137, filename]
    [x+33, y+859, 264, 264, -127, -137, filename]
    [x+1, y+1255, 295, 264, -159, -137, filename]	
}

//template for sprite tile.4
template template_realhouse_t4(x,y,filename) {
    [x+2, y+2, 64, 64, -1, -1, filename]
    [x+2, y+2, 64, 64, -1, -1, filename]
    [x+2, y+2, 64, 64, -1, -1, filename]
    [x+2, y+2, 64, 64, -1, -1, filename]
}

//template for sprite tile32.4 (v4.1, v4.2, v4.3, v4.4)
template template_realhouse_32_t4(x,y,filename) {
    [x+160, y+127, 264, 264, -128, -139, filename]
    [x+160, y+524, 264, 264, -128, -139, filename]
    [x+160, y+921, 264, 264, -128, -139, filename]
    [x+160, y+1317, 264, 264, -128, -139, filename]
	
}

/* template_realhouse_001 */

//spritesets with 4 directions and the PURCHASE-menu
spriteset (spriteset_template_realhouse_001_t1) {
    template_realhouse_t1(0,0,"realhouse/gfx/template_realhouse_001.png")
}
alternative_sprites (spriteset_template_realhouse_001_t1, ZOOM_LEVEL_IN_4X, BIT_DEPTH_32BPP) { 
    template_realhouse_32_t1(0,0,"realhouse/gfx/template_realhouse_32_001.png")
}

spriteset (spriteset_template_realhouse_001_t2) {
    template_realhouse_t2(0,0,"realhouse/gfx/template_realhouse_001.png")
}

alternative_sprites (spriteset_template_realhouse_001_t2, ZOOM_LEVEL_IN_4X, BIT_DEPTH_32BPP) { 
    template_realhouse_32_t2(0,0,"realhouse/gfx/template_realhouse_32_001.png")
}

spriteset (spriteset_template_realhouse_001_t3) {
    template_realhouse_t3(0,0,"realhouse/gfx/template_realhouse_001.png")
}

alternative_sprites (spriteset_template_realhouse_001_t3, ZOOM_LEVEL_IN_4X, BIT_DEPTH_32BPP) { 
    template_realhouse_32_t3(0,0,"realhouse/gfx/template_realhouse_32_001.png")
}

spriteset (spriteset_template_realhouse_001_t4) {
    template_realhouse_t4(0,0,"realhouse/gfx/template_realhouse_001.png")
}

alternative_sprites (spriteset_template_realhouse_001_t4, ZOOM_LEVEL_IN_4X, BIT_DEPTH_32BPP) { 
    template_realhouse_32_t4(0,0,"realhouse/gfx/template_realhouse_32_001.png")
}

spriteset (spriteset_template_realhouse_001_PURCHASE) {
    template_realhouse_purchase(0,0,"realhouse/gfx/template_realhouse_001_PURCHASE.png")
}
alternative_sprites (spriteset_template_realhouse_001_PURCHASE, ZOOM_LEVEL_IN_4X, BIT_DEPTH_32BPP) { 
    template_realhouse_purchase_32(0,0,"realhouse/gfx/template_realhouse_32_001.png")
}

//View_1
spritelayout spritelayout_template_realhouse_001_t1_view1 {
    ground {
      // normal ground sprite - always draw
      sprite: LOAD_TEMP(0) + LOAD_TEMP(1);
   }
    
    building {
        sprite: spriteset_template_realhouse_001_t1(0);
        hide_sprite: nearby_tile_height(0, 0) >= snowline_height;
        xoffset: 0; //from NE edge
        yoffset: 0; //from NW edge
        zoffset: 0;
        xextent: 16;
        yextent: 16;
        zextent: 16;
    }

}

spritelayout spritelayout_template_realhouse_001_t2_view1 {
    ground {
      // normal ground sprite - always draw
      sprite: LOAD_TEMP(0) + LOAD_TEMP(1);
   }
    
    building {
        sprite: spriteset_template_realhouse_001_t2(0);
        hide_sprite: nearby_tile_height(0, 0) >= snowline_height;
        xoffset: 0; //from NE edge
        yoffset: 0; //from NW edge
        zoffset: 0;
        xextent: 16;
        yextent: 16;
        zextent: 16;
    }

}

spritelayout spritelayout_template_realhouse_001_t3_view1 {
    ground {
      // normal ground sprite - always draw
      sprite: LOAD_TEMP(0) + LOAD_TEMP(1);
   }
    
    building {
        sprite: spriteset_template_realhouse_001_t3(0);
        hide_sprite: nearby_tile_height(0, 0) >= snowline_height;
        xoffset: 0; //from NE edge
        yoffset: 0; //from NW edge
        zoffset: 0;
        xextent: 16;
        yextent: 16;
        zextent: 16;
    }

}

spritelayout spritelayout_template_realhouse_001_t4_view1 {
    ground {
      // normal ground sprite - always draw
      sprite: LOAD_TEMP(0) + LOAD_TEMP(1);
   }
    
    building {
        sprite: spriteset_template_realhouse_001_t4(0);
        hide_sprite: nearby_tile_height(0, 0) >= snowline_height;
        xoffset: 0; //from NE edge
        yoffset: 0; //from NW edge
        zoffset: 0;
        xextent: 16;
        yextent: 16;
        zextent: 16;
    }

}

spritelayout spritelayout_template_realhouse_001_view1_purchase {
	ground {
        sprite: GROUNDSPRITE_NORMAL;
	}
	building {
		sprite: spriteset_template_realhouse_001_PURCHASE(0);
		xoffset: 0; //from NE edge
                yoffset: 16; //from NW edge
                zoffset: 0;
                xextent: 16;
                yextent: 16;
                zextent: 16;
	}
}

//View_2
spritelayout spritelayout_template_realhouse_001_t1_view2 {
    ground {
      // normal ground sprite - always draw
      sprite: LOAD_TEMP(0) + LOAD_TEMP(1);
   }
    
    building {
        sprite: spriteset_template_realhouse_001_t1(1);
        hide_sprite: nearby_tile_height(0, 0) >= snowline_height;
        xoffset: 0; //from NE edge
        yoffset: 0; //from NW edge
        zoffset: 0;
        xextent: 16;
        yextent: 16;
        zextent: 16;
    }

}

spritelayout spritelayout_template_realhouse_001_t2_view2 {
    ground {
      // normal ground sprite - always draw
      sprite: LOAD_TEMP(0) + LOAD_TEMP(1);
   }
    
    building {
        sprite: spriteset_template_realhouse_001_t2(1);
        hide_sprite: nearby_tile_height(0, 0) >= snowline_height;
        xoffset: 0; //from NE edge
        yoffset: 0; //from NW edge
        zoffset: 0;
        xextent: 16;
        yextent: 16;
        zextent: 16;
    }

}

spritelayout spritelayout_template_realhouse_001_t3_view2 {
    ground {
      // normal ground sprite - always draw
      sprite: LOAD_TEMP(0) + LOAD_TEMP(1);
   }
    
    building {
        sprite: spriteset_template_realhouse_001_t3(1);
        hide_sprite: nearby_tile_height(0, 0) >= snowline_height;
        xoffset: 0; //from NE edge
        yoffset: 0; //from NW edge
        zoffset: 0;
        xextent: 16;
        yextent: 16;
        zextent: 16;
    }

}

spritelayout spritelayout_template_realhouse_001_t4_view2 {
    ground {
      // normal ground sprite - always draw
      sprite: LOAD_TEMP(0) + LOAD_TEMP(1);
   }
    
    building {
        sprite: spriteset_template_realhouse_001_t4(1);
        hide_sprite: nearby_tile_height(0, 0) >= snowline_height;
        xoffset: 0; //from NE edge
        yoffset: 0; //from NW edge
        zoffset: 0;
        xextent: 16;
        yextent: 16;
        zextent: 16;
    }

}

spritelayout spritelayout_template_realhouse_001_view2_purchase {
	ground {
        sprite: GROUNDSPRITE_NORMAL;
	}
	building {
		sprite: spriteset_template_realhouse_001_PURCHASE(1);
		xoffset: 0; //from NE edge
                yoffset: 16; //from NW edge
                zoffset: 0;
                xextent: 16;
                yextent: 16;
                zextent: 16;
	}
}


//View_3
spritelayout spritelayout_template_realhouse_001_t1_view3 {
    ground {
      // normal ground sprite - always draw
      sprite: LOAD_TEMP(0) + LOAD_TEMP(1);
   }
    
    building {
        sprite: spriteset_template_realhouse_001_t1(2);
        hide_sprite: nearby_tile_height(0, 0) >= snowline_height;
        xoffset: 0; //from NE edge
        yoffset: 0; //from NW edge
        zoffset: 0;
        xextent: 16;
        yextent: 16;
        zextent: 16;
    }

}

spritelayout spritelayout_template_realhouse_001_t2_view3 {
    ground {
      // normal ground sprite - always draw
      sprite: LOAD_TEMP(0) + LOAD_TEMP(1);
   }
    
    building {
        sprite: spriteset_template_realhouse_001_t2(2);
        hide_sprite: nearby_tile_height(0, 0) >= snowline_height;
        xoffset: 0; //from NE edge
        yoffset: 0; //from NW edge
        zoffset: 0;
        xextent: 16;
        yextent: 16;
        zextent: 16;
    }

}

spritelayout spritelayout_template_realhouse_001_t3_view3 {
    ground {
      // normal ground sprite - always draw
      sprite: LOAD_TEMP(0) + LOAD_TEMP(1);
   }
    
    building {
        sprite: spriteset_template_realhouse_001_t3(2);
        hide_sprite: nearby_tile_height(0, 0) >= snowline_height;
        xoffset: 0; //from NE edge
        yoffset: 0; //from NW edge
        zoffset: 0;
        xextent: 16;
        yextent: 16;
        zextent: 16;
    }

}

spritelayout spritelayout_template_realhouse_001_t4_view3 {
    ground {
      // normal ground sprite - always draw
      sprite: LOAD_TEMP(0) + LOAD_TEMP(1);
   }
    
    building {
        sprite: spriteset_template_realhouse_001_t4(2);
        hide_sprite: nearby_tile_height(0, 0) >= snowline_height;
        xoffset: 0; //from NE edge
        yoffset: 0; //from NW edge
        zoffset: 0;
        xextent: 16;
        yextent: 16;
        zextent: 16;
    }
}

spritelayout spritelayout_template_realhouse_001_view3_purchase {
	ground {
        sprite: GROUNDSPRITE_NORMAL;
	}
	building {
		sprite: spriteset_template_realhouse_001_PURCHASE(2);
		xoffset: 0; //from NE edge
                yoffset: 16; //from NW edge
                zoffset: 0;
                xextent: 16;
                yextent: 16;
                zextent: 16;
	}
}


//View_4
spritelayout spritelayout_template_realhouse_001_t1_view4 {
    ground {
      // normal ground sprite - always draw
      sprite: LOAD_TEMP(0) + LOAD_TEMP(1);
   }
    
    building {
        sprite: spriteset_template_realhouse_001_t1(3);
        hide_sprite: nearby_tile_height(0, 0) >= snowline_height;
        xoffset: 0; //from NE edge
        yoffset: 0; //from NW edge
        zoffset: 0;
        xextent: 16;
        yextent: 16;
        zextent: 16;
    }
}

spritelayout spritelayout_template_realhouse_001_t2_view4 {
    ground {
      // normal ground sprite - always draw
      sprite: LOAD_TEMP(0) + LOAD_TEMP(1);
   }
    
    building {
        sprite: spriteset_template_realhouse_001_t2(3);
        hide_sprite: nearby_tile_height(0, 0) >= snowline_height;
        xoffset: 0; //from NE edge
        yoffset: 0; //from NW edge
        zoffset: 0;
        xextent: 16;
        yextent: 16;
        zextent: 16;
    }
}

spritelayout spritelayout_template_realhouse_001_t3_view4 {
    ground {
      // normal ground sprite - always draw
      sprite: LOAD_TEMP(0) + LOAD_TEMP(1);
   }
    
    building {
        sprite: spriteset_template_realhouse_001_t3(3);
        hide_sprite: nearby_tile_height(0, 0) >= snowline_height;
        xoffset: 0; //from NE edge
        yoffset: 0; //from NW edge
        zoffset: 0;
        xextent: 16;
        yextent: 16;
        zextent: 16;
    }

}

spritelayout spritelayout_template_realhouse_001_t4_view4 {
    ground {
      // normal ground sprite - always draw
      sprite: LOAD_TEMP(0) + LOAD_TEMP(1);
   }
    
    building {
        sprite: spriteset_template_realhouse_001_t4(3);
        hide_sprite: nearby_tile_height(0, 0) >= snowline_height;
        xoffset: 0; //from NE edge
        yoffset: 0; //from NW edge
        zoffset: 0;
        xextent: 16;
        yextent: 16;
        zextent: 16;
    }

}

spritelayout spritelayout_template_realhouse_001_view4_purchase {
	ground {
        sprite: GROUNDSPRITE_NORMAL;
	}
	building {
		sprite: spriteset_template_realhouse_001_PURCHASE(3);
		xoffset: 0; //from NE edge
                yoffset: 16; //from NW edge
                zoffset: 0;
                xextent: 16;
                yextent: 16;
                zextent: 16;
	}
}

//select correct sprites for position of the tiles for the four views
switch (FEAT_OBJECTS, SELF, switch_template_realhouse_001_position_view1, relative_pos) {
	relative_coord(0, 0): spritelayout_template_realhouse_001_t1_view1;
	relative_coord(0, 1): spritelayout_template_realhouse_001_t2_view1;
	relative_coord(1, 0): spritelayout_template_realhouse_001_t3_view1;
	relative_coord(1, 1): spritelayout_template_realhouse_001_t4_view1;
    spritelayout_template_realhouse_001_t1_view1;
    }

switch (FEAT_OBJECTS, SELF, switch_template_realhouse_001_position_view2, relative_pos) {
	relative_coord(0, 0): spritelayout_template_realhouse_001_t1_view2;
	relative_coord(0, 1): spritelayout_template_realhouse_001_t2_view2;
	relative_coord(1, 0): spritelayout_template_realhouse_001_t3_view2;
	relative_coord(1, 1): spritelayout_template_realhouse_001_t4_view2;
    spritelayout_template_realhouse_001_t1_view2;
    }

switch (FEAT_OBJECTS, SELF, switch_template_realhouse_001_position_view3, relative_pos) {
	relative_coord(0, 0): spritelayout_template_realhouse_001_t1_view3;
	relative_coord(0, 1): spritelayout_template_realhouse_001_t2_view3;
	relative_coord(1, 0): spritelayout_template_realhouse_001_t3_view3;
	relative_coord(1, 1): spritelayout_template_realhouse_001_t4_view3;
    spritelayout_template_realhouse_001_t1_view3;
    }

switch (FEAT_OBJECTS, SELF, switch_template_realhouse_001_position_view4, relative_pos) {
	relative_coord(0, 0) : spritelayout_template_realhouse_001_t1_view4;
	relative_coord(0, 1) : spritelayout_template_realhouse_001_t2_view4;
	relative_coord(1, 0) : spritelayout_template_realhouse_001_t3_view4;
	relative_coord(1, 1) : spritelayout_template_realhouse_001_t4_view4;
    spritelayout_template_realhouse_001_t1_view4;
    }
 
//decide spritelayout for each of the 4 directions
switch (FEAT_OBJECTS, SELF, switch_template_realhouse_001_view, view) {
    1:  switch_template_realhouse_001_position_view2;
    2:  switch_template_realhouse_001_position_view3;
    3:  switch_template_realhouse_001_position_view4;
    switch_template_realhouse_001_position_view1;
}

//calculate ground sprite for object
switch (FEAT_OBJECTS, SELF, switch_template_realhouse_001_object, [
    STORE_TEMP(GROUNDSPRITE_NORMAL, 1),
    STORE_TEMP( (nearby_tile_terrain_type(0,0) == TILETYPE_DESERT) * GROUNDSPRITE_DESERT, 1),
    STORE_TEMP( LOAD_TEMP(1) + (LOAD_TEMP(1) == 0) * 4512 * (nearby_tile_terrain_type( 1, 0) == TILETYPE_DESERT), 1),
    STORE_TEMP( LOAD_TEMP(1) + (LOAD_TEMP(1) == 0) * 4512 * (nearby_tile_terrain_type(-1, 0) == TILETYPE_DESERT), 1),
    STORE_TEMP( LOAD_TEMP(1) + (LOAD_TEMP(1) == 0) * 4512 * (nearby_tile_terrain_type( 0, 1) == TILETYPE_DESERT), 1),
    STORE_TEMP( LOAD_TEMP(1) + (LOAD_TEMP(1) == 0) * 4512 * (nearby_tile_terrain_type( 0,-1) == TILETYPE_DESERT), 1),
    STORE_TEMP( LOAD_TEMP(1) + (LOAD_TEMP(1) == 0) * GROUNDSPRITE_NORMAL, 1),
    STORE_TEMP(terrain_type == TILETYPE_SNOW   ? GROUNDSPRITE_SNOW : LOAD_TEMP(1), 1),
    STORE_TEMP(snowline_height == 0xFF ? 0xFF : nearby_tile_height(0,0) - snowline_height, 255),
    STORE_TEMP((LOAD_TEMP(255) == -1) ? GROUNDSPRITE_SNOW_1_4 : LOAD_TEMP(1), 1),
    STORE_TEMP((LOAD_TEMP(255) ==  0) ? GROUNDSPRITE_SNOW_2_4 : LOAD_TEMP(1), 1),
    STORE_TEMP((LOAD_TEMP(255) ==  1) ? GROUNDSPRITE_SNOW_3_4 : LOAD_TEMP(1), 1)
        ]) {
    switch_template_realhouse_001_view;
}

//calculate ground sprite for purchase menu
switch (FEAT_OBJECTS, SELF, switch_template_realhouse_001_purchase, view) {
    1:  spritelayout_template_realhouse_001_view2_purchase;
    2:  spritelayout_template_realhouse_001_view3_purchase;
    3:  spritelayout_template_realhouse_001_view4_purchase;
    spritelayout_template_realhouse_001_view1_purchase;
}

switch (FEAT_OBJECTS, SELF, switch_add_text_template_realhouse_001, view) {
1: string(STR_template_realhouse_001_purchase_view2);
2: string(STR_template_realhouse_001_purchase_view3);
3: string(STR_template_realhouse_001_purchase_view4);
default: string(STR_template_realhouse_001_purchase_view1);
}

item (FEAT_OBJECTS, template_realhouse_001, 000) {
    property {
        class: "RH2S";
        classname: string(STR_RH2S);
        name: string(STR_template_realhouse_001);
        climates_available: ALL_CLIMATES;
        size: [2,2];
        build_cost_multiplier: 0;
        remove_cost_multiplier: 0;
        introduction_date: date(1700,1,1);
        end_of_life_date: 0xFFFFFFFF;
        object_flags: bitmask(OBJ_FLAG_ALLOW_BRIDGE, OBJ_FLAG_ON_WATER, OBJ_FLAG_DRAW_WATER, OBJ_FLAG_ANYTHING_REMOVE, OBJ_FLAG_REMOVE_IS_INCOME);
        height: 0;
        num_views: 4;
     }
    graphics {
        default: switch_template_realhouse_001_object;
        purchase: switch_template_realhouse_001_purchase;
        additional_text: switch_add_text_template_realhouse_001;
      }
}
I want to convert these 2x2 object to a 2x2 house! originally i was doing a newgrf eyecandy of houses and buildings, but for a while i have been converting it to a town set, i mean houses instead of eyecandy, I only achieved it with 1x1 houses with the generous guidance and help of other forum members since I am not a coder.

The working code of a 1x1 house is the one I posted above, how can I do it in this 2x2 code?

I know I can add a swicth for the address / street detection but again, I don't know how to convert home the part of detecting that a house has several tiles.