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 (_settings_client.sound.confirm) SndPlayTileFx(SND_27_CONSTRUCTION_BRIDGE, end_tile);
auto [tile, p1, p2, text] = EndianBufferReader::ToValue<CommandTraits<CMD_BUILD_BRIDGE>::Args>(data);
TransportType transport_type = Extract<TransportType, 15, 2>(p2);
auto [tile, tile_start, transport_type, bridge_type, road_rail_type] = EndianBufferReader::ToValue<CommandTraits<CMD_BUILD_BRIDGE>::Args>(data);
if (transport_type == TRANSPORT_ROAD) {
DiagDirection end_direction = ReverseDiagDir(GetTunnelBridgeDirection(end_tile));
ConnectRoadToStructure(end_tile, end_direction);
DiagDirection start_direction = ReverseDiagDir(GetTunnelBridgeDirection(p1));
ConnectRoadToStructure(p1, start_direction);
DiagDirection start_direction = ReverseDiagDir(GetTunnelBridgeDirection(tile_start));
ConnectRoadToStructure(tile_start, start_direction);
}
}
@ -86,7 +84,8 @@ private:
/* Internal variables */
TileIndex start_tile;
TileIndex end_tile;
uint32 type;
TransportType transport_type;
byte road_rail_type;
GUIBridgeList *bridges;
int bridgetext_offset; ///< Horizontal offset of the text describing the bridge properties in #WID_BBS_BRIDGE_LIST relative to the left edge.
Scrollbar *vscroll;
@ -111,13 +110,13 @@ private:
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_ROAD: _last_roadbridge_type = this->bridges->at(i).index; break;
default: break;
}
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 */
@ -134,19 +133,20 @@ private:
}
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),
end_tile(end),
type(br_type),
transport_type(transport_type),
road_rail_type(road_rail_type),
bridges(bl)
{
this->CreateNestedTree();
this->vscroll = this->GetScrollbar(WID_BBS_SCROLLBAR);
/* 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->FinishInitNested(GB(br_type, 15, 2)); // Initializes 'this->bridgetext_offset'.
this->GetWidget<NWidgetCore>(WID_BBS_CAPTION)->widget_data = (transport_type == TRANSPORT_ROAD) ? STR_SELECT_ROAD_BRIDGE_CAPTION : STR_SELECT_RAIL_BRIDGE_CAPTION;
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->SetSortFuncs(this->sorter_funcs);
this->bridges->NeedResort();
@ -361,12 +361,6 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo
{
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. */
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
}
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;
}
/* only query bridge building possibility once, result is the same for all bridges!
* returns CMD_ERROR on failure, and price on success */
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;
if (ret.Failed()) {
@ -449,7 +443,7 @@ void ShowBuildBridgeWindow(TileIndex start, TileIndex end, TransportType transpo
}
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 {
delete bl;
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;
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;
case WID_DT_DEMOLISH: // Demolish aka dynamite button
@ -234,7 +234,7 @@ struct BuildDocksToolbarWindow : Window {
break;
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;
default: NOT_REACHED();
@ -254,10 +254,10 @@ struct BuildDocksToolbarWindow : Window {
GUIPlaceProcDragXY(select_proc, start_tile, end_tile);
break;
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;
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;
default: break;

View File

@ -648,7 +648,7 @@ struct BuildRailToolbarWindow : Window {
break;
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;
case WID_RAT_CONVERT_RAIL:
@ -746,7 +746,7 @@ struct BuildRailToolbarWindow : Window {
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);
}

View File

@ -606,14 +606,13 @@ static CommandCost CheckRoadSlope(Slope tileh, RoadBits *pieces, RoadBits existi
* Build a piece of road.
* @param flags operation to perform
* @param tile tile where to build road
* @param p1 bit 0..3 road pieces to build (RoadBits)
* bit 4..9 road type
* bit 11..12 disallowed directions to toggle
* @param p2 the town that is building the road (0 if not applicable)
* @param text unused
* @param pieces road pieces to build (RoadBits)
* @param rt road type
* @param toggle_drd disallowed directions to toggle
* @param town_id the town that is building the road (0 if not applicable)
* @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;
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
* 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) {
const Town *town = CalcClosestTownFromTile(tile);
p2 = (town != nullptr) ? town->index : INVALID_TOWN;
town_id = (town != nullptr) ? town->index : INVALID_TOWN;
if (company == OWNER_DEITY) {
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 */
if (pieces == ROAD_NONE) return CMD_ERROR;
RoadType rt = Extract<RoadType, 4, 6>(p1);
if (pieces == ROAD_NONE || !IsEnumValid(pieces) || !IsEnumValid(toggle_drd)) return CMD_ERROR;
if (!ValParamRoadType(rt)) return CMD_ERROR;
DisallowedRoadDirections toggle_drd = Extract<DisallowedRoadDirections, 11, 2>(p1);
Slope tileh = GetTileSlope(tile);
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) */
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);
UpdateLevelCrossing(tile, false);
MarkTileDirtyByTile(tile);
@ -870,7 +863,7 @@ do_clear:;
if (HasPowerOnRoad(rt, existing_rt)) {
rt = existing_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;
cost.AddCost(ret);
} else {
@ -895,7 +888,7 @@ do_clear:;
if (existing == ROAD_NONE || rttype == ROAD_TILE_CROSSING) {
SetRoadType(tile, rtt, rt);
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);
break;
@ -927,7 +920,7 @@ do_clear:;
}
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;
}
@ -971,49 +964,40 @@ static bool CanConnectToRoad(TileIndex tile, RoadType rt, DiagDirection dir)
* Build a long piece of road.
* @param flags operation to perform
* @param start_tile start tile of drag (the building cost will appear over this tile)
* @param p1 end tile of drag
* @param p2 various bitstuffed elements
* - 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
* - 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
* - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
* - p2 = (bit 3..8) - road type
* - p2 = (bit 10) - set road direction
* - p2 = (bit 11) - defines two different behaviors for this command:
* - 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
* - 1 = Fail if an obstacle is found. Always take into account bit 0 and 1. This behavior is used for scripts
* @param text unused
* @param end_tile end tile of drag
* @param rt road type
* @param axis direction
* @param drd set road direction
* @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
* @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
* @param is_ai 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
* - true = Fail if an obstacle is found. Always take into account start_half and end_half. This behavior is used for scripts
* @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;
TileIndex end_tile = p1;
if (!ValParamRoadType(rt) || !IsEnumValid(axis) || !IsEnumValid(drd)) return CMD_ERROR;
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 */
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
DiagDirection dir = AxisToDiagDir(axis);
/* Swap direction, also the half-tile drag var (bit 0 and 1) */
if (start_tile > end_tile || (start_tile == end_tile && HasBit(p2, 0))) {
/* Swap direction, also the half-tile drag vars. */
if (start_tile > end_tile || (start_tile == end_tile && start_half)) {
dir = ReverseDiagDir(dir);
p2 ^= 3;
drd = DRD_SOUTHBOUND;
std::swap(start_half, end_half);
if (drd == DRD_NORTHBOUND || drd == DRD_SOUTHBOUND) drd ^= DRD_BOTH;
}
/* On the X-axis, we have to swap the initial bits, so they
* will be interpreted correctly in the GTTS. Furthermore
* 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;
/* No disallowed direction bits have to be toggled */
if (!HasBit(p2, 10)) drd = DRD_NONE;
if ((drd == DRD_NORTHBOUND || drd == DRD_SOUTHBOUND) && (axis == AXIS_Y) == (start_tile == end_tile && start_half == end_half)) drd ^= DRD_BOTH;
CommandCost cost(EXPENSES_CONSTRUCTION);
CommandCost last_error = CMD_ERROR;
@ -1021,7 +1005,6 @@ CommandCost CmdBuildLongRoad(DoCommandFlag flags, TileIndex start_tile, uint32 p
bool had_bridge = false;
bool had_tunnel = false;
bool had_success = false;
bool is_ai = HasBit(p2, 11);
/* Start tile is the first tile clicked by the user. */
for (;;) {
@ -1037,11 +1020,11 @@ CommandCost CmdBuildLongRoad(DoCommandFlag flags, TileIndex start_tile, uint32 p
}
} else {
/* 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 == start_tile && HasBit(p2, 0)) bits &= DiagDirToRoadBits(dir);
if (tile == end_tile && !end_half) bits &= DiagDirToRoadBits(ReverseDiagDir(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()) {
last_error = ret;
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.
* @param flags operation to perform
* @param start_tile start tile of drag
* @param p1 end tile of drag
* @param p2 various bitstuffed elements
* - p2 = (bit 0) - start tile starts in the 2nd half of tile (p2 & 1)
* - p2 = (bit 1) - end tile starts in the 2nd half of tile (p2 & 2)
* - p2 = (bit 2) - direction: 0 = along x-axis, 1 = along y-axis (p2 & 4)
* - p2 = (bit 3 - 8) - road type
* @param text unused
* @param end_tile end tile of drag
* @param rt road type
* @param axis direction
* @param start_half start tile starts in the 2nd half of tile
* @param end_half end tile starts in the 2nd half of tile (p2 & 2)
* @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);
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 */
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
/* Swap start and ending tile, also the half-tile drag var (bit 0 and 1) */
if (start_tile > end_tile || (start_tile == end_tile && HasBit(p2, 0))) {
TileIndex t = start_tile;
start_tile = end_tile;
end_tile = t;
p2 ^= IsInsideMM(p2 & 3, 1, 3) ? 3 : 0;
/* Swap start and ending tile, also the half-tile drag vars. */
if (start_tile > end_tile || (start_tile == end_tile && start_half)) {
std::swap(start_tile, end_tile);
std::swap(start_half, end_half);
}
Money money_available = GetAvailableMoneyForCommand();
@ -1121,8 +1096,8 @@ CommandCost CmdRemoveLongRoad(DoCommandFlag flags, TileIndex start_tile, uint32
for (;;) {
RoadBits bits = AxisToRoadBits(axis);
if (tile == end_tile && !HasBit(p2, 1)) bits &= ROAD_NW | ROAD_NE;
if (tile == start_tile && HasBit(p2, 0)) bits &= ROAD_SE | ROAD_SW;
if (tile == end_tile && !end_half) bits &= ROAD_NW | ROAD_NE;
if (tile == start_tile && start_half) bits &= ROAD_SE | ROAD_SW;
/* try to remove the halves. */
if (bits != 0) {
@ -1132,7 +1107,7 @@ CommandCost CmdRemoveLongRoad(DoCommandFlag flags, TileIndex start_tile, uint32
if (flags & DC_EXEC) {
money_spent += ret.GetCost();
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;
}
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 tile end tile of road conversion drag
* @param p1 start tile of drag
* @param p2 various bitstuffed elements:
* - p2 = (bit 0..5) new roadtype to convert to.
* @param text unused
* @param area_start start tile of drag
* @param to_type new roadtype to convert to.
* @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;
if (!ValParamRoadType(to_type)) return CMD_ERROR;

View File

@ -17,11 +17,11 @@
void DrawRoadDepotSprite(int x, int y, DiagDirection dir, RoadType rt);
void UpdateNearestTownForRoadTiles(bool invalidate);
CommandProc CmdBuildLongRoad;
CommandProc CmdRemoveLongRoad;
CommandProc CmdBuildRoad;
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);
CommandCost CmdRemoveLongRoad(DoCommandFlag flags, TileIndex start_tile, TileIndex end_tile, RoadType rt, Axis axis, bool start_half, bool end_half);
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);
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_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 _one_way_button_clicked;
/**
* Define the values of the RoadFlags
* @see CmdBuildLongRoad
*/
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 Axis _place_road_dir;
static bool _place_road_start_half_x;
static bool _place_road_start_half_y;
static bool _place_road_end_half;
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 (IsNormalRoadTile(tile)) {
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;
switch (this->last_started_action) {
case WID_ROT_ROAD_X:
_place_road_flag = RF_DIR_X;
if (_tile_fract_coords.x >= 8) _place_road_flag |= RF_START_HALFROAD_X;
_place_road_dir = AXIS_X;
_place_road_start_half_x = _tile_fract_coords.x >= 8;
VpStartPlaceSizing(tile, VPM_FIX_Y, DDSP_PLACE_ROAD_X_DIR);
break;
case WID_ROT_ROAD_Y:
_place_road_flag = RF_DIR_Y;
if (_tile_fract_coords.y >= 8) _place_road_flag |= RF_START_HALFROAD_Y;
_place_road_dir = AXIS_Y;
_place_road_start_half_y = _tile_fract_coords.y >= 8;
VpStartPlaceSizing(tile, VPM_FIX_X, DDSP_PLACE_ROAD_Y_DIR);
break;
case WID_ROT_AUTOROAD:
_place_road_flag = RF_NONE;
if (_tile_fract_coords.x >= 8) _place_road_flag |= RF_START_HALFROAD_X;
if (_tile_fract_coords.y >= 8) _place_road_flag |= RF_START_HALFROAD_Y;
_place_road_dir = INVALID_AXIS;
_place_road_start_half_x = _tile_fract_coords.x >= 8;
_place_road_start_half_y = _tile_fract_coords.y >= 8;
VpStartPlaceSizing(tile, VPM_X_OR_Y, DDSP_PLACE_AUTOROAD);
break;
@ -564,7 +552,7 @@ struct BuildRoadToolbarWindow : Window {
case WID_ROT_BUILD_TUNNEL:
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;
case WID_ROT_CONVERT_ROAD:
@ -603,30 +591,26 @@ struct BuildRoadToolbarWindow : Window {
* bits and if needed we set them again. */
switch (select_proc) {
case DDSP_PLACE_ROAD_X_DIR:
_place_road_flag &= ~RF_END_HALFROAD_X;
if (pt.x & 8) _place_road_flag |= RF_END_HALFROAD_X;
_place_road_end_half = pt.x & 8;
break;
case DDSP_PLACE_ROAD_Y_DIR:
_place_road_flag &= ~RF_END_HALFROAD_Y;
if (pt.y & 8) _place_road_flag |= RF_END_HALFROAD_Y;
_place_road_end_half = pt.y & 8;
break;
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
* direction of the road */
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) ))) {
/* Set dir = X */
_place_road_flag &= ~RF_DIR_Y;
_place_road_dir = AXIS_X;
_place_road_end_half = pt.x & 8;
} else {
/* Set dir = Y */
_place_road_flag |= RF_DIR_Y;
_place_road_dir = AXIS_Y;
_place_road_end_half = pt.y & 8;
}
break;
@ -654,25 +638,18 @@ struct BuildRoadToolbarWindow : Window {
case DDSP_PLACE_ROAD_X_DIR:
case DDSP_PLACE_ROAD_Y_DIR:
case DDSP_PLACE_AUTOROAD:
/* Flag description:
* 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));
case DDSP_PLACE_AUTOROAD: {
bool start_half = _place_road_dir == AXIS_Y ? _place_road_start_half_y : _place_road_start_half_y;
if (_remove_button_clicked) {
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 {
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;
}
case DDSP_BUILD_BUSSTOP:
case DDSP_REMOVE_BUSSTOP:
@ -699,7 +676,7 @@ struct BuildRoadToolbarWindow : Window {
break;
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;
}
}
@ -707,7 +684,7 @@ struct BuildRoadToolbarWindow : Window {
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);
}

View File

@ -15,6 +15,7 @@
#include "rail_type.h"
#include "road_func.h"
#include "tile_map.h"
#include "road_type.h"
/** 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);
}
/** 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
* @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.
*/
enum RoadType {
enum RoadType : byte {
ROADTYPE_BEGIN = 0, ///< Used for iterations
ROADTYPE_ROAD = 0, ///< Basic road type
ROADTYPE_TRAM = 1, ///< Trams
@ -47,7 +47,7 @@ DECLARE_ENUM_AS_BIT_SET(RoadTypes)
* This enumeration defines the possible road parts which
* can be build on a tile.
*/
enum RoadBits {
enum RoadBits : byte {
ROAD_NONE = 0U, ///< No road-part is build
ROAD_NW = 1U, ///< North-west part
ROAD_SW = 2U, ///< South-west part
@ -68,4 +68,16 @@ enum RoadBits {
DECLARE_ENUM_AS_BIT_SET(RoadBits)
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 */

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. */
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();
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, ScriptObject::GetCompany() != OWNER_DEITY || vehicle_type == ScriptVehicle::VT_ROAD);
uint type = 0;
switch (vehicle_type) {
case ScriptVehicle::VT_ROAD:
type |= (TRANSPORT_ROAD << 15);
type |= (ScriptRoad::GetCurrentRoadType() << 8);
break;
ScriptObject::SetCallbackVariable(0, start);
ScriptObject::SetCallbackVariable(1, end);
return ScriptObject::Command<CMD_BUILD_BRIDGE>::Do(&::_DoCommandReturnBuildBridge1, end, start, TRANSPORT_ROAD, bridge_id, ScriptRoad::GetCurrentRoadType());
case ScriptVehicle::VT_RAIL:
type |= (TRANSPORT_RAIL << 15);
type |= (ScriptRail::GetCurrentRailType() << 8);
break;
return ScriptObject::Command<CMD_BUILD_BRIDGE>::Do(end, start, TRANSPORT_RAIL, bridge_id, ScriptRail::GetCurrentRailType());
case ScriptVehicle::VT_WATER:
type |= (TRANSPORT_WATER << 15);
break;
return ScriptObject::Command<CMD_BUILD_BRIDGE>::Do(end, start, TRANSPORT_WATER, bridge_id, 0);
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()
@ -115,7 +102,7 @@ static void _DoCommandReturnBuildBridge1(class ScriptInstance *instance)
DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start);
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()
@ -127,7 +114,7 @@ static void _DoCommandReturnBuildBridge1(class ScriptInstance *instance)
DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start);
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)

View File

@ -108,7 +108,7 @@
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
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)
@ -116,7 +116,7 @@
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
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)

View File

@ -129,7 +129,7 @@
EnforcePrecondition(false, ::IsValidTile(end_tile));
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(). */
@ -495,7 +495,8 @@ static bool NeighbourHasReachableRoad(::RoadType rt, TileIndex start_tile, DiagD
EnforcePrecondition(false, !one_way || RoadTypeIsRoad(ScriptObject::GetRoadType()));
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)
@ -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, 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)
@ -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, 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)

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, 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) {
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()
@ -115,7 +106,7 @@ static void _DoCommandReturnBuildTunnel1(class ScriptInstance *instance)
DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start);
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()
@ -127,7 +118,7 @@ static void _DoCommandReturnBuildTunnel1(class ScriptInstance *instance)
DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start);
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)

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.
* This is to make sure that we can build a road here later. */
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()) {
return false;
}
@ -1112,7 +1112,7 @@ static bool GrowTownWithExtraHouse(Town *t, TileIndex tile)
static bool GrowTownWithRoad(const Town *t, TileIndex tile, RoadBits rcmd)
{
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;
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 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? */
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()) {
Command<CMD_BUILD_BRIDGE>::Do(DC_EXEC | CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_BRIDGE>()), tile, bridge_tile, bridge_type | rt << 8 | TRANSPORT_ROAD << 15, {});
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, TRANSPORT_ROAD, bridge_type, rt);
_grow_town_result = GROWTH_SUCCEED;
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. */
RoadType rt = GetTownRoadType(t);
if (Command<CMD_BUILD_TUNNEL>::Do(CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_TUNNEL>()), tile, rt | (TRANSPORT_ROAD << 8), 0, {}).Succeeded()) {
Command<CMD_BUILD_TUNNEL>::Do(DC_EXEC | CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_TUNNEL>()), tile, rt | (TRANSPORT_ROAD << 8), 0, {});
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, TRANSPORT_ROAD, rt);
_grow_town_result = GROWTH_SUCCEED;
return true;
}
@ -1739,7 +1739,7 @@ static bool GrowTown(Town *t)
if (!IsTileType(tile, MP_HOUSE) && IsTileFlat(tile)) {
if (Command<CMD_LANDSCAPE_CLEAR>::Do(DC_AUTO | DC_NO_WATER, tile, 0, 0, {}).Succeeded()) {
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();
return true;
}

View File

@ -16,7 +16,7 @@
typedef uint16 UnitID;
/** Available types of transport */
enum TransportType {
enum TransportType : byte {
/* These constants are for now linked to the representation of bridges
* and tunnels, so they can be used by GetTileTrackStatus_TunnelBridge.
* 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
* @param flags type of operation
* @param end_tile end tile
* @param p1 packed start tile coords (~ dx)
* @param p2 various bitstuffed elements
* - p2 = (bit 0- 7) - bridge type (hi bh)
* - p2 = (bit 8-13) - rail type or road types.
* - p2 = (bit 15-16) - transport type.
* @param text unused
* @param tile_end end tile
* @param tile_start start tile
* @param transport_type transport type.
* @param bridge_type bridge type (hi bh)
* @param road_rail_type rail type or road types.
* @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;
RailType railtype = INVALID_RAILTYPE;
RoadType roadtype = INVALID_ROADTYPE;
/* unpack parameters */
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);
if (!IsValidTile(tile_start)) return_cmd_error(STR_ERROR_BRIDGE_THROUGH_MAP_BORDER);
/* type of bridge */
switch (transport_type) {
case TRANSPORT_ROAD:
roadtype = Extract<RoadType, 8, 6>(p2);
roadtype = (RoadType)road_rail_type;
if (!ValParamRoadType(roadtype)) return CMD_ERROR;
break;
case TRANSPORT_RAIL:
railtype = Extract<RailType, 8, 6>(p2);
railtype = (RailType)road_rail_type;
if (!ValParamRailtype(railtype)) return CMD_ERROR;
break;
@ -293,8 +286,6 @@ CommandCost CmdBuildBridge(DoCommandFlag flags, TileIndex end_tile, uint32 p1, u
/* Airports don't have bridges. */
return CMD_ERROR;
}
TileIndex tile_start = p1;
TileIndex tile_end = end_tile;
if (company == OWNER_DEITY) {
if (transport_type != TRANSPORT_ROAD) return CMD_ERROR;
@ -627,28 +618,25 @@ CommandCost CmdBuildBridge(DoCommandFlag flags, TileIndex end_tile, uint32 p1, u
* Build Tunnel.
* @param flags type of operation
* @param start_tile start tile of tunnel
* @param p1 bit 0-5 railtype or roadtype
* bit 8-9 transport type
* @param p2 unused
* @param text unused
* @param transport_type transport type
* @param road_rail_type railtype or roadtype
* @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;
TransportType transport_type = Extract<TransportType, 8, 2>(p1);
RailType railtype = INVALID_RAILTYPE;
RoadType roadtype = INVALID_ROADTYPE;
_build_tunnel_endtile = 0;
switch (transport_type) {
case TRANSPORT_RAIL:
railtype = Extract<RailType, 0, 6>(p1);
railtype = (RailType)road_rail_type;
if (!ValParamRailtype(railtype)) return CMD_ERROR;
break;
case TRANSPORT_ROAD:
roadtype = Extract<RoadType, 0, 6>(p1);
roadtype = (RoadType)road_rail_type;
if (!ValParamRoadType(roadtype)) return CMD_ERROR;
break;

View File

@ -11,9 +11,11 @@
#define TUNNELBRIDGE_CMD_H
#include "command_type.h"
#include "transport_type.h"
#include "bridge.h"
CommandProc CmdBuildBridge;
CommandProc CmdBuildTunnel;
CommandCost CmdBuildBridge(DoCommandFlag flags, TileIndex tile_end, TileIndex tile_start, TransportType transport_type, BridgeType bridge_type, byte road_rail_type);
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_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.
* @param flags type of operation
* @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
*/
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));
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.
* @param flags type of operation
* @param tile end tile of stretch-dragging
* @param p1 start tile of stretch-dragging
* @param p2 various bitstuffed data
* bits 0-1: waterclass to build. sea and river can only be built in scenario editor
* bit 2: Whether to use the Orthogonal (0) or Diagonal (1) iterator.
* @param text unused
* @param start_tile start tile of stretch-dragging
* @param wc 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.
* @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 (p1 >= MapSize() || wc == WATER_CLASS_INVALID) return CMD_ERROR;
if (start_tile >= MapSize() || !IsEnumValid(wc)) return CMD_ERROR;
/* Outside of the editor you can only build canals, not oceans */
if (wc != WATER_CLASS_CANAL && _game_mode != GM_EDITOR) return CMD_ERROR;
/* Outside the editor you can only drag canals, and not areas */
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;
}
CommandCost cost(EXPENSES_CONSTRUCTION);
std::unique_ptr<TileIterator> iter;
if (HasBit(p2, 2)) {
iter = std::make_unique<DiagonalTileIterator>(tile, (TileIndex)p1);
if (diagonal) {
iter = std::make_unique<DiagonalTileIterator>(tile, start_tile);
} else {
iter = std::make_unique<OrthogonalTileIterator>(tile, (TileIndex)p1);
iter = std::make_unique<OrthogonalTileIterator>(tile, start_tile);
}
for (; *iter != INVALID_TILE; ++(*iter)) {

View File

@ -11,10 +11,11 @@
#define WATER_CMD_H
#include "command_type.h"
#include "water_map.h"
CommandCost CmdBuildShipDepot(DoCommandFlag flags, TileIndex tile, Axis axis);
CommandProc CmdBuildCanal;
CommandProc CmdBuildLock;
CommandCost CmdBuildCanal(DoCommandFlag flags, TileIndex tile, TileIndex start_tile, WaterClass wc, bool diagonal);
CommandCost CmdBuildLock(DoCommandFlag flags, TileIndex tile);
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)

View File

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