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);
}
/**
* 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.
*
@ -73,6 +87,7 @@ Depot::~Depot()
* placed again later without messing vehicle orders.
*
* @see Depot::IsInUse
* @see Depot::Reuse
*/
void Depot::Disuse()
{
@ -112,13 +127,19 @@ CommandCost Depot::BeforeAddTiles(TileArea ta)
{
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. */
ta.Add(this->ta.tile);
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 CommandCost();
@ -158,8 +179,13 @@ void Depot::AfterAddRemove(TileArea ta, bool adding)
} else {
assert(this->IsInUse());
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);
}

View File

@ -78,12 +78,14 @@ struct Depot : DepotPool::PoolItem<&_depot_pool> {
* and the depot awaits to be deleted.
* @return true iff still in use
* @see Depot::Disuse
* @see Depot::Reuse
*/
inline bool IsInUse() const
{
return this->delete_ctr == 0;
}
void Reuse(TileIndex xy);
void Disuse();
/* 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();
}
/**
* 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()
{
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) {
assert(Depot::IsValidID(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);
assert(depot->owner == _current_company);
assert(depot->veh_type == veh_type);
if (!depot->IsInUse() && (flags & DC_EXEC)) depot->Reuse(ta.tile);
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);
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;
}