diff --git a/src/economy.cpp b/src/economy.cpp index 0b1fd030e0..07fefdac1b 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -929,6 +929,9 @@ static Money DeliverGoods(int num_pieces, CargoID cargo_type, StationID dest, Ti /* Give the goods to the industry. */ uint accepted = DeliverGoodsToIndustry(st, cargo_type, num_pieces, src_type == ST_INDUSTRY ? src : INVALID_INDUSTRY); + /* If there are non-industries around accepting the cargo, accept it all */ + if (HasBit(st->town_acc, cargo_type)) accepted = num_pieces; + /* Determine profit */ Money profit = GetTransportedGoodsIncome(accepted, DistanceManhattan(source_tile, st->xy), days_in_transit, cargo_type); diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index a86551aa73..584a7e87ed 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -392,7 +392,7 @@ static Foundation GetFoundation_Industry(TileIndex tile, Slope tileh) return FlatteningFoundation(tileh); } -static void AddAcceptedCargo_Industry(TileIndex tile, CargoArray &acceptance) +static void AddAcceptedCargo_Industry(TileIndex tile, CargoArray &acceptance, uint32 *town_acc) { IndustryGfx gfx = GetIndustryGfx(tile); const IndustryTileSpec *itspec = GetIndustryTileSpec(gfx); diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index e03224cf9e..79ae4b70f1 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -159,7 +159,7 @@ public: td.grf = NULL; CargoArray acceptance; - AddAcceptedCargo(tile, acceptance); + AddAcceptedCargo(tile, acceptance, NULL); GetTileDesc(tile, &td); uint line_nr = 0; diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index ce03b01af1..afdbd41514 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -1946,6 +1946,11 @@ bool AfterLoadGame() } } + if (CheckSavegameVersion(127)) { + Station *st; + FOR_ALL_STATIONS(st) UpdateStationAcceptance(st, false); + } + AfterLoadLabelMaps(); GamelogPrintDebug(1); diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index 0fd7a25610..39e6afa0ed 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -48,7 +48,7 @@ #include "saveload_internal.h" -extern const uint16 SAVEGAME_VERSION = 126; +extern const uint16 SAVEGAME_VERSION = 127; SavegameType _savegame_type; ///< type of savegame we are loading diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp index 03979c9a0f..1094072a3f 100644 --- a/src/saveload/station_sl.cpp +++ b/src/saveload/station_sl.cpp @@ -326,6 +326,7 @@ static const SaveLoad _station_desc[] = { SLE_VAR(Station, last_vehicle_type, SLE_UINT8), SLE_VAR(Station, had_vehicle_of_type, SLE_UINT8), SLE_LST(Station, loading_vehicles, REF_VEHICLE), + SLE_CONDVAR(Station, town_acc, SLE_UINT32, 127, SL_MAX_VERSION), SLE_END() }; diff --git a/src/station_base.h b/src/station_base.h index 30f42a34db..9ed0262c69 100644 --- a/src/station_base.h +++ b/src/station_base.h @@ -85,6 +85,7 @@ public: byte last_vehicle_type; std::list loading_vehicles; GoodsEntry goods[NUM_CARGO]; ///< Goods at this station + uint32 town_acc; ///< Bitmask of cargos accepted by town houses and headquarters IndustryVector industries_near; ///< Cached list of industries near the station that can accept cargo, @see DeliverGoodsToIndustry() diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 5264be8aef..d2c8f0d1fd 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -510,10 +510,12 @@ CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad) * @param w X extent of area * @param h Y extent of area * @param rad Search radius in addition to given area + * @param town_acc bitmask of cargo accepted by houses and headquarters; can be NULL */ -CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad) +CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad, uint32 *town_acc) { CargoArray acceptance; + if (town_acc != NULL) *town_acc = 0; int x = TileX(tile); int y = TileY(tile); @@ -533,7 +535,7 @@ CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad) for (int yc = y1; yc != y2; yc++) { for (int xc = x1; xc != x2; xc++) { TileIndex tile = TileXY(xc, yc); - AddAcceptedCargo(tile, acceptance); + AddAcceptedCargo(tile, acceptance, town_acc); } } @@ -544,7 +546,7 @@ CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad) * @param st Station to update * @param show_msg controls whether to display a message that acceptance was changed. */ -static void UpdateStationAcceptance(Station *st, bool show_msg) +void UpdateStationAcceptance(Station *st, bool show_msg) { /* old accepted goods types */ uint old_acc = GetAcceptanceMask(st); @@ -556,7 +558,8 @@ static void UpdateStationAcceptance(Station *st, bool show_msg) TileXY(st->rect.left, st->rect.top), st->rect.right - st->rect.left + 1, st->rect.bottom - st->rect.top + 1, - st->GetCatchmentRadius() + st->GetCatchmentRadius(), + &st->town_acc ); } diff --git a/src/station_func.h b/src/station_func.h index b574a1f0ba..5ab8664c2a 100644 --- a/src/station_func.h +++ b/src/station_func.h @@ -30,7 +30,9 @@ void ShowStationViewWindow(StationID station); void UpdateAllStationVirtCoords(); CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad); -CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad); +CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad, uint32 *town_acc = NULL); + +void UpdateStationAcceptance(Station *st, bool show_msg); const DrawTileSprites *GetStationTileLayout(StationType st, byte gfx); void StationPickerDrawSprite(int x, int y, StationType st, RailType railtype, RoadType roadtype, int image); diff --git a/src/tile_cmd.h b/src/tile_cmd.h index 05f76cc628..593c0500f8 100644 --- a/src/tile_cmd.h +++ b/src/tile_cmd.h @@ -78,10 +78,11 @@ typedef CommandCost ClearTileProc(TileIndex tile, DoCommandFlag flags); /** * Tile callback function signature for obtaining cargo acceptance of a tile - * @param tile Tile queried for its accepted cargo - * @param acceptance Storage destination of the cargo acceptance in 1/8 + * @param tile Tile queried for its accepted cargo + * @param acceptance Storage destination of the cargo acceptance in 1/8 + * @param town_acc Bitmask of town and headquarters-accepted cargo */ -typedef void AddAcceptedCargoProc(TileIndex tile, CargoArray &acceptance); +typedef void AddAcceptedCargoProc(TileIndex tile, CargoArray &acceptance, uint32 *town_acc); /** * Tile callback function signature for obtaining a tile description @@ -164,11 +165,12 @@ VehicleEnterTileStatus VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y void ChangeTileOwner(TileIndex tile, Owner old_owner, Owner new_owner); void GetTileDesc(TileIndex tile, TileDesc *td); -static inline void AddAcceptedCargo(TileIndex tile, CargoArray &acceptance) +static inline void AddAcceptedCargo(TileIndex tile, CargoArray &acceptance, uint32 *town_acc) { AddAcceptedCargoProc *proc = _tile_type_procs[GetTileType(tile)]->add_accepted_cargo_proc; if (proc == NULL) return; - proc(tile, acceptance); + uint32 dummy = 0; // use dummy bitmask so there don't need to be several 'town_acc != NULL' checks + proc(tile, acceptance, town_acc == NULL ? &dummy : town_acc); } static inline void AddProducedCargo(TileIndex tile, CargoArray &produced) diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index d15cead5e7..49775798c5 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -579,7 +579,14 @@ static void AddProducedCargo_Town(TileIndex tile, CargoArray &produced) } } -static void AddAcceptedCargo_Town(TileIndex tile, CargoArray &acceptance) +static inline void AddAcceptedCargoSetMask(CargoID cargo, uint amount, CargoArray &acceptance, uint32 *town_acc) +{ + if (cargo == CT_INVALID || amount == 0) return; + acceptance[cargo] += amount; + SetBit(*town_acc, cargo); +} + +static void AddAcceptedCargo_Town(TileIndex tile, CargoArray &acceptance, uint32 *town_acc) { const HouseSpec *hs = HouseSpec::Get(GetHouseType(tile)); CargoID accepts[3]; @@ -604,13 +611,13 @@ static void AddAcceptedCargo_Town(TileIndex tile, CargoArray &acceptance) if (HasBit(hs->callback_mask, CBM_HOUSE_CARGO_ACCEPTANCE)) { uint16 callback = GetHouseCallback(CBID_HOUSE_CARGO_ACCEPTANCE, 0, 0, GetHouseType(tile), Town::GetByTile(tile), tile); if (callback != CALLBACK_FAILED) { - if (accepts[0] != CT_INVALID) acceptance[accepts[0]] += GB(callback, 0, 4); - if (accepts[1] != CT_INVALID) acceptance[accepts[1]] += GB(callback, 4, 4); + AddAcceptedCargoSetMask(accepts[0], GB(callback, 0, 4), acceptance, town_acc); + AddAcceptedCargoSetMask(accepts[1], GB(callback, 4, 4), acceptance, town_acc); if (_settings_game.game_creation.landscape != LT_TEMPERATE && HasBit(callback, 12)) { /* The 'S' bit indicates food instead of goods */ - acceptance[CT_FOOD] += GB(callback, 8, 4); + AddAcceptedCargoSetMask(CT_FOOD, GB(callback, 8, 4), acceptance, town_acc); } else { - if (accepts[2] != CT_INVALID) acceptance[accepts[2]] += GB(callback, 8, 4); + AddAcceptedCargoSetMask(accepts[2], GB(callback, 8, 4), acceptance, town_acc); } return; } @@ -618,7 +625,7 @@ static void AddAcceptedCargo_Town(TileIndex tile, CargoArray &acceptance) /* No custom acceptance, so fill in with the default values */ for (uint8 i = 0; i < lengthof(accepts); i++) { - if (accepts[i] != CT_INVALID) acceptance[accepts[i]] += hs->cargo_acceptance[i]; + AddAcceptedCargoSetMask(accepts[i], hs->cargo_acceptance[i], acceptance, town_acc); } } diff --git a/src/unmovable_cmd.cpp b/src/unmovable_cmd.cpp index d3ddf69c9a..f4cf786cdb 100644 --- a/src/unmovable_cmd.cpp +++ b/src/unmovable_cmd.cpp @@ -301,7 +301,7 @@ static CommandCost ClearTile_Unmovable(TileIndex tile, DoCommandFlag flags) return CommandCost(); } -static void AddAcceptedCargo_Unmovable(TileIndex tile, CargoArray &acceptance) +static void AddAcceptedCargo_Unmovable(TileIndex tile, CargoArray &acceptance, uint32 *town_acc) { if (!IsCompanyHQ(tile)) return; @@ -314,12 +314,14 @@ static void AddAcceptedCargo_Unmovable(TileIndex tile, CargoArray &acceptance) /* Top town building generates 10, so to make HQ interesting, the top * type makes 20. */ acceptance[CT_PASSENGERS] += max(1U, level); + SetBit(*town_acc, CT_PASSENGERS); /* Top town building generates 4, HQ can make up to 8. The * proportion passengers:mail is different because such a huge * commercial building generates unusually high amount of mail * correspondence per physical visitor. */ acceptance[CT_MAIL] += max(1U, level / 2); + SetBit(*town_acc, CT_MAIL); }