* Move an order inside the orderlist * @param flags operation to perform * @param veh the ID of the vehicle * @param moving_order the order to move * @param target_order the target order * @return the cost of this operation or an error * @note The target order will move one place down in the orderlist * if you move the order upwards else it'll move it one place down */
| 1072 | * if you move the order upwards else it'll move it one place down |
| 1073 | */ |
| 1074 | CommandCost CmdMoveOrder(DoCommandFlags flags, VehicleID veh, VehicleOrderID moving_order, VehicleOrderID target_order) |
| 1075 | { |
| 1076 | Vehicle *v = Vehicle::GetIfValid(veh); |
| 1077 | if (v == nullptr || !v->IsPrimaryVehicle()) return CMD_ERROR; |
| 1078 | |
| 1079 | CommandCost ret = CheckOwnership(v->owner); |
| 1080 | if (ret.Failed()) return ret; |
| 1081 | |
| 1082 | /* Don't make senseless movements */ |
| 1083 | if (moving_order >= v->GetNumOrders() || target_order >= v->GetNumOrders() || |
| 1084 | moving_order == target_order || v->GetNumOrders() <= 1) return CMD_ERROR; |
| 1085 | |
| 1086 | Order *moving_one = v->GetOrder(moving_order); |
| 1087 | /* Don't move an empty order */ |
| 1088 | if (moving_one == nullptr) return CMD_ERROR; |
| 1089 | |
| 1090 | if (flags.Test(DoCommandFlag::Execute)) { |
| 1091 | v->orders->MoveOrder(moving_order, target_order); |
| 1092 | |
| 1093 | /* Update shared list */ |
| 1094 | Vehicle *u = v->FirstShared(); |
| 1095 | |
| 1096 | DeleteOrderWarnings(u); |
| 1097 | |
| 1098 | for (; u != nullptr; u = u->NextShared()) { |
| 1099 | /* Update the current order. |
| 1100 | * There are multiple ways to move orders, which result in cur_implicit_order_index |
| 1101 | * and cur_real_order_index to not longer make any sense. E.g. moving another |
| 1102 | * real order between them. |
| 1103 | * |
| 1104 | * Basically one could choose to preserve either of them, but not both. |
| 1105 | * While both ways are suitable in this or that case from a human point of view, neither |
| 1106 | * of them makes really sense. |
| 1107 | * However, from an AI point of view, preserving cur_real_order_index is the most |
| 1108 | * predictable and transparent behaviour. |
| 1109 | * |
| 1110 | * With that decision it basically does not matter what we do to cur_implicit_order_index. |
| 1111 | * If we change orders between the implicit- and real-index, the implicit orders are mostly likely |
| 1112 | * completely out-dated anyway. So, keep it simple and just keep cur_implicit_order_index as well. |
| 1113 | * The worst which can happen is that a lot of implicit orders are removed when reaching current_order. |
| 1114 | */ |
| 1115 | if (u->cur_real_order_index == moving_order) { |
| 1116 | u->cur_real_order_index = target_order; |
| 1117 | } else if (u->cur_real_order_index > moving_order && u->cur_real_order_index <= target_order) { |
| 1118 | u->cur_real_order_index--; |
| 1119 | } else if (u->cur_real_order_index < moving_order && u->cur_real_order_index >= target_order) { |
| 1120 | u->cur_real_order_index++; |
| 1121 | } |
| 1122 | |
| 1123 | if (u->cur_implicit_order_index == moving_order) { |
| 1124 | u->cur_implicit_order_index = target_order; |
| 1125 | } else if (u->cur_implicit_order_index > moving_order && u->cur_implicit_order_index <= target_order) { |
| 1126 | u->cur_implicit_order_index--; |
| 1127 | } else if (u->cur_implicit_order_index < moving_order && u->cur_implicit_order_index >= target_order) { |
| 1128 | u->cur_implicit_order_index++; |
| 1129 | } |
| 1130 | /* Unbunching data is no longer valid. */ |
| 1131 | u->ResetDepotUnbunching(); |
nothing calls this directly
no test coverage detected