NMLTutorial/Road vehicle item definition
The example used here is from the NML source. The code for this was originally written by Terkhen and planetmaker. The graphics used in the example are by DanMack and Zephyris. 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 the first part of the road vehicle example. Let's define ourselves a road vehicle!
Item block
In order to define a road vehicle, we need an item block. For this item's feature we of course set FEAT_ROADVEHS
to define a road vehicle. We also give the vehicle item identifier a name: item_flatbed_truck_1.
The NML code for this looks as follows:
/* Define the road vehicle */ item(FEAT_ROADVEHS, item_flatbed_truck_1) { }
That wasn't too complicated, was it? Of course the item block is still empty, so let's fill it.
Property block
What properties are available for road vehicles must be looked up in the NML Documentation in two tables. One table has properites common to all vehicle types (i.e. trains, road vehicles, ships and planes) and a second table has road vehicle specific properties. Properties from both tables can go in the same property block and their order of appearance doesn't matter.
We'll not explain every property here, as you can easily look them up. Here's a full set of properties for the example road vehicle:
property { /* Properties common to all vehicle types */ name: string(STR_NAME_FLATBED_TRUCK_1); climates_available: bitmask(CLIMATE_TEMPERATE, CLIMATE_ARCTIC, CLIMATE_TROPICAL); introduction_date: date(1926,01,01); model_life: 65; /* retire_early not set, use default retirement behaviour */ vehicle_life: 15; reliability_decay: 20; refittable_cargo_classes: bitmask(CC_PIECE_GOODS, CC_EXPRESS); non_refittable_cargo_classes: bitmask(CC_PASSENGERS, CC_REFRIGERATED); loading_speed: 5; cost_factor: 108; running_cost_factor: 90; /* cargo_age_period is left at default */ /* RV-specific properties */ sprite_id: SPRITE_ID_NEW_ROADVEH; //enable new graphics speed: 48 km/h; misc_flags: bitmask(ROADVEH_FLAG_2CC); refit_cost: 0; // Refitting is free /* callback_flags are not set, no need to manually enable callbacks */ running_cost_base: RUNNING_COST_ROADVEH; power: 120 hp; weight: 9.5 ton; /* TE and air drag coefficient is left at default */ cargo_capacity: 20; sound_effect: SOUND_BUS_START_PULL_AWAY; /* Visual effect is left at default (no effect) */ }
Units
For some property values you need to supply a unit. The NML Documentation has a list of units which you can use for speed, power and weight. That way, you don't have to do any calculations on these values and just use the units you're comfortable with. NML will do the calculation for you, and you may for instance even specify the speed of one vehicle in km/h and that of the other vehicle in mph.
Functions
For some property values you are required to use a function. The NML Documentation has a list of builtin functions, but whether you actually need a function is listed in the value range column of the properties tables. Most of these functions are self-explanatory.
The bitmask() function however is important enough to address seperately. Some properties can have a list of options that you want. For instance, for the refittable_cargo_classes you can provide a list of cargo classes you want the vehicle to be refittable to. This list is encoded in a bitmask using the bitmask function.
- If you want one or more options available for the specific bitmask, use the bitmask() function.
- If you want all, put them all in the bitmask, or use the ALL_ value available for some properties without the bitmask() function.
Cargos
When defining which cargos a vehicle can carry, you can use cargo classes or cargo labels. Cargo classes combine a group of cargos into one class. Cargo labels refer to a single specific cargo. If you set what cargo a vehicle can carry, always use cargo classes. Use cargo labels only to define exceptions to these classes or to provide special graphics for specific cargos. We'll see about these special graphics later. Note that when using cargo labels you need a cargotable definition. More about the cargotable later when we get to cargo-dependent graphics for the road vehicle.
Graphics block
The graphics block links the item definition to the graphics definition. For now, we'll limit ourselves to one livery for the truck and no specific purchase menu sprite (these are generally not needed for non-articulated vehicles). This means we only have a default "callback":
/* Define graphics */ graphics { default: spritegroup_flatbed_truck_1_goods; // use a goods container for a (loaded) flatbed truck }
This tells NML to look in the spritegroup with the identifier spritegroup_flatbed_truck_1_goods
for the graphics for this vehicle. More about spritegroups on the next page.
Whatever identifier you choose here is again up to you. It's recommended to start it with spritegroup_ so you know directly from the identifier that it links to a spritegroup block. That way you don't need an additional comment for that.
Expanding the language file
You may have noticed the string(STR_NAME_FLATBED_TRUCK_1)
value for the vehicle name in the property. This means that we also need to define this particular string in the language file. Open the language file and add the string:
##grflangid 0x01 # GRF name and description STR_GRF_NAME :NML Example NewGRF: Road Vehicle STR_GRF_DESC :{ORANGE}NML Example NewGRF: Road Vehicle{}{BLACK}This NewGRF is intended to provide a coding example for the high-level NewGRF-coding language NML.{}Original graphics by {SILVER}DanMack, Zephyris, {BLACK}coding by {SILVER}Terkhen, planetmaker.{}{BLACK}This NewGRF defines first-generation flatbed truck. # vehicle names STR_NAME_FLATBED_TRUCK_1 :Flatbed Truck MkI
The complete code so far
The complete NML file so far will look like this. Don't forget to update your language file if you haven't done that yet; it should look as the one directly above.
//define the grf grf { grfid: "NML\03"; name: string(STR_GRF_NAME); desc: string(STR_GRF_DESC); version: 1; min_compatible_version: 1; } /* Define the road vehicle */ item(FEAT_ROADVEHS, item_flatbed_truck_1) { property { /* Properties common to all vehicle types */ name: string(STR_NAME_FLATBED_TRUCK_1); climates_available: bitmask(CLIMATE_TEMPERATE, CLIMATE_ARCTIC, CLIMATE_TROPICAL); introduction_date: date(1926,01,01); model_life: 65; /* retire_early not set, use default retirement behaviour */ vehicle_life: 15; reliability_decay: 20; refittable_cargo_classes: bitmask(CC_PIECE_GOODS, CC_EXPRESS); non_refittable_cargo_classes: bitmask(CC_PASSENGERS, CC_REFRIGERATED); loading_speed: 5; cost_factor: 108; running_cost_factor: 90; /* cargo_age_period is left at default */ /* RV-specific properties */ sprite_id: SPRITE_ID_NEW_ROADVEH; //enable new graphics speed: 48 km/h; misc_flags: bitmask(ROADVEH_FLAG_2CC); refit_cost: 0; // Refitting is free /* callback_flags are not set, no need to manually enable callbacks */ running_cost_base: RUNNING_COST_ROADVEH; power: 120 hp; weight: 9.5 ton; /* TE and air drag coefficient is left at default */ cargo_capacity: 20; sound_effect: SOUND_BUS_START_PULL_AWAY; /* Visual effect is left at default (no effect) */ } /* Define graphics */ graphics { default: spritegroup_flatbed_truck_1_goods; // use a goods container for a (loaded) flatbed truck } }
This concludes the item definition for the road vehicle. Continue to learn about adding graphics and after that you'll see how to add the graphics for the road vehicle.
NML Tutorial: Road vehicle item definition