#include "../stdafx.h" #include "cm_station_gui.hpp" #include "cm_hotkeys.hpp" #include "../core/math_func.hpp" #include "../command_type.h" #include "../command_func.h" #include "../company_func.h" #include "../industry_map.h" #include "../industry.h" #include "../landscape.h" #include "../newgrf_station.h" // StationClassID #include "../newgrf_house.h" // GetHouseCallback #include "../newgrf_cargo.h" // GetCargoTranslation #include "../object_type.h" #include "../object_map.h" #include "../station_base.h" #include "../strings_func.h" // GetString, SetDParam #include "../tilehighlight_type.h" #include "../town_map.h" #include "../town.h" #include "../viewport_func.h" #include "../viewport_kdtree.h" #include "../window_gui.h" #include "../zoom_type.h" #include "../zoom_func.h" #include extern const Station *_viewport_highlight_station; extern TileHighlightData _thd; extern void MarkCatchmentTilesDirty(); extern DiagDirection _road_station_picker_orientation; extern bool CheckDriveThroughRoadStopDirection(TileArea area, RoadBits r); extern DiagDirection AutodetectRoadObjectDirection(TileIndex tile); extern DiagDirection AutodetectDriveThroughRoadStopDirection(TileArea area); extern bool CheckClickOnViewportSign(const Viewport *vp, int x, int y, const ViewportSign *sign); extern Rect ExpandRectWithViewportSignMargins(Rect r, ZoomLevel zoom); extern ViewportSignKdtree _viewport_sign_kdtree; extern AirportClassID _selected_airport_class; extern int _selected_airport_index; extern byte _selected_airport_layout; extern RailType _cur_railtype; // rail_gui.cpp struct RailStationGUISettings { Axis orientation; ///< Currently selected rail station orientation bool newstations; ///< Are custom station definitions available? StationClassID station_class; ///< Currently selected custom station class (if newstations is \c true ) byte station_type; ///< %Station type within the currently selected custom station class (if newstations is \c true ) byte station_count; ///< Number of custom stations (if newstations is \c true ) }; extern RailStationGUISettings _railstation; //rail_gui.cpp namespace citymania { StationBuildingStatus _station_building_status = StationBuildingStatus::NEW; const Station *_station_to_join = nullptr; const Station *_highlight_station_to_join = nullptr; TileArea _highlight_join_area; // void SetStationTileSelectSize(int w, int h, int catchment) { // _station_select.w = w; // _station_select.h = h; // _station_select.catchment = catchment; // } void SetStationBiildingStatus(StationBuildingStatus status) { _station_building_status = status; }; static const int MAX_TILE_EXTENT_LEFT = ZOOM_LVL_BASE * TILE_PIXELS; ///< Maximum left extent of tile relative to north corner. static const int MAX_TILE_EXTENT_RIGHT = ZOOM_LVL_BASE * TILE_PIXELS; ///< Maximum right extent of tile relative to north corner. static const int MAX_TILE_EXTENT_TOP = ZOOM_LVL_BASE * MAX_BUILDING_PIXELS; ///< Maximum top extent of tile relative to north corner (not considering bridges). static const int MAX_TILE_EXTENT_BOTTOM = ZOOM_LVL_BASE * (TILE_PIXELS + 2 * TILE_HEIGHT); ///< Maximum bottom extent of tile relative to north corner (worst case: #SLOPE_STEEP_N). void MarkTileAreaDirty(const TileArea &ta) { if (ta.tile == INVALID_TILE) return; auto x = TileX(ta.tile); auto y = TileY(ta.tile); Point p1 = RemapCoords(x * TILE_SIZE, y * TILE_SIZE, TileHeight(ta.tile) * TILE_HEIGHT); Point p2 = RemapCoords((x + ta.w) * TILE_SIZE, (y + ta.h) * TILE_SIZE, TileHeight(TileXY(x + ta.w - 1, y + ta.h - 1)) * TILE_HEIGHT); Point p3 = RemapCoords((x + ta.w) * TILE_SIZE, y * TILE_SIZE, TileHeight(TileXY(x + ta.w - 1, y)) * TILE_HEIGHT); Point p4 = RemapCoords(x * TILE_SIZE, (y + ta.h) * TILE_SIZE, TileHeight(TileXY(x, y + ta.h - 1)) * TILE_HEIGHT); MarkAllViewportsDirty( p3.x - MAX_TILE_EXTENT_LEFT, p4.x - MAX_TILE_EXTENT_TOP, p1.y + MAX_TILE_EXTENT_RIGHT, p2.y + MAX_TILE_EXTENT_BOTTOM); } static void UpdateHiglightJoinArea(const Station *station) { if (!station) { MarkTileAreaDirty(_highlight_join_area); _highlight_join_area.tile = INVALID_TILE; return; } auto &r = _station_to_join->rect; auto d = (int)_settings_game.station.station_spread - 1; TileArea ta( TileXY(std::max(r.right - d, 0), std::max(r.bottom - d, 0)), TileXY(std::min(r.left + d, MapSizeX() - 1), std::min(r.top + d, MapSizeY() - 1)) ); if (_highlight_join_area.tile == ta.tile && _highlight_join_area.w == ta.w && _highlight_join_area.h == ta.h) return; MarkTileAreaDirty(_highlight_join_area); _highlight_join_area = ta; MarkTileAreaDirty(_highlight_join_area); } static void MarkCoverageAreaDirty(const Station *station) { MarkTileAreaDirty(station->catchment_tiles); } void MarkCoverageHighlightDirty() { MarkCatchmentTilesDirty(); } void SetHighlightStationToJoin(const Station *station, bool with_area) { UpdateHiglightJoinArea(with_area ? station : nullptr); if (_highlight_station_to_join == station) return; if (_highlight_station_to_join && _settings_client.gui.station_show_coverage) MarkCoverageAreaDirty(_highlight_station_to_join); _highlight_station_to_join = station; if (_highlight_station_to_join && _settings_client.gui.station_show_coverage) MarkCoverageAreaDirty(_highlight_station_to_join); } void OnStationTileSetChange(const Station *station, bool adding, StationType type) { if (station == _highlight_station_to_join) { if (_highlight_join_area.tile != INVALID_TILE) UpdateHiglightJoinArea(_station_to_join); if (_settings_client.gui.station_show_coverage) MarkCoverageAreaDirty(_highlight_station_to_join); } if (station == _viewport_highlight_station) MarkCoverageAreaDirty(_viewport_highlight_station); } CommandContainer _last_station_bulid_cmd; void OnStationPartBuilt(const Station *station, TileIndex tile, uint32 p1, uint32 p2) { if (_current_company != _local_company) return; if (tile != _last_station_bulid_cmd.tile || p1 != _last_station_bulid_cmd.p1 || p2 != _last_station_bulid_cmd.p2) return; _station_to_join = station; CheckRedrawStationCoverage(); } const Station *CheckClickOnDeadStationSign() { int x = _cursor.pos.x; int y = _cursor.pos.y; Window *w = FindWindowFromPt(x, y); if (w == nullptr) return nullptr; Viewport *vp = IsPtInWindowViewport(w, x, y); if (!HasBit(_display_opt, DO_SHOW_STATION_NAMES) && !IsInvisibilitySet(TO_SIGNS)) return nullptr; x = ScaleByZoom(x - vp->left, vp->zoom) + vp->virtual_left; y = ScaleByZoom(y - vp->top, vp->zoom) + vp->virtual_top; Rect search_rect{ x - 1, y - 1, x + 1, y + 1 }; search_rect = ExpandRectWithViewportSignMargins(search_rect, vp->zoom); const Station *last_st = nullptr; _viewport_sign_kdtree.FindContained(search_rect.left, search_rect.top, search_rect.right, search_rect.bottom, [&](const ViewportSignKdtreeItem & item) { if (item.type != ViewportSignKdtreeItem::VKI_STATION) return; auto st = Station::Get(item.id.station); if (st->IsInUse()) return; if (_local_company != st->owner) return; if (CheckClickOnViewportSign(vp, x, y, &st->sign)) last_st = st; }); return last_st; } bool CheckStationJoin(TileIndex start_tile, TileIndex end_tile) { // if (_ctrl_pressed && start_tile == end_tile) { if (citymania::_fn_mod) { if (IsTileType (start_tile, MP_STATION)) { citymania::SelectStationToJoin(Station::GetByTile(start_tile)); return true; } auto st = CheckClickOnDeadStationSign(); if (st) { citymania::SelectStationToJoin(st); return true; } } return false; } void JoinAndBuild(CommandContainer cmdcont) { auto join_to = _highlight_station_to_join; uint32 adj_bit = ((citymania::_fn_mod || join_to) ? 1 : 0); auto cmd = (cmdcont.cmd & CMD_ID_MASK); if (cmd == CMD_BUILD_RAIL_STATION) { SB(cmdcont.p1, 24, 1, adj_bit); } else if (cmd == CMD_BUILD_ROAD_STOP) { SB(cmdcont.p2, 2, 1, adj_bit); } else if (cmd == CMD_BUILD_DOCK) { SB(cmdcont.p1, 0, 1, adj_bit); } else if (cmd == CMD_BUILD_AIRPORT) { SB(cmdcont.p2, 0, 1, adj_bit); } if (citymania::_fn_mod) SB(cmdcont.p2, 16, 16, NEW_STATION); else if (join_to) SB(cmdcont.p2, 16, 16, join_to->index); else SB(cmdcont.p2, 16, 16, INVALID_STATION); _last_station_bulid_cmd = cmdcont; DoCommandP(&cmdcont); } void PlaceRoadStop(TileIndex start_tile, TileIndex end_tile, uint32 p2, uint32 cmd) { uint8 ddir = _road_station_picker_orientation; SB(p2, 16, 16, INVALID_STATION); // no station to join TileArea ta(start_tile, end_tile); if (CheckStationJoin(start_tile, end_tile)) return; if (ddir >= DIAGDIR_END) { if (ddir < DIAGDIR_END + 2) { SetBit(p2, 1); // It's a drive-through stop. ddir -= DIAGDIR_END; // Adjust picker result to actual direction. // When placed on road autorotate anyway if (ddir == DIAGDIR_SE) { if (!CheckDriveThroughRoadStopDirection(ta, ROAD_Y)) ddir = DIAGDIR_NE; } else { if (!CheckDriveThroughRoadStopDirection(ta, ROAD_X)) ddir = DIAGDIR_SE; } } else if (ddir == DIAGDIR_END + 2) { ddir = AutodetectRoadObjectDirection(start_tile); } else if (ddir == DIAGDIR_END + 3) { SetBit(p2, 1); // It's a drive-through stop. ddir = AutodetectDriveThroughRoadStopDirection(ta); } } p2 |= ddir << 3; // Set the DiagDirecion into p2 bits 3 and 4. CommandContainer cmdcont = { ta.tile, (uint32)(ta.w | ta.h << 8), p2, cmd, CcRoadStop, "" }; JoinAndBuild(cmdcont); } void HandleStationPlacement(TileIndex start, TileIndex end) { if (CheckStationJoin(start, end)) return; TileArea ta(start, end); uint numtracks = ta.w; uint platlength = ta.h; if (_railstation.orientation == AXIS_X) Swap(numtracks, platlength); uint32 p1 = _cur_railtype | _railstation.orientation << 6 | numtracks << 8 | platlength << 16 | (citymania::_fn_mod ? 1 << 24 : 0); uint32 p2 = _railstation.station_class | _railstation.station_type << 8 | INVALID_STATION << 16; CommandContainer cmdcont = { ta.tile, p1, p2, CMD_BUILD_RAIL_STATION | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_STATION), CcStation, "" }; JoinAndBuild(cmdcont); } void PlaceRail_Station(TileIndex tile) { if (CheckStationJoin(tile, tile)) return; uint32 p1 = _cur_railtype | _railstation.orientation << 6 | _settings_client.gui.station_numtracks << 8 | _settings_client.gui.station_platlength << 16 | (citymania::_fn_mod ? 1 << 24 : 0); uint32 p2 = _railstation.station_class | _railstation.station_type << 8 | INVALID_STATION << 16; int w = _settings_client.gui.station_numtracks; int h = _settings_client.gui.station_platlength; if (!_railstation.orientation) Swap(w, h); CommandContainer cmdcont = { tile, p1, p2, CMD_BUILD_RAIL_STATION | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_STATION), CcStation, "" }; JoinAndBuild(cmdcont); } void PlaceDock(TileIndex tile) { if (CheckStationJoin(tile, tile)) return; uint32 p2 = (uint32)INVALID_STATION << 16; // no station to join /* tile is always the land tile, so need to evaluate _thd.pos */ CommandContainer cmdcont = { tile, citymania::_fn_mod, p2, CMD_BUILD_DOCK | CMD_MSG(STR_ERROR_CAN_T_BUILD_DOCK_HERE), CcBuildDocks, "" }; /* Determine the watery part of the dock. */ // DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile)); // TileIndex tile_to = (dir != INVALID_DIAGDIR ? TileAddByDiagDir(tile, ReverseDiagDir(dir)) : tile); JoinAndBuild(cmdcont); } void PlaceAirport(TileIndex tile) { if (CheckStationJoin(tile, tile)) return; if (_selected_airport_index == -1) return; uint32 p2 = (citymania::_fn_mod ? 1 : 0); SB(p2, 16, 16, INVALID_STATION); // no station to join uint32 p1 = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index)->GetIndex(); p1 |= _selected_airport_layout << 8; CommandContainer cmdcont = { tile, p1, p2, CMD_BUILD_AIRPORT | CMD_MSG(STR_ERROR_CAN_T_BUILD_AIRPORT_HERE), CcBuildAirport, "" }; JoinAndBuild(cmdcont); } static void FindStationsAroundSelection(const TileArea &location) { /* Extended area by one tile */ int x = TileX(location.tile); int y = TileY(location.tile); TileArea ta(TileXY(std::max(0, x - 1), std::max(0, y - 1)), TileXY(std::min(MapMaxX() - 1, x + location.w + 1), std::min(MapMaxY() - 1, y + location.h + 1))); Station *adjacent = nullptr; /* Direct loop instead of FindStationsAroundTiles as we are not interested in catchment area */ TILE_AREA_LOOP(tile, ta) { if (IsTileType(tile, MP_STATION) && GetTileOwner(tile) == _local_company) { Station *st = Station::GetByTile(tile); if (st == nullptr) continue; int tx = TileX(tile); int ty = TileY(tile); bool is_corner = ((tx == x - 1 || tx == x + location.w + 1) && (ty == y - 1 || ty == y + location.h + 1)); if (adjacent && is_corner) continue; adjacent = st; if (!is_corner) break; } } SetHighlightStationToJoin(adjacent, false); _station_building_status = (adjacent == nullptr ? StationBuildingStatus::NEW : StationBuildingStatus::JOIN); } bool CheckRedrawStationCoverage() { // static bool last_ctrl_pressed = false; static TileArea last_location; static bool last_station_mode = false; static bool last_fn_mod = false; TileArea location(TileVirtXY(_thd.pos.x, _thd.pos.y), _thd.size.x / TILE_SIZE - 1, _thd.size.y / TILE_SIZE - 1); bool station_mode = ((_thd.drawstyle & HT_DRAG_MASK) == HT_RECT && _thd.outersize.x > 0); bool location_changed = (location.tile != last_location.tile || location.w != last_location.w || location.h != last_location.h); bool mode_changed = (last_station_mode != station_mode); if (!location_changed && citymania::_fn_mod == last_fn_mod && !mode_changed) return false; last_fn_mod = citymania::_fn_mod; last_location = location; last_station_mode = station_mode; if (citymania::_fn_mod) { Station *st = nullptr; if (IsTileType(location.tile, MP_STATION) && GetTileOwner(location.tile) == _local_company) st = Station::GetByTile(location.tile); SetHighlightStationToJoin(st, _station_to_join && st == _station_to_join); _station_building_status = (st == nullptr ? StationBuildingStatus::NEW : StationBuildingStatus::JOIN); } else { if (_station_to_join) { SetHighlightStationToJoin(_station_to_join, true); _station_building_status = StationBuildingStatus::JOIN; } else { FindStationsAroundSelection(location); } } return true; } void SelectStationToJoin(const Station *station) { if (_station_to_join == station) _station_to_join = nullptr; else _station_to_join = station; CheckRedrawStationCoverage(); } void AbortStationPlacement() { _station_to_join = nullptr; SetHighlightStationToJoin(nullptr, false); } uint GetMonthlyFrom256Tick(uint amount) { return ((amount * DAY_TICKS * 30) >> 8); } uint GetAverageHouseProduction(byte amount) { static const uint AVG[2][256] = { {0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 22, 24, 27, 30, 33, 36, 39, 42, 45, 48, 52, 56, 60, 64, 68, 72, 76, 80, 85, 90, 95, 100, 105, 110, 115, 120, 126, 132, 138, 144, 150, 156, 162, 168, 175, 182, 189, 196, 203, 210, 217, 224, 232, 240, 248, 256, 264, 272, 280, 288, 297, 306, 315, 324, 333, 342, 351, 360, 370, 380, 390, 400, 410, 420, 430, 440, 451, 462, 473, 484, 495, 506, 517, 528, 540, 552, 564, 576, 588, 600, 612, 624, 637, 650, 663, 676, 689, 702, 715, 728, 742, 756, 770, 784, 798, 812, 826, 840, 855, 870, 885, 900, 915, 930, 945, 960, 976, 992, 1008, 1024, 1040, 1056, 1072, 1088, 1105, 1122, 1139, 1156, 1173, 1190, 1207, 1224, 1242, 1260, 1278, 1296, 1314, 1332, 1350, 1368, 1387, 1406, 1425, 1444, 1463, 1482, 1501, 1520, 1540, 1560, 1580, 1600, 1620, 1640, 1660, 1680, 1701, 1722, 1743, 1764, 1785, 1806, 1827, 1848, 1870, 1892, 1914, 1936, 1958, 1980, 2002, 2024, 2047, 2070, 2093, 2116, 2139, 2162, 2185, 2208, 2232, 2256, 2280, 2304, 2328, 2352, 2376, 2400, 2425, 2450, 2475, 2500, 2525, 2550, 2575, 2600, 2626, 2652, 2678, 2704, 2730, 2756, 2782, 2808, 2835, 2862, 2889, 2916, 2943, 2970, 2997, 3024, 3052, 3080, 3108, 3136, 3164, 3192, 3220, 3248, 3277, 3306, 3335, 3364, 3393, 3422, 3451, 3480, 3510, 3540, 3570, 3600, 3630, 3660, 3690, 3720, 3751, 3782, 3813, 3844, 3875, 3906, 3937, 3968, 4000, 4032, 4064, 4096, 4128, 4160, 4192}, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 51, 54, 57, 60, 63, 66, 69, 72, 75, 78, 81, 84, 87, 90, 93, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 156, 160, 165, 170, 175, 180, 185, 190, 195, 200, 205, 210, 215, 220, 225, 230, 235, 240, 246, 252, 258, 264, 270, 276, 282, 288, 294, 300, 306, 312, 318, 324, 330, 336, 343, 350, 357, 364, 371, 378, 385, 392, 399, 406, 413, 420, 427, 434, 441, 448, 456, 464, 472, 480, 488, 496, 504, 512, 520, 528, 536, 544, 552, 560, 568, 576, 585, 594, 603, 612, 621, 630, 639, 648, 657, 666, 675, 684, 693, 702, 711, 720, 730, 740, 750, 760, 770, 780, 790, 800, 810, 820, 830, 840, 850, 860, 870, 880, 891, 902, 913, 924, 935, 946, 957, 968, 979, 990, 1001, 1012, 1023, 1034, 1045, 1056, 1068, 1080, 1092, 1104, 1116, 1128, 1140, 1152, 1164, 1176, 1188, 1200, 1212, 1224, 1236, 1248, 1261, 1274, 1287, 1300, 1313, 1326, 1339, 1352, 1365, 1378, 1391, 1404, 1417, 1430, 1443, 1456, 1470, 1484, 1498, 1512, 1526, 1540, 1554, 1568, 1582, 1596, 1610, 1624, 1638, 1652, 1666, 1680, 1695, 1710, 1725, 1740, 1755, 1770, 1785, 1800, 1815, 1830, 1845, 1860, 1875, 1890, 1905, 1920, 1936, 1952, 1968, 1984, 2000, 2016, 2032, 2048, 2064, 2080, 2096, 2112, 2128, 2144, 2160} }; if (amount == 0) return 0; switch (_settings_game.economy.town_cargogen_mode) { case TCGM_ORIGINAL: return GetMonthlyFrom256Tick(AVG[EconomyIsInRecession() ? 1 : 0][amount]); case TCGM_BITCOUNT: { uint amt = (amount + 7) / 8; if (EconomyIsInRecession()) amt += 2; else amt *= 2; return GetMonthlyFrom256Tick(amt * 16); } default: NOT_REACHED(); } return 0; } static void AddProducedCargo_Town(TileIndex tile, CargoArray &produced) { if (!IsHouseCompleted(tile)) return; HouseID house_id = GetHouseType(tile); const HouseSpec *hs = HouseSpec::Get(house_id); Town *t = Town::GetByTile(tile); if (HasBit(hs->callback_mask, CBM_HOUSE_PRODUCE_CARGO)) { for (uint i = 0; i < 256; i++) { uint16 callback = GetHouseCallback(CBID_HOUSE_PRODUCE_CARGO, i, 0, house_id, t, tile); if (callback == CALLBACK_FAILED || callback == CALLBACK_HOUSEPRODCARGO_END) break; CargoID cargo = GetCargoTranslation(GB(callback, 8, 7), hs->grf_prop.grffile); if (cargo == CT_INVALID) continue; produced[cargo] += GetMonthlyFrom256Tick((uint)GB(callback, 0, 8)) ; } } else { produced[CT_PASSENGERS] += GetAverageHouseProduction(hs->population); produced[CT_MAIL] += GetAverageHouseProduction(hs->mail_generation); } } // Similar to ::GetProductionAroundTiles but counts production total CargoArray GetProductionAroundTiles(TileIndex tile, int w, int h, int rad) { static const uint HQ_AVG_POP[2][5] = { {48, 64, 84, 128, 384}, {48, 64, 84, 128, 256}, }; static const uint HQ_AVG_MAIL[2][5] = { {36, 48, 64, 96, 264}, {36, 48, 64, 96, 196} }; CargoArray produced; std::set industries; TileArea ta = TileArea(tile, w, h).Expand(rad); /* Loop over all tiles to get the produced cargo of * everything except industries */ TILE_AREA_LOOP(tile, ta) { switch (GetTileType(tile)) { case MP_INDUSTRY: industries.insert(GetIndustryIndex(tile)); break; case MP_HOUSE: AddProducedCargo_Town(tile, produced); break; case MP_OBJECT: if (IsObjectType(tile, OBJECT_HQ)) { produced[CT_PASSENGERS] += GetMonthlyFrom256Tick(HQ_AVG_POP[EconomyIsInRecession() ? 1 : 0][GetAnimationFrame(tile)]); produced[CT_MAIL] += GetMonthlyFrom256Tick(HQ_AVG_MAIL[EconomyIsInRecession() ? 1 : 0][GetAnimationFrame(tile)]); } default: break; } } /* Loop over the seen industries. They produce cargo for * anything that is within 'rad' of any one of their tiles. */ for (IndustryID industry : industries) { const Industry *i = Industry::Get(industry); /* Skip industry with neutral station */ if (i->neutral_station != nullptr && !_settings_game.station.serve_neutral_industries) continue; for (uint j = 0; j < lengthof(i->produced_cargo); j++) { CargoID cargo = i->produced_cargo[j]; if (cargo != CT_INVALID) produced[cargo] += ((uint)i->last_month_production[j]) << 8; } } return produced; } std::string GetStationCoverageProductionText(TileIndex tile, int w, int h, int rad, StationCoverageType sct) { auto production = GetProductionAroundTiles(tile, w, h, rad); std::ostringstream s; char buffer[DRAW_STRING_BUFFER]; GetString(buffer, STR_CM_STATION_BUILD_SUPPLIES, lastof(buffer)); s << buffer; bool first = true; for (CargoID i = 0; i < NUM_CARGO; i++) { switch (sct) { case SCT_PASSENGERS_ONLY: if (!IsCargoInClass(i, CC_PASSENGERS)) continue; break; case SCT_NON_PASSENGERS_ONLY: if (IsCargoInClass(i, CC_PASSENGERS)) continue; break; case SCT_ALL: break; default: NOT_REACHED(); } if (production[i] == 0) continue; if (!first) s << ", "; first = false; SetDParam(0, i); SetDParam(1, production[i] >> 8); // GetString(buffer, STR_CM_STATION_BUILD_SUPPLIES_CARGO, lastof(buffer)); GetString(buffer, STR_JUST_CARGO, lastof(buffer)); s << buffer; } return s.str(); } } // namespace citymania