From 2033299336547a32e5d6bcdf1ea4deea4836dd9e Mon Sep 17 00:00:00 2001 From: dP Date: Sun, 14 Dec 2025 17:37:16 +0500 Subject: [PATCH] Don't crash when opening airport build tool with no available airports --- src/citymania/cm_highlight.cpp | 9 ++++++--- src/citymania/cm_station_gui.cpp | 32 +++++++++++++++++++++++--------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/citymania/cm_highlight.cpp b/src/citymania/cm_highlight.cpp index 72840ddf41..5c7c5051cf 100644 --- a/src/citymania/cm_highlight.cpp +++ b/src/citymania/cm_highlight.cpp @@ -2500,9 +2500,12 @@ HighLightStyle UpdateTileSelection(HighLightStyle new_drawstyle) { } else if (_thd.select_proc == CM_DDSP_BUILD_AIRPORT) { auto tile = TileXY(_thd.new_pos.x / TILE_SIZE, _thd.new_pos.y / TILE_SIZE); if (_selected_airport_index != -1) { - const AirportSpec *as = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index); - _thd.cm_new = ObjectHighlight::make_airport(tile, as->GetIndex(), _selected_airport_layout); - new_drawstyle = HT_RECT; + auto ac = AirportClass::Get(_selected_airport_class); + auto as = (ac != nullptr ? ac->GetSpec(_selected_airport_index) : nullptr); + if (as != nullptr) { + _thd.cm_new = ObjectHighlight::make_airport(tile, as->GetIndex(), _selected_airport_layout); + new_drawstyle = HT_RECT; + } } } else if (_thd.select_proc == DDSP_BUILD_STATION || _thd.select_proc == DDSP_BUILD_BUSSTOP || _thd.select_proc == DDSP_BUILD_TRUCKSTOP) { // station diff --git a/src/citymania/cm_station_gui.cpp b/src/citymania/cm_station_gui.cpp index 3e421670b2..039e476359 100644 --- a/src/citymania/cm_station_gui.cpp +++ b/src/citymania/cm_station_gui.cpp @@ -800,7 +800,7 @@ ToolGUIInfo RemoveAction::GetGUIInfo() { if (area.has_value()) { hlmap.AddTileAreaWithBorder(area.value(), CM_PALETTE_TINT_RED_DEEP); auto cmd = this->GetCommand(area.value()); - if (cmd) cost = cmd->test(); + if (cmd != nullptr) cost = cmd->test(); } return {hlmap, data, cost}; } @@ -810,7 +810,7 @@ void RemoveAction::OnStationRemoved(const Station *) {} // --- PlacementAction --- ToolGUIInfo PlacementAction::PrepareGUIInfo(std::optional ohl, up cmd, StationCoverageType sct, uint rad) { - if (!cmd || !ohl.has_value()) return {}; + if (cmd == nullptr || !ohl.has_value()) return {}; ohl.value().UpdateTiles(); auto palette = CM_PALETTE_TINT_WHITE; auto area = ohl.value().GetArea(); @@ -1106,6 +1106,7 @@ extern void ShowSelectStationWindow(TileArea ta, StationPickerCmdProc&& proc); template bool PostBuildStationCommand(Taction *action, Tcallback callback, Targ arg, StationID join_to) { auto cmd = action->GetCommand(arg, join_to); + if (cmd == nullptr) return false; if (UseImprovedStationJoin()) { cmd->with_callback([](bool res)->bool { if (!res) return false; @@ -1114,7 +1115,7 @@ bool PostBuildStationCommand(Taction *action, Tcallback callback, Targ arg, Stat return true; }); } - return cmd ? cmd->post(callback) : false; + return cmd->post(callback); } template @@ -1129,7 +1130,7 @@ bool ExecuteBuildCommand(Taction *action, Tcallback callback, Targ arg) { [&](StationAction::Picker &) { auto cmd = action->GetCommand(arg, INVALID_STATION); auto proc = [cmd=sp{std::move(cmd)}, callback](bool test, StationID to_join) -> bool { - if (!cmd) return false; + if (cmd == nullptr) return false; auto station_cmd = dynamic_cast(cmd.get()); if (station_cmd == nullptr) return false; station_cmd->station_to_join = to_join; @@ -1169,6 +1170,7 @@ up RailStationBuildTool::RemoveAction::GetCommand(TileArea area) { bool RailStationBuildTool::RemoveAction::Execute(TileArea area) { auto cmd = this->GetCommand(area); + if (cmd == nullptr) return false; return cmd->post(&CcPlaySound_CONSTRUCTION_RAIL); } @@ -1300,6 +1302,7 @@ up RoadStopBuildTool::RemoveAction::GetCommand(TileArea area) { bool RoadStopBuildTool::RemoveAction::Execute(TileArea area) { auto cmd = this->GetCommand(area); + if (cmd == nullptr) return false; return cmd->post(&CcPlaySound_CONSTRUCTION_OTHER); } @@ -1504,13 +1507,17 @@ bool AirportBuildTool::RemoveAction::Execute(TileArea area) { std::optional AirportBuildTool::SizedPlacementAction::GetArea() const { if (!IsValidTile(this->cur_tile)) return std::nullopt; - auto as = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index); + auto ac = AirportClass::Get(_selected_airport_class); + if (ac == nullptr) return std::nullopt; + auto as = ac->GetSpec(_selected_airport_index); if (as == nullptr) return std::nullopt; return TileArea{this->cur_tile, as->size_x, as->size_y}; } up AirportBuildTool::SizedPlacementAction::GetCommand(TileIndex tile, StationID to_join) { - auto as = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index); + auto ac = AirportClass::Get(_selected_airport_class); + if (ac == nullptr) return nullptr; + auto as = ac->GetSpec(_selected_airport_index); if (as == nullptr) return nullptr; byte airport_type = as->GetIndex(); byte layout = _selected_airport_layout; @@ -1530,14 +1537,21 @@ bool AirportBuildTool::SizedPlacementAction::Execute(TileIndex tile) { } std::optional AirportBuildTool::SizedPlacementAction::GetObjectHighlight(TileIndex tile) { - byte airport_type = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index)->GetIndex(); + auto ac = AirportClass::Get(_selected_airport_class); + if (ac == nullptr) return std::nullopt; + auto as = ac->GetSpec(_selected_airport_index); + if (as == nullptr) return std::nullopt; + byte airport_type = as->GetIndex(); byte layout = _selected_airport_layout; return ObjectHighlight::make_airport(tile, airport_type, layout); } std::pair AirportBuildTool::SizedPlacementAction::GetCatchmentParams() { - auto rad = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index)->catchment; - return {SCT_ALL, rad}; + auto ac = AirportClass::Get(_selected_airport_class); + if (ac == nullptr) return {SCT_ALL, 0}; + auto as = ac->GetSpec(_selected_airport_index); + if (as == nullptr) return {SCT_ALL, 0}; + return {SCT_ALL, as->catchment}; }