From TTWiki

The example used here is the HTM 4001 from the Dutch Tram Set. The original code and graphics for this are by FooBar. Code and graphics are both licensed according to the GPL v2 or later. The code has been modified for the purpose of this tutorial.


You already know how to make a road vehicle. This example will show you how to make an articulated tram vehicle. The difference between a road vehicle and a tram is exactly one line of code, so if you want to make an articulated road vehicle that is not a tram, you can follow this example and leave out this one line of code.

Callbacks and switches will be used to make the tram vehicle articulated. Switches will be used as well to have different graphics for each part of the tram.

Folder structure

For this example we'll assume the following folder structure. There will be two language files in the lang folder, one graphics file in the gfx folder. These two folders sit together with custom_tags.txt and the main NML file in one project folder. Nothing fancy, but it's good to have seen the structure:

 |- lang
 |   |- dutch.lng
 |   |- english.lng
 |- gfx
 |   |- htm_4001.png
 |- custom_tags.txt
 |- tram_example.nml

Language files

English will be the default language for the NewGRF and we'll provide translations in Dutch and German. Apart from the regular GRF name and description, we already know that we'll be making one vehicle, so we'll add the string for that right away. Furthermore, we want an additional description in the purchase menu for this vehicle. How to do that will be shown later, but you can imagine that you need a string for that as well, so let's add this string right now as well.


##grflangid 0x01

#Main grf title and description
STR_GRF_DESCRIPTION		:Trams of The Netherlands for OpenTTD {}(c)2007,2008,2011 Rendall, FooBar and others. {}License: GPLv2 or higher. {}See readme for details.

#Vehicle names
STR_NAME_HTM_4001		:HTM 4001-4072 'Citadis'

#Vehicle descriptions
STR_DESC_HTM_4001		:Origin: {SILVER}The Hague {}{BLACK}Historic facts: {SILVER}Built in 2006 and 2011 by Alstom. Used on the RandstadRail lines operated by HTM.

Note that {TITLE} is a custom string code, defined in custom_tags.txt.


##grflangid 0x1F

#Main grf title en description
STR_GRF_NAME			:{TITLE} - Nederlandse Tram Set
STR_GRF_DESCRIPTION		:Nederlandse trams voor OpenTTD {}(c)2007,2008,2011 Rendall, FooBar en anderen. {}Licentie: GPLv2 of hoger. {}Lees de readme voor details.

#Vehicle descriptions
STR_DESC_HTM_4001		:Herkomst: {SILVER}Den Haag {}{BLACK}Historische feiten: {SILVER}Gebouwd in 2006 en 2011 door Alstom. Gebruikt op de RandstadRail lijnen van HTM.

As you can see, we keep the same (English) title from custom_tags.txt and add a Dutch translation to it. The vehicle name needs no translation, so we don't define one for that. Of course, you can add as many translations as you want.


custom_tags.txt will contain a custom string code for the English title and version of the release. This will then be inserted in every translation by NML.

TITLE    :Dutch Tram Set r87M

NML file

Obviously the NML file will need a grf block. Add one:

// define the newgrf
grf {
	grfid:	"\FB\FB\01\02";
	name:	string(STR_GRF_NAME);
	desc:	string(STR_GRF_DESCRIPTION);
	version:		REPO_REVISION;
	min_compatible_version:	87;

The grfid in this case is that of the Dutch Tram Set. FooBar thought it was a good idea to use the bytes 0xFB 0xFB for his initials, rather than the literal string "FB" (which would be 0x46 0x42 as bytes). While this isn't of much importance for the example, it shows that you can also write the complete GRFID as four escaped bytes. If you think the backslashes away, it's exaclty how the GRFID is displayed ingame and how it shows up on the OpenTTD Online Content and GRFCrawler websites.

The name and desc of course are defined as a string from the language file(s) that we defined earlier.

The version in this particular case is substituted for REPO_REVISION which will be filled by the preprocessing framework used by the Dutch Tram Set, using the revision of the version control system. If you don't have such a framework and version control system, you would in this case write a number at least as big as the min_compatible_version of 87 here.

Next we'll define the tram vehicle and make it articulated.

NML Tutorial: Tram