OpenTTD Cargo Income Calculator
See exactly what each delivery pays in OpenTTD. Pick a cargo, set the distance and days in transit, and the calculator returns £ per trip, £ per tile, £ per day, and the most profitable cargo for that route.
Calculate the income for one delivery.
Determines which cargos appear in the cargo dropdown. Match this to the climate of the OpenTTD save you're playing.
The cargo your train, ship, plane or truck is delivering. Each cargo has its own payment rate and freshness curve.
passengers
tiles
days
How this number is calculated
- Time factor
- 255 − 24 − 2·0 → 231
- Half distance
- 100 ÷ 2 → 50
- Stage 1 (>> 7)
- 50 × 231 × 100 ÷ 128 → 9,023
- Times payment rate
- × 3,185
- Divide by 8192 (>> 13)
- ÷ 8192
- Income
- £3,508
| Cargo | Pay rate | Best at distance | Goes stale at |
|---|---|---|---|
| Valuables | 7,509 | ≤ 75 tiles | 33 periods |
| Goods | 6,144 | ≤ 375 tiles | 33 periods |
| Coal | 5,916 | ≤ 525 tiles | — |
| Steel | 5,688 | ≤ 525 tiles | — |
| Iron Ore | 5,120 | ≤ 675 tiles | — |
| Wood | 5,005 | ≤ 1,125 tiles | — |
| Grain | 4,778 | ≤ 300 tiles | 44 periods |
| 4,550 | ≤ 1,500 tiles | 110 periods | |
| Oil | 4,437 | ≤ 1,875 tiles | — |
| Livestock | 4,322 | ≤ 300 tiles | 22 periods |
| Passengers | 3,185 | any distance | 24 periods |
Vanilla OpenTTD 14.x and JGRPP. NewGRF cargo sets override the default rates and are not yet supported. Inflation is shown as base-year (1950) values; your save scales these proportionally.
OpenTTD cargo income calculator. £ per trip from cargo, distance, and days in transit.
What is the OpenTTD cargo income calculator?
How to calculate OpenTTD cargo income (and how the calculator does it)
Cargo income — the integer formula from economy.cpp
- = Income in in-game £ for one delivery (the integer the calculator returns)
- = Manhattan tile distance between source and destination station — |x_src − x_dst| + |y_src − y_dst|
- = Time factor (0–255), 255 = perfectly fresh, clamped at MIN_TIME_FACTOR = 31
- = Amount of cargo delivered (passengers, tonnes, bags, litres, items)
- = Cargo base payment rate from economy.cpp's _default_cargo table — 3185 passengers, 5916 coal, 7964 sub-tropical wood (highest), 7509 valuables (highest non-wood)
- = Transit periods — calendar days divided by 2.5 and floored. One transit period = 2.5 in-game days
- = Cargo's days1 threshold — early-decay boundary in transit periods. 0 for passengers and food, 1 for valuables, 7 for coal, 25 for oil, 30 for plastic and fizzy drinks
- = Cargo's days2 threshold — late-decay boundary in transit periods. 24 passengers, 32 valuables, 40 grain, 255 coal (effectively unlimited)
Worked examples with the full math
Wiki reference — 27 passengers, 100 tiles, 60 days, temperate
Coal long-haul — 200 tonnes, 300 tiles, 200 days, sub-arctic
Valuables ultra-short — 50 valuables, 50 tiles, 5 days, temperate
Sub-tropical wood — 100 tonnes, 200 tiles, 80 days
Compare two trips — coal vs valuables on the same 100-tile route
Cargo income planning tips for OpenTTD veterans and Steam newcomers
- Coal pays £5,916 base — not the highest rate in the game — but its days1/days2 pair (7, 255) means it stays at near-full price even on 2,000-tile cross-map rail networks. Coal is the cargo that lets you build sloppy track and still profit. Valuables pays £7,509 base but with days1 = 1 and days2 = 32, anything past 80 calendar days (32 transit periods) collapses the time factor toward the 31 floor. Use valuables on routes under 50 tiles, coal on everything else.
- Distance is Manhattan tiles, not track length. The income formula uses |x_src − x_dst| + |y_src − y_dst| between the two stations — no matter how many curves your track takes. A serpentine route through mountains earns the same £ as a straight line, as long as the station coordinates are the same. This is the #1 confusion on tt-forums: players assume a 200-tile track on a 100-tile-Manhattan route earns 200 tiles of income. It does not. Place stations on the far sides of industries to maximise Manhattan distance.
- One "day" on the wiki's cargo income page is 2.5 calendar days in your save. OpenTTD stores transit time in 2.5-day units internally so the byte-sized 0–255 counter covers the long-ship range. The calculator above accepts calendar days (the unit the in-game vehicle window shows) and converts internally — but if you pull values directly from the wiki's worded formula, multiply or divide by 2.5 yourself.
- Time factor floors at 31, never zero. MIN_TIME_FACTOR = 31 in src/economy.cpp means even a cargo that has been in transit for game-years still pays roughly 31/255 = 12 percent of its fresh value. Players sometimes report that "my old cargo earned nothing" — that is usually because the £ amount is small (1 passenger on a 2,000-tile, 4,000-day ship trip works out to floor(2000 × 31 × 1 × 3185 / 2,097,152) = £94) but it is never literally £0 unless distance or amount is also zero.
- Sub-tropical wood pays £7,964 base — the highest base rate of any vanilla cargo, beating valuables (£7,509) and matched only by toyland fizzy drinks (£6,250) on per-tile yield over short routes. Same cargo name as temperate wood (£5,005), 59 percent higher price. If your save is sub-tropical, prioritise wood over goods on every viable lumber-mill-to-sawmill route.
- JGR's Patch Pack uses the same formula. The cargo income code in JGRPP is byte-identical to vanilla — the only economy difference is the cargo aging rate setting (default 100% in both, configurable in JGRPP). Numbers from this calculator transfer 1-for-1 to a JGRPP save unless you have explicitly modified economy.cargo_aging_rate. NewGRF cargo packs (FIRS, ECS, YETI) override the payment table and are out of scope; for a NewGRF save, treat this calculator as the vanilla baseline and scale by the NewGRF's published rate ratio.
- Inflation scales the result proportionally. The £ figure shown is the base-year (1950) value, identical to the in-game cargo payment graph's calibration. OpenTTD's default ~1.5%/year inflation multiplier scales both costs and revenues, so your relative income vs running costs is unchanged — the calculator's £ is not your real bank-statement £ in 2050, but the ratio between two trips is exactly preserved.
- Read the cheat-sheet table below the calculator before laying track. It sorts all 33 vanilla cargo rows (31 unique cargo names plus separate Wood and Oil rows for sub-tropical) by paymentRate and labels each with "best at distance ≤ N tiles" using the heuristic days1 × 75 (since 30 km/h × 2.5 days/period ≈ 75 tiles per period at typical 1950 train speeds). Cargos with days2 = 255 get the "effectively unlimited" tag — they never go critically stale on land routes.
OpenTTD cargo income calculator — frequently asked questions
What is the formula for cargo income in OpenTTD?
Income = floor(distance × timeFactor × amount × paymentRate / 2,097,152), where timeFactor = max(255 − max(tp − days1, 0) − max(max(tp − days1, 0) − days2, 0), 31) and tp = floor(daysInTransit / 2.5). The constants 2,097,152 = 2^21, 255 = MAX_TIME_FACTOR, and 31 = MIN_TIME_FACTOR come from src/economy.cpp's GetTransportedGoodsIncome() function. The formula applies in vanilla 14.x, JGRPP, and classic Transport Tycoon Deluxe — it has not changed since 1995.
How is distance measured for cargo income?
Distance is Manhattan distance between source and destination station, in tiles: |x_src − x_dst| + |y_src − y_dst|. It is NOT the track length. A 200-tile straight track and a 350-tile track that snakes around obstacles earn the same income if both stations sit on the same two coordinates. Place stations on the far ends of industries to maximise Manhattan distance — a documented community trick that does not require longer track.
Why is one 'day' on the wiki actually 2.5 days in the game?
OpenTTD counts cargo age in a one-byte (0–255) counter that ticks once every 2.5 calendar days. The wiki's formula uses these 'transit periods' directly; the calculator accepts the calendar days the in-game vehicle window shows and divides by 2.5 for you.
What is the best cargo for money in OpenTTD?
Best by base payment rate is sub-tropical wood (£7,964), then valuables (£7,509), fizzy drinks (£6,250), goods/sweets (£6,144), coal (£5,916). Best on long routes is coal — its days2 = 255 keeps the time factor near max even at 1,500-tile distances. Best per-month (factoring industry production volume) is usually coal, because coal mines produce 100+ tonnes/month while banks produce 1-8 valuables/month. Use the calculator's 'Compare two trips' mode to see exactly when valuables out-earns coal on your save.
Does this calculator work for JGR's Patch Pack saves?
Yes — the cargo income code is byte-identical between vanilla OpenTTD 14.x and JGR's Patch Pack. The only economy difference is the cargo aging rate setting (default 100 percent in both, exposed as economy.cargo_aging_rate in JGRPP). The 33-row payment table (31 unique cargo names plus separate sub-tropical Wood and Oil) and the integer formula are unchanged. If you have not modified the aging rate, numbers from this calculator transfer 1-for-1 to a JGRPP save.
Does it work with NewGRF cargo packs like FIRS, ECS, or YETI?
No. NewGRF cargo packs override the vanilla _default_cargo table with their own paymentRate, days1, and days2 values. The calculator ships the vanilla cargo definitions only (31 unique cargo names — 33 rows because Wood and Oil have separate sub-tropical entries) — using it on a FIRS save will give the right formula but the wrong constants. For a NewGRF save, treat the calculator's output as the vanilla baseline and scale by the NewGRF's published rate ratio (most NewGRFs document this in their README).
Why does my cargo show '£0' on a long-haul ship route?
The MIN_TIME_FACTOR clamp at 31 means a stale cargo always pays at least 31/255 ≈ 12 percent of its fresh rate — so the income should not literally be zero unless distance or amount is zero. If you are seeing £0, check (a) distance is non-zero (same-station deliveries pay nothing), (b) amount is non-zero, and (c) paymentRate is non-zero (some NewGRFs zero out cargos they do not want shipped). On a 2,000-tile, 4,000-day passenger ship the income will be small (£94 for one passenger — floor(2000 × 31 × 1 × 3185 / 2,097,152)) but never zero.
Why do CityMania and the in-game graph give slightly different numbers?
CityMania's tool (citymania.org/tools/profit) discloses on its own page that 'numbers may not be exactly accurate (they should be pretty close though)' — it uses an approximation and rounds intermediate values. The in-game cargo payment graph uses the exact same integer formula this calculator implements, but quantises the y-axis at low resolution so the eyeballed value can be off by ±5 percent. This calculator's numbers match the engine to the unit, because we replicate the bit-shift exactly. If your in-game £ differs by more than a few units, double-check that the days-in-transit you entered matches what the vehicle's actual cargo says (the in-game number can climb as the cargo waits at the station).
Does inflation change the result?
The calculator returns the base-year (1950) £ value, exactly the same calibration as the in-game cargo payment graph. OpenTTD's default inflation multiplier (~1.5 percent per year) scales both costs and revenues, so your real bank-statement income in 2050 is roughly 4.4 times the calculator's £ — but your relative income (this trip vs that trip, this cargo vs that cargo, this distance vs that distance) is exactly preserved. The calculator deliberately does not show year-adjusted £ because the wiki, the in-game graph, and economy.cpp all calibrate to the 1950 base.
How accurate is this calculator vs the actual game?
Bit-exact for vanilla 14.x and JGRPP — the 40-test QA suite cross-references every output against the C++ math in src/economy.cpp. The calculator does not model NewGRF cargo callbacks (some NewGRFs add a multiplier via a cargo callback hook), feeder-service negative-income chains, or cargo aging beyond the 4,000-day input cap. Within those limits, the £ result is identical to what the engine writes to your account when the vehicle unloads.
What is the difference between days1 and days2?
days1 is the early-decay threshold: how many transit periods the cargo can sit in a vehicle before its time factor starts dropping. days2 is the late-decay threshold added on top — past days1 + days2 the time factor drops at double speed (the formula subtracts both periodsOverDays1 and periodsOverDays2). A cargo with days2 = 255 (coal, oil, iron ore, steel, wood, copper ore, sugar, toys, plastic) effectively never reaches the steep-decay zone on any reasonable route. Passengers (0, 24) decay immediately; valuables (1, 32) decay almost as fast and have the steepest combined drop in the game.
Is this calculator free to use?
The breakdown panel and cargo cheat-sheet are exposed by default rather than gated — open to anyone, no account, no rate limits, no ads on the calc itself. Every intermediate value (transit periods, time factor, raw numerator) is visible from the first render.
What if I want to compare two routes side by side?
Use the 'Compare two trips' tab at the top of the calculator. Climate is shared (a route comparison only makes sense in one climate), but cargo, amount, distance, and days-in-transit are independent for Trip A and Trip B. The calculator prints both £ totals plus the delta (Trip B − Trip A) with a green-or-red banner. Defaults are coal vs passengers on the same 100-tile, 60-day route — the canonical 'which cargo should I ship?' comparison.
Does speed matter for income, or just days in transit?
Only days in transit matter directly. The cargo income formula does not read vehicle speed — it reads how many calendar days the cargo has been inside the vehicle. Speed matters only because faster vehicles complete the same Manhattan distance in fewer days, which reduces transit periods, which raises the time factor. A 100 km/h train and a 200 km/h train on the same route earn different income only because the second one delivers in half the days. The wiki notes that speed matters most below ~50 km/h and starts to level off above; doubling 200 km/h to 400 km/h has a much smaller effect than doubling 25 to 50.
OpenTTD cargo and economy glossary
Manhattan distance
The straight-line tile-grid distance between two stations, computed as |x_src − x_dst| + |y_src − y_dst|. Used by OpenTTD's cargo income formula; not the actual track length the vehicle drives.
Transit period
The internal time unit OpenTTD uses to count cargo age. One transit period = 2.5 calendar days. Stored in a one-byte counter so the maximum value is 255 transit periods (≈ 637 calendar days) before the time factor floors at MIN_TIME_FACTOR = 31.
Time factor
The freshness multiplier in the income formula, ranging 0 to 255 (clamped at 31). 255 = perfectly fresh, 31 = stale floor. Each transit period past days1 reduces it by 1; each period past days1 + days2 reduces it by an additional 1 (so 2 per period in the slow zone).
days1
A cargo's early-decay threshold in transit periods. Below days1 the cargo earns at the maximum time factor of 255. Examples: 0 for passengers and food, 1 for valuables, 7 for coal, 25 for oil and toys.
days2
A cargo's late-decay threshold added on top of days1. Past days1 + days2 the time factor drops twice as fast. Coal, oil, iron ore, steel, wood, copper ore, sugar, toys, and plastic all set days2 = 255 (effectively unlimited).
paymentRate
The per-cargo base payment rate from src/economy.cpp's _default_cargo table. Highest is sub-tropical wood (7964), then valuables (7509), fizzy drinks (6250), goods/sweets (6144), coal (5916). Lowest is fruit (4209). Stored as a Q11.4 fixed-point integer in the engine.
GetTransportedGoodsIncome()
The C++ function in src/economy.cpp that computes the £ payment when a vehicle unloads cargo. Implements the exact integer formula this calculator reproduces, including the BigMulS shift-by-21 final divide.
JGR's Patch Pack (JGRPP)
A long-running community fork of OpenTTD by Jonathan Rennison with hundreds of additional features (realistic braking, programmable signals, town zones). The cargo income code is byte-identical to vanilla — numbers from this calculator transfer 1-for-1.
NewGRF
OpenTTD's user-content format for adding vehicles, industries, town buildings, and cargo packs. NewGRF cargo packs (FIRS, ECS, YETI) override the vanilla paymentRate table (33 rows: 31 unique cargos plus separate sub-tropical Wood and Oil); this calculator uses vanilla rates only.
Climate
One of OpenTTD's four scenario settings: Temperate (default), Sub-arctic, Sub-tropical, Toyland. Determines which cargos are available — Coal is Temperate/Sub-arctic only, Diamonds Sub-tropical only, Toys/Sweets/Cola Toyland only.
Cargo aging rate
An economy setting (economy.cargo_aging_rate) that scales how fast cargo accumulates transit periods. Default 100 percent in both vanilla and JGRPP. JGRPP exposes this as a configurable percentage; vanilla hardcodes it at 100.
Inflation
OpenTTD's per-year multiplier applied to costs and revenues (~1.5 percent/year by default). The calculator reports base-year (1950) £, identical to the in-game cargo payment graph; relative comparisons are unchanged by inflation.
Content verified by the Smart Calculators Team