diff --git a/src/command.cpp b/src/command.cpp index a67e83ee9f..4f214f7e77 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -126,6 +126,8 @@ CommandProc CmdRenamePresident; CommandProc CmdRenameStation; CommandProc CmdRenameDepot; +CommandProc CmdSetStationCargoAllowedSupply; + CommandProc CmdPlaceSign; CommandProc CmdRenameSign; @@ -348,6 +350,8 @@ static const Command _command_proc_table[] = { DEF_CMD(CmdRenameStation, 0, CMDT_OTHER_MANAGEMENT ), // CMD_RENAME_STATION DEF_CMD(CmdRenameDepot, 0, CMDT_OTHER_MANAGEMENT ), // CMD_RENAME_DEPOT + DEF_CMD(CmdSetStationCargoAllowedSupply, 0, CMDT_OTHER_MANAGEMENT ), // CMD_SET_STATION_CARGO_ALLOWED_SUPPLY + DEF_CMD(CmdPlaceSign, CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_PLACE_SIGN DEF_CMD(CmdRenameSign, CMD_DEITY, CMDT_OTHER_MANAGEMENT ), // CMD_RENAME_SIGN diff --git a/src/command_type.h b/src/command_type.h index bf52d7c4e3..b461f25958 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -289,6 +289,7 @@ enum Commands { CMD_RENAME_PRESIDENT, ///< change the president name CMD_RENAME_STATION, ///< rename a station CMD_RENAME_DEPOT, ///< rename a depot + CMD_SET_STATION_CARGO_ALLOWED_SUPPLY, ///< set station cargo allowed supply CMD_PLACE_SIGN, ///< place a sign CMD_RENAME_SIGN, ///< rename a sign diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp index 6e17932ac8..fa1761233c 100644 --- a/src/newgrf_station.cpp +++ b/src/newgrf_station.cpp @@ -425,10 +425,10 @@ uint32 Station::GetNewGRFVariable(const ResolverObject &object, byte variable, b switch (variable) { case 0x60: return min(ge->cargo.TotalCount(), 4095); - case 0x61: return ge->HasVehicleEverTriedLoading() ? ge->time_since_pickup : 0; + case 0x61: return ge->HasVehicleEverTriedLoading() && ge->IsSupplyAllowed() ? ge->time_since_pickup : 0; case 0x62: return ge->HasRating() ? ge->rating : 0xFFFFFFFF; case 0x63: return ge->cargo.DaysInTransit(); - case 0x64: return ge->HasVehicleEverTriedLoading() ? ge->last_speed | (ge->last_age << 8) : 0xFF00; + case 0x64: return ge->HasVehicleEverTriedLoading() && ge->IsSupplyAllowed() ? ge->last_speed | (ge->last_age << 8) : 0xFF00; case 0x65: return GB(ge->status, GoodsEntry::GES_ACCEPTANCE, 1) << 3; case 0x69: { assert_compile((int)GoodsEntry::GES_EVER_ACCEPTED + 1 == (int)GoodsEntry::GES_LAST_MONTH); diff --git a/src/saveload/extended_ver_sl.cpp b/src/saveload/extended_ver_sl.cpp index 4aa1e30fdb..d0681a2557 100644 --- a/src/saveload/extended_ver_sl.cpp +++ b/src/saveload/extended_ver_sl.cpp @@ -112,6 +112,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = { { XSLFI_DEBUG, XSCF_IGNORABLE_ALL, 1, 1, "debug", nullptr, nullptr, "DBGL" }, { XSLFI_FLOW_STAT_FLAGS, XSCF_NULL, 1, 1, "flow_stat_flags", nullptr, nullptr, nullptr }, { XSLFI_SPEED_RESTRICTION, XSCF_NULL, 1, 1, "speed_restriction", nullptr, nullptr, "VESR" }, + { XSLFI_STATION_GOODS_EXTRA, XSCF_NULL, 1, 1, "station_goods_extra", nullptr, nullptr, nullptr }, { XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker }; diff --git a/src/saveload/extended_ver_sl.h b/src/saveload/extended_ver_sl.h index f2b9dfcb00..4e29146fb5 100644 --- a/src/saveload/extended_ver_sl.h +++ b/src/saveload/extended_ver_sl.h @@ -77,6 +77,7 @@ enum SlXvFeatureIndex { XSLFI_DEBUG, ///< Debugging info XSLFI_FLOW_STAT_FLAGS, ///< FlowStat flags XSLFI_SPEED_RESTRICTION, ///< Train speed restrictions + XSLFI_STATION_GOODS_EXTRA, ///< Extra station goods entry statuses XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit XSLFI_HEIGHT_8_BIT, ///< Map tile height is 8 bit instead of 4 bit, but savegame version may be before this became true in trunk diff --git a/src/station_base.h b/src/station_base.h index 10e28ccad3..bd5c01f2f7 100644 --- a/src/station_base.h +++ b/src/station_base.h @@ -521,6 +521,11 @@ struct GoodsEntry { * This flag is reset every STATION_ACCEPTANCE_TICKS ticks. */ GES_ACCEPTED_BIGTICK, + + /** + * Set when cargo is not permitted to be supplied by nearby industries/houses. + */ + GES_NO_CARGO_SUPPLY = 7, }; GoodsEntry() : @@ -574,6 +579,11 @@ struct GoodsEntry { FlowStatMap flows; ///< Planned flows through this station. uint max_waiting_cargo; ///< Max cargo from this station waiting at any station. + bool IsSupplyAllowed() const + { + return !HasBit(this->status, GES_NO_CARGO_SUPPLY); + } + /** * Reports whether a vehicle has ever tried to load the cargo at this station. * This does not imply that there was cargo available for loading. Refer to GES_RATING for that. diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 49a3c624e2..fc2b286544 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -3740,7 +3740,7 @@ static void UpdateStationRating(Station *st) * 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; + uint last_speed = ge->HasVehicleEverTriedLoading() && ge->IsSupplyAllowed() ? ge->last_speed : 0xFF; uint32 var18 = min(ge->time_since_pickup, 0xFF) | (min(ge->max_waiting_cargo, 0xFFFF) << 8) | (min(last_speed, 0xFF) << 24); /* Convert to the 'old' vehicle types */ @@ -4179,6 +4179,37 @@ CommandCost CmdRenameStation(TileIndex tile, DoCommandFlag flags, uint32 p1, uin return CommandCost(); } +/** + * Change whether a cargo may be supplied to a station + * @param tile unused + * @param flags operation to perform + * @param p1 station ID + * @param p2 various bitstuffed elements + * - p2 = (bit 0- 7) - cargo ID + * - p2 = (bit 8) - whether to allow supply + * @param text unused + * @return the cost of this operation or an error + */ +CommandCost CmdSetStationCargoAllowedSupply(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +{ + Station *st = Station::GetIfValid(p1); + if (st == nullptr) return CMD_ERROR; + + CommandCost ret = CheckOwnership(st->owner); + if (ret.Failed()) return ret; + + CargoID cid = GB(p2, 0, 8); + if (cid >= NUM_CARGO) return CMD_ERROR; + + if (flags & DC_EXEC) { + GoodsEntry &ge = st->goods[cid]; + SB(ge.status, GoodsEntry::GES_NO_CARGO_SUPPLY, 1, HasBit(p2, 8) ? 0 : 1); + InvalidateWindowData(WC_STATION_VIEW, st->index, -1); + } + + return CommandCost(); +} + static void AddNearbyStationsByCatchment(TileIndex tile, StationList *stations, StationList &nearby) { for (Station *st : nearby) { @@ -4261,6 +4292,8 @@ static bool CanMoveGoodsToStation(const Station *st, CargoID type) /* Lowest possible rating, better not to give cargo anymore. */ if (st->goods[type].rating == 0) return false; + if (!st->goods[type].IsSupplyAllowed()) return false; + /* Selectively servicing stations, and not this one. */ if (_settings_game.order.selectgoods && !st->goods[type].HasVehicleEverTriedLoading()) return false; diff --git a/src/station_gui.cpp b/src/station_gui.cpp index d6878bdfc3..f36a873549 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -1877,7 +1877,11 @@ struct StationViewWindow : public Window { SetDParam(1, lg != nullptr ? lg->Monthly((*lg)[ge->node].Supply()) : 0); SetDParam(2, STR_CARGO_RATING_APPALLING + (ge->rating >> 5)); SetDParam(3, ToPercent8(ge->rating)); - DrawString(r.left + WD_FRAMERECT_LEFT + 6, r.right - WD_FRAMERECT_RIGHT - 6, y, STR_STATION_VIEW_CARGO_SUPPLY_RATING); + int x = DrawString(r.left + WD_FRAMERECT_LEFT + 6, r.right - WD_FRAMERECT_RIGHT - 6, y, STR_STATION_VIEW_CARGO_SUPPLY_RATING); + if (!ge->IsSupplyAllowed() && x != 0) { + int line_y = y + (FONT_HEIGHT_NORMAL / 2) - 1; + GfxDrawLine(r.left + WD_FRAMERECT_LEFT + 6, line_y, x, line_y, PC_WHITE, 1); + } y += FONT_HEIGHT_NORMAL; } return CeilDiv(y - r.top - WD_FRAMERECT_TOP, FONT_HEIGHT_NORMAL); @@ -1998,6 +2002,23 @@ struct StationViewWindow : public Window { ShowStationDepartures((StationID)this->window_number); break; } + + case WID_SV_ACCEPT_RATING_LIST: { + if (this->owner != _local_company || !_ctrl_pressed || this->GetWidget(WID_SV_ACCEPTS_RATINGS)->widget_data == STR_STATION_VIEW_RATINGS_BUTTON) break; + int row = this->GetRowFromWidget(pt.y, WID_SV_ACCEPT_RATING_LIST, WD_FRAMERECT_TOP, FONT_HEIGHT_NORMAL); + if (row < 1) break; + const Station *st = Station::Get(this->window_number); + const CargoSpec *cs; + FOR_ALL_SORTED_STANDARD_CARGOSPECS(cs) { + const GoodsEntry *ge = &st->goods[cs->Index()]; + if (!ge->HasRating()) continue; + if (row == 1) { + DoCommandP(0, this->window_number, cs->Index() | (ge->IsSupplyAllowed() ? 0 : 1 << 8), CMD_SET_STATION_CARGO_ALLOWED_SUPPLY | CMD_MSG(STR_ERROR_CAN_T_DO_THIS)); + } + row--; + } + break; + } } }