1
0
Fork 0

Feature: Try to reuse a removed depot when placing a new one. (based on patch by adf88, #6328, #7051)

pull/8480/head
J0anJosep 2021-12-06 14:15:51 +01:00
parent 2ff99e2377
commit 6bdf50ca02
4 changed files with 63 additions and 2 deletions

View File

@ -65,6 +65,20 @@ Depot::~Depot()
InvalidateWindowData(WC_SELECT_DEPOT, this->veh_type); InvalidateWindowData(WC_SELECT_DEPOT, this->veh_type);
} }
/**
* Cancel deletion of this depot (reuse it).
* @param xy New location of the depot.
* @see Depot::IsInUse
* @see Depot::Disuse
*/
void Depot::Reuse(TileIndex xy)
{
this->delete_ctr = 0;
this->xy = xy;
this->ta.tile = xy;
this->ta.h = this->ta.w = 1;
}
/** /**
* Schedule deletion of this depot. * Schedule deletion of this depot.
* *
@ -73,6 +87,7 @@ Depot::~Depot()
* placed again later without messing vehicle orders. * placed again later without messing vehicle orders.
* *
* @see Depot::IsInUse * @see Depot::IsInUse
* @see Depot::Reuse
*/ */
void Depot::Disuse() void Depot::Disuse()
{ {
@ -112,13 +127,19 @@ CommandCost Depot::BeforeAddTiles(TileArea ta)
{ {
assert(ta.tile != INVALID_TILE); assert(ta.tile != INVALID_TILE);
if (this->ta.tile != INVALID_TILE) { if (this->ta.tile != INVALID_TILE && this->IsInUse()) {
/* Important when the old rect is completely inside the new rect, resp. the old one was empty. */ /* Important when the old rect is completely inside the new rect, resp. the old one was empty. */
ta.Add(this->ta.tile); ta.Add(this->ta.tile);
ta.Add(TileAddXY(this->ta.tile, this->ta.w - 1, this->ta.h - 1)); ta.Add(TileAddXY(this->ta.tile, this->ta.w - 1, this->ta.h - 1));
} }
if ((ta.w > _settings_game.depot.depot_spread) || (ta.h > _settings_game.depot.depot_spread)) { /* A max depot spread of 1 for VEH_SHIP is a special case,
* as ship depots consist of two tiles. */
if (this->veh_type == VEH_SHIP && _settings_game.depot.depot_spread == 1) {
/* (ta.w, ta.h) must be equal to (1, 2) or (2, 1).
* This means that ta.w * ta.h must be equal to 2. */
if (ta.w * ta.h != 2) return_cmd_error(STR_ERROR_DEPOT_TOO_SPREAD_OUT);
} else if (std::max(ta.w, ta.h) > _settings_game.depot.depot_spread) {
return_cmd_error(STR_ERROR_DEPOT_TOO_SPREAD_OUT); return_cmd_error(STR_ERROR_DEPOT_TOO_SPREAD_OUT);
} }
return CommandCost(); return CommandCost();
@ -158,8 +179,13 @@ void Depot::AfterAddRemove(TileArea ta, bool adding)
} else { } else {
assert(this->IsInUse()); assert(this->IsInUse());
this->Disuse(); this->Disuse();
TileIndex old_tile = this->xy;
this->RescanDepotTiles();
assert(this->depot_tiles.empty());
this->xy = old_tile;
} }
InvalidateWindowData(WC_VEHICLE_DEPOT, this->index);
InvalidateWindowData(WC_SELECT_DEPOT, veh_type); InvalidateWindowData(WC_SELECT_DEPOT, veh_type);
} }

View File

@ -78,12 +78,14 @@ struct Depot : DepotPool::PoolItem<&_depot_pool> {
* and the depot awaits to be deleted. * and the depot awaits to be deleted.
* @return true iff still in use * @return true iff still in use
* @see Depot::Disuse * @see Depot::Disuse
* @see Depot::Reuse
*/ */
inline bool IsInUse() const inline bool IsInUse() const
{ {
return this->delete_ctr == 0; return this->delete_ctr == 0;
} }
void Reuse(TileIndex xy);
void Disuse(); void Disuse();
/* Check we can add some tiles to this depot. */ /* Check we can add some tiles to this depot. */

View File

@ -77,6 +77,23 @@ CommandCost CmdRenameDepot(DoCommandFlag flags, DepotID depot_id, const std::str
return CommandCost(); return CommandCost();
} }
/**
* Find a demolished depot close to a tile.
* @param ta Tile area to search for.
* @param type Depot type.
* @param cid Previous owner of the depot.
* @return The index of a demolished nearby depot, or INVALID_DEPOT if none.
*/
DepotID FindDeletedDepotCloseTo(TileArea ta, VehicleType type, CompanyID cid)
{
for (Depot *depot : Depot::Iterate()) {
if (depot->IsInUse() || depot->veh_type != type || depot->owner != cid) continue;
if (ta.Contains(depot->xy)) return depot->index;
}
return INVALID_DEPOT;
}
void OnTick_Depot() void OnTick_Depot()
{ {
if (_game_mode == GM_EDITOR) return; if (_game_mode == GM_EDITOR) return;
@ -128,6 +145,12 @@ CommandCost FindJoiningDepot(TileArea ta, VehicleType veh_type, DepotID &join_to
} }
} }
if (closest_depot == INVALID_DEPOT) {
/* Check for close unused depots. */
check_area.Expand(7); // total distance of 8
closest_depot = FindDeletedDepotCloseTo(check_area, veh_type, _current_company);
}
if (closest_depot != INVALID_DEPOT) { if (closest_depot != INVALID_DEPOT) {
assert(Depot::IsValidID(closest_depot)); assert(Depot::IsValidID(closest_depot));
depot = Depot::Get(closest_depot); depot = Depot::Get(closest_depot);
@ -151,6 +174,7 @@ CommandCost FindJoiningDepot(TileArea ta, VehicleType veh_type, DepotID &join_to
depot = Depot::Get(join_to); depot = Depot::Get(join_to);
assert(depot->owner == _current_company); assert(depot->owner == _current_company);
assert(depot->veh_type == veh_type); assert(depot->veh_type == veh_type);
if (!depot->IsInUse() && (flags & DC_EXEC)) depot->Reuse(ta.tile);
return depot->BeforeAddTiles(ta); return depot->BeforeAddTiles(ta);
} }

View File

@ -1249,6 +1249,15 @@ static const Depot *FindDepotsNearby(TileArea ta, VehicleType veh_type, bool dis
TileIndex tile = TileAddByDir(andd.search_area.tile, DIR_N); TileIndex tile = TileAddByDir(andd.search_area.tile, DIR_N);
CircularTileSearch(&tile, max_dist, ta.w, ta.h, AddNearbyDepot, &andd); CircularTileSearch(&tile, max_dist, ta.w, ta.h, AddNearbyDepot, &andd);
/* Add reusable depots. */
ta.Expand(8);
for (Depot *d : Depot::Iterate()) {
if (d->IsInUse()) continue;
if (d->veh_type != veh_type || d->owner != _current_company) continue;
if (!ta.Contains(d->xy)) continue;
_depots_nearby_list.push_back(d->index);
}
return nullptr; return nullptr;
} }