diff --git a/src/airport_gui.cpp b/src/airport_gui.cpp index 014884c..6437f23 100644 --- a/src/airport_gui.cpp +++ b/src/airport_gui.cpp @@ -91,7 +91,7 @@ struct BuildAirToolbarWindow : Window { { if (!gui_scope) return; - if (!CanBuildVehicleInfrastructure(VEH_AIRCRAFT, 0)) delete this; + if (!CanBuildVehicleInfrastructure(VEH_AIRCRAFT)) delete this; } virtual void OnClick(Point pt, int widget, int click_count) @@ -159,7 +159,7 @@ struct BuildAirToolbarWindow : Window { */ static EventState AirportToolbarGlobalHotkeys(int hotkey) { - if (_game_mode != GM_NORMAL || !CanBuildVehicleInfrastructure(VEH_AIRCRAFT, 0)) return ES_NOT_HANDLED; + if (_game_mode != GM_NORMAL || !CanBuildVehicleInfrastructure(VEH_AIRCRAFT)) return ES_NOT_HANDLED; Window *w = ShowBuildAirToolbar(); if (w == NULL) return ES_NOT_HANDLED; return w->OnHotkey(hotkey); diff --git a/src/dock_gui.cpp b/src/dock_gui.cpp index 531fb4b..79eaa89 100644 --- a/src/dock_gui.cpp +++ b/src/dock_gui.cpp @@ -117,7 +117,7 @@ struct BuildDocksToolbarWindow : Window { { if (!gui_scope) return; - bool can_build = CanBuildVehicleInfrastructure(VEH_SHIP, 0); + bool can_build = CanBuildVehicleInfrastructure(VEH_SHIP); this->SetWidgetsDisabledState(!can_build, WID_DT_DEPOT, WID_DT_STATION, @@ -145,17 +145,17 @@ struct BuildDocksToolbarWindow : Window { break; case WID_DT_DEPOT: // Build depot button - if (!CanBuildVehicleInfrastructure(VEH_SHIP, 0)) return; + if (!CanBuildVehicleInfrastructure(VEH_SHIP)) return; if (HandlePlacePushButton(this, WID_DT_DEPOT, SPR_CURSOR_SHIP_DEPOT, HT_RECT)) ShowBuildDocksDepotPicker(this); break; case WID_DT_STATION: // Build station button - if (!CanBuildVehicleInfrastructure(VEH_SHIP, 0)) return; + if (!CanBuildVehicleInfrastructure(VEH_SHIP)) return; if (HandlePlacePushButton(this, WID_DT_STATION, SPR_CURSOR_DOCK, HT_SPECIAL)) ShowBuildDockStationPicker(this); break; case WID_DT_BUOY: // Build buoy button - if (!CanBuildVehicleInfrastructure(VEH_SHIP, 0)) return; + if (!CanBuildVehicleInfrastructure(VEH_SHIP)) return; HandlePlacePushButton(this, WID_DT_BUOY, SPR_CURSOR_BUOY, HT_RECT); break; diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index 2c407b6..56e663c 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -444,7 +444,7 @@ struct BuildRailToolbarWindow : Window { { if (!gui_scope) return; - if (!CanBuildVehicleInfrastructure(VEH_TRAIN, 0)) delete this; + if (!CanBuildVehicleInfrastructure(VEH_TRAIN)) delete this; } /** @@ -778,7 +778,7 @@ struct BuildRailToolbarWindow : Window { */ static EventState RailToolbarGlobalHotkeys(int hotkey) { - if (_game_mode != GM_NORMAL || !CanBuildVehicleInfrastructure(VEH_TRAIN, 0)) return ES_NOT_HANDLED; + if (_game_mode != GM_NORMAL || !CanBuildVehicleInfrastructure(VEH_TRAIN)) return ES_NOT_HANDLED; extern RailType _last_built_railtype; Window *w = ShowBuildRailToolbar(_last_built_railtype); if (w == NULL) return ES_NOT_HANDLED; diff --git a/src/road.cpp b/src/road.cpp index b891bb5..8cb4859 100644 --- a/src/road.cpp +++ b/src/road.cpp @@ -257,10 +257,11 @@ bool RoadTypeIdentifier::UnpackIfValid(uint32 data) */ RoadSubTypes ExistingRoadSubTypesForRoadType(RoadType rt, CompanyID c, bool any_date) { - if (c != INVALID_COMPANY) { + /* Check only players which can actually own vehicles, editor and gamescripts are considered deities */ + if (c < OWNER_END) { const Company *company = Company::GetIfValid(c); - return company->avail_roadtypes[rt]; + if (company != NULL) return company->avail_roadtypes[rt]; } RoadSubTypes known_roadsubtypes = ROADSUBTYPES_NONE; diff --git a/src/road_gui.cpp b/src/road_gui.cpp index 1b9a32f..12c4f73 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -300,7 +300,7 @@ struct BuildRoadToolbarWindow : Window { { if (!gui_scope) return; - bool can_build = CanBuildVehicleInfrastructure(VEH_ROAD, this->roadtype_identifier.basetype); + bool can_build = CanBuildVehicleInfrastructure(this->roadtype_identifier, _local_company, false); this->SetWidgetsDisabledState(!can_build, WID_ROT_DEPOT, @@ -440,7 +440,7 @@ struct BuildRoadToolbarWindow : Window { break; case WID_ROT_DEPOT: - if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD, this->roadtype_identifier.basetype)) return; + if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(this->roadtype_identifier, _local_company, false)) return; if (HandlePlacePushButton(this, WID_ROT_DEPOT, GetRoadTypeInfo(roadtype_identifier)->cursor.depot, HT_RECT)) { ShowRoadDepotPicker(this); this->last_started_action = widget; @@ -448,7 +448,7 @@ struct BuildRoadToolbarWindow : Window { break; case WID_ROT_BUS_STATION: - if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD, this->roadtype_identifier.basetype)) return; + if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(this->roadtype_identifier, _local_company, false)) return; if (HandlePlacePushButton(this, WID_ROT_BUS_STATION, SPR_CURSOR_BUS_STATION, HT_RECT)) { ShowRVStationPicker(this, ROADSTOP_BUS); this->last_started_action = widget; @@ -456,7 +456,7 @@ struct BuildRoadToolbarWindow : Window { break; case WID_ROT_TRUCK_STATION: - if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(VEH_ROAD, this->roadtype_identifier.basetype)) return; + if (_game_mode == GM_EDITOR || !CanBuildVehicleInfrastructure(this->roadtype_identifier, _local_company, false)) return; if (HandlePlacePushButton(this, WID_ROT_TRUCK_STATION, SPR_CURSOR_TRUCK_STATION, HT_RECT)) { ShowRVStationPicker(this, ROADSTOP_TRUCK); this->last_started_action = widget; @@ -707,7 +707,7 @@ struct BuildRoadToolbarWindow : Window { */ static EventState RoadTramToolbarGlobalHotkeys(int hotkey, RoadTypeIdentifier last_build) { - if (last_build.basetype == ROADTYPE_TRAM && (_game_mode != GM_NORMAL || !CanBuildVehicleInfrastructure(VEH_ROAD, last_build.basetype))) return ES_NOT_HANDLED; + if (last_build.basetype == ROADTYPE_TRAM && (_game_mode != GM_NORMAL || !CanBuildVehicleInfrastructure(last_build, _local_company, false))) return ES_NOT_HANDLED; Window *w = NULL; switch (_game_mode) { @@ -1316,7 +1316,7 @@ DropDownList *GetScenRoadTypeDropDownList(RoadTypes roadtypes) for (RoadType rt = ROADTYPE_BEGIN; rt < ROADTYPE_END; rt++) { if (!HasBit(roadtypes, rt)) continue; - used_roadtypes = ExistingRoadSubTypesForRoadType(rt, INVALID_COMPANY, true); + used_roadtypes = ExistingRoadSubTypesForRoadType(rt, OWNER_DEITY, true); /* If it's not used ever, don't show it to the user. */ RoadTypeIdentifier rtid; diff --git a/src/toolbar_gui.cpp b/src/toolbar_gui.cpp index 4fe7d03..4180218 100644 --- a/src/toolbar_gui.cpp +++ b/src/toolbar_gui.cpp @@ -2054,9 +2054,9 @@ struct MainToolbarWindow : Window { this->SetWidgetDisabledState(WID_TN_GOAL, Goal::GetNumItems() == 0); this->SetWidgetDisabledState(WID_TN_STORY, StoryPage::GetNumItems() == 0); - this->SetWidgetDisabledState(WID_TN_RAILS, !CanBuildVehicleInfrastructure(VEH_TRAIN, 0)); - this->SetWidgetDisabledState(WID_TN_TRAMS, !CanBuildVehicleInfrastructure(VEH_ROAD, ROADTYPE_TRAM)); - this->SetWidgetDisabledState(WID_TN_AIR, !CanBuildVehicleInfrastructure(VEH_AIRCRAFT, 0)); + this->SetWidgetDisabledState(WID_TN_RAILS, !CanBuildVehicleInfrastructure(VEH_TRAIN)); + this->SetWidgetDisabledState(WID_TN_TRAMS, !CanBuildVehicleInfrastructure(RoadTypeIdentifier(ROADTYPE_TRAM, ROADSUBTYPE_NORMAL), _local_company, false)); //TODO: should loop through all tramtypes + this->SetWidgetDisabledState(WID_TN_AIR, !CanBuildVehicleInfrastructure(VEH_AIRCRAFT)); this->DrawWidgets(); } @@ -2097,11 +2097,11 @@ struct MainToolbarWindow : Window { case MTHK_AIRCRAFT_LIST: ShowVehicleListWindow(_local_company, VEH_AIRCRAFT); break; case MTHK_ZOOM_IN: ToolbarZoomInClick(this); break; case MTHK_ZOOM_OUT: ToolbarZoomOutClick(this); break; - case MTHK_BUILD_RAIL: if (CanBuildVehicleInfrastructure(VEH_TRAIN, 0)) ShowBuildRailToolbar(_last_built_railtype); break; + case MTHK_BUILD_RAIL: if (CanBuildVehicleInfrastructure(VEH_TRAIN)) ShowBuildRailToolbar(_last_built_railtype); break; case MTHK_BUILD_ROAD: ShowBuildRoadToolbar(_last_built_roadtype_identifier); break; - case MTHK_BUILD_TRAM: if (CanBuildVehicleInfrastructure(VEH_ROAD, ROADTYPE_TRAM)) ShowBuildRoadToolbar(_last_built_tramtype_identifier); break; + case MTHK_BUILD_TRAM: if (CanBuildVehicleInfrastructure(_last_built_tramtype_identifier, _local_company , false)) ShowBuildRoadToolbar(_last_built_tramtype_identifier); break; case MTHK_BUILD_DOCKS: ShowBuildDocksToolbar(); break; - case MTHK_BUILD_AIRPORT: if (CanBuildVehicleInfrastructure(VEH_AIRCRAFT, 0)) ShowBuildAirToolbar(); break; + case MTHK_BUILD_AIRPORT: if (CanBuildVehicleInfrastructure(VEH_AIRCRAFT)) ShowBuildAirToolbar(); break; case MTHK_BUILD_TREES: ShowBuildTreesToolbar(); break; case MTHK_MUSIC: ShowMusicWindow(); break; case MTHK_AI_DEBUG: ShowAIDebugWindow(); break; diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 86e3dbc..687bfc3 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -1714,12 +1714,12 @@ UnitID GetFreeUnitNumber(VehicleType type) * vehicle type. This to disable building stations etc. when * you are not allowed/able to have the vehicle type yet. * @param type the vehicle type to check this for - * @param subtype for road vehicles, either ROADTYPE_ROAD, ROADTYPE_TRAM or INVALID_ROADTYPE * @return true if there is any reason why you may build * the infrastructure for the given vehicle type */ -bool CanBuildVehicleInfrastructure(VehicleType type, uint subtype) +bool CanBuildVehicleInfrastructure(VehicleType type) { + assert(type != VEH_ROAD); assert(IsCompanyBuildableVehicleType(type)); if (!Company::IsValidID(_local_company)) return false; @@ -1728,7 +1728,6 @@ bool CanBuildVehicleInfrastructure(VehicleType type, uint subtype) UnitID max; switch (type) { case VEH_TRAIN: max = _settings_game.vehicle.max_trains; break; - case VEH_ROAD: max = _settings_game.vehicle.max_roadveh; break; case VEH_SHIP: max = _settings_game.vehicle.max_ships; break; case VEH_AIRCRAFT: max = _settings_game.vehicle.max_aircraft; break; default: NOT_REACHED(); @@ -1739,8 +1738,7 @@ bool CanBuildVehicleInfrastructure(VehicleType type, uint subtype) /* Can we actually build the vehicle type? */ const Engine *e; FOR_ALL_ENGINES_OF_TYPE(e, type) { - if ((type != VEH_ROAD || subtype == INVALID_ROADTYPE || subtype == e->GetRoadType().basetype) && - HasBit(e->company_avail, _local_company)) return true; + if (HasBit(e->company_avail, _local_company)) return true; } return false; } @@ -1748,14 +1746,47 @@ bool CanBuildVehicleInfrastructure(VehicleType type, uint subtype) /* We should be able to build infrastructure when we have the actual vehicle type */ const Vehicle *v; FOR_ALL_VEHICLES(v) { - if (v->type == type && - (type != VEH_ROAD || subtype == INVALID_ROADTYPE || subtype == RoadVehicle::From(v)->rtid.basetype) && - v->owner == _local_company) return true; + if (v->type == type && v->owner == _local_company) return true; } return false; } +/** + * Check whether we can build infrastructure for the given RoadType. This to disable building stations etc. when + * you are not allowed/able to have the RoadType yet. + * @param rtid the roadtype to check this for + * @param company the company id to check this for + * @param any_date to check only existing vehicles or if it is possible to build them in the future + * @return true if there is any reason why you may build the infrastructure for the given roadtype + */ +bool CanBuildVehicleInfrastructure(RoadTypeIdentifier rtid, CompanyID company, bool any_date) +{ + if (_game_mode != GM_EDITOR && !Company::IsValidID(company)) return false; + if (!_settings_client.gui.disable_unsuitable_building) return true; + + RoadSubTypes roadsubtypes = ExistingRoadSubTypesForRoadType(rtid.basetype, company, any_date); + + /* Check if the filtered subtypes does have the subtype we are checking for + * and if we can build new ones */ + if (_settings_game.vehicle.max_roadveh > 0 && HasBit(roadsubtypes, rtid.subtype)) { + /* Can we actually build the vehicle type? */ + const Engine *e; + FOR_ALL_ENGINES_OF_TYPE(e, VEH_ROAD) { + if (e->GetRoadType() == rtid) return true; + } + return false; + } + + /* We should be able to build infrastructure when we have the actual vehicle type */ + const Vehicle *v; + FOR_ALL_VEHICLES(v) { + if (v->type == VEH_ROAD && (company == OWNER_DEITY || v->owner == company) && + HasBit(roadsubtypes, RoadVehicle::From(v)->rtid.subtype) && RoadVehicle::From(v)->rtid == rtid) return true; + } + + return false; +} /** * Determines the #LiveryScheme for a vehicle. diff --git a/src/vehicle_func.h b/src/vehicle_func.h index 9d08529..430d793 100644 --- a/src/vehicle_func.h +++ b/src/vehicle_func.h @@ -71,7 +71,8 @@ UnitID GetFreeUnitNumber(VehicleType type); void VehicleEnterDepot(Vehicle *v); -bool CanBuildVehicleInfrastructure(VehicleType type, uint subtype); +bool CanBuildVehicleInfrastructure(VehicleType type); +bool CanBuildVehicleInfrastructure(RoadTypeIdentifier rtid, CompanyID company, bool any_date); /** Position information of a vehicle after it moved */ struct GetNewVehiclePosResult {