NIMBY Rails – Mod development guide

NIMBY Rails – Mod development guide 7 - steamlists.com
NIMBY Rails – Mod development guide 7 - steamlists.com
How to create mods for NIMBY Rails.

 
 

Introduction

At this time NIMBY Rails supports adding new train models to the game with Steamworks mods. Other kinds of mods may be added in the future. In this guide I will describe how these mods are structured, how to develop and test them, and how to upload them to Steamworks. 
 
 
 

Concepts

 

Rules

In the game systems, a rule is an object that contains constant, immutable data that controls parameters of the simulation. Mods are just a collection of rules objects written in an easy to edit text format, plus any required data in separate files, like textures. 
 

IDs

Rules objects usually have an ID field, and often make reference to other rules objects by using their ID. When creating your own mods you must pick unique IDs for your rules objects, not used by the game or by other mods. IDs are arbitrarily long strings so it should be easy to come up with both unique and readable IDs. 
 

schema

All the objects declared in the mod have a schema field. This declares the version of the mod structure, and allows the game to load older mods. Use the schema value indicated in the rules tables in the next section. 
 

(E)MUs

At the time of this writting the game only supports train models known as (electrical) en.wikipedia.org – https://en.wikipedia.org/wiki/Multiple_unit. In MU trains the carriages are self-propelled and are usually part of a single whole train designed to go together. There’s still a distinction of carriages for the ends of the train and the inner carriages, and the game has support for this. In the future the game may also support custom train compositions edited in-game by the player. 
 
 
 

Train Rules

 

TrainUnit

The rules object TrainUnit represents the combined concept of a train car and/or locomotive. The game makes no distinction, and a TrainUnit may act as both concepts at the same time, depending on how it is configured. This is modeled after contemporary electrical multiple unit trains (EMU), which can have engines in every car. It is of course possible to declare a TrainUnit with no power if unpowered cars are desired. 
 

Field Type Range Description
schema integer 1 This guide describes schema version 1
id string any string Global, unique ID that identifies this TrainUnit
name_loc string any string ID used to localize name_en
name_en string any string English name of the carriage
length meters 1 to 30 Length of the carriage
width meters 1 to 3.75 Width of the carriage
max_speed km/h 10 to 10,000 Max allowed speed
power kW 0 to 100,000 See the description below
empty_mass kg 1,000 to 100,000,000 Empty mass of the carriage
price "cash" 0 to 1,000,000,000 Price for one carriage unit
max_pax passengers 0 to 1,000 Max allowed passengers
cost_per_km_per_pax "cash" 0 to 1,000 Price to pay for every passenger in this carriage over 1km
cost_per_day "cash" 0 to 100,000 Price to pay for running this carriage for 1 day
tex_base relative path any valid relative path Base, colorizable texture
tex_top relative path any valid relative path Top texture
tex_decors relative path list a list of valid relative paths List to decorative colorizable textures
tex_m_width meters 30 This field must be always 30
tex_m_height meters 3.75 This field must be always 3.75

 

The power field vs tractive effort

Engines are not currently moddable, so instead the TrainUnit only allows to specify a power output value in kW, then the game applies an internal formula to derive a tractive effort. 
// tractive effort = K * (n * P / V) // tractive effort is expressed in N // K = constant // n = efficiency of motors // P = power in W // V = speed in m/s tractive_effort += 3.0681818 * ((0.9f * power) / max_speed); When deriving this value, keep in mind you are specifying its value per carriage, so divide accordingly for MU trains. 
 

TrainMultipleUnit

A TrainMultipleUnit represents a multiple unit train model, and references TrainUnit objects for the head, cars and tail composition. The game only supports multiple unit trains, and you must declare at least one TrainMultipleUnit if you want to add new trains to the game. 
 

Field Type Range Description
schema integer 1 This guide describes schema version 1
id string any string Global, unique ID that identifies this TrainMultipleUnit
name_loc string any string ID used to localize name_en
name_en string any string English name of the multiple unit
head_id string a valid TrainUnit ID ID of the TrainUnit positioned in the front
car_id string a valid TrainUnit ID ID of the TrainUnit of the inner carriage
tail_id string a valid TrainUnit ID ID of the TrainUnit of the last carriage
tail_flip boolean true or false Horizontally flip the texture of the tail TrainUnit
min_cars integer 1 to 30 Minimum amount of inner carriages
max_cars integer min_cars to 30 Maximum amount of inner carriages

 
 
 
 

Mod structure and development

A mod is just a folder that contains a file named mod.txt. This file is formatted using the simple en.wikipedia.org – https://en.wikipedia.org/wiki/INI_file. Inside mod.txt you must declare at least one ModMeta section, and then one or more rules sections. 
 

Folder structure

Here’s how the structure of folders and files looks like when you are developing a mod in your local PC. If you put your mod in the "mods" folder of your local saved games folder, it will show up in game. In this example you are developing a mod inside the folder "nr-example-train". 
 
NIMBY Rails - Mod development guide 
 
The only mandatory file is "mod.txt". You can also create any other folders and files required to organize and bundle textures in your mod. 
 

Example mod.txt

 
This mod.txt file can be found in the github.com – https://github.com/weirdandwry/nr-example-train
 
[ModMeta] schema=1 name=Test train mod author=Weird and Wry desc=testing 1 2 3 version=1.0.0 [TrainUnit] schema=1 id=test1_car name_loc=test1_name name_en=TestTrain length=6.5 width=2.4 max_speed=70 power=144 empty_mass=7000 price=1700000 max_pax=45 cost_per_km_per_pax=0.05 cost_per_day=700 tex_base=AlstomCitadis/car_0.png tex_top=AlstomCitadis/car_2.png tex_decors=AlstomCitadis/car_1_0.png,AlstomCitadis/car_1_1.png tex_m_width=30 tex_m_height=3.75 [TrainUnit] schema=1 id=test1_head name_loc=test1_name name_en=TestTrain length=6.5 width=2.4 max_speed=70 power=144 empty_mass=7000 price=1700000 max_pax=40 cost_per_km_per_pax=0.05 cost_per_day=500 tex_base=AlstomCitadis/loco_0.png tex_top=AlstomCitadis/loco_2.png tex_decors=AlstomCitadis/loco_1_0.png,AlstomCitadis/loco_1_1.png tex_m_width=30 tex_m_height=3.75 [TrainMultipleUnit] schema=1 id=test1_mu name_loc=test1_car_name name_en=TestTrain head_id=test1_head car_id=test1_car tail_id=test1_head tail_flip=true min_cars=1 max_cars=3  
 

ModMeta

The ModMeta section gives some general information that is displayed to the user in the game UI. 
 

Field Type Range Description
schema integer 1 This guide describes schema version 1
name string any string Mod name used in the in-game UI
author string any string Mod author name used in the in-game UI
desc string any string Mod description used in the in-game UI
version string any string Mod version used in the in-game UI

 
 

Steamworks uploader

In order to create and upload your mods to Steamworks, you first need to make sure your mod works properly as a local mod, and have it installed as such. So the first step is to develop your mod as a local mod, in your local mods folder as described in the first section of this chapter. 
 
Once your local mod is ready, you can use the Steamworks mod uploader available in the Main Menu, Options dialog. 
 
NIMBY Rails - Mod development guide 
 
By default the mod uploader shows a listing of your authored mods already uploaded in Steamworks, and a series of options. 

  • New mod: Create a new mod from an existing local mod 
  • Update mod: Update the selected Steamworks mod from an existing local mod 
  • View mod in workshop: view the selected Steamworks mod in the Steam overlay 
  • Manage workshop: view your private Workshop in the Steam overlay 
  • Mod development guide: opens a browser with this guide

 
When you select "New mod" or "Update mod" the mod editor is displayed: 
 
NIMBY Rails - Mod development guide 
 
You must fill all the displayed fields before you can create or update an existing Steamworks mod. 

  • Title: mod title to display in the Workshop 
  • Visibility: decide if you want to make your mod public or not. You can change this option later if you update your mod again 
  • Local mod to upload: select an existing, local, valid mod as the contents for this Steamworks mod 
  • Icon file: type a path or open a file picker to select an image to display in the Workshop as the mod icon 
  • Description: mod description to display in the Workshop 
  • Update note: mod change log to display in the Workshop (only for updates)

 
You may find it easier and more usable to edit the description and update note fields from the Workshop interface than from the uploader interface, after the uploader is done creating or updating your mod. 
 
 
 

Textures

Train units are drawn with 3 texture layers: base, decal and top. Every layer is a full RGBA 32bit PNG image of size 1024×128, which always corresponds to a real world size of 30m x 3.75m. Train units can be shorter and narrower than this size, in that case the unit must be aligned to the left of the image for the X axis, and centered in the Y axis. The real size of the train unit is then declared in the TrainUnit section of the mod.txt file (in meters, never in pixels). Use a conversion factor of 34.13 pixels per meter when drawing the textures. 
 
You can store the PNG files in the mod folder with any name, and with any subfolder structure you wish to use, as long as you use correct relative paths to reference them from the mod.txt file. 
 
NIMBY Rails - Mod development guide 
 
The base layer is drawn first, and it can be colorized by the user in the train properties editor. For this reason it is recommended to make this layer grayscale. The colorization function is a simple component-wise color multiplication. Use this layer to represent the bulk of the train unit. 
 
NIMBY Rails - Mod development guide 
 
The decal layer is drawn on top of the base layer. It is also colorizable by the user, and uses the same multiplication function. It is possible to declare a series of decal layers in the same TrainUnit by separating them with commas. The user will then be capable of choosing one in the train properties editor. Use this layer as a decoration, to give the user more customization options. The user can also colorize this layer with the line colors. 
 
NIMBY Rails - Mod development guide 
 
The top layer is drawn on top of the decal layer, and it is not colorizable. Use this layer for final details and for parts of the train that should never be colorized, like windows. 
 
 
 

Translation mods

Translation mods are structured in the same way as any other mod: a main mod.txt file which declares generic information about the mod, and then one or more sections declaring which language is being supported, and which dictionary files are to be loaded. Read the "Mod structure and development" section on how to create local mods for development, and how to upload your work to Steamworks. 
 

Source translation

To make a new translation you will need to customize github.com – https://github.com/weirdandwry/nr-local-spa to your language. This translation is kept up to date with the game, so on new versions you will be able to also track the changes in your own translations. Edit the mod.txt and game.po files as described in the rest of this guide. 
 

mod.txt for translation mods

Make sure to read what is the mod.txt file and its basic ModMeta section as described earlier in this guide. This is a complete example of a mod.txt file for the Spanish translation: 
 
[ModMeta] schema=1 name=Traducción al Español author=Weird and Wry version=1.0.0 [Language] code_iso_639_2=spa name=Español [LanguageDict] code_iso_639_2=spa po=game.po  
There are 2 translation specific sections: Language and LanguageDict. 
 

Language section

The language section identifies a language to be displayed in the options drop down in the game Options dialog. If no Language section is provided, the game will never display the option to select a language, even if a LanguageDict and a PO file is present. 
 

Field Type Range Description
code_iso_639_2 string an ISO 639-2 code Languages are identified by ISO 632-2 codes
name string any string Native name of the language

 
Only use ISO 632-2, 3 letter codes to identify languages, do not make up any random code or use the 2 digit codes. You can look up the codes in en.wikipedia.org – https://en.wikipedia.org/wiki/List_of_ISO_639-2_codes. Also always use UTF-8 file encoding, both in mod.txt files and PO files. No other encoding is supported. 
 

LanguageDict section

The LanguageDict section declares a PO file as a translation dictionary for a given language ISO 632-2 code. 
 

Field Type Range Description
code_iso_639_2 string an ISO 639-2 code Languages are identified by ISO 632-2 codes
po string a relative path Relative path to a PO file

 
 

The PO file

Translation dictionaries are a simple text file that repeatedly lists the strings to translate in the game. Edit PO files with any text editor that supports UTF-8 editing. For every string you will find 3 entries: msgctxt, msgid and msgstr. For example: 
 
msgctxt "host_game" msgid "Host game" msgstr "Hospedar partida"  

  • msgctxt: the internal identifier for the string. Do not edit this text. It often gives extra information about the context of the string. 
  • msgid: the original english text of the string. 
  • msgstr: the translated text of the string. This is the text you have to edit.

 
Sometimes strings contain arguments, indicated as {}, and your translated text MUST preserve these arguments. For example: 
 
msgctxt "banner_join_friend" msgid "{} wants to join your game." msgstr "{} quiere entrar a tu partida."  
You can locate the {} argument anywhere inside your string. Sometimes there’s more than one argument, and this is indicated by a series of arguments like {0} and {1}: 
 
msgctxt "banner_prompt_nogame_join_user" msgid "{0} proposes you to join a game hosted by {1}. Do you want to join?" msgstr "{1} hospeda una partida y {0} te propone entrar a jugar. Quieres jugar con ellos?"  
Again, if an argument is present in msgid, it MUST also be present in msgstr, but it does not have to be in the same position. Reorder arguments as you see fit for your language. Occasionally you will also come across more complicated arguments like {2:+.2f}. Just locate them in any position you decide, but don’t modify the contents. The game will actively reject your translated strings if their arguments don’t match, and it may even crash if your translated string is too malformed. 
 
To test your translation in-game, first make a local mod in your Saved Games folder as described earlier in this guide. If it’s created properly it will show up in the Languages drop down in the Options dialog, and it can be immediately activated. Keep in mind a few strings are not properly updated when changing languages this way, like tab titles. Restarting the game will fix this. 
 

Written by Weird and Wry

This is all about NIMBY Rails – Mod development guide; I hope you enjoy reading the Guide! If you feel like we should add more information or we forget/mistake, please let us know via commenting below, and thanks! See you soon!
 
 
 
 


Be the first to comment

Leave a Reply

Your email address will not be published.


*