From 6d93fa649cdf9a02605c86a7f78e0544409cc079 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Sun, 7 Jan 2024 19:32:41 +0000 Subject: [PATCH] Change: Towns generate cargo based on town production effect. This replaces the fixed handling of passengers and mail. --- src/town_cmd.cpp | 90 ++++++++++++++++++++++++++++++++---------------- src/town_gui.cpp | 22 ++++++------ 2 files changed, 72 insertions(+), 40 deletions(-) diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 2f98727a5c..5663c11815 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -541,9 +541,52 @@ static void TownGenerateCargo(Town *t, CargoID ct, uint amount, StationFinder &s amount = ScaleByCargoScale(amount, true); /* Actually generate cargo and update town statistics. */ - uint moved = MoveGoodsToStation(ct, amount, SourceType::Town, t->index, stations.GetStations()); t->supplied[ct].new_max += amount; - t->supplied[ct].new_act += moved; + t->supplied[ct].new_act += MoveGoodsToStation(ct, amount, SourceType::Town, t->index, stations.GetStations());; +} + +/** + * Generate cargo for a house using the original algorithm. + * @param t The current town. + * @param tpe The town production effect. + * @param rate The town's product rate for this production. + * @param stations Available stations for this house. + */ +static void TownGenerateCargoOriginal(Town *t, TownProductionEffect tpe, uint8_t rate, StationFinder &stations) +{ + for (const CargoSpec *cs : CargoSpec::town_production_cargoes[tpe]) { + uint32_t r = Random(); + if (GB(r, 0, 8) < rate) { + CargoID cid = cs->Index(); + uint amt = GB(r, 0, 8) / 8 + 1; + + TownGenerateCargo(t, cid, amt, stations, true); + } + } +} + +/** + * Generate cargo for a house using the binominal algorithm. + * @param t The current town. + * @param tpe The town production effect. + * @param rate The town's product rate for this production. + * @param stations Available stations for this house. + */ +static void TownGenerateCargoBinominal(Town *t, TownProductionEffect tpe, uint8_t rate, StationFinder &stations) +{ + for (const CargoSpec *cs : CargoSpec::town_production_cargoes[tpe]) { + CargoID cid = cs->Index(); + uint32_t r = Random(); + + /* Make a bitmask with up to 32 bits set, one for each potential pax. */ + int genmax = (rate + 7) / 8; + uint32_t genmask = (genmax >= 32) ? 0xFFFFFFFF : ((1 << genmax) - 1); + + /* Mask random value by potential pax and count number of actual pax. */ + uint amt = CountBits(r & genmask); + + TownGenerateCargo(t, cid, amt, stations, true); + } } /** @@ -600,15 +643,8 @@ static void TileLoop_Town(TileIndex tile) switch (_settings_game.economy.town_cargogen_mode) { case TCGM_ORIGINAL: /* Original (quadratic) cargo generation algorithm */ - if (GB(r, 0, 8) < hs->population) { - uint amt = GB(r, 0, 8) / 8 + 1; - TownGenerateCargo(t, CT_PASSENGERS, amt, stations, true); - } - - if (GB(r, 8, 8) < hs->mail_generation) { - uint amt = GB(r, 8, 8) / 8 + 1; - TownGenerateCargo(t, CT_MAIL, amt, stations, true); - } + TownGenerateCargoOriginal(t, TPE_PASSENGERS, hs->population, stations); + TownGenerateCargoOriginal(t, TPE_MAIL, hs->mail_generation, stations); break; case TCGM_BITCOUNT: @@ -616,20 +652,8 @@ static void TileLoop_Town(TileIndex tile) /* Reduce generation rate to a 1/4, using tile bits to spread out distribution. * As tick counter is incremented by 256 between each call, we ignore the lower 8 bits. */ if (GB(TimerGameTick::counter, 8, 2) == GB(tile.base(), 0, 2)) { - /* Make a bitmask with up to 32 bits set, one for each potential pax */ - int genmax = (hs->population + 7) / 8; - uint32_t genmask = (genmax >= 32) ? 0xFFFFFFFF : ((1 << genmax) - 1); - /* Mask random value by potential pax and count number of actual pax */ - uint amt = CountBits(r & genmask); - /* Adjust and apply */ - TownGenerateCargo(t, CT_PASSENGERS, amt, stations, true); - - /* Do the same for mail, with a fresh random */ - r = Random(); - genmax = (hs->mail_generation + 7) / 8; - genmask = (genmax >= 32) ? 0xFFFFFFFF : ((1 << genmax) - 1); - amt = CountBits(r & genmask); - TownGenerateCargo(t, CT_MAIL, amt, stations, true); + TownGenerateCargoBinominal(t, TPE_PASSENGERS, hs->population, stations); + TownGenerateCargoBinominal(t, TPE_MAIL, hs->mail_generation, stations); } break; @@ -731,10 +755,14 @@ static void AddProducedCargo_Town(TileIndex tile, CargoArray &produced) } } else { if (hs->population > 0) { - produced[CT_PASSENGERS]++; + for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TPE_PASSENGERS]) { + produced[cs->Index()]++; + } } if (hs->mail_generation > 0) { - produced[CT_MAIL]++; + for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TPE_MAIL]) { + produced[cs->Index()]++; + } } } } @@ -1883,8 +1911,12 @@ void UpdateTownRadius(Town *t) */ void UpdateTownMaxPass(Town *t) { - t->supplied[CT_PASSENGERS].old_max = ScaleByCargoScale(t->cache.population >> 3, true); - t->supplied[CT_MAIL].old_max = ScaleByCargoScale(t->cache.population >> 4, true); + for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TPE_PASSENGERS]) { + t->supplied[cs->Index()].old_max = ScaleByCargoScale(t->cache.population >> 3, true); + } + for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TPE_MAIL]) { + t->supplied[cs->Index()].old_max = ScaleByCargoScale(t->cache.population >> 4, true); + } } static void UpdateTownGrowthRate(Town *t); diff --git a/src/town_gui.cpp b/src/town_gui.cpp index 9124e09672..c3e1bf1a2a 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -408,17 +408,17 @@ public: tr.top += GetCharacterHeight(FS_NORMAL); StringID str_last_period = TimerGameEconomy::UsingWallclockUnits() ? STR_TOWN_VIEW_CARGO_LAST_MINUTE_MAX : STR_TOWN_VIEW_CARGO_LAST_MONTH_MAX; - SetDParam(0, 1 << CT_PASSENGERS); - SetDParam(1, this->town->supplied[CT_PASSENGERS].old_act); - SetDParam(2, this->town->supplied[CT_PASSENGERS].old_max); - DrawString(tr, str_last_period); - tr.top += GetCharacterHeight(FS_NORMAL); - SetDParam(0, 1 << CT_MAIL); - SetDParam(1, this->town->supplied[CT_MAIL].old_act); - SetDParam(2, this->town->supplied[CT_MAIL].old_max); - DrawString(tr, str_last_period); - tr.top += GetCharacterHeight(FS_NORMAL); + for (auto tpe : {TPE_PASSENGERS, TPE_MAIL}) { + for (const CargoSpec *cs : CargoSpec::town_production_cargoes[tpe]) { + CargoID cid = cs->Index(); + SetDParam(0, 1ULL << cid); + SetDParam(1, this->town->supplied[cid].old_act); + SetDParam(2, this->town->supplied[cid].old_max); + DrawString(tr, str_last_period); + tr.top += GetCharacterHeight(FS_NORMAL); + } + } bool first = true; for (int i = TAE_BEGIN; i < TAE_END; i++) { @@ -539,7 +539,7 @@ public: */ uint GetDesiredInfoHeight(int width) const { - uint aimed_height = 3 * GetCharacterHeight(FS_NORMAL); + uint aimed_height = static_cast(1 + CargoSpec::town_production_cargoes[TPE_PASSENGERS].size() + CargoSpec::town_production_cargoes[TPE_MAIL].size()) * GetCharacterHeight(FS_NORMAL); bool first = true; for (int i = TAE_BEGIN; i < TAE_END; i++) {