Codechange: Un-bitstuff remaining transport infrastructure commands.

This commit is contained in:
Michael Lutz 2021-11-15 00:03:01 +01:00
parent 55170ae703
commit 46bd2f1ced
20 changed files with 180 additions and 274 deletions

View File

@ -60,16 +60,14 @@ void CcBuildBridge(Commands cmd, const CommandCost &result, TileIndex end_tile,
if (result.Failed()) return; if (result.Failed()) return;
if (_settings_client.sound.confirm) SndPlayTileFx(SND_27_CONSTRUCTION_BRIDGE, end_tile); if (_settings_client.sound.confirm) SndPlayTileFx(SND_27_CONSTRUCTION_BRIDGE, end_tile);
auto [tile, p1, p2, text] = EndianBufferReader::ToValue<CommandTraits<CMD_BUILD_BRIDGE>::Args>(data); auto [tile, tile_start, transport_type, bridge_type, road_rail_type] = EndianBufferReader::ToValue<CommandTraits<CMD_BUILD_BRIDGE>::Args>(data);
TransportType transport_type = Extract<TransportType, 15, 2>(p2);
if (transport_type == TRANSPORT_ROAD) { if (transport_type == TRANSPORT_ROAD) {
DiagDirection end_direction = ReverseDiagDir(GetTunnelBridgeDirection(end_tile)); DiagDirection end_direction = ReverseDiagDir(GetTunnelBridgeDirection(end_tile));
ConnectRoadToStructure(end_tile, end_direction); ConnectRoadToStructure(end_tile, end_direction);
DiagDirection start_direction = ReverseDiagDir(GetTunnelBridgeDirection(p1)); DiagDirection start_direction = ReverseDiagDir(GetTunnelBridgeDirection(tile_start));
ConnectRoadToStructure(p1, start_direction); ConnectRoadToStructure(tile_start, start_direction);
} }
} }
@ -86,7 +84,8 @@ private:
/* Internal variables */ /* Internal variables */
TileIndex start_tile; TileIndex start_tile;
TileIndex end_tile; TileIndex end_tile;
uint32 type; TransportType transport_type;
byte road_rail_type;
GUIBridgeList *bridges; GUIBridgeList *bridges;
int bridgetext_offset; ///< Horizontal offset of the text describing the bridge properties in #WID_BBS_BRIDGE_LIST relative to the left edge. int bridgetext_offset; ///< Horizontal offset of the text describing the bridge properties in #WID_BBS_BRIDGE_LIST relative to the left edge.
Scrollbar *vscroll; Scrollbar *vscroll;
@ -111,13 +110,13 @@ private:
void BuildBridge(uint8 i) void BuildBridge(uint8 i)
{ {
switch ((TransportType)(this->type >> 15)) { switch (this->transport_type) {
case TRANSPORT_RAIL: _last_railbridge_type = this->bridges->at(i).index; break; case TRANSPORT_RAIL: _last_railbridge_type = this->bridges->at(i).index; break;
case TRANSPORT_ROAD: _last_roadbridge_type = this->bridges->at(i).index; break; case TRANSPORT_ROAD: _last_roadbridge_type = this->bridges->at(i).index; break;
default: break; default: break;
} }
Command<CMD_BUILD_BRIDGE>::Post(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE, CcBuildBridge, Command<CMD_BUILD_BRIDGE>::Post(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE, CcBuildBridge,
this->end_tile, this->start_tile, this->type | this->bridges->at(i).index, {}); this->end_tile, this->start_tile, this->transport_type, this->bridges->at(i).index, this->road_rail_type);
} }
/** Sort the builable bridges */ /** Sort the builable bridges */
@ -134,19 +133,20 @@ private:
} }
public: public:
BuildBridgeWindow(WindowDesc *desc, TileIndex start, TileIndex end, uint32 br_type, GUIBridgeList *bl) : Window(desc), BuildBridgeWindow(WindowDesc *desc, TileIndex start, TileIndex end, TransportType transport_type, byte road_rail_type, GUIBridgeList *bl) : Window(desc),
start_tile(start), start_tile(start),
end_tile(end), end_tile(end),
type(br_type), transport_type(transport_type),
road_rail_type(road_rail_type),
bridges(bl) bridges(bl)
{ {
this->CreateNestedTree(); this->CreateNestedTree();
this->vscroll = this->GetScrollbar(WID_BBS_SCROLLBAR); this->vscroll = this->GetScrollbar(WID_BBS_SCROLLBAR);
/* Change the data, or the caption of the gui. Set it to road or rail, accordingly. */ /* Change the data, or the caption of the gui. Set it to road or rail, accordingly. */
this->GetWidget<NWidgetCore>(WID_BBS_CAPTION)->widget_data = (GB(this->type, 15, 2) == TRANSPORT_ROAD) ? STR_SELECT_ROAD_BRIDGE_CAPTION : STR_SELECT_RAIL_BRIDGE_CAPTION; this->GetWidget<NWidgetCore>(WID_BBS_CAPTION)->widget_data = (transport_type == TRANSPORT_ROAD) ? STR_SELECT_ROAD_BRIDGE_CAPTION : STR_SELECT_RAIL_BRIDGE_CAPTION;
this->FinishInitNested(GB(br_type, 15, 2)); // Initializes 'this->bridgetext_offset'. this->FinishInitNested(transport_type); // Initializes 'this->bridgetext_offset'.
this->parent = FindWindowById(WC_BUILD_TOOLBAR, GB(this->type, 15, 2)); this->parent = FindWindowById(WC_BUILD_TOOLBAR, transport_type);
this->bridges->SetListing(this->last_sorting); this->bridges->SetListing(this->last_sorting);
this->bridges->SetSortFuncs(this->sorter_funcs); this->bridges->SetSortFuncs(this->sorter_funcs);
this->bridges->NeedResort(); this->bridges->NeedResort();
@ -361,12 +361,6 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo
{ {
CloseWindowByClass(WC_BUILD_BRIDGE); CloseWindowByClass(WC_BUILD_BRIDGE);
/* Data type for the bridge.
* Bit 16,15 = transport type,
* 14..8 = road/rail types,
* 7..0 = type of bridge */
uint32 type = (transport_type << 15) | (road_rail_type << 8);
/* The bridge length without ramps. */ /* The bridge length without ramps. */
const uint bridge_len = GetTunnelBridgeLength(start, end); const uint bridge_len = GetTunnelBridgeLength(start, end);
@ -382,14 +376,14 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo
default: break; // water ways and air routes don't have bridge types default: break; // water ways and air routes don't have bridge types
} }
if (_ctrl_pressed && CheckBridgeAvailability(last_bridge_type, bridge_len).Succeeded()) { if (_ctrl_pressed && CheckBridgeAvailability(last_bridge_type, bridge_len).Succeeded()) {
Command<CMD_BUILD_BRIDGE>::Post(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE, CcBuildBridge, end, start, type | last_bridge_type, {}); Command<CMD_BUILD_BRIDGE>::Post(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE, CcBuildBridge, end, start, transport_type, last_bridge_type, road_rail_type);
return; return;
} }
/* only query bridge building possibility once, result is the same for all bridges! /* only query bridge building possibility once, result is the same for all bridges!
* returns CMD_ERROR on failure, and price on success */ * returns CMD_ERROR on failure, and price on success */
StringID errmsg = INVALID_STRING_ID; StringID errmsg = INVALID_STRING_ID;
CommandCost ret = Command<CMD_BUILD_BRIDGE>::Do(CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_BRIDGE>()) | DC_QUERY_COST, end, start, type, {}); CommandCost ret = Command<CMD_BUILD_BRIDGE>::Do(CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_BRIDGE>()) | DC_QUERY_COST, end, start, transport_type, 0, road_rail_type);
GUIBridgeList *bl = nullptr; GUIBridgeList *bl = nullptr;
if (ret.Failed()) { if (ret.Failed()) {
@ -449,7 +443,7 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo
} }
if (bl != nullptr && bl->size() != 0) { if (bl != nullptr && bl->size() != 0) {
new BuildBridgeWindow(&_build_bridge_desc, start, end, type, bl); new BuildBridgeWindow(&_build_bridge_desc, start, end, transport_type, road_rail_type, bl);
} else { } else {
delete bl; delete bl;
ShowErrorMessage(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE, errmsg, WL_INFO, TileX(end) * TILE_SIZE, TileY(end) * TILE_SIZE); ShowErrorMessage(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE, errmsg, WL_INFO, TileX(end) * TILE_SIZE, TileY(end) * TILE_SIZE);

View File

@ -196,7 +196,7 @@ struct BuildDocksToolbarWindow : Window {
break; break;
case WID_DT_LOCK: // Build lock button case WID_DT_LOCK: // Build lock button
Command<CMD_BUILD_LOCK>::Post(STR_ERROR_CAN_T_BUILD_LOCKS, CcBuildDocks, tile, 0, 0, {}); Command<CMD_BUILD_LOCK>::Post(STR_ERROR_CAN_T_BUILD_LOCKS, CcBuildDocks, tile);
break; break;
case WID_DT_DEMOLISH: // Demolish aka dynamite button case WID_DT_DEMOLISH: // Demolish aka dynamite button
@ -234,7 +234,7 @@ struct BuildDocksToolbarWindow : Window {
break; break;
case WID_DT_BUILD_AQUEDUCT: // Build aqueduct button case WID_DT_BUILD_AQUEDUCT: // Build aqueduct button
Command<CMD_BUILD_BRIDGE>::Post(STR_ERROR_CAN_T_BUILD_AQUEDUCT_HERE, CcBuildBridge, tile, GetOtherAqueductEnd(tile), TRANSPORT_WATER << 15, {}); Command<CMD_BUILD_BRIDGE>::Post(STR_ERROR_CAN_T_BUILD_AQUEDUCT_HERE, CcBuildBridge, tile, GetOtherAqueductEnd(tile), TRANSPORT_WATER, 0, 0);
break; break;
default: NOT_REACHED(); default: NOT_REACHED();
@ -254,10 +254,10 @@ struct BuildDocksToolbarWindow : Window {
GUIPlaceProcDragXY(select_proc, start_tile, end_tile); GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
break; break;
case DDSP_CREATE_WATER: case DDSP_CREATE_WATER:
Command<CMD_BUILD_CANAL>::Post(STR_ERROR_CAN_T_BUILD_CANALS, CcPlaySound_CONSTRUCTION_WATER, end_tile, start_tile, (_game_mode == GM_EDITOR && _ctrl_pressed) ? WATER_CLASS_SEA : WATER_CLASS_CANAL, {}); Command<CMD_BUILD_CANAL>::Post(STR_ERROR_CAN_T_BUILD_CANALS, CcPlaySound_CONSTRUCTION_WATER, end_tile, start_tile, (_game_mode == GM_EDITOR && _ctrl_pressed) ? WATER_CLASS_SEA : WATER_CLASS_CANAL, false);
break; break;
case DDSP_CREATE_RIVER: case DDSP_CREATE_RIVER:
Command<CMD_BUILD_CANAL>::Post(STR_ERROR_CAN_T_PLACE_RIVERS, CcPlaySound_CONSTRUCTION_WATER, end_tile, start_tile, WATER_CLASS_RIVER | (_ctrl_pressed ? 1 << 2 : 0), {}); Command<CMD_BUILD_CANAL>::Post(STR_ERROR_CAN_T_PLACE_RIVERS, CcPlaySound_CONSTRUCTION_WATER, end_tile, start_tile, WATER_CLASS_RIVER, _ctrl_pressed);
break; break;
default: break; default: break;

View File

@ -648,7 +648,7 @@ struct BuildRailToolbarWindow : Window {
break; break;
case WID_RAT_BUILD_TUNNEL: case WID_RAT_BUILD_TUNNEL:
Command<CMD_BUILD_TUNNEL>::Post(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE, CcBuildRailTunnel, tile, _cur_railtype | (TRANSPORT_RAIL << 8), 0, {}); Command<CMD_BUILD_TUNNEL>::Post(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE, CcBuildRailTunnel, tile, TRANSPORT_RAIL, _cur_railtype);
break; break;
case WID_RAT_CONVERT_RAIL: case WID_RAT_CONVERT_RAIL:
@ -746,7 +746,7 @@ struct BuildRailToolbarWindow : Window {
void OnPlacePresize(Point pt, TileIndex tile) override void OnPlacePresize(Point pt, TileIndex tile) override
{ {
Command<CMD_BUILD_TUNNEL>::Do(DC_AUTO, tile, _cur_railtype | (TRANSPORT_RAIL << 8), 0, {}); Command<CMD_BUILD_TUNNEL>::Do(DC_AUTO, tile, TRANSPORT_RAIL, _cur_railtype);
VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile); VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile);
} }

View File

@ -606,14 +606,13 @@ static CommandCost CheckRoadSlope(Slope tileh, RoadBits *pieces, RoadBits existi
* Build a piece of road. * Build a piece of road.
* @param flags operation to perform * @param flags operation to perform
* @param tile tile where to build road * @param tile tile where to build road
* @param p1 bit 0..3 road pieces to build (RoadBits) * @param pieces road pieces to build (RoadBits)
* bit 4..9 road type * @param rt road type
* bit 11..12 disallowed directions to toggle * @param toggle_drd disallowed directions to toggle
* @param p2 the town that is building the road (0 if not applicable) * @param town_id the town that is building the road (0 if not applicable)
* @param text unused
* @return the cost of this operation or an error * @return the cost of this operation or an error
*/ */
CommandCost CmdBuildRoad(DoCommandFlag flags, TileIndex tile, uint32 p1, uint32 p2, const std::string &text) CommandCost CmdBuildRoad(DoCommandFlag flags, TileIndex tile, RoadBits pieces, RoadType rt, DisallowedRoadDirections toggle_drd, TownID town_id)
{ {
CompanyID company = _current_company; CompanyID company = _current_company;
CommandCost cost(EXPENSES_CONSTRUCTION); CommandCost cost(EXPENSES_CONSTRUCTION);
@ -623,10 +622,10 @@ CommandCost CmdBuildRoad(DoCommandFlag flags, TileIndex tile, uint32 p1, uint32
/* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero /* Road pieces are max 4 bitset values (NE, NW, SE, SW) and town can only be non-zero
* if a non-company is building the road */ * if a non-company is building the road */
if ((Company::IsValidID(company) && p2 != 0) || (company == OWNER_TOWN && !Town::IsValidID(p2)) || (company == OWNER_DEITY && p2 != 0)) return CMD_ERROR; if ((Company::IsValidID(company) && town_id != 0) || (company == OWNER_TOWN && !Town::IsValidID(town_id)) || (company == OWNER_DEITY && town_id != 0)) return CMD_ERROR;
if (company != OWNER_TOWN) { if (company != OWNER_TOWN) {
const Town *town = CalcClosestTownFromTile(tile); const Town *town = CalcClosestTownFromTile(tile);
p2 = (town != nullptr) ? town->index : INVALID_TOWN; town_id = (town != nullptr) ? town->index : INVALID_TOWN;
if (company == OWNER_DEITY) { if (company == OWNER_DEITY) {
company = OWNER_TOWN; company = OWNER_TOWN;
@ -638,16 +637,10 @@ CommandCost CmdBuildRoad(DoCommandFlag flags, TileIndex tile, uint32 p1, uint32
} }
} }
RoadBits pieces = Extract<RoadBits, 0, 4>(p1);
/* do not allow building 'zero' road bits, code wouldn't handle it */ /* do not allow building 'zero' road bits, code wouldn't handle it */
if (pieces == ROAD_NONE) return CMD_ERROR; if (pieces == ROAD_NONE || !IsEnumValid(pieces) || !IsEnumValid(toggle_drd)) return CMD_ERROR;
RoadType rt = Extract<RoadType, 4, 6>(p1);
if (!ValParamRoadType(rt)) return CMD_ERROR; if (!ValParamRoadType(rt)) return CMD_ERROR;
DisallowedRoadDirections toggle_drd = Extract<DisallowedRoadDirections, 11, 2>(p1);
Slope tileh = GetTileSlope(tile); Slope tileh = GetTileSlope(tile);
RoadTramType rtt = GetRoadTramType(rt); RoadTramType rtt = GetRoadTramType(rt);
@ -785,7 +778,7 @@ CommandCost CmdBuildRoad(DoCommandFlag flags, TileIndex tile, uint32 p1, uint32
/* Always add road to the roadtypes (can't draw without it) */ /* Always add road to the roadtypes (can't draw without it) */
bool reserved = HasBit(GetRailReservationTrackBits(tile), railtrack); bool reserved = HasBit(GetRailReservationTrackBits(tile), railtrack);
MakeRoadCrossing(tile, company, company, GetTileOwner(tile), roaddir, GetRailType(tile), rtt == RTT_ROAD ? rt : INVALID_ROADTYPE, (rtt == RTT_TRAM) ? rt : INVALID_ROADTYPE, p2); MakeRoadCrossing(tile, company, company, GetTileOwner(tile), roaddir, GetRailType(tile), rtt == RTT_ROAD ? rt : INVALID_ROADTYPE, (rtt == RTT_TRAM) ? rt : INVALID_ROADTYPE, town_id);
SetCrossingReservation(tile, reserved); SetCrossingReservation(tile, reserved);
UpdateLevelCrossing(tile, false); UpdateLevelCrossing(tile, false);
MarkTileDirtyByTile(tile); MarkTileDirtyByTile(tile);
@ -870,7 +863,7 @@ do_clear:;
if (HasPowerOnRoad(rt, existing_rt)) { if (HasPowerOnRoad(rt, existing_rt)) {
rt = existing_rt; rt = existing_rt;
} else if (HasPowerOnRoad(existing_rt, rt)) { } else if (HasPowerOnRoad(existing_rt, rt)) {
CommandCost ret = Command<CMD_CONVERT_ROAD>::Do(flags, tile, tile, rt, {}); CommandCost ret = Command<CMD_CONVERT_ROAD>::Do(flags, tile, tile, rt);
if (ret.Failed()) return ret; if (ret.Failed()) return ret;
cost.AddCost(ret); cost.AddCost(ret);
} else { } else {
@ -895,7 +888,7 @@ do_clear:;
if (existing == ROAD_NONE || rttype == ROAD_TILE_CROSSING) { if (existing == ROAD_NONE || rttype == ROAD_TILE_CROSSING) {
SetRoadType(tile, rtt, rt); SetRoadType(tile, rtt, rt);
SetRoadOwner(tile, rtt, company); SetRoadOwner(tile, rtt, company);
if (rtt == RTT_ROAD) SetTownIndex(tile, p2); if (rtt == RTT_ROAD) SetTownIndex(tile, town_id);
} }
if (rttype != ROAD_TILE_CROSSING) SetRoadBits(tile, existing | pieces, rtt); if (rttype != ROAD_TILE_CROSSING) SetRoadBits(tile, existing | pieces, rtt);
break; break;
@ -927,7 +920,7 @@ do_clear:;
} }
default: default:
MakeRoadNormal(tile, pieces, (rtt == RTT_ROAD) ? rt : INVALID_ROADTYPE, (rtt == RTT_TRAM) ? rt : INVALID_ROADTYPE, p2, company, company); MakeRoadNormal(tile, pieces, (rtt == RTT_ROAD) ? rt : INVALID_ROADTYPE, (rtt == RTT_TRAM) ? rt : INVALID_ROADTYPE, town_id, company, company);
break; break;
} }
@ -971,49 +964,40 @@ static bool CanConnectToRoad(TileIndex tile, RoadType rt, DiagDirection dir)
* Build a long piece of road. * Build a long piece of road.
* @param flags operation to perform * @param flags operation to perform
* @param start_tile start tile of drag (the building cost will appear over this tile) * @param start_tile start tile of drag (the building cost will appear over this tile)
* @param p1 end tile of drag * @param end_tile end tile of drag
* @param p2 various bitstuffed elements * @param rt road type
* - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1). Only used if bit 6 is set or if we are building a single tile * @param axis direction
* - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2). Only used if bit 6 is set or if we are building a single tile * @param drd set road direction
* - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4) * @param start_half start tile starts in the 2nd half of tile (p2 & 1). Only used if \c is_ai is set or if we are building a single tile
* - p2 = (bit 3..8) - road type * @param end_half end tile starts in the 2nd half of tile (p2 & 2). Only used if \c is_ai is set or if we are building a single tile
* - p2 = (bit 10) - set road direction * @param is_ai defines two different behaviors for this command:
* - p2 = (bit 11) - defines two different behaviors for this command: * - false = Build up to an obstacle. Do not build the first and last roadbits unless they can be connected to something, or if we are building a single tile
* - 0 = Build up to an obstacle. Do not build the first and last roadbits unless they can be connected to something, or if we are building a single tile * - true = Fail if an obstacle is found. Always take into account start_half and end_half. This behavior is used for scripts
* - 1 = Fail if an obstacle is found. Always take into account bit 0 and 1. This behavior is used for scripts
* @param text unused
* @return the cost of this operation or an error * @return the cost of this operation or an error
*/ */
CommandCost CmdBuildLongRoad(DoCommandFlag flags, TileIndex start_tile, uint32 p1, uint32 p2, const std::string &text) CommandCost CmdBuildLongRoad(DoCommandFlag flags, TileIndex start_tile, TileIndex end_tile, RoadType rt, Axis axis, DisallowedRoadDirections drd, bool start_half, bool end_half, bool is_ai)
{ {
DisallowedRoadDirections drd = DRD_NORTHBOUND; if (end_tile >= MapSize()) return CMD_ERROR;
if (p1 >= MapSize()) return CMD_ERROR; if (!ValParamRoadType(rt) || !IsEnumValid(axis) || !IsEnumValid(drd)) return CMD_ERROR;
TileIndex end_tile = p1;
RoadType rt = Extract<RoadType, 3, 6>(p2);
if (!ValParamRoadType(rt)) return CMD_ERROR;
Axis axis = Extract<Axis, 2, 1>(p2);
/* Only drag in X or Y direction dictated by the direction variable */ /* Only drag in X or Y direction dictated by the direction variable */
if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
DiagDirection dir = AxisToDiagDir(axis); DiagDirection dir = AxisToDiagDir(axis);
/* Swap direction, also the half-tile drag var (bit 0 and 1) */ /* Swap direction, also the half-tile drag vars. */
if (start_tile > end_tile || (start_tile == end_tile && HasBit(p2, 0))) { if (start_tile > end_tile || (start_tile == end_tile && start_half)) {
dir = ReverseDiagDir(dir); dir = ReverseDiagDir(dir);
p2 ^= 3; std::swap(start_half, end_half);
drd = DRD_SOUTHBOUND; if (drd == DRD_NORTHBOUND || drd == DRD_SOUTHBOUND) drd ^= DRD_BOTH;
} }
/* On the X-axis, we have to swap the initial bits, so they /* On the X-axis, we have to swap the initial bits, so they
* will be interpreted correctly in the GTTS. Furthermore * will be interpreted correctly in the GTTS. Furthermore
* when you just 'click' on one tile to build them. */ * when you just 'click' on one tile to build them. */
if ((axis == AXIS_Y) == (start_tile == end_tile && HasBit(p2, 0) == HasBit(p2, 1))) drd ^= DRD_BOTH; if ((drd == DRD_NORTHBOUND || drd == DRD_SOUTHBOUND) && (axis == AXIS_Y) == (start_tile == end_tile && start_half == end_half)) drd ^= DRD_BOTH;
/* No disallowed direction bits have to be toggled */
if (!HasBit(p2, 10)) drd = DRD_NONE;
CommandCost cost(EXPENSES_CONSTRUCTION); CommandCost cost(EXPENSES_CONSTRUCTION);
CommandCost last_error = CMD_ERROR; CommandCost last_error = CMD_ERROR;
@ -1021,7 +1005,6 @@ CommandCost CmdBuildLongRoad(DoCommandFlag flags, TileIndex start_tile, uint32 p
bool had_bridge = false; bool had_bridge = false;
bool had_tunnel = false; bool had_tunnel = false;
bool had_success = false; bool had_success = false;
bool is_ai = HasBit(p2, 11);
/* Start tile is the first tile clicked by the user. */ /* Start tile is the first tile clicked by the user. */
for (;;) { for (;;) {
@ -1037,11 +1020,11 @@ CommandCost CmdBuildLongRoad(DoCommandFlag flags, TileIndex start_tile, uint32 p
} }
} else { } else {
/* Road parts only have to be built at the start tile or at the end tile. */ /* Road parts only have to be built at the start tile or at the end tile. */
if (tile == end_tile && !HasBit(p2, 1)) bits &= DiagDirToRoadBits(ReverseDiagDir(dir)); if (tile == end_tile && !end_half) bits &= DiagDirToRoadBits(ReverseDiagDir(dir));
if (tile == start_tile && HasBit(p2, 0)) bits &= DiagDirToRoadBits(dir); if (tile == start_tile && start_half) bits &= DiagDirToRoadBits(dir);
} }
CommandCost ret = Command<CMD_BUILD_ROAD>::Do(flags, tile, drd << 11 | rt << 4 | bits, 0, {}); CommandCost ret = Command<CMD_BUILD_ROAD>::Do(flags, tile, bits, rt, drd, 0);
if (ret.Failed()) { if (ret.Failed()) {
last_error = ret; last_error = ret;
if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT) { if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT) {
@ -1080,36 +1063,28 @@ CommandCost CmdBuildLongRoad(DoCommandFlag flags, TileIndex start_tile, uint32 p
* Remove a long piece of road. * Remove a long piece of road.
* @param flags operation to perform * @param flags operation to perform
* @param start_tile start tile of drag * @param start_tile start tile of drag
* @param p1 end tile of drag * @param end_tile end tile of drag
* @param p2 various bitstuffed elements * @param rt road type
* - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1) * @param axis direction
* - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2) * @param start_half start tile starts in the 2nd half of tile
* - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4) * @param end_half end tile starts in the 2nd half of tile (p2 & 2)
* - p2 = (bit 3 - 8) - road type
* @param text unused
* @return the cost of this operation or an error * @return the cost of this operation or an error
*/ */
CommandCost CmdRemoveLongRoad(DoCommandFlag flags, TileIndex start_tile, uint32 p1, uint32 p2, const std::string &text) CommandCost CmdRemoveLongRoad(DoCommandFlag flags, TileIndex start_tile, TileIndex end_tile, RoadType rt, Axis axis, bool start_half, bool end_half)
{ {
CommandCost cost(EXPENSES_CONSTRUCTION); CommandCost cost(EXPENSES_CONSTRUCTION);
if (p1 >= MapSize()) return CMD_ERROR; if (end_tile >= MapSize()) return CMD_ERROR;
if (!ValParamRoadType(rt) || !IsEnumValid(axis)) return CMD_ERROR;
TileIndex end_tile = p1;
RoadType rt = Extract<RoadType, 3, 6>(p2);
if (!ValParamRoadType(rt)) return CMD_ERROR;
Axis axis = Extract<Axis, 2, 1>(p2);
/* Only drag in X or Y direction dictated by the direction variable */ /* Only drag in X or Y direction dictated by the direction variable */
if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
/* Swap start and ending tile, also the half-tile drag var (bit 0 and 1) */ /* Swap start and ending tile, also the half-tile drag vars. */
if (start_tile > end_tile || (start_tile == end_tile && HasBit(p2, 0))) { if (start_tile > end_tile || (start_tile == end_tile && start_half)) {
TileIndex t = start_tile; std::swap(start_tile, end_tile);
start_tile = end_tile; std::swap(start_half, end_half);
end_tile = t;
p2 ^= IsInsideMM(p2 & 3, 1, 3) ? 3 : 0;
} }
Money money_available = GetAvailableMoneyForCommand(); Money money_available = GetAvailableMoneyForCommand();
@ -1121,8 +1096,8 @@ CommandCost CmdRemoveLongRoad(DoCommandFlag flags, TileIndex start_tile, uint32
for (;;) { for (;;) {
RoadBits bits = AxisToRoadBits(axis); RoadBits bits = AxisToRoadBits(axis);
if (tile == end_tile && !HasBit(p2, 1)) bits &= ROAD_NW | ROAD_NE; if (tile == end_tile && !end_half) bits &= ROAD_NW | ROAD_NE;
if (tile == start_tile && HasBit(p2, 0)) bits &= ROAD_SE | ROAD_SW; if (tile == start_tile && start_half) bits &= ROAD_SE | ROAD_SW;
/* try to remove the halves. */ /* try to remove the halves. */
if (bits != 0) { if (bits != 0) {
@ -1132,7 +1107,7 @@ CommandCost CmdRemoveLongRoad(DoCommandFlag flags, TileIndex start_tile, uint32
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
money_spent += ret.GetCost(); money_spent += ret.GetCost();
if (money_spent > 0 && money_spent > money_available) { if (money_spent > 0 && money_spent > money_available) {
_additional_cash_required = Command<CMD_REMOVE_LONG_ROAD>::Do(flags & ~DC_EXEC, start_tile, end_tile, p2, {}).GetCost(); _additional_cash_required = Command<CMD_REMOVE_LONG_ROAD>::Do(flags & ~DC_EXEC, start_tile, end_tile, rt, axis, start_half, end_half).GetCost();
return cost; return cost;
} }
RemoveRoad(tile, flags, bits, rtt, true, false); RemoveRoad(tile, flags, bits, rtt, true, false);
@ -2342,17 +2317,12 @@ static void ConvertRoadTypeOwner(TileIndex tile, uint num_pieces, Owner owner, R
* *
* @param flags operation to perform * @param flags operation to perform
* @param tile end tile of road conversion drag * @param tile end tile of road conversion drag
* @param p1 start tile of drag * @param area_start start tile of drag
* @param p2 various bitstuffed elements: * @param to_type new roadtype to convert to.
* - p2 = (bit 0..5) new roadtype to convert to.
* @param text unused
* @return the cost of this operation or an error * @return the cost of this operation or an error
*/ */
CommandCost CmdConvertRoad(DoCommandFlag flags, TileIndex tile, uint32 p1, uint32 p2, const std::string &text) CommandCost CmdConvertRoad(DoCommandFlag flags, TileIndex tile, TileIndex area_start, RoadType to_type)
{ {
RoadType to_type = Extract<RoadType, 0, 6>(p2);
TileIndex area_start = p1;
TileIndex area_end = tile; TileIndex area_end = tile;
if (!ValParamRoadType(to_type)) return CMD_ERROR; if (!ValParamRoadType(to_type)) return CMD_ERROR;

View File

@ -17,11 +17,11 @@
void DrawRoadDepotSprite(int x, int y, DiagDirection dir, RoadType rt); void DrawRoadDepotSprite(int x, int y, DiagDirection dir, RoadType rt);
void UpdateNearestTownForRoadTiles(bool invalidate); void UpdateNearestTownForRoadTiles(bool invalidate);
CommandProc CmdBuildLongRoad; CommandCost CmdBuildLongRoad(DoCommandFlag flags, TileIndex start_tile, TileIndex end_tile, RoadType rt, Axis axis, DisallowedRoadDirections drd, bool start_half, bool end_half, bool is_ai);
CommandProc CmdRemoveLongRoad; CommandCost CmdRemoveLongRoad(DoCommandFlag flags, TileIndex start_tile, TileIndex end_tile, RoadType rt, Axis axis, bool start_half, bool end_half);
CommandProc CmdBuildRoad; CommandCost CmdBuildRoad(DoCommandFlag flags, TileIndex tile, RoadBits pieces, RoadType rt, DisallowedRoadDirections toggle_drd, TownID town_id);
CommandCost CmdBuildRoadDepot(DoCommandFlag flags, TileIndex tile, RoadType rt, DiagDirection dir); CommandCost CmdBuildRoadDepot(DoCommandFlag flags, TileIndex tile, RoadType rt, DiagDirection dir);
CommandProc CmdConvertRoad; CommandCost CmdConvertRoad(DoCommandFlag flags, TileIndex tile, TileIndex area_start, RoadType to_type);
DEF_CMD_TRAIT(CMD_BUILD_LONG_ROAD, CmdBuildLongRoad, CMD_AUTO | CMD_NO_WATER | CMD_DEITY, CMDT_LANDSCAPE_CONSTRUCTION) DEF_CMD_TRAIT(CMD_BUILD_LONG_ROAD, CmdBuildLongRoad, CMD_AUTO | CMD_NO_WATER | CMD_DEITY, CMDT_LANDSCAPE_CONSTRUCTION)
DEF_CMD_TRAIT(CMD_REMOVE_LONG_ROAD, CmdRemoveLongRoad, CMD_AUTO | CMD_NO_TEST, CMDT_LANDSCAPE_CONSTRUCTION) // towns may disallow removing road bits (as they are connected) in test, but in exec they're removed and thus removing is allowed. DEF_CMD_TRAIT(CMD_REMOVE_LONG_ROAD, CmdRemoveLongRoad, CMD_AUTO | CMD_NO_TEST, CMDT_LANDSCAPE_CONSTRUCTION) // towns may disallow removing road bits (as they are connected) in test, but in exec they're removed and thus removing is allowed.

View File

@ -47,22 +47,10 @@ static void ShowRoadDepotPicker(Window *parent);
static bool _remove_button_clicked; static bool _remove_button_clicked;
static bool _one_way_button_clicked; static bool _one_way_button_clicked;
/** static Axis _place_road_dir;
* Define the values of the RoadFlags static bool _place_road_start_half_x;
* @see CmdBuildLongRoad static bool _place_road_start_half_y;
*/ static bool _place_road_end_half;
enum RoadFlags {
RF_NONE = 0x00,
RF_START_HALFROAD_Y = 0x01, // The start tile in Y-dir should have only a half road
RF_END_HALFROAD_Y = 0x02, // The end tile in Y-dir should have only a half road
RF_DIR_Y = 0x04, // The direction is Y-dir
RF_DIR_X = RF_NONE, // Dummy; Dir X is set when RF_DIR_Y is not set
RF_START_HALFROAD_X = 0x08, // The start tile in X-dir should have only a half road
RF_END_HALFROAD_X = 0x10, // The end tile in X-dir should have only a half road
};
DECLARE_ENUM_AS_BIT_SET(RoadFlags)
static RoadFlags _place_road_flag;
static RoadType _cur_roadtype; static RoadType _cur_roadtype;
@ -124,7 +112,7 @@ void ConnectRoadToStructure(TileIndex tile, DiagDirection direction)
/* if there is a roadpiece just outside of the station entrance, build a connecting route */ /* if there is a roadpiece just outside of the station entrance, build a connecting route */
if (IsNormalRoadTile(tile)) { if (IsNormalRoadTile(tile)) {
if (GetRoadBits(tile, GetRoadTramType(_cur_roadtype)) != ROAD_NONE) { if (GetRoadBits(tile, GetRoadTramType(_cur_roadtype)) != ROAD_NONE) {
Command<CMD_BUILD_ROAD>::Post(tile, _cur_roadtype << 4 | DiagDirToRoadBits(ReverseDiagDir(direction)), 0, {}); Command<CMD_BUILD_ROAD>::Post(tile, DiagDirToRoadBits(ReverseDiagDir(direction)), _cur_roadtype, DRD_NONE, 0);
} }
} }
} }
@ -523,21 +511,21 @@ struct BuildRoadToolbarWindow : Window {
_one_way_button_clicked = RoadTypeIsRoad(this->roadtype) ? this->IsWidgetLowered(WID_ROT_ONE_WAY) : false; _one_way_button_clicked = RoadTypeIsRoad(this->roadtype) ? this->IsWidgetLowered(WID_ROT_ONE_WAY) : false;
switch (this->last_started_action) { switch (this->last_started_action) {
case WID_ROT_ROAD_X: case WID_ROT_ROAD_X:
_place_road_flag = RF_DIR_X; _place_road_dir = AXIS_X;
if (_tile_fract_coords.x >= 8) _place_road_flag |= RF_START_HALFROAD_X; _place_road_start_half_x = _tile_fract_coords.x >= 8;
VpStartPlaceSizing(tile, VPM_FIX_Y, DDSP_PLACE_ROAD_X_DIR); VpStartPlaceSizing(tile, VPM_FIX_Y, DDSP_PLACE_ROAD_X_DIR);
break; break;
case WID_ROT_ROAD_Y: case WID_ROT_ROAD_Y:
_place_road_flag = RF_DIR_Y; _place_road_dir = AXIS_Y;
if (_tile_fract_coords.y >= 8) _place_road_flag |= RF_START_HALFROAD_Y; _place_road_start_half_y = _tile_fract_coords.y >= 8;
VpStartPlaceSizing(tile, VPM_FIX_X, DDSP_PLACE_ROAD_Y_DIR); VpStartPlaceSizing(tile, VPM_FIX_X, DDSP_PLACE_ROAD_Y_DIR);
break; break;
case WID_ROT_AUTOROAD: case WID_ROT_AUTOROAD:
_place_road_flag = RF_NONE; _place_road_dir = INVALID_AXIS;
if (_tile_fract_coords.x >= 8) _place_road_flag |= RF_START_HALFROAD_X; _place_road_start_half_x = _tile_fract_coords.x >= 8;
if (_tile_fract_coords.y >= 8) _place_road_flag |= RF_START_HALFROAD_Y; _place_road_start_half_y = _tile_fract_coords.y >= 8;
VpStartPlaceSizing(tile, VPM_X_OR_Y, DDSP_PLACE_AUTOROAD); VpStartPlaceSizing(tile, VPM_X_OR_Y, DDSP_PLACE_AUTOROAD);
break; break;
@ -564,7 +552,7 @@ struct BuildRoadToolbarWindow : Window {
case WID_ROT_BUILD_TUNNEL: case WID_ROT_BUILD_TUNNEL:
Command<CMD_BUILD_TUNNEL>::Post(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE, CcBuildRoadTunnel, Command<CMD_BUILD_TUNNEL>::Post(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE, CcBuildRoadTunnel,
tile, _cur_roadtype | (TRANSPORT_ROAD << 8), 0, {}); tile, TRANSPORT_ROAD, _cur_roadtype);
break; break;
case WID_ROT_CONVERT_ROAD: case WID_ROT_CONVERT_ROAD:
@ -603,30 +591,26 @@ struct BuildRoadToolbarWindow : Window {
* bits and if needed we set them again. */ * bits and if needed we set them again. */
switch (select_proc) { switch (select_proc) {
case DDSP_PLACE_ROAD_X_DIR: case DDSP_PLACE_ROAD_X_DIR:
_place_road_flag &= ~RF_END_HALFROAD_X; _place_road_end_half = pt.x & 8;
if (pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X;
break; break;
case DDSP_PLACE_ROAD_Y_DIR: case DDSP_PLACE_ROAD_Y_DIR:
_place_road_flag &= ~RF_END_HALFROAD_Y; _place_road_end_half = pt.y & 8;
if (pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y;
break; break;
case DDSP_PLACE_AUTOROAD: case DDSP_PLACE_AUTOROAD:
_place_road_flag &= ~(RF_END_HALFROAD_Y | RF_END_HALFROAD_X);
if (pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y;
if (pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X;
/* For autoroad we need to update the /* For autoroad we need to update the
* direction of the road */ * direction of the road */
if (_thd.size.x > _thd.size.y || (_thd.size.x == _thd.size.y && if (_thd.size.x > _thd.size.y || (_thd.size.x == _thd.size.y &&
( (_tile_fract_coords.x < _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) < 16) || ( (_tile_fract_coords.x < _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) < 16) ||
(_tile_fract_coords.x > _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) > 16) ))) { (_tile_fract_coords.x > _tile_fract_coords.y && (_tile_fract_coords.x + _tile_fract_coords.y) > 16) ))) {
/* Set dir = X */ /* Set dir = X */
_place_road_flag &= ~RF_DIR_Y; _place_road_dir = AXIS_X;
_place_road_end_half = pt.x & 8;
} else { } else {
/* Set dir = Y */ /* Set dir = Y */
_place_road_flag |= RF_DIR_Y; _place_road_dir = AXIS_Y;
_place_road_end_half = pt.y & 8;
} }
break; break;
@ -654,25 +638,18 @@ struct BuildRoadToolbarWindow : Window {
case DDSP_PLACE_ROAD_X_DIR: case DDSP_PLACE_ROAD_X_DIR:
case DDSP_PLACE_ROAD_Y_DIR: case DDSP_PLACE_ROAD_Y_DIR:
case DDSP_PLACE_AUTOROAD: case DDSP_PLACE_AUTOROAD: {
/* Flag description: bool start_half = _place_road_dir == AXIS_Y ? _place_road_start_half_y : _place_road_start_half_y;
* Use the first three bits (0x07) if dir == Y
* else use the last 2 bits (X dir has
* not the 3rd bit set) */
/* Even if _cur_roadtype_id is a uint8 we only use 5 bits so
* we could ignore the last 3 bits and reuse them for other
* flags */
_place_road_flag = (RoadFlags)((_place_road_flag & RF_DIR_Y) ? (_place_road_flag & 0x07) : (_place_road_flag >> 3));
if (_remove_button_clicked) { if (_remove_button_clicked) {
Command<CMD_REMOVE_LONG_ROAD>::Post(this->rti->strings.err_remove_road, CcPlaySound_CONSTRUCTION_OTHER, Command<CMD_REMOVE_LONG_ROAD>::Post(this->rti->strings.err_remove_road, CcPlaySound_CONSTRUCTION_OTHER,
start_tile, end_tile, _place_road_flag | (_cur_roadtype << 3) | (_one_way_button_clicked << 10), {}); start_tile, end_tile, _cur_roadtype, _place_road_dir, start_half, _place_road_end_half);
} else { } else {
Command<CMD_BUILD_LONG_ROAD>::Post(this->rti->strings.err_build_road, CcPlaySound_CONSTRUCTION_OTHER, Command<CMD_BUILD_LONG_ROAD>::Post(this->rti->strings.err_build_road, CcPlaySound_CONSTRUCTION_OTHER,
start_tile, end_tile, _place_road_flag | (_cur_roadtype << 3) | (_one_way_button_clicked << 10), {}); start_tile, end_tile, _cur_roadtype, _place_road_dir, _one_way_button_clicked ? DRD_NORTHBOUND : DRD_NONE, start_tile, _place_road_end_half, false);
} }
break; break;
}
case DDSP_BUILD_BUSSTOP: case DDSP_BUILD_BUSSTOP:
case DDSP_REMOVE_BUSSTOP: case DDSP_REMOVE_BUSSTOP:
@ -699,7 +676,7 @@ struct BuildRoadToolbarWindow : Window {
break; break;
case DDSP_CONVERT_ROAD: case DDSP_CONVERT_ROAD:
Command<CMD_CONVERT_ROAD>::Post(rti->strings.err_convert_road, CcPlaySound_CONSTRUCTION_OTHER, end_tile, start_tile, _cur_roadtype, {}); Command<CMD_CONVERT_ROAD>::Post(rti->strings.err_convert_road, CcPlaySound_CONSTRUCTION_OTHER, end_tile, start_tile, _cur_roadtype);
break; break;
} }
} }
@ -707,7 +684,7 @@ struct BuildRoadToolbarWindow : Window {
void OnPlacePresize(Point pt, TileIndex tile) override void OnPlacePresize(Point pt, TileIndex tile) override
{ {
Command<CMD_BUILD_TUNNEL>::Do(DC_AUTO, tile, _cur_roadtype | (TRANSPORT_ROAD << 8), 0, {}); Command<CMD_BUILD_TUNNEL>::Do(DC_AUTO, tile, TRANSPORT_ROAD, _cur_roadtype);
VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile); VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile);
} }

View File

@ -15,6 +15,7 @@
#include "rail_type.h" #include "rail_type.h"
#include "road_func.h" #include "road_func.h"
#include "tile_map.h" #include "tile_map.h"
#include "road_type.h"
/** The different types of road tiles. */ /** The different types of road tiles. */
@ -281,18 +282,6 @@ static inline bool HasTownOwnedRoad(TileIndex t)
return HasTileRoadType(t, RTT_ROAD) && IsRoadOwner(t, RTT_ROAD, OWNER_TOWN); return HasTileRoadType(t, RTT_ROAD) && IsRoadOwner(t, RTT_ROAD, OWNER_TOWN);
} }
/** Which directions are disallowed ? */
enum DisallowedRoadDirections {
DRD_NONE, ///< None of the directions are disallowed
DRD_SOUTHBOUND, ///< All southbound traffic is disallowed
DRD_NORTHBOUND, ///< All northbound traffic is disallowed
DRD_BOTH, ///< All directions are disallowed
DRD_END, ///< Sentinel
};
DECLARE_ENUM_AS_BIT_SET(DisallowedRoadDirections)
/** Helper information for extract tool. */
template <> struct EnumPropsT<DisallowedRoadDirections> : MakeEnumPropsT<DisallowedRoadDirections, byte, DRD_NONE, DRD_END, DRD_END, 2> {};
/** /**
* Gets the disallowed directions * Gets the disallowed directions
* @param t the tile to get the directions from * @param t the tile to get the directions from

View File

@ -19,7 +19,7 @@ typedef uint32 RoadTypeLabel;
* *
* @note currently only ROADTYPE_ROAD and ROADTYPE_TRAM are supported. * @note currently only ROADTYPE_ROAD and ROADTYPE_TRAM are supported.
*/ */
enum RoadType { enum RoadType : byte {
ROADTYPE_BEGIN = 0, ///< Used for iterations ROADTYPE_BEGIN = 0, ///< Used for iterations
ROADTYPE_ROAD = 0, ///< Basic road type ROADTYPE_ROAD = 0, ///< Basic road type
ROADTYPE_TRAM = 1, ///< Trams ROADTYPE_TRAM = 1, ///< Trams
@ -47,7 +47,7 @@ DECLARE_ENUM_AS_BIT_SET(RoadTypes)
* This enumeration defines the possible road parts which * This enumeration defines the possible road parts which
* can be build on a tile. * can be build on a tile.
*/ */
enum RoadBits { enum RoadBits : byte {
ROAD_NONE = 0U, ///< No road-part is build ROAD_NONE = 0U, ///< No road-part is build
ROAD_NW = 1U, ///< North-west part ROAD_NW = 1U, ///< North-west part
ROAD_SW = 2U, ///< South-west part ROAD_SW = 2U, ///< South-west part
@ -68,4 +68,16 @@ enum RoadBits {
DECLARE_ENUM_AS_BIT_SET(RoadBits) DECLARE_ENUM_AS_BIT_SET(RoadBits)
template <> struct EnumPropsT<RoadBits> : MakeEnumPropsT<RoadBits, byte, ROAD_NONE, ROAD_END, ROAD_NONE, 4> {}; template <> struct EnumPropsT<RoadBits> : MakeEnumPropsT<RoadBits, byte, ROAD_NONE, ROAD_END, ROAD_NONE, 4> {};
/** Which directions are disallowed ? */
enum DisallowedRoadDirections : byte {
DRD_NONE, ///< None of the directions are disallowed
DRD_SOUTHBOUND, ///< All southbound traffic is disallowed
DRD_NORTHBOUND, ///< All northbound traffic is disallowed
DRD_BOTH, ///< All directions are disallowed
DRD_END, ///< Sentinel
};
DECLARE_ENUM_AS_BIT_SET(DisallowedRoadDirections)
/** Helper information for extract tool. */
template <> struct EnumPropsT<DisallowedRoadDirections> : MakeEnumPropsT<DisallowedRoadDirections, byte, DRD_NONE, DRD_END, DRD_END, 2> {};
#endif /* ROAD_TYPE_H */ #endif /* ROAD_TYPE_H */

View File

@ -1131,7 +1131,7 @@ static bool CanBuildTramTrackOnTile(CompanyID c, TileIndex t, RoadType rt, RoadB
/* The 'current' company is not necessarily the owner of the vehicle. */ /* The 'current' company is not necessarily the owner of the vehicle. */
Backup<CompanyID> cur_company(_current_company, c, FILE_LINE); Backup<CompanyID> cur_company(_current_company, c, FILE_LINE);
CommandCost ret = Command<CMD_BUILD_ROAD>::Do(DC_NO_WATER, t, rt << 4 | r, 0, {}); CommandCost ret = Command<CMD_BUILD_ROAD>::Do(DC_NO_WATER, t, r, rt, DRD_NONE, 0);
cur_company.Restore(); cur_company.Restore();
return ret.Succeeded(); return ret.Succeeded();

View File

@ -80,30 +80,17 @@ static void _DoCommandReturnBuildBridge1(class ScriptInstance *instance)
EnforcePrecondition(false, vehicle_type != ScriptVehicle::VT_ROAD || ScriptRoad::IsRoadTypeAvailable(ScriptRoad::GetCurrentRoadType())); EnforcePrecondition(false, vehicle_type != ScriptVehicle::VT_ROAD || ScriptRoad::IsRoadTypeAvailable(ScriptRoad::GetCurrentRoadType()));
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY || vehicle_type == ScriptVehicle::VT_ROAD); EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY || vehicle_type == ScriptVehicle::VT_ROAD);
uint type = 0;
switch (vehicle_type) { switch (vehicle_type) {
case ScriptVehicle::VT_ROAD: case ScriptVehicle::VT_ROAD:
type |= (TRANSPORT_ROAD << 15); ScriptObject::SetCallbackVariable(0, start);
type |= (ScriptRoad::GetCurrentRoadType() << 8); ScriptObject::SetCallbackVariable(1, end);
break; return ScriptObject::Command<CMD_BUILD_BRIDGE>::Do(&::_DoCommandReturnBuildBridge1, end, start, TRANSPORT_ROAD, bridge_id, ScriptRoad::GetCurrentRoadType());
case ScriptVehicle::VT_RAIL: case ScriptVehicle::VT_RAIL:
type |= (TRANSPORT_RAIL << 15); return ScriptObject::Command<CMD_BUILD_BRIDGE>::Do(end, start, TRANSPORT_RAIL, bridge_id, ScriptRail::GetCurrentRailType());
type |= (ScriptRail::GetCurrentRailType() << 8);
break;
case ScriptVehicle::VT_WATER: case ScriptVehicle::VT_WATER:
type |= (TRANSPORT_WATER << 15); return ScriptObject::Command<CMD_BUILD_BRIDGE>::Do(end, start, TRANSPORT_WATER, bridge_id, 0);
break;
default: NOT_REACHED(); default: NOT_REACHED();
} }
/* For rail and water we do nothing special */
if (vehicle_type == ScriptVehicle::VT_RAIL || vehicle_type == ScriptVehicle::VT_WATER) {
return ScriptObject::Command<CMD_BUILD_BRIDGE>::Do(end, start, type | bridge_id, {});
}
ScriptObject::SetCallbackVariable(0, start);
ScriptObject::SetCallbackVariable(1, end);
return ScriptObject::Command<CMD_BUILD_BRIDGE>::Do(&::_DoCommandReturnBuildBridge1, end, start, type | bridge_id, {});
} }
/* static */ bool ScriptBridge::_BuildBridgeRoad1() /* static */ bool ScriptBridge::_BuildBridgeRoad1()
@ -115,7 +102,7 @@ static void _DoCommandReturnBuildBridge1(class ScriptInstance *instance)
DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start); DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start);
DiagDirection dir_2 = ::ReverseDiagDir(dir_1); DiagDirection dir_2 = ::ReverseDiagDir(dir_1);
return ScriptObject::Command<CMD_BUILD_ROAD>::Do(&::_DoCommandReturnBuildBridge2, start + ::TileOffsByDiagDir(dir_1), ::DiagDirToRoadBits(dir_2) | (ScriptRoad::GetCurrentRoadType() << 4), 0, {}); return ScriptObject::Command<CMD_BUILD_ROAD>::Do(&::_DoCommandReturnBuildBridge2, start + ::TileOffsByDiagDir(dir_1), ::DiagDirToRoadBits(dir_2), (::RoadType)ScriptRoad::GetCurrentRoadType(), DRD_NONE, 0);
} }
/* static */ bool ScriptBridge::_BuildBridgeRoad2() /* static */ bool ScriptBridge::_BuildBridgeRoad2()
@ -127,7 +114,7 @@ static void _DoCommandReturnBuildBridge1(class ScriptInstance *instance)
DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start); DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start);
DiagDirection dir_2 = ::ReverseDiagDir(dir_1); DiagDirection dir_2 = ::ReverseDiagDir(dir_1);
return ScriptObject::Command<CMD_BUILD_ROAD>::Do(end + ::TileOffsByDiagDir(dir_2), ::DiagDirToRoadBits(dir_1) | (ScriptRoad::GetCurrentRoadType() << 4), 0, {}); return ScriptObject::Command<CMD_BUILD_ROAD>::Do(end + ::TileOffsByDiagDir(dir_2), ::DiagDirToRoadBits(dir_1), (::RoadType)ScriptRoad::GetCurrentRoadType(), DRD_NONE, 0);
} }
/* static */ bool ScriptBridge::RemoveBridge(TileIndex tile) /* static */ bool ScriptBridge::RemoveBridge(TileIndex tile)

View File

@ -108,7 +108,7 @@
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY); EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
EnforcePrecondition(false, ::IsValidTile(tile)); EnforcePrecondition(false, ::IsValidTile(tile));
return ScriptObject::Command<CMD_BUILD_LOCK>::Do(tile, 0, 0, {}); return ScriptObject::Command<CMD_BUILD_LOCK>::Do(tile);
} }
/* static */ bool ScriptMarine::BuildCanal(TileIndex tile) /* static */ bool ScriptMarine::BuildCanal(TileIndex tile)
@ -116,7 +116,7 @@
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY); EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
EnforcePrecondition(false, ::IsValidTile(tile)); EnforcePrecondition(false, ::IsValidTile(tile));
return ScriptObject::Command<CMD_BUILD_CANAL>::Do(tile, tile, WATER_CLASS_CANAL, {}); return ScriptObject::Command<CMD_BUILD_CANAL>::Do(tile, tile, WATER_CLASS_CANAL, false);
} }
/* static */ bool ScriptMarine::RemoveWaterDepot(TileIndex tile) /* static */ bool ScriptMarine::RemoveWaterDepot(TileIndex tile)

View File

@ -129,7 +129,7 @@
EnforcePrecondition(false, ::IsValidTile(end_tile)); EnforcePrecondition(false, ::IsValidTile(end_tile));
EnforcePrecondition(false, IsRoadTypeAvailable(road_type)); EnforcePrecondition(false, IsRoadTypeAvailable(road_type));
return ScriptObject::Command<CMD_CONVERT_ROAD>::Do(start_tile, end_tile, (::RoadType)road_type, {}); return ScriptObject::Command<CMD_CONVERT_ROAD>::Do(start_tile, end_tile, (::RoadType)road_type);
} }
/* Helper functions for ScriptRoad::CanBuildConnectedRoadParts(). */ /* Helper functions for ScriptRoad::CanBuildConnectedRoadParts(). */
@ -495,7 +495,8 @@ static bool NeighbourHasReachableRoad(::RoadType rt, TileIndex start_tile, DiagD
EnforcePrecondition(false, !one_way || RoadTypeIsRoad(ScriptObject::GetRoadType())); EnforcePrecondition(false, !one_way || RoadTypeIsRoad(ScriptObject::GetRoadType()));
EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType())); EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType()));
return ScriptObject::Command<CMD_BUILD_LONG_ROAD>::Do(start, end, (::TileY(start) != ::TileY(end) ? 4 : 0) | (((start < end) == !full) ? 1 : 2) | (ScriptObject::GetRoadType() << 3) | ((one_way ? 1 : 0) << 10) | 1 << 11, {}); Axis axis = ::TileY(start) != ::TileY(end) ? AXIS_Y : AXIS_X;
return ScriptObject::Command<CMD_BUILD_LONG_ROAD>::Do(start, end, ScriptObject::GetRoadType(), axis, one_way ? DRD_NORTHBOUND : DRD_NONE, (start < end) == !full, (start < end) != !full, true);
} }
/* static */ bool ScriptRoad::BuildRoad(TileIndex start, TileIndex end) /* static */ bool ScriptRoad::BuildRoad(TileIndex start, TileIndex end)
@ -570,7 +571,7 @@ static bool NeighbourHasReachableRoad(::RoadType rt, TileIndex start_tile, DiagD
EnforcePrecondition(false, ::TileX(start) == ::TileX(end) || ::TileY(start) == ::TileY(end)); EnforcePrecondition(false, ::TileX(start) == ::TileX(end) || ::TileY(start) == ::TileY(end));
EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType())); EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType()));
return ScriptObject::Command<CMD_REMOVE_LONG_ROAD>::Do(start, end, (::TileY(start) != ::TileY(end) ? 4 : 0) | (start < end ? 1 : 2) | (ScriptObject::GetRoadType() << 3), {}); return ScriptObject::Command<CMD_REMOVE_LONG_ROAD>::Do(start, end, ScriptObject::GetRoadType(), ::TileY(start) != ::TileY(end) ? AXIS_Y : AXIS_X, start < end, start >= end);
} }
/* static */ bool ScriptRoad::RemoveRoadFull(TileIndex start, TileIndex end) /* static */ bool ScriptRoad::RemoveRoadFull(TileIndex start, TileIndex end)
@ -582,7 +583,7 @@ static bool NeighbourHasReachableRoad(::RoadType rt, TileIndex start_tile, DiagD
EnforcePrecondition(false, ::TileX(start) == ::TileX(end) || ::TileY(start) == ::TileY(end)); EnforcePrecondition(false, ::TileX(start) == ::TileX(end) || ::TileY(start) == ::TileY(end));
EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType())); EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType()));
return ScriptObject::Command<CMD_REMOVE_LONG_ROAD>::Do(start, end, (::TileY(start) != ::TileY(end) ? 4 : 0) | (start < end ? 2 : 1) | (ScriptObject::GetRoadType() << 3), {}); return ScriptObject::Command<CMD_REMOVE_LONG_ROAD>::Do(start, end, ScriptObject::GetRoadType(), ::TileY(start) != ::TileY(end) ? AXIS_Y : AXIS_X, start >= end, start < end);
} }
/* static */ bool ScriptRoad::RemoveRoadDepot(TileIndex tile) /* static */ bool ScriptRoad::RemoveRoadDepot(TileIndex tile)

View File

@ -88,22 +88,13 @@ static void _DoCommandReturnBuildTunnel1(class ScriptInstance *instance)
EnforcePrecondition(false, vehicle_type != ScriptVehicle::VT_ROAD || ScriptRoad::IsRoadTypeAvailable(ScriptRoad::GetCurrentRoadType())); EnforcePrecondition(false, vehicle_type != ScriptVehicle::VT_ROAD || ScriptRoad::IsRoadTypeAvailable(ScriptRoad::GetCurrentRoadType()));
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY || vehicle_type == ScriptVehicle::VT_ROAD); EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY || vehicle_type == ScriptVehicle::VT_ROAD);
uint type = 0;
if (vehicle_type == ScriptVehicle::VT_ROAD) {
type |= (TRANSPORT_ROAD << 8);
type |= ScriptRoad::GetCurrentRoadType();
} else {
type |= (TRANSPORT_RAIL << 8);
type |= ScriptRail::GetCurrentRailType();
}
/* For rail we do nothing special */
if (vehicle_type == ScriptVehicle::VT_RAIL) { if (vehicle_type == ScriptVehicle::VT_RAIL) {
return ScriptObject::Command<CMD_BUILD_TUNNEL>::Do(start, type, 0, {}); /* For rail we do nothing special */
return ScriptObject::Command<CMD_BUILD_TUNNEL>::Do(start, TRANSPORT_RAIL, ScriptRail::GetCurrentRailType());
} else {
ScriptObject::SetCallbackVariable(0, start);
return ScriptObject::Command<CMD_BUILD_TUNNEL>::Do(&::_DoCommandReturnBuildTunnel1, start, TRANSPORT_ROAD, ScriptRoad::GetCurrentRoadType());
} }
ScriptObject::SetCallbackVariable(0, start);
return ScriptObject::Command<CMD_BUILD_TUNNEL>::Do(&::_DoCommandReturnBuildTunnel1, start, type, 0, {});
} }
/* static */ bool ScriptTunnel::_BuildTunnelRoad1() /* static */ bool ScriptTunnel::_BuildTunnelRoad1()
@ -115,7 +106,7 @@ static void _DoCommandReturnBuildTunnel1(class ScriptInstance *instance)
DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start); DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start);
DiagDirection dir_2 = ::ReverseDiagDir(dir_1); DiagDirection dir_2 = ::ReverseDiagDir(dir_1);
return ScriptObject::Command<CMD_BUILD_ROAD>::Do(&::_DoCommandReturnBuildTunnel2, start + ::TileOffsByDiagDir(dir_1), ::DiagDirToRoadBits(dir_2) | (ScriptObject::GetRoadType() << 4), 0, {}); return ScriptObject::Command<CMD_BUILD_ROAD>::Do(&::_DoCommandReturnBuildTunnel2, start + ::TileOffsByDiagDir(dir_1), ::DiagDirToRoadBits(dir_2), ScriptRoad::GetRoadType(), DRD_NONE, 0);
} }
/* static */ bool ScriptTunnel::_BuildTunnelRoad2() /* static */ bool ScriptTunnel::_BuildTunnelRoad2()
@ -127,7 +118,7 @@ static void _DoCommandReturnBuildTunnel1(class ScriptInstance *instance)
DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start); DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start);
DiagDirection dir_2 = ::ReverseDiagDir(dir_1); DiagDirection dir_2 = ::ReverseDiagDir(dir_1);
return ScriptObject::Command<CMD_BUILD_ROAD>::Do(end + ::TileOffsByDiagDir(dir_2), ::DiagDirToRoadBits(dir_1) | (ScriptObject::GetRoadType() << 4), 0, {}); return ScriptObject::Command<CMD_BUILD_ROAD>::Do(end + ::TileOffsByDiagDir(dir_2), ::DiagDirToRoadBits(dir_1), ScriptRoad::GetRoadType(), DRD_NONE, 0);
} }
/* static */ bool ScriptTunnel::RemoveTunnel(TileIndex tile) /* static */ bool ScriptTunnel::RemoveTunnel(TileIndex tile)

View File

@ -943,7 +943,7 @@ static bool IsRoadAllowedHere(Town *t, TileIndex tile, DiagDirection dir)
* If that fails clear the land, and if that fails exit. * If that fails clear the land, and if that fails exit.
* This is to make sure that we can build a road here later. */ * This is to make sure that we can build a road here later. */
RoadType rt = GetTownRoadType(t); RoadType rt = GetTownRoadType(t);
if (Command<CMD_BUILD_ROAD>::Do(DC_AUTO | DC_NO_WATER, tile, ((dir == DIAGDIR_NW || dir == DIAGDIR_SE) ? ROAD_Y : ROAD_X) | (rt << 4), 0, {}).Failed() && if (Command<CMD_BUILD_ROAD>::Do(DC_AUTO | DC_NO_WATER, tile, (dir == DIAGDIR_NW || dir == DIAGDIR_SE) ? ROAD_Y : ROAD_X, rt, DRD_NONE, 0).Failed() &&
Command<CMD_LANDSCAPE_CLEAR>::Do(DC_AUTO | DC_NO_WATER, tile, 0, 0, {}).Failed()) { Command<CMD_LANDSCAPE_CLEAR>::Do(DC_AUTO | DC_NO_WATER, tile, 0, 0, {}).Failed()) {
return false; return false;
} }
@ -1112,7 +1112,7 @@ static bool GrowTownWithExtraHouse(Town *t, TileIndex tile)
static bool GrowTownWithRoad(const Town *t, TileIndex tile, RoadBits rcmd) static bool GrowTownWithRoad(const Town *t, TileIndex tile, RoadBits rcmd)
{ {
RoadType rt = GetTownRoadType(t); RoadType rt = GetTownRoadType(t);
if (Command<CMD_BUILD_ROAD>::Do(DC_EXEC | DC_AUTO | DC_NO_WATER, tile, rcmd | (rt << 4), t->index, {}).Succeeded()) { if (Command<CMD_BUILD_ROAD>::Do(DC_EXEC | DC_AUTO | DC_NO_WATER, tile, rcmd, rt, DRD_NONE, t->index).Succeeded()) {
_grow_town_result = GROWTH_SUCCEED; _grow_town_result = GROWTH_SUCCEED;
return true; return true;
} }
@ -1159,7 +1159,7 @@ static bool CanRoadContinueIntoNextTile(const Town *t, const TileIndex tile, con
if (IsTileType(next_tile, MP_RAILWAY) && !_settings_game.economy.allow_town_level_crossings) return false; if (IsTileType(next_tile, MP_RAILWAY) && !_settings_game.economy.allow_town_level_crossings) return false;
/* If a road tile can be built, the construction is allowed. */ /* If a road tile can be built, the construction is allowed. */
return Command<CMD_BUILD_ROAD>::Do(DC_AUTO | DC_NO_WATER, next_tile, rcmd | (rt << 4), t->index, {}).Succeeded(); return Command<CMD_BUILD_ROAD>::Do(DC_AUTO | DC_NO_WATER, next_tile, rcmd, rt, DRD_NONE, t->index).Succeeded();
} }
/** /**
@ -1227,8 +1227,8 @@ static bool GrowTownWithBridge(const Town *t, const TileIndex tile, const DiagDi
/* Can we actually build the bridge? */ /* Can we actually build the bridge? */
RoadType rt = GetTownRoadType(t); RoadType rt = GetTownRoadType(t);
if (Command<CMD_BUILD_BRIDGE>::Do(CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_BRIDGE>()), tile, bridge_tile, bridge_type | rt << 8 | TRANSPORT_ROAD << 15, {}).Succeeded()) { if (Command<CMD_BUILD_BRIDGE>::Do(CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_BRIDGE>()), tile, bridge_tile, TRANSPORT_ROAD, bridge_type, rt).Succeeded()) {
Command<CMD_BUILD_BRIDGE>::Do(DC_EXEC | CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_BRIDGE>()), tile, bridge_tile, bridge_type | rt << 8 | TRANSPORT_ROAD << 15, {}); Command<CMD_BUILD_BRIDGE>::Do(DC_EXEC | CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_BRIDGE>()), tile, bridge_tile, TRANSPORT_ROAD, bridge_type, rt);
_grow_town_result = GROWTH_SUCCEED; _grow_town_result = GROWTH_SUCCEED;
return true; return true;
} }
@ -1298,8 +1298,8 @@ static bool GrowTownWithTunnel(const Town *t, const TileIndex tile, const DiagDi
/* Attempt to build the tunnel. Return false if it fails to let the town build a road instead. */ /* Attempt to build the tunnel. Return false if it fails to let the town build a road instead. */
RoadType rt = GetTownRoadType(t); RoadType rt = GetTownRoadType(t);
if (Command<CMD_BUILD_TUNNEL>::Do(CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_TUNNEL>()), tile, rt | (TRANSPORT_ROAD << 8), 0, {}).Succeeded()) { if (Command<CMD_BUILD_TUNNEL>::Do(CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_TUNNEL>()), tile, TRANSPORT_ROAD, rt).Succeeded()) {
Command<CMD_BUILD_TUNNEL>::Do(DC_EXEC | CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_TUNNEL>()), tile, rt | (TRANSPORT_ROAD << 8), 0, {}); Command<CMD_BUILD_TUNNEL>::Do(DC_EXEC | CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_TUNNEL>()), tile, TRANSPORT_ROAD, rt);
_grow_town_result = GROWTH_SUCCEED; _grow_town_result = GROWTH_SUCCEED;
return true; return true;
} }
@ -1739,7 +1739,7 @@ static bool GrowTown(Town *t)
if (!IsTileType(tile, MP_HOUSE) && IsTileFlat(tile)) { if (!IsTileType(tile, MP_HOUSE) && IsTileFlat(tile)) {
if (Command<CMD_LANDSCAPE_CLEAR>::Do(DC_AUTO | DC_NO_WATER, tile, 0, 0, {}).Succeeded()) { if (Command<CMD_LANDSCAPE_CLEAR>::Do(DC_AUTO | DC_NO_WATER, tile, 0, 0, {}).Succeeded()) {
RoadType rt = GetTownRoadType(t); RoadType rt = GetTownRoadType(t);
Command<CMD_BUILD_ROAD>::Do(DC_EXEC | DC_AUTO, tile, GenRandomRoadBits() | (rt << 4), t->index, {}); Command<CMD_BUILD_ROAD>::Do(DC_EXEC | DC_AUTO, tile, GenRandomRoadBits(), rt, DRD_NONE, t->index);
cur_company.Restore(); cur_company.Restore();
return true; return true;
} }

View File

@ -16,7 +16,7 @@
typedef uint16 UnitID; typedef uint16 UnitID;
/** Available types of transport */ /** Available types of transport */
enum TransportType { enum TransportType : byte {
/* These constants are for now linked to the representation of bridges /* These constants are for now linked to the representation of bridges
* and tunnels, so they can be used by GetTileTrackStatus_TunnelBridge. * and tunnels, so they can be used by GetTileTrackStatus_TunnelBridge.
* In an ideal world, these constants would be used everywhere when * In an ideal world, these constants would be used everywhere when

View File

@ -251,38 +251,31 @@ static Money TunnelBridgeClearCost(TileIndex tile, Price base_price)
/** /**
* Build a Bridge * Build a Bridge
* @param flags type of operation * @param flags type of operation
* @param end_tile end tile * @param tile_end end tile
* @param p1 packed start tile coords (~ dx) * @param tile_start start tile
* @param p2 various bitstuffed elements * @param transport_type transport type.
* - p2 = (bit 0- 7) - bridge type (hi bh) * @param bridge_type bridge type (hi bh)
* - p2 = (bit 8-13) - rail type or road types. * @param road_rail_type rail type or road types.
* - p2 = (bit 15-16) - transport type.
* @param text unused
* @return the cost of this operation or an error * @return the cost of this operation or an error
*/ */
CommandCost CmdBuildBridge(DoCommandFlag flags, TileIndex end_tile, uint32 p1, uint32 p2, const std::string &text) CommandCost CmdBuildBridge(DoCommandFlag flags, TileIndex tile_end, TileIndex tile_start, TransportType transport_type, BridgeType bridge_type, byte road_rail_type)
{ {
CompanyID company = _current_company; CompanyID company = _current_company;
RailType railtype = INVALID_RAILTYPE; RailType railtype = INVALID_RAILTYPE;
RoadType roadtype = INVALID_ROADTYPE; RoadType roadtype = INVALID_ROADTYPE;
/* unpack parameters */ if (!IsValidTile(tile_start)) return_cmd_error(STR_ERROR_BRIDGE_THROUGH_MAP_BORDER);
BridgeType bridge_type = GB(p2, 0, 8);
if (!IsValidTile(p1)) return_cmd_error(STR_ERROR_BRIDGE_THROUGH_MAP_BORDER);
TransportType transport_type = Extract<TransportType, 15, 2>(p2);
/* type of bridge */ /* type of bridge */
switch (transport_type) { switch (transport_type) {
case TRANSPORT_ROAD: case TRANSPORT_ROAD:
roadtype = Extract<RoadType, 8, 6>(p2); roadtype = (RoadType)road_rail_type;
if (!ValParamRoadType(roadtype)) return CMD_ERROR; if (!ValParamRoadType(roadtype)) return CMD_ERROR;
break; break;
case TRANSPORT_RAIL: case TRANSPORT_RAIL:
railtype = Extract<RailType, 8, 6>(p2); railtype = (RailType)road_rail_type;
if (!ValParamRailtype(railtype)) return CMD_ERROR; if (!ValParamRailtype(railtype)) return CMD_ERROR;
break; break;
@ -293,8 +286,6 @@ CommandCost CmdBuildBridge(DoCommandFlag flags, TileIndex end_tile, uint32 p1, u
/* Airports don't have bridges. */ /* Airports don't have bridges. */
return CMD_ERROR; return CMD_ERROR;
} }
TileIndex tile_start = p1;
TileIndex tile_end = end_tile;
if (company == OWNER_DEITY) { if (company == OWNER_DEITY) {
if (transport_type != TRANSPORT_ROAD) return CMD_ERROR; if (transport_type != TRANSPORT_ROAD) return CMD_ERROR;
@ -627,28 +618,25 @@ CommandCost CmdBuildBridge(DoCommandFlag flags, TileIndex end_tile, uint32 p1, u
* Build Tunnel. * Build Tunnel.
* @param flags type of operation * @param flags type of operation
* @param start_tile start tile of tunnel * @param start_tile start tile of tunnel
* @param p1 bit 0-5 railtype or roadtype * @param transport_type transport type
* bit 8-9 transport type * @param road_rail_type railtype or roadtype
* @param p2 unused
* @param text unused
* @return the cost of this operation or an error * @return the cost of this operation or an error
*/ */
CommandCost CmdBuildTunnel(DoCommandFlag flags, TileIndex start_tile, uint32 p1, uint32 p2, const std::string &text) CommandCost CmdBuildTunnel(DoCommandFlag flags, TileIndex start_tile, TransportType transport_type, byte road_rail_type)
{ {
CompanyID company = _current_company; CompanyID company = _current_company;
TransportType transport_type = Extract<TransportType, 8, 2>(p1);
RailType railtype = INVALID_RAILTYPE; RailType railtype = INVALID_RAILTYPE;
RoadType roadtype = INVALID_ROADTYPE; RoadType roadtype = INVALID_ROADTYPE;
_build_tunnel_endtile = 0; _build_tunnel_endtile = 0;
switch (transport_type) { switch (transport_type) {
case TRANSPORT_RAIL: case TRANSPORT_RAIL:
railtype = Extract<RailType, 0, 6>(p1); railtype = (RailType)road_rail_type;
if (!ValParamRailtype(railtype)) return CMD_ERROR; if (!ValParamRailtype(railtype)) return CMD_ERROR;
break; break;
case TRANSPORT_ROAD: case TRANSPORT_ROAD:
roadtype = Extract<RoadType, 0, 6>(p1); roadtype = (RoadType)road_rail_type;
if (!ValParamRoadType(roadtype)) return CMD_ERROR; if (!ValParamRoadType(roadtype)) return CMD_ERROR;
break; break;

View File

@ -11,9 +11,11 @@
#define TUNNELBRIDGE_CMD_H #define TUNNELBRIDGE_CMD_H
#include "command_type.h" #include "command_type.h"
#include "transport_type.h"
#include "bridge.h"
CommandProc CmdBuildBridge; CommandCost CmdBuildBridge(DoCommandFlag flags, TileIndex tile_end, TileIndex tile_start, TransportType transport_type, BridgeType bridge_type, byte road_rail_type);
CommandProc CmdBuildTunnel; CommandCost CmdBuildTunnel(DoCommandFlag flags, TileIndex start_tile, TransportType transport_type, byte road_rail_type);
DEF_CMD_TRAIT(CMD_BUILD_BRIDGE, CmdBuildBridge, CMD_DEITY | CMD_AUTO | CMD_NO_WATER, CMDT_LANDSCAPE_CONSTRUCTION) DEF_CMD_TRAIT(CMD_BUILD_BRIDGE, CmdBuildBridge, CMD_DEITY | CMD_AUTO | CMD_NO_WATER, CMDT_LANDSCAPE_CONSTRUCTION)
DEF_CMD_TRAIT(CMD_BUILD_TUNNEL, CmdBuildTunnel, CMD_DEITY | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION) DEF_CMD_TRAIT(CMD_BUILD_TUNNEL, CmdBuildTunnel, CMD_DEITY | CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION)

View File

@ -411,12 +411,9 @@ static CommandCost RemoveLock(TileIndex tile, DoCommandFlag flags)
* Builds a lock. * Builds a lock.
* @param flags type of operation * @param flags type of operation
* @param tile tile where to place the lock * @param tile tile where to place the lock
* @param p1 unused
* @param p2 unused
* @param text unused
* @return the cost of this operation or an error * @return the cost of this operation or an error
*/ */
CommandCost CmdBuildLock(DoCommandFlag flags, TileIndex tile, uint32 p1, uint32 p2, const std::string &text) CommandCost CmdBuildLock(DoCommandFlag flags, TileIndex tile)
{ {
DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile)); DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile));
if (dir == INVALID_DIAGDIR) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION); if (dir == INVALID_DIAGDIR) return_cmd_error(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
@ -435,34 +432,31 @@ bool RiverModifyDesertZone(TileIndex tile, void *)
* Build a piece of canal. * Build a piece of canal.
* @param flags type of operation * @param flags type of operation
* @param tile end tile of stretch-dragging * @param tile end tile of stretch-dragging
* @param p1 start tile of stretch-dragging * @param start_tile start tile of stretch-dragging
* @param p2 various bitstuffed data * @param wc waterclass to build. sea and river can only be built in scenario editor
* bits 0-1: waterclass to build. sea and river can only be built in scenario editor * @param diagonal Whether to use the Orthogonal (0) or Diagonal (1) iterator.
* bit 2: Whether to use the Orthogonal (0) or Diagonal (1) iterator.
* @param text unused
* @return the cost of this operation or an error * @return the cost of this operation or an error
*/ */
CommandCost CmdBuildCanal(DoCommandFlag flags, TileIndex tile, uint32 p1, uint32 p2, const std::string &text) CommandCost CmdBuildCanal(DoCommandFlag flags, TileIndex tile, TileIndex start_tile, WaterClass wc, bool diagonal)
{ {
WaterClass wc = Extract<WaterClass, 0, 2>(p2); if (start_tile >= MapSize() || !IsEnumValid(wc)) return CMD_ERROR;
if (p1 >= MapSize() || wc == WATER_CLASS_INVALID) return CMD_ERROR;
/* Outside of the editor you can only build canals, not oceans */ /* Outside of the editor you can only build canals, not oceans */
if (wc != WATER_CLASS_CANAL && _game_mode != GM_EDITOR) return CMD_ERROR; if (wc != WATER_CLASS_CANAL && _game_mode != GM_EDITOR) return CMD_ERROR;
/* Outside the editor you can only drag canals, and not areas */ /* Outside the editor you can only drag canals, and not areas */
if (_game_mode != GM_EDITOR) { if (_game_mode != GM_EDITOR) {
TileArea ta(tile, (TileIndex)p1); TileArea ta(tile, start_tile);
if (ta.w != 1 && ta.h != 1) return CMD_ERROR; if (ta.w != 1 && ta.h != 1) return CMD_ERROR;
} }
CommandCost cost(EXPENSES_CONSTRUCTION); CommandCost cost(EXPENSES_CONSTRUCTION);
std::unique_ptr<TileIterator> iter; std::unique_ptr<TileIterator> iter;
if (HasBit(p2, 2)) { if (diagonal) {
iter = std::make_unique<DiagonalTileIterator>(tile, (TileIndex)p1); iter = std::make_unique<DiagonalTileIterator>(tile, start_tile);
} else { } else {
iter = std::make_unique<OrthogonalTileIterator>(tile, (TileIndex)p1); iter = std::make_unique<OrthogonalTileIterator>(tile, start_tile);
} }
for (; *iter != INVALID_TILE; ++(*iter)) { for (; *iter != INVALID_TILE; ++(*iter)) {

View File

@ -11,10 +11,11 @@
#define WATER_CMD_H #define WATER_CMD_H
#include "command_type.h" #include "command_type.h"
#include "water_map.h"
CommandCost CmdBuildShipDepot(DoCommandFlag flags, TileIndex tile, Axis axis); CommandCost CmdBuildShipDepot(DoCommandFlag flags, TileIndex tile, Axis axis);
CommandProc CmdBuildCanal; CommandCost CmdBuildCanal(DoCommandFlag flags, TileIndex tile, TileIndex start_tile, WaterClass wc, bool diagonal);
CommandProc CmdBuildLock; CommandCost CmdBuildLock(DoCommandFlag flags, TileIndex tile);
DEF_CMD_TRAIT(CMD_BUILD_SHIP_DEPOT, CmdBuildShipDepot, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION) DEF_CMD_TRAIT(CMD_BUILD_SHIP_DEPOT, CmdBuildShipDepot, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION)
DEF_CMD_TRAIT(CMD_BUILD_CANAL, CmdBuildCanal, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION) DEF_CMD_TRAIT(CMD_BUILD_CANAL, CmdBuildCanal, CMD_AUTO, CMDT_LANDSCAPE_CONSTRUCTION)

View File

@ -44,7 +44,7 @@ enum WaterTileType {
}; };
/** classes of water (for #WATER_TILE_CLEAR water tile type). */ /** classes of water (for #WATER_TILE_CLEAR water tile type). */
enum WaterClass { enum WaterClass : byte {
WATER_CLASS_SEA, ///< Sea. WATER_CLASS_SEA, ///< Sea.
WATER_CLASS_CANAL, ///< Canal. WATER_CLASS_CANAL, ///< Canal.
WATER_CLASS_RIVER, ///< River. WATER_CLASS_RIVER, ///< River.