Skip to content

Vehicles

A vehicle is a model (.mdl) whose metadata has the vehicle blocks described here. Meshes, materials, LODs and the general metadata blocks (lights, labels, load indicators, particles) work as in any other model, see Models and assets. This page covers the metadata of buses, trains, ships and planes, how the vehicle types differ, and repaint mods. Transformator scripts, reversible trains, buy menu groups and fake bogies are on the second page, Vehicles: advanced topics.

The wiki splits vehicles into two groups: vehicles the player buys and runs on lines (buses, trucks, trams, trains, ships, aircraft), and cars, which the game drives on its own as private traffic.

Where the vehicle files are

The base game keeps its vehicles in vehicle/<type>/<name>/ inside the content folder. In the unpacked files each vehicle is its own archive, so the path doubles the vehicle name: the eCitaro bus is base/content/vehicle/bus/ecitaro/ecitaro/ecitaro.mdl, which the game addresses as vehicle/bus/ecitaro/ecitaro.mdl (see How the zips map to folders). Next to the model are mat/ (materials, with textures in mat/tex/), msh/, ani/ and icons/.

Folder Base models Contents
vehicle/bus 24 buses and coaches
vehicle/truck 48 trucks, horse carts
vehicle/car 46 private cars (AI traffic)
vehicle/tram 55 trams, tram wagons, light rail
vehicle/train 70 locomotives and multiple unit parts
vehicle/waggon 41 unpowered rail wagons (the folder is spelled waggon)
vehicle/ship 27 ships, ferries, hovercraft
vehicle/plane 30 aircraft
vehicle/helicopter 11 helicopters
vehicle/zeppelin 3 airships, see below

The wiki names vehicle/wagon for unmotorized rail vehicles; the base game folder is vehicle/waggon. Shared files such as sound sets, emissive light materials and shared animations sit in vehicle/<type>/shared/ and vehicle/shared/. The DLCs add 18 more vehicle models under dlcs/<dlc>/content/vehicle/vehicle/..., for example the Concorde in dlcs/urbangames_deluxe_upgrade_pack/content/vehicle/vehicle/plane/concorde/concorde.mdl.

Which metadata blocks a vehicle needs

Block Used by Purpose
transportVehicle every vehicle the player can buy carrier, transport modes, capacity, loading, depot filter
landVehicle road, tram and rail engines, top speed, weights, braking
roadVehicle buses, trucks, cars axles, steering wheels and fake bogies
railVehicle trains, wagons, trams axles and fake bogies
waterVehicle ships power, drag area, waterline
airVehicle aircraft, helicopters thrust, wing area, landing gear
car private cars marks the model as AI traffic
colorConfig private cars random paint colours
seatProvider almost all driver and passenger positions
emissions almost all noise and pollution
soundConfig almost all sound set
transformatorConfig all script that drives animations and particles
availability, cost, maintenance, description buyable vehicles years, price, running costs, name (see Common blocks)

The types are in the reference as ModelMetadata.TransportVehicle, LandVehicle, WaterVehicle and AirVehicle. roadVehicle, railVehicle, seatProvider, car and colorConfig appear in the model files but have no Teal record.

All base vehicles are version = 2 models. For those the base game adds nothing on its own: the loaders that would add a default transformatorConfig (addTransformatorConfig) and default door, wheel and light animations (createAnimationEvents*Vehicle in base/content/base/base/metadataanimationutil.lua) only run for older model versions. A new vehicle has to name its transformator and carry its animations on the nodes itself.

Transport vehicle

From the eCitaro, base/content/vehicle/bus/ecitaro/ecitaro/ecitaro.mdl (shortened):

transportVehicle = { 
    carrier = "ROAD",
    comfortFactor = 0.65,
    compartments = {
        { 
            loadConfigs = {
                { 
                    cargoEntry = { 
                        capacity = 80,
                        cargoTypeSet = { 
                            cargoClassesIncluded = { "PASSENGERS", },
                            cargoClassesExcluded = { },
                            cargoTypesIncluded = { },
                            cargoTypesExcluded = { },
                        },
                        loadIndicator = "",
                        seats = { },
                    },
                    toHide = { },
                },
            },
        },
    },
    engineTransportModes = { "BUS", },
    entrances = {
        { path = { { 4.8, -3, 0.3, }, { 4.4, 0, 0.4, }, }, },
        { path = { { -1.1, -3, 0.3, }, { -1.1, 0, 0.4, }, }, },
    },
    filterTags = { "default", },
    loadSpeed = 5,
    transportModes = { "BUS", },
},

Transport modes

carrier picks the means of transport, transportModes the networks the vehicle can run on and engineTransportModes the networks on which its own engines can move it. An electric locomotive runs on all tracks but drives only under catenary, so it lists TRAIN and ELECTRIC_TRAIN as transport modes and only ELECTRIC_TRAIN as engine mode. A wagon has an empty engineTransportModes. The values in the base game files:

carrier transportModes engineTransportModes
"ROAD" BUS or TRUCK the same
"TRAM" TRAM, ELECTRIC_TRAM; light rail adds TRAM_TRACK, ELECTRIC_TRAM_TRACK ELECTRIC_TRAM (plus ELECTRIC_TRAM_TRACK), or TRAM, ELECTRIC_TRAM for horse and steam trams
"RAIL" TRAIN, ELECTRIC_TRAIN ELECTRIC_TRAIN (electric), TRAIN, ELECTRIC_TRAIN (steam, diesel), empty (wagons)
"WATER" SMALL_SHIP or SHIP the same
"AIR" SMALL_AIRCRAFT, AIRCRAFT or HELICOPTER the same

Light rail vehicles such as base/content/vehicle/tram/caf_urbos3/caf_urbos3/caf_urbos3.mdl add the *_TRAM_TRACK modes (9 base models); the vehicle store counts such parts as light rail compatible (base/content/gui/gui/line_vehicle_mgmt/vehicle_store_util.tl). The enums are Carrier and TransportMode.

If a model leaves transportModes empty, the loader addTransportVehicleTransportModes fills both lists from the carrier: road vehicles get BUS or TRUCK from the cargo of their first load config, rail and tram vehicles get the electric-only engine mode if all engines are ELECTRIC, ships and aircraft get the small or big mode from waterVehicle.type or airVehicle.type (helicopters from isHelicopter). The base game models set the lists explicitly.

Other transport vehicle fields

Field Meaning
loadSpeed Loading and unloading speed. For passenger cars the wiki counts one unit per door lane that a person can use at the same time. -1 lets the game estimate it.
comfortFactor How slowly passenger happiness drops during the trip, 0 to 1, 0.5 is average.
priceFactor, maintenanceFactor The wiki says both are currently unused.
arrivalDelay, departureDelay Milliseconds between arriving and the start of loading, and between the end of loading and departure. The wiki asks for the length of the longest door animation.
reversible The vehicle can be part of a push-pull train, see Reversible trains.
filterTags A depot only offers vehicles that have all of its tags. Missing means { "default" }, the tag of the base depots. An empty list hides the vehicle from every depot; it can still be part of a multiple unit.
multipleUnitOnly The vehicle is only sold as part of a multiple unit (see Multiple units).
groupFileName Parent entry for grouping variants in the buy menu, see Buy menu groups.
entrances Paths that boarding passengers walk along, each a list of points relative to the model. 119 base models have them; the wiki does not describe them.
noCblendMask true when the model has no colour blend mask, so the player cannot recolour it.

The base game files differ from the wiki on some of these:

  • The wiki says -1 for comfortFactor makes the game compute a value from the vehicle's properties. In base/content/base/base/base_mod.lua the first loadModel modifier replaces -1 with a fixed value per carrier (0.5 by default, 0.2 for AIR, 0.7 for WATER) and sets priceFactor at the same time (0.5, 0.9 for AIR, 0.1 for WATER, 0.3 for ROAD and TRAM). No base vehicle uses -1; 115 of them use comfortFactor = 0.
  • The wiki gives 0.5 as the default of maintenanceFactor. newLoadSpeedsAndMaintenanceFactor in model_metadata_util.lua sets it to 1 when it is missing.
  • Only one base transport vehicle sets arrivalDelay and departureDelay (both 0, the horse tram base/content/vehicle/tram/double_horse/double_horse/double_horse.mdl). Cars set arrivalDelay = 2000 inside their car block instead.
  • addFilterTags gives a vehicle without filterTags the tag default, except when multipleUnitOnly is set: then the list stays empty.

Compartments

The wiki calls the capacity list compartmentsList. 313 base and DLC models use the name compartments, 8 DLC models use compartmentsList; the loader toCompartmentList renames compartmentsList to compartments, so both work. It also converts the older capacities and loadConfigs forms.

The structure has three levels:

  • A list of compartments. Most vehicles have one. A vehicle that carries two loads at once (the wiki's example is a double-deck tram with passengers upstairs and cargo below) has one compartment per load.
  • Each compartment has loadConfigs, the alternative ways to fill it. A ship that carries either coal alone or coal and iron ore half and half needs two load configs. When an empty vehicle loads, the game picks the first config that moves the most cargo under the line's cargo filter.
  • Each load config has a cargoEntry (capacity, cargoTypeSet, loadIndicator, seats) and toHide, a list of node names hidden while the config is in use.

cargoTypeSet lists included and excluded cargo classes and cargo types (see the wiki's cargo page). loadIndicator names an entry in the model's loadIndicator block (Load indicators). seats lists the seat indices that belong to this entry, which matters for early ships that carry passengers and cargo in the same hull.

Emissions

emissions = { 
    noise = { score = 15, },
    pollution = { score = 15, },
},

score is 0 to 100 and rates the vehicle within its carrier; the game maps it to real values per carrier and fills in idle (standing), speed (at top speed) and power (at full thrust) with interpolation in between. -1 asks the game to estimate the score from the vehicle's other stats; a vehicle without emissions gets score = -1 for both (addMissingVehicleStats in model_metadata_util.lua). The wiki asks for higher noise and pollution on vehicles with better power and speed, so that every vehicle has a drawback.

Seats

seatProvider = { 
    crewModels = { },
    drivingLicense = "BUS",
    seats = {
        { 
            animation = "driving_upright",
            crew = true,
            group = "comp",
            transf = { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 4.63, 0.79, 0.435, 1, },
        },
        { animation = "sitting", group = "comp", transf = { ... }, },
        -- ...
    },
},

drivingLicense picks the default crew models: BUS, TRUCK, TRAM, RAIL, WATER, AIR and AIR_OUTDOOR (pilot with helmet) in the wiki. The base helicopters use a further value, HELICOPTER (12 base and DLC models, e.g. base/content/vehicle/helicopter/bell_47/bell_47/bell_47.mdl). crewModels replaces the defaults with your own character models.

Each seat has an animation (driving, driving_upright, idle, sitting or walk), crew (crew are visible even with no passengers on board; default false), group (the node the seat moves and hides with) and transf. forward limits a crew seat to one direction of travel in reversible trains. A seat on a node that is hidden is hidden too, which is how a second locomotive gets no driver.

Sound

soundConfig = { 
    soundSet = { name = "/vehicle/bus/shared/sound/bus_electric.snd", },
},

soundSet.name points to a sound set (.snd, see the wiki's sound set page). effects overrides single events of that set. The wiki sample writes it as "horn" = "audio/horn.wav", which is not valid Lua; the type (SoundConfig.effects) and the zeppelins (base/content/vehicle/zeppelin/zeppelin_nt/zeppelin_nt/zeppelin_nt.mdl) use a list of files per event:

effects = {
    select = { "sound/selected_zeppelin.wav" },
},

Cars

A road model becomes private traffic with a car block. The wiki shows an empty car = { }. All 48 base and DLC cars set two values in it, from base/content/vehicle/car/beetle/beetle/beetle.mdl:

car = { 
    arrivalDelay = 2000,
    spawnWeight = 1,
},
colorConfig = { 
    configs = {
        { { 0.601961, 0.572635, 0.496913, }, },
        { { 0.553856, 0.633333, 0.623564, }, },
        -- ...
    },
},

spawnWeight is 1 for most cars and lower (down to 0.0001) for rare ones; the wiki does not mention it. A car has landVehicle, roadVehicle, seatProvider and emissions like a bus, but no transportVehicle. colorConfig.configs lists colours (RGB, 0 to 1) that the game picks at random; the car's material needs a colour blend map for this.

The wiki's top speeds for base cars by era, as a guide for balancing: 20 km/h until 1925, 50 km/h until 1950, 80 km/h until 1980, 100 km/h until 2000 and 120 km/h after that. topSpeed is in m/s, so divide by 3.6.

Vehicle types

In TF3 most type-specific metadata names parts of the model by their node name. Give the nodes clear names; the Model Editor shows them in the node tree and copies a name on double click.

Land vehicles

Road, tram and rail vehicles share a landVehicle block. From the eCitaro:

landVehicle = { 
    curveSpeedScale = 1,
    engines = {
        { power = 150, tractiveEffort = 30, type = "ELECTRIC", },
    },
    topSpeed = 19.444,
    weightEmpty = 14000,
    weightMaxPayload = 15429,
},
Field Meaning
engines zero or more engines, each with type (HORSE, STEAM, DIESEL, ELECTRIC), power in kW and tractiveEffort in kN
topSpeed m/s
weightEmpty, weightMaxPayload kg; the payload is the extra weight when fully loaded
friction, brakeDeceleration acceleration and braking behaviour
curveSpeedScale set to 1 in 48 base models; the wiki does not describe it

The wiki puts speed and weight among the properties of roadVehicle and railVehicle. The base models keep them in landVehicle. turnRoadAndRailToLandVehicle builds a landVehicle from an older roadVehicle or railVehicle when the model has none, with a default brake deceleration of 5 (road) or 2.5 (rail) and friction of 0.1 or 0.02.

Road vehicles

roadVehicle.config names the moving parts. From the eCitaro (one fake bogie list per LOD):

roadVehicle = { 
    config = { 
        axles = { "w2", },
        fakeBogies = {
            { { group = "RootNode", offset = 0, position = 0, }, },        -- LOD 0
            { { group = "RootNode", offset = 0, position = 0, }, },        -- LOD 1
            { { group = "RootNode", offset = 0, position = 0, },
              { group = "RootNode", offset = 0, position = -2.63, }, },    -- LOD 2
        },
        steeringParts = { },
        wheels = { "w1_lft", "w1_rgt", },
    },
},

axles are nodes that only roll (turn around the y axis), usually rear axles. wheels roll and steer (also turn around the z axis), usually front wheels. steeringParts only steer. fakeBogies are explained on the advanced page; a road vehicle usually has one between the steering axle and the first rear axle. Put the mesh origin of an axle at its centre on the x and z axes, or it wobbles in the game.

Rail vehicles

railVehicle.config has axles and fakeBogies. Simple rail vehicles only need fake bogies in LODs without separate axles; articulated trams and trains with Jacobs bogies need them in more LODs. The Be 4/6 tram, base/content/vehicle/tram/be4_6mirage/be4_6mirage/be4_6mirage.mdl (start of LOD 0):

railVehicle = { 
    config = { 
        axles = { "front_w1", "front_w2", "middle_w1", "middle_w2", "back_w1", "back_w2", },
        fakeBogies = {
            {
                { group = "front_grp", offset = 0, position = 2.5, },
                { group = "back_grp", offset = 0, position = -1.81, },
                { group = "middle_grp", offset = 0, position = 2.5, },
                { group = "middle_grp", offset = 0, position = -1.5, },
                -- ...
            },
            -- further LODs
        },
    },
},

Trams and trains differ by carrier (TRAM or RAIL) and their transformator (default_tram.trf or default_train.trf).

Multiple units

A multiple unit is a fixed consist sold as one vehicle. It is a .mu.lua file next to its models; the base game has 13. From base/content/vehicle/train/emd_f/emd_f/emd_f.mu.lua:

function data()
    return {
        vehicles = {
            { name = "emd_fa.mdl", forward = true },
            { name = "emd_fb.mdl", forward = true },
        },
        name = _("VEHICLE_MULTIPLEUNIT_EMD_F_NAME"),
        desc = _("VEHICLE_MULTIPLEUNIT_EMD_F_DESCRIPTION"),
        filterTags = { "default" },
    }
end

vehicles lists the models relative to the .mu.lua file; forward = false turns the model by 180 degrees, as the ICE 1 does with its rear power car in base/content/vehicle/train/ice1/ice1/ice1.mu.lua. name and desc appear in the vehicle store (wrapped in _() for translation); the technical data is computed from the parts. filterTags and an optional groupFileName work as on a single vehicle. A multiple unit is available only while all its parts are within their availability years.

The parts of the base multiple units set multipleUnitOnly = true and filterTags = { } in their transportVehicle (31 models, e.g. ice1_front.mdl), so they are not sold on their own.

Water vehicles

Ships have a waterVehicle block. From base/content/vehicle/ship/kakadua/kakadua/kakadua.mdl (waterline shortened):

waterVehicle = { 
    area = 5,
    availPower = 600000,
    maxRpm = 133,
    topSpeed = 10.5556,
    waterLine = {
        { 11.8805, 0, },
        { 11.8805, 0.125, },
        -- ... 31 points along one side of the hull
        { -10.96, 0, },
    },
    weightEmpty = 125000,
    weightMaxPayload = 18000,
},
Field Meaning
area largest underwater cross section of the hull in m²; drag grows linearly with it
availPower engine power in W (not kW)
weightEmpty, weightMaxPayload kg
maxRpm top revolutions of the paddle wheel or propeller, for the animation
topSpeed m/s
type "SMALL" ships can use small piers, "BIG" ships need the large harbour
waterLine x/y points of the hull outline at water level, for the foam around the ship

The base ships do not set type; they state the size through transportModes = { "SMALL_SHIP" } or { "SHIP" }, from which the loader would otherwise derive it. Only the DLC ship ts_queen_mary.mdl sets type.

Air vehicles

Aircraft and helicopters have an airVehicle block. From base/content/vehicle/plane/douglas_dc3/douglas_dc3/douglas_dc3.mdl (shortened):

airVehicle = { 
    axles = {
        { position = { 3.38, 0.59, }, radius = 0.59, },
        { position = { 3.38, 0.59, }, radius = 0.59, },
    },
    config = { 
        axleRadii = { 0.59, 0.59, },
        axles = { "w1_lft", "w1_rgt", },
        fakeBogies = { ... },
        steeringParts = { "g2", },
        wheelRadii = { 0.29, },
        wheels = { "w3", },
    },
    hasFlaps = true,
    maxThrust = 25000,
    timeToFullThrust = 3,
    topSpeed = 83.333,
    weightEmpty = 7700,
    wheels = {
        { position = { -7.81, 2.56535, }, radius = 0.27, },
    },
    wingArea = 91,
},

The outer axles and wheels lists give the position (x and z from the origin) and radius of every axle and wheel, so the game can place and tilt the aircraft on the ground. config names the nodes as for road vehicles; axleRadii and wheelRadii give one radius in metres per listed node. The flight values are maxThrust and idleThrust in N, timeToFullThrust in seconds, topSpeed in m/s, weightEmpty and weightMaxPayload in kg, wingArea in m² (lift grows linearly with it), hasFlaps, isHelicopter for vertical take-off and landing, and type ("SMALL" for small airfields, "BIG" for airports).

As with ships, the base aircraft give the size through transportModes (SMALL_AIRCRAFT, AIRCRAFT, HELICOPTER) and leave out type. The Concorde also sets maxTakeOffWeight = 54400, a field the wiki does not list. Helicopters such as the Bell 47 set isHelicopter = true, transportModes = { "HELICOPTER" } and drivingLicense = "HELICOPTER".

The three models in base/content/vehicle/zeppelin/ are not transport vehicles. They have no transportVehicle or airVehicle, and their own transformator vehicle/zeppelin/shared/zeppelin.trf moves them.

Animation events by type

With the default transformators, animations named after these events play on their own. Times for rudder, aileron_* and elevator run from 0 to 1000 with 500 as the centre position; flaps runs from 0 (retracted) to 1000 (extended).

Event Road Tram Rail Water Air
forever (loops, e.g. fans, radar) yes yes yes yes yes
drive (follows the speed) yes yes yes yes yes
wheels (length mapped to one wheel turn) yes
open_all_doors, close_all_doors yes yes yes yes yes
open_doors_left/_right, close_doors_left/_right yes yes yes yes yes
brake_lights_on/_off yes yes yes
blink_lights_left_on/_off, blink_lights_right_on/_off yes yes
paddles, rudder yes rudder
aileron_left, aileron_right, elevator, flaps yes
beacon_lights, strobe_lights, landing_light_on/_off yes
props_on/_off, props_blurred_on/_off yes
open_doors_cargo, close_doors_cargo, open_wheels, close_wheels yes

The door events fire after the vehicle stops and before it leaves; the left and right variants only for stops on that side. For ship propellers, turn the mesh by 90 degrees so that its y axis points along the rotation axis. Reversible trains have further show/hide events, see Reversible trains. The eCitaro keeps its door animations as files per event, e.g. ani/open_doors_right/d1.ani.

Repaints

A repaint adds a new livery to an existing vehicle. The wiki names three levels: new textures, new textures with extra meshes, and new textures with changed meshes. Only the last needs copies of the original files, and so the original author's permission. Even for the first two, the community asks the author first; many authors then share their texture work files.

Ship only new or changed files, give the repaint its own modId and declare the original mod as a dependency in mod.json (Dependencies). A repaint of a base game vehicle needs no dependency. The wiki has an example repaint of the base eCitaro for download.

A texture-only repaint has:

  • the usual mod files (mod.json, _metadata/modinfo.json, see Mod structure); naming the original author as co-author is good manners
  • a .mtl for every material that gets new textures
  • a .mdl for every new variant
  • the three icons of every new variant
  • the textures

Materials

Copy the original .mtl and change the texture references. A vehicle material usually has four maps that a repaint may change: map_albedo_opacity (colour and transparency), map_normal (normal map, e.g. for raised number plates), map_metal_gloss_ao (metal, gloss, ambient occlusion) and map_cblend_dirt_rust (where the player can recolour, and where dirt and rust show). From base/content/vehicle/bus/ecitaro/ecitaro/mat/ecitaro.mtl (shortened):

map_albedo_opacity = { 
    fragmentSamplers = { 
        albedoOpacityTex = { 
            fileName = "tex/ecitaro_albedo_opacity.dds",
            type = "TWOD",
            wrapS = "REPEAT",
            wrapT = "REPEAT",
        },
    },
},
-- map_normal, map_metal_gloss_ao and map_cblend_dirt_rust look the same
map_dirt = { 
    fragmentSamplers = { 
        dirtTex = { fileName = "/vehicle/shared/mat/tex/dirt_albedo.dds", ... },
    },
},

The texture paths are relative to the material. In the copy, every texture you keep must point back to the original: write "::/vehicle/bus/ecitaro/mat/tex/ecitaro_normal.dds" for a base game file, or "<original_modid>::/..." for another mod. The relative form "::tex/..." only works if your file sits at the same path as the original. The rules are in File names and paths.

Model

Copy the original .mdl and change three things: the material references in every LOD, availability, and description (with new translation keys):

lods = {
    {
        node = {
            children = {
                {
                    materials = { "mat/ecitaro_red.mtl", },
                    mesh = "::/vehicle/bus/ecitaro/msh/body_lod0.msh",
                    -- ...
                },
                -- ...
metadata = {
    availability = { yearFrom = 2019, yearTo = 0, },
    description = {
        description = _("VEHICLE_BUS_ECITARO_RED_DESCRIPTION"),
        name = _("VEHICLE_BUS_ECITARO_RED_NAME"),
    },
    -- everything else as in the original
},

Meshes and animations stay in the original mod, so their paths need the base game or mod prefix as well. To group the repaint under the original in the vehicle store, see Buy menu groups.

Icons

The wiki lists three icons, and the Model Editor's SCREENSHOT button (top right) creates them in the right folder. The base game file names are slightly different from the wiki's: the eCitaro has icons/ecitaro_store.tga, icons/ecitaro_icon_small@2x.tga and icons/ecitaro_icon20@2x.tga, plus _cblend masks for the small and the 20 px icon. The wiki writes the middle one as <vehiclename>_small_icon. When description sets no icons, addIconMetadata uses these defaults, with <vehicle> as the model file name:

description field Default Used for
icon3d icons/<vehicle>_store.tga details in the vehicle store
iconSmall, iconSmallCblend icons/<vehicle>_icon_small.tga, ..._icon_small_cblend.tga compact list in the vehicle store
icon20, icon20cblend icons/<vehicle>_icon20.tga, ..._icon20_cblend.tga other windows and lists

Icons are stored at double size under an @2x.tga name (see Textures), while the defaults name the file without @2x. The icon paths are relative to the model, so a repaint keeps its icons in an icons/ folder next to its .mdl.

Textures

DDS compression loses detail, so don't paint over the shipped .dds files; ask the author for work files where possible. The general texture rules are in Textures.

Official wiki: Vehicle basics, Vehicle types, Repaint mods, Vehicle advanced topics, Cargo, Model definition (.mdl).