NMLTutorial/Object slopes
The example used here is from the Dutch Road Furniture. The original graphics for this are by FooBar. The code is by FooBar, based on code for the object example from the NML source by planetmaker and Hirundu. Code and graphics are both licensed according to the GPL v2 or later. The code has been modified for the purpose of this tutorial.
This continues and concludes the second part of the object example. In this last part we'll make the object compatible with sloped terrain as well as snow and desert terrain. For this some recent features of OpenTTD will be used, which makes this last part of the example incompatible with anything other than OpenTTD 1.2.0 (r22723) or higher.
Version check
if (version_openttd(1,2,0,22723) > openttd_version) { error(FATAL, REQUIRES_OPENTTD, string(STR_OPENTTD_VERSION)); }
STR_OPENTTD_VERSION :1.2.0 (r22723)
Sloped ground sprites
default: switch_fingerpost_3_object; purchase: switch_fingerpost_3_purchase; autoslope: return(CB_RESULT_AUTOSLOPE);
switch (FEAT_OBJECTS, SELF, switch_fingerpost_3_object, [ //tile slope offset in storage register 0 STORE_TEMP(slope_to_sprite_offset(tile_slope), 0), //terrain type in storage register 1 STORE_TEMP(GROUNDSPRITE_NORMAL, 1), STORE_TEMP(terrain_type == TILETYPE_DESERT ? GROUNDSPRITE_DESERT : LOAD_TEMP(1), 1), STORE_TEMP(terrain_type == TILETYPE_SNOW ? GROUNDSPRITE_SNOW : LOAD_TEMP(1), 1) ]) { switch_fingerpost_3_build_date; }
//calculate ground sprite for purchase menu switch (FEAT_OBJECTS, SELF, switch_fingerpost_3_purchase, [ //use flat gound sprite for purchase menu STORE_TEMP(0, 0), //use normal terrain for purchase menu STORE_TEMP(GROUNDSPRITE_NORMAL, 1), ]) { switch_fingerpost_3_build_date; }
With this the end of the object example is reached. You can now encode this as a NewGRF.
The complete code
If you put everything in the correct order, this will be the complete NML file:
// define the newgrf grf { grfid: "\FB\FB\05\01"; name: string(STR_GRF_NAME); desc: string(STR_GRF_DESCRIPTION); version: 0; min_compatible_version: 0; } //check OpenTTD version //parameterized spritelayout is only supported since OpenTTD 1.2.0 r22723 if (version_openttd(1,2,0,22723) > openttd_version) { error(FATAL, REQUIRES_OPENTTD, string(STR_OPENTTD_VERSION)); } //templates template template_fingerpost(x,y,filename) { [x, y, 20, 32, -10, -28, filename] [x+30, y, 20, 32, -10, -28, filename] [x+60, y, 20, 32, -10, -28, filename] [x+90, y, 20, 32, -10, -28, filename] } //spriteset with four directions spriteset (spriteset_fingerpost_3) { template_fingerpost(0,0,"gfx/dutch_fingerpost.png") } /* spritelayouts */ //south east spritelayout spritelayout_fingerpost_3_SE { ground { sprite: LOAD_TEMP(0) + LOAD_TEMP(1); } building { sprite: spriteset_fingerpost_3(0); xextent: 4; yextent: 4; zextent: 24; xoffset: 6; //from NE edge yoffset: 12; //from NW edge zoffset: 0; } } //south west spritelayout spritelayout_fingerpost_3_SW { ground { sprite: LOAD_TEMP(0) + LOAD_TEMP(1); } building { sprite: spriteset_fingerpost_3(1); xextent: 4; yextent: 4; zextent: 24; xoffset: 12; //from NE edge yoffset: 6; //from NW edge zoffset: 0; } } //north west spritelayout spritelayout_fingerpost_3_NW { ground { sprite: LOAD_TEMP(0) + LOAD_TEMP(1); } building { sprite: spriteset_fingerpost_3(2); xextent: 4; yextent: 4; zextent: 24; xoffset: 6; //from NE edge yoffset: 0; //from NW edge zoffset: 0; } } //north east spritelayout spritelayout_fingerpost_3_NE { ground { sprite: LOAD_TEMP(0) + LOAD_TEMP(1); } building { sprite: spriteset_fingerpost_3(3); xextent: 4; yextent: 4; zextent: 24; xoffset: 0; //from NE edge yoffset: 6; //from NW edge zoffset: 0; } } //decide spritelayout for each of the 4 views switch (FEAT_OBJECTS, SELF, switch_fingerpost_3_view, view) { 1: spritelayout_fingerpost_3_SW; 2: spritelayout_fingerpost_3_NW; 3: spritelayout_fingerpost_3_NE; spritelayout_fingerpost_3_SE; } //calculate ground sprite for object switch (FEAT_OBJECTS, SELF, switch_fingerpost_3_object, [ //tile slope offset in storage register 0 STORE_TEMP(slope_to_sprite_offset(tile_slope), 0), //terrain type in storage register 1 STORE_TEMP(GROUNDSPRITE_NORMAL, 1), STORE_TEMP(terrain_type == TILETYPE_DESERT ? GROUNDSPRITE_DESERT : LOAD_TEMP(1), 1), STORE_TEMP(terrain_type == TILETYPE_SNOW ? GROUNDSPRITE_SNOW : LOAD_TEMP(1), 1) ]) { switch_fingerpost_3_build_date; } //calculate ground sprite for purchase menu switch (FEAT_OBJECTS, SELF, switch_fingerpost_3_purchase, [ //use flat gound sprite for purchase menu STORE_TEMP(0, 0), //use normal terrain for purchase menu STORE_TEMP(GROUNDSPRITE_NORMAL, 1), ]) { switch_fingerpost_3_build_date; } item (FEAT_OBJECTS, fingerpost_3) { property { class: "NLRF"; classname: string(STR_NLRF); name: string(STR_HANDWIJZER_3); climates_available: ALL_CLIMATES; size: [1,1]; build_cost_multiplier: 2; remove_cost_multiplier: 8; introduction_date: date(1961,1,1); end_of_life_date: 0xFFFFFFFF; object_flags: bitmask(OBJ_FLAG_REMOVE_IS_INCOME, OBJ_FLAG_NO_FOUNDATIONS, OBJ_FLAG_ALLOW_BRIDGE); height: 2; num_views: 4; } graphics { default: switch_fingerpost_3_object; purchase: switch_fingerpost_3_purchase; autoslope: return(CB_RESULT_AUTOSLOPE); additional_text: string(STR_FINGERPOST_3_PURCHASE); } }
The language file will now contain:
##grflangid 0x01 #Main grf title and description STR_GRF_NAME :{TITLE} STR_GRF_DESCRIPTION :Description: {SILVER}Dutch Road Furniture is an eyecandy object NewGRF that features road furniture that can be found alongside Dutch roads. {}(c)2011 FooBar. {}{BLACK}License: {SILVER}GPLv2 or higher. #error messages STR_OPENTTD_VERSION :1.2.0 (r22723) #object classes STR_NLRF :Dutch Road Furniture #object name and description STR_FINGERPOST_3 :Dutch Fingerpost three-way STR_FINGERPOST_3_PURCHASE :The three-way fingerpost is centered at one side of the tile and facing outward. Intended to be placed directly opposite of the secondary road at a three-way junction.
This is the end of this example and the end of the series. Only thing left for you to skip is a useless conclusion
NML Tutorial: Object slopes