tron@2186: /* $Id$ */ tron@2186: rubidium@4549: /** @file order.h */ celestar@2214: truelight@1024: #ifndef ORDER_H truelight@1024: #define ORDER_H truelight@1024: matthijs@5216: #include "oldpool.h" rubidium@8609: #include "core/bitmath_func.hpp" rubidium@8615: #include "cargo_type.h" rubidium@8615: #include "vehicle_type.h" rubidium@8634: #include "tile_type.h" rubidium@8707: #include "date_type.h" truelight@1314: bjarni@4408: enum { bjarni@4712: INVALID_VEH_ORDER_ID = 0xFF, bjarni@4408: }; bjarni@4408: rubidium@5838: static const OrderID INVALID_ORDER = 0xFFFF; rubidium@5838: truelight@1024: /* Order types */ rubidium@5838: enum OrderType { rubidium@5838: OT_BEGIN = 0, truelight@1024: OT_NOTHING = 0, truelight@1024: OT_GOTO_STATION = 1, truelight@1024: OT_GOTO_DEPOT = 2, truelight@1024: OT_LOADING = 3, truelight@1024: OT_LEAVESTATION = 4, truelight@1024: OT_DUMMY = 5, truelight@4421: OT_GOTO_WAYPOINT = 6, rubidium@5838: OT_END truelight@4421: }; rubidium@5838: truelight@4421: /* It needs to be 8bits, because we save and load it as such */ rubidium@5838: /** Define basic enum properties */ rubidium@5838: template <> struct EnumPropsT : MakeEnumPropsT {}; rubidium@5838: typedef TinyEnumT OrderTypeByte; rubidium@5838: truelight@1024: rubidium@8798: /* Order flags -- please use OF instead OF and use HASBIT/SETBIT/CLEARBIT */ pasky@1615: celestar@2214: /** Order flag masks - these are for direct bit operations */ celestar@2214: enum OrderFlagMasks { celestar@1530: //Flags for stations: celestar@2214: /** vehicle will transfer cargo (i. e. not deliver to nearby industry/town even if accepted there) */ rubidium@8798: OFB_TRANSFER = 0x1, rubidium@8798: /** If OFB_TRANSFER is not set, drop any cargo loaded. If accepted, deliver, otherwise cargo remains at the station. celestar@2214: * No new cargo is loaded onto the vehicle whatsoever */ rubidium@8798: OFB_UNLOAD = 0x2, celestar@2214: /** Wait for full load of all vehicles, or of at least one cargo type, depending on patch setting celestar@2214: * @todo make this two different flags */ rubidium@8798: OFB_FULL_LOAD = 0x4, celestar@1530: celestar@1530: //Flags for depots: celestar@2214: /** The current depot-order was initiated because it was in the vehicle's order list */ rubidium@8798: OFB_PART_OF_ORDERS = 0x2, rubidium@8798: /** if OFB_PART_OF_ORDERS is not set, this will cause the vehicle to be stopped in the depot */ rubidium@8798: OFB_HALT_IN_DEPOT = 0x4, rubidium@8798: /** if OFB_PART_OF_ORDERS is set, this will cause the order only be come active if the vehicle needs servicing */ rubidium@8798: OFB_SERVICE_IF_NEEDED = 0x4, //used when OFB_PART_OF_ORDERS is set. celestar@1530: celestar@1530: //Common flags celestar@2214: /** This causes the vehicle not to stop at intermediate OR the destination station (depending on patch settings) celestar@2214: * @todo make this two different flags */ rubidium@8798: OFB_NON_STOP = 0x8 truelight@1024: }; truelight@1024: celestar@2214: /** Order flags bits - these are for the *BIT macros tron@4077: * for descrption of flags, see OrderFlagMasks tron@4077: * @see OrderFlagMasks tron@4077: */ truelight@1024: enum { rubidium@8798: OF_TRANSFER = 0, rubidium@8798: OF_UNLOAD = 1, rubidium@8798: OF_FULL_LOAD = 2, rubidium@8798: OF_PART_OF_ORDERS = 1, rubidium@8798: OF_HALT_IN_DEPOT = 2, rubidium@8798: OF_SERVICE_IF_NEEDED = 2, rubidium@8798: OF_NON_STOP = 3 truelight@1024: }; truelight@1024: pasky@1615: truelight@1024: /* Possible clone options */ truelight@1024: enum { truelight@1024: CO_SHARE = 0, truelight@1024: CO_COPY = 1, truelight@1024: CO_UNSHARE = 2 truelight@1024: }; truelight@1024: rubidium@7887: struct Order; rubidium@7887: DECLARE_OLD_POOL(Order, Order, 6, 1000) rubidium@7887: truelight@1024: /* If you change this, keep in mind that it is saved on 3 places: tron@4077: * - Load_ORDR, all the global orders tron@4077: * - Vehicle -> current_order maedhros@7476: * - REF_ORDER (all REFs are currently limited to 16 bits!!) tron@4077: */ rubidium@7887: struct Order : PoolItem { rubidium@6574: Order *next; ///< Pointer to next order. If NULL, end of list tron@6189: rubidium@5838: OrderTypeByte type; truelight@1024: uint8 flags; truelight@4389: DestinationID dest; ///< The destionation of the order. truelight@1024: bjarni@4712: CargoID refit_cargo; // Refit CargoID bjarni@4712: byte refit_subtype; // Refit subtype bjarni@6589: maedhros@7476: uint16 wait_time; ///< How long in ticks to wait at the destination. maedhros@7476: uint16 travel_time; ///< How long in ticks the journey to this destination should take. maedhros@7476: rubidium@7887: Order() : refit_cargo(CT_NO_REFIT) {} rubidium@7887: ~Order() { this->type = OT_NOTHING; } rubidium@7887: rubidium@7992: /** rubidium@7992: * Check if a Order really exists. rubidium@7992: */ rubidium@7992: inline bool IsValid() const { return this->type != OT_NOTHING; } rubidium@7992: bjarni@6589: void Free(); bjarni@6589: void FreeChain(); rubidium@6574: }; truelight@1024: rubidium@8149: struct BackuppedOrders { rubidium@8818: BackuppedOrders() : order(NULL), name(NULL) { } rubidium@8818: ~BackuppedOrders() { free(order); free(name); } Darkvater@2433: truelight@1024: VehicleID clone; truelight@4391: VehicleOrderID orderindex; glx@9146: GroupID group; rubidium@8149: Order *order; truelight@1024: uint16 service_interval; peter1138@8754: char *name; rubidium@6574: }; truelight@1024: rubidium@8764: extern TileIndex _backup_orders_tile; rubidium@8764: extern BackuppedOrders _backup_orders_data; truelight@1024: rubidium@6573: static inline VehicleOrderID GetMaxOrderIndex() truelight@4354: { truelight@4354: /* TODO - This isn't the real content of the function, but truelight@4354: * with the new pool-system this will be replaced with one that matthijs@5247: * _really_ returns the highest index. Now it just returns truelight@4354: * the next safe value we are sure about everything is below. truelight@4354: */ matthijs@5247: return GetOrderPoolSize() - 1; matthijs@5247: } matthijs@5247: rubidium@6573: static inline VehicleOrderID GetNumOrders() matthijs@5247: { truelight@4354: return GetOrderPoolSize(); truelight@4354: } truelight@4354: bjarni@6589: inline void Order::Free() truelight@4384: { rubidium@7887: this->type = OT_NOTHING; rubidium@7887: this->flags = 0; rubidium@7887: this->dest = 0; rubidium@7887: this->next = NULL; truelight@4384: } truelight@4384: bjarni@6589: inline void Order::FreeChain() bjarni@6589: { bjarni@6589: if (next != NULL) next->FreeChain(); rubidium@7887: delete this; bjarni@6589: } bjarni@6589: bjarni@6589: #define FOR_ALL_ORDERS_FROM(order, start) for (order = GetOrder(start); order != NULL; order = (order->index + 1U < GetOrderPoolSize()) ? GetOrder(order->index + 1U) : NULL) if (order->IsValid()) truelight@1314: #define FOR_ALL_ORDERS(order) FOR_ALL_ORDERS_FROM(order, 0) truelight@1314: truelight@1024: truelight@1024: #define FOR_VEHICLE_ORDERS(v, order) for (order = v->orders; order != NULL; order = order->next) truelight@1024: truelight@1024: static inline bool HasOrderPoolFree(uint amount) truelight@1024: { truelight@1043: const Order *order; truelight@1024: truelight@1314: /* There is always room if not all blocks in the pool are reserved */ rubidium@7871: if (_Order_pool.CanAllocateMoreBlocks()) return true; truelight@1314: rubidium@7871: FOR_ALL_ORDERS(order) if (!order->IsValid() && --amount == 0) return true; truelight@1024: truelight@1024: return false; truelight@1024: } truelight@1024: truelight@1024: truelight@1024: /* Pack and unpack routines */ truelight@1024: truelight@1024: static inline uint32 PackOrder(const Order *order) truelight@1024: { tron@4527: return order->dest << 16 | order->flags << 8 | order->type; truelight@1024: } truelight@1024: truelight@1024: static inline Order UnpackOrder(uint32 packed) truelight@1024: { truelight@1024: Order order; truelight@4351: order.type = (OrderType)GB(packed, 0, 8); tron@2140: order.flags = GB(packed, 8, 8); tron@4527: order.dest = GB(packed, 16, 16); truelight@1024: order.next = NULL; hackykid@1884: order.index = 0; // avoid compiler warning bjarni@4780: order.refit_cargo = CT_NO_REFIT; bjarni@4715: order.refit_subtype = 0; maedhros@7476: order.wait_time = 0; maedhros@7476: order.travel_time = 0; truelight@1024: return order; truelight@1024: } truelight@1024: truelight@1024: /* Functions */ rubidium@8149: void BackupVehicleOrders(const Vehicle *v, BackuppedOrders *order = &_backup_orders_data); rubidium@8149: void RestoreVehicleOrders(const Vehicle *v, const BackuppedOrders *order = &_backup_orders_data); truelight@4389: void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination); truelight@1024: void InvalidateVehicleOrder(const Vehicle *v); truelight@1024: bool VehicleHasDepotOrders(const Vehicle *v); tron@3140: void CheckOrders(const Vehicle*); truelight@1024: void DeleteVehicleOrders(Vehicle *v); truelight@1024: void AssignOrder(Order *order, Order data); tron@2630: bool CheckForValidOrders(const Vehicle* v); truelight@1024: truelight@1024: Order UnpackOldOrder(uint16 packed); truelight@1024: rubidium@8707: #define MIN_SERVINT_PERCENT 5 rubidium@8707: #define MAX_SERVINT_PERCENT 90 rubidium@8707: #define MIN_SERVINT_DAYS 30 rubidium@8707: #define MAX_SERVINT_DAYS 800 rubidium@8707: rubidium@8707: /** rubidium@8707: * Get the service interval domain. rubidium@8707: * Get the new proposed service interval for the vehicle is indeed, clamped rubidium@8707: * within the given bounds. @see MIN_SERVINT_PERCENT ,etc. rubidium@8707: * @param index proposed service interval rubidium@8707: * @return service interval rubidium@8707: */ rubidium@8707: Date GetServiceIntervalClamped(uint index); rubidium@8707: truelight@1024: #endif /* ORDER_H */