## FIRS cargo payment calculation

**Moderator:** OpenTTD Developers

### FIRS cargo payment calculation

Hi, can someone give me some insight on how the cargo payment in FIRS new grf is calculated?

I got this process worked out in vanilla open ttd, using this formula and cargo parameters (https://wiki.openttd.org/Cargo_income)

for example:

Passengers: base=3185, c1 days=0, c2 days=24

you transfer 200 passengers across 100 tiles in 25 days (with loading/unloading) => 25>c1+c2, so time factor would be 255-2*(25-0)+24 = 229

therefore payment: 3185 (base) * 200 (passengers) * 100 (tiles) * 229 (time factor) / 2^21 = 6,955.77 GBP

from my observations in-game, it is correct

As for FIRS, I found out there's some different approach used, the payment parameters don't look like in base version at all (eg for price_factor='109' for ACID in https://hg.openttdcoop.org/firs/files/9 ... src/cargos)

I know the document says price_factor='109' is for 10 units of cargo across 20 tiles

Still, no matter how I try to tackle the problem I can't get those numbers right

Can someone enlighten me?

Thanks!

I got this process worked out in vanilla open ttd, using this formula and cargo parameters (https://wiki.openttd.org/Cargo_income)

for example:

Passengers: base=3185, c1 days=0, c2 days=24

you transfer 200 passengers across 100 tiles in 25 days (with loading/unloading) => 25>c1+c2, so time factor would be 255-2*(25-0)+24 = 229

therefore payment: 3185 (base) * 200 (passengers) * 100 (tiles) * 229 (time factor) / 2^21 = 6,955.77 GBP

from my observations in-game, it is correct

As for FIRS, I found out there's some different approach used, the payment parameters don't look like in base version at all (eg for price_factor='109' for ACID in https://hg.openttdcoop.org/firs/files/9 ... src/cargos)

I know the document says price_factor='109' is for 10 units of cargo across 20 tiles

Still, no matter how I try to tackle the problem I can't get those numbers right

Can someone enlighten me?

Thanks!

### Re: FIRS cargo payment calculation

income calculation for NewGRF cargos can be found here: https://newgrf-specs.tt-wiki.net/wiki/A ... 11.2C12.29

You might not exactly be interested in Ferion, but if you are, have fun

### Re: FIRS cargo payment calculation

Hi, thanks a lot for the link that's immensely helpful

Still, the numbers don't match, using this formula:

income=((((distance/2) * timefactor * amount_moved) >> 7) * cargopricefactor) >> 13

continuing previous example, in FIRS we have:

Passengers: pricefactor=105, c1 days=0, c2 days=22

you transfer 200 passengers across 100 tiles in 25 days (with loading/unloading) => 25>c1+c2, so time factor would be 255-(25-0)-(25-22-0)=227

therefore payment:

step 1) 50 (distance in tiles/2) * 227 (timefactor) * 100 (passengers) = 1,135,000.00

step 2) shift right 1,135,000.00 by 7 bits => 8867 (i'm using excel BITRSHIFT and checked with some online bit calculator)

step 3) 8867 * 105 (cargo price factor) = 931,035.00

step 4) shift right 931,035.00 by 13 bits => 113.00 GBP profit per 1 trip

that's way too low

where's the catch?

Still, the numbers don't match, using this formula:

income=((((distance/2) * timefactor * amount_moved) >> 7) * cargopricefactor) >> 13

continuing previous example, in FIRS we have:

Passengers: pricefactor=105, c1 days=0, c2 days=22

you transfer 200 passengers across 100 tiles in 25 days (with loading/unloading) => 25>c1+c2, so time factor would be 255-(25-0)-(25-22-0)=227

therefore payment:

step 1) 50 (distance in tiles/2) * 227 (timefactor) * 100 (passengers) = 1,135,000.00

step 2) shift right 1,135,000.00 by 7 bits => 8867 (i'm using excel BITRSHIFT and checked with some online bit calculator)

step 3) 8867 * 105 (cargo price factor) = 931,035.00

step 4) shift right 931,035.00 by 13 bits => 113.00 GBP profit per 1 trip

that's way too low

where's the catch?

### Re: FIRS cargo payment calculation

have you considered the conversion from game days (74 ticks) to cargo age units (185 ticks, can be changed by some vehicles)? if you're transporting for 25 game days, the cargo only aged 10 times, not 25 times.

You might not exactly be interested in Ferion, but if you are, have fun

### Re: FIRS cargo payment calculation

no, but that's not it

that only means cargo payments function counts game days in "2.5 day" batches => if your cargo travelled exactly 16 game days, you'd get a payment for 17.5 days (2.5x7 batches) - that's how I understand it at least and it made sense with vanilla game calculations

here, in firs, the error is more of a factor of 100x than 2x

that only means cargo payments function counts game days in "2.5 day" batches => if your cargo travelled exactly 16 game days, you'd get a payment for 17.5 days (2.5x7 batches) - that's how I understand it at least and it made sense with vanilla game calculations

here, in firs, the error is more of a factor of 100x than 2x

### Re: FIRS cargo payment calculation

no, that's not how that works. if the cargo was loaded 16 days ago, then "days_in_transit" in all the relevant formulas will be 6drsh1 wrote:if your cargo travelled exactly 16 game days, you'd get a payment for 17.5 days (2.5x7 batches) - that's how I understand it at least

it could be that firs hides some factor elsewhere in its code... have you tried other industry GRFs?here, in firs, the error is more of a factor of 100x than 2x

You might not exactly be interested in Ferion, but if you are, have fun

### Re: FIRS cargo payment calculation

But it only applies to new grfs then? I'm sure I got numbers for vanilla game right and this wasn't the case there.Eddi wrote:no, that's not how that works. if the cargo was loaded 16 days ago, then "days_in_transit" in all the relevant formulas will be 6

Plus, I investigated the cargo payment graphs ingame and it seems you're right - the graphs are shifted. By default, the graph should be a downward trending line with turning points in "day1" and "day2" value where slope becomes steeper. With FIRS active, it looks like the turning points are in values for "day1", "day2" x2.5 than in documentation (eg for wood day1=about 60 when it should be 24)

As for the calculation, I run through code and found a formula that makes even less sense for me:

Code: Select all

```
Money GetTransportedGoodsIncome(uint num_pieces, uint dist, byte transit_days, CargoID cargo_type)
{
/* non-important */
const CargoSpec *cs = CargoSpec::Get(cargo_type);
if (!cs->IsValid()) {
/* User changed newgrfs and some vehicle still carries some cargo which is no longer available. */
return 0;
}
/* Use callback to calculate cargo profit, if available */
/* starts here */
if (HasBit(cs->callback_mask, CBM_CARGO_PROFIT_CALC)) {
/* bitwise sum of distance, amount moved, transit days */
uint32 var18 = min(dist, 0xFFFF) | (min(num_pieces, 0xFF) << 16) | (transit_days << 24);
/* CBID_CARGO_PROFIT_CALC = 0x39 = 57 */
uint16 callback = GetCargoCallback(CBID_CARGO_PROFIT_CALC, 0, var18, cs);
/* apply GB function to "callback" */
/* GB can be found https://github.com/OpenTTD/OpenTTD/blob/18ca3e8660f90737d672b6780301ff4b998df56f/src/core/bitmath_func.hpp */
/* GB (x, s, n) = (x << s) & ( 1U << n) - 1) where 1U << 1 = 1 = 00000001, 1U << 2 = 2 = 00000010 etc * /
if (callback != CALLBACK_FAILED) {
int result = GB(callback, 0, 14);
/* Simulate a 15 bit signed value */
/* if "callback" is max value for 14bits, lower it by 1, result = 16384-1 = 16383; this is max "result" */
if (HasBit(callback, 14)) result -= 0x4000;
/* "The result should be a signed multiplier that gets multiplied
* by the amount of cargo moved and the price factor, then gets
* divided by 8192." */
return result * num_pieces * cs->current_payment / 8192;
}
}
```

### Re: FIRS cargo payment calculation

That code just implements a call to https://newgrf-specs.tt-wiki.net/wiki/C ... s_.2839.29 Stuff gets encoded in a single variable with some shifting and capping at the upper limit, and the result gets decoded again for the signed 14 bit number, which looks a bit weird, since C/C++ doesn't have native 14 bit numbers.

Otherwise, it just does what the description of the call says.

Otherwise, it just does what the description of the call says.

Being a OpenTTD developer does not mean I know what I am doing.

Also, other OpenTTD developers may have different opinions.

Also, other OpenTTD developers may have different opinions.

- andythenorth
- Tycoon
**Posts:**4974**Joined:**31 Mar 2007 14:23**Location:**Lost in Music

### Re: FIRS cargo payment calculation

I think you've got CB 39 there https://newgrf-specs.tt-wiki.net/wiki/C ... s_.2839.29

AFAIK, FIRS doesn't use CB 39.

I am watching this with interest. I've got no useful information to add, but I'm not convinced that FIRS cargo payments are working as I want them to. They were set a long time ago, and there's been no attention to them since then.

AFAIK, FIRS doesn't use CB 39.

I am watching this with interest. I've got no useful information to add, but I'm not convinced that FIRS cargo payments are working as I want them to. They were set a long time ago, and there's been no attention to them since then.

FIRS Industry Replacement Set (Released) | HEQS Heavy Equipment Set (trucks, industrial trams and more) (Finished)

Squid Ate FISH (ships) (Released) | CHIPS Has Improved Players' Stations (Finished)

Iron Horse (trains, released) | Termite (tracks for Iron Horse, released) | Busy Bee (game script, released)

Road Hog (road vehicles, released)

Squid Ate FISH (ships) (Released) | CHIPS Has Improved Players' Stations (Finished)

Iron Horse (trains, released) | Termite (tracks for Iron Horse, released) | Busy Bee (game script, released)

Road Hog (road vehicles, released)

### Re: FIRS cargo payment calculation

thanks for feedback guys

later I'll try to convert the code to somewhat more user-friendly math formulas and I'll show you why the "callback approach" makes no sense to me

later I'll try to convert the code to somewhat more user-friendly math formulas and I'll show you why the "callback approach" makes no sense to me

### Re: FIRS cargo payment calculation

ok guys I think I got this

actually, the whole thing is astonishingly simple. the correct formula is:

CARGO PRICE from the in-game graph /200 * AMOUNT * DISTANCE

where CARGO PRICE is calculated followingly:

FIRS pricefactor * timefactor scaled with 2,5days correction

^ FIRS pricefactor is price_factor value from https://hg.openttdcoop.org/firs/files/9 ... src/cargos. has to be divided by 200 because it's a payment for transporting 10t across 20 tiles

^ timefactor is calculated in exactly the same way as in base game (or in the code chunk above) ONLY the in-game days used for calculation must be divided by 2.5 (new grfs feature?)

example:

we transport 360,000 L of MILK (price_factor = 145, days1= 0, days2 = 16) across 131 tiles within 54 days (with loading/unloading)

^ effective days are 54/2.5 = 21.6 -> 22 (i'm not sure how the game handles rounding - I use mathematical rounding)

^ .. so the timefactor for 22 days is 255-(22-0)-(22-0-16)= 227

^ CARGO PRICE would be 145 (price_factor) * 227 (timefactor) / 255 = 129,08 GBP => this is the approximate payment rate you can read from in-game graph for transporting MILK within 22 days

^ 129.08 / 200 (10t across 20 tiles) * 360 (amount) * 131 (distance) = 30,437.06 GBP which is very close to real game payment

now, what part of code does this - I have no idea

actually, the whole thing is astonishingly simple. the correct formula is:

CARGO PRICE from the in-game graph /200 * AMOUNT * DISTANCE

where CARGO PRICE is calculated followingly:

FIRS pricefactor * timefactor scaled with 2,5days correction

^ FIRS pricefactor is price_factor value from https://hg.openttdcoop.org/firs/files/9 ... src/cargos. has to be divided by 200 because it's a payment for transporting 10t across 20 tiles

^ timefactor is calculated in exactly the same way as in base game (or in the code chunk above) ONLY the in-game days used for calculation must be divided by 2.5 (new grfs feature?)

example:

we transport 360,000 L of MILK (price_factor = 145, days1= 0, days2 = 16) across 131 tiles within 54 days (with loading/unloading)

^ effective days are 54/2.5 = 21.6 -> 22 (i'm not sure how the game handles rounding - I use mathematical rounding)

^ .. so the timefactor for 22 days is 255-(22-0)-(22-0-16)= 227

^ CARGO PRICE would be 145 (price_factor) * 227 (timefactor) / 255 = 129,08 GBP => this is the approximate payment rate you can read from in-game graph for transporting MILK within 22 days

^ 129.08 / 200 (10t across 20 tiles) * 360 (amount) * 131 (distance) = 30,437.06 GBP which is very close to real game payment

now, what part of code does this - I have no idea

### Re: FIRS cargo payment calculation

for the travel time, this is always rounded down, as it is a counter that is increased by 1 in a regular interval. if the interval hasn't expired, there will be no counting updrsh1 wrote:(i'm not sure how the game handles rounding - I use mathematical rounding)

You might not exactly be interested in Ferion, but if you are, have fun

### Who is online

Users browsing this forum: No registered users and 4 guests