From 9c02767a927ea5c6e8072e1ffad2a82188fdf00e Mon Sep 17 00:00:00 2001 From: rubidium Date: Sat, 13 Feb 2010 14:02:36 +0000 Subject: [PATCH] (svn r19119) -Fix [FS#3616]: removing towns (in the scenario editor) that had stations/depots refer to them or vehicles were on the town's road could cause a crash --- src/lang/english.txt | 1 + src/town_gui.cpp | 58 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/lang/english.txt b/src/lang/english.txt index 07c7136085..3f599922d3 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -3373,6 +3373,7 @@ STR_ERROR_TOO_MANY_TOWNS :{WHITE}... too STR_ERROR_NO_SPACE_FOR_TOWN :{WHITE}... there is no more space on the map STR_ERROR_TOWN_EXPAND_WARN_NO_ROADS :{WHITE}The town will not build roads. You can enable building of roads via Advanced Settings->Economy->Towns. STR_ERROR_ROAD_WORKS_IN_PROGRESS :{WHITE}Road works in progress +STR_ERROR_TOWN_CAN_T_DELETE :{WHITE}Can't delete this town...{}A station or depot is referring to the town or a town owned tile can't be removed # Industry related errors STR_ERROR_CAN_T_GENERATE_INDUSTRIES :{WHITE}Can't generate industries... diff --git a/src/town_gui.cpp b/src/town_gui.cpp index 2f6bae453b..be4f3b3a82 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -34,6 +34,8 @@ #include "townname_func.h" #include "townname_type.h" #include "core/geometry_func.hpp" +#include "station_base.h" +#include "depot_base.h" #include "table/sprites.h" #include "table/strings.h" @@ -457,11 +459,65 @@ public: break; case TVW_DELETE: // delete town - only available on Scenario editor - delete this->town; + if (this->CanDeleteTown()) { + delete this->town; + } else { + ShowErrorMessage(STR_ERROR_TOWN_CAN_T_DELETE, INVALID_STRING_ID, 0, 0); + } break; } } + /** + * Can we delete the town? + * Or in other words, does anything refer to this town? + * @return true if it's possible + */ + bool CanDeleteTown() const + { + /* Stations refer to towns. */ + const Station *st; + FOR_ALL_STATIONS(st) { + if (st->town == this->town) { + /* Non-oil rig stations are always a problem. */ + if (!(st->facilities & FACIL_AIRPORT) || st->airport_type != AT_OILRIG) return false; + /* We can only automatically delete oil rigs *if* there's no vehicle on them. */ + if (DoCommand(st->airport_tile, 0, 0, DC_NONE, CMD_LANDSCAPE_CLEAR).Failed()) return false; + } + } + + /* Depots refer to towns. */ + const Depot *d; + FOR_ALL_DEPOTS(d) { + if (d->town_index == this->town->index) return false; + } + + /* Check all tiles for town ownership. */ + for (TileIndex tile = 0; tile < MapSize(); ++tile) { + switch (GetTileType(tile)) { + case MP_ROAD: + if (HasTownOwnedRoad(tile) && GetTownIndex(tile) == this->town->index) { + /* Can we clear this tile? */ + if (DoCommand(tile, 0, 0, DC_NONE, CMD_LANDSCAPE_CLEAR).Failed()) return false; + } + break; + + case MP_TUNNELBRIDGE: + if (IsTileOwner(tile, OWNER_TOWN) && + ClosestTownFromTile(tile, UINT_MAX) == this->town) { + /* Can we clear this bridge? */ + if (DoCommand(tile, 0, 0, DC_NONE, CMD_LANDSCAPE_CLEAR).Failed()) return false; + } + break; + + default: + break; + } + } + + return true; + } + virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) { switch (widget) {