1
0
mirror of https://github.com/OpenTTD/OpenTTD synced 2025-12-10 06:52:05 +01:00

Codechange: Early continue for cargos not moved by this station

This commit is contained in:
Tyler Trahan
2025-07-21 06:46:16 -04:00
parent 1ac5baab31
commit 2ab3b5516f

View File

@@ -3955,144 +3955,146 @@ static void UpdateStationRating(Station *st)
for (const CargoSpec *cs : CargoSpec::Iterate()) { for (const CargoSpec *cs : CargoSpec::Iterate()) {
GoodsEntry *ge = &st->goods[cs->Index()]; GoodsEntry *ge = &st->goods[cs->Index()];
/* Slowly increase the rating back to its original level in the case we
* didn't deliver cargo yet to this station. This happens when a bribe /* The station might not currently be moving this cargo. */
* failed while you didn't moved that cargo yet to a station. */ if (!ge->HasRating()) {
if (!ge->HasRating() && ge->rating < INITIAL_STATION_RATING) { /* Slowly increase the rating back to its original level in the case we
ge->rating++; * didn't deliver cargo yet to this station. This happens when a bribe
* failed while you didn't moved that cargo yet to a station. */
if (ge->rating < INITIAL_STATION_RATING) ge->rating++;
/* Nothing else to do with this cargo. */
continue;
} }
/* Only change the rating if we are moving this cargo */ byte_inc_sat(&ge->time_since_pickup);
if (ge->HasRating()) { if (ge->time_since_pickup == 255 && _settings_game.order.selectgoods) {
byte_inc_sat(&ge->time_since_pickup); ge->status.Reset(GoodsEntry::State::Rating);
if (ge->time_since_pickup == 255 && _settings_game.order.selectgoods) { ge->last_speed = 0;
ge->status.Reset(GoodsEntry::State::Rating); TruncateCargo(cs, ge);
ge->last_speed = 0; waiting_changed = true;
TruncateCargo(cs, ge); continue;
waiting_changed = true; }
continue;
}
bool skip = false; bool skip = false;
int rating = 0; int rating = 0;
uint waiting = ge->HasData() ? ge->GetData().cargo.AvailableCount() : 0; uint waiting = ge->HasData() ? ge->GetData().cargo.AvailableCount() : 0;
/* num_dests is at least 1 if there is any cargo as /* num_dests is at least 1 if there is any cargo as
* StationID::Invalid() is also a destination. * StationID::Invalid() is also a destination.
*/ */
uint num_dests = ge->HasData() ? static_cast<uint>(ge->GetData().cargo.Packets()->MapSize()) : 0; uint num_dests = ge->HasData() ? static_cast<uint>(ge->GetData().cargo.Packets()->MapSize()) : 0;
/* Average amount of cargo per next hop, but prefer solitary stations /* Average amount of cargo per next hop, but prefer solitary stations
* with only one or two next hops. They are allowed to have more * with only one or two next hops. They are allowed to have more
* cargo waiting per next hop. * cargo waiting per next hop.
* With manual cargo distribution waiting_avg = waiting / 2 as then * With manual cargo distribution waiting_avg = waiting / 2 as then
* StationID::Invalid() is the only destination. * StationID::Invalid() is the only destination.
*/ */
uint waiting_avg = waiting / (num_dests + 1); uint waiting_avg = waiting / (num_dests + 1);
if (_cheats.station_rating.value) { if (_cheats.station_rating.value) {
ge->rating = rating = MAX_STATION_RATING; ge->rating = rating = MAX_STATION_RATING;
skip = true;
} else if (cs->callback_mask.Test(CargoCallbackMask::StationRatingCalc)) {
/* Perform custom station rating. If it succeeds the speed, days in transit and
* waiting cargo ratings must not be executed. */
/* NewGRFs expect last speed to be 0xFF when no vehicle has arrived yet. */
uint last_speed = ge->HasVehicleEverTriedLoading() ? ge->last_speed : 0xFF;
uint32_t var18 = ClampTo<uint8_t>(ge->time_since_pickup)
| (ClampTo<uint16_t>(ge->max_waiting_cargo) << 8)
| (ClampTo<uint8_t>(last_speed) << 24);
/* Convert to the 'old' vehicle types */
uint32_t var10 = (st->last_vehicle_type == VEH_INVALID) ? 0x0 : (st->last_vehicle_type + 0x10);
uint16_t callback = GetCargoCallback(CBID_CARGO_STATION_RATING_CALC, var10, var18, cs);
if (callback != CALLBACK_FAILED) {
skip = true; skip = true;
} else if (cs->callback_mask.Test(CargoCallbackMask::StationRatingCalc)) { rating = GB(callback, 0, 14);
/* Perform custom station rating. If it succeeds the speed, days in transit and
* waiting cargo ratings must not be executed. */
/* NewGRFs expect last speed to be 0xFF when no vehicle has arrived yet. */ /* Simulate a 15 bit signed value */
uint last_speed = ge->HasVehicleEverTriedLoading() ? ge->last_speed : 0xFF; if (HasBit(callback, 14)) rating -= 0x4000;
}
}
uint32_t var18 = ClampTo<uint8_t>(ge->time_since_pickup) if (!skip) {
| (ClampTo<uint16_t>(ge->max_waiting_cargo) << 8) int b = ge->last_speed - 85;
| (ClampTo<uint8_t>(last_speed) << 24); if (b >= 0) rating += b >> 2;
/* Convert to the 'old' vehicle types */
uint32_t var10 = (st->last_vehicle_type == VEH_INVALID) ? 0x0 : (st->last_vehicle_type + 0x10);
uint16_t callback = GetCargoCallback(CBID_CARGO_STATION_RATING_CALC, var10, var18, cs);
if (callback != CALLBACK_FAILED) {
skip = true;
rating = GB(callback, 0, 14);
/* Simulate a 15 bit signed value */ uint8_t waittime = ge->time_since_pickup;
if (HasBit(callback, 14)) rating -= 0x4000; if (st->last_vehicle_type == VEH_SHIP) waittime >>= 2;
if (waittime <= 21) rating += 25;
if (waittime <= 12) rating += 25;
if (waittime <= 6) rating += 45;
if (waittime <= 3) rating += 35;
rating -= 90;
if (ge->max_waiting_cargo <= 1500) rating += 55;
if (ge->max_waiting_cargo <= 1000) rating += 35;
if (ge->max_waiting_cargo <= 600) rating += 10;
if (ge->max_waiting_cargo <= 300) rating += 20;
if (ge->max_waiting_cargo <= 100) rating += 10;
}
if (Company::IsValidID(st->owner) && st->town->statues.Test(st->owner)) rating += 26;
uint8_t age = ge->last_age;
if (age < 3) rating += 10;
if (age < 2) rating += 10;
if (age < 1) rating += 13;
{
int or_ = ge->rating; // old rating
/* only modify rating in steps of -2, -1, 0, 1 or 2 */
ge->rating = rating = ClampTo<uint8_t>(or_ + Clamp(rating - or_, -2, 2));
/* if rating is <= 64 and more than 100 items waiting on average per destination,
* remove some random amount of goods from the station */
if (rating <= 64 && waiting_avg >= 100) {
int dec = Random() & 0x1F;
if (waiting_avg < 200) dec &= 7;
waiting -= (dec + 1) * num_dests;
waiting_changed = true;
}
/* if rating is <= 127 and there are any items waiting, maybe remove some goods. */
if (rating <= 127 && waiting != 0) {
uint32_t r = Random();
if (rating <= (int)GB(r, 0, 7)) {
/* Need to have int, otherwise it will just overflow etc. */
waiting = std::max((int)waiting - (int)((GB(r, 8, 2) - 1) * num_dests), 0);
waiting_changed = true;
} }
} }
if (!skip) { /* At some point we really must cap the cargo. Previously this
int b = ge->last_speed - 85; * was a strict 4095, but now we'll have a less strict, but
if (b >= 0) rating += b >> 2; * increasingly aggressive truncation of the amount of cargo. */
static const uint WAITING_CARGO_THRESHOLD = 1 << 12;
static const uint WAITING_CARGO_CUT_FACTOR = 1 << 6;
static const uint MAX_WAITING_CARGO = 1 << 15;
uint8_t waittime = ge->time_since_pickup; if (waiting > WAITING_CARGO_THRESHOLD) {
if (st->last_vehicle_type == VEH_SHIP) waittime >>= 2; uint difference = waiting - WAITING_CARGO_THRESHOLD;
if (waittime <= 21) rating += 25; waiting -= (difference / WAITING_CARGO_CUT_FACTOR);
if (waittime <= 12) rating += 25;
if (waittime <= 6) rating += 45;
if (waittime <= 3) rating += 35;
rating -= 90; waiting = std::min(waiting, MAX_WAITING_CARGO);
if (ge->max_waiting_cargo <= 1500) rating += 55; waiting_changed = true;
if (ge->max_waiting_cargo <= 1000) rating += 35;
if (ge->max_waiting_cargo <= 600) rating += 10;
if (ge->max_waiting_cargo <= 300) rating += 20;
if (ge->max_waiting_cargo <= 100) rating += 10;
} }
if (Company::IsValidID(st->owner) && st->town->statues.Test(st->owner)) rating += 26; /* We can't truncate cargo that's already reserved for loading.
* Thus StoredCount() here. */
if (waiting_changed && waiting < (ge->HasData() ? ge->GetData().cargo.AvailableCount() : 0)) {
/* Feed back the exact own waiting cargo at this station for the
* next rating calculation. */
ge->max_waiting_cargo = 0;
uint8_t age = ge->last_age; TruncateCargo(cs, ge, ge->GetData().cargo.AvailableCount() - waiting);
if (age < 3) rating += 10; } else {
if (age < 2) rating += 10; /* If the average number per next hop is low, be more forgiving. */
if (age < 1) rating += 13; ge->max_waiting_cargo = waiting_avg;
{
int or_ = ge->rating; // old rating
/* only modify rating in steps of -2, -1, 0, 1 or 2 */
ge->rating = rating = ClampTo<uint8_t>(or_ + Clamp(rating - or_, -2, 2));
/* if rating is <= 64 and more than 100 items waiting on average per destination,
* remove some random amount of goods from the station */
if (rating <= 64 && waiting_avg >= 100) {
int dec = Random() & 0x1F;
if (waiting_avg < 200) dec &= 7;
waiting -= (dec + 1) * num_dests;
waiting_changed = true;
}
/* if rating is <= 127 and there are any items waiting, maybe remove some goods. */
if (rating <= 127 && waiting != 0) {
uint32_t r = Random();
if (rating <= (int)GB(r, 0, 7)) {
/* Need to have int, otherwise it will just overflow etc. */
waiting = std::max((int)waiting - (int)((GB(r, 8, 2) - 1) * num_dests), 0);
waiting_changed = true;
}
}
/* At some point we really must cap the cargo. Previously this
* was a strict 4095, but now we'll have a less strict, but
* increasingly aggressive truncation of the amount of cargo. */
static const uint WAITING_CARGO_THRESHOLD = 1 << 12;
static const uint WAITING_CARGO_CUT_FACTOR = 1 << 6;
static const uint MAX_WAITING_CARGO = 1 << 15;
if (waiting > WAITING_CARGO_THRESHOLD) {
uint difference = waiting - WAITING_CARGO_THRESHOLD;
waiting -= (difference / WAITING_CARGO_CUT_FACTOR);
waiting = std::min(waiting, MAX_WAITING_CARGO);
waiting_changed = true;
}
/* We can't truncate cargo that's already reserved for loading.
* Thus StoredCount() here. */
if (waiting_changed && waiting < (ge->HasData() ? ge->GetData().cargo.AvailableCount() : 0)) {
/* Feed back the exact own waiting cargo at this station for the
* next rating calculation. */
ge->max_waiting_cargo = 0;
TruncateCargo(cs, ge, ge->GetData().cargo.AvailableCount() - waiting);
} else {
/* If the average number per next hop is low, be more forgiving. */
ge->max_waiting_cargo = waiting_avg;
}
} }
} }
} }