* Build a road waypoint on an existing road. * @param flags type of operation. * @param start_tile northern most tile where waypoint will be built. * @param axis orientation (Axis). * @param width width of waypoint. * @param height height of waypoint. * @param spec_class custom road stop class. * @param spec_index custom road stop id. * @param station_to_join station ID to join (NEW_STATIO
| 340 | * @return the cost of this operation or an error. |
| 341 | */ |
| 342 | CommandCost CmdBuildRoadWaypoint(DoCommandFlags flags, TileIndex start_tile, Axis axis, uint8_t width, uint8_t height, RoadStopClassID spec_class, uint16_t spec_index, StationID station_to_join, bool adjacent) |
| 343 | { |
| 344 | if (!IsValidAxis(axis)) return CMD_ERROR; |
| 345 | /* Check if the given station class is valid */ |
| 346 | if (static_cast<uint>(spec_class) >= RoadStopClass::GetClassCount()) return CMD_ERROR; |
| 347 | const RoadStopClass *cls = RoadStopClass::Get(spec_class); |
| 348 | if (!IsWaypointClass(*cls)) return CMD_ERROR; |
| 349 | if (spec_index >= cls->GetSpecCount()) return CMD_ERROR; |
| 350 | |
| 351 | const RoadStopSpec *roadstopspec = RoadStopClass::Get(spec_class)->GetSpec(spec_index); |
| 352 | |
| 353 | /* The number of parts to build */ |
| 354 | uint8_t count = axis == AXIS_X ? height : width; |
| 355 | |
| 356 | if ((axis == AXIS_X ? width : height) != 1) return CMD_ERROR; |
| 357 | if (count == 0 || count > _settings_game.station.station_spread) return CMD_ERROR; |
| 358 | |
| 359 | bool reuse = (station_to_join != NEW_STATION); |
| 360 | if (!reuse) station_to_join = StationID::Invalid(); |
| 361 | bool distant_join = (station_to_join != StationID::Invalid()); |
| 362 | |
| 363 | if (distant_join && (!_settings_game.station.distant_join_stations || !Waypoint::IsValidID(station_to_join))) return CMD_ERROR; |
| 364 | |
| 365 | TileArea roadstop_area(start_tile, width, height); |
| 366 | |
| 367 | /* Total road stop cost. */ |
| 368 | Money unit_cost; |
| 369 | if (roadstopspec != nullptr) { |
| 370 | unit_cost = roadstopspec->GetBuildCost(PR_BUILD_STATION_TRUCK); |
| 371 | } else { |
| 372 | unit_cost = _price[PR_BUILD_STATION_TRUCK]; |
| 373 | } |
| 374 | StationID est = StationID::Invalid(); |
| 375 | CommandCost cost = CalculateRoadStopCost(roadstop_area, flags, true, StationType::RoadWaypoint, roadstopspec, axis, AxisToDiagDir(axis), &est, INVALID_ROADTYPE, unit_cost); |
| 376 | if (cost.Failed()) return cost; |
| 377 | |
| 378 | Waypoint *wp = nullptr; |
| 379 | CommandCost ret = FindJoiningWaypoint(est, station_to_join, adjacent, roadstop_area, &wp, true); |
| 380 | if (ret.Failed()) return ret; |
| 381 | |
| 382 | /* Check if there is an already existing, deleted, waypoint close to us that we can reuse. */ |
| 383 | TileIndex center_tile = start_tile + (count / 2) * TileOffsByAxis(OtherAxis(axis)); |
| 384 | if (wp == nullptr && reuse) wp = FindDeletedWaypointCloseTo(center_tile, STR_SV_STNAME_WAYPOINT, _current_company, true); |
| 385 | |
| 386 | if (wp != nullptr) { |
| 387 | /* Reuse an existing waypoint. */ |
| 388 | if (!HasBit(wp->waypoint_flags, WPF_ROAD)) return CMD_ERROR; |
| 389 | if (wp->owner != _current_company) return CommandCost(STR_ERROR_TOO_CLOSE_TO_ANOTHER_WAYPOINT); |
| 390 | |
| 391 | ret = wp->rect.BeforeAddRect(start_tile, width, height, StationRect::ADD_TEST); |
| 392 | if (ret.Failed()) return ret; |
| 393 | } else { |
| 394 | /* Check if we can create a new waypoint. */ |
| 395 | if (!Waypoint::CanAllocateItem()) return CommandCost(STR_ERROR_TOO_MANY_STATIONS_LOADING); |
| 396 | } |
| 397 | |
| 398 | /* Check if we can allocate a custom spec to this waypoint. */ |
| 399 | auto specindex = AllocateSpecToRoadStop(roadstopspec, wp); |
nothing calls this directly
no test coverage detected