* Add an order to the orderlist of a vehicle. * @param flags operation to perform * @param veh ID of the vehicle * @param sel_ord the selected order (if any). If the last order is given, * the order will be inserted before that one * the maximum vehicle order id is 254. * @param new_order order to insert * @return the cost of this operation or a
| 619 | * @return the cost of this operation or an error |
| 620 | */ |
| 621 | CommandCost CmdInsertOrder(DoCommandFlags flags, VehicleID veh, VehicleOrderID sel_ord, const Order &new_order) |
| 622 | { |
| 623 | Vehicle *v = Vehicle::GetIfValid(veh); |
| 624 | if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR; |
| 625 | |
| 626 | CommandCost ret = CheckOwnership(v->owner); |
| 627 | if (ret.Failed()) return ret; |
| 628 | |
| 629 | /* Validate properties we don't want to have different from default as they are set by other commands. */ |
| 630 | if (new_order.GetRefitCargo() != CARGO_NO_REFIT || new_order.GetWaitTime() != 0 || new_order.GetTravelTime() != 0 || new_order.GetMaxSpeed() != UINT16_MAX) return CMD_ERROR; |
| 631 | |
| 632 | /* Check if the inserted order is to the correct destination (owner, type), |
| 633 | * and has the correct flags if any */ |
| 634 | switch (new_order.GetType()) { |
| 635 | case OT_GOTO_STATION: { |
| 636 | const Station *st = Station::GetIfValid(new_order.GetDestination().ToStationID()); |
| 637 | if (st == nullptr) return CMD_ERROR; |
| 638 | |
| 639 | if (st->owner != OWNER_NONE) { |
| 640 | ret = CheckOwnership(st->owner); |
| 641 | if (ret.Failed()) return ret; |
| 642 | } |
| 643 | |
| 644 | if (!CanVehicleUseStation(v, st)) return CommandCost(STR_ERROR_CAN_T_ADD_ORDER, GetVehicleCannotUseStationReason(v, st)); |
| 645 | for (Vehicle *u = v->FirstShared(); u != nullptr; u = u->NextShared()) { |
| 646 | if (!CanVehicleUseStation(u, st)) return CommandCost(STR_ERROR_CAN_T_ADD_ORDER_SHARED, GetVehicleCannotUseStationReason(u, st)); |
| 647 | } |
| 648 | |
| 649 | /* Non stop only allowed for ground vehicles. */ |
| 650 | if (new_order.GetNonStopType().Any() && !v->IsGroundVehicle()) return CMD_ERROR; |
| 651 | |
| 652 | /* Filter invalid load/unload types. */ |
| 653 | switch (new_order.GetLoadType()) { |
| 654 | case OrderLoadType::LoadIfPossible: |
| 655 | case OrderLoadType::NoLoad: |
| 656 | break; |
| 657 | |
| 658 | case OrderLoadType::FullLoad: |
| 659 | case OrderLoadType::FullLoadAny: |
| 660 | if (v->HasUnbunchingOrder()) return CommandCost(STR_ERROR_UNBUNCHING_NO_FULL_LOAD); |
| 661 | break; |
| 662 | |
| 663 | default: |
| 664 | return CMD_ERROR; |
| 665 | } |
| 666 | switch (new_order.GetUnloadType()) { |
| 667 | case OrderUnloadType::UnloadIfPossible: |
| 668 | case OrderUnloadType::Unload: |
| 669 | case OrderUnloadType::Transfer: |
| 670 | case OrderUnloadType::NoUnload: |
| 671 | break; |
| 672 | |
| 673 | default: |
| 674 | return CMD_ERROR; |
| 675 | } |
| 676 | |
| 677 | /* Filter invalid stop locations */ |
| 678 | switch (new_order.GetStopLocation()) { |
nothing calls this directly
no test coverage detected