diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index 7bdba7deaa..bff07382c6 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -1461,8 +1461,8 @@ static void AircraftEventHandler_Flying(Aircraft *v, const AirportFTAClass *apc) { Station *st = Station::Get(v->targetairport); - /* runway busy or not allowed to use this airstation, circle */ - if (CanVehicleUseStation(v, st) && (st->owner == OWNER_NONE || st->owner == v->owner)) { + /* Runway busy, not allowed to use this airstation or closed, circle. */ + if (CanVehicleUseStation(v, st) && (st->owner == OWNER_NONE || st->owner == v->owner) && !(st->airport.flags & AIRPORT_CLOSED_block)) { /* {32,FLYING,NOTHING_block,37}, {32,LANDING,N,33}, {32,HELILANDING,N,41}, * if it is an airplane, look for LANDING, for helicopter HELILANDING * it is possible to choose from multiple landing runways, so loop until a free one is found */ diff --git a/src/airport.h b/src/airport.h index 7f11838404..7f0cac494b 100644 --- a/src/airport.h +++ b/src/airport.h @@ -122,7 +122,8 @@ static const uint64 OUT_WAY_block2 = 1ULL << 31, /* end of new blocks */ - NOTHING_block = 1ULL << 30; + NOTHING_block = 1ULL << 30, + AIRPORT_CLOSED_block = 1ULL << 63; ///< Dummy block for indicating a closed airport. /** A single location on an airport where aircraft can move to. */ struct AirportMovingData { diff --git a/src/command.cpp b/src/command.cpp index d04fc5ad61..bc33c27d5d 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -181,6 +181,8 @@ CommandProc CmdSetVehicleOnTime; CommandProc CmdAutofillTimetable; CommandProc CmdSetTimetableStart; +CommandProc CmdOpenCloseAirport; + #define DEF_CMD(proc, flags, type) {proc, #proc, (CommandFlags)flags, type} /** @@ -322,6 +324,8 @@ static const Command _command_proc_table[] = { DEF_CMD(CmdSetVehicleOnTime, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_SET_VEHICLE_ON_TIME DEF_CMD(CmdAutofillTimetable, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_AUTOFILL_TIMETABLE DEF_CMD(CmdSetTimetableStart, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_SET_TIMETABLE_START + + DEF_CMD(CmdOpenCloseAirport, 0, CMDT_ROUTE_MANAGEMENT ), // CMD_OPEN_CLOSE_AIRPORT }; /*! diff --git a/src/command_type.h b/src/command_type.h index 35c05573be..ee7b1a956c 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -302,6 +302,8 @@ enum Commands { CMD_AUTOFILL_TIMETABLE, ///< autofill the timetable CMD_SET_TIMETABLE_START, ///< set the date that a timetable should start + CMD_OPEN_CLOSE_AIRPORT, ///< open/close an airport to incoming aircraft + CMD_END, ///< Must ALWAYS be on the end of this list!! (period) }; diff --git a/src/lang/english.txt b/src/lang/english.txt index 0b06eeaf31..8c341302ad 100644 --- a/src/lang/english.txt +++ b/src/lang/english.txt @@ -2751,6 +2751,9 @@ STR_STATION_VIEW_SCHEDULED_SHIPS_TOOLTIP :{BLACK}Show all STR_STATION_VIEW_RENAME_STATION_CAPTION :Rename station/loading area +STR_STATION_VIEW_CLOSE_AIRPORT :{BLACK}Close airport +STR_STATION_VIEW_CLOSE_AIRPORT_TOOLTIP :{BLACK}Prevent aircraft from landing on this airport + # Waypoint/buoy view window STR_WAYPOINT_VIEW_CAPTION :{WHITE}{WAYPOINT} STR_WAYPOINT_VIEW_CENTER_TOOLTIP :{BLACK}Centre main view on waypoint location. Ctrl+Click opens a new viewport on waypoint location diff --git a/src/script/api/ai/ai_station.hpp.sq b/src/script/api/ai/ai_station.hpp.sq index 47072e68e7..620f378b99 100644 --- a/src/script/api/ai/ai_station.hpp.sq +++ b/src/script/api/ai/ai_station.hpp.sq @@ -56,6 +56,8 @@ void SQAIStation_Register(Squirrel *engine) SQAIStation.DefSQStaticMethod(engine, &ScriptStation::HasStationType, "HasStationType", 3, ".ii"); SQAIStation.DefSQStaticMethod(engine, &ScriptStation::HasRoadType, "HasRoadType", 3, ".ii"); SQAIStation.DefSQStaticMethod(engine, &ScriptStation::GetNearestTown, "GetNearestTown", 2, ".i"); + SQAIStation.DefSQStaticMethod(engine, &ScriptStation::IsAirportClosed, "IsAirportClosed", 2, ".i"); + SQAIStation.DefSQStaticMethod(engine, &ScriptStation::OpenCloseAirport, "OpenCloseAirport", 2, ".i"); SQAIStation.PostRegister(engine); } diff --git a/src/script/api/ai_changelog.hpp b/src/script/api/ai_changelog.hpp index a355aeb0a0..ef7a5853b5 100644 --- a/src/script/api/ai_changelog.hpp +++ b/src/script/api/ai_changelog.hpp @@ -19,6 +19,10 @@ * * 1.3.0 is not yet released. The following changes are not set in stone yet. * + * API additions: + * \li AIStation::IsAirportClosed + * \li AIStation::OpenCloseAirport + * * \b 1.2.0 * * API additions: diff --git a/src/script/api/game/game_station.hpp.sq b/src/script/api/game/game_station.hpp.sq index cf5b59ebe8..9e95d32bf5 100644 --- a/src/script/api/game/game_station.hpp.sq +++ b/src/script/api/game/game_station.hpp.sq @@ -57,6 +57,8 @@ void SQGSStation_Register(Squirrel *engine) SQGSStation.DefSQStaticMethod(engine, &ScriptStation::HasStationType, "HasStationType", 3, ".ii"); SQGSStation.DefSQStaticMethod(engine, &ScriptStation::HasRoadType, "HasRoadType", 3, ".ii"); SQGSStation.DefSQStaticMethod(engine, &ScriptStation::GetNearestTown, "GetNearestTown", 2, ".i"); + SQGSStation.DefSQStaticMethod(engine, &ScriptStation::IsAirportClosed, "IsAirportClosed", 2, ".i"); + SQGSStation.DefSQStaticMethod(engine, &ScriptStation::OpenCloseAirport, "OpenCloseAirport", 2, ".i"); SQGSStation.PostRegister(engine); } diff --git a/src/script/api/game/game_window.hpp.sq b/src/script/api/game/game_window.hpp.sq index 37317fce92..300eb69473 100644 --- a/src/script/api/game/game_window.hpp.sq +++ b/src/script/api/game/game_window.hpp.sq @@ -1040,6 +1040,7 @@ void SQGSWindow_Register(Squirrel *engine) SQGSWindow.DefSQConst(engine, ScriptWindow::WID_SV_LOCATION, "WID_SV_LOCATION"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_SV_ACCEPTS_RATINGS, "WID_SV_ACCEPTS_RATINGS"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_SV_RENAME, "WID_SV_RENAME"); + SQGSWindow.DefSQConst(engine, ScriptWindow::WID_SV_CLOSE_AIRPORT, "WID_SV_CLOSE_AIRPORT"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_SV_TRAINS, "WID_SV_TRAINS"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_SV_ROADVEHS, "WID_SV_ROADVEHS"); SQGSWindow.DefSQConst(engine, ScriptWindow::WID_SV_SHIPS, "WID_SV_SHIPS"); diff --git a/src/script/api/game_changelog.hpp b/src/script/api/game_changelog.hpp index 8d1da2f772..19279c8e50 100644 --- a/src/script/api/game_changelog.hpp +++ b/src/script/api/game_changelog.hpp @@ -19,6 +19,10 @@ * * 1.3.0 is not yet released. The following changes are not set in stone yet. * + * API additions: + * \li GSStation::IsAirportClosed + * \li GSStation::OpenCloseAirport + * * \b 1.2.0 * \li First stable release with the NoGo framework. */ diff --git a/src/script/api/script_station.cpp b/src/script/api/script_station.cpp index c42ed4a93e..423c5545ae 100644 --- a/src/script/api/script_station.cpp +++ b/src/script/api/script_station.cpp @@ -127,3 +127,19 @@ return ::Station::Get(station_id)->town->index; } + +/*static */ bool ScriptStation::IsAirportClosed(StationID station_id) +{ + EnforcePrecondition(false, IsValidStation(station_id)); + EnforcePrecondition(false, HasStationType(station_id, STATION_AIRPORT)); + + return (::Station::Get(station_id)->airport.flags & AIRPORT_CLOSED_block) != 0; +} + +/*static */ bool ScriptStation::OpenCloseAirport(StationID station_id) +{ + EnforcePrecondition(false, IsValidStation(station_id)); + EnforcePrecondition(false, HasStationType(station_id, STATION_AIRPORT)); + + return ScriptObject::DoCommand(0, station_id, 0, CMD_OPEN_CLOSE_AIRPORT); +} diff --git a/src/script/api/script_station.hpp b/src/script/api/script_station.hpp index 268a0bce4f..bb5d22c1b8 100644 --- a/src/script/api/script_station.hpp +++ b/src/script/api/script_station.hpp @@ -172,6 +172,24 @@ public: * towns grow, towns change. So don't depend on this value too much. */ static TownID GetNearestTown(StationID station_id); + + /** + * Get the open/closed state of an airport. + * @param station_id The airport to look at. + * @pre IsValidStation(station_id). + * @pre HasStationType(station_id, STATION_AIRPORT). + * @return True if the airport is currently closed to incoming traffic. + */ + static bool IsAirportClosed(StationID station_id); + + /** + * Toggle the open/closed state of an airport. + * @param station_id The airport to modify. + * @pre IsValidStation(station_id). + * @pre HasStationType(station_id, STATION_AIRPORT). + * @return True if the state could be toggled. + */ + static bool OpenCloseAirport(StationID station_id); }; DECLARE_ENUM_AS_BIT_SET(ScriptStation::StationType) diff --git a/src/script/api/script_window.hpp b/src/script/api/script_window.hpp index 99f8313f7a..9facdbfc8c 100644 --- a/src/script/api/script_window.hpp +++ b/src/script/api/script_window.hpp @@ -2059,6 +2059,7 @@ public: WID_SV_LOCATION = ::WID_SV_LOCATION, ///< 'Location' button. WID_SV_ACCEPTS_RATINGS = ::WID_SV_ACCEPTS_RATINGS, ///< 'Accepts' / 'Ratings' button. WID_SV_RENAME = ::WID_SV_RENAME, ///< 'Rename' button. + WID_SV_CLOSE_AIRPORT = ::WID_SV_CLOSE_AIRPORT, ///< 'Close airport' button. WID_SV_TRAINS = ::WID_SV_TRAINS, ///< List of scheduled trains button. WID_SV_ROADVEHS = ::WID_SV_ROADVEHS, ///< List of scheduled road vehs button. WID_SV_SHIPS = ::WID_SV_SHIPS, ///< List of scheduled ships button. diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 64b83e8e24..c0774556f5 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -2263,7 +2263,7 @@ CommandCost CmdBuildAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint st->RecomputeIndustriesNear(); InvalidateWindowData(WC_SELECT_STATION, 0, 0); InvalidateWindowData(WC_STATION_LIST, st->owner, 0); - SetWindowWidgetDirty(WC_STATION_VIEW, st->index, WID_SV_PLANES); + InvalidateWindowData(WC_STATION_VIEW, st->index); if (_settings_game.economy.station_noise_level) { SetWindowDirty(WC_TOWN_VIEW, st->town->index); @@ -2339,7 +2339,7 @@ static CommandCost RemoveAirport(TileIndex tile, DoCommandFlag flags) st->airport.Clear(); st->facilities &= ~FACIL_AIRPORT; - SetWindowWidgetDirty(WC_STATION_VIEW, st->index, WID_SV_PLANES); + InvalidateWindowData(WC_STATION_VIEW, st->index); if (_settings_game.economy.station_noise_level) { SetWindowDirty(WC_TOWN_VIEW, st->town->index); @@ -2357,6 +2357,32 @@ static CommandCost RemoveAirport(TileIndex tile, DoCommandFlag flags) return cost; } +/** + * Open/close an airport to incoming aircraft. + * @param tile Unused. + * @param flags Operation to perform. + * @param p1 Station ID of the airport. + * @param p2 Unused. + * @param text unused + * @return the cost of this operation or an error + */ +CommandCost CmdOpenCloseAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) +{ + if (!Station::IsValidID(p1)) return CMD_ERROR; + Station *st = Station::Get(p1); + + if (!(st->facilities & FACIL_AIRPORT)) return CMD_ERROR; + + CommandCost ret = CheckOwnership(st->owner); + if (ret.Failed()) return ret; + + if (flags & DC_EXEC) { + st->airport.flags ^= AIRPORT_CLOSED_block; + SetWindowWidgetDirty(WC_STATION_VIEW, st->index, WID_SV_CLOSE_AIRPORT); + } + return CommandCost(); +} + /** * Tests whether the company's vehicles have this station in orders * @param station station ID diff --git a/src/station_gui.cpp b/src/station_gui.cpp index e3610c2cce..7600e216d4 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -762,13 +762,17 @@ static const NWidgetPart _nested_station_view_widgets[] = { NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_SV_SCROLLBAR), EndContainer(), NWidget(WWT_PANEL, COLOUR_GREY, WID_SV_ACCEPT_RATING_LIST), SetMinimalSize(249, 32), SetResize(1, 0), EndContainer(), - NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SV_LOCATION), SetMinimalSize(60, 12), SetResize(1, 0), SetFill(1, 1), - SetDataTip(STR_BUTTON_LOCATION, STR_STATION_VIEW_CENTER_TOOLTIP), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SV_ACCEPTS_RATINGS), SetMinimalSize(61, 12), SetResize(1, 0), SetFill(1, 1), - SetDataTip(STR_STATION_VIEW_RATINGS_BUTTON, STR_STATION_VIEW_RATINGS_TOOLTIP), - NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SV_RENAME), SetMinimalSize(60, 12), SetResize(1, 0), SetFill(1, 1), - SetDataTip(STR_BUTTON_RENAME, STR_STATION_VIEW_RENAME_TOOLTIP), + NWidget(NWID_HORIZONTAL), + NWidget(NWID_HORIZONTAL, NC_EQUALSIZE), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SV_LOCATION), SetMinimalSize(45, 12), SetResize(1, 0), SetFill(1, 1), + SetDataTip(STR_BUTTON_LOCATION, STR_STATION_VIEW_CENTER_TOOLTIP), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SV_ACCEPTS_RATINGS), SetMinimalSize(46, 12), SetResize(1, 0), SetFill(1, 1), + SetDataTip(STR_STATION_VIEW_RATINGS_BUTTON, STR_STATION_VIEW_RATINGS_TOOLTIP), + NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SV_RENAME), SetMinimalSize(45, 12), SetResize(1, 0), SetFill(1, 1), + SetDataTip(STR_BUTTON_RENAME, STR_STATION_VIEW_RENAME_TOOLTIP), + EndContainer(), + NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_SV_CLOSE_AIRPORT), SetMinimalSize(45, 12), SetResize(1, 0), SetFill(1, 1), + SetDataTip(STR_STATION_VIEW_CLOSE_AIRPORT, STR_STATION_VIEW_CLOSE_AIRPORT_TOOLTIP), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SV_TRAINS), SetMinimalSize(14, 12), SetFill(0, 1), SetDataTip(STR_TRAIN, STR_STATION_VIEW_SCHEDULED_TRAINS_TOOLTIP), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SV_ROADVEHS), SetMinimalSize(14, 12), SetFill(0, 1), SetDataTip(STR_LORRY, STR_STATION_VIEW_SCHEDULED_ROAD_VEHICLES_TOOLTIP), NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_SV_SHIPS), SetMinimalSize(14, 12), SetFill(0, 1), SetDataTip(STR_SHIP, STR_STATION_VIEW_SCHEDULED_SHIPS_TOOLTIP), @@ -869,6 +873,15 @@ struct StationViewWindow : public Window { case WID_SV_ACCEPT_RATING_LIST: size->height = WD_FRAMERECT_TOP + ((this->GetWidget(WID_SV_ACCEPTS_RATINGS)->widget_data == STR_STATION_VIEW_RATINGS_BUTTON) ? this->accepts_lines : this->rating_lines) * FONT_HEIGHT_NORMAL + WD_FRAMERECT_BOTTOM; break; + + case WID_SV_CLOSE_AIRPORT: + if (!(Station::Get(this->window_number)->facilities & FACIL_AIRPORT)) { + /* Hide 'Close Airport' button if no airport present. */ + size->width = 0; + resize->width = 0; + fill->width = 0; + } + break; } } @@ -887,6 +900,8 @@ struct StationViewWindow : public Window { this->SetWidgetDisabledState(WID_SV_ROADVEHS, !(st->facilities & FACIL_TRUCK_STOP) && !(st->facilities & FACIL_BUS_STOP)); this->SetWidgetDisabledState(WID_SV_SHIPS, !(st->facilities & FACIL_DOCK)); this->SetWidgetDisabledState(WID_SV_PLANES, !(st->facilities & FACIL_AIRPORT)); + this->SetWidgetDisabledState(WID_SV_CLOSE_AIRPORT, !(st->facilities & FACIL_AIRPORT) || st->owner != _local_company); + this->SetWidgetLoweredState(WID_SV_CLOSE_AIRPORT, (st->facilities & FACIL_AIRPORT) && (st->airport.flags & AIRPORT_CLOSED_block) != 0); this->DrawWidgets(); @@ -1133,6 +1148,10 @@ struct StationViewWindow : public Window { this, CS_ALPHANUMERAL, QSF_ENABLE_DEFAULT | QSF_LEN_IN_CHARS); break; + case WID_SV_CLOSE_AIRPORT: + DoCommandP(0, this->window_number, 0, CMD_OPEN_CLOSE_AIRPORT); + break; + case WID_SV_TRAINS: // Show list of scheduled trains to this station case WID_SV_ROADVEHS: // Show list of scheduled road-vehicles to this station case WID_SV_SHIPS: // Show list of scheduled ships to this station @@ -1153,6 +1172,16 @@ struct StationViewWindow : public Window { { this->vscroll->SetCapacityFromWidget(this, WID_SV_WAITING, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM); } + + /** + * Some data on this window has become invalid. + * @param data Information about the changed data. + * @param gui_scope Whether the call is done from GUI scope. You may not do everything when not in GUI scope. See #InvalidateWindowData() for details. + */ + virtual void OnInvalidateData(int data = 0, bool gui_scope = true) + { + if (gui_scope) this->ReInit(); + } }; diff --git a/src/widgets/station_widget.h b/src/widgets/station_widget.h index 4d52049d85..e33565ea1d 100644 --- a/src/widgets/station_widget.h +++ b/src/widgets/station_widget.h @@ -21,6 +21,7 @@ enum StationViewWidgets { WID_SV_LOCATION, ///< 'Location' button. WID_SV_ACCEPTS_RATINGS, ///< 'Accepts' / 'Ratings' button. WID_SV_RENAME, ///< 'Rename' button. + WID_SV_CLOSE_AIRPORT, ///< 'Close airport' button. WID_SV_TRAINS, ///< List of scheduled trains button. WID_SV_ROADVEHS, ///< List of scheduled road vehs button. WID_SV_SHIPS, ///< List of scheduled ships button.