rubidium@9837: /* $Id$ */ rubidium@9837: rubidium@10455: /** @file order_base.h Base class for orders. */ rubidium@9837: rubidium@9837: #ifndef ORDER_BASE_H rubidium@9837: #define ORDER_BASE_H rubidium@9837: rubidium@9837: #include "order_type.h" rubidium@9837: #include "oldpool.h" rubidium@9837: #include "core/bitmath_func.hpp" rubidium@9837: #include "cargo_type.h" rubidium@9869: #include "depot_type.h" rubidium@9869: #include "station_type.h" rubidium@9869: #include "vehicle_type.h" rubidium@9869: #include "waypoint_type.h" rubidium@9837: rubidium@9837: DECLARE_OLD_POOL(Order, Order, 6, 1000) rubidium@9837: rubidium@9837: /* If you change this, keep in mind that it is saved on 3 places: rubidium@9837: * - Load_ORDR, all the global orders rubidium@9837: * - Vehicle -> current_order rubidium@9837: * - REF_ORDER (all REFs are currently limited to 16 bits!!) rubidium@9837: */ rubidium@9837: struct Order : PoolItem { rubidium@9869: private: rubidium@9869: friend const struct SaveLoad *GetVehicleDescription(VehicleType vt); ///< Saving and loading the current order of vehicles. rubidium@9869: friend void Load_VEHS(); ///< Loading of ancient vehicles. rubidium@9869: friend const struct SaveLoad *GetOrderDescription(); ///< Saving and loading of orders. rubidium@9837: rubidium@10142: uint8 type; ///< The type of order + non-stop flags rubidium@10142: uint8 flags; ///< Load/unload types, depot order/action types. rubidium@9869: DestinationID dest; ///< The destination of the order. rubidium@9837: rubidium@9869: CargoID refit_cargo; ///< Refit CargoID rubidium@9869: byte refit_subtype; ///< Refit subtype rubidium@9869: rubidium@9869: public: rubidium@9869: Order *next; ///< Pointer to next order. If NULL, end of list rubidium@9837: rubidium@9837: uint16 wait_time; ///< How long in ticks to wait at the destination. rubidium@9837: uint16 travel_time; ///< How long in ticks the journey to this destination should take. rubidium@9837: rubidium@9837: Order() : refit_cargo(CT_NO_REFIT) {} rubidium@9837: ~Order() { this->type = OT_NOTHING; } rubidium@9837: rubidium@9837: /** rubidium@9869: * Create an order based on a packed representation of that order. rubidium@9869: * @param packed the packed representation. rubidium@9869: */ rubidium@9869: Order(uint32 packed); rubidium@9869: rubidium@9869: /** rubidium@9837: * Check if a Order really exists. rubidium@9869: * @return true if the order is valid. rubidium@9837: */ rubidium@9837: inline bool IsValid() const { return this->type != OT_NOTHING; } rubidium@9837: rubidium@9869: /** rubidium@9869: * Check whether this order is of the given type. rubidium@9869: * @param type the type to check against. rubidium@9869: * @return true if the order matches. rubidium@9869: */ rubidium@10142: inline bool IsType(OrderType type) const { return this->GetType() == type; } rubidium@9869: rubidium@9869: /** rubidium@9869: * Get the type of order of this order. rubidium@9869: * @return the order type. rubidium@9869: */ rubidium@10142: inline OrderType GetType() const { return (OrderType)GB(this->type, 0, 4); } rubidium@9869: rubidium@9869: /** rubidium@9869: * 'Free' the order rubidium@9869: * @note ONLY use on "current_order" vehicle orders! rubidium@9869: */ rubidium@9837: void Free(); rubidium@9869: rubidium@9869: /** rubidium@9869: * Makes this order a Go To Station order. rubidium@9869: * @param destsination the station to go to. rubidium@9869: */ rubidium@9869: void MakeGoToStation(StationID destination); rubidium@9869: rubidium@9869: /** rubidium@9869: * Makes this order a Go To Depot order. rubidium@9869: * @param destination the depot to go to. rubidium@9869: * @param order is this order a 'default' order, or an overriden vehicle order? rubidium@9869: * @param cargo the cargo type to change to. rubidium@9869: * @param subtype the subtype to change to. rubidium@9869: */ rubidium@10142: void MakeGoToDepot(DepotID destination, OrderDepotTypeFlags order, CargoID cargo = CT_NO_REFIT, byte subtype = 0); rubidium@9869: rubidium@9869: /** rubidium@9869: * Makes this order a Go To Waypoint order. rubidium@9869: * @param destination the waypoint to go to. rubidium@9869: */ rubidium@9869: void MakeGoToWaypoint(WaypointID destination); rubidium@9869: rubidium@9869: /** rubidium@9869: * Makes this order a Loading order. rubidium@9869: * @param ordered is this an ordered stop? rubidium@9869: */ rubidium@9869: void MakeLoading(bool ordered); rubidium@9869: rubidium@9869: /** rubidium@9869: * Makes this order a Leave Station order. rubidium@9869: */ rubidium@9869: void MakeLeaveStation(); rubidium@9869: rubidium@9869: /** rubidium@9869: * Makes this order a Dummy order. rubidium@9869: */ rubidium@9869: void MakeDummy(); rubidium@9869: rubidium@9869: /** rubidium@10142: * Makes this order an conditional order. rubidium@10142: * @param order the order to jump to. rubidium@10142: */ rubidium@10142: void MakeConditional(VehicleOrderID order); rubidium@10142: rubidium@10142: /** rubidium@9869: * Free a complete order chain. rubidium@9869: * @note do not use on "current_order" vehicle orders! rubidium@9869: */ rubidium@9837: void FreeChain(); rubidium@9869: rubidium@9869: /** rubidium@9869: * Gets the destination of this order. rubidium@9869: * @pre IsType(OT_GOTO_WAYPOINT) || IsType(OT_GOTO_DEPOT) || IsType(OT_GOTO_STATION). rubidium@9869: * @return the destination of the order. rubidium@9869: */ rubidium@9869: inline DestinationID GetDestination() const { return this->dest; } rubidium@9869: rubidium@9869: /** rubidium@9869: * Sets the destination of this order. rubidium@9869: * @param destination the new destination of the order. rubidium@9869: * @pre IsType(OT_GOTO_WAYPOINT) || IsType(OT_GOTO_DEPOT) || IsType(OT_GOTO_STATION). rubidium@9869: */ rubidium@9869: inline void SetDestination(DestinationID destination) { this->dest = destination; } rubidium@9869: rubidium@9869: /** rubidium@9869: * Is this order a refit order. rubidium@9869: * @pre IsType(OT_GOTO_DEPOT) rubidium@9869: * @return true if a refit should happen. rubidium@9869: */ rubidium@9869: inline bool IsRefit() const { return this->refit_cargo < NUM_CARGO; } rubidium@9869: rubidium@9869: /** rubidium@9869: * Get the cargo to to refit to. rubidium@9869: * @pre IsType(OT_GOTO_DEPOT) rubidium@9869: * @return the cargo type. rubidium@9869: */ rubidium@9869: inline CargoID GetRefitCargo() const { return this->refit_cargo; } rubidium@9869: rubidium@9869: /** rubidium@9869: * Get the cargo subtype to to refit to. rubidium@9869: * @pre IsType(OT_GOTO_DEPOT) rubidium@9869: * @return the cargo subtype. rubidium@9869: */ rubidium@9869: inline byte GetRefitSubtype() const { return this->refit_subtype; } rubidium@9869: rubidium@9869: /** rubidium@9869: * Make this depot order also a refit order. rubidium@9869: * @param cargo the cargo type to change to. rubidium@9869: * @param subtype the subtype to change to. rubidium@9869: * @pre IsType(OT_GOTO_DEPOT). rubidium@9869: */ rubidium@9869: void SetRefit(CargoID cargo, byte subtype = 0); rubidium@9869: rubidium@9869: /** How must the consist be loaded? */ rubidium@10142: inline OrderLoadFlags GetLoadType() const { return (OrderLoadFlags)GB(this->flags, 4, 4); } rubidium@9869: /** How must the consist be unloaded? */ rubidium@10142: inline OrderUnloadFlags GetUnloadType() const { return (OrderUnloadFlags)GB(this->flags, 0, 4); } rubidium@9869: /** Where must we stop? */ rubidium@10142: inline OrderNonStopFlags GetNonStopType() const { return (OrderNonStopFlags)GB(this->type, 6, 2); } rubidium@9869: /** What caused us going to the depot? */ rubidium@10142: inline OrderDepotTypeFlags GetDepotOrderType() const { return (OrderDepotTypeFlags)GB(this->flags, 0, 4); } rubidium@9869: /** What are we going to do when in the depot. */ rubidium@10142: inline OrderDepotActionFlags GetDepotActionType() const { return (OrderDepotActionFlags)GB(this->flags, 4, 4); } rubidium@10142: /** What variable do we have to compare? */ rubidium@10142: inline OrderConditionVariable GetConditionVariable() const { return (OrderConditionVariable)GB(this->dest, 11, 5); } rubidium@10142: /** What is the comparator to use? */ rubidium@10142: inline OrderConditionComparator GetConditionComparator() const { return (OrderConditionComparator)GB(this->type, 5, 3); } rubidium@10142: /** Get the order to skip to. */ rubidium@10142: inline VehicleOrderID GetConditionSkipToOrder() const { return this->flags; } rubidium@10142: /** Get the value to base the skip on. */ rubidium@10142: inline uint16 GetConditionValue() const { return GB(this->dest, 0, 11); } rubidium@9869: rubidium@9869: /** Set how the consist must be loaded. */ rubidium@10142: inline void SetLoadType(OrderLoadFlags load_type) { SB(this->flags, 4, 4, load_type); } rubidium@9869: /** Set how the consist must be unloaded. */ rubidium@10142: inline void SetUnloadType(OrderUnloadFlags unload_type) { SB(this->flags, 0, 4, unload_type); } rubidium@9869: /** Set whether we must stop at stations or not. */ rubidium@10142: inline void SetNonStopType(OrderNonStopFlags non_stop_type) { SB(this->type, 6, 2, non_stop_type); } rubidium@9869: /** Set the cause to go to the depot. */ rubidium@10142: inline void SetDepotOrderType(OrderDepotTypeFlags depot_order_type) { SB(this->flags, 0, 4, depot_order_type); } rubidium@9869: /** Set what we are going to do in the depot. */ rubidium@10142: inline void SetDepotActionType(OrderDepotActionFlags depot_service_type) { SB(this->flags, 4, 4, depot_service_type); } rubidium@10142: /** Set variable we have to compare. */ rubidium@10142: inline void SetConditionVariable(OrderConditionVariable condition_variable) { SB(this->dest, 11, 5, condition_variable); } rubidium@10142: /** Set the comparator to use. */ rubidium@10142: inline void SetConditionComparator(OrderConditionComparator condition_comparator) { SB(this->type, 5, 3, condition_comparator); } rubidium@10142: /** Get the order to skip to. */ rubidium@10142: inline void SetConditionSkipToOrder(VehicleOrderID order_id) { this->flags = order_id; } rubidium@10142: /** Set the value to base the skip on. */ rubidium@10142: inline void SetConditionValue(uint16 value) { SB(this->dest, 0, 11, value); } rubidium@9869: rubidium@9869: bool ShouldStopAtStation(const Vehicle *v, StationID station) const; rubidium@9869: rubidium@9869: /** rubidium@9869: * Assign the given order to this one. rubidium@9869: * @param other the data to copy (except next pointer). rubidium@9869: */ rubidium@9869: void AssignOrder(const Order &other); rubidium@9869: rubidium@9869: /** rubidium@9869: * Does this order have the same type, flags and destination? rubidium@9869: * @param other the second order to compare to. rubidium@9869: * @return true if the type, flags and destination match. rubidium@9869: */ rubidium@9869: bool Equals(const Order &other) const; rubidium@9869: rubidium@9869: /** rubidium@9869: * Pack this order into a 32 bits integer, or actually only rubidium@9869: * the type, flags and destination. rubidium@9869: * @return the packed representation. rubidium@9869: * @note unpacking is done in the constructor. rubidium@9869: */ rubidium@9869: uint32 Pack() const; rubidium@10142: rubidium@10142: /** rubidium@10142: * Converts this order from an old savegame's version; rubidium@10142: * it moves all bits to the new location. rubidium@10142: */ rubidium@10142: void ConvertFromOldSavegame(); rubidium@9837: }; rubidium@9837: rubidium@9837: static inline VehicleOrderID GetMaxOrderIndex() rubidium@9837: { rubidium@9837: /* TODO - This isn't the real content of the function, but rubidium@9837: * with the new pool-system this will be replaced with one that rubidium@9837: * _really_ returns the highest index. Now it just returns rubidium@9837: * the next safe value we are sure about everything is below. rubidium@9837: */ rubidium@9837: return GetOrderPoolSize() - 1; rubidium@9837: } rubidium@9837: rubidium@9837: static inline VehicleOrderID GetNumOrders() rubidium@9837: { rubidium@9837: return GetOrderPoolSize(); rubidium@9837: } rubidium@9837: rubidium@9837: #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()) rubidium@9837: #define FOR_ALL_ORDERS(order) FOR_ALL_ORDERS_FROM(order, 0) rubidium@9837: rubidium@9837: rubidium@9837: #define FOR_VEHICLE_ORDERS(v, order) for (order = v->orders; order != NULL; order = order->next) rubidium@9837: rubidium@9869: /* (Un)pack routines */ rubidium@9837: Order UnpackOldOrder(uint16 packed); rubidium@9837: rubidium@9837: #endif /* ORDER_H */