* Remove 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 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 */
| 1061 | * @return the cost of this operation or an error |
| 1062 | */ |
| 1063 | std::tuple<CommandCost, Money> CmdRemoveLongRoad(DoCommandFlags flags, TileIndex end_tile, TileIndex start_tile, RoadType rt, Axis axis, bool start_half, bool end_half) |
| 1064 | { |
| 1065 | CommandCost cost(EXPENSES_CONSTRUCTION); |
| 1066 | |
| 1067 | if (start_tile >= Map::Size()) return { CMD_ERROR, 0 }; |
| 1068 | if (!ValParamRoadType(rt) || !IsValidAxis(axis)) return { CMD_ERROR, 0 }; |
| 1069 | |
| 1070 | /* Only drag in X or Y direction dictated by the direction variable */ |
| 1071 | if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return { CMD_ERROR, 0 }; // x-axis |
| 1072 | if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return { CMD_ERROR, 0 }; // y-axis |
| 1073 | |
| 1074 | /* Swap start and ending tile, also the half-tile drag vars. */ |
| 1075 | if (start_tile > end_tile || (start_tile == end_tile && start_half)) { |
| 1076 | std::swap(start_tile, end_tile); |
| 1077 | std::swap(start_half, end_half); |
| 1078 | } |
| 1079 | |
| 1080 | Money money_available = GetAvailableMoneyForCommand(); |
| 1081 | Money money_spent = 0; |
| 1082 | TileIndex tile = start_tile; |
| 1083 | CommandCost last_error = CMD_ERROR; |
| 1084 | bool had_success = false; |
| 1085 | /* Start tile is the small number. */ |
| 1086 | for (;;) { |
| 1087 | RoadBits bits = AxisToRoadBits(axis); |
| 1088 | |
| 1089 | if (tile == end_tile && !end_half) bits &= ROAD_NW | ROAD_NE; |
| 1090 | if (tile == start_tile && start_half) bits &= ROAD_SE | ROAD_SW; |
| 1091 | |
| 1092 | /* try to remove the halves. */ |
| 1093 | if (bits != 0) { |
| 1094 | RoadTramType rtt = GetRoadTramType(rt); |
| 1095 | CommandCost ret = RemoveRoad(tile, DoCommandFlags{flags}.Reset(DoCommandFlag::Execute), bits, rtt, true); |
| 1096 | if (ret.Succeeded()) { |
| 1097 | if (flags.Test(DoCommandFlag::Execute)) { |
| 1098 | money_spent += ret.GetCost(); |
| 1099 | if (money_spent > 0 && money_spent > money_available) { |
| 1100 | return { cost, std::get<0>(Command<CMD_REMOVE_LONG_ROAD>::Do(DoCommandFlags{flags}.Reset(DoCommandFlag::Execute), end_tile, start_tile, rt, axis, start_half, end_half)).GetCost() }; |
| 1101 | } |
| 1102 | RemoveRoad(tile, flags, bits, rtt, false); |
| 1103 | } |
| 1104 | cost.AddCost(ret.GetCost()); |
| 1105 | had_success = true; |
| 1106 | } else { |
| 1107 | /* Some errors are more equal than others. */ |
| 1108 | switch (last_error.GetErrorMessage()) { |
| 1109 | case STR_ERROR_OWNED_BY: |
| 1110 | case STR_ERROR_LOCAL_AUTHORITY_REFUSES_TO_ALLOW_THIS: |
| 1111 | break; |
| 1112 | default: |
| 1113 | last_error = std::move(ret); |
| 1114 | } |
| 1115 | } |
| 1116 | } |
| 1117 | |
| 1118 | if (tile == end_tile) break; |
| 1119 | |
| 1120 | tile += TileOffsByAxis(axis); |
nothing calls this directly
no test coverage detected