diff --git a/src/bridge_gui.cpp b/src/bridge_gui.cpp index 38ff698eb6..77261932b3 100644 --- a/src/bridge_gui.cpp +++ b/src/bridge_gui.cpp @@ -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::Args>(data); - - TransportType transport_type = Extract(p2); + auto [tile, tile_start, transport_type, bridge_type, road_rail_type] = EndianBufferReader::ToValue::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::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(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(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::Post(STR_ERROR_CAN_T_BUILD_BRIDGE_HERE, CcBuildBridge, end, start, type | last_bridge_type, {}); + Command::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::Do(CommandFlagsToDCFlags(GetCommandFlags()) | DC_QUERY_COST, end, start, type, {}); + CommandCost ret = Command::Do(CommandFlagsToDCFlags(GetCommandFlags()) | 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); diff --git a/src/dock_gui.cpp b/src/dock_gui.cpp index cdcb4ea84a..d8cd7c5d46 100644 --- a/src/dock_gui.cpp +++ b/src/dock_gui.cpp @@ -196,7 +196,7 @@ struct BuildDocksToolbarWindow : Window { break; case WID_DT_LOCK: // Build lock button - Command::Post(STR_ERROR_CAN_T_BUILD_LOCKS, CcBuildDocks, tile, 0, 0, {}); + Command::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::Post(STR_ERROR_CAN_T_BUILD_AQUEDUCT_HERE, CcBuildBridge, tile, GetOtherAqueductEnd(tile), TRANSPORT_WATER << 15, {}); + Command::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::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::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::Post(STR_ERROR_CAN_T_PLACE_RIVERS, CcPlaySound_CONSTRUCTION_WATER, end_tile, start_tile, WATER_CLASS_RIVER | (_ctrl_pressed ? 1 << 2 : 0), {}); + Command::Post(STR_ERROR_CAN_T_PLACE_RIVERS, CcPlaySound_CONSTRUCTION_WATER, end_tile, start_tile, WATER_CLASS_RIVER, _ctrl_pressed); break; default: break; diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index a8e8b68b42..bac59d7474 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -648,7 +648,7 @@ struct BuildRailToolbarWindow : Window { break; case WID_RAT_BUILD_TUNNEL: - Command::Post(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE, CcBuildRailTunnel, tile, _cur_railtype | (TRANSPORT_RAIL << 8), 0, {}); + Command::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::Do(DC_AUTO, tile, _cur_railtype | (TRANSPORT_RAIL << 8), 0, {}); + Command::Do(DC_AUTO, tile, TRANSPORT_RAIL, _cur_railtype); VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile); } diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index ece49676be..e160a2b842 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -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(p1); - /* do not allow building 'zero' road bits, code wouldn't handle it */ - if (pieces == ROAD_NONE) return CMD_ERROR; - - RoadType rt = Extract(p1); + if (pieces == ROAD_NONE || !IsEnumValid(pieces) || !IsEnumValid(toggle_drd)) return CMD_ERROR; if (!ValParamRoadType(rt)) return CMD_ERROR; - DisallowedRoadDirections toggle_drd = Extract(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::Do(flags, tile, tile, rt, {}); + CommandCost ret = Command::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(p2); - if (!ValParamRoadType(rt)) return CMD_ERROR; - - Axis axis = Extract(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::Do(flags, tile, drd << 11 | rt << 4 | bits, 0, {}); + CommandCost ret = Command::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(p2); - if (!ValParamRoadType(rt)) return CMD_ERROR; - - Axis axis = Extract(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::Do(flags & ~DC_EXEC, start_tile, end_tile, p2, {}).GetCost(); + _additional_cash_required = Command::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(p2); - - TileIndex area_start = p1; TileIndex area_end = tile; if (!ValParamRoadType(to_type)) return CMD_ERROR; diff --git a/src/road_cmd.h b/src/road_cmd.h index 0cab1252f0..3c142bdfed 100644 --- a/src/road_cmd.h +++ b/src/road_cmd.h @@ -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. diff --git a/src/road_gui.cpp b/src/road_gui.cpp index beba949e4c..1aa0b59ac4 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -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::Post(tile, _cur_roadtype << 4 | DiagDirToRoadBits(ReverseDiagDir(direction)), 0, {}); + Command::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::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::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::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::Post(rti->strings.err_convert_road, CcPlaySound_CONSTRUCTION_OTHER, end_tile, start_tile, _cur_roadtype, {}); + Command::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::Do(DC_AUTO, tile, _cur_roadtype | (TRANSPORT_ROAD << 8), 0, {}); + Command::Do(DC_AUTO, tile, TRANSPORT_ROAD, _cur_roadtype); VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile); } diff --git a/src/road_map.h b/src/road_map.h index 22d0fa54d3..4cb9125ea6 100644 --- a/src/road_map.h +++ b/src/road_map.h @@ -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 : MakeEnumPropsT {}; - /** * Gets the disallowed directions * @param t the tile to get the directions from diff --git a/src/road_type.h b/src/road_type.h index 969b141ba2..a792db7ba5 100644 --- a/src/road_type.h +++ b/src/road_type.h @@ -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 : MakeEnumPropsT {}; +/** 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 : MakeEnumPropsT {}; + #endif /* ROAD_TYPE_H */ diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 0b8d9deff8..c1e510273a 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -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 cur_company(_current_company, c, FILE_LINE); - CommandCost ret = Command::Do(DC_NO_WATER, t, rt << 4 | r, 0, {}); + CommandCost ret = Command::Do(DC_NO_WATER, t, r, rt, DRD_NONE, 0); cur_company.Restore(); return ret.Succeeded(); diff --git a/src/script/api/script_bridge.cpp b/src/script/api/script_bridge.cpp index dc357c2552..fbea9fb127 100644 --- a/src/script/api/script_bridge.cpp +++ b/src/script/api/script_bridge.cpp @@ -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::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::Do(end, start, TRANSPORT_RAIL, bridge_id, ScriptRail::GetCurrentRailType()); case ScriptVehicle::VT_WATER: - type |= (TRANSPORT_WATER << 15); - break; + return ScriptObject::Command::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::Do(end, start, type | bridge_id, {}); - } - - ScriptObject::SetCallbackVariable(0, start); - ScriptObject::SetCallbackVariable(1, end); - return ScriptObject::Command::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::Do(&::_DoCommandReturnBuildBridge2, start + ::TileOffsByDiagDir(dir_1), ::DiagDirToRoadBits(dir_2) | (ScriptRoad::GetCurrentRoadType() << 4), 0, {}); + return ScriptObject::Command::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::Do(end + ::TileOffsByDiagDir(dir_2), ::DiagDirToRoadBits(dir_1) | (ScriptRoad::GetCurrentRoadType() << 4), 0, {}); + return ScriptObject::Command::Do(end + ::TileOffsByDiagDir(dir_2), ::DiagDirToRoadBits(dir_1), (::RoadType)ScriptRoad::GetCurrentRoadType(), DRD_NONE, 0); } /* static */ bool ScriptBridge::RemoveBridge(TileIndex tile) diff --git a/src/script/api/script_marine.cpp b/src/script/api/script_marine.cpp index 8093233948..059157e276 100644 --- a/src/script/api/script_marine.cpp +++ b/src/script/api/script_marine.cpp @@ -108,7 +108,7 @@ EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY); EnforcePrecondition(false, ::IsValidTile(tile)); - return ScriptObject::Command::Do(tile, 0, 0, {}); + return ScriptObject::Command::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::Do(tile, tile, WATER_CLASS_CANAL, {}); + return ScriptObject::Command::Do(tile, tile, WATER_CLASS_CANAL, false); } /* static */ bool ScriptMarine::RemoveWaterDepot(TileIndex tile) diff --git a/src/script/api/script_road.cpp b/src/script/api/script_road.cpp index c629396b70..297a8f56c1 100644 --- a/src/script/api/script_road.cpp +++ b/src/script/api/script_road.cpp @@ -129,7 +129,7 @@ EnforcePrecondition(false, ::IsValidTile(end_tile)); EnforcePrecondition(false, IsRoadTypeAvailable(road_type)); - return ScriptObject::Command::Do(start_tile, end_tile, (::RoadType)road_type, {}); + return ScriptObject::Command::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::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::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::Do(start, end, (::TileY(start) != ::TileY(end) ? 4 : 0) | (start < end ? 1 : 2) | (ScriptObject::GetRoadType() << 3), {}); + return ScriptObject::Command::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::Do(start, end, (::TileY(start) != ::TileY(end) ? 4 : 0) | (start < end ? 2 : 1) | (ScriptObject::GetRoadType() << 3), {}); + return ScriptObject::Command::Do(start, end, ScriptObject::GetRoadType(), ::TileY(start) != ::TileY(end) ? AXIS_Y : AXIS_X, start >= end, start < end); } /* static */ bool ScriptRoad::RemoveRoadDepot(TileIndex tile) diff --git a/src/script/api/script_tunnel.cpp b/src/script/api/script_tunnel.cpp index ea9cbc5186..8529f908db 100644 --- a/src/script/api/script_tunnel.cpp +++ b/src/script/api/script_tunnel.cpp @@ -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::Do(start, type, 0, {}); + /* For rail we do nothing special */ + return ScriptObject::Command::Do(start, TRANSPORT_RAIL, ScriptRail::GetCurrentRailType()); + } else { + ScriptObject::SetCallbackVariable(0, start); + return ScriptObject::Command::Do(&::_DoCommandReturnBuildTunnel1, start, TRANSPORT_ROAD, ScriptRoad::GetCurrentRoadType()); } - - ScriptObject::SetCallbackVariable(0, start); - return ScriptObject::Command::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::Do(&::_DoCommandReturnBuildTunnel2, start + ::TileOffsByDiagDir(dir_1), ::DiagDirToRoadBits(dir_2) | (ScriptObject::GetRoadType() << 4), 0, {}); + return ScriptObject::Command::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::Do(end + ::TileOffsByDiagDir(dir_2), ::DiagDirToRoadBits(dir_1) | (ScriptObject::GetRoadType() << 4), 0, {}); + return ScriptObject::Command::Do(end + ::TileOffsByDiagDir(dir_2), ::DiagDirToRoadBits(dir_1), ScriptRoad::GetRoadType(), DRD_NONE, 0); } /* static */ bool ScriptTunnel::RemoveTunnel(TileIndex tile) diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 8e87739d3d..7a564d48ab 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -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::Do(DC_AUTO | DC_NO_WATER, tile, ((dir == DIAGDIR_NW || dir == DIAGDIR_SE) ? ROAD_Y : ROAD_X) | (rt << 4), 0, {}).Failed() && + if (Command::Do(DC_AUTO | DC_NO_WATER, tile, (dir == DIAGDIR_NW || dir == DIAGDIR_SE) ? ROAD_Y : ROAD_X, rt, DRD_NONE, 0).Failed() && Command::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::Do(DC_EXEC | DC_AUTO | DC_NO_WATER, tile, rcmd | (rt << 4), t->index, {}).Succeeded()) { + if (Command::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::Do(DC_AUTO | DC_NO_WATER, next_tile, rcmd | (rt << 4), t->index, {}).Succeeded(); + return Command::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::Do(CommandFlagsToDCFlags(GetCommandFlags()), tile, bridge_tile, bridge_type | rt << 8 | TRANSPORT_ROAD << 15, {}).Succeeded()) { - Command::Do(DC_EXEC | CommandFlagsToDCFlags(GetCommandFlags()), tile, bridge_tile, bridge_type | rt << 8 | TRANSPORT_ROAD << 15, {}); + if (Command::Do(CommandFlagsToDCFlags(GetCommandFlags()), tile, bridge_tile, TRANSPORT_ROAD, bridge_type, rt).Succeeded()) { + Command::Do(DC_EXEC | CommandFlagsToDCFlags(GetCommandFlags()), 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::Do(CommandFlagsToDCFlags(GetCommandFlags()), tile, rt | (TRANSPORT_ROAD << 8), 0, {}).Succeeded()) { - Command::Do(DC_EXEC | CommandFlagsToDCFlags(GetCommandFlags()), tile, rt | (TRANSPORT_ROAD << 8), 0, {}); + if (Command::Do(CommandFlagsToDCFlags(GetCommandFlags()), tile, TRANSPORT_ROAD, rt).Succeeded()) { + Command::Do(DC_EXEC | CommandFlagsToDCFlags(GetCommandFlags()), 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::Do(DC_AUTO | DC_NO_WATER, tile, 0, 0, {}).Succeeded()) { RoadType rt = GetTownRoadType(t); - Command::Do(DC_EXEC | DC_AUTO, tile, GenRandomRoadBits() | (rt << 4), t->index, {}); + Command::Do(DC_EXEC | DC_AUTO, tile, GenRandomRoadBits(), rt, DRD_NONE, t->index); cur_company.Restore(); return true; } diff --git a/src/transport_type.h b/src/transport_type.h index b244e48b31..172649aba5 100644 --- a/src/transport_type.h +++ b/src/transport_type.h @@ -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 diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 85c611ae5d..14ff79854d 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -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(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(p2); + roadtype = (RoadType)road_rail_type; if (!ValParamRoadType(roadtype)) return CMD_ERROR; break; case TRANSPORT_RAIL: - railtype = Extract(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(p1); RailType railtype = INVALID_RAILTYPE; RoadType roadtype = INVALID_ROADTYPE; _build_tunnel_endtile = 0; switch (transport_type) { case TRANSPORT_RAIL: - railtype = Extract(p1); + railtype = (RailType)road_rail_type; if (!ValParamRailtype(railtype)) return CMD_ERROR; break; case TRANSPORT_ROAD: - roadtype = Extract(p1); + roadtype = (RoadType)road_rail_type; if (!ValParamRoadType(roadtype)) return CMD_ERROR; break; diff --git a/src/tunnelbridge_cmd.h b/src/tunnelbridge_cmd.h index 6c78db48b1..ae924cf69d 100644 --- a/src/tunnelbridge_cmd.h +++ b/src/tunnelbridge_cmd.h @@ -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) diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index 3c96f79ad8..ee911312ef 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -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(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 iter; - if (HasBit(p2, 2)) { - iter = std::make_unique(tile, (TileIndex)p1); + if (diagonal) { + iter = std::make_unique(tile, start_tile); } else { - iter = std::make_unique(tile, (TileIndex)p1); + iter = std::make_unique(tile, start_tile); } for (; *iter != INVALID_TILE; ++(*iter)) { diff --git a/src/water_cmd.h b/src/water_cmd.h index 4d3375aa39..1c56790327 100644 --- a/src/water_cmd.h +++ b/src/water_cmd.h @@ -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) diff --git a/src/water_map.h b/src/water_map.h index 22e54e967f..793d07c8a2 100644 --- a/src/water_map.h +++ b/src/water_map.h @@ -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.