Initial implementation of road waypoints
This commit is contained in:
@@ -1032,7 +1032,7 @@
|
||||
</tr>
|
||||
</table>
|
||||
</li>
|
||||
<li>m6 bits <span style="color: blue">6</span>..3: the station type (rail, airport, truck, bus, oilrig, dock, buoy, waypoint)</li>
|
||||
<li>m6 bits <span style="color: blue">6</span>..3: the station type (rail, airport, truck, bus, oilrig, dock, buoy, waypoint, <span style="color: blue">road waypoint</span>)</li>
|
||||
<li>m6 bit 2: pbs reservation state for railway stations/waypoints</li>
|
||||
|
||||
<li>m7 bits 4..0: <a href="#OwnershipInfo">owner</a> of road (road stops)</li>
|
||||
|
@@ -67,6 +67,7 @@ CommandProc CmdBuildTunnel;
|
||||
|
||||
CommandProc CmdBuildTrainDepot;
|
||||
CommandProcEx CmdBuildRailWaypoint;
|
||||
CommandProc CmdBuildRoadWaypoint;
|
||||
CommandProc CmdRenameWaypoint;
|
||||
CommandProc CmdSetWaypointLabelHidden;
|
||||
CommandProc CmdRemoveFromRailWaypoint;
|
||||
@@ -316,6 +317,7 @@ static const Command _command_proc_table[] = {
|
||||
DEF_CMD(CmdRemoveFromRailStation, 0, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_REMOVE_FROM_RAIL_STATION
|
||||
DEF_CMD(CmdConvertRail, 0, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_CONVERT_RAIL
|
||||
DEF_CMD(CmdBuildRailWaypoint, 0, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_BUILD_RAIL_WAYPOINT
|
||||
DEF_CMD(CmdBuildRoadWaypoint, 0, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_BUILD_ROAD_WAYPOINT
|
||||
DEF_CMD(CmdRenameWaypoint, 0, CMDT_OTHER_MANAGEMENT ), // CMD_RENAME_WAYPOINT
|
||||
DEF_CMD(CmdSetWaypointLabelHidden, 0, CMDT_OTHER_MANAGEMENT ), // CMD_SET_WAYPOINT_LABEL_HIDDEN
|
||||
DEF_CMD(CmdRemoveFromRailWaypoint, 0, CMDT_LANDSCAPE_CONSTRUCTION), // CMD_REMOVE_FROM_RAIL_WAYPOINT
|
||||
|
@@ -251,6 +251,7 @@ enum Commands {
|
||||
CMD_CONVERT_RAIL, ///< convert a rail type
|
||||
|
||||
CMD_BUILD_RAIL_WAYPOINT, ///< build a waypoint
|
||||
CMD_BUILD_ROAD_WAYPOINT, ///< build a road waypoint
|
||||
CMD_RENAME_WAYPOINT, ///< rename a waypoint
|
||||
CMD_SET_WAYPOINT_LABEL_HIDDEN, ///< set whether waypoint label is hidden
|
||||
CMD_REMOVE_FROM_RAIL_WAYPOINT, ///< remove a (rectangle of) tiles from a rail waypoint
|
||||
|
@@ -3549,6 +3549,8 @@ STR_ROAD_TOOLBAR_TOOLTIP_BUILD_AUTOROAD :{BLACK}Build ro
|
||||
STR_ROAD_TOOLBAR_TOOLTIP_BUILD_AUTOTRAM :{BLACK}Build tramway section using the Autotram mode. Ctrl toggles build/remove for tramway construction. Shift toggles building/showing cost estimate
|
||||
STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_VEHICLE_DEPOT :{BLACK}Build road vehicle depot (for buying and servicing vehicles). Shift toggles building/showing cost estimate
|
||||
STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAM_VEHICLE_DEPOT :{BLACK}Build tram vehicle depot (for buying and servicing vehicles). Shift toggles building/showing cost estimate
|
||||
STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_ROAD_TO_WAYPOINT :{BLACK}Convert road to waypoint. Ctrl enables joining waypoints. Shift toggles building/showing cost estimate
|
||||
STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_TRAM_TO_WAYPOINT :{BLACK}Convert tram to waypoint. Ctrl enables joining waypoints. Shift toggles building/showing cost estimate
|
||||
STR_ROAD_TOOLBAR_TOOLTIP_BUILD_BUS_STATION :{BLACK}Build bus station. Ctrl enables joining stations. Shift toggles building/showing cost estimate
|
||||
STR_ROAD_TOOLBAR_TOOLTIP_BUILD_PASSENGER_TRAM_STATION :{BLACK}Build passenger tram station. Ctrl enables joining stations. Shift toggles building/showing cost estimate
|
||||
STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRUCK_LOADING_BAY :{BLACK}Build lorry loading bay. Ctrl enables joining stations. Shift toggles building/showing cost estimate
|
||||
@@ -6142,11 +6144,14 @@ STR_ERROR_WAYPOINT_ADJOINS_MORE_THAN_ONE_EXISTING :{WHITE}Adjoins
|
||||
STR_ERROR_TOO_CLOSE_TO_ANOTHER_WAYPOINT :{WHITE}Too close to another waypoint
|
||||
|
||||
STR_ERROR_CAN_T_BUILD_TRAIN_WAYPOINT :{WHITE}Can't build train waypoint here...
|
||||
STR_ERROR_CAN_T_BUILD_ROAD_WAYPOINT :{WHITE}Can't build road waypoint here...
|
||||
STR_ERROR_CAN_T_POSITION_BUOY_HERE :{WHITE}Can't place buoy here...
|
||||
STR_ERROR_CAN_T_CHANGE_WAYPOINT_NAME :{WHITE}Can't change waypoint name...
|
||||
|
||||
STR_ERROR_CAN_T_REMOVE_TRAIN_WAYPOINT :{WHITE}Can't remove train waypoint here...
|
||||
STR_ERROR_CAN_T_REMOVE_ROAD_WAYPOINT :{WHITE}Can't remove road waypoint here...
|
||||
STR_ERROR_MUST_REMOVE_RAILWAYPOINT_FIRST :{WHITE}Must remove rail waypoint first
|
||||
STR_ERROR_MUST_REMOVE_ROADWAYPOINT_FIRST :{WHITE}Must remove road waypoint first
|
||||
STR_ERROR_BUOY_IN_THE_WAY :{WHITE}... buoy in the way
|
||||
STR_ERROR_BUOY_IS_IN_USE :{WHITE}... buoy is in use by another company!
|
||||
|
||||
|
@@ -1090,6 +1090,14 @@ CommandCost CmdInsertOrderIntl(DoCommandFlag flags, Vehicle *v, VehicleOrderID s
|
||||
break;
|
||||
}
|
||||
|
||||
case VEH_ROAD: {
|
||||
if (!(wp->facilities & FACIL_BUS_STOP) || !(wp->facilities & FACIL_TRUCK_STOP)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
|
||||
|
||||
CommandCost ret = CheckInfraUsageAllowed(v->type, wp->owner);
|
||||
if (ret.Failed()) return ret;
|
||||
break;
|
||||
}
|
||||
|
||||
case VEH_SHIP:
|
||||
if (!(wp->facilities & FACIL_DOCK)) return_cmd_error(STR_ERROR_CAN_T_ADD_ORDER);
|
||||
if (wp->owner != OWNER_NONE) {
|
||||
@@ -1101,9 +1109,9 @@ CommandCost CmdInsertOrderIntl(DoCommandFlag flags, Vehicle *v, VehicleOrderID s
|
||||
|
||||
/* Order flags can be any of the following for waypoints:
|
||||
* [non-stop]
|
||||
* non-stop orders (if any) are only valid for trains */
|
||||
if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && v->type != VEH_TRAIN) return CMD_ERROR;
|
||||
if (_settings_game.order.nonstop_only && !(new_order.GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) && v->type == VEH_TRAIN) return CMD_ERROR;
|
||||
* non-stop orders (if any) are only valid for trains/RVs */
|
||||
if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && !v->IsGroundVehicle()) return CMD_ERROR;
|
||||
if (_settings_game.order.nonstop_only && !(new_order.GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) && v->IsGroundVehicle()) return CMD_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@@ -1130,6 +1130,15 @@ static Order GetOrderCmdFromTile(const Vehicle *v, TileIndex tile)
|
||||
return order;
|
||||
}
|
||||
|
||||
/* check road waypoint */
|
||||
if (IsRoadWaypointTile(tile) &&
|
||||
v->type == VEH_ROAD &&
|
||||
IsInfraTileUsageAllowed(VEH_ROAD, v->owner, tile)) {
|
||||
order.MakeGoToWaypoint(GetStationIndex(tile));
|
||||
if (_settings_client.gui.new_nonstop != _ctrl_pressed || _settings_game.order.nonstop_only) order.SetNonStopType(ONSF_NO_STOP_AT_ANY_STATION);
|
||||
return order;
|
||||
}
|
||||
|
||||
/* check buoy (no ownership) */
|
||||
if (IsBuoyTile(tile) && v->type == VEH_SHIP) {
|
||||
order.MakeGoToWaypoint(GetStationIndex(tile));
|
||||
|
@@ -228,7 +228,7 @@ protected:
|
||||
/* special handling for stations */
|
||||
if (IsRailTT() && HasStationTileRail(m_new_tile)) {
|
||||
m_is_station = true;
|
||||
} else if (IsRoadTT() && IsRoadStopTile(m_new_tile)) {
|
||||
} else if (IsRoadTT() && IsStationRoadStopTile(m_new_tile)) {
|
||||
m_is_station = true;
|
||||
}
|
||||
}
|
||||
|
@@ -341,6 +341,7 @@ static int32 NPFRoadPathCost(AyStar *as, AyStarNode *current, OpenListNode *pare
|
||||
|
||||
case MP_STATION: {
|
||||
cost = NPF_TILE_LENGTH;
|
||||
if (IsRoadWaypoint(tile)) break;
|
||||
const RoadStop *rs = RoadStop::GetByTile(tile, GetRoadStopType(tile));
|
||||
if (IsDriveThroughStopTile(tile)) {
|
||||
/* Increase the cost for drive-through road stops */
|
||||
@@ -1131,7 +1132,7 @@ static void NPFFillWithOrderData(NPFFindStationOrTileData *fstd, const Vehicle *
|
||||
if (v->type == VEH_TRAIN) {
|
||||
fstd->station_type = v->current_order.IsType(OT_GOTO_STATION) ? STATION_RAIL : STATION_WAYPOINT;
|
||||
} else if (v->type == VEH_ROAD) {
|
||||
fstd->station_type = RoadVehicle::From(v)->IsBus() ? STATION_BUS : STATION_TRUCK;
|
||||
fstd->station_type = v->current_order.IsType(OT_GOTO_STATION) ? (RoadVehicle::From(v)->IsBus() ? STATION_BUS : STATION_TRUCK) : STATION_ROADWAYPOINT;
|
||||
} else if (v->type == VEH_SHIP) {
|
||||
fstd->station_type = v->current_order.IsType(OT_GOTO_STATION) ? STATION_DOCK : STATION_BUOY;
|
||||
}
|
||||
|
@@ -92,6 +92,8 @@ protected:
|
||||
break;
|
||||
|
||||
case MP_STATION: {
|
||||
if (IsRoadWaypoint(tile)) break;
|
||||
|
||||
const RoadStop *rs = RoadStop::GetByTile(tile, GetRoadStopType(tile));
|
||||
if (IsDriveThroughStopTile(tile)) {
|
||||
/* Increase the cost for drive-through road stops */
|
||||
@@ -270,7 +272,7 @@ protected:
|
||||
TileIndex m_destTile;
|
||||
TrackdirBits m_destTrackdirs;
|
||||
StationID m_dest_station;
|
||||
bool m_bus;
|
||||
StationType m_station_type;
|
||||
bool m_non_artic;
|
||||
|
||||
public:
|
||||
@@ -278,8 +280,14 @@ public:
|
||||
{
|
||||
if (v->current_order.IsType(OT_GOTO_STATION)) {
|
||||
m_dest_station = v->current_order.GetDestination();
|
||||
m_bus = v->IsBus();
|
||||
m_destTile = CalcClosestStationTile(m_dest_station, v->tile, m_bus ? STATION_BUS : STATION_TRUCK);
|
||||
m_station_type = v->IsBus() ? STATION_BUS : STATION_TRUCK;
|
||||
m_destTile = CalcClosestStationTile(m_dest_station, v->tile, m_station_type);
|
||||
m_non_artic = !v->HasArticulatedPart();
|
||||
m_destTrackdirs = INVALID_TRACKDIR_BIT;
|
||||
} else if (v->current_order.IsType(OT_GOTO_WAYPOINT)) {
|
||||
m_dest_station = v->current_order.GetDestination();
|
||||
m_station_type = STATION_ROADWAYPOINT;
|
||||
m_destTile = CalcClosestStationTile(m_dest_station, v->tile, m_station_type);
|
||||
m_non_artic = !v->HasArticulatedPart();
|
||||
m_destTrackdirs = INVALID_TRACKDIR_BIT;
|
||||
} else {
|
||||
@@ -313,7 +321,7 @@ public:
|
||||
if (m_dest_station != INVALID_STATION) {
|
||||
return IsTileType(tile, MP_STATION) &&
|
||||
GetStationIndex(tile) == m_dest_station &&
|
||||
(m_bus ? IsBusStop(tile) : IsTruckStop(tile)) &&
|
||||
(m_station_type == GetStationType(tile)) &&
|
||||
(m_non_artic || IsDriveThroughStopTile(tile));
|
||||
}
|
||||
|
||||
|
@@ -1967,7 +1967,7 @@ void DrawRoadCatenary(const TileInfo *ti)
|
||||
tram = road = (GetCrossingRailAxis(ti->tile) == AXIS_Y ? ROAD_X : ROAD_Y);
|
||||
}
|
||||
} else if (IsTileType(ti->tile, MP_STATION)) {
|
||||
if (IsRoadStop(ti->tile)) {
|
||||
if (IsAnyRoadStop(ti->tile)) {
|
||||
if (IsDriveThroughStopTile(ti->tile)) {
|
||||
Axis axis = GetRoadStopDir(ti->tile) == DIAGDIR_NE ? AXIS_X : AXIS_Y;
|
||||
tram = road = (axis == AXIS_X ? ROAD_X : ROAD_Y);
|
||||
@@ -2976,7 +2976,7 @@ CommandCost CmdConvertRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
||||
TileType tt = GetTileType(tile);
|
||||
switch (tt) {
|
||||
case MP_STATION:
|
||||
if (!IsRoadStop(tile)) continue;
|
||||
if (!IsAnyRoadStop(tile)) continue;
|
||||
break;
|
||||
case MP_ROAD:
|
||||
if (IsLevelCrossing(tile) && RoadNoLevelCrossing(to_type)) {
|
||||
@@ -3036,7 +3036,7 @@ CommandCost CmdConvertRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
||||
}
|
||||
|
||||
uint num_pieces;
|
||||
if (IsRoadDepotTile(tile) || IsRoadStopTile(tile)) {
|
||||
if (IsRoadDepotTile(tile) || IsAnyRoadStopTile(tile)) {
|
||||
num_pieces = HasTileRoadType(tile, rtt) ? 2 : 0;
|
||||
} else {
|
||||
num_pieces = CountBits(GetAnyRoadBits(tile, rtt));
|
||||
@@ -3047,7 +3047,7 @@ CommandCost CmdConvertRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
||||
|
||||
if (flags & DC_EXEC) { // we can safely convert, too
|
||||
/* Update the company infrastructure counters. */
|
||||
if (!IsRoadStopTile(tile) && owner == _current_company) {
|
||||
if (!IsAnyRoadStopTile(tile) && owner == _current_company) {
|
||||
ConvertRoadTypeOwner(tile, num_pieces, owner, from_type, to_type);
|
||||
} else {
|
||||
UpdateCompanyRoadInfrastructure(from_type, owner, -(int)num_pieces);
|
||||
|
@@ -32,6 +32,7 @@
|
||||
#include "core/geometry_func.hpp"
|
||||
#include "date_func.h"
|
||||
#include "station_map.h"
|
||||
#include "waypoint_func.h"
|
||||
#include "widgets/road_widget.h"
|
||||
#include "table/strings.h"
|
||||
|
||||
@@ -197,6 +198,29 @@ static void PlaceRoadStop(TileIndex start_tile, TileIndex end_tile, uint32 p2, u
|
||||
ShowSelectStationIfNeeded(cmdcont, ta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Place a road waypoint.
|
||||
* @param tile Position to start dragging a waypoint.
|
||||
*/
|
||||
static void PlaceRoad_Waypoint(TileIndex tile)
|
||||
{
|
||||
if (_remove_button_clicked) {
|
||||
VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_REMOVE_ROAD_WAYPOINT);
|
||||
return;
|
||||
}
|
||||
|
||||
Axis axis = GetAxisForNewRoadWaypoint(tile);
|
||||
if (IsValidAxis(axis)) {
|
||||
/* Valid tile for waypoints */
|
||||
VpStartPlaceSizing(tile, axis == AXIS_X ? VPM_X_LIMITED : VPM_Y_LIMITED, DDSP_BUILD_ROAD_WAYPOINT);
|
||||
VpSetPlaceSizingLimit(_settings_game.station.station_spread);
|
||||
} else {
|
||||
/* Tile where we can't build rail waypoints. This is always going to fail,
|
||||
* but provides the user with a proper error message. */
|
||||
DoCommandP(tile, 1 | 1 << 8, INVALID_STATION << 16, CMD_BUILD_ROAD_WAYPOINT | CMD_MSG(STR_ERROR_CAN_T_BUILD_ROAD_WAYPOINT));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for placing a bus station.
|
||||
* @param tile Position to place the station.
|
||||
@@ -309,6 +333,7 @@ struct BuildRoadToolbarWindow : Window {
|
||||
bool can_build = CanBuildVehicleInfrastructure(VEH_ROAD, rtt);
|
||||
this->SetWidgetsDisabledState(!can_build,
|
||||
WID_ROT_DEPOT,
|
||||
WID_ROT_BUILD_WAYPOINT,
|
||||
WID_ROT_BUS_STATION,
|
||||
WID_ROT_TRUCK_STATION,
|
||||
WIDGET_LIST_END);
|
||||
@@ -322,10 +347,12 @@ struct BuildRoadToolbarWindow : Window {
|
||||
if (!can_build) {
|
||||
/* Show in the tooltip why this button is disabled. */
|
||||
this->GetWidget<NWidgetCore>(WID_ROT_DEPOT)->SetToolTip(STR_TOOLBAR_DISABLED_NO_VEHICLE_AVAILABLE);
|
||||
this->GetWidget<NWidgetCore>(WID_ROT_BUILD_WAYPOINT)->SetToolTip(STR_TOOLBAR_DISABLED_NO_VEHICLE_AVAILABLE);
|
||||
this->GetWidget<NWidgetCore>(WID_ROT_BUS_STATION)->SetToolTip(STR_TOOLBAR_DISABLED_NO_VEHICLE_AVAILABLE);
|
||||
this->GetWidget<NWidgetCore>(WID_ROT_TRUCK_STATION)->SetToolTip(STR_TOOLBAR_DISABLED_NO_VEHICLE_AVAILABLE);
|
||||
} else {
|
||||
this->GetWidget<NWidgetCore>(WID_ROT_DEPOT)->SetToolTip(rtt == RTT_ROAD ? STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_VEHICLE_DEPOT : STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAM_VEHICLE_DEPOT);
|
||||
this->GetWidget<NWidgetCore>(WID_ROT_BUILD_WAYPOINT)->SetToolTip(rtt == RTT_ROAD ? STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_ROAD_TO_WAYPOINT : STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_TRAM_TO_WAYPOINT);
|
||||
this->GetWidget<NWidgetCore>(WID_ROT_BUS_STATION)->SetToolTip(rtt == RTT_ROAD ? STR_ROAD_TOOLBAR_TOOLTIP_BUILD_BUS_STATION : STR_ROAD_TOOLBAR_TOOLTIP_BUILD_PASSENGER_TRAM_STATION);
|
||||
this->GetWidget<NWidgetCore>(WID_ROT_TRUCK_STATION)->SetToolTip(rtt == RTT_ROAD ? STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRUCK_LOADING_BAY : STR_ROAD_TOOLBAR_TOOLTIP_BUILD_CARGO_TRAM_STATION);
|
||||
}
|
||||
@@ -405,6 +432,7 @@ struct BuildRoadToolbarWindow : Window {
|
||||
|
||||
case WID_ROT_BUS_STATION:
|
||||
case WID_ROT_TRUCK_STATION:
|
||||
case WID_ROT_BUILD_WAYPOINT:
|
||||
if (RoadTypeIsRoad(this->roadtype)) this->DisableWidget(WID_ROT_ONE_WAY);
|
||||
this->SetWidgetDisabledState(WID_ROT_REMOVE, !this->IsWidgetLowered(clicked_widget));
|
||||
break;
|
||||
@@ -465,6 +493,12 @@ struct BuildRoadToolbarWindow : Window {
|
||||
}
|
||||
break;
|
||||
|
||||
case WID_ROT_BUILD_WAYPOINT:
|
||||
if (HandlePlacePushButton(this, WID_ROT_BUILD_WAYPOINT, SPR_CURSOR_WAYPOINT, HT_RECT)) {
|
||||
this->last_started_action = widget;
|
||||
}
|
||||
break;
|
||||
|
||||
case WID_ROT_BUS_STATION:
|
||||
if (HandlePlacePushButton(this, WID_ROT_BUS_STATION, SPR_CURSOR_BUS_STATION, HT_RECT)) {
|
||||
ShowRVStationPicker(this, ROADSTOP_BUS);
|
||||
@@ -554,6 +588,10 @@ struct BuildRoadToolbarWindow : Window {
|
||||
CMD_BUILD_ROAD_DEPOT | CMD_MSG(this->rti->strings.err_depot), CcRoadDepot);
|
||||
break;
|
||||
|
||||
case WID_ROT_BUILD_WAYPOINT:
|
||||
PlaceRoad_Waypoint(tile);
|
||||
break;
|
||||
|
||||
case WID_ROT_BUS_STATION:
|
||||
PlaceRoad_BusStation(tile);
|
||||
break;
|
||||
@@ -675,6 +713,22 @@ struct BuildRoadToolbarWindow : Window {
|
||||
CMD_BUILD_LONG_ROAD | CMD_MSG(this->rti->strings.err_build_road), CcPlaySound_CONSTRUCTION_OTHER);
|
||||
break;
|
||||
|
||||
case DDSP_BUILD_ROAD_WAYPOINT:
|
||||
case DDSP_REMOVE_ROAD_WAYPOINT:
|
||||
if (this->IsWidgetLowered(WID_ROT_BUILD_WAYPOINT)) {
|
||||
TileArea ta(start_tile, end_tile);
|
||||
if (_remove_button_clicked) {
|
||||
DoCommandP(ta.tile, ta.w | ta.h << 8, (1 << 2), CMD_REMOVE_ROAD_STOP | CMD_MSG(STR_ERROR_CAN_T_REMOVE_ROAD_WAYPOINT), CcPlaySound_CONSTRUCTION_OTHER);
|
||||
} else {
|
||||
uint32 p1 = ta.w | ta.h << 8 | _ctrl_pressed << 16 | (select_method == VPM_X_LIMITED ? AXIS_X : AXIS_Y) << 17;
|
||||
uint32 p2 = INVALID_STATION << 16;
|
||||
|
||||
CommandContainer cmdcont = NewCommandContainerBasic(ta.tile, p1, p2, CMD_BUILD_ROAD_WAYPOINT | CMD_MSG(STR_ERROR_CAN_T_BUILD_ROAD_WAYPOINT), CcPlaySound_CONSTRUCTION_OTHER);
|
||||
ShowSelectWaypointIfNeeded(cmdcont, ta);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case DDSP_BUILD_BUSSTOP:
|
||||
case DDSP_REMOVE_BUSSTOP:
|
||||
if (this->IsWidgetLowered(WID_ROT_BUS_STATION)) {
|
||||
@@ -812,6 +866,8 @@ static const NWidgetPart _nested_build_road_widgets[] = {
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_DEPOT),
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_DEPOT, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_ROAD_VEHICLE_DEPOT),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_BUILD_WAYPOINT),
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_WAYPOINT, STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_ROAD_TO_WAYPOINT),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_BUS_STATION),
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_BUS_STATION, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_BUS_STATION),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_TRUCK_STATION),
|
||||
@@ -855,6 +911,8 @@ static const NWidgetPart _nested_build_tramway_widgets[] = {
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_DYNAMITE, STR_TOOLTIP_DEMOLISH_BUILDINGS_ETC),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_DEPOT),
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_ROAD_DEPOT, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_TRAM_VEHICLE_DEPOT),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_BUILD_WAYPOINT),
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_WAYPOINT, STR_ROAD_TOOLBAR_TOOLTIP_CONVERT_TRAM_TO_WAYPOINT),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_BUS_STATION),
|
||||
SetFill(0, 1), SetMinimalSize(22, 22), SetDataTip(SPR_IMG_BUS_STATION, STR_ROAD_TOOLBAR_TOOLTIP_BUILD_PASSENGER_TRAM_STATION),
|
||||
NWidget(WWT_IMGBTN, COLOUR_DARK_GREEN, WID_ROT_TRUCK_STATION),
|
||||
@@ -1314,7 +1372,7 @@ static void SetDefaultRoadGui()
|
||||
std::array<uint, ROADTYPE_END> tram_count = {};
|
||||
for (TileIndex t = 0; t < MapSize(); t++) {
|
||||
if (MayHaveRoad(t)) {
|
||||
if (IsTileType(t, MP_STATION) && !IsRoadStop(t)) continue;
|
||||
if (IsTileType(t, MP_STATION) && !IsAnyRoadStop(t)) continue;
|
||||
RoadType road_type = GetRoadTypeRoad(t);
|
||||
if (road_type != INVALID_ROADTYPE) road_count[road_type]++;
|
||||
RoadType tram_type = GetRoadTypeTram(t);
|
||||
|
@@ -44,7 +44,7 @@ RoadBits GetAnyRoadBits(TileIndex tile, RoadTramType rtt, bool straight_tunnel_b
|
||||
}
|
||||
|
||||
case MP_STATION:
|
||||
if (!IsRoadStopTile(tile)) return ROAD_NONE;
|
||||
if (!IsAnyRoadStopTile(tile)) return ROAD_NONE;
|
||||
if (IsDriveThroughStopTile(tile)) return (GetRoadStopDir(tile) == DIAGDIR_NE) ? ROAD_X : ROAD_Y;
|
||||
return DiagDirToRoadBits(GetRoadStopDir(tile));
|
||||
|
||||
|
@@ -1804,7 +1804,7 @@ again:
|
||||
v->tile != tile) {
|
||||
/* So, keep 'our' state */
|
||||
dir = (Trackdir)v->state;
|
||||
} else if (IsRoadStop(v->tile)) {
|
||||
} else if (IsStationRoadStop(v->tile)) {
|
||||
/* We're not continuing our drive through road stop, so leave. */
|
||||
RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile))->Leave(v);
|
||||
}
|
||||
|
@@ -1234,7 +1234,7 @@ bool AfterLoadGame()
|
||||
break;
|
||||
|
||||
case MP_STATION:
|
||||
if (IsRoadStop(t)) SB(_me[t].m7, 6, 2, 1);
|
||||
if (IsStationRoadStop(t)) SB(_me[t].m7, 6, 2, 1);
|
||||
break;
|
||||
|
||||
case MP_TUNNELBRIDGE:
|
||||
@@ -1288,7 +1288,7 @@ bool AfterLoadGame()
|
||||
break;
|
||||
|
||||
case MP_STATION:
|
||||
if (!IsRoadStop(t)) break;
|
||||
if (!IsStationRoadStop(t)) break;
|
||||
|
||||
if (fix_roadtypes) SB(_me[t].m7, 6, 2, (RoadTypes)GB(_m[t].m3, 0, 3));
|
||||
SB(_me[t].m7, 0, 5, HasBit(_me[t].m6, 2) ? OWNER_TOWN : GetTileOwner(t));
|
||||
@@ -1445,7 +1445,7 @@ bool AfterLoadGame()
|
||||
has_road = true;
|
||||
break;
|
||||
case MP_STATION:
|
||||
has_road = IsRoadStop(t);
|
||||
has_road = IsAnyRoadStop(t);
|
||||
break;
|
||||
case MP_TUNNELBRIDGE:
|
||||
has_road = GetTunnelBridgeTransportType(t) == TRANSPORT_ROAD;
|
||||
@@ -1499,7 +1499,7 @@ bool AfterLoadGame()
|
||||
has_road = true;
|
||||
break;
|
||||
case MP_STATION:
|
||||
has_road = IsRoadStop(t);
|
||||
has_road = IsAnyRoadStop(t);
|
||||
break;
|
||||
case MP_TUNNELBRIDGE:
|
||||
has_road = GetTunnelBridgeTransportType(t) == TRANSPORT_ROAD;
|
||||
|
@@ -160,7 +160,8 @@ void AfterLoadCompanyStats()
|
||||
break;
|
||||
|
||||
case STATION_BUS:
|
||||
case STATION_TRUCK: {
|
||||
case STATION_TRUCK:
|
||||
case STATION_ROADWAYPOINT: {
|
||||
/* Iterate all present road types as each can have a different owner. */
|
||||
for (RoadTramType rtt : _roadtramtypes) {
|
||||
RoadType rt = GetRoadType(tile, rtt);
|
||||
|
@@ -166,6 +166,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
|
||||
{ XSLFI_ST_INDUSTRY_CARGO_MODE, XSCF_IGNORABLE_UNKNOWN, 1, 1, "st_industry_cargo_mode", nullptr, nullptr, nullptr },
|
||||
{ XSLFI_TL_SPEED_LIMIT, XSCF_IGNORABLE_UNKNOWN, 1, 1, "tl_speed_limit", nullptr, nullptr, nullptr },
|
||||
{ XSLFI_WAYPOINT_FLAGS, XSCF_NULL, 1, 1, "waypoint_flags", nullptr, nullptr, nullptr },
|
||||
{ XSLFI_ROAD_WAYPOINTS, XSCF_NULL, 1, 1, "road_waypoints", nullptr, nullptr, nullptr },
|
||||
{ XSLFI_MORE_STATION_TYPES, XSCF_NULL, 1, 1, "more_station_types", nullptr, nullptr, nullptr },
|
||||
{ XSLFI_SCRIPT_INT64, XSCF_NULL, 1, 1, "script_int64", nullptr, nullptr, nullptr },
|
||||
{ XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker
|
||||
|
@@ -120,6 +120,7 @@ enum SlXvFeatureIndex {
|
||||
XSLFI_ST_INDUSTRY_CARGO_MODE, ///< Station industry cargo mode setting
|
||||
XSLFI_TL_SPEED_LIMIT, ///< Through load maximum speed setting
|
||||
XSLFI_WAYPOINT_FLAGS, ///< Waypoint flags
|
||||
XSLFI_ROAD_WAYPOINTS, ///< Road waypoints
|
||||
XSLFI_MORE_STATION_TYPES, ///< More station types (field widening)
|
||||
|
||||
XSLFI_SCRIPT_INT64, ///< See: SLV_SCRIPT_INT64
|
||||
|
@@ -462,6 +462,9 @@ static const SaveLoad _waypoint_desc[] = {
|
||||
SLE_CONDVAR(Waypoint, train_station.w, SLE_FILE_U8 | SLE_VAR_U16, SLV_124, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Waypoint, train_station.h, SLE_FILE_U8 | SLE_VAR_U16, SLV_124, SL_MAX_VERSION),
|
||||
SLE_CONDVAR_X(Waypoint, waypoint_flags, SLE_UINT16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_WAYPOINT_FLAGS)),
|
||||
SLE_CONDVAR_X(Waypoint, road_waypoint_area.tile, SLE_UINT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_ROAD_WAYPOINTS)),
|
||||
SLE_CONDVAR_X(Waypoint, road_waypoint_area.w, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_ROAD_WAYPOINTS)),
|
||||
SLE_CONDVAR_X(Waypoint, road_waypoint_area.h, SLE_FILE_U8 | SLE_VAR_U16, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_ROAD_WAYPOINTS)),
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -1135,6 +1135,8 @@ static byte GetTopographyValue(TileIndex tile)
|
||||
return MKCOLOUR(PC_WATER);
|
||||
case STATION_WAYPOINT:
|
||||
return MKCOLOUR(PC_GREY);
|
||||
case STATION_ROADWAYPOINT:
|
||||
return MKCOLOUR(PC_GREY);
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
}
|
||||
@@ -1228,6 +1230,8 @@ static byte GetIndustryValue(TileIndex tile)
|
||||
return MKCOLOUR(PC_BLACK);
|
||||
case STATION_WAYPOINT:
|
||||
return MKCOLOUR(PC_GREY);
|
||||
case STATION_ROADWAYPOINT:
|
||||
return MKCOLOUR(PC_GREY);
|
||||
default: NOT_REACHED();
|
||||
}
|
||||
}
|
||||
|
@@ -50,7 +50,7 @@
|
||||
if (!::IsValidTile(tile)) return false;
|
||||
if (!IsRoadTypeAvailable(GetCurrentRoadType())) return false;
|
||||
|
||||
return ::IsRoadStopTile(tile) && HasBit(::GetPresentRoadTypes(tile), (::RoadType)GetCurrentRoadType());
|
||||
return ::IsStationRoadStopTile(tile) && HasBit(::GetPresentRoadTypes(tile), (::RoadType)GetCurrentRoadType());
|
||||
}
|
||||
|
||||
/* static */ bool ScriptRoad::IsDriveThroughRoadStationTile(TileIndex tile)
|
||||
@@ -624,7 +624,7 @@ static bool NeighbourHasReachableRoad(::RoadType rt, TileIndex start_tile, DiagD
|
||||
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
|
||||
EnforcePrecondition(false, ::IsValidTile(tile));
|
||||
EnforcePrecondition(false, IsTileType(tile, MP_STATION));
|
||||
EnforcePrecondition(false, IsRoadStop(tile));
|
||||
EnforcePrecondition(false, IsStationRoadStop(tile));
|
||||
|
||||
return ScriptObject::DoCommand(tile, 1 | 1 << 8, GetRoadStopType(tile), CMD_REMOVE_ROAD_STOP);
|
||||
}
|
||||
|
@@ -314,13 +314,15 @@ static uint GetTileCatchmentRadius(TileIndex tile, const Station *st)
|
||||
|
||||
default: NOT_REACHED();
|
||||
case STATION_BUOY:
|
||||
case STATION_WAYPOINT: return CA_NONE;
|
||||
case STATION_WAYPOINT:
|
||||
case STATION_ROADWAYPOINT: return CA_NONE;
|
||||
}
|
||||
} else {
|
||||
switch (GetStationType(tile)) {
|
||||
default: return CA_UNMODIFIED + inc;
|
||||
case STATION_BUOY:
|
||||
case STATION_WAYPOINT: return CA_NONE;
|
||||
case STATION_WAYPOINT:
|
||||
case STATION_ROADWAYPOINT: return CA_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -98,8 +98,8 @@ bool IsHangar(TileIndex t)
|
||||
* @param st to 'return' the found station
|
||||
* @return Succeeded command (if zero or one station found) or failed command (for two or more stations found).
|
||||
*/
|
||||
template <class T>
|
||||
CommandCost GetStationAround(TileArea ta, StationID closest_station, CompanyID company, T **st)
|
||||
template <class T, class F>
|
||||
CommandCost GetStationAround(TileArea ta, StationID closest_station, CompanyID company, T **st, F filter)
|
||||
{
|
||||
ta.Expand(1);
|
||||
|
||||
@@ -107,7 +107,7 @@ CommandCost GetStationAround(TileArea ta, StationID closest_station, CompanyID c
|
||||
for (TileIndex tile_cur : ta) {
|
||||
if (IsTileType(tile_cur, MP_STATION)) {
|
||||
StationID t = GetStationIndex(tile_cur);
|
||||
if (!T::IsValidID(t) || Station::Get(t)->owner != company) continue;
|
||||
if (!T::IsValidID(t) || T::Get(t)->owner != company || !filter(T::Get(t))) continue;
|
||||
if (closest_station == INVALID_STATION) {
|
||||
closest_station = t;
|
||||
} else if (closest_station != t) {
|
||||
@@ -1068,13 +1068,14 @@ static CommandCost CheckFlatLandRailStation(TileArea tile_area, DoCommandFlag fl
|
||||
* @param flags Operation to perform.
|
||||
* @param invalid_dirs Prohibited directions (set of DiagDirections).
|
||||
* @param is_drive_through True if trying to build a drive-through station.
|
||||
* @param is_truck_stop True when building a truck stop, false otherwise.
|
||||
* @param station_type Station type (bus, truck or road waypoint).
|
||||
* @param axis Axis of a drive-through road stop.
|
||||
* @param station StationID to be queried and returned if available.
|
||||
* @param rt Road type to build.
|
||||
* @param require_road Is existing road required.
|
||||
* @return The cost in case of success, or an error code if it failed.
|
||||
*/
|
||||
static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags, uint invalid_dirs, bool is_drive_through, bool is_truck_stop, Axis axis, StationID *station, RoadType rt)
|
||||
CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags, uint invalid_dirs, bool is_drive_through, StationType station_type, Axis axis, StationID *station, RoadType rt, bool require_road)
|
||||
{
|
||||
CommandCost cost(EXPENSES_CONSTRUCTION);
|
||||
int allowed_z = -1;
|
||||
@@ -1097,10 +1098,10 @@ static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags
|
||||
* Station points to INVALID_STATION if we can build on any station.
|
||||
* Or it points to a station if we're only allowed to build on exactly that station. */
|
||||
if (station != nullptr && IsTileType(cur_tile, MP_STATION)) {
|
||||
if (!IsRoadStop(cur_tile)) {
|
||||
if (!IsAnyRoadStop(cur_tile)) {
|
||||
return ClearTile_Station(cur_tile, DC_AUTO); // Get error message.
|
||||
} else {
|
||||
if (is_truck_stop != IsTruckStop(cur_tile) ||
|
||||
if (station_type != GetStationType(cur_tile) ||
|
||||
is_drive_through != IsDriveThroughStopTile(cur_tile)) {
|
||||
return ClearTile_Station(cur_tile, DC_AUTO); // Get error message.
|
||||
}
|
||||
@@ -1147,10 +1148,10 @@ static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags
|
||||
}
|
||||
uint num_pieces = CountBits(GetRoadBits(cur_tile, RTT_ROAD));
|
||||
|
||||
if (RoadTypeIsRoad(rt) && !HasPowerOnRoad(rt, road_rt)) return_cmd_error(STR_ERROR_NO_SUITABLE_ROAD);
|
||||
if (rt != INVALID_ROADTYPE && RoadTypeIsRoad(rt) && !HasPowerOnRoad(rt, road_rt)) return_cmd_error(STR_ERROR_NO_SUITABLE_ROAD);
|
||||
|
||||
cost.AddCost(RoadBuildCost(road_rt) * (2 - num_pieces));
|
||||
} else if (RoadTypeIsRoad(rt)) {
|
||||
} else if (rt != INVALID_ROADTYPE && RoadTypeIsRoad(rt)) {
|
||||
cost.AddCost(RoadBuildCost(rt) * 2);
|
||||
}
|
||||
|
||||
@@ -1168,12 +1169,14 @@ static CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags
|
||||
}
|
||||
uint num_pieces = CountBits(GetRoadBits(cur_tile, RTT_TRAM));
|
||||
|
||||
if (RoadTypeIsTram(rt) && !HasPowerOnRoad(rt, tram_rt)) return_cmd_error(STR_ERROR_NO_SUITABLE_ROAD);
|
||||
if (rt != INVALID_ROADTYPE && RoadTypeIsTram(rt) && !HasPowerOnRoad(rt, tram_rt)) return_cmd_error(STR_ERROR_NO_SUITABLE_ROAD);
|
||||
|
||||
cost.AddCost(RoadBuildCost(tram_rt) * (2 - num_pieces));
|
||||
} else if (RoadTypeIsTram(rt)) {
|
||||
} else if (rt != INVALID_ROADTYPE && RoadTypeIsTram(rt)) {
|
||||
cost.AddCost(RoadBuildCost(rt) * 2);
|
||||
}
|
||||
} else if (require_road) {
|
||||
return_cmd_error(STR_ERROR_THERE_IS_NO_ROAD);
|
||||
} else {
|
||||
ret = DoCommand(cur_tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
|
||||
if (ret.Failed()) return ret;
|
||||
@@ -1316,8 +1319,8 @@ void GetStationLayout(byte *layout, uint numtracks, uint plat_len, const Station
|
||||
* @param error_message the error message when building a station on top of others
|
||||
* @return command cost with the error or 'okay'
|
||||
*/
|
||||
template <class T>
|
||||
CommandCost FindJoiningBaseStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, T **st, StringID error_message)
|
||||
template <class T, class F>
|
||||
CommandCost FindJoiningBaseStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, T **st, StringID error_message, F filter)
|
||||
{
|
||||
assert(*st == nullptr);
|
||||
bool check_surrounding = true;
|
||||
@@ -1331,7 +1334,8 @@ CommandCost FindJoiningBaseStation(StationID existing_station, StationID station
|
||||
} else {
|
||||
/* Extend the current station, and don't check whether it will
|
||||
* be near any other stations. */
|
||||
*st = T::GetIfValid(existing_station);
|
||||
T *candidate = T::GetIfValid(existing_station);
|
||||
if (candidate != nullptr && filter(candidate)) *st = candidate;
|
||||
check_surrounding = (*st == nullptr);
|
||||
}
|
||||
} else {
|
||||
@@ -1343,7 +1347,7 @@ CommandCost FindJoiningBaseStation(StationID existing_station, StationID station
|
||||
|
||||
if (check_surrounding) {
|
||||
/* Make sure there is no more than one other station around us that is owned by us. */
|
||||
CommandCost ret = GetStationAround(ta, existing_station, _current_company, st);
|
||||
CommandCost ret = GetStationAround(ta, existing_station, _current_company, st, filter);
|
||||
if (ret.Failed()) return ret;
|
||||
}
|
||||
|
||||
@@ -1365,7 +1369,7 @@ CommandCost FindJoiningBaseStation(StationID existing_station, StationID station
|
||||
*/
|
||||
static CommandCost FindJoiningStation(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, Station **st, StringID error_message = STR_ERROR_MUST_REMOVE_RAILWAY_STATION_FIRST)
|
||||
{
|
||||
return FindJoiningBaseStation<Station>(existing_station, station_to_join, adjacent, ta, st, error_message);
|
||||
return FindJoiningBaseStation<Station>(existing_station, station_to_join, adjacent, ta, st, error_message, [](Station *st) -> bool { return true; });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1377,9 +1381,11 @@ static CommandCost FindJoiningStation(StationID existing_station, StationID stat
|
||||
* @param wp 'return' pointer for the found waypoint
|
||||
* @return command cost with the error or 'okay'
|
||||
*/
|
||||
CommandCost FindJoiningWaypoint(StationID existing_waypoint, StationID waypoint_to_join, bool adjacent, TileArea ta, Waypoint **wp)
|
||||
CommandCost FindJoiningWaypoint(StationID existing_waypoint, StationID waypoint_to_join, bool adjacent, TileArea ta, Waypoint **wp, bool is_road)
|
||||
{
|
||||
return FindJoiningBaseStation<Waypoint>(existing_waypoint, waypoint_to_join, adjacent, ta, wp, STR_ERROR_MUST_REMOVE_RAILWAYPOINT_FIRST);
|
||||
return FindJoiningBaseStation<Waypoint>(existing_waypoint, waypoint_to_join, adjacent, ta, wp,
|
||||
is_road ? STR_ERROR_MUST_REMOVE_ROADWAYPOINT_FIRST : STR_ERROR_MUST_REMOVE_RAILWAYPOINT_FIRST,
|
||||
[is_road](Waypoint *wp) -> bool { return HasBit(wp->waypoint_flags, WPF_ROAD) == is_road; });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1736,6 +1742,16 @@ static void MakeShipStationAreaSmaller(Station *st)
|
||||
UpdateStationDockingTiles(st);
|
||||
}
|
||||
|
||||
static bool TileBelongsToRoadWaypointStation(BaseStation *st, TileIndex tile)
|
||||
{
|
||||
return IsRoadWaypointTile(tile) && GetStationIndex(tile) == st->index;
|
||||
}
|
||||
|
||||
void MakeRoadWaypointStationAreaSmaller(BaseStation *st, TileArea &road_waypoint_area)
|
||||
{
|
||||
road_waypoint_area = MakeStationAreaSmaller(st, road_waypoint_area, TileBelongsToRoadWaypointStation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a number of tiles from any rail station within the area.
|
||||
* @param ta the area to clear station tile from.
|
||||
@@ -2004,7 +2020,7 @@ static RoadStop **FindRoadStopSpot(bool truck_station, Station *st)
|
||||
}
|
||||
}
|
||||
|
||||
static CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlag flags);
|
||||
CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlag flags);
|
||||
|
||||
/**
|
||||
* Find a nearby station that joins this road stop.
|
||||
@@ -2017,7 +2033,7 @@ static CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlag flags);
|
||||
*/
|
||||
static CommandCost FindJoiningRoadStop(StationID existing_stop, StationID station_to_join, bool adjacent, TileArea ta, Station **st)
|
||||
{
|
||||
return FindJoiningBaseStation<Station>(existing_stop, station_to_join, adjacent, ta, st, STR_ERROR_MUST_REMOVE_ROAD_STOP_FIRST);
|
||||
return FindJoiningBaseStation<Station>(existing_stop, station_to_join, adjacent, ta, st, STR_ERROR_MUST_REMOVE_ROAD_STOP_FIRST, [](Station *st) -> bool { return true; });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2082,7 +2098,7 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
|
||||
/* Total road stop cost. */
|
||||
CommandCost cost(EXPENSES_CONSTRUCTION, roadstop_area.w * roadstop_area.h * _price[type ? PR_BUILD_STATION_TRUCK : PR_BUILD_STATION_BUS]);
|
||||
StationID est = INVALID_STATION;
|
||||
ret = CheckFlatLandRoadStop(roadstop_area, flags, is_drive_through ? 5 << axis : 1 << ddir, is_drive_through, type, axis, &est, rt);
|
||||
ret = CheckFlatLandRoadStop(roadstop_area, flags, is_drive_through ? 5 << axis : 1 << ddir, is_drive_through, type ? STATION_TRUCK : STATION_BUS, axis, &est, rt, false);
|
||||
if (ret.Failed()) return ret;
|
||||
cost.AddCost(ret);
|
||||
|
||||
@@ -2106,7 +2122,7 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
|
||||
Owner tram_owner = tram_rt != INVALID_ROADTYPE ? GetRoadOwner(cur_tile, RTT_TRAM) : _current_company;
|
||||
DisallowedRoadDirections drd = IsNormalRoadTile(cur_tile) ? GetDisallowedRoadDirections(cur_tile) : DRD_NONE;
|
||||
|
||||
if (IsTileType(cur_tile, MP_STATION) && IsRoadStop(cur_tile)) {
|
||||
if (IsTileType(cur_tile, MP_STATION) && IsAnyRoadStop(cur_tile)) {
|
||||
RemoveRoadStop(cur_tile, flags);
|
||||
}
|
||||
|
||||
@@ -2141,7 +2157,7 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
|
||||
UpdateCompanyRoadInfrastructure(road_rt, road_owner, ROAD_STOP_TRACKBIT_FACTOR);
|
||||
UpdateCompanyRoadInfrastructure(tram_rt, tram_owner, ROAD_STOP_TRACKBIT_FACTOR);
|
||||
|
||||
MakeDriveThroughRoadStop(cur_tile, st->owner, road_owner, tram_owner, st->index, rs_type, road_rt, tram_rt, axis);
|
||||
MakeDriveThroughRoadStop(cur_tile, st->owner, road_owner, tram_owner, st->index, (rs_type == ROADSTOP_BUS ? STATION_BUS : STATION_TRUCK), road_rt, tram_rt, axis);
|
||||
SetDriveThroughStopDisallowedRoadDirections(cur_tile, drd);
|
||||
road_stop->MakeDriveThrough();
|
||||
} else {
|
||||
@@ -2154,10 +2170,10 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
|
||||
Company::Get(st->owner)->infrastructure.station++;
|
||||
|
||||
MarkTileDirtyByTile(cur_tile);
|
||||
UpdateRoadCachedOneWayStatesAroundTile(cur_tile);
|
||||
}
|
||||
ZoningMarkDirtyStationCoverageArea(st);
|
||||
NotifyRoadLayoutChanged(true);
|
||||
UpdateRoadCachedOneWayStatesAroundTile(tile);
|
||||
|
||||
if (st != nullptr) {
|
||||
st->AfterStationTileSetChange(true, type ? STATION_TRUCK: STATION_BUS);
|
||||
@@ -2181,6 +2197,52 @@ static Vehicle *ClearRoadStopStatusEnum(Vehicle *v, void *)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CommandCost RemoveRoadWaypointStop(TileIndex tile, DoCommandFlag flags)
|
||||
{
|
||||
Waypoint *wp = Waypoint::GetByTile(tile);
|
||||
|
||||
if (_current_company != OWNER_WATER) {
|
||||
CommandCost ret = CheckOwnership(wp->owner);
|
||||
if (ret.Failed()) return ret;
|
||||
}
|
||||
|
||||
/* don't do the check for drive-through road stops when company bankrupts */
|
||||
if (!(flags & DC_BANKRUPT)) {
|
||||
CommandCost ret = EnsureNoVehicleOnGround(tile);
|
||||
if (ret.Failed()) return ret;
|
||||
}
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
/* Update company infrastructure counts. */
|
||||
for (RoadTramType rtt : _roadtramtypes) {
|
||||
RoadType rt = GetRoadType(tile, rtt);
|
||||
UpdateCompanyRoadInfrastructure(rt, GetRoadOwner(tile, rtt), -static_cast<int>(ROAD_STOP_TRACKBIT_FACTOR));
|
||||
}
|
||||
|
||||
Company::Get(wp->owner)->infrastructure.station--;
|
||||
DirtyCompanyInfrastructureWindows(wp->owner);
|
||||
|
||||
DoClearSquare(tile);
|
||||
|
||||
wp->rect.AfterRemoveTile(wp, tile);
|
||||
|
||||
MakeRoadWaypointStationAreaSmaller(wp, wp->road_waypoint_area);
|
||||
|
||||
UpdateStationSignCoord(wp);
|
||||
|
||||
/* if we deleted the whole waypoint, delete the road facility. */
|
||||
if (wp->road_waypoint_area.tile == INVALID_TILE) {
|
||||
wp->facilities &= ~(FACIL_BUS_STOP | FACIL_TRUCK_STOP);
|
||||
SetWindowWidgetDirty(WC_STATION_VIEW, wp->index, WID_SV_ROADVEHS);
|
||||
wp->UpdateVirtCoord();
|
||||
DeleteStationIfEmpty(wp);
|
||||
}
|
||||
|
||||
NotifyRoadLayoutChanged(false);
|
||||
}
|
||||
|
||||
return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_CLEAR_STATION_TRUCK]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a bus station/truck stop
|
||||
@@ -2188,8 +2250,12 @@ static Vehicle *ClearRoadStopStatusEnum(Vehicle *v, void *)
|
||||
* @param flags operation to perform
|
||||
* @return cost or failure of operation
|
||||
*/
|
||||
static CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlag flags)
|
||||
CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlag flags)
|
||||
{
|
||||
if (IsRoadWaypoint(tile)) {
|
||||
return RemoveRoadWaypointStop(tile, flags);
|
||||
}
|
||||
|
||||
Station *st = Station::GetByTile(tile);
|
||||
|
||||
if (_current_company != OWNER_WATER) {
|
||||
@@ -2289,6 +2355,7 @@ static CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlag flags)
|
||||
* bit 8..15: Height of the removal area.
|
||||
* @param p2 bit 0: 0 For bus stops, 1 for truck stops.
|
||||
* @param p2 bit 1: 0 to keep roads of all drive-through stops, 1 to remove them.
|
||||
* @param p2 bit 2: 0 for bus/truck stops, 1 for road waypoints.
|
||||
* @param text Unused.
|
||||
* @return The cost of this operation or an error.
|
||||
*/
|
||||
@@ -2296,7 +2363,7 @@ CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, ui
|
||||
{
|
||||
uint8 width = (uint8)GB(p1, 0, 8);
|
||||
uint8 height = (uint8)GB(p1, 8, 8);
|
||||
bool keep_drive_through_roads = !HasBit(p2, 1);
|
||||
bool keep_drive_through_roads = !HasBit(p2, 1) || HasBit(p2, 2);
|
||||
|
||||
/* Check for incorrect width / height. */
|
||||
if (width == 0 || height == 0) return CMD_ERROR;
|
||||
@@ -2312,8 +2379,13 @@ CommandCost CmdRemoveRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, ui
|
||||
bool had_success = false;
|
||||
|
||||
for (TileIndex cur_tile : roadstop_area) {
|
||||
if (HasBit(p2, 2)) {
|
||||
/* Make sure the specified tile is a road waypoint */
|
||||
if (!IsTileType(cur_tile, MP_STATION) || !IsRoadWaypoint(cur_tile)) continue;
|
||||
} else {
|
||||
/* Make sure the specified tile is a road stop of the correct type */
|
||||
if (!IsTileType(cur_tile, MP_STATION) || !IsRoadStop(cur_tile) || (uint32)GetRoadStopType(cur_tile) != GB(p2, 0, 1)) continue;
|
||||
if (!IsTileType(cur_tile, MP_STATION) || !IsStationRoadStop(cur_tile) || (uint32)GetRoadStopType(cur_tile) != GB(p2, 0, 1)) continue;
|
||||
}
|
||||
|
||||
/* Save information on to-be-restored roads before the stop is removed. */
|
||||
RoadBits road_bits = ROAD_NONE;
|
||||
@@ -3336,7 +3408,7 @@ draw_default_foundation:
|
||||
|
||||
if (HasStationRail(ti->tile) && HasRailCatenaryDrawn(GetRailType(ti->tile))) DrawRailCatenary(ti);
|
||||
|
||||
if (IsRoadStop(ti->tile)) {
|
||||
if (IsAnyRoadStop(ti->tile)) {
|
||||
RoadType road_rt = GetRoadTypeRoad(ti->tile);
|
||||
RoadType tram_rt = GetRoadTypeTram(ti->tile);
|
||||
const RoadTypeInfo* road_rti = road_rt == INVALID_ROADTYPE ? nullptr : GetRoadTypeInfo(road_rt);
|
||||
@@ -3441,7 +3513,7 @@ static void GetTileDesc_Station(TileIndex tile, TileDesc *td)
|
||||
{
|
||||
td->owner[0] = GetTileOwner(tile);
|
||||
|
||||
if (IsRoadStopTile(tile)) {
|
||||
if (IsAnyRoadStopTile(tile)) {
|
||||
RoadType road_rt = GetRoadTypeRoad(tile);
|
||||
RoadType tram_rt = GetRoadTypeTram(tile);
|
||||
Owner road_owner = INVALID_OWNER;
|
||||
@@ -3535,6 +3607,7 @@ static void GetTileDesc_Station(TileIndex tile, TileDesc *td)
|
||||
case STATION_DOCK: str = STR_LAI_STATION_DESCRIPTION_SHIP_DOCK; break;
|
||||
case STATION_BUOY: str = STR_LAI_STATION_DESCRIPTION_BUOY; break;
|
||||
case STATION_WAYPOINT: str = STR_LAI_STATION_DESCRIPTION_WAYPOINT; break;
|
||||
case STATION_ROADWAYPOINT: str = STR_LAI_STATION_DESCRIPTION_WAYPOINT; break;
|
||||
}
|
||||
td->str = str;
|
||||
}
|
||||
@@ -3564,7 +3637,7 @@ static TrackStatus GetTileTrackStatus_Station(TileIndex tile, TransportType mode
|
||||
break;
|
||||
|
||||
case TRANSPORT_ROAD:
|
||||
if (IsRoadStop(tile)) {
|
||||
if (IsAnyRoadStop(tile)) {
|
||||
RoadTramType rtt = (RoadTramType)sub_mode;
|
||||
if (!HasTileRoadType(tile, rtt)) break;
|
||||
|
||||
@@ -3733,7 +3806,7 @@ static VehicleEnterTileStatus VehicleEnter_Station(Vehicle *v, TileIndex tile, i
|
||||
} else if (v->type == VEH_ROAD) {
|
||||
RoadVehicle *rv = RoadVehicle::From(v);
|
||||
if (rv->state < RVSB_IN_ROAD_STOP && !IsReversingRoadTrackdir((Trackdir)rv->state) && rv->frame == 0) {
|
||||
if (IsRoadStop(tile) && rv->IsFrontEngine()) {
|
||||
if (IsStationRoadStop(tile) && rv->IsFrontEngine()) {
|
||||
/* Attempt to allocate a parking bay in a road stop */
|
||||
return RoadStop::GetByTile(tile, GetRoadStopType(tile))->Enter(rv) ? VETSB_CONTINUE : VETSB_CANNOT_ENTER;
|
||||
}
|
||||
@@ -4712,7 +4785,7 @@ void DeleteOilRig(TileIndex tile)
|
||||
|
||||
static void ChangeTileOwner_Station(TileIndex tile, Owner old_owner, Owner new_owner)
|
||||
{
|
||||
if (IsRoadStopTile(tile)) {
|
||||
if (IsAnyRoadStopTile(tile)) {
|
||||
for (RoadTramType rtt : _roadtramtypes) {
|
||||
/* Update all roadtypes, no matter if they are present */
|
||||
if (GetRoadOwner(tile, rtt) == old_owner) {
|
||||
@@ -4749,6 +4822,7 @@ static void ChangeTileOwner_Station(TileIndex tile, Owner old_owner, Owner new_o
|
||||
|
||||
case STATION_BUS:
|
||||
case STATION_TRUCK:
|
||||
case STATION_ROADWAYPOINT:
|
||||
/* Road stops were already handled above. */
|
||||
break;
|
||||
|
||||
@@ -4839,6 +4913,7 @@ CommandCost ClearTile_Station(TileIndex tile, DoCommandFlag flags)
|
||||
default: break;
|
||||
case STATION_RAIL: return_cmd_error(STR_ERROR_MUST_DEMOLISH_RAILROAD);
|
||||
case STATION_WAYPOINT: return_cmd_error(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
|
||||
case STATION_ROADWAYPOINT: return_cmd_error(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
|
||||
case STATION_AIRPORT: return_cmd_error(STR_ERROR_MUST_DEMOLISH_AIRPORT_FIRST);
|
||||
case STATION_TRUCK: return_cmd_error(HasTileRoadType(tile, RTT_TRAM) ? STR_ERROR_MUST_DEMOLISH_CARGO_TRAM_STATION_FIRST : STR_ERROR_MUST_DEMOLISH_TRUCK_STATION_FIRST);
|
||||
case STATION_BUS: return_cmd_error(HasTileRoadType(tile, RTT_TRAM) ? STR_ERROR_MUST_DEMOLISH_PASSENGER_TRAM_STATION_FIRST : STR_ERROR_MUST_DEMOLISH_BUS_STATION_FIRST);
|
||||
@@ -4866,6 +4941,11 @@ CommandCost ClearTile_Station(TileIndex tile, DoCommandFlag flags)
|
||||
return RemoveRoadStopAndUpdateRoadCachedOneWayState(tile, flags);
|
||||
case STATION_BUOY: return RemoveBuoy(tile, flags);
|
||||
case STATION_DOCK: return RemoveDock(tile, flags);
|
||||
case STATION_ROADWAYPOINT:
|
||||
if (IsDriveThroughStopTile(tile) && !CanRemoveRoadWithStop(tile, flags)) {
|
||||
return_cmd_error(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
|
||||
}
|
||||
return RemoveRoadStopAndUpdateRoadCachedOneWayState(tile, flags);
|
||||
default: break;
|
||||
}
|
||||
|
||||
@@ -4892,7 +4972,8 @@ static CommandCost TerraformTile_Station(TileIndex tile, DoCommandFlag flags, in
|
||||
return CommandCost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_FOUNDATION]);
|
||||
|
||||
case STATION_TRUCK:
|
||||
case STATION_BUS: {
|
||||
case STATION_BUS:
|
||||
case STATION_ROADWAYPOINT: {
|
||||
DiagDirection direction = GetRoadStopDir(tile);
|
||||
if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, direction)) break;
|
||||
if (IsDriveThroughStopTile(tile)) {
|
||||
|
@@ -2326,6 +2326,10 @@ struct TileAndStation {
|
||||
|
||||
static std::vector<TileAndStation> _deleted_stations_nearby;
|
||||
static std::vector<StationID> _stations_nearby_list;
|
||||
static bool _station_nearby_road_waypoint_search;
|
||||
|
||||
static bool IsNearbyStationRightType(const Station *st) { return true; }
|
||||
static bool IsNearbyStationRightType(const Waypoint *wp) { return HasBit(wp->waypoint_flags, WPF_ROAD) == _station_nearby_road_waypoint_search; }
|
||||
|
||||
/**
|
||||
* Add station on this tile to _stations_nearby_list if it's fully within the
|
||||
@@ -2358,7 +2362,7 @@ static bool AddNearbyStation(TileIndex tile, void *user_data)
|
||||
if (!T::IsValidID(sid)) return false;
|
||||
|
||||
T *st = T::Get(sid);
|
||||
if (st->owner != _local_company || std::find(_stations_nearby_list.begin(), _stations_nearby_list.end(), sid) != _stations_nearby_list.end()) return false;
|
||||
if (st->owner != _local_company || !IsNearbyStationRightType(st) || std::find(_stations_nearby_list.begin(), _stations_nearby_list.end(), sid) != _stations_nearby_list.end()) return false;
|
||||
|
||||
if (st->rect.BeforeAddRect(ctx->tile, ctx->w, ctx->h, StationRect::ADD_TEST).Succeeded()) {
|
||||
_stations_nearby_list.push_back(sid);
|
||||
@@ -2391,7 +2395,7 @@ static const T *FindStationsNearby(TileArea ta, bool distant_join)
|
||||
|
||||
/* Look for deleted stations */
|
||||
for (const BaseStation *st : BaseStation::Iterate()) {
|
||||
if (T::IsExpected(st) && !st->IsInUse() && st->owner == _local_company) {
|
||||
if (T::IsExpected(st) && !st->IsInUse() && st->owner == _local_company && IsNearbyStationRightType(T::From(st))) {
|
||||
/* Include only within station spread (yes, it is strictly less than) */
|
||||
if (std::max(DistanceMax(ta.tile, st->xy), DistanceMax(TILE_ADDXY(ta.tile, ta.w - 1, ta.h - 1), st->xy)) < _settings_game.station.station_spread) {
|
||||
_deleted_stations_nearby.push_back({st->xy, st->index});
|
||||
@@ -2546,6 +2550,7 @@ struct SelectStationWindow : Window {
|
||||
void OnInvalidateData(int data = 0, bool gui_scope = true) override
|
||||
{
|
||||
if (!gui_scope) return;
|
||||
if (T::EXPECTED_FACIL == FACIL_WAYPOINT) _station_nearby_road_waypoint_search = (this->select_station_cmd.cmd & CMD_ID_MASK) == CMD_BUILD_ROAD_WAYPOINT;
|
||||
FindStationsNearby<T>(this->area, true);
|
||||
this->vscroll->SetCount((uint)_stations_nearby_list.size() + 1);
|
||||
this->SetDirty();
|
||||
@@ -2608,6 +2613,7 @@ static bool StationJoinerNeeded(const CommandContainer &cmd, TileArea ta)
|
||||
/* Test for adjacent station or station below selection.
|
||||
* If adjacent-stations is disabled and we are building next to a station, do not show the selection window.
|
||||
* but join the other station immediately. */
|
||||
if (T::EXPECTED_FACIL == FACIL_WAYPOINT) _station_nearby_road_waypoint_search = (cmd.cmd & CMD_ID_MASK) == CMD_BUILD_ROAD_WAYPOINT;
|
||||
const T *st = FindStationsNearby<T>(ta, false);
|
||||
return st == nullptr && (_settings_game.station.adjacent_stations || _stations_nearby_list.size() == 0);
|
||||
}
|
||||
|
@@ -193,13 +193,34 @@ static inline bool IsBusStop(TileIndex t)
|
||||
return GetStationType(t) == STATION_BUS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the station at \a t a road waypoint?
|
||||
* @param t Tile to check
|
||||
* @pre IsTileType(t, MP_STATION)
|
||||
* @return \c true if station is a road waypoint, \c false otherwise
|
||||
*/
|
||||
static inline bool IsRoadWaypoint(TileIndex t)
|
||||
{
|
||||
return GetStationType(t) == STATION_ROADWAYPOINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this tile a station tile and a road waypoint?
|
||||
* @param t the tile to get the information from
|
||||
* @return true if and only if the tile is a road waypoint
|
||||
*/
|
||||
static inline bool IsRoadWaypointTile(TileIndex t)
|
||||
{
|
||||
return IsTileType(t, MP_STATION) && IsRoadWaypoint(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the station at \a t a road station?
|
||||
* @param t Tile to check
|
||||
* @pre IsTileType(t, MP_STATION)
|
||||
* @return \c true if station at the tile is a bus top or a truck stop, \c false otherwise
|
||||
* @return \c true if station at the tile is a bus stop, truck stop \c false otherwise
|
||||
*/
|
||||
static inline bool IsRoadStop(TileIndex t)
|
||||
static inline bool IsStationRoadStop(TileIndex t)
|
||||
{
|
||||
assert_tile(IsTileType(t, MP_STATION), t);
|
||||
return IsTruckStop(t) || IsBusStop(t);
|
||||
@@ -210,9 +231,31 @@ static inline bool IsRoadStop(TileIndex t)
|
||||
* @param t Tile to check
|
||||
* @return \c true if the tile is a station tile and a road stop
|
||||
*/
|
||||
static inline bool IsRoadStopTile(TileIndex t)
|
||||
static inline bool IsStationRoadStopTile(TileIndex t)
|
||||
{
|
||||
return IsTileType(t, MP_STATION) && IsRoadStop(t);
|
||||
return IsTileType(t, MP_STATION) && IsStationRoadStop(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the station at \a t a road station?
|
||||
* @param t Tile to check
|
||||
* @pre IsTileType(t, MP_STATION)
|
||||
* @return \c true if station at the tile is a bus stop, truck stop or road waypoint, \c false otherwise
|
||||
*/
|
||||
static inline bool IsAnyRoadStop(TileIndex t)
|
||||
{
|
||||
assert_tile(IsTileType(t, MP_STATION), t);
|
||||
return IsTruckStop(t) || IsBusStop(t) || IsRoadWaypoint(t);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is tile \a t a road stop station?
|
||||
* @param t Tile to check
|
||||
* @return \c true if the tile is a station tile and a road stop
|
||||
*/
|
||||
static inline bool IsAnyRoadStopTile(TileIndex t)
|
||||
{
|
||||
return IsTileType(t, MP_STATION) && IsAnyRoadStop(t);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -222,7 +265,7 @@ static inline bool IsRoadStopTile(TileIndex t)
|
||||
*/
|
||||
static inline bool IsStandardRoadStopTile(TileIndex t)
|
||||
{
|
||||
return IsRoadStopTile(t) && GetStationGfx(t) < GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET;
|
||||
return IsAnyRoadStopTile(t) && GetStationGfx(t) < GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -232,7 +275,7 @@ static inline bool IsStandardRoadStopTile(TileIndex t)
|
||||
*/
|
||||
static inline bool IsDriveThroughStopTile(TileIndex t)
|
||||
{
|
||||
return IsRoadStopTile(t) && GetStationGfx(t) >= GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET;
|
||||
return IsAnyRoadStopTile(t) && GetStationGfx(t) >= GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -274,13 +317,13 @@ static inline StationGfx GetAirportGfx(TileIndex t)
|
||||
/**
|
||||
* Gets the direction the road stop entrance points towards.
|
||||
* @param t the tile of the road stop
|
||||
* @pre IsRoadStopTile(t)
|
||||
* @pre IsAnyRoadStopTile(t)
|
||||
* @return the direction of the entrance
|
||||
*/
|
||||
static inline DiagDirection GetRoadStopDir(TileIndex t)
|
||||
{
|
||||
StationGfx gfx = GetStationGfx(t);
|
||||
assert_tile(IsRoadStopTile(t), t);
|
||||
assert_tile(IsAnyRoadStopTile(t), t);
|
||||
if (gfx < GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET) {
|
||||
return (DiagDirection)(gfx);
|
||||
} else {
|
||||
@@ -630,9 +673,9 @@ static inline void MakeRoadStop(TileIndex t, Owner o, StationID sid, RoadStopTyp
|
||||
* @param tram_rt the tram roadtype on this tile
|
||||
* @param a the direction of the roadstop
|
||||
*/
|
||||
static inline void MakeDriveThroughRoadStop(TileIndex t, Owner station, Owner road, Owner tram, StationID sid, RoadStopType rst, RoadType road_rt, RoadType tram_rt, Axis a)
|
||||
static inline void MakeDriveThroughRoadStop(TileIndex t, Owner station, Owner road, Owner tram, StationID sid, StationType rst, RoadType road_rt, RoadType tram_rt, Axis a)
|
||||
{
|
||||
MakeStation(t, station, sid, (rst == ROADSTOP_BUS ? STATION_BUS : STATION_TRUCK), GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET + a);
|
||||
MakeStation(t, station, sid, rst, GFX_TRUCK_BUS_DRIVETHROUGH_OFFSET + a);
|
||||
SetRoadTypes(t, road_rt, tram_rt);
|
||||
SetRoadOwner(t, RTT_ROAD, road);
|
||||
SetRoadOwner(t, RTT_TRAM, tram);
|
||||
|
@@ -41,6 +41,7 @@ enum StationType {
|
||||
STATION_DOCK,
|
||||
STATION_BUOY,
|
||||
STATION_WAYPOINT,
|
||||
STATION_ROADWAYPOINT,
|
||||
};
|
||||
|
||||
/** Types of RoadStops */
|
||||
|
@@ -16,6 +16,7 @@
|
||||
#include "../ship.h"
|
||||
#include "../aircraft.h"
|
||||
#include "../object_map.h"
|
||||
#include "../waypoint_base.h"
|
||||
#include "../string_func_extra.h"
|
||||
|
||||
/* Helper for filling property tables */
|
||||
@@ -1269,6 +1270,27 @@ class NIHStationStruct : public NIHelper {
|
||||
seprintf(buffer, lastof(buffer), " Docking tiles: %X, %u x %u", st->docking_station.tile, st->docking_station.w, st->docking_station.h);
|
||||
output.print(buffer);
|
||||
}
|
||||
const Waypoint *wp = Waypoint::GetIfValid(index);
|
||||
if (wp) {
|
||||
output.register_next_line_click_flag_toggle(1);
|
||||
seprintf(buffer, lastof(buffer), " [%c] flags: 0x%X", output.flags & 1 ? '-' : '+', wp->waypoint_flags);
|
||||
output.print(buffer);
|
||||
if (output.flags & 1) {
|
||||
auto print = [&](const char *name) {
|
||||
seprintf(buffer, lastof(buffer), " %s", name);
|
||||
output.print(buffer);
|
||||
};
|
||||
auto check_flag = [&](WaypointFlags flag, const char *name) {
|
||||
if (HasBit(wp->waypoint_flags, flag)) print(name);
|
||||
};
|
||||
check_flag(WPF_HIDE_LABEL, "WPF_HIDE_LABEL");
|
||||
check_flag(WPF_ROAD, "WPF_ROAD");
|
||||
}
|
||||
|
||||
seprintf(buffer, lastof(buffer), " road_waypoint_area: tile: %X (%u x %u), width: %u, height: %u",
|
||||
wp->road_waypoint_area.tile, TileX(wp->road_waypoint_area.tile), TileY(wp->road_waypoint_area.tile), wp->road_waypoint_area.w, wp->road_waypoint_area.h);
|
||||
output.print(buffer);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -955,6 +955,15 @@ static const DrawTileSprites _station_display_datas_bus[] = {
|
||||
TILE_SPRITE_LINE(SPR_ROAD_PAVED_STRAIGHT_Y, _station_display_datas_0171)
|
||||
};
|
||||
|
||||
static const DrawTileSprites _station_display_datas_road_waypoint[] = {
|
||||
TILE_SPRITE_LINE(SPR_BUS_STOP_NE_GROUND | (1U << PALETTE_MODIFIER_COLOUR), _station_display_datas_71)
|
||||
TILE_SPRITE_LINE(SPR_BUS_STOP_SE_GROUND | (1U << PALETTE_MODIFIER_COLOUR), _station_display_datas_72)
|
||||
TILE_SPRITE_LINE(SPR_BUS_STOP_SW_GROUND | (1U << PALETTE_MODIFIER_COLOUR), _station_display_datas_73)
|
||||
TILE_SPRITE_LINE(SPR_BUS_STOP_NW_GROUND | (1U << PALETTE_MODIFIER_COLOUR), _station_display_datas_74)
|
||||
TILE_SPRITE_LINE(SPR_ROAD_PAVED_STRAIGHT_X, _station_display_datas_0170)
|
||||
TILE_SPRITE_LINE(SPR_ROAD_PAVED_STRAIGHT_Y, _station_display_datas_0171)
|
||||
};
|
||||
|
||||
static const DrawTileSprites _station_display_datas_oilrig[] = {
|
||||
TILE_SPRITE_LINE(SPR_FLAT_WATER_TILE, _station_display_nothing)
|
||||
};
|
||||
@@ -999,4 +1008,5 @@ static const DrawTileSprites * const _station_display_datas[] = {
|
||||
_station_display_datas_dock,
|
||||
_station_display_datas_buoy,
|
||||
_station_display_datas_waypoint,
|
||||
_station_display_datas_road_waypoint,
|
||||
};
|
||||
|
@@ -1301,7 +1301,7 @@ static bool CanRoadContinueIntoNextTile(const Town *t, const TileIndex tile, con
|
||||
/* If the next tile is a station, allow if it's a road station facing the proper direction. Otherwise return false. */
|
||||
if (IsTileType(next_tile, MP_STATION)) {
|
||||
/* If the next tile is a road station, allow if it can be entered by the new tunnel/bridge, otherwise disallow. */
|
||||
return IsRoadStop(next_tile) && (GetRoadStopDir(next_tile) == ReverseDiagDir(road_dir) || (IsDriveThroughStopTile(next_tile) && GetRoadStopDir(next_tile) == road_dir));
|
||||
return IsAnyRoadStop(next_tile) && (GetRoadStopDir(next_tile) == ReverseDiagDir(road_dir) || (IsDriveThroughStopTile(next_tile) && GetRoadStopDir(next_tile) == road_dir));
|
||||
}
|
||||
|
||||
/* If the next tile is a road depot, allow if it's facing the right way. */
|
||||
|
@@ -549,7 +549,8 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
|
||||
}
|
||||
|
||||
case STATION_BUS:
|
||||
case STATION_TRUCK: {
|
||||
case STATION_TRUCK:
|
||||
case STATION_ROADWAYPOINT: {
|
||||
CommandCost ret = IsRoadStopBridgeAboveOK(tile, IsDriveThroughStopTile(tile), GetRoadStopDir(tile),
|
||||
tile_start, tile_end, z_start + 1, bridge_type, transport_type);
|
||||
if (ret.Failed()) {
|
||||
@@ -672,7 +673,8 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
|
||||
}
|
||||
|
||||
case STATION_BUS:
|
||||
case STATION_TRUCK: {
|
||||
case STATION_TRUCK:
|
||||
case STATION_ROADWAYPOINT: {
|
||||
CommandCost ret = IsRoadStopBridgeAboveOK(tile, IsDriveThroughStopTile(tile), GetRoadStopDir(tile),
|
||||
tile_start, tile_end, z_start + 1, bridge_type, transport_type);
|
||||
if (ret.Failed()) {
|
||||
|
@@ -2470,6 +2470,7 @@ public:
|
||||
|
||||
/* check rail waypoint or buoy (no ownership) */
|
||||
if ((IsRailWaypointTile(tile) && this->vli.vtype == VEH_TRAIN && IsInfraTileUsageAllowed(VEH_TRAIN, this->vli.company, tile))
|
||||
|| (IsRoadWaypointTile(tile) && this->vli.vtype == VEH_ROAD && IsInfraTileUsageAllowed(VEH_ROAD, this->vli.company, tile))
|
||||
|| (IsBuoyTile(tile) && this->vli.vtype == VEH_SHIP)) {
|
||||
if (this->vli.type != VL_STATION_LIST) return;
|
||||
if (!(Station::Get(this->vli.index)->facilities & FACIL_WAYPOINT)) return;
|
||||
@@ -2480,7 +2481,7 @@ public:
|
||||
|
||||
if (IsTileType(tile, MP_STATION)) {
|
||||
if (this->vli.type != VL_STATION_LIST) return;
|
||||
if (Station::Get(this->vli.index)->facilities & FACIL_WAYPOINT) return;
|
||||
if (BaseStation::Get(this->vli.index)->facilities & FACIL_WAYPOINT) return;
|
||||
|
||||
StationID st_index = GetStationIndex(tile);
|
||||
const Station *st = Station::Get(st_index);
|
||||
@@ -3754,7 +3755,7 @@ public:
|
||||
break;
|
||||
|
||||
case OT_GOTO_WAYPOINT: {
|
||||
assert(v->type == VEH_TRAIN || v->type == VEH_SHIP);
|
||||
assert(v->type == VEH_TRAIN || v->type == VEH_ROAD || v->type == VEH_SHIP);
|
||||
SetDParam(0, v->current_order.GetDestination());
|
||||
str = HasBit(v->vehicle_flags, VF_PATHFINDER_LOST) ? STR_VEHICLE_STATUS_CANNOT_REACH_WAYPOINT_VEL : STR_VEHICLE_STATUS_HEADING_FOR_WAYPOINT_VEL;
|
||||
SetDParam(1, v->GetDisplaySpeed());
|
||||
|
@@ -194,8 +194,10 @@ enum ViewportDragDropSelectionProcess {
|
||||
DDSP_PLACE_ROAD_X_DIR, ///< Road placement (X axis)
|
||||
DDSP_PLACE_ROAD_Y_DIR, ///< Road placement (Y axis)
|
||||
DDSP_PLACE_AUTOROAD, ///< Road placement (auto)
|
||||
DDSP_BUILD_ROAD_WAYPOINT, ///< Road stop placement (waypoint)
|
||||
DDSP_BUILD_BUSSTOP, ///< Road stop placement (buses)
|
||||
DDSP_BUILD_TRUCKSTOP, ///< Road stop placement (trucks)
|
||||
DDSP_REMOVE_ROAD_WAYPOINT, ///< Road stop removal (waypoint)
|
||||
DDSP_REMOVE_BUSSTOP, ///< Road stop removal (buses)
|
||||
DDSP_REMOVE_TRUCKSTOP, ///< Road stop removal (trucks)
|
||||
DDSP_CONVERT_ROAD, ///< Road conversion
|
||||
|
@@ -41,6 +41,10 @@ void Waypoint::GetTileArea(TileArea *ta, StationType type) const
|
||||
*ta = this->train_station;
|
||||
return;
|
||||
|
||||
case STATION_ROADWAYPOINT:
|
||||
*ta = this->road_waypoint_area;
|
||||
return;
|
||||
|
||||
case STATION_BUOY:
|
||||
ta->tile = this->xy;
|
||||
ta->w = 1;
|
||||
|
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
enum WaypointFlags {
|
||||
WPF_HIDE_LABEL = 0, ///< Hide waypoint label
|
||||
WPF_ROAD = 1, ///< This is a road waypoint
|
||||
};
|
||||
|
||||
/** Representation of a waypoint. */
|
||||
@@ -24,6 +25,8 @@ struct Waypoint FINAL : SpecializedStation<Waypoint, true> {
|
||||
uint16 town_cn; ///< The N-1th waypoint for this town (consecutive number)
|
||||
uint16 waypoint_flags; ///< Waypoint flags, see WaypointFlags
|
||||
|
||||
TileArea road_waypoint_area; ///< Tile area the road waypoint part covers
|
||||
|
||||
/**
|
||||
* Create a waypoint at the given tile.
|
||||
* @param tile The location of the waypoint.
|
||||
|
@@ -68,13 +68,13 @@ void Waypoint::MoveSign(TileIndex new_xy)
|
||||
* @param cid previous owner of the waypoint
|
||||
* @return the deleted nearby waypoint
|
||||
*/
|
||||
static Waypoint *FindDeletedWaypointCloseTo(TileIndex tile, StringID str, CompanyID cid)
|
||||
static Waypoint *FindDeletedWaypointCloseTo(TileIndex tile, StringID str, CompanyID cid, bool is_road)
|
||||
{
|
||||
Waypoint *best = nullptr;
|
||||
uint thres = 8;
|
||||
|
||||
for (Waypoint *wp : Waypoint::Iterate()) {
|
||||
if (!wp->IsInUse() && wp->string_id == str && wp->owner == cid) {
|
||||
if (!wp->IsInUse() && wp->string_id == str && wp->owner == cid && HasBit(wp->waypoint_flags, WPF_ROAD) == is_road) {
|
||||
uint cur_dist = DistanceManhattan(tile, wp->xy);
|
||||
|
||||
if (cur_dist < thres) {
|
||||
@@ -109,6 +109,29 @@ Axis GetAxisForNewWaypoint(TileIndex tile)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the axis for a new road waypoint. This means that if it is a valid
|
||||
* tile to build a waypoint on it returns a valid Axis, otherwise an
|
||||
* invalid one.
|
||||
* @param tile the tile to look at.
|
||||
* @return the axis for the to-be-build waypoint.
|
||||
*/
|
||||
Axis GetAxisForNewRoadWaypoint(TileIndex tile)
|
||||
{
|
||||
/* The axis for rail waypoints is easy. */
|
||||
if (IsRoadWaypointTile(tile)) return DiagDirToAxis(GetRoadStopDir(tile));
|
||||
|
||||
/* Non-plain road type, no valid axis for waypoints. */
|
||||
if (!IsNormalRoadTile(tile)) return INVALID_AXIS;
|
||||
|
||||
RoadBits bits = GetAllRoadBits(tile);
|
||||
|
||||
if ((bits & ROAD_Y) == 0) return AXIS_X;
|
||||
if ((bits & ROAD_X) == 0) return AXIS_Y;
|
||||
|
||||
return INVALID_AXIS;
|
||||
}
|
||||
|
||||
extern CommandCost ClearTile_Station(TileIndex tile, DoCommandFlag flags);
|
||||
|
||||
/**
|
||||
@@ -152,7 +175,7 @@ static CommandCost IsValidTileForWaypoint(TileIndex tile, Axis axis, StationID *
|
||||
}
|
||||
|
||||
extern void GetStationLayout(byte *layout, uint numtracks, uint plat_len, const StationSpec *statspec);
|
||||
extern CommandCost FindJoiningWaypoint(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, Waypoint **wp);
|
||||
extern CommandCost FindJoiningWaypoint(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, Waypoint **wp, bool is_road);
|
||||
extern CommandCost CanExpandRailStation(const BaseStation *st, TileArea &new_ta, Axis axis);
|
||||
extern CommandCost IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec *statspec, byte layout);
|
||||
|
||||
@@ -232,15 +255,16 @@ CommandCost CmdBuildRailWaypoint(TileIndex start_tile, DoCommandFlag flags, uint
|
||||
|
||||
Waypoint *wp = nullptr;
|
||||
TileArea new_location(start_tile, width, height);
|
||||
CommandCost ret = FindJoiningWaypoint(est, station_to_join, adjacent, new_location, &wp);
|
||||
CommandCost ret = FindJoiningWaypoint(est, station_to_join, adjacent, new_location, &wp, false);
|
||||
if (ret.Failed()) return ret;
|
||||
|
||||
/* Check if there is an already existing, deleted, waypoint close to us that we can reuse. */
|
||||
TileIndex center_tile = start_tile + (count / 2) * offset;
|
||||
if (wp == nullptr && reuse) wp = FindDeletedWaypointCloseTo(center_tile, STR_SV_STNAME_WAYPOINT, _current_company);
|
||||
if (wp == nullptr && reuse) wp = FindDeletedWaypointCloseTo(center_tile, STR_SV_STNAME_WAYPOINT, _current_company, false);
|
||||
|
||||
if (wp != nullptr) {
|
||||
/* Reuse an existing waypoint. */
|
||||
if (HasBit(wp->waypoint_flags, WPF_ROAD)) return CMD_ERROR;
|
||||
if (wp->owner != _current_company) return_cmd_error(STR_ERROR_TOO_CLOSE_TO_ANOTHER_WAYPOINT);
|
||||
|
||||
/* check if we want to expand an already existing waypoint? */
|
||||
@@ -301,6 +325,134 @@ CommandCost CmdBuildRailWaypoint(TileIndex start_tile, DoCommandFlag flags, uint
|
||||
return CommandCost(EXPENSES_CONSTRUCTION, count * _price[PR_BUILD_WAYPOINT_RAIL]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert existing road to waypoint. Eg build a waypoint station over
|
||||
* piece of road
|
||||
* @param start_tile northern most tile where waypoint will be built
|
||||
* @param flags Operation to perform.
|
||||
* @param p1 bit 0..7: Width of the road stop.
|
||||
* bit 8..15: Length of the road stop.
|
||||
* bit 16: Allow stations directly adjacent to other stations.
|
||||
* bit 17: #Axis of the road.
|
||||
* @param p2 bit 16..31: Station ID to join (NEW_STATION if build new one).
|
||||
* @param text Unused.
|
||||
* @return The cost of this operation or an error.
|
||||
*/
|
||||
CommandCost CmdBuildRoadWaypoint(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||
{
|
||||
StationID station_to_join = GB(p2, 16, 16);
|
||||
byte width = GB(p1, 0, 8);
|
||||
byte height = GB(p1, 8, 8);
|
||||
bool adjacent = HasBit(p1, 16);
|
||||
Axis axis = Extract<Axis, 17, 1>(p1);
|
||||
|
||||
/* The number of parts to build */
|
||||
byte count = axis == AXIS_X ? height : width;
|
||||
|
||||
if ((axis == AXIS_X ? width : height) != 1) return CMD_ERROR;
|
||||
if (count == 0 || count > _settings_game.station.station_spread) return CMD_ERROR;
|
||||
|
||||
bool reuse = (station_to_join != NEW_STATION);
|
||||
if (!reuse) station_to_join = INVALID_STATION;
|
||||
bool distant_join = (station_to_join != INVALID_STATION);
|
||||
|
||||
if (distant_join && (!_settings_game.station.distant_join_stations || !Waypoint::IsValidID(station_to_join))) return CMD_ERROR;
|
||||
|
||||
/* Check if the first tile and the last tile are valid */
|
||||
if (!IsValidTile(start_tile) || TileAddWrap(start_tile, width - 1, height - 1) == INVALID_TILE) return CMD_ERROR;
|
||||
|
||||
TileArea roadstop_area(start_tile, width, height);
|
||||
/* Total road stop cost. */
|
||||
CommandCost cost(EXPENSES_CONSTRUCTION, roadstop_area.w * roadstop_area.h * _price[PR_BUILD_STATION_TRUCK]);
|
||||
StationID est = INVALID_STATION;
|
||||
extern CommandCost CheckFlatLandRoadStop(TileArea tile_area, DoCommandFlag flags, uint invalid_dirs, bool is_drive_through, StationType station_type, Axis axis, StationID *station, RoadType rt, bool require_road);
|
||||
CommandCost ret = CheckFlatLandRoadStop(roadstop_area, flags, 5 << axis, true, STATION_ROADWAYPOINT, axis, &est, INVALID_ROADTYPE, true);
|
||||
if (ret.Failed()) return ret;
|
||||
cost.AddCost(ret);
|
||||
|
||||
Waypoint *wp = nullptr;
|
||||
ret = FindJoiningWaypoint(est, station_to_join, adjacent, roadstop_area, &wp, true);
|
||||
if (ret.Failed()) return ret;
|
||||
|
||||
/* Check if there is an already existing, deleted, waypoint close to us that we can reuse. */
|
||||
TileIndex center_tile = start_tile + (count / 2) * TileOffsByDiagDir(AxisToDiagDir(OtherAxis(axis)));;
|
||||
if (wp == nullptr && reuse) wp = FindDeletedWaypointCloseTo(center_tile, STR_SV_STNAME_WAYPOINT, _current_company, true);
|
||||
|
||||
if (wp != nullptr) {
|
||||
/* Reuse an existing waypoint. */
|
||||
if (!HasBit(wp->waypoint_flags, WPF_ROAD)) return CMD_ERROR;
|
||||
if (wp->owner != _current_company) return_cmd_error(STR_ERROR_TOO_CLOSE_TO_ANOTHER_WAYPOINT);
|
||||
|
||||
CommandCost ret = wp->rect.BeforeAddRect(start_tile, width, height, StationRect::ADD_TEST);
|
||||
if (ret.Failed()) return ret;
|
||||
} else {
|
||||
/* allocate and initialize new waypoint */
|
||||
if (!Waypoint::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_STATIONS_LOADING);
|
||||
}
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
if (wp == nullptr) {
|
||||
wp = new Waypoint(start_tile);
|
||||
SetBit(wp->waypoint_flags, WPF_ROAD);
|
||||
} else if (!wp->IsInUse()) {
|
||||
/* Move existing (recently deleted) waypoint to the new location */
|
||||
wp->xy = start_tile;
|
||||
}
|
||||
wp->owner = _current_company;
|
||||
|
||||
wp->rect.BeforeAddRect(start_tile, width, height, StationRect::ADD_TRY);
|
||||
|
||||
wp->delete_ctr = 0;
|
||||
wp->facilities |= FACIL_BUS_STOP | FACIL_TRUCK_STOP;
|
||||
wp->build_date = _date;
|
||||
wp->string_id = STR_SV_STNAME_WAYPOINT;
|
||||
|
||||
if (wp->town == nullptr) MakeDefaultName(wp);
|
||||
|
||||
wp->UpdateVirtCoord();
|
||||
|
||||
/* Check every tile in the area. */
|
||||
for (TileIndex cur_tile : roadstop_area) {
|
||||
/* Get existing road types and owners before any tile clearing */
|
||||
RoadType road_rt = MayHaveRoad(cur_tile) ? GetRoadType(cur_tile, RTT_ROAD) : INVALID_ROADTYPE;
|
||||
RoadType tram_rt = MayHaveRoad(cur_tile) ? GetRoadType(cur_tile, RTT_TRAM) : INVALID_ROADTYPE;
|
||||
Owner road_owner = road_rt != INVALID_ROADTYPE ? GetRoadOwner(cur_tile, RTT_ROAD) : _current_company;
|
||||
Owner tram_owner = tram_rt != INVALID_ROADTYPE ? GetRoadOwner(cur_tile, RTT_TRAM) : _current_company;
|
||||
DisallowedRoadDirections drd = IsNormalRoadTile(cur_tile) ? GetDisallowedRoadDirections(cur_tile) : DRD_NONE;
|
||||
|
||||
extern CommandCost RemoveRoadStop(TileIndex tile, DoCommandFlag flags);
|
||||
if (IsTileType(cur_tile, MP_STATION) && IsAnyRoadStop(cur_tile)) {
|
||||
RemoveRoadStop(cur_tile, flags);
|
||||
}
|
||||
|
||||
wp->road_waypoint_area.Add(cur_tile);
|
||||
|
||||
wp->rect.BeforeAddTile(cur_tile, StationRect::ADD_TRY);
|
||||
|
||||
/* Update company infrastructure counts. If the current tile is a normal road tile, remove the old
|
||||
* bits first. */
|
||||
if (IsNormalRoadTile(cur_tile)) {
|
||||
UpdateCompanyRoadInfrastructure(road_rt, road_owner, -(int)CountBits(GetRoadBits(cur_tile, RTT_ROAD)));
|
||||
UpdateCompanyRoadInfrastructure(tram_rt, tram_owner, -(int)CountBits(GetRoadBits(cur_tile, RTT_TRAM)));
|
||||
}
|
||||
|
||||
UpdateCompanyRoadInfrastructure(road_rt, road_owner, ROAD_STOP_TRACKBIT_FACTOR);
|
||||
UpdateCompanyRoadInfrastructure(tram_rt, tram_owner, ROAD_STOP_TRACKBIT_FACTOR);
|
||||
|
||||
MakeDriveThroughRoadStop(cur_tile, wp->owner, road_owner, tram_owner, wp->index, STATION_ROADWAYPOINT, road_rt, tram_rt, axis);
|
||||
SetDriveThroughStopDisallowedRoadDirections(cur_tile, drd);
|
||||
|
||||
Company::Get(wp->owner)->infrastructure.station++;
|
||||
|
||||
MarkTileDirtyByTile(cur_tile);
|
||||
UpdateRoadCachedOneWayStatesAroundTile(cur_tile);
|
||||
}
|
||||
NotifyRoadLayoutChanged(true);
|
||||
DirtyCompanyInfrastructureWindows(wp->owner);
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a buoy.
|
||||
* @param tile tile where to place the buoy
|
||||
@@ -317,7 +469,7 @@ CommandCost CmdBuildBuoy(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
|
||||
if (!IsTileFlat(tile)) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
|
||||
|
||||
/* Check if there is an already existing, deleted, waypoint close to us that we can reuse. */
|
||||
Waypoint *wp = FindDeletedWaypointCloseTo(tile, STR_SV_STNAME_BUOY, OWNER_NONE);
|
||||
Waypoint *wp = FindDeletedWaypointCloseTo(tile, STR_SV_STNAME_BUOY, OWNER_NONE, false);
|
||||
if (wp == nullptr && !Waypoint::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_STATIONS_LOADING);
|
||||
|
||||
CommandCost cost(EXPENSES_CONSTRUCTION, _price[PR_BUILD_WAYPOINT_BUOY]);
|
||||
|
@@ -17,6 +17,7 @@
|
||||
CommandCost RemoveBuoy(TileIndex tile, DoCommandFlag flags);
|
||||
|
||||
Axis GetAxisForNewWaypoint(TileIndex tile);
|
||||
Axis GetAxisForNewRoadWaypoint(TileIndex tile);
|
||||
void ShowWaypointWindow(const Waypoint *wp);
|
||||
void DrawWaypointSprite(int x, int y, int stat_id, RailType railtype);
|
||||
|
||||
|
@@ -45,7 +45,24 @@ private:
|
||||
if (!this->wp->IsInUse()) return this->wp->xy;
|
||||
|
||||
TileArea ta;
|
||||
this->wp->GetTileArea(&ta, this->vt == VEH_TRAIN ? STATION_WAYPOINT : STATION_BUOY);
|
||||
StationType type;
|
||||
switch (this->vt) {
|
||||
case VEH_TRAIN:
|
||||
type = STATION_WAYPOINT;
|
||||
break;
|
||||
|
||||
case VEH_ROAD:
|
||||
type = STATION_ROADWAYPOINT;
|
||||
break;
|
||||
|
||||
case VEH_SHIP:
|
||||
type = STATION_BUOY;
|
||||
break;
|
||||
|
||||
default:
|
||||
NOT_REACHED();
|
||||
}
|
||||
this->wp->GetTileArea(&ta, type);
|
||||
return ta.GetCenterTile();
|
||||
}
|
||||
|
||||
@@ -58,15 +75,24 @@ public:
|
||||
WaypointWindow(WindowDesc *desc, WindowNumber window_number) : Window(desc)
|
||||
{
|
||||
this->wp = Waypoint::Get(window_number);
|
||||
this->vt = (wp->string_id == STR_SV_STNAME_WAYPOINT) ? VEH_TRAIN : VEH_SHIP;
|
||||
if (wp->string_id == STR_SV_STNAME_WAYPOINT) {
|
||||
this->vt = HasBit(this->wp->waypoint_flags, WPF_ROAD) ? VEH_ROAD : VEH_TRAIN;
|
||||
} else {
|
||||
this->vt = VEH_SHIP;
|
||||
}
|
||||
|
||||
this->CreateNestedTree();
|
||||
if (this->vt == VEH_TRAIN) {
|
||||
this->GetWidget<NWidgetCore>(WID_W_SHOW_VEHICLES)->SetDataTip(STR_TRAIN, STR_STATION_VIEW_SCHEDULED_TRAINS_TOOLTIP);
|
||||
}
|
||||
if (this->vt == VEH_ROAD) {
|
||||
this->GetWidget<NWidgetCore>(WID_W_SHOW_VEHICLES)->SetDataTip(STR_LORRY, STR_STATION_VIEW_SCHEDULED_ROAD_VEHICLES_TOOLTIP);
|
||||
}
|
||||
if (this->vt != VEH_SHIP) {
|
||||
this->GetWidget<NWidgetCore>(WID_W_CENTER_VIEW)->tool_tip = STR_WAYPOINT_VIEW_CENTER_TOOLTIP;
|
||||
this->GetWidget<NWidgetCore>(WID_W_RENAME)->tool_tip = STR_WAYPOINT_VIEW_CHANGE_WAYPOINT_NAME;
|
||||
}
|
||||
this->show_hide_label = (this->vt == VEH_TRAIN && _settings_client.gui.allow_hiding_waypoint_labels);
|
||||
this->show_hide_label = (this->vt != VEH_SHIP && _settings_client.gui.allow_hiding_waypoint_labels);
|
||||
this->GetWidget<NWidgetStacked>(WID_W_TOGGLE_HIDDEN_SEL)->SetDisplayedPlane(this->show_hide_label ? 0 : SZSP_NONE);
|
||||
this->FinishInitNested(window_number);
|
||||
|
||||
@@ -135,7 +161,7 @@ public:
|
||||
|
||||
this->SetWidgetLoweredState(WID_W_TOGGLE_HIDDEN, HasBit(this->wp->waypoint_flags, WPF_HIDE_LABEL));
|
||||
|
||||
bool show_hide_label = (this->vt == VEH_TRAIN && _settings_client.gui.allow_hiding_waypoint_labels);
|
||||
bool show_hide_label = (this->vt != VEH_SHIP && _settings_client.gui.allow_hiding_waypoint_labels);
|
||||
if (show_hide_label != this->show_hide_label) {
|
||||
this->show_hide_label = show_hide_label;
|
||||
this->GetWidget<NWidgetStacked>(WID_W_TOGGLE_HIDDEN_SEL)->SetDisplayedPlane(this->show_hide_label ? 0 : SZSP_NONE);
|
||||
|
@@ -19,6 +19,7 @@ enum RoadToolbarWidgets {
|
||||
WID_ROT_AUTOROAD, ///< Autorail.
|
||||
WID_ROT_DEMOLISH, ///< Demolish.
|
||||
WID_ROT_DEPOT, ///< Build depot.
|
||||
WID_ROT_BUILD_WAYPOINT, ///< Build waypoint.
|
||||
WID_ROT_BUS_STATION, ///< Build bus station.
|
||||
WID_ROT_TRUCK_STATION, ///< Build truck station.
|
||||
WID_ROT_ONE_WAY, ///< Build one-way road.
|
||||
|
Reference in New Issue
Block a user