Index: src/ai/api/ai_order.cpp =================================================================== --- src/ai/api/ai_order.cpp (revision 23119) +++ src/ai/api/ai_order.cpp (working copy) @@ -75,6 +75,29 @@ return order; } +/** + * Convert an AIOrder::OrderPosition (which is the manual order index) to an order index + * as expected by the OpenTTD commands. + * @param order_position The OrderPosition to convert. + * @return An OpenTTD-internal index for the same order. + */ +static const int AIOrderPositionToRealOrderPosition(VehicleID vehicle_id, AIOrder::OrderPosition order_position) +{ + assert(AIOrder::IsValidVehicleOrder(vehicle_id, order_position) && order_position != AIOrder::ORDER_CURRENT); + const Vehicle *v = ::Vehicle::Get(vehicle_id); + + int res = (int)order_position; + const Order *order = v->orders.list->GetFirstOrder(); + for (; order->GetType() == OT_IMPLICIT; order = order->next) res++; + while (order_position > 0) { + order_position = (AIOrder::OrderPosition)(order_position - 1); + order = order->next; + for (; order->GetType() == OT_IMPLICIT; order = order->next) res++; + } + + return res; +} + /* static */ bool AIOrder::IsGotoStationOrder(VehicleID vehicle_id, OrderPosition order_position) { if (!IsValidVehicleOrder(vehicle_id, order_position)) return false; @@ -113,7 +136,7 @@ if (order_position == ORDER_CURRENT) return false; if (!IsValidVehicleOrder(vehicle_id, order_position)) return false; - const Order *order = Vehicle::Get(vehicle_id)->GetOrder(order_position); + const Order *order = ResolveOrder(vehicle_id, order_position); return order->GetType() == OT_DUMMY; } @@ -338,7 +361,8 @@ EnforcePrecondition(false, order_position != ORDER_CURRENT && IsConditionalOrder(vehicle_id, order_position)); EnforcePrecondition(false, condition >= OC_LOAD_PERCENTAGE && condition <= OC_REMAINING_LIFETIME); - return AIObject::DoCommand(0, vehicle_id | (order_position << 20), MOF_COND_VARIABLE | (condition << 4), CMD_MODIFY_ORDER); + int order_pos = AIOrderPositionToRealOrderPosition(vehicle_id, order_position); + return AIObject::DoCommand(0, vehicle_id | (order_pos << 20), MOF_COND_VARIABLE | (condition << 4), CMD_MODIFY_ORDER); } /* static */ bool AIOrder::SetOrderCompareFunction(VehicleID vehicle_id, OrderPosition order_position, CompareFunction compare) @@ -347,7 +371,8 @@ EnforcePrecondition(false, order_position != ORDER_CURRENT && IsConditionalOrder(vehicle_id, order_position)); EnforcePrecondition(false, compare >= CF_EQUALS && compare <= CF_IS_FALSE); - return AIObject::DoCommand(0, vehicle_id | (order_position << 20), MOF_COND_COMPARATOR | (compare << 4), CMD_MODIFY_ORDER); + int order_pos = AIOrderPositionToRealOrderPosition(vehicle_id, order_position); + return AIObject::DoCommand(0, vehicle_id | (order_pos << 20), MOF_COND_COMPARATOR | (compare << 4), CMD_MODIFY_ORDER); } /* static */ bool AIOrder::SetOrderCompareValue(VehicleID vehicle_id, OrderPosition order_position, int32 value) @@ -357,7 +382,8 @@ EnforcePrecondition(false, value >= 0 && value < 2048); if (GetOrderCondition(vehicle_id, order_position) == OC_MAX_SPEED) value = value * 10 / 16; - return AIObject::DoCommand(0, vehicle_id | (order_position << 20), MOF_COND_VALUE | (value << 4), CMD_MODIFY_ORDER); + int order_pos = AIOrderPositionToRealOrderPosition(vehicle_id, order_position); + return AIObject::DoCommand(0, vehicle_id | (order_pos << 20), MOF_COND_VALUE | (value << 4), CMD_MODIFY_ORDER); } /* static */ bool AIOrder::SetStopLocation(VehicleID vehicle_id, OrderPosition order_position, StopLocation stop_location) @@ -367,7 +393,8 @@ EnforcePrecondition(false, IsGotoStationOrder(vehicle_id, order_position)); EnforcePrecondition(false, stop_location >= STOPLOCATION_NEAR && stop_location <= STOPLOCATION_FAR); - uint32 p1 = vehicle_id | (order_position << 20); + int order_pos = AIOrderPositionToRealOrderPosition(vehicle_id, order_position); + uint32 p1 = vehicle_id | (order_pos << 20); uint32 p2 = MOF_STOP_LOCATION | (stop_location << 4); return AIObject::DoCommand(0, p1, p2, CMD_MODIFY_ORDER); } @@ -377,7 +404,7 @@ EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id)); EnforcePrecondition(false, AreOrderFlagsValid(destination, order_flags)); - return InsertOrder(vehicle_id, (AIOrder::OrderPosition)::Vehicle::Get(vehicle_id)->GetNumOrders(), destination, order_flags); + return InsertOrder(vehicle_id, (AIOrder::OrderPosition)::Vehicle::Get(vehicle_id)->GetNumManualOrders(), destination, order_flags); } /* static */ bool AIOrder::AppendConditionalOrder(VehicleID vehicle_id, OrderPosition jump_to) @@ -385,7 +412,7 @@ EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id)); EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, jump_to)); - return InsertConditionalOrder(vehicle_id, (AIOrder::OrderPosition)::Vehicle::Get(vehicle_id)->GetNumOrders(), jump_to); + return InsertConditionalOrder(vehicle_id, (AIOrder::OrderPosition)::Vehicle::Get(vehicle_id)->GetNumManualOrders(), jump_to); } /* static */ bool AIOrder::InsertOrder(VehicleID vehicle_id, OrderPosition order_position, TileIndex destination, AIOrder::AIOrderFlags order_flags) @@ -394,7 +421,7 @@ if (order_position == ORDER_CURRENT) order_position = AIOrder::ResolveOrderPosition(vehicle_id, order_position); EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id)); - EnforcePrecondition(false, order_position >= 0 && order_position <= ::Vehicle::Get(vehicle_id)->GetNumOrders()); + EnforcePrecondition(false, order_position >= 0 && order_position <= ::Vehicle::Get(vehicle_id)->GetNumManualOrders()); EnforcePrecondition(false, AreOrderFlagsValid(destination, order_flags)); Order order; @@ -438,7 +465,8 @@ order.SetNonStopType((OrderNonStopFlags)GB(order_flags, 0, 2)); - return AIObject::DoCommand(0, vehicle_id | (order_position << 20), order.Pack(), CMD_INSERT_ORDER); + int order_pos = AIOrderPositionToRealOrderPosition(vehicle_id, order_position); + return AIObject::DoCommand(0, vehicle_id | (order_pos << 20), order.Pack(), CMD_INSERT_ORDER); } /* static */ bool AIOrder::InsertConditionalOrder(VehicleID vehicle_id, OrderPosition order_position, OrderPosition jump_to) @@ -447,12 +475,14 @@ if (order_position == ORDER_CURRENT) order_position = AIOrder::ResolveOrderPosition(vehicle_id, order_position); EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id)); - EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, jump_to)); + EnforcePrecondition(false, order_position >= 0 && order_position <= ::Vehicle::Get(vehicle_id)->GetNumManualOrders()); + EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, jump_to) && jump_to != ORDER_CURRENT); Order order; order.MakeConditional(jump_to); - return AIObject::DoCommand(0, vehicle_id | (order_position << 20), order.Pack(), CMD_INSERT_ORDER); + int order_pos = AIOrderPositionToRealOrderPosition(vehicle_id, order_position); + return AIObject::DoCommand(0, vehicle_id | (order_pos << 20), order.Pack(), CMD_INSERT_ORDER); } /* static */ bool AIOrder::RemoveOrder(VehicleID vehicle_id, OrderPosition order_position) @@ -461,7 +491,8 @@ EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position)); - return AIObject::DoCommand(0, vehicle_id, order_position, CMD_DELETE_ORDER); + int order_pos = AIOrderPositionToRealOrderPosition(vehicle_id, order_position); + return AIObject::DoCommand(0, vehicle_id, order_pos, CMD_DELETE_ORDER); } /* static */ bool AIOrder::SkipToOrder(VehicleID vehicle_id, OrderPosition next_order) @@ -470,7 +501,8 @@ EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, next_order)); - return AIObject::DoCommand(0, vehicle_id, next_order, CMD_SKIP_TO_ORDER); + int order_pos = AIOrderPositionToRealOrderPosition(vehicle_id, next_order); + return AIObject::DoCommand(0, vehicle_id, order_pos, CMD_SKIP_TO_ORDER); } /** @@ -507,13 +539,14 @@ EnforcePrecondition(false, AreOrderFlagsValid(GetOrderDestination(vehicle_id, order_position), order_flags)); const Order *order = ::ResolveOrder(vehicle_id, order_position); + int order_pos = AIOrderPositionToRealOrderPosition(vehicle_id, order_position); AIOrderFlags current = GetOrderFlags(vehicle_id, order_position); EnforcePrecondition(false, (order_flags & AIOF_GOTO_NEAREST_DEPOT) == (current & AIOF_GOTO_NEAREST_DEPOT)); if ((current & AIOF_NON_STOP_FLAGS) != (order_flags & AIOF_NON_STOP_FLAGS)) { - return AIObject::DoCommand(0, vehicle_id | (order_position << 20), (order_flags & AIOF_NON_STOP_FLAGS) << 4 | MOF_NON_STOP, CMD_MODIFY_ORDER, NULL, &::_DoCommandReturnSetOrderFlags); + return AIObject::DoCommand(0, vehicle_id | (order_pos << 20), (order_flags & AIOF_NON_STOP_FLAGS) << 4 | MOF_NON_STOP, CMD_MODIFY_ORDER, NULL, &::_DoCommandReturnSetOrderFlags); } switch (order->GetType()) { @@ -522,16 +555,16 @@ uint data = DA_ALWAYS_GO; if (order_flags & AIOF_SERVICE_IF_NEEDED) data = DA_SERVICE; if (order_flags & AIOF_STOP_IN_DEPOT) data = DA_STOP; - return AIObject::DoCommand(0, vehicle_id | (order_position << 20), (data << 4) | MOF_DEPOT_ACTION, CMD_MODIFY_ORDER, NULL, &::_DoCommandReturnSetOrderFlags); + return AIObject::DoCommand(0, vehicle_id | (order_pos << 20), (data << 4) | MOF_DEPOT_ACTION, CMD_MODIFY_ORDER, NULL, &::_DoCommandReturnSetOrderFlags); } break; case OT_GOTO_STATION: if ((current & AIOF_UNLOAD_FLAGS) != (order_flags & AIOF_UNLOAD_FLAGS)) { - return AIObject::DoCommand(0, vehicle_id | (order_position << 20), (order_flags & AIOF_UNLOAD_FLAGS) << 2 | MOF_UNLOAD, CMD_MODIFY_ORDER, NULL, &::_DoCommandReturnSetOrderFlags); + return AIObject::DoCommand(0, vehicle_id | (order_pos << 20), (order_flags & AIOF_UNLOAD_FLAGS) << 2 | MOF_UNLOAD, CMD_MODIFY_ORDER, NULL, &::_DoCommandReturnSetOrderFlags); } if ((current & AIOF_LOAD_FLAGS) != (order_flags & AIOF_LOAD_FLAGS)) { - return AIObject::DoCommand(0, vehicle_id | (order_position << 20), (order_flags & AIOF_LOAD_FLAGS) >> 1 | MOF_LOAD, CMD_MODIFY_ORDER, NULL, &::_DoCommandReturnSetOrderFlags); + return AIObject::DoCommand(0, vehicle_id | (order_pos << 20), (order_flags & AIOF_LOAD_FLAGS) >> 1 | MOF_LOAD, CMD_MODIFY_ORDER, NULL, &::_DoCommandReturnSetOrderFlags); } break; @@ -562,7 +595,9 @@ EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position_move)); EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position_target)); - return AIObject::DoCommand(0, vehicle_id, order_position_move | (order_position_target << 16), CMD_MOVE_ORDER); + int order_pos_move = AIOrderPositionToRealOrderPosition(vehicle_id, order_position_move); + int order_pos_target = AIOrderPositionToRealOrderPosition(vehicle_id, order_position_target); + return AIObject::DoCommand(0, vehicle_id, order_pos_move | (order_pos_target << 16), CMD_MOVE_ORDER); } /* static */ bool AIOrder::CopyOrders(VehicleID vehicle_id, VehicleID main_vehicle_id)