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