MCPcopy Create free account
hub / github.com/OpenTTD/OpenTTD / CmdBuildLongRoad

Function CmdBuildLongRoad

src/road_cmd.cpp:966–1050  ·  view source on GitHub ↗

* Build a long piece of road. * @param flags operation to perform * @param end_tile end tile of drag * @param start_tile start 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

Source from the content-addressed store, hash-verified

964 * @return the cost of this operation or an error
965 */
966CommandCost CmdBuildLongRoad(DoCommandFlags flags, TileIndex end_tile, TileIndex start_tile, RoadType rt, Axis axis, DisallowedRoadDirections drd, bool start_half, bool end_half, bool is_ai)
967{
968 if (start_tile >= Map::Size()) return CMD_ERROR;
969
970 if (!ValParamRoadType(rt) || !IsValidAxis(axis) || !IsValidDisallowedRoadDirections(drd)) return CMD_ERROR;
971
972 /* Only drag in X or Y direction dictated by the direction variable */
973 if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis
974 if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis
975
976 DiagDirection dir = AxisToDiagDir(axis);
977
978 /* Swap direction, also the half-tile drag vars. */
979 if (start_tile > end_tile || (start_tile == end_tile && start_half)) {
980 dir = ReverseDiagDir(dir);
981 start_half = !start_half;
982 end_half = !end_half;
983 if (drd == DRD_NORTHBOUND || drd == DRD_SOUTHBOUND) drd ^= DRD_BOTH;
984 }
985
986 /* On the X-axis, we have to swap the initial bits, so they
987 * will be interpreted correctly in the GTTS. Furthermore
988 * when you just 'click' on one tile to build them. */
989 if ((drd == DRD_NORTHBOUND || drd == DRD_SOUTHBOUND) && (axis == AXIS_Y) == (start_tile == end_tile && start_half == end_half)) drd ^= DRD_BOTH;
990
991 CommandCost cost(EXPENSES_CONSTRUCTION);
992 CommandCost last_error = CMD_ERROR;
993 TileIndex tile = start_tile;
994 bool had_bridge = false;
995 bool had_tunnel = false;
996 bool had_success = false;
997
998 /* Start tile is the first tile clicked by the user. */
999 for (;;) {
1000 RoadBits bits = AxisToRoadBits(axis);
1001
1002 /* Determine which road parts should be built. */
1003 if (!is_ai && start_tile != end_tile) {
1004 /* Only build the first and last roadbit if they can connect to something. */
1005 if (tile == end_tile && !CanConnectToRoad(tile, rt, dir)) {
1006 bits = DiagDirToRoadBits(ReverseDiagDir(dir));
1007 } else if (tile == start_tile && !CanConnectToRoad(tile, rt, ReverseDiagDir(dir))) {
1008 bits = DiagDirToRoadBits(dir);
1009 }
1010 } else {
1011 /* Road parts only have to be built at the start tile or at the end tile. */
1012 if (tile == end_tile && !end_half) bits &= DiagDirToRoadBits(ReverseDiagDir(dir));
1013 if (tile == start_tile && start_half) bits &= DiagDirToRoadBits(dir);
1014 }
1015
1016 CommandCost ret = Command<CMD_BUILD_ROAD>::Do(flags, tile, bits, rt, drd, TownID::Invalid());
1017 if (!is_ai && ret.GetErrorMessage() == STR_ERROR_ALREADY_BUILT) had_success = true;
1018 if (ret.Failed()) {
1019 last_error = std::move(ret);
1020 if (last_error.GetErrorMessage() != STR_ERROR_ALREADY_BUILT) {
1021 if (is_ai) return last_error;
1022 if (had_success) break; // Keep going if we haven't constructed any road yet, skipping the start of the drag
1023 }

Callers

nothing calls this directly

Calls 15

ValParamRoadTypeFunction · 0.85
IsValidAxisFunction · 0.85
TileYFunction · 0.85
TileXFunction · 0.85
AxisToDiagDirFunction · 0.85
ReverseDiagDirFunction · 0.85
AxisToRoadBitsFunction · 0.85
CanConnectToRoadFunction · 0.85
DiagDirToRoadBitsFunction · 0.85
InvalidFunction · 0.85
IsTileTypeFunction · 0.85

Tested by

no test coverage detected