From c405a59bbc67a374a4796c3befb6c08d69ab1799 Mon Sep 17 00:00:00 2001 From: J0anJosep Date: Mon, 8 Apr 2024 18:01:07 +0200 Subject: [PATCH] Prepare: Add some members to depot struct. --- src/build_vehicle_gui.cpp | 48 +++++++------ src/depot.cpp | 100 ++++++++++++++++++++++++++-- src/depot_base.h | 34 +++++++++- src/depot_cmd.cpp | 5 +- src/depot_gui.cpp | 13 ++-- src/economy.cpp | 7 ++ src/order_cmd.cpp | 23 +------ src/rail.h | 13 ++++ src/rail_cmd.cpp | 2 +- src/road.h | 13 ++++ src/road_cmd.cpp | 2 +- src/saveload/afterload.cpp | 34 ++++++++++ src/saveload/depot_sl.cpp | 6 ++ src/saveload/oldloader_sl.cpp | 2 + src/saveload/saveload.h | 1 + src/script/api/script_depotlist.cpp | 31 ++------- src/station.cpp | 10 ++- src/water_cmd.cpp | 2 +- 18 files changed, 259 insertions(+), 87 deletions(-) diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index abccb01f20..45a93c0c44 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -1168,8 +1168,8 @@ enum BuildVehicleHotkeys { struct BuildVehicleWindow : Window { VehicleType vehicle_type; ///< Type of vehicles shown in the window. union { - RailType railtype; ///< Rail type to show, or #INVALID_RAILTYPE. - RoadType roadtype; ///< Road type to show, or #INVALID_ROADTYPE. + RailTypes railtypes; ///< Rail types to show, or #INVALID_RAILTYPES. + RoadTypes roadtypes; ///< Road types to show, or #INVALID_ROADTYPES. } filter; ///< Filter to apply. bool descending_sort_order; ///< Sort direction, @see _engine_sort_direction uint8_t sort_criteria; ///< Current sort criterium. @@ -1248,7 +1248,7 @@ struct BuildVehicleWindow : Window { this->vehicle_editbox.cancel_button = QueryString::ACTION_CLEAR; Depot *depot = Depot::GetIfValid(depot_id); - this->owner = (depot != nullptr) ? GetTileOwner(depot->xy) : _local_company; + this->owner = depot != nullptr ? depot->owner : _local_company; this->eng_list.ForceRebuild(); this->GenerateBuildList(); // generate the list, since we need it in the next line @@ -1263,28 +1263,16 @@ struct BuildVehicleWindow : Window { /** Set the filter type according to the depot type */ void UpdateFilterByTile() { - TileIndex tile = INVALID_TILE; - if (!this->listview_mode) tile = Depot::Get(this->window_number)->xy; + Depot *depot = this->listview_mode ? nullptr : Depot::Get(this->window_number); switch (this->vehicle_type) { default: NOT_REACHED(); case VEH_TRAIN: - if (this->listview_mode) { - this->filter.railtype = INVALID_RAILTYPE; - } else { - this->filter.railtype = GetRailType(tile); - } + this->filter.railtypes = this->listview_mode ? INVALID_RAILTYPES : depot->r_types.rail_types; break; case VEH_ROAD: - if (this->listview_mode) { - this->filter.roadtype = INVALID_ROADTYPE; - } else { - this->filter.roadtype = GetRoadTypeRoad(tile); - if (this->filter.roadtype == INVALID_ROADTYPE) { - this->filter.roadtype = GetRoadTypeTram(tile); - } - } + this->filter.roadtypes = this->listview_mode ? INVALID_ROADTYPES : depot->r_types.road_types; break; case VEH_SHIP: @@ -1403,7 +1391,7 @@ struct BuildVehicleWindow : Window { EngineID eid = e->index; const RailVehicleInfo *rvi = &e->u.rail; - if (this->filter.railtype != INVALID_RAILTYPE && !HasPowerOnRail(rvi->railtype, this->filter.railtype)) continue; + if (!this->listview_mode && !HasPowerOnRails(rvi->railtype, this->filter.railtypes)) continue; if (!IsEngineBuildable(eid, VEH_TRAIN, _local_company)) continue; /* Filter now! So num_engines and num_wagons is valid */ @@ -1463,7 +1451,7 @@ struct BuildVehicleWindow : Window { if (!this->show_hidden_engines && e->IsVariantHidden(_local_company)) continue; EngineID eid = e->index; if (!IsEngineBuildable(eid, VEH_ROAD, _local_company)) continue; - if (this->filter.roadtype != INVALID_ROADTYPE && !HasPowerOnRoad(e->u.road.roadtype, this->filter.roadtype)) continue; + if (!this->listview_mode && !HasPowerOnRoads(e->u.road.roadtype, this->filter.roadtypes)) continue; /* Filter by name or NewGRF extra text */ if (!FilterByText(e)) continue; @@ -1503,7 +1491,7 @@ struct BuildVehicleWindow : Window { this->eng_list.clear(); - const Station *st = this->listview_mode ? nullptr : Station::GetByTile(this->window_number); + const Station *st = this->listview_mode ? nullptr : Depot::Get(this->window_number)->station; /* Make list of all available planes. * Also check to see if the previously selected plane is still available, @@ -1743,11 +1731,21 @@ struct BuildVehicleWindow : Window { switch (widget) { case WID_BV_CAPTION: if (this->vehicle_type == VEH_TRAIN && !this->listview_mode) { - const RailTypeInfo *rti = GetRailTypeInfo(this->filter.railtype); - SetDParam(0, rti->strings.build_caption); + uint num_railtypes = CountBits(this->filter.railtypes); + if (num_railtypes != 1) { + SetDParam(0, STR_BUY_VEHICLE_TRAIN_ALL_CAPTION); + } else { + const RailTypeInfo *rti = GetRailTypeInfo((RailType)FindFirstBit(this->filter.railtypes)); + SetDParam(0, rti->strings.build_caption); + } } else if (this->vehicle_type == VEH_ROAD && !this->listview_mode) { - const RoadTypeInfo *rti = GetRoadTypeInfo(this->filter.roadtype); - SetDParam(0, rti->strings.build_caption); + uint num_roadtypes = CountBits(this->filter.roadtypes); + if (num_roadtypes != 1) { + SetDParam(0, STR_BUY_VEHICLE_ROAD_VEHICLE_CAPTION); + } else { + const RoadTypeInfo *rti = GetRoadTypeInfo((RoadType)FindFirstBit(this->filter.roadtypes)); + SetDParam(0, rti->strings.build_caption); + } } else { SetDParam(0, (this->listview_mode ? STR_VEHICLE_LIST_AVAILABLE_TRAINS : STR_BUY_VEHICLE_TRAIN_ALL_CAPTION) + this->vehicle_type); } diff --git a/src/depot.cpp b/src/depot.cpp index 49297f91fa..bc5f62c8bd 100644 --- a/src/depot.cpp +++ b/src/depot.cpp @@ -15,9 +15,12 @@ #include "core/pool_func.hpp" #include "vehicle_gui.h" #include "vehiclelist.h" +#include "command_func.h" #include "safeguards.h" +#include "table/strings.h" + /** All our depots tucked away in a pool. */ DepotPool _depot_pool("Depot"); INSTANTIATE_POOL_METHODS(Depot) @@ -29,8 +32,9 @@ Depot::~Depot() { if (CleaningPool()) return; - if (!IsDepotTile(this->xy) || GetDepotIndex(this->xy) != this->index) { - /* It can happen there is no depot here anymore (TTO/TTD savegames) */ + if (this->owner == INVALID_OWNER) { + /* Deleting depot remnants of TTD savegames while saveload conversion. */ + assert(this->veh_type == VEH_INVALID); return; } @@ -44,6 +48,94 @@ Depot::~Depot() CloseWindowById(WC_VEHICLE_DEPOT, this->index); /* Delete the depot list */ - VehicleType vt = GetDepotVehicleType(this->xy); - CloseWindowById(GetWindowClassForVehicleType(vt), VehicleListIdentifier(VL_DEPOT_LIST, vt, GetTileOwner(this->xy), this->index).Pack()); + CloseWindowById(GetWindowClassForVehicleType(this->veh_type), + VehicleListIdentifier(VL_DEPOT_LIST, + this->veh_type, this->owner, this->index).Pack()); +} + +/** + * Check we can add some tiles to this depot. + * @param ta The affected tile area. + * @return Whether it is possible to add the tiles or an error message. + */ +CommandCost Depot::BeforeAddTiles(TileArea ta) +{ + assert(ta.tile != INVALID_TILE); + + if (this->ta.tile != INVALID_TILE) { + /* Important when the old rect is completely inside the new rect, resp. the old one was empty. */ + ta.Add(this->ta.tile); + ta.Add(TileAddXY(this->ta.tile, this->ta.w - 1, this->ta.h - 1)); + } + + return CommandCost(); +} + +/** + * Add some tiles to this depot and rescan area for depot_tiles. + * @param ta Affected tile area + * @param adding Whether adding or removing depot tiles. + */ +void Depot::AfterAddRemove(TileArea ta, bool adding) +{ + assert(ta.tile != INVALID_TILE); + + if (adding) { + if (this->ta.tile != INVALID_TILE) { + ta.Add(this->ta.tile); + ta.Add(TileAddXY(this->ta.tile, this->ta.w - 1, this->ta.h - 1)); + } + } else { + ta = this->ta; + } + + this->ta.Clear(); + + for (TileIndex tile : ta) { + if (!IsDepotTile(tile)) continue; + if (GetDepotIndex(tile) != this->index) continue; + this->ta.Add(tile); + } + + if (this->ta.tile != INVALID_TILE) { + this->RescanDepotTiles(); + assert(!this->depot_tiles.empty()); + this->xy = this->depot_tiles[0]; + } else { + delete this; + } +} + +/** + * Rescan depot_tiles. Done after AfterAddRemove and SaveLoad. + * Updates the tiles of the depot and its railtypes/roadtypes... + */ +void Depot::RescanDepotTiles() +{ + this->depot_tiles.clear(); + RailTypes old_rail_types = this->r_types.rail_types; + this->r_types.rail_types = RAILTYPES_NONE; + + for (TileIndex tile : this->ta) { + if (!IsDepotTile(tile)) continue; + if (GetDepotIndex(tile) != this->index) continue; + this->depot_tiles.push_back(tile); + switch (veh_type) { + case VEH_ROAD: + this->r_types.road_types |= GetPresentRoadTypes(tile); + break; + case VEH_TRAIN: + this->r_types.rail_types |= (RailTypes)(1 << GetRailType(tile)); + break; + case VEH_SHIP: + /* Mark this ship depot has at least one part, so ships can be built. */ + this->r_types.rail_types |= INVALID_RAILTYPES; + break; + default: break; + } + } + + if (old_rail_types != this->r_types.rail_types) { + InvalidateWindowData(WC_BUILD_VEHICLE, this->index, 0, true); + } } diff --git a/src/depot_base.h b/src/depot_base.h index 1d8330fc74..66c6dc3472 100644 --- a/src/depot_base.h +++ b/src/depot_base.h @@ -13,10 +13,14 @@ #include "depot_map.h" #include "core/pool_type.hpp" #include "timer/timer_game_calendar.h" +#include "rail_type.h" +#include "road_type.h" typedef Pool DepotPool; extern DepotPool _depot_pool; +class CommandCost; + struct Depot : DepotPool::PoolItem<&_depot_pool> { /* DepotID index member of DepotPool is 2 bytes. */ uint16_t town_cn; ///< The N-1th depot for this town (consecutive number) @@ -25,11 +29,30 @@ struct Depot : DepotPool::PoolItem<&_depot_pool> { std::string name; TimerGameCalendar::Date build_date; ///< Date of construction - Depot(TileIndex xy = INVALID_TILE) : xy(xy) {} + VehicleType veh_type; ///< Vehicle type of the depot. + Owner owner; ///< Owner of the depot. + Station *station; ///< For aircraft, station associated with this hangar. + + union { + RoadTypes road_types; + RailTypes rail_types; + } r_types; + + TileArea ta; + std::vector depot_tiles; + + Depot(TileIndex xy = INVALID_TILE, VehicleType type = VEH_INVALID, Owner owner = INVALID_OWNER, Station *station = nullptr) : + xy(xy), + veh_type(type), + owner(owner), + station(station), + ta(xy, 1, 1) {} + ~Depot(); static inline Depot *GetByTile(TileIndex tile) { + assert(Depot::IsValidID(GetDepotIndex(tile))); return Depot::Get(GetDepotIndex(tile)); } @@ -43,6 +66,15 @@ struct Depot : DepotPool::PoolItem<&_depot_pool> { { return GetTileType(d->xy) == GetTileType(this->xy); } + + /* Check we can add some tiles to this depot. */ + CommandCost BeforeAddTiles(TileArea ta); + + /* Add some tiles to this depot and rescan area for depot_tiles. */ + void AfterAddRemove(TileArea ta, bool adding); + + /* Rescan depot_tiles. Done after AfterAddRemove and SaveLoad. */ + void RescanDepotTiles(); }; #endif /* DEPOT_BASE_H */ diff --git a/src/depot_cmd.cpp b/src/depot_cmd.cpp index 1e1700f6cb..5b29591616 100644 --- a/src/depot_cmd.cpp +++ b/src/depot_cmd.cpp @@ -48,7 +48,7 @@ CommandCost CmdRenameDepot(DoCommandFlag flags, DepotID depot_id, const std::str Depot *d = Depot::GetIfValid(depot_id); if (d == nullptr) return CMD_ERROR; - CommandCost ret = CheckTileOwnership(d->xy); + CommandCost ret = CheckOwnership(d->owner); if (ret.Failed()) return ret; bool reset = text.empty(); @@ -71,8 +71,7 @@ CommandCost CmdRenameDepot(DoCommandFlag flags, DepotID depot_id, const std::str SetWindowDirty(WC_VEHICLE_DEPOT, d->index); /* Update the depot list */ - VehicleType vt = GetDepotVehicleType(d->xy); - SetWindowDirty(GetWindowClassForVehicleType(vt), VehicleListIdentifier(VL_DEPOT_LIST, vt, GetTileOwner(d->xy), d->index).Pack()); + SetWindowDirty(GetWindowClassForVehicleType(d->veh_type), VehicleListIdentifier(VL_DEPOT_LIST, d->veh_type, d->owner, d->index).Pack()); } return CommandCost(); } diff --git a/src/depot_gui.cpp b/src/depot_gui.cpp index 7364840bff..7c27f92c96 100644 --- a/src/depot_gui.cpp +++ b/src/depot_gui.cpp @@ -29,6 +29,7 @@ #include "zoom_func.h" #include "error.h" #include "depot_cmd.h" +#include "station_base.h" #include "train_cmd.h" #include "vehicle_cmd.h" #include "core/geometry_func.hpp" @@ -270,13 +271,13 @@ struct DepotWindow : Window { { assert(Depot::IsValidID(depot_id)); Depot *depot = Depot::Get(depot_id); - assert(IsCompanyBuildableVehicleType(GetDepotVehicleType(depot->xy))); + assert(IsCompanyBuildableVehicleType(depot->veh_type)); this->sel = INVALID_VEHICLE; this->vehicle_over = INVALID_VEHICLE; this->generate_list = true; this->hovered_widget = -1; - this->type = GetDepotVehicleType(depot->xy); + this->type = depot->veh_type; this->num_columns = 1; // for non-trains this gets set in FinishInitNested() this->unitnumber_digits = 2; @@ -292,7 +293,7 @@ struct DepotWindow : Window { this->SetupWidgetData(this->type); this->FinishInitNested(depot_id); - this->owner = GetTileOwner(depot->xy); + this->owner = depot->owner; OrderBackup::Reset(); } @@ -428,7 +429,7 @@ struct DepotWindow : Window { if (widget != WID_D_CAPTION) return; SetDParam(0, this->type); - SetDParam(1, (this->type == VEH_AIRCRAFT) ? GetStationIndex(Depot::Get(this->window_number)->xy) : this->window_number); + SetDParam(1, (this->type == VEH_AIRCRAFT) ? Depot::Get(this->window_number)->station->index : this->window_number); } struct GetDepotVehiclePtData { @@ -1121,7 +1122,7 @@ static void DepotSellAllConfirmationCallback(Window *win, bool confirmed) if (confirmed) { assert(Depot::IsValidID(win->window_number)); Depot *d = Depot::Get(win->window_number); - Command::Post(d->xy, GetDepotVehicleType(d->xy)); + Command::Post(d->xy, d->veh_type); } } @@ -1135,7 +1136,7 @@ void ShowDepotWindow(DepotID depot_id) if (BringWindowToFrontById(WC_VEHICLE_DEPOT, depot_id) != nullptr) return; Depot *d = Depot::Get(depot_id); - switch (GetDepotVehicleType(d->xy)) { + switch (d->veh_type) { default: NOT_REACHED(); case VEH_TRAIN: new DepotWindow(_train_depot_desc, depot_id); break; case VEH_ROAD: new DepotWindow(_road_depot_desc, depot_id); break; diff --git a/src/economy.cpp b/src/economy.cpp index cd99094239..5c0d4f7bec 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -55,6 +55,7 @@ #include "timer/timer.h" #include "timer/timer_game_calendar.h" #include "timer/timer_game_economy.h" +#include "depot_base.h" #include "table/strings.h" #include "table/pricebase.h" @@ -374,6 +375,12 @@ void ChangeOwnershipOfCompanyItems(Owner old_owner, Owner new_owner) } if (new_owner == INVALID_OWNER) RebuildSubsidisedSourceAndDestinationCache(); + for (Depot *dep : Depot::Iterate()) { + if (dep->owner == old_owner && new_owner != INVALID_OWNER) { + dep->owner = new_owner; + } + } + /* Take care of rating and transport rights in towns */ for (Town *t : Town::Iterate()) { /* If a company takes over, give the ratings to that company. */ diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 070b0d84b1..9252e3d516 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -789,28 +789,11 @@ CommandCost CmdInsertOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID se if (dp == nullptr) return CMD_ERROR; - ret = CheckOwnership(GetTileOwner(dp->xy)); + ret = CheckOwnership(dp->owner); if (ret.Failed()) return ret; - switch (v->type) { - case VEH_TRAIN: - if (!IsRailDepotTile(dp->xy)) return CMD_ERROR; - break; - - case VEH_ROAD: - if (!IsRoadDepotTile(dp->xy)) return CMD_ERROR; - break; - - case VEH_SHIP: - if (!IsShipDepotTile(dp->xy)) return CMD_ERROR; - break; - - case VEH_AIRCRAFT: - if (!CanVehicleUseStation(v, Station::GetByTile(dp->xy)) || !IsHangarTile(dp->xy)) return CMD_ERROR; - break; - - default: return CMD_ERROR; - } + if (v->type != dp->veh_type) return CMD_ERROR; + if (v->type == VEH_AIRCRAFT && !CanVehicleUseStation(v, Station::GetByTile(dp->xy))) return CMD_ERROR; } if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && !v->IsGroundVehicle()) return CMD_ERROR; diff --git a/src/rail.h b/src/rail.h index 149996aae0..f15b9d6703 100644 --- a/src/rail.h +++ b/src/rail.h @@ -337,6 +337,19 @@ inline bool HasPowerOnRail(RailType enginetype, RailType tiletype) return HasBit(GetRailTypeInfo(enginetype)->powered_railtypes, tiletype); } +/** + * Checks if an engine with a given \a enginetype is powered on \a rail_types. + * This would normally just be an equality check, + * but for electric rails (which also support non-electric vehicles). + * @param enginetype The RailType of the engine we are considering. + * @param rail_types The RailTypes we are considering. + * @return Whether the engine got power on this tile. + */ +static inline bool HasPowerOnRails(RailType enginetype, RailTypes rail_types) +{ + return (GetRailTypeInfo(enginetype)->powered_railtypes & rail_types) != 0; +} + /** * Test if a RailType disallows build of level crossings. * @param rt The RailType to check. diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index a44d5d5521..91dff791db 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -1010,7 +1010,7 @@ CommandCost CmdBuildTrainDepot(DoCommandFlag flags, TileIndex tile, RailType rai if (rotate_existing_depot) { SetRailDepotExitDirection(tile, dir); } else { - Depot *d = new Depot(tile); + Depot *d = new Depot(tile, VEH_TRAIN, _current_company); d->build_date = TimerGameCalendar::date; MakeRailDepot(tile, _current_company, d->index, dir, railtype); diff --git a/src/road.h b/src/road.h index 44f4fcd198..c2591d2f1d 100644 --- a/src/road.h +++ b/src/road.h @@ -244,6 +244,19 @@ inline bool HasPowerOnRoad(RoadType enginetype, RoadType tiletype) return HasBit(GetRoadTypeInfo(enginetype)->powered_roadtypes, tiletype); } +/** + * Checks if an engine with a given \a enginetype is powered on \a road_types. + * This would normally just be an equality check, + * but for electrified roads (which also support non-electric vehicles). + * @param enginetype The RoadType of the engine we are considering. + * @param rail_types The RoadTypes we are considering. + * @return Whether the engine got power on this tile. + */ +static inline bool HasPowerOnRoads(RoadType enginetype, RoadTypes road_types) +{ + return (GetRoadTypeInfo(enginetype)->powered_roadtypes & road_types) != 0; +} + /** * Returns the cost of building the specified roadtype. * @param roadtype The roadtype being built. diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index e387deb372..7760a90fbe 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -1188,7 +1188,7 @@ CommandCost CmdBuildRoadDepot(DoCommandFlag flags, TileIndex tile, RoadType rt, if (rotate_existing_depot) { SetRoadDepotExitDirection(tile, dir); } else { - Depot *dep = new Depot(tile); + Depot *dep = new Depot(tile, VEH_ROAD, _current_company); dep->build_date = TimerGameCalendar::date; MakeRoadDepot(tile, _current_company, dep->index, dir, rt); MakeDefaultName(dep); diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp index 3719cbd398..4c13d6985f 100644 --- a/src/saveload/afterload.cpp +++ b/src/saveload/afterload.cpp @@ -294,6 +294,10 @@ static void InitializeWindowsAndCaches() } } + for (Depot *dep : Depot::Iterate()) { + dep->RescanDepotTiles(); + } + RecomputePrices(); GroupStatistics::UpdateAfterLoad(); @@ -2823,6 +2827,36 @@ bool AfterLoadGame() } } + if (IsSavegameVersionBefore(SLV_ADD_MEMBERS_TO_DEPOT_STRUCT)) { + for (Depot *depot : Depot::Iterate()) { + if (!IsDepotTile(depot->xy) || GetDepotIndex(depot->xy) != depot->index) { + /* It can happen there is no depot here anymore (TTO/TTD savegames) */ + depot->veh_type = VEH_INVALID; + depot->owner = INVALID_OWNER; + delete depot; + continue; + } + + depot->owner = GetTileOwner(depot->xy); + depot->veh_type = GetDepotVehicleType(depot->xy); + switch (depot->veh_type) { + case VEH_SHIP: + depot->AfterAddRemove(TileArea(depot->xy, 2, 2), true); + break; + case VEH_ROAD: + case VEH_TRAIN: + depot->AfterAddRemove(TileArea(depot->xy, 1, 1), true); + break; + case VEH_AIRCRAFT: + assert(IsHangarTile(depot->xy)); + depot->station = Station::GetByTile(depot->xy); + break; + default: + break; + } + } + } + /* In old versions it was possible to remove an airport while a plane was * taking off or landing. This gives all kind of problems when building * another airport in the same station so we don't allow that anymore. diff --git a/src/saveload/depot_sl.cpp b/src/saveload/depot_sl.cpp index 2a7859211c..1987605ea3 100644 --- a/src/saveload/depot_sl.cpp +++ b/src/saveload/depot_sl.cpp @@ -27,6 +27,12 @@ static const SaveLoad _depot_desc[] = { SLE_CONDVAR(Depot, town_cn, SLE_UINT16, SLV_141, SL_MAX_VERSION), SLE_CONDSSTR(Depot, name, SLE_STR, SLV_141, SL_MAX_VERSION), SLE_CONDVAR(Depot, build_date, SLE_INT32, SLV_142, SL_MAX_VERSION), + SLE_CONDVAR(Depot, owner, SLE_UINT8, SLV_ADD_MEMBERS_TO_DEPOT_STRUCT, SL_MAX_VERSION), + SLE_CONDVAR(Depot, veh_type, SLE_UINT8, SLV_ADD_MEMBERS_TO_DEPOT_STRUCT, SL_MAX_VERSION), + SLE_CONDVAR(Depot, ta.tile, SLE_UINT32, SLV_ADD_MEMBERS_TO_DEPOT_STRUCT, SL_MAX_VERSION), + SLE_CONDVAR(Depot, ta.w, SLE_FILE_U8 | SLE_VAR_U16, SLV_ADD_MEMBERS_TO_DEPOT_STRUCT, SL_MAX_VERSION), + SLE_CONDVAR(Depot, ta.h, SLE_FILE_U8 | SLE_VAR_U16, SLV_ADD_MEMBERS_TO_DEPOT_STRUCT, SL_MAX_VERSION), + SLE_CONDREF(Depot, station, REF_STATION, SLV_ADD_MEMBERS_TO_DEPOT_STRUCT, SL_MAX_VERSION), }; struct DEPTChunkHandler : ChunkHandler { diff --git a/src/saveload/oldloader_sl.cpp b/src/saveload/oldloader_sl.cpp index 538c1336c3..dc48d09399 100644 --- a/src/saveload/oldloader_sl.cpp +++ b/src/saveload/oldloader_sl.cpp @@ -690,6 +690,8 @@ static bool LoadOldDepot(LoadgameState *ls, int num) if (d->xy != 0) { d->town = RemapTown(d->xy); } else { + d->owner = INVALID_OWNER; + d->veh_type = VEH_INVALID; delete d; } diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h index dd4d9af27f..6e4b830836 100644 --- a/src/saveload/saveload.h +++ b/src/saveload/saveload.h @@ -391,6 +391,7 @@ enum SaveLoadVersion : uint16_t { SLV_ALIGN_WATER_BITS, ///< 315 PR#XXXXX Align some water bits in the map array. SLV_DEPOTS_ALIGN_RAIL_DEPOT_BITS, ///< 316 PR#XXXXX Align one bit for rail depots. + SLV_ADD_MEMBERS_TO_DEPOT_STRUCT, ///< 317 PR#XXXXX Add some members to depot struct. SL_MAX_VERSION, ///< Highest possible saveload version }; diff --git a/src/script/api/script_depotlist.cpp b/src/script/api/script_depotlist.cpp index eb43139165..7997d399e7 100644 --- a/src/script/api/script_depotlist.cpp +++ b/src/script/api/script_depotlist.cpp @@ -17,33 +17,16 @@ ScriptDepotList::ScriptDepotList(ScriptTile::TransportType transport_type) { EnforceDeityOrCompanyModeValid_Void(); - ::TileType tile_type; - switch (transport_type) { - default: return; + static_assert(VEH_TRAIN == (int)ScriptTile::TRANSPORT_RAIL); + static_assert(VEH_ROAD == (int)ScriptTile::TRANSPORT_ROAD); + static_assert(VEH_SHIP == (int)ScriptTile::TRANSPORT_WATER); - case ScriptTile::TRANSPORT_ROAD: tile_type = ::MP_ROAD; break; - case ScriptTile::TRANSPORT_RAIL: tile_type = ::MP_RAILWAY; break; - case ScriptTile::TRANSPORT_WATER: tile_type = ::MP_WATER; break; - - case ScriptTile::TRANSPORT_AIR: { - /* Hangars are not seen as real depots by the depot code. */ - bool is_deity = ScriptCompanyMode::IsDeity(); - CompanyID owner = ScriptObject::GetCompany(); - for (const Station *st : Station::Iterate()) { - if (is_deity || st->owner == owner) { - for (uint i = 0; i < st->airport.GetNumHangars(); i++) { - this->AddItem(st->airport.GetHangarTile(i).base()); - } - } - } - return; - } - } - - /* Handle 'standard' depots. */ bool is_deity = ScriptCompanyMode::IsDeity(); CompanyID owner = ScriptObject::GetCompany(); for (const Depot *depot : Depot::Iterate()) { - if ((is_deity || ::GetTileOwner(depot->xy) == owner) && ::IsTileType(depot->xy, tile_type)) this->AddItem(depot->xy.base()); + if (depot->veh_type != (VehicleType)transport_type || + (!is_deity && ::GetTileOwner(depot->xy) != owner)) continue; + + this->AddItem(depot->xy.base()); } } diff --git a/src/station.cpp b/src/station.cpp index 0ee8f2a605..0d4198ac6c 100644 --- a/src/station.cpp +++ b/src/station.cpp @@ -737,9 +737,17 @@ void Airport::AddHangar() assert(Depot::CanAllocateItem()); assert(this->GetNumHangars() > 0); Station *st = Station::GetByTile(this->GetHangarTile(0)); - this->hangar = new Depot(this->GetHangarTile(0)); + this->hangar = new Depot(this->GetHangarTile(0), VEH_AIRCRAFT, st->owner, st); this->hangar->build_date = st->build_date; this->hangar->town = st->town; + + this->hangar->ta.tile = st->airport.tile; + this->hangar->ta.w = st->airport.w; + this->hangar->ta.h = st->airport.h; + + for (uint i = 0; i < this->GetNumHangars(); i++) { + this->hangar->depot_tiles.push_back(this->GetHangarTile(i)); + } } /** diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index 07078c00f0..54f943451b 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -134,7 +134,7 @@ CommandCost CmdBuildShipDepot(DoCommandFlag flags, TileIndex tile, Axis axis) } if (flags & DC_EXEC) { - Depot *depot = new Depot(tile); + Depot *depot = new Depot(tile, VEH_SHIP, _current_company); depot->build_date = TimerGameCalendar::date; uint new_water_infra = 2 * LOCK_DEPOT_TILE_FACTOR;