changeset 18284:9c6632d5d556 draft

(svn r23120) -Feature: [NoAI] Support for refit orders.
author michi_cc <michi_cc@openttd.org>
date Sat, 05 Nov 2011 15:31:21 +0000
parents 0e2e0050b70a
children a08e7009f586
files src/ai/api/ai_cargo.hpp src/ai/api/ai_cargo.hpp.sq src/ai/api/ai_changelog.hpp src/ai/api/ai_order.cpp src/ai/api/ai_order.hpp src/ai/api/ai_order.hpp.sq
diffstat 6 files changed, 85 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/ai/api/ai_cargo.hpp
+++ b/src/ai/api/ai_cargo.hpp
@@ -51,6 +51,14 @@
 	};
 
 	/**
+	 * Special cargo types.
+	 */
+	enum SpecialCargoID {
+		CT_AUTO_REFIT = 0xFD, ///< Automatically choose cargo type when doing auto-refitting.
+		CT_NO_REFIT   = 0xFE, ///< Do not refit cargo of a vehicle.
+	};
+
+	/**
 	 * Checks whether the given cargo type is valid.
 	 * @param cargo_type The cargo to check.
 	 * @return True if and only if the cargo type is valid.
--- a/src/ai/api/ai_cargo.hpp.sq
+++ b/src/ai/api/ai_cargo.hpp.sq
@@ -17,6 +17,8 @@
 	template <> int Return<AICargo::CargoClass>(HSQUIRRELVM vm, AICargo::CargoClass res) { sq_pushinteger(vm, (int32)res); return 1; }
 	template <> AICargo::TownEffect GetParam(ForceType<AICargo::TownEffect>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AICargo::TownEffect)tmp; }
 	template <> int Return<AICargo::TownEffect>(HSQUIRRELVM vm, AICargo::TownEffect res) { sq_pushinteger(vm, (int32)res); return 1; }
+	template <> AICargo::SpecialCargoID GetParam(ForceType<AICargo::SpecialCargoID>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQInteger tmp; sq_getinteger(vm, index, &tmp); return (AICargo::SpecialCargoID)tmp; }
+	template <> int Return<AICargo::SpecialCargoID>(HSQUIRRELVM vm, AICargo::SpecialCargoID res) { sq_pushinteger(vm, (int32)res); return 1; }
 
 	/* Allow AICargo to be used as Squirrel parameter */
 	template <> AICargo *GetParam(ForceType<AICargo *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQUserPointer instance; sq_getinstanceup(vm, index, &instance, 0); return  (AICargo *)instance; }
@@ -48,6 +50,8 @@
 	SQAICargo.DefSQConst(engine, AICargo::TE_GOODS,        "TE_GOODS");
 	SQAICargo.DefSQConst(engine, AICargo::TE_WATER,        "TE_WATER");
 	SQAICargo.DefSQConst(engine, AICargo::TE_FOOD,         "TE_FOOD");
+	SQAICargo.DefSQConst(engine, AICargo::CT_AUTO_REFIT,   "CT_AUTO_REFIT");
+	SQAICargo.DefSQConst(engine, AICargo::CT_NO_REFIT,     "CT_NO_REFIT");
 
 	SQAICargo.DefSQStaticMethod(engine, &AICargo::IsValidCargo,   "IsValidCargo",   2, ".i");
 	SQAICargo.DefSQStaticMethod(engine, &AICargo::GetCargoLabel,  "GetCargoLabel",  2, ".i");
--- a/src/ai/api/ai_changelog.hpp
+++ b/src/ai/api/ai_changelog.hpp
@@ -21,12 +21,17 @@
  *
  * API additions:
  *
+ * \li AICargo::CT_AUTO_REFIT
+ * \li AICargo::CT_NO_REFIT
  * \li AICompany::GetQuarterlyIncome
  * \li AICompany::GetQuarterlyExpenses
  * \li AICompany::GetQuarterlyCargoDelivered
  * \li AICompany::GetQuarterlyPerformanceRating
  * \li AICompany::GetQuarterlyCompanyValue
  * \li AIController::GetOpsTillSuspend
+ * \li AIOrder::GetOrderRefit
+ * \li AIOrder::IsRefitOrder
+ * \li AIOrder::SetOrderRefit
  * \li AITown::GetTownAuthority
  * \li AIVehicle::ERR_VEHICLE_TOO_LONG in case vehicle length limit is reached
  *
--- a/src/ai/api/ai_order.cpp
+++ b/src/ai/api/ai_order.cpp
@@ -12,6 +12,7 @@
 #include "../../stdafx.h"
 #include "ai_order.hpp"
 #include "ai_vehicle.hpp"
+#include "ai_cargo.hpp"
 #include "../ai_instance.hpp"
 #include "../../debug.h"
 #include "../../vehicle_base.h"
@@ -117,6 +118,14 @@
 	return order->GetType() == OT_DUMMY;
 }
 
+/* static */ bool AIOrder::IsRefitOrder(VehicleID vehicle_id, OrderPosition order_position)
+{
+	if (!IsValidVehicleOrder(vehicle_id, order_position)) return false;
+
+	const Order *order = ::ResolveOrder(vehicle_id, order_position);
+	return order != NULL && order->IsRefit();
+}
+
 /* static */ bool AIOrder::IsCurrentOrderPartOfOrderList(VehicleID vehicle_id)
 {
 	if (AIVehicle::IsValidVehicle(vehicle_id)) return false;
@@ -323,6 +332,15 @@
 	return (AIOrder::StopLocation)order->GetStopLocation();
 }
 
+/* static */ CargoID AIOrder::GetOrderRefit(VehicleID vehicle_id, OrderPosition order_position)
+{
+	if (!IsValidVehicleOrder(vehicle_id, order_position)) return CT_NO_REFIT;
+	if (order_position != ORDER_CURRENT && !IsGotoStationOrder(vehicle_id, order_position) && !IsGotoDepotOrder(vehicle_id, order_position)) return CT_NO_REFIT;
+
+	const Order *order = ::ResolveOrder(vehicle_id, order_position);
+	return order->IsRefit() ? order->GetRefitCargo() : CT_NO_REFIT;
+}
+
 /* static */ bool AIOrder::SetOrderJumpTo(VehicleID vehicle_id, OrderPosition order_position, OrderPosition jump_to)
 {
 	EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position));
@@ -372,6 +390,17 @@
 	return AIObject::DoCommand(0, p1, p2, CMD_MODIFY_ORDER);
 }
 
+/* static */ bool AIOrder::SetOrderRefit(VehicleID vehicle_id, OrderPosition order_position, CargoID refit_cargo)
+{
+	EnforcePrecondition(false, IsValidVehicleOrder(vehicle_id, order_position));
+	EnforcePrecondition(false, IsGotoStationOrder(vehicle_id, order_position) || (IsGotoDepotOrder(vehicle_id, order_position) && refit_cargo != CT_AUTO_REFIT));
+	EnforcePrecondition(false, AICargo::IsValidCargo(refit_cargo) || refit_cargo == CT_AUTO_REFIT || refit_cargo == CT_NO_REFIT);
+
+	uint32 p1 = vehicle_id;
+	uint32 p2 = refit_cargo | AIOrder::ResolveOrderPosition(vehicle_id, order_position) << 16;
+	return AIObject::DoCommand(0, p1, p2, CMD_ORDER_REFIT);
+}
+
 /* static */ bool AIOrder::AppendOrder(VehicleID vehicle_id, TileIndex destination, AIOrderFlags order_flags)
 {
 	EnforcePrecondition(false, AIVehicle::IsValidVehicle(vehicle_id));
--- a/src/ai/api/ai_order.hpp
+++ b/src/ai/api/ai_order.hpp
@@ -191,6 +191,15 @@
 	static bool IsVoidOrder(VehicleID vehicle_id, OrderPosition order_position);
 
 	/**
+	 * Checks whether the given order has a valid refit cargo.
+	 * @param vehicle_id The vehicle to check.
+	 * @param order_position The order index to check.
+	 * @pre order_position != ORDER_CURRENT && IsValidVehicleOrder(vehicle_id, order_position).
+	 * @return True if and only if the order is has a valid refit cargo.
+	 */
+	static bool IsRefitOrder(VehicleID vehicle_id, OrderPosition order_position);
+
+	/**
 	 * Checks whether the current order is part of the orderlist.
 	 * @param vehicle_id The vehicle to check.
 	 * @pre AIVehicle::IsValidVehicle(vehicle_id).
@@ -320,6 +329,21 @@
 	static StopLocation GetStopLocation(VehicleID vehicle_id, OrderPosition order_position);
 
 	/**
+	 * Gets the refit cargo type of the given order for the given vehicle.
+	 * @param vehicle_id The vehicle to get the refit cargo for.
+	 * @param order_position The order to get the refit cargo for.
+	 * @pre IsValidVehicleOrder(vehicle_id, order_position).
+	 * @pre order_position == ORDER_CURRENT || IsGotoStationOrder(vehicle_id, order_position) || IsGotoDepotOrder(vehicle_id, order_position).
+	 * @note Giving ORDER_CURRENT as order_position will give the order that is
+	 *  currently being executed by the vehicle. This is not necessarily the
+	 *  current order as given by ResolveOrderPosition (the current index in the
+	 *  order list) as manual or autoservicing depot orders do not show up
+	 *  in the orderlist, but they can be the current order of a vehicle.
+	 * @return The refit cargo of the order or CT_NO_REFIT if no refit is set.
+	 */
+	static CargoID GetOrderRefit(VehicleID vehicle_id, OrderPosition order_position);
+
+	/**
 	 * Sets the OrderPosition to jump to if the check succeeds of the given order for the given vehicle.
 	 * @param vehicle_id The vehicle to set the OrderPosition for.
 	 * @param order_position The order to set the OrderPosition for.
@@ -381,6 +405,18 @@
 	static bool SetStopLocation(VehicleID vehicle_id, OrderPosition order_position, StopLocation stop_location);
 
 	/**
+	 * Sets the refit cargo type of the given order for the given vehicle.
+	 * @param vehicle_id The vehicle to set the refit cargo for.
+	 * @param order_position The order to set the refit cargo for.
+	 * @param refit_cargo The cargo to refit to. The refit can be cleared by passing CT_NO_REFIT.
+	 * @pre IsValidVehicleOrder(vehicle_id, order_position).
+	 * @pre IsGotoStationOrder(vehicle_id, order_position) || (IsGotoDepotOrder(vehicle_id, order_position) && refit_cargo != CT_AUTO_REFIT).
+	 * @pre AICargo::IsValidCargo(refit_cargo) || refit_cargo == CT_AUTO_REFIT || refit_cargo == CT_NO_REFIT
+	 * @return Whether the order has been/can be changed.
+	 */
+	static bool SetOrderRefit(VehicleID vehicle_id, OrderPosition order_position, CargoID refit_cargo);
+
+	/**
 	 * Appends an order to the end of the vehicle's order list.
 	 * @param vehicle_id The vehicle to append the order to.
 	 * @param destination The destination of the order.
--- a/src/ai/api/ai_order.hpp.sq
+++ b/src/ai/api/ai_order.hpp.sq
@@ -96,6 +96,7 @@
 	SQAIOrder.DefSQStaticMethod(engine, &AIOrder::IsGotoWaypointOrder,           "IsGotoWaypointOrder",           3, ".ii");
 	SQAIOrder.DefSQStaticMethod(engine, &AIOrder::IsConditionalOrder,            "IsConditionalOrder",            3, ".ii");
 	SQAIOrder.DefSQStaticMethod(engine, &AIOrder::IsVoidOrder,                   "IsVoidOrder",                   3, ".ii");
+	SQAIOrder.DefSQStaticMethod(engine, &AIOrder::IsRefitOrder,                  "IsRefitOrder",                  3, ".ii");
 	SQAIOrder.DefSQStaticMethod(engine, &AIOrder::IsCurrentOrderPartOfOrderList, "IsCurrentOrderPartOfOrderList", 2, ".i");
 	SQAIOrder.DefSQStaticMethod(engine, &AIOrder::ResolveOrderPosition,          "ResolveOrderPosition",          3, ".ii");
 	SQAIOrder.DefSQStaticMethod(engine, &AIOrder::AreOrderFlagsValid,            "AreOrderFlagsValid",            3, ".ii");
@@ -108,11 +109,13 @@
 	SQAIOrder.DefSQStaticMethod(engine, &AIOrder::GetOrderCompareFunction,       "GetOrderCompareFunction",       3, ".ii");
 	SQAIOrder.DefSQStaticMethod(engine, &AIOrder::GetOrderCompareValue,          "GetOrderCompareValue",          3, ".ii");
 	SQAIOrder.DefSQStaticMethod(engine, &AIOrder::GetStopLocation,               "GetStopLocation",               3, ".ii");
+	SQAIOrder.DefSQStaticMethod(engine, &AIOrder::GetOrderRefit,                 "GetOrderRefit",                 3, ".ii");
 	SQAIOrder.DefSQStaticMethod(engine, &AIOrder::SetOrderJumpTo,                "SetOrderJumpTo",                4, ".iii");
 	SQAIOrder.DefSQStaticMethod(engine, &AIOrder::SetOrderCondition,             "SetOrderCondition",             4, ".iii");
 	SQAIOrder.DefSQStaticMethod(engine, &AIOrder::SetOrderCompareFunction,       "SetOrderCompareFunction",       4, ".iii");
 	SQAIOrder.DefSQStaticMethod(engine, &AIOrder::SetOrderCompareValue,          "SetOrderCompareValue",          4, ".iii");
 	SQAIOrder.DefSQStaticMethod(engine, &AIOrder::SetStopLocation,               "SetStopLocation",               4, ".iii");
+	SQAIOrder.DefSQStaticMethod(engine, &AIOrder::SetOrderRefit,                 "SetOrderRefit",                 4, ".iii");
 	SQAIOrder.DefSQStaticMethod(engine, &AIOrder::AppendOrder,                   "AppendOrder",                   4, ".iii");
 	SQAIOrder.DefSQStaticMethod(engine, &AIOrder::AppendConditionalOrder,        "AppendConditionalOrder",        3, ".ii");
 	SQAIOrder.DefSQStaticMethod(engine, &AIOrder::InsertOrder,                   "InsertOrder",                   5, ".iiii");