Changeset - r20078:a7a34cf316df
[Not reviewed]
master
0 7 0
frosch - 11 years ago 2013-02-24 16:41:51
frosch@openttd.org
(svn r25041) -Remove [FS#3764-ish]: ordered refit with subtypes, since the cases where it worked were corner cases rather than the general case.
7 files changed with 21 insertions and 35 deletions:
0 comments (0 inline, 0 general)
src/economy.cpp
Show inline comments
 
@@ -1420,91 +1420,89 @@ static void LoadUnloadVehicle(Vehicle *f
 
				unloading_time += amount_unloaded;
 

	
 
				/* Deliver goods to the station */
 
				st->time_since_unload = 0;
 
			}
 

	
 
			if (_settings_game.order.gradual_loading && remaining) {
 
				completely_emptied = false;
 
			} else {
 
				/* We have finished unloading (cargo count == 0) */
 
				ClrBit(v->vehicle_flags, VF_CARGO_UNLOADING);
 
			}
 

	
 
			continue;
 
		}
 

	
 
		/* Do not pick up goods when we have no-load set or loading is stopped. */
 
		if (front->current_order.GetLoadType() & OLFB_NO_LOAD || HasBit(front->vehicle_flags, VF_STOP_LOADING)) continue;
 

	
 
		/* This order has a refit, if this is the first vehicle part carrying cargo and the whole vehicle is empty, try refitting. */
 
		if (front->current_order.IsRefit() && artic_part == 1 && IsArticulatedVehicleEmpty(v) &&
 
				(v->type != VEH_AIRCRAFT || (Aircraft::From(v)->IsNormalAircraft() && v->Next()->cargo.Count() == 0))) {
 
			Vehicle *v_start = v->GetFirstEnginePart();
 
			CargoID new_cid = front->current_order.GetRefitCargo();
 
			byte new_subtype = front->current_order.GetRefitSubtype();
 

	
 
			/* Remove old capacity from consist capacity */
 
			consist_capleft[v_start->cargo_type] -= v_start->cargo_cap;
 
			for (Vehicle *w = v_start; w->HasArticulatedPart(); ) {
 
				w = w->GetNextArticulatedPart();
 
				consist_capleft[w->cargo_type] -= w->cargo_cap;
 
			}
 

	
 
			Backup<CompanyByte> cur_company(_current_company, front->owner, FILE_LINE);
 

	
 
			/* Check if all articulated parts are empty and collect refit mask. */
 
			uint32 refit_mask = v->GetEngine()->info.refit_mask;
 
			Vehicle *w = v_start;
 
			while (w->HasArticulatedPart()) {
 
				w = w->GetNextArticulatedPart();
 
				if (w->cargo.Count() > 0) new_cid = CT_NO_REFIT;
 
				refit_mask |= EngInfo(w->engine_type)->refit_mask;
 
			}
 

	
 
			if (new_cid == CT_AUTO_REFIT) {
 
				/* Get refittable cargo type with the most waiting cargo. */
 
				int amount = 0;
 
				CargoID cid;
 
				FOR_EACH_SET_CARGO_ID(cid, refit_mask) {
 
					/* Consider refitting to this cargo, if other vehicles of the consist cannot
 
					 * already take the cargo without refitting */
 
					if ((int)st->goods[cid].cargo.Count() > (int)consist_capleft[cid] + amount) {
 
						/* Try to find out if auto-refitting would succeed. In case the refit is allowed,
 
						 * the returned refit capacity will be greater than zero. */
 
						new_subtype = GetBestFittingSubType(v, v, cid);
 
						DoCommand(v_start->tile, v_start->index, cid | 1U << 6 | new_subtype << 8 | 1U << 16, DC_QUERY_COST, GetCmdRefitVeh(v_start)); // Auto-refit and only this vehicle including artic parts.
 
						DoCommand(v_start->tile, v_start->index, cid | 1U << 6 | 0xFF << 8 | 1U << 16, DC_QUERY_COST, GetCmdRefitVeh(v_start)); // Auto-refit and only this vehicle including artic parts.
 
						if (_returned_refit_capacity > 0) {
 
							amount = st->goods[cid].cargo.Count() - consist_capleft[cid];
 
							new_cid = cid;
 
						}
 
					}
 
				}
 
			}
 

	
 
			/* Refit if given a valid cargo. */
 
			if (new_cid < NUM_CARGO) {
 
				CommandCost cost = DoCommand(v_start->tile, v_start->index, new_cid | 1U << 6 | new_subtype << 8 | 1U << 16, DC_EXEC, GetCmdRefitVeh(v_start)); // Auto-refit and only this vehicle including artic parts.
 
				CommandCost cost = DoCommand(v_start->tile, v_start->index, new_cid | 1U << 6 | 0xFF << 8 | 1U << 16, DC_EXEC, GetCmdRefitVeh(v_start)); // Auto-refit and only this vehicle including artic parts.
 
				if (cost.Succeeded()) front->profit_this_year -= cost.GetCost() << 8;
 
				ge = &st->goods[v->cargo_type];
 
			}
 

	
 
			/* Add new capacity to consist capacity and reserve cargo */
 
			w = v_start;
 
			do {
 
				st->goods[w->cargo_type].cargo.Reserve(w->cargo_cap, &w->cargo, st->xy);
 
				consist_capleft[w->cargo_type] += w->cargo_cap - w->cargo.Count();
 
				w = w->HasArticulatedPart() ? w->GetNextArticulatedPart() : NULL;
 
			} while (w != NULL);
 

	
 
			cur_company.Restore();
 
		}
 

	
 
		/* update stats */
 
		int t;
 
		switch (front->type) {
 
			case VEH_TRAIN: /* FALL THROUGH */
 
			case VEH_SHIP:
 
				t = front->vcache.cached_max_speed;
 
				break;
 

	
 
			case VEH_ROAD:
src/order_base.h
Show inline comments
 
@@ -21,79 +21,78 @@
 
#include "vehicle_type.h"
 
#include "date_type.h"
 

	
 
typedef Pool<Order, OrderID, 256, 64000> OrderPool;
 
typedef Pool<OrderList, OrderListID, 128, 64000> OrderListPool;
 
extern OrderPool _order_pool;
 
extern OrderListPool _orderlist_pool;
 

	
 
/* If you change this, keep in mind that it is saved on 3 places:
 
 * - Load_ORDR, all the global orders
 
 * - Vehicle -> current_order
 
 * - REF_ORDER (all REFs are currently limited to 16 bits!!)
 
 */
 
struct Order : OrderPool::PoolItem<&_order_pool> {
 
private:
 
	friend const struct SaveLoad *GetVehicleDescription(VehicleType vt); ///< Saving and loading the current order of vehicles.
 
	friend void Load_VEHS();                                             ///< Loading of ancient vehicles.
 
	friend const struct SaveLoad *GetOrderDescription();                 ///< Saving and loading of orders.
 

	
 
	uint8 type;           ///< The type of order + non-stop flags
 
	uint8 flags;          ///< Load/unload types, depot order/action types.
 
	DestinationID dest;   ///< The destination of the order.
 

	
 
	CargoID refit_cargo;  ///< Refit CargoID
 
	byte refit_subtype;   ///< Refit subtype
 

	
 
public:
 
	Order *next;          ///< Pointer to next order. If NULL, end of list
 

	
 
	uint16 wait_time;    ///< How long in ticks to wait at the destination.
 
	uint16 travel_time;  ///< How long in ticks the journey to this destination should take.
 
	uint16 max_speed;    ///< How fast the vehicle may go on the way to the destination.
 

	
 
	Order() : refit_cargo(CT_NO_REFIT), max_speed(UINT16_MAX) {}
 
	~Order();
 

	
 
	Order(uint32 packed);
 

	
 
	/**
 
	 * Check whether this order is of the given type.
 
	 * @param type the type to check against.
 
	 * @return true if the order matches.
 
	 */
 
	inline bool IsType(OrderType type) const { return this->GetType() == type; }
 

	
 
	/**
 
	 * Get the type of order of this order.
 
	 * @return the order type.
 
	 */
 
	inline OrderType GetType() const { return (OrderType)GB(this->type, 0, 4); }
 

	
 
	void Free();
 

	
 
	void MakeGoToStation(StationID destination);
 
	void MakeGoToDepot(DepotID destination, OrderDepotTypeFlags order, OrderNonStopFlags non_stop_type = ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS, OrderDepotActionFlags action = ODATF_SERVICE_ONLY, CargoID cargo = CT_NO_REFIT, byte subtype = 0);
 
	void MakeGoToDepot(DepotID destination, OrderDepotTypeFlags order, OrderNonStopFlags non_stop_type = ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS, OrderDepotActionFlags action = ODATF_SERVICE_ONLY, CargoID cargo = CT_NO_REFIT);
 
	void MakeGoToWaypoint(StationID destination);
 
	void MakeLoading(bool ordered);
 
	void MakeLeaveStation();
 
	void MakeDummy();
 
	void MakeConditional(VehicleOrderID order);
 
	void MakeImplicit(StationID destination);
 

	
 
	/**
 
	 * Is this a 'goto' order with a real destination?
 
	 * @return True if the type is either #OT_GOTO_WAYPOINT, #OT_GOTO_DEPOT or #OT_GOTO_STATION.
 
	 */
 
	inline bool IsGotoOrder() const
 
	{
 
		return IsType(OT_GOTO_WAYPOINT) || IsType(OT_GOTO_DEPOT) || IsType(OT_GOTO_STATION);
 
	}
 

	
 
	/**
 
	 * Gets the destination of this order.
 
	 * @pre IsType(OT_GOTO_WAYPOINT) || IsType(OT_GOTO_DEPOT) || IsType(OT_GOTO_STATION).
 
	 * @return the destination of the order.
 
	 */
 
	inline DestinationID GetDestination() const { return this->dest; }
 

	
 
	/**
 
@@ -103,56 +102,49 @@ public:
 
	 */
 
	inline void SetDestination(DestinationID destination) { this->dest = destination; }
 

	
 
	/**
 
	 * Is this order a refit order.
 
	 * @pre IsType(OT_GOTO_DEPOT) || IsType(OT_GOTO_STATION)
 
	 * @return true if a refit should happen.
 
	 */
 
	inline bool IsRefit() const { return this->refit_cargo < NUM_CARGO || this->refit_cargo == CT_AUTO_REFIT; }
 

	
 
	/**
 
	 * Is this order a auto-refit order.
 
	 * @pre IsType(OT_GOTO_DEPOT) || IsType(OT_GOTO_STATION)
 
	 * @return true if a auto-refit should happen.
 
	 */
 
	inline bool IsAutoRefit() const { return this->refit_cargo == CT_AUTO_REFIT; }
 

	
 
	/**
 
	 * Get the cargo to to refit to.
 
	 * @pre IsType(OT_GOTO_DEPOT) || IsType(OT_GOTO_STATION)
 
	 * @return the cargo type.
 
	 */
 
	inline CargoID GetRefitCargo() const { return this->refit_cargo; }
 

	
 
	/**
 
	 * Get the cargo subtype to to refit to.
 
	 * @pre IsType(OT_GOTO_DEPOT) || IsType(OT_GOTO_STATION)
 
	 * @return the cargo subtype.
 
	 */
 
	inline byte GetRefitSubtype() const { return this->refit_subtype; }
 

	
 
	void SetRefit(CargoID cargo, byte subtype = 0);
 
	void SetRefit(CargoID cargo);
 

	
 
	/** How must the consist be loaded? */
 
	inline OrderLoadFlags GetLoadType() const { return (OrderLoadFlags)GB(this->flags, 4, 4); }
 
	/** How must the consist be unloaded? */
 
	inline OrderUnloadFlags GetUnloadType() const { return (OrderUnloadFlags)GB(this->flags, 0, 4); }
 
	/** At which stations must we stop? */
 
	inline OrderNonStopFlags GetNonStopType() const { return (OrderNonStopFlags)GB(this->type, 6, 2); }
 
	/** Where must we stop at the platform? */
 
	inline OrderStopLocation GetStopLocation() const { return (OrderStopLocation)GB(this->type, 4, 2); }
 
	/** What caused us going to the depot? */
 
	inline OrderDepotTypeFlags GetDepotOrderType() const { return (OrderDepotTypeFlags)GB(this->flags, 0, 4); }
 
	/** What are we going to do when in the depot. */
 
	inline OrderDepotActionFlags GetDepotActionType() const { return (OrderDepotActionFlags)GB(this->flags, 4, 4); }
 
	/** What variable do we have to compare? */
 
	inline OrderConditionVariable GetConditionVariable() const { return (OrderConditionVariable)GB(this->dest, 11, 5); }
 
	/** What is the comparator to use? */
 
	inline OrderConditionComparator GetConditionComparator() const { return (OrderConditionComparator)GB(this->type, 5, 3); }
 
	/** Get the order to skip to. */
 
	inline VehicleOrderID GetConditionSkipToOrder() const { return this->flags; }
 
	/** Get the value to base the skip on. */
 
	inline uint16 GetConditionValue() const { return GB(this->dest, 0, 11); }
 

	
 
	/** Set how the consist must be loaded. */
 
	inline void SetLoadType(OrderLoadFlags load_type) { SB(this->flags, 4, 4, load_type); }
src/order_cmd.cpp
Show inline comments
 
@@ -62,58 +62,57 @@ void Order::Free()
 
	this->type  = OT_NOTHING;
 
	this->flags = 0;
 
	this->dest  = 0;
 
	this->next  = NULL;
 
}
 

	
 
/**
 
 * Makes this order a Go To Station order.
 
 * @param destination the station to go to.
 
 */
 
void Order::MakeGoToStation(StationID destination)
 
{
 
	this->type = OT_GOTO_STATION;
 
	this->flags = 0;
 
	this->dest = destination;
 
}
 

	
 
/**
 
 * Makes this order a Go To Depot order.
 
 * @param destination   the depot to go to.
 
 * @param order         is this order a 'default' order, or an overridden vehicle order?
 
 * @param non_stop_type how to get to the depot?
 
 * @param action        what to do in the depot?
 
 * @param cargo         the cargo type to change to.
 
 * @param subtype       the subtype to change to.
 
 */
 
void Order::MakeGoToDepot(DepotID destination, OrderDepotTypeFlags order, OrderNonStopFlags non_stop_type, OrderDepotActionFlags action, CargoID cargo, byte subtype)
 
void Order::MakeGoToDepot(DepotID destination, OrderDepotTypeFlags order, OrderNonStopFlags non_stop_type, OrderDepotActionFlags action, CargoID cargo)
 
{
 
	this->type = OT_GOTO_DEPOT;
 
	this->SetDepotOrderType(order);
 
	this->SetDepotActionType(action);
 
	this->SetNonStopType(non_stop_type);
 
	this->dest = destination;
 
	this->SetRefit(cargo, subtype);
 
	this->SetRefit(cargo);
 
}
 

	
 
/**
 
 * Makes this order a Go To Waypoint order.
 
 * @param destination the waypoint to go to.
 
 */
 
void Order::MakeGoToWaypoint(StationID destination)
 
{
 
	this->type = OT_GOTO_WAYPOINT;
 
	this->flags = 0;
 
	this->dest = destination;
 
}
 

	
 
/**
 
 * Makes this order a Loading order.
 
 * @param ordered is this an ordered stop?
 
 */
 
void Order::MakeLoading(bool ordered)
 
{
 
	this->type = OT_LOADING;
 
	if (!ordered) this->flags = 0;
 
}
 

	
 
/**
 
@@ -137,55 +136,53 @@ void Order::MakeDummy()
 
/**
 
 * Makes this order an conditional order.
 
 * @param order the order to jump to.
 
 */
 
void Order::MakeConditional(VehicleOrderID order)
 
{
 
	this->type = OT_CONDITIONAL;
 
	this->flags = order;
 
	this->dest = 0;
 
}
 

	
 
/**
 
 * Makes this order an implicit order.
 
 * @param destination the station to go to.
 
 */
 
void Order::MakeImplicit(StationID destination)
 
{
 
	this->type = OT_IMPLICIT;
 
	this->dest = destination;
 
}
 

	
 
/**
 
 * Make this depot/station order also a refit order.
 
 * @param cargo   the cargo type to change to.
 
 * @param subtype the subtype to change to.
 
 * @pre IsType(OT_GOTO_DEPOT) || IsType(OT_GOTO_STATION).
 
 */
 
void Order::SetRefit(CargoID cargo, byte subtype)
 
void Order::SetRefit(CargoID cargo)
 
{
 
	this->refit_cargo = cargo;
 
	this->refit_subtype = subtype;
 
}
 

	
 
/**
 
 * Does this order have the same type, flags and destination?
 
 * @param other the second order to compare to.
 
 * @return true if the type, flags and destination match.
 
 */
 
bool Order::Equals(const Order &other) const
 
{
 
	/* In case of go to nearest depot orders we need "only" compare the flags
 
	 * with the other and not the nearest depot order bit or the actual
 
	 * destination because those get clear/filled in during the order
 
	 * evaluation. If we do not do this the order will continuously be seen as
 
	 * a different order and it will try to find a "nearest depot" every tick. */
 
	if ((this->IsType(OT_GOTO_DEPOT) && this->type == other.type) &&
 
			((this->GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0 ||
 
			 (other.GetDepotActionType() & ODATFB_NEAREST_DEPOT) != 0)) {
 
		return this->GetDepotOrderType() == other.GetDepotOrderType() &&
 
				(this->GetDepotActionType() & ~ODATFB_NEAREST_DEPOT) == (other.GetDepotActionType() & ~ODATFB_NEAREST_DEPOT);
 
	}
 

	
 
	return this->type == other.type && this->flags == other.flags && this->dest == other.dest;
 
}
 

	
 
@@ -217,89 +214,87 @@ uint16 Order::MapOldOrder() const
 
			break;
 
		case OT_GOTO_DEPOT:
 
			if (!(this->GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) SetBit(order, 6);
 
			SetBit(order, 7);
 
			order |= GB(this->GetDestination(), 0, 8) << 8;
 
			break;
 
		case OT_LOADING:
 
			if (this->GetLoadType() & OLFB_FULL_LOAD) SetBit(order, 6);
 
			break;
 
	}
 
	return order;
 
}
 

	
 
/**
 
 * Create an order based on a packed representation of that order.
 
 * @param packed the packed representation.
 
 */
 
Order::Order(uint32 packed)
 
{
 
	this->type    = (OrderType)GB(packed,  0,  8);
 
	this->flags   = GB(packed,  8,  8);
 
	this->dest    = GB(packed, 16, 16);
 
	this->next    = NULL;
 
	this->refit_cargo   = CT_NO_REFIT;
 
	this->refit_subtype = 0;
 
	this->wait_time     = 0;
 
	this->travel_time   = 0;
 
	this->max_speed     = UINT16_MAX;
 
}
 

	
 
/**
 
 *
 
 * Updates the widgets of a vehicle which contains the order-data
 
 *
 
 */
 
void InvalidateVehicleOrder(const Vehicle *v, int data)
 
{
 
	SetWindowDirty(WC_VEHICLE_VIEW, v->index);
 

	
 
	if (data != 0) {
 
		/* Calls SetDirty() too */
 
		InvalidateWindowData(WC_VEHICLE_ORDERS,    v->index, data);
 
		InvalidateWindowData(WC_VEHICLE_TIMETABLE, v->index, data);
 
		return;
 
	}
 

	
 
	SetWindowDirty(WC_VEHICLE_ORDERS,    v->index);
 
	SetWindowDirty(WC_VEHICLE_TIMETABLE, v->index);
 
}
 

	
 
/**
 
 *
 
 * Assign data to an order (from another order)
 
 *   This function makes sure that the index is maintained correctly
 
 * @param other the data to copy (except next pointer).
 
 *
 
 */
 
void Order::AssignOrder(const Order &other)
 
{
 
	this->type  = other.type;
 
	this->flags = other.flags;
 
	this->dest  = other.dest;
 

	
 
	this->refit_cargo   = other.refit_cargo;
 
	this->refit_subtype = other.refit_subtype;
 

	
 
	this->wait_time   = other.wait_time;
 
	this->travel_time = other.travel_time;
 
	this->max_speed   = other.max_speed;
 
}
 

	
 
/**
 
 * Recomputes everything.
 
 * @param chain first order in the chain
 
 * @param v one of vehicle that is using this orderlist
 
 */
 
void OrderList::Initialize(Order *chain, Vehicle *v)
 
{
 
	this->first = chain;
 
	this->first_shared = v;
 

	
 
	this->num_orders = 0;
 
	this->num_manual_orders = 0;
 
	this->num_vehicles = 1;
 
	this->timetable_duration = 0;
 

	
 
	for (Order *o = this->first; o != NULL; o = o->next) {
 
		++this->num_orders;
 
		if (!o->IsType(OT_IMPLICIT)) ++this->num_manual_orders;
 
@@ -1566,92 +1561,90 @@ CommandCost CmdCloneOrder(TileIndex tile
 
					dst->orders.list = new OrderList(first, dst);
 
				}
 

	
 
				InvalidateVehicleOrder(dst, VIWD_REMOVE_ALL_ORDERS);
 

	
 
				InvalidateWindowClassesData(GetWindowClassForVehicleType(dst->type), 0);
 
			}
 
			break;
 
		}
 

	
 
		case CO_UNSHARE: return DecloneOrder(dst, flags);
 
		default: return CMD_ERROR;
 
	}
 

	
 
	return CommandCost();
 
}
 

	
 
/**
 
 * Add/remove refit orders from an order
 
 * @param tile Not used
 
 * @param flags operation to perform
 
 * @param p1 VehicleIndex of the vehicle having the order
 
 * @param p2 bitmask
 
 *   - bit 0-7 CargoID
 
 *   - bit 8-15 Cargo subtype
 
 *   - bit 16-23 number of order to modify
 
 * @param text unused
 
 * @return the cost of this operation or an error
 
 */
 
CommandCost CmdOrderRefit(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	VehicleID veh = GB(p1, 0, 20);
 
	VehicleOrderID order_number  = GB(p2, 16, 8);
 
	CargoID cargo = GB(p2, 0, 8);
 
	byte subtype  = GB(p2, 8, 8);
 

	
 
	if (cargo >= NUM_CARGO && cargo != CT_NO_REFIT && cargo != CT_AUTO_REFIT) return CMD_ERROR;
 

	
 
	const Vehicle *v = Vehicle::GetIfValid(veh);
 
	if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
 

	
 
	CommandCost ret = CheckOwnership(v->owner);
 
	if (ret.Failed()) return ret;
 

	
 
	Order *order = v->GetOrder(order_number);
 
	if (order == NULL) return CMD_ERROR;
 

	
 
	/* Automatic refit cargo is only supported for goto station orders. */
 
	if (cargo == CT_AUTO_REFIT && !order->IsType(OT_GOTO_STATION)) return CMD_ERROR;
 

	
 
	if (order->GetLoadType() & OLFB_NO_LOAD) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		order->SetRefit(cargo, subtype);
 
		order->SetRefit(cargo);
 

	
 
		/* Make the depot order an 'always go' order. */
 
		if (cargo != CT_NO_REFIT && order->IsType(OT_GOTO_DEPOT)) {
 
			order->SetDepotOrderType((OrderDepotTypeFlags)(order->GetDepotOrderType() & ~ODTFB_SERVICE));
 
			order->SetDepotActionType((OrderDepotActionFlags)(order->GetDepotActionType() & ~ODATFB_HALT));
 
		}
 

	
 
		for (Vehicle *u = v->FirstShared(); u != NULL; u = u->NextShared()) {
 
			/* Update any possible open window of the vehicle */
 
			InvalidateVehicleOrder(u, VIWD_MODIFY_ORDERS);
 

	
 
			/* If the vehicle already got the current depot set as current order, then update current order as well */
 
			if (u->cur_real_order_index == order_number && (u->current_order.GetDepotOrderType() & ODTFB_PART_OF_ORDERS)) {
 
				u->current_order.SetRefit(cargo, subtype);
 
				u->current_order.SetRefit(cargo);
 
			}
 
		}
 
	}
 

	
 
	return CommandCost();
 
}
 

	
 

	
 
/**
 
 *
 
 * Check the orders of a vehicle, to see if there are invalid orders and stuff
 
 *
 
 */
 
void CheckOrders(const Vehicle *v)
 
{
 
	/* Does the user wants us to check things? */
 
	if (_settings_client.gui.order_review_system == 0) return;
 

	
 
	/* Do nothing for crashed vehicles */
 
	if (v->vehstatus & VS_CRASHED) return;
 

	
 
	/* Do nothing for stopped vehicles if setting is '1' */
 
	if (_settings_client.gui.order_review_system == 1 && (v->vehstatus & VS_STOPPED)) return;
 

	
 
@@ -1911,49 +1904,49 @@ bool UpdateOrderDest(Vehicle *v, const O
 
	switch (order->GetType()) {
 
		case OT_GOTO_STATION:
 
			v->dest_tile = v->GetOrderStationLocation(order->GetDestination());
 
			return true;
 

	
 
		case OT_GOTO_DEPOT:
 
			if ((order->GetDepotOrderType() & ODTFB_SERVICE) && !v->NeedsServicing()) {
 
				assert(!pbs_look_ahead);
 
				UpdateVehicleTimetable(v, true);
 
				v->IncrementRealOrderIndex();
 
				break;
 
			}
 

	
 
			if (v->current_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) {
 
				/* We need to search for the nearest depot (hangar). */
 
				TileIndex location;
 
				DestinationID destination;
 
				bool reverse;
 

	
 
				if (v->FindClosestDepot(&location, &destination, &reverse)) {
 
					/* PBS reservations cannot reverse */
 
					if (pbs_look_ahead && reverse) return false;
 

	
 
					v->dest_tile = location;
 
					v->current_order.MakeGoToDepot(destination, v->current_order.GetDepotOrderType(), v->current_order.GetNonStopType(), (OrderDepotActionFlags)(v->current_order.GetDepotActionType() & ~ODATFB_NEAREST_DEPOT), v->current_order.GetRefitCargo(), v->current_order.GetRefitSubtype());
 
					v->current_order.MakeGoToDepot(destination, v->current_order.GetDepotOrderType(), v->current_order.GetNonStopType(), (OrderDepotActionFlags)(v->current_order.GetDepotActionType() & ~ODATFB_NEAREST_DEPOT), v->current_order.GetRefitCargo());
 

	
 
					/* If there is no depot in front, reverse automatically (trains only) */
 
					if (v->type == VEH_TRAIN && reverse) DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_REVERSE_TRAIN_DIRECTION);
 

	
 
					if (v->type == VEH_AIRCRAFT) {
 
						Aircraft *a = Aircraft::From(v);
 
						if (a->state == FLYING && a->targetairport != destination) {
 
							/* The aircraft is now heading for a different hangar than the next in the orders */
 
							extern void AircraftNextAirportPos_and_Order(Aircraft *a);
 
							AircraftNextAirportPos_and_Order(a);
 
						}
 
					}
 
					return true;
 
				}
 

	
 
				/* If there is no depot, we cannot help PBS either. */
 
				if (pbs_look_ahead) return false;
 

	
 
				UpdateVehicleTimetable(v, true);
 
				v->IncrementRealOrderIndex();
 
			} else {
 
				if (v->type != VEH_AIRCRAFT) {
 
					v->dest_tile = Depot::Get(order->GetDestination())->xy;
 
				}
src/saveload/order_sl.cpp
Show inline comments
 
@@ -86,49 +86,49 @@ static Order UnpackVersion4Order(uint16 
 
 * @param packed packed order
 
 * @return unpacked order
 
 */
 
Order UnpackOldOrder(uint16 packed)
 
{
 
	Order order = UnpackVersion4Order(packed);
 

	
 
	/*
 
	 * Sanity check
 
	 * TTD stores invalid orders as OT_NOTHING with non-zero flags/station
 
	 */
 
	if (order.IsType(OT_NOTHING) && packed != 0) order.MakeDummy();
 

	
 
	return order;
 
}
 

	
 
const SaveLoad *GetOrderDescription()
 
{
 
	static const SaveLoad _order_desc[] = {
 
		     SLE_VAR(Order, type,           SLE_UINT8),
 
		     SLE_VAR(Order, flags,          SLE_UINT8),
 
		     SLE_VAR(Order, dest,           SLE_UINT16),
 
		     SLE_REF(Order, next,           REF_ORDER),
 
		 SLE_CONDVAR(Order, refit_cargo,    SLE_UINT8,   36, SL_MAX_VERSION),
 
		 SLE_CONDVAR(Order, refit_subtype,  SLE_UINT8,   36, SL_MAX_VERSION),
 
		SLE_CONDNULL(1,                                  36, 181), // refit_subtype
 
		 SLE_CONDVAR(Order, wait_time,      SLE_UINT16,  67, SL_MAX_VERSION),
 
		 SLE_CONDVAR(Order, travel_time,    SLE_UINT16,  67, SL_MAX_VERSION),
 
		 SLE_CONDVAR(Order, max_speed,      SLE_UINT16, 172, SL_MAX_VERSION),
 

	
 
		/* Leftover from the minor savegame version stuff
 
		 * We will never use those free bytes, but we have to keep this line to allow loading of old savegames */
 
		SLE_CONDNULL(10,                                  5,  35),
 
		     SLE_END()
 
	};
 

	
 
	return _order_desc;
 
}
 

	
 
static void Save_ORDR()
 
{
 
	Order *order;
 

	
 
	FOR_ALL_ORDERS(order) {
 
		SlSetArrayIndex(order->index);
 
		SlObject(order, GetOrderDescription());
 
	}
 
}
 

	
 
static void Load_ORDR()
src/saveload/vehicle_sl.cpp
Show inline comments
 
@@ -618,49 +618,49 @@ const SaveLoad *GetVehicleDescription(Ve
 
		 SLE_CONDVAR(Vehicle, cargo_age_counter,     SLE_UINT16,                 162, SL_MAX_VERSION),
 

	
 
		     SLE_VAR(Vehicle, day_counter,           SLE_UINT8),
 
		     SLE_VAR(Vehicle, tick_counter,          SLE_UINT8),
 
		 SLE_CONDVAR(Vehicle, running_ticks,         SLE_UINT8,                   88, SL_MAX_VERSION),
 

	
 
		     SLE_VAR(Vehicle, cur_implicit_order_index,  SLE_UINT8),
 
		 SLE_CONDVAR(Vehicle, cur_real_order_index,  SLE_UINT8,                  158, SL_MAX_VERSION),
 
		/* num_orders is now part of OrderList and is not saved but counted */
 
		SLE_CONDNULL(1,                                                            0, 104),
 

	
 
		/* This next line is for version 4 and prior compatibility.. it temporarily reads
 
		 type and flags (which were both 4 bits) into type. Later on this is
 
		 converted correctly */
 
		 SLE_CONDVAR(Vehicle, current_order.type,    SLE_UINT8,                    0,   4),
 
		 SLE_CONDVAR(Vehicle, current_order.dest,    SLE_FILE_U8  | SLE_VAR_U16,   0,   4),
 

	
 
		/* Orders for version 5 and on */
 
		 SLE_CONDVAR(Vehicle, current_order.type,    SLE_UINT8,                    5, SL_MAX_VERSION),
 
		 SLE_CONDVAR(Vehicle, current_order.flags,   SLE_UINT8,                    5, SL_MAX_VERSION),
 
		 SLE_CONDVAR(Vehicle, current_order.dest,    SLE_UINT16,                   5, SL_MAX_VERSION),
 

	
 
		/* Refit in current order */
 
		 SLE_CONDVAR(Vehicle, current_order.refit_cargo,   SLE_UINT8,             36, SL_MAX_VERSION),
 
		 SLE_CONDVAR(Vehicle, current_order.refit_subtype, SLE_UINT8,             36, SL_MAX_VERSION),
 
		SLE_CONDNULL(1,                                                           36, 181), // refit_subtype
 

	
 
		/* Timetable in current order */
 
		 SLE_CONDVAR(Vehicle, current_order.wait_time,     SLE_UINT16,            67, SL_MAX_VERSION),
 
		 SLE_CONDVAR(Vehicle, current_order.travel_time,   SLE_UINT16,            67, SL_MAX_VERSION),
 
		 SLE_CONDVAR(Vehicle, current_order.max_speed,     SLE_UINT16,           174, SL_MAX_VERSION),
 
		 SLE_CONDVAR(Vehicle, timetable_start,       SLE_INT32,                  129, SL_MAX_VERSION),
 

	
 
		 SLE_CONDREF(Vehicle, orders,                REF_ORDER,                    0, 104),
 
		 SLE_CONDREF(Vehicle, orders,                REF_ORDERLIST,              105, SL_MAX_VERSION),
 

	
 
		 SLE_CONDVAR(Vehicle, age,                   SLE_FILE_U16 | SLE_VAR_I32,   0,  30),
 
		 SLE_CONDVAR(Vehicle, age,                   SLE_INT32,                   31, SL_MAX_VERSION),
 
		 SLE_CONDVAR(Vehicle, max_age,               SLE_FILE_U16 | SLE_VAR_I32,   0,  30),
 
		 SLE_CONDVAR(Vehicle, max_age,               SLE_INT32,                   31, SL_MAX_VERSION),
 
		 SLE_CONDVAR(Vehicle, date_of_last_service,  SLE_FILE_U16 | SLE_VAR_I32,   0,  30),
 
		 SLE_CONDVAR(Vehicle, date_of_last_service,  SLE_INT32,                   31, SL_MAX_VERSION),
 
		 SLE_CONDVAR(Vehicle, service_interval,      SLE_UINT16,                   0,  30),
 
		 SLE_CONDVAR(Vehicle, service_interval,      SLE_FILE_U32 | SLE_VAR_U16,  31, 179),
 
		 SLE_CONDVAR(Vehicle, service_interval,      SLE_UINT16,                 180, SL_MAX_VERSION),
 
		     SLE_VAR(Vehicle, reliability,           SLE_UINT16),
 
		     SLE_VAR(Vehicle, reliability_spd_dec,   SLE_UINT16),
 
		     SLE_VAR(Vehicle, breakdown_ctr,         SLE_UINT8),
 
		     SLE_VAR(Vehicle, breakdown_delay,       SLE_UINT8),
 
		     SLE_VAR(Vehicle, breakdowns_since_last_service, SLE_UINT8),
src/vehicle.cpp
Show inline comments
 
@@ -1346,49 +1346,49 @@ void VehicleEnterDepot(Vehicle *v)
 
	VehicleServiceInDepot(v);
 

	
 
	/* After a vehicle trigger, the graphics and properties of the vehicle could change. */
 
	TriggerVehicle(v, VEHICLE_TRIGGER_DEPOT);
 
	v->MarkDirty();
 

	
 
	if (v->current_order.IsType(OT_GOTO_DEPOT)) {
 
		SetWindowDirty(WC_VEHICLE_VIEW, v->index);
 

	
 
		const Order *real_order = v->GetOrder(v->cur_real_order_index);
 
		Order t = v->current_order;
 
		v->current_order.MakeDummy();
 

	
 
		/* Test whether we are heading for this depot. If not, do nothing.
 
		 * Note: The target depot for nearest-/manual-depot-orders is only updated on junctions, but we want to accept every depot. */
 
		if ((t.GetDepotOrderType() & ODTFB_PART_OF_ORDERS) &&
 
				real_order != NULL && !(real_order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) &&
 
				(v->type == VEH_AIRCRAFT ? t.GetDestination() != GetStationIndex(v->tile) : v->dest_tile != v->tile)) {
 
			/* We are heading for another depot, keep driving. */
 
			return;
 
		}
 

	
 
		if (t.IsRefit()) {
 
			Backup<CompanyByte> cur_company(_current_company, v->owner, FILE_LINE);
 
			CommandCost cost = DoCommand(v->tile, v->index, t.GetRefitCargo() | t.GetRefitSubtype() << 8, DC_EXEC, GetCmdRefitVeh(v));
 
			CommandCost cost = DoCommand(v->tile, v->index, t.GetRefitCargo() | 0xFF << 8, DC_EXEC, GetCmdRefitVeh(v));
 
			cur_company.Restore();
 

	
 
			if (cost.Failed()) {
 
				_vehicles_to_autoreplace[v] = false;
 
				if (v->owner == _local_company) {
 
					/* Notify the user that we stopped the vehicle */
 
					SetDParam(0, v->index);
 
					AddVehicleAdviceNewsItem(STR_NEWS_ORDER_REFIT_FAILED, v->index);
 
				}
 
			} else if (cost.GetCost() != 0) {
 
				v->profit_this_year -= cost.GetCost() << 8;
 
				if (v->owner == _local_company) {
 
					ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost.GetCost());
 
				}
 
			}
 
		}
 

	
 
		if (t.GetDepotOrderType() & ODTFB_PART_OF_ORDERS) {
 
			/* Part of orders */
 
			v->DeleteUnreachedImplicitOrders();
 
			UpdateVehicleTimetable(v, true);
 
			v->IncrementImplicitOrderIndex();
 
		}
 
		if (t.GetDepotActionType() & ODATFB_HALT) {
src/vehicle_gui.cpp
Show inline comments
 
@@ -384,50 +384,53 @@ struct RefitWindow : public Window {
 
		GetVehicleSet(vehicles_to_refit, Vehicle::Get(this->selected_vehicle), this->num_vehicles);
 

	
 
		do {
 
			if (v->type == VEH_TRAIN && !vehicles_to_refit.Contains(v->index)) continue;
 
			const Engine *e = v->GetEngine();
 
			uint32 cmask = e->info.refit_mask;
 
			byte callback_mask = e->info.callback_mask;
 

	
 
			/* Skip this engine if it does not carry anything */
 
			if (!e->CanCarryCargo()) continue;
 
			/* Skip this engine if we build the list for auto-refitting and engine doesn't allow it. */
 
			if (this->auto_refit && !HasBit(e->info.misc_flags, EF_AUTO_REFIT)) continue;
 

	
 
			/* Loop through all cargoes in the refit mask */
 
			int current_index = 0;
 
			const CargoSpec *cs;
 
			FOR_ALL_SORTED_CARGOSPECS(cs) {
 
				CargoID cid = cs->Index();
 
				/* Skip cargo type if it's not listed */
 
				if (!HasBit(cmask, cid)) {
 
					current_index++;
 
					continue;
 
				}
 

	
 
				/* Check the vehicle's callback mask for cargo suffixes */
 
				if (HasBit(callback_mask, CBM_VEHICLE_CARGO_SUFFIX)) {
 
				/* Check the vehicle's callback mask for cargo suffixes.
 
				 * This is not supported for ordered refits, since subtypes only have a meaning
 
				 * for a specific vehicle at a specific point in time, which conflicts with shared orders,
 
				 * autoreplace, autorenew, clone, order restoration, ... */
 
				if (this->order == INVALID_VEH_ORDER_ID && HasBit(callback_mask, CBM_VEHICLE_CARGO_SUFFIX)) {
 
					/* Make a note of the original cargo type. It has to be
 
					 * changed to test the cargo & subtype... */
 
					CargoID temp_cargo = v->cargo_type;
 
					byte temp_subtype  = v->cargo_subtype;
 

	
 
					v->cargo_type = cid;
 

	
 
					for (uint refit_cyc = 0; refit_cyc < MAX_REFIT_CYCLE; refit_cyc++) {
 
						v->cargo_subtype = refit_cyc;
 

	
 
						/* Make sure we don't pick up anything cached. */
 
						v->First()->InvalidateNewGRFCache();
 
						v->InvalidateNewGRFCache();
 
						uint16 callback = GetVehicleCallback(CBID_VEHICLE_CARGO_SUFFIX, 0, 0, v->engine_type, v);
 

	
 
						if (callback != CALLBACK_FAILED) {
 
							if (callback > 0x400) ErrorUnknownCallbackResult(v->GetGRFID(), CBID_VEHICLE_CARGO_SUFFIX, callback);
 
							if (callback >= 0x400 || (v->GetGRF()->grf_version < 8 && callback == 0xFF)) callback = CALLBACK_FAILED;
 
						}
 
						if (refit_cyc != 0 && callback == CALLBACK_FAILED) break;
 

	
 
						RefitOption option;
 
						option.cargo   = cid;
 
						option.subtype = refit_cyc;
 
@@ -466,64 +469,64 @@ struct RefitWindow : public Window {
 
	/**
 
	 * Gets the #RefitOption placed in the selected index.
 
	 * @return Pointer to the #RefitOption currently in use.
 
	 */
 
	RefitOption *GetRefitOption()
 
	{
 
		if (this->sel < 0) return NULL;
 
		int subtype = 0;
 
		for (uint i = 0; subtype <= this->sel && i < NUM_CARGO; i++) {
 
			for (uint j = 0; subtype <= this->sel && j < this->list[i].Length(); j++) {
 
				if (subtype == this->sel) {
 
					return &this->list[i][j];
 
				}
 
				subtype++;
 
			}
 
		}
 

	
 
		return NULL;
 
	}
 

	
 
	RefitWindow(const WindowDesc *desc, const Vehicle *v, VehicleOrderID order, bool auto_refit) : Window()
 
	{
 
		this->sel = -1;
 
		this->auto_refit = auto_refit;
 
		this->order = order;
 
		this->CreateNestedTree(desc);
 

	
 
		this->vscroll = this->GetScrollbar(WID_VR_SCROLLBAR);
 
		this->hscroll = (v->IsGroundVehicle() ? this->GetScrollbar(WID_VR_HSCROLLBAR) : NULL);
 
		this->GetWidget<NWidgetCore>(WID_VR_SELECT_HEADER)->tool_tip = STR_REFIT_TRAIN_LIST_TOOLTIP + v->type;
 
		this->GetWidget<NWidgetCore>(WID_VR_MATRIX)->tool_tip        = STR_REFIT_TRAIN_LIST_TOOLTIP + v->type;
 
		NWidgetCore *nwi = this->GetWidget<NWidgetCore>(WID_VR_REFIT);
 
		nwi->widget_data = STR_REFIT_TRAIN_REFIT_BUTTON + v->type;
 
		nwi->tool_tip    = STR_REFIT_TRAIN_REFIT_TOOLTIP + v->type;
 
		this->GetWidget<NWidgetStacked>(WID_VR_SHOW_HSCROLLBAR)->SetDisplayedPlane(v->IsGroundVehicle() ? 0 : SZSP_HORIZONTAL);
 
		this->GetWidget<NWidgetCore>(WID_VR_VEHICLE_PANEL_DISPLAY)->tool_tip = (v->type == VEH_TRAIN) ? STR_REFIT_SELECT_VEHICLES_TOOLTIP : STR_NULL;
 

	
 
		this->FinishInitNested(desc, v->index);
 
		this->owner = v->owner;
 

	
 
		this->order = order;
 
		this->SetWidgetDisabledState(WID_VR_REFIT, this->sel == -1);
 
	}
 

	
 
	virtual void OnInit()
 
	{
 
		if (this->cargo != NULL) {
 
			/* Store the RefitOption currently in use. */
 
			RefitOption current_refit_option = *(this->cargo);
 

	
 
			/* Rebuild the refit list */
 
			this->BuildRefitList();
 
			this->sel = -1;
 
			this->cargo = NULL;
 
			int current = 0;
 
			for (uint i = 0; this->cargo == NULL && i < NUM_CARGO; i++) {
 
				for (uint j = 0; j < list[i].Length(); j++) {
 
					if (list[i][j] == current_refit_option) {
 
						this->sel = current;
 
						this->cargo = &list[i][j];
 
						this->vscroll->ScrollTowards(current);
 
						break;
 
					}
 
					current++;
 
				}
 
@@ -826,49 +829,49 @@ struct RefitWindow : public Window {
 
					/* The vehicle selection has changed. */
 
					this->InvalidateData(2);
 
				}
 
				break;
 
			}
 

	
 
			case WID_VR_MATRIX: { // listbox
 
				this->sel = this->vscroll->GetScrolledRowFromWidget(pt.y, this, WID_VR_MATRIX);
 
				if (this->sel == INT_MAX) this->sel = -1;
 
				this->SetWidgetDisabledState(WID_VR_REFIT, this->sel == -1);
 
				this->InvalidateData(1);
 

	
 
				if (click_count == 1) break;
 
				/* FALL THROUGH */
 
			}
 

	
 
			case WID_VR_REFIT: // refit button
 
				if (this->cargo != NULL) {
 
					const Vehicle *v = Vehicle::Get(this->window_number);
 

	
 
					if (this->order == INVALID_VEH_ORDER_ID) {
 
						bool delete_window = this->selected_vehicle == v->index && this->num_vehicles == UINT8_MAX;
 
						if (DoCommandP(v->tile, this->selected_vehicle, this->cargo->cargo | this->cargo->subtype << 8 | this->num_vehicles << 16, GetCmdRefitVeh(v)) && delete_window) delete this;
 
					} else {
 
						if (DoCommandP(v->tile, v->index, this->cargo->cargo | this->cargo->subtype << 8 | this->order << 16, CMD_ORDER_REFIT)) delete this;
 
						if (DoCommandP(v->tile, v->index, this->cargo->cargo | this->order << 16, CMD_ORDER_REFIT)) delete this;
 
					}
 
				}
 
				break;
 
		}
 
	}
 

	
 
	virtual void OnMouseDrag(Point pt, int widget)
 
	{
 
		switch (widget) {
 
			case WID_VR_VEHICLE_PANEL_DISPLAY: { // Vehicle image.
 
				if (this->order != INVALID_VEH_ORDER_ID) break;
 
				NWidgetBase *nwi = this->GetWidget<NWidgetBase>(WID_VR_VEHICLE_PANEL_DISPLAY);
 
				this->SetSelectedVehicles(pt.x - nwi->pos_x);
 
				this->SetWidgetDirty(WID_VR_VEHICLE_PANEL_DISPLAY);
 
				break;
 
			}
 
		}
 
	}
 

	
 
	virtual void OnDragDrop(Point pt, int widget)
 
	{
 
		switch (widget) {
 
			case WID_VR_VEHICLE_PANEL_DISPLAY: { // Vehicle image.
 
				if (this->order != INVALID_VEH_ORDER_ID) break;
 
@@ -903,49 +906,49 @@ static const NWidgetPart _nested_vehicle
 
	EndContainer(),
 
	NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_VR_SELECT_HEADER), SetDataTip(STR_REFIT_TITLE, STR_NULL), SetResize(1, 0),
 
	/* Matrix + scrollbar. */
 
	NWidget(NWID_HORIZONTAL),
 
		NWidget(WWT_MATRIX, COLOUR_GREY, WID_VR_MATRIX), SetMinimalSize(228, 112), SetResize(1, 14), SetFill(1, 1), SetDataTip(0x801, STR_NULL), SetScrollbar(WID_VR_SCROLLBAR),
 
		NWidget(NWID_VSCROLLBAR, COLOUR_GREY, WID_VR_SCROLLBAR),
 
	EndContainer(),
 
	NWidget(WWT_PANEL, COLOUR_GREY, WID_VR_INFO), SetMinimalTextLines(2, WD_FRAMERECT_TOP + WD_FRAMERECT_BOTTOM), SetResize(1, 0), EndContainer(),
 
	NWidget(NWID_HORIZONTAL),
 
		NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VR_REFIT), SetFill(1, 0), SetResize(1, 0),
 
		NWidget(WWT_RESIZEBOX, COLOUR_GREY),
 
	EndContainer(),
 
};
 

	
 
static const WindowDesc _vehicle_refit_desc(
 
	WDP_AUTO, 240, 174,
 
	WC_VEHICLE_REFIT, WC_VEHICLE_VIEW,
 
	WDF_CONSTRUCTION,
 
	_nested_vehicle_refit_widgets, lengthof(_nested_vehicle_refit_widgets)
 
);
 

	
 
/**
 
 * Show the refit window for a vehicle
 
 * @param *v The vehicle to show the refit window for
 
 * @param order of the vehicle ( ? )
 
 * @param order of the vehicle to assign refit to, or INVALID_VEH_ORDER_ID to refit the vehicle now
 
 * @param parent the parent window of the refit window
 
 * @param auto_refit Choose cargo for auto-refitting
 
 */
 
void ShowVehicleRefitWindow(const Vehicle *v, VehicleOrderID order, Window *parent, bool auto_refit)
 
{
 
	DeleteWindowById(WC_VEHICLE_REFIT, v->index);
 
	RefitWindow *w = new RefitWindow(&_vehicle_refit_desc, v, order, auto_refit);
 
	w->parent = parent;
 
}
 

	
 
/** Display list of cargo types of the engine, for the purchase information window */
 
uint ShowRefitOptionsList(int left, int right, int y, EngineID engine)
 
{
 
	/* List of cargo types of this engine */
 
	uint32 cmask = GetUnionOfArticulatedRefitMasks(engine, false);
 
	/* List of cargo types available in this climate */
 
	uint32 lmask = _cargo_mask;
 

	
 
	/* Draw nothing if the engine is not refittable */
 
	if (HasAtMostOneBit(cmask)) return y;
 

	
 
	if (cmask == lmask) {
 
		/* Engine can be refitted to all types in this climate */
 
		SetDParam(0, STR_PURCHASE_INFO_ALL_TYPES);
0 comments (0 inline, 0 general)