Based on the pioneering work in locomotive mods done by Kimmo Jaske
(a.k.a. Bombardiere) and others who dissected the file structures in
Railroad Tycoon 3, I have developed the following method of creating
new rolling stock (freight and passenger cars) for use in the game. If
you want to see and download some of my cars, then
click here to see the cars I have created.
Jump to .3DP FILE EDITING...
EDIT: Current Modding Tools I recommend are - Image Editor =
GIMP; Hex Editor =
Tiny Hexer (mirkes.de); PK4 Unpacker =
Game Extractor, Watto Studios; DDS Converter =
DDSview (save as DXT-C3), or use User Skinning Tools to create PK4's in which a DDS is packed.
To begin, you must BACKUP ANY FILES WHICH YOU WILL BE CHANGING. In most
cases, this means only the .CTY file, as this method assumes that you
are creating new assets for all the rest (based on copying and renaming
the default game files). I created a "Backup" folder within my
UserExtraContent folder, which contains a complete archive of all the
types of files I use - basically I unpacked the PK4 files into
similarly-named subfolders here. You might prefer to store your
backups elsewhere; it is probably better to NOT have them in
UserExtraContent.
STEP 1: There is a
.CTY file for each unique cargo in the game, kept in the
DATA/CARGOTYPES/ folder. The easiest way to introduce a reskinned or
new car is right here. Use a Hex Editor to get into this file and
change it to refer to a different car type (which you will be
creating), rather than the game's default. Refer to documentation by
Pjay and Milo on the file structures to see what to edit and where.
Aside from referencing a new car type here, you can also adjust the
baseline price of the cargo as well as the cargo ID; there is also a
byte used by the CargoModel to determine what kind of load to
represent. That is, this is what tells a hopper to load up with coal or
iron or bauxite, similarly for flatcars. For starters, though, leave
all of this untouched aside from the reference to your new car type.
Save right back to DATA/CARGOTYPES/ with the same filename.
STEP 2: This method
assumes that you are creating a new car type based on a game default,
such as creating an Iron Ore Hopper to carry iron, based on the default
Hopper. Open the .CCT file for the default car, found in
DATA/ENGINETYPES/, and save it using your new car type's name in the
same folder. In this example, open the HOPPER.CCT file and do an
immediate "Save As" to rename it IRONORE.CCT (you can give it any name
you want, but shorter is better, because you will be typing it a lot in
the next few steps!). I suggest saving before modifying so that you
don't accidentally screw up the default - again, a BACKUP OF ALL .CCT
FILES would be very prudent.
Once you have your new car's .CCT file begun, you can change it in a
Hex Editor to refer to the new car's name. This reference tells the
game engine which Car Bodies and Cargo Loads to look for. I recommend
using the same [carname] prefix for all assets belonging to this car,
although there might be ways to avoid redundancy by refering to some
shared or default assets in some cases. A relatively recent computer
can surely handle the redundant assets. As for my recommendation for
[carname], I suggest the following:
HBAUX = H+BAUX = Hopper car for Bauxite
Use one letter for type, plus the first four letters of the specific cargo. Types would be:
A=Auto Carrier
B=Boxcar
C=Covered Hopper
D=Diner
F=Flatbed
H=Open Hopper
M=Mail
P=Passenger
R=Refrigerated Box Car
S=Stock Car
T=Tank Car
X=Caboose
STEP 3: Create .CAR
and .CGO files for your new car in a manner similar to what you just
did for the .CCT file. You can do this by copy+paste if you prefer,
renaming the pasted files before you open them up in the Hex Editor. By
default, the game uses a four-era structure, with an A, B, C, and D
version of each car. These car models swap out in 1850, 1900, and 1950.
However, these dates are not carved in stone! It is in the .CAR file
where you can define different start and stop years for each era.
Moreover, you can introduce additional eras (I use W, X, Y, and Z
versions as transitional models, such that a W-era car comes between A
and B, while Z comes after D) and thus end up with a car body that goes
through more than four versions during the course of the game. Each era
that you intend to use must have both a .CAR file and a .CGO file.
Again, refer to documentation by others to understand what gets changed
in the file. The .CAR file is the "master index" of the graphical
assets that will be displayed, as well as other things. Note that
locomotives also have .CAR files; be sure to use a freight or express
car's files as your template here. The segment of the file that gives
the weight of the car appears to give 1/2 the weight, or the
theoretical "empty" weight of the car. I am not sure that the game
makes any use of this, since "empties" don't run on trains in the game,
but I just set this to half the loaded weight. For cars like the Diner
and Caboose, the weight given here is actually the total weight, since
there is no .CGO file; these cars do not get loaded.
The .CGO file just gives the total loaded weight of the car. This can
be altered; I am working on re-weighting the cars to make it such that
heavy steam engines have a noticeable advantage after about 1930. My
feeling is that the default game behavior makes articulated steam like
the U.P. Big Boy almost always a losing proposition - you can run
Mikados right up to 1950. By introducing some slightly heavier cars
every few years, the average car weight will rise over time and begin
to slow down that Mike... at least that is the theory!
The .CAR file will also refer to "CarSideView1.imb" for the 2D profile
of the car that shows up in the train list interface. CarSideView is a
collection of all the cars and locomotives in the game in one image
file; the IMB file tells the interface where to crop for each unique
car type. Editing this would be a major pain, so the far easier way to
create the profile is to change this to refer instead to
"[carname]A_Profile.IMB". In step 4, you will create the Profile IMB
and DDS files that this refers to.
All files edited in Steps 2 and 3 get saved into the DATA/ENGINETYPES/ folder.
STEP 4: This is the
real meat of your work, and likely to take a fair amount of time. The
simplest thing is to gather all the .3DP assets you will need; simply
copy+paste the ones you intend to use and rename them using your chosen
[carname]. If you are doing a version of a Hopper, then you will need
to copy all of the HOPA_*.3DP, HOPB_*.3DP, HOPC_*.3DP, and HOPD_*.3DP
files, for instance. Feel free to mix-and-match, though; if you want to
"promote" the D-era car body into the C-era, for instance, then you can
just name the D assets as C assets. If you think the C-era boxcar shape
looks more like a Reefer (I did!) then you can choose to use those 3DP
files instead. It may be possible, in a manner similar to Bombardiere's
work with locomotive modding, to mix-and-match Trucks with Car Bodies,
but I have not done so yet. A reason for doing so might be if someone
were to work on a European set of cars, many of which have single-axle
trucks rather than the American 2-axle "bettendorf" trucks.
For the car skins, fire up your favorite image editor and have at it!
You will need software that can at least read the DDS files that the
game uses, though preferably one that can save the DDS file to a TGA or
other format (and vice-versa). You need to preserve the Alpha Channel
as you convert to whatever file type you will be working with in your
editor; the Alpha Channel will tell the game engine that some pixels in
the skin are fully transparent, others are fully opaque, and the rest
are to be treated as if they glow at night. Keep this in mind while you
work, and do what it takes to keep control over the alpha channel. You
can use the alpha channel to change the car's shape in subtle ways,
too, such as making all the zig-zags along the bottom of a boxcar's
sill line. The Stock car is basically just a box car with alpha'ed
space (transparency) between the slats - you can use the Stock car's
3DP files to represent a solid-walled boxcar or reefer (I have!).
To create a realistic-looking car, scour the internet for side-on
images of the type of car you wish to represent. Photos of real cars
are preferable, but often it is easier to locate photos of models,
particularly from hobby manufacturers such as Atlas. Depending on what
you find, you may need to do some perspective correction to get the car
side photo to be truly rectangular. Once you do so, though, really all
you have to do is paste in that car side into the "A" skin you are
working on. Always work on the "A" skin; the game uses A,B,C,D,E, and
sometimes F skins at smaller and smaller resolutions, swapping them out
based on how far away the camera is zoomed. You can complete the A
skin, then resize it and save as B, resize and save as C, etc.
Alternately, you can feed the A skin into the UserSkinningTools
provided with the Coast to Coast expansion, creating a dummy loco mod
that uses that skin, and it will produce a PK4 file which, when
unpacked, includes all of the A, B, C, etc. versions, saved as DDS
files.
However, I prefer to do resizing manually, because you need to clean up
the alpha channel between iterations! Otherwise, you end up with skins
that glow around the edges at night time. This happens because the
reduced-resolution versions of the skin end up with partially
transparent pixels around the border between transparent and opaque
areas. To overcome this, in the image editor I select all the fully
transparent pixels, create a new layer which will underlay the original
artwork, invert the selection (so that now I have a selection that
includes all of the non-transparent pixels, including those half-opaque
offenders), and then fill the selection with a solid black or dark grey
color. In essence this is creating a silhouette of the non-transparent
areas on a mostly-hidden layer, which has the effect of forcing the
alpha channel to stark contrast (fully transparent or opaque). Of
course, some cars like passenger cars have windows which are intended
to glow at night - you will need to erase the silhouette from beneath
those windows so that they remain partially transparent. As you resize,
from 1024x1024 (A) to 512x512 (B) to 256x256 (C) etc., each time you
should erase the silhouette layer and recreate it, otherwise the
silhouette itself will develop a partially-transparent fringe.
Ultimately, you will need a set of A,B,C,D,E,F skins for each car model
(of each era A,B,C,D, and more if you create them), saved as TGA or DDS
files. The TGA's are easier to work with and I usually leave them at
that, but if you use the UserSkinningTools then you'll end up with DDS
files, which are smaller. Yes, this is a LOT of graphic art work! But
after you've done a few, it gets easier and quicker.
For the 2D Profile icon that shows up in the train list, you can
copy+paste a portion of your D-level skin into a file that is 32x128. I
start with the CarSideView1.DDS file that comes with the game, and crop
in to the type of car I am working on. This car will be shorter than
128 pixels, so just add transparent area as need to achieve this size -
do not leave it at some odd value like 49x32! The DDS file format
apparently expects dimensions in powers of 2, otherwise you get an
oddly garbled icon when you make the conversion to DDS. The car should
be all the way over to the left, with its wheels resting on the bottom
of the image. Now, you can paste in the car side from your D-level
skin, resizing it as necessary to match the icon. Pay attention to just
how long, in pixels, the car icon actually is; this width must be
entered into the .IMB file to tell the game what to crop that 128x32
image down to. When you open the .IMB file in a hex editor, you will
see at the end of it a listing of coordinates, like "0 0 56 32".
This is telling the game to use the rectangular portion between pixel
0,0 and pixel 56,32; in other words, crop in to a width of 56, height
of 32. Just change the third coordinate to whatever width the icon
really is.
All files in Steps 4 and 5 get saved into your DATA/USEREXTRACONTENT/ folder.
STEP 5: This step is
not needed for all cars, but some cars do make use of a Cargo Icon or a
Cargo Model. A Cargo Icon is like a decal of the type of load that the
car is carrying, for instance a boxcar loaded with cotton will show the
cotton icon on its side. If you don't want to see this icon (if it is
obscuring your wonderful artwork), then you can try first to just
eliminate the _CargoIcon1.3DP file. I know this works for passenger
cars. Another option is to use a different source for the .3DP file,
such as using the TankA_CargoIcon1.3DP for a boxcar. What this does is
effectively locate the icon inside the body of the car, because the
TankA body is skinnier than other cars.
Flatcars and Hoppers utilize the CargoModels to make them look
different when they are carrying different loads, such as Iron and Coal
in a hopper. The game selects the right CargoModel based not on the
Cargo ID but rather another variable embedded in the .CTY, declared way
back in Step 1, although I discovered that it actually uses that number
plus one! In other words, if byte 32 of the CTY file = 03, then
CargoModel04 will get used. Refer to the documentation by Pjay and Milo
on this; it is rather arcane. But one possible use of this that I am
envisioning is taking a stock car body (since it has a floor), using
the alpha channel to erase the roof and half of the walls, skin it as a
gondola, then fill it up with CargoModel10 (heaps of coal) or even
CargoModel05 (coils of steel).
3DP FILE EDITING
Notes
on the 3DP file structure compiled by PJay, as shared with Bombardiere
(Kimmo Jaske) and WPandP (Michael Rountree), edited by Michael Rountree.
3DP files
4 bytes : "3DPF" = bytes: 51 68 80 70
4 bytes : 04 00 01 00
4 bytes : "3DMD" - bytes: 51 68 77 68
4 bytes : int: number of instances
3*4 bytes : float: center X, Y, Z
[Editor's Note: The Center point appears to be the nodal point
which defines where this element connects to other elements; for a
_Body.3dp it refers to the spot where it sits on the track, and for
things like pistons or connecting rods it refers to connections to
dependent elements. If you get this wrong, you'll see weird
behavior like a driving rod that loops around through space.
Also, I saw that changing the X-value on what amounts to the axle of a
wheel does have an effect, even though the axle is basically a line in
the X dimension; two wheels with the same center Y and Z values but
different X values will rotate at differing speeds. This may be
due to absolute distance to centerline of track.]
INSTANCES / LIGHTS
INSTANCE
============
4 bytes : "INST" = bytes: 73 78 83 84
4 bytes : int: number of coordinates (or points)
4 bytes : int: number of triangles (or faces)
?*12 bytes: points (defined below)
?*76 bytes: faces (defined below)
[Editor's Note: INST's are redundant in that they repeat points
and faces, but with decreasing detail. I have been editing only
the first INST with success, but perhaps because my computer is fast
enough to max all graphics settings; lesser rigs may depend on the
simplified INST's. It may be necessary to reduce an edited 3DP to
just a single INST, unless you make the same changes to the
corresponding points in all INST's. If you do reduce to a single
INST, then make note of it in the Readme, to the effect that this mod
will tax the resources of lesser computers or possibly even induce game
crash; I haven't seen this happen yet, but again it may just be because
I've got a decent rig.]
LIGHT
============
4 bytes : "LGHT" - bytes: 76 71 72 84
4 bytes : int: number of lights
if number of lights = 1
--------------
12 bytes : int: 00 00 ... 00 00
4 bytes : float: 0.0 <=> 1.0
3*4 bytes : float: 0.0 <=> 1.0
3*4 bytes : float: -... <=> +... (X, Y, Z)
if number of lights = 2
--------------
4 bytes : int: 0
4 bytes : float: 6 <=> 46
4 bytes : float: 15 <=> 65
4 bytes : float: 0.0 <=> 1.0 (of 2.0)
3*4 bytes : float: 0.0 <=> 1.0
3*4 bytes : float: -... <=> +... (X, Y, Z)
3*4 bytes : float: -... <=> +... (X, Y, Z)
[Editor's Note: I do not yet understand and have not attempted to
mod the Lights of a model. The glowing of lit windows, such as on
a passenger car at night, is done through the alpha channel of the skin
file, not in the 3DP file.]
POINTS / COORDINATES
=============
4 bytes : float: X value
4 bytes : float: Y value
4 bytes : float: Z value
[Editor's Note: Values are relative to origin (0,0,0) equal to center
of the model at track height, for cars and engines at least. +X
is left side of train, -X is right side of train, +Y is caboose end of
train, -Y is front end of train, +Z is above railhead, -Z is below
track. Units are not to any apparent scale, but rail gauge
appears to be 6.25 units, so 1.0 unit = roughly 9 inches for American
standard gauge. Models appear to not be created to a uniform
scale; the Pacific 4-6-2 for instance is gigantic compared to other
steam engines.]
FACES / TRIANGLES
=============
3*4 bytes : int: Point number (according to order of points listed above)
3*4 bytes : float: normal vector in point 1 (X, Y, Z)
3*4 bytes : float: normal vector in point 2 (X, Y, Z)
3*4 bytes : float: normal vector in point 3 (X, Y, Z)
2*4 bytes : float: coordinate 1 in
texture file (x, y) [range 0.0=left or top most pixel to 1.0=right or
bottom pixel]
2*4 bytes : float: coordinate 2 in
texture file (x, y) [range 0.0=left or top most pixel to 1.0=right or
bottom pixel]
2*4 bytes : float: coordinate 3 in
texture file (x, y) [range 0.0=left or top most pixel to 1.0=right or
bottom pixel]
4 bytes : int: main direction (0=-x, 1=+x, 2=+y, 3=-y, 4=-z, 5=+z)
[Editor's Note: I am unsure of the purpose behind the normal
vectors and the main direction. Whatever portion of the skin file
you map onto the set of points will display to both sides, as if the
normal was both ways all the time. If you type in the coordinates
in the wrong order, your skin will appear warped and turned on the
model, but the easy way to correct this is just to list the points in a
different order, in the first 12 bytes. This may be necessary if
you copy and paste the (x, y) coordinates from one source to another,
as the source may have listed its points in a different order. In
other words, if AA - AB - AC looks funky the way you've defined it,
don't bother retyping all those floating point X and Y values; just try
AB - AA - AC and other permutations until it looks right. Also,
note that you do not have to use the triangles given in the source
file... you can define a triangle between any three points! This
may be a way to get rid of a face that you don't want to see, or to
create features that did not exist in the source. An example
might be a chain between the bell and the cab roof on an old steam
engine: this could be just a single triangle that goes between
the center peak of the bell, to the center peak of the roof, with the
third point somewhere near the midpoint down low between the
rails. In the skin file, draw the sagging chain with a lot of
clear (alpha-masked) space around it, and map the coordinates with one
end of the chain at the first point, the other end of the chain at the
second, and the third point somewhere deep below the center of the
chain. Of course, to create a new triangle like this, you must
give up one of the other triangles... unless you go back to the
beginning of the file and change the number of points or faces or both.]
OTHER
=============
Other .3DP file first 8 bytes:
BE BA 00 00 68 01 00 00 => _anim.3dp
_Anim*.3dp => INST's in 3DMD files
_Light*.3dp => LGHT's in 3DMD files
[Editor's Note: A decent hex editor, like "Tiny Hexer" from
mirkes.de, will allow you to set the number of columns to view the
file's contents, and when set to 12 columns then the long sections of
X, Y, Z coordinates will line up such that all X's are in one column,
etc. This is helpful so that you can see which points belong
together, as, for instance, the side of a boxcar will have the same
value for X, two values for Y, and two values for Z. To map out a
_Body.3dp file takes patience, but can be done by changing one value to
a ridiculous amount, such as setting the X-value to -30. Save the
file, making sure that you will be able to Undo after Save first, then
load in the game. The model will be warped at that point, you can
it write down (i.e. "Point 0A = Cab Roof Front Right"). Most of
the time, points are grouped together where they describe a given
rectangle or even the full cylinder of a boiler, so you don't have to
map every point. Just find the major features, and of course you
need to find all the points you intend to modify.
This is tedious for a complex model like a Steam Engine, but can be
done. It is much easier for lesser models, like Trucks or
Bogies. Bogies are just simple square faces (the roundness is
achieved via alpha mask in the skin file), with four corners and a
center of rotation, and two triangles defined. To relocate a
wheel, you'll edit the Y values for all five points by the same amount;
changing the Y value moves a feature forward and back along the
track. "Tiny Hexer" has a Structure Viewer tool that can be set
to show floating point (32-bit) values directly, and permit you to
change that value by typing in the new decimal value. With other
hex editors, you may need to do some manual translation of values via
another means]