NMLTutorial/NML Syntax

From TTWiki
< NMLTutorial
Revision as of 15:16, 22 August 2011 by FooBar (talk | contribs) (nml syntax theory)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

This page will be a theoretical introduction to the NML syntax. It is very well possible that you don't understand anything of what is written here. If that is the case, please read the page carefully once and then just continue with the next page which will take you on an example journey through the world of coding in NML.

If you do understand this page completely, then it's very likely that you don't need the rest of this NML tutorial and just can look up what you need in the NML Documentation. At your option you can browse through the tutorial quickly or just start making your NewGRF and figure things out as you go.


NML is a programming language

NFO is not a programming language: it's hex editing. NML on the other hand is a human-readable programming language and contains things like if/else statements, operators such as &&, ||, !=, >= etc. and curly brackets to enclose groups of statements.

If you already know a programming language such as C++ or PHP, it's probably very easy to understand and adapt to the NML syntax. If you're new to programming, you should understand a few concepts:

If you're new to programming

Name things the way you want
If you define something, it's you who gives it a name. There's no set of rules how things should be called. If you want to name everything foo0001 through foo9999 that's up to you. That doesn't make it very easy to remember which is which, but it isn't wrong per se. However, don't use any fancy symbols in names: you may use (capital) letters a through z, numbers 0 through 9 and an underscore (_). Numbers furthermore cannot be at the beginning of the name of an identifier.
When referencing something, it needs to exist
If you want to use a string, the string needs to exists. That probably makes as much sense to you as that a circle is round, right? But it goes further than that: if you define a vehicle and want it to use this and that graphics, the graphics need to be defined before you define the vehicle that uses it. This applies to everything; if your reference something somewhere, that something needs to exists and essentially needs to be before the reference.
Compilers don't understand typos
If you make a typo, the compiler (in this case nmlc) doesn't understand what you mean. This especially applies to the names of things we discussed earlier. If you name your vehicle definition KirbyPaulTank, then you must use the exact capitalization everywhere. For a compiler, Kirbypaultank, kirbypaultank, kirbypaulTank etc. are all completely different things. You need to pay special attention to this if you come from Windows. In Windows there's no difference if you write a file or directory with or without captials; in a programming language with or without capitals is a completely different thing and essentially a typo when not used consistently.
Add more comments than you think is necessary
When working on a piece of code, you easily remember what does what and why you made it the way you did. However, if you don't look at a piece of code for a couple of months, chances are you have no clue what it does if you haven't commented it. Using decent names for definitions helps a great deal towards reducing the amount of comments, but ideally every code block should have a line stating what it's for and more complicated things also get comments as you go. If you do certain things differently for a reason, state why you did that. If you work with more people on one project, comments are vital in helping fellow developers understand what you did.


NML structure: blocks

NML files are mainly composed from blocks. A block starts with the type of the block, optional arguments and then the contents enclosed by curly braces. Some blocks are supplied with an identifier (ID, a name), some with even more arguments and some are only referenced by their type. The basic block syntax is as follows:

type {
    //block contents
}

or

type name {
    //block contents
}

or

type (name, argument1, [argument2 [,...]] {
    //block contents
}

Currently, the following block types exist:

  • grf
  • item
  • recolour_sprite
  • template
  • spriteset
  • spritegroup
  • spritelayout
  • tilelayout
  • switch
  • produce
  • random_switch
  • cargotable
  • railtypetable
  • error
  • disable_item
  • deactivate
  • engine_override
  • replace
  • replacenew
  • font_glpyh
  • alt_sprites
  • town_names
  • snowline
  • basecost

Some special "blocks", which aren't really blocks but language constructs, exist as well:

  • if
  • else

Furthermore, there are too many functions to list here. For now you can forget these if you want, but it's good to have seen their names.

The blocks define things that can be referenced or make new things available in the game. Some blocks can contain sub-blocks. The grf block can contain a param subblock to add parameter settings. The item block can contain property, graphics and livery_override subblocks.

If you need to do some calculations you do those outside the blocks, or in some special cases in a block's expression argument, but never inside a block. ifs and elses also have no place inside blocks and can only be used outside them.


Features

Some blocks can do multiple things. For example, the item can define a train, but also a road vehicle, ship, or aircraft. In case of such a block, you need to set which feature the block is for and supply this to the block as an argument. Below is a table of available features:

Name Description
FEAT_TRAINS Trains
FEAT_ROADVEHS Road vehicles
FEAT_SHIPS Ships
FEAT_AIRCRAFT Aircraft
FEAT_STATIONS Train stations
FEAT_CANALS Canals
FEAT_BRIDGES Bridges
FEAT_HOUSES Town houses
FEAT_GLOBALVARS Various global variables
FEAT_INDUSTRYTILES Industry tiles (visible part of industries)
FEAT_INDUSTRIES Industries
FEAT_CARGOS Cargo types
FEAT_SOUNDEFFECTS Sound effects
FEAT_AIRPORTS Airports
FEAT_SIGNALS Train signals
FEAT_OBJECTS Non-interactive objects (example: lighthouse)
FEAT_RAILTYPES Rail types
FEAT_AIRPORTTILES Airport tiles (visible part of airports)


Conclusion

Yes, that's a bunch of stuff with little hands-on examples, but I warned you about that. You'll find (most of) these different blocks explained in the remainder of this tutorial. And, of course, how every block should be written is clearly documented in the block syntax chapter of the NML Documentation.


NML Tutorial: NML Syntax