Changeset - r10546:a4ec290c1c46
[Not reviewed]
master
0 12 0
rubidium - 15 years ago 2009-01-03 13:52:06
rubidium@openttd.org
(svn r14803) -Codechange: move order list management into it's own class and remove the order count from the savegame as we can easily count that (PhilSophus)
12 files changed with 536 insertions and 232 deletions:
0 comments (0 inline, 0 general)
src/oldloader.cpp
Show inline comments
 
@@ -329,12 +329,9 @@ static StringID *_old_vehicle_names = NU
 

	
 
static void FixOldVehicles()
 
{
 
	/* Check for shared orders, and link them correctly */
 
	Vehicle* v;
 

	
 
	FOR_ALL_VEHICLES(v) {
 
		Vehicle *u;
 

	
 
		v->name = CopyFromOldName(_old_vehicle_names[v->index]);
 

	
 
		/* We haven't used this bit for stations for ages */
 
@@ -356,14 +353,7 @@ static void FixOldVehicles()
 
			v->current_order.MakeDummy();
 
		}
 

	
 
		FOR_ALL_VEHICLES_FROM(u, v->index + 1) {
 
			/* If a vehicle has the same orders, add the link to eachother
 
			 * in both vehicles */
 
			if (v->orders == u->orders) {
 
				u->AddToShared(v);
 
				break;
 
			}
 
		}
 
		/* Shared orders are fixed in AfterLoadVehicles now */
 
	}
 
}
 

	
 
@@ -1144,7 +1134,7 @@ static const OldChunks vehicle_chunk[] =
 
	OCL_VAR ( OC_UINT32,   1, &_old_order_ptr ),
 
	OCL_VAR ( OC_UINT16,   1, &_old_order ),
 

	
 
	OCL_SVAR(  OC_UINT8, Vehicle, num_orders ),
 
	OCL_NULL ( 1 ), ///< num_orders, now calculated
 
	OCL_SVAR(  OC_UINT8, Vehicle, cur_order_index ),
 
	OCL_SVAR(   OC_TILE, Vehicle, dest_tile ),
 
	OCL_SVAR( OC_UINT16, Vehicle, load_unload_time_rem ),
 
@@ -1250,7 +1240,7 @@ bool LoadOldVehicle(LoadgameState *ls, i
 
			 * we go over that limit something is very wrong. In that case
 
			 * we just assume there are no orders for the vehicle.
 
			 */
 
			if (old_id < 5000) v->orders = GetOrder(old_id);
 
			if (old_id < 5000) v->orders.old = GetOrder(old_id);
 
		}
 
		v->current_order.AssignOrder(UnpackOldOrder(_old_order));
 

	
src/openttd.cpp
Show inline comments
 
@@ -2386,7 +2386,10 @@ bool AfterLoadGame()
 

	
 
		Vehicle *v;
 
		FOR_ALL_VEHICLES(v) {
 
			if (v->orders != NULL && !v->orders->IsValid()) v->orders = NULL;
 
			if (v->orders.list != NULL && v->orders.list->GetFirstOrder() != NULL && !v->orders.list->GetFirstOrder()->IsValid()) {
 
				v->orders.list->FreeChain();
 
				v->orders.list = NULL;
 
			}
 

	
 
			v->current_order.ConvertFromOldSavegame();
 
			if (v->type == VEH_ROAD && v->IsPrimaryVehicle() && v->FirstShared() == v) {
src/order_base.h
Show inline comments
 
@@ -15,6 +15,7 @@
 
#include "waypoint_type.h"
 

	
 
DECLARE_OLD_POOL(Order, Order, 6, 1000)
 
DECLARE_OLD_POOL(OrderList, OrderList, 4, 4000)
 

	
 
/* If you change this, keep in mind that it is saved on 3 places:
 
 * - Load_ORDR, all the global orders
 
@@ -119,12 +120,6 @@ public:
 
	void MakeConditional(VehicleOrderID order);
 

	
 
	/**
 
	 * Free a complete order chain.
 
	 * @note do not use on "current_order" vehicle orders!
 
	 */
 
	void FreeChain();
 

	
 
	/**
 
	 * 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.
 
@@ -207,6 +202,14 @@ public:
 

	
 
	bool ShouldStopAtStation(const Vehicle *v, StationID station) const;
 

	
 
	/** Checks if this order has travel_time and if needed wait_time set. */
 
	inline bool IsCompletelyTimetabled() const
 
	{
 
		if (this->travel_time == 0 && !this->IsType(OT_CONDITIONAL)) return false;
 
		if (this->wait_time == 0 && this->IsType(OT_GOTO_STATION) && !(this->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION)) return false;
 
		return true;
 
	}
 

	
 
	/**
 
	 * Assign the given order to this one.
 
	 * @param other the data to copy (except next pointer).
 
@@ -250,11 +253,183 @@ static inline VehicleOrderID GetNumOrder
 
	return GetOrderPoolSize();
 
}
 

	
 
/** Shared order list linking together the linked list of orders and the list
 
 *  of vehicles sharing this order list.
 
 */
 
struct OrderList : PoolItem<OrderList, OrderListID, &_OrderList_pool> {
 
private:
 
	friend void AfterLoadVehicles(bool part_of_load); ///< For instantiating the shared vehicle chain
 
	friend const struct SaveLoad *GetOrderListDescription(); ///< Saving and loading of order lists.
 

	
 
	Order *first;                   ///< First order of the order list
 
	VehicleOrderID num_orders;      ///< NOSAVE: How many orders there are in the list
 
	unsigned num_vehicles;          ///< NOSAVE: Number of vehicles that share this order list
 
	Vehicle *first_shared;          ///< NOSAVE: pointer to the first vehicle in the shared order chain
 

	
 
	unsigned timetable_duration;    ///< NOSAVE: Total duration of the order list
 

	
 
public:
 
	/** Default constructor producing an invalid order list. */
 
	OrderList()
 
		: first(NULL), num_orders(INVALID_VEH_ORDER_ID), num_vehicles(0), first_shared(NULL),
 
		  timetable_duration(0) { }
 

	
 
	/** Create an order list with the given order chain for the given vehicle.
 
	 *  @param chain is the pointer to the first order of the order chain
 
	 *  @param v is any vehicle of the shared order vehicle chain (does not need to be the first)
 
	 */
 
	OrderList(Order *chain, Vehicle *v);
 

	
 
	/** Destructor. Invalidates OrderList for re-usage by the pool. */
 
	~OrderList() { this->num_orders = INVALID_VEH_ORDER_ID; }
 

	
 
	/** Checks, if this is a valid order list. */
 
	inline bool IsValid() const { return this->num_orders != INVALID_VEH_ORDER_ID; }
 

	
 
	/**
 
	 * Get the first order of the order chain.
 
	 * @return the first order of the chain.
 
	 */
 
	inline Order *GetFirstOrder() const { return this->first; }
 

	
 
	/**
 
	 * Get a certain order of the order chain.
 
	 * @param index zero-based index of the order within the chain.
 
	 * @return the order at position index.
 
	 */
 
	Order *GetOrderAt(int index) const;
 

	
 
	/**
 
	 * Get the last order of the order chain.
 
	 * @return the last order of the chain.
 
	 */
 
	inline Order *GetLastOrder() const { return this->GetOrderAt(this->num_orders - 1); }
 

	
 
	/**
 
	 * Get number of orders in the order list.
 
	 * @return number of orders in the chain. */
 
	inline VehicleOrderID GetNumOrders() const { return this->num_orders; }
 

	
 
	/**
 
	 * Insert a new order into the order chain.
 
	 * @param new_order is the order to insert into the chain.
 
	 * @param index is the position where the order is supposed to be inserted. */
 
	void InsertOrderAt(Order *new_order, int index);
 

	
 
	/**
 
	 * Remove an order from the order list and delete it.
 
	 * @param index is the position of the order which is to be deleted.
 
	 */
 
	void DeleteOrderAt(int index);
 

	
 
	/**
 
	 * Move an order to another position within the order list.
 
	 * @param from is the zero-based position of the order to move.
 
	 * @param to is the zero-based position where the order is moved to. */
 
	void MoveOrder(int from, int to);
 

	
 
	/**
 
	 * Is this a shared order list?
 
	 * @return whether this order list is shared among multiple vehicles
 
	 */
 
	inline bool IsShared() const { return this->num_vehicles > 1; };
 

	
 
	/**
 
	 * Get the first vehicle of this vehicle chain.
 
	 * @return the first vehicle of the chain.
 
	 */
 
	inline Vehicle *GetFirstSharedVehicle() const { return this->first_shared; }
 

	
 
	/**
 
	 * Return the number of vehicles that share this orders list
 
	 * @return the count of vehicles that use this shared orders list
 
	 */
 
	inline unsigned GetNumVehicles() const { return this->num_vehicles; }
 

	
 
	/**
 
	 * Checks whether a vehicle is part of the shared vehicle chain.
 
	 * @param v is the vehicle to search in the shared vehicle chain.
 
	 */
 
	bool IsVehicleInSharedOrdersList(const Vehicle *v) const;
 

	
 
	/**
 
	 * Gets the position of the given vehicle within the shared order vehicle list.
 
	 * @param v is the vehicle of which to get the position
 
	 * @return position of v within the shared vehicle chain.
 
	 */
 
	int GetPositionInSharedOrderList(const Vehicle *v) const;
 

	
 
	/**
 
	 * Adds the given vehicle to this shared order list.
 
	 * @note This is supposed to be called after the vehicle has been inserted
 
	 *       into the shared vehicle chain.
 
	 * @param v vehicle to add to the list
 
	 */
 
	inline void AddVehicle(Vehicle *v) { ++this->num_vehicles; }
 

	
 
	/**
 
	 * Removes the vehicle from the shared order list.
 
	 * @note This is supposed to be called when the vehicle is still in the chain
 
	 * @param v vehicle to remove from the list
 
	 */
 
	void RemoveVehicle(Vehicle *v);
 

	
 
	/**
 
	 * Checks whether all orders of the list have a filled timetable.
 
	 * @return whether all orders have a filled timetable.
 
	 */
 
	bool IsCompleteTimetable() const;
 

	
 
	/**
 
	 * Gets the total duration of the vehicles timetable or -1 is the timetable is not complete.
 
	 * @return total timetable duration or -1 for incomplete timetables
 
	 */
 
	inline int GetTimetableTotalDuration() const { return this->IsCompleteTimetable() ? this->timetable_duration : -1; }
 

	
 
	/**
 
	 * Gets the known duration of the vehicles timetable even if the timetable is not complete.
 
	 * @return known timetable duration
 
	 */
 
	inline int GetTimetableDurationIncomplete() const { return this->timetable_duration; }
 

	
 
	/**
 
	 * Must be called if an order's timetable is changed to update internal book keeping.
 
	 * @param delta By how many ticks has the timetable duration changed
 
	 */
 
	void UpdateOrderTimetable(int delta) { this->timetable_duration += delta; }
 

	
 
	/**
 
	 * Must be called if the whole timetable is cleared to update internal book keeping.
 
	 */
 
	void ResetOrderTimetable() { this->timetable_duration = 0; }
 

	
 
	/**
 
	 * Free a complete order chain.
 
	 * @param keep_orderlist If this is true only delete the orders, otherwise also delete the OrderList.
 
	 * @note do not use on "current_order" vehicle orders!
 
	 */
 
	void FreeChain(bool keep_orderlist = false);
 

	
 
	/**
 
	 * Checks for internal consistency of order list. Triggers assertion if something is wrong.
 
	 */
 
	void DebugCheckSanity() const;
 
};
 

	
 
static inline bool IsValidOrderListID(uint index)
 
{
 
	return index < GetOrderListPoolSize() && GetOrderList(index)->IsValid();
 
}
 

	
 
#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())
 
#define FOR_ALL_ORDERS(order) FOR_ALL_ORDERS_FROM(order, 0)
 

	
 

	
 
#define FOR_VEHICLE_ORDERS(v, order) for (order = v->orders; order != NULL; order = order->next)
 
#define FOR_VEHICLE_ORDERS(v, order) for (order = (v->orders.list == NULL) ? NULL : v->orders.list->GetFirstOrder(); order != NULL; order = order->next)
 

	
 

	
 
#define FOR_ALL_ORDER_LISTS_FROM(ol, start) for (ol = GetOrderList(start); ol != NULL; ol = (ol->index + 1U < GetOrderListPoolSize()) ? GetOrderList(ol->index + 1U) : NULL) if (ol->IsValid())
 
#define FOR_ALL_ORDER_LISTS(ol) FOR_ALL_ORDER_LISTS_FROM(ol, 0)
 

	
 
/* (Un)pack routines */
 
Order UnpackOldOrder(uint16 packed);
src/order_cmd.cpp
Show inline comments
 
@@ -4,6 +4,7 @@
 

	
 
#include "stdafx.h"
 
#include "openttd.h"
 
#include "debug.h"
 
#include "order_base.h"
 
#include "order_func.h"
 
#include "airport.h"
 
@@ -41,6 +42,7 @@ TileIndex _backup_orders_tile;
 
BackuppedOrders _backup_orders_data;
 

	
 
DEFINE_OLD_POOL_GENERIC(Order, Order);
 
DEFINE_OLD_POOL_GENERIC(OrderList, OrderList);
 

	
 
void Order::Free()
 
{
 
@@ -107,12 +109,6 @@ void Order::SetRefit(CargoID cargo, byte
 
	this->refit_subtype = subtype;
 
}
 

	
 
void Order::FreeChain()
 
{
 
	if (next != NULL) next->FreeChain();
 
	delete this;
 
}
 

	
 
bool Order::Equals(const Order &other) const
 
{
 
	/* In case of go to nearest depot orders we need "only" compare the flags
 
@@ -249,22 +245,6 @@ void InvalidateVehicleOrder(const Vehicl
 

	
 
/**
 
 *
 
 * Swap two orders
 
 *
 
 */
 
static void SwapOrders(Order *order1, Order *order2)
 
{
 
	Order temp_order;
 

	
 
	temp_order = *order1;
 
	order1->AssignOrder(*order2);
 
	order1->next = order2->next;
 
	order2->AssignOrder(temp_order);
 
	order2->next = temp_order.next;
 
}
 

	
 
/**
 
 *
 
 * Assign data to an order (from an other order)
 
 *   This function makes sure that the index is maintained correctly
 
 *
 
@@ -283,6 +263,176 @@ void Order::AssignOrder(const Order &oth
 
}
 

	
 

	
 
OrderList::OrderList(Order *chain, Vehicle *v) :
 
		first(chain), num_orders(0), num_vehicles(1), first_shared(v),
 
		timetable_duration(0)
 
{
 
	for (Order *o = this->first; o != NULL; o = o->next) {
 
		++this->num_orders;
 
		this->timetable_duration += o->wait_time + o->travel_time;
 
	}
 

	
 
	for (Vehicle *u = v->PreviousShared(); u != NULL; u = u->PreviousShared()) {
 
		++this->num_vehicles;
 
		this->first_shared = u;
 
	}
 

	
 
	for (const Vehicle *u = v->NextShared(); u != NULL; u = u->NextShared()) ++this->num_vehicles;
 
}
 

	
 
void OrderList::FreeChain(bool keep_orderlist)
 
{
 
	Order *next;
 
	for(Order *o = this->first; o != NULL; o = next) {
 
		next = o->next;
 
		delete o;
 
	}
 

	
 
	if (keep_orderlist) {
 
		this->first = NULL;
 
		this->num_orders = 0;
 
		this->timetable_duration = 0;
 
	} else {
 
		delete this;
 
	}
 
}
 

	
 
Order *OrderList::GetOrderAt(int index) const
 
{
 
	if (index < 0) return NULL;
 

	
 
	Order *order = this->first;
 

	
 
	while (order != NULL && index-- > 0)
 
		order = order->next;
 

	
 
	return order;
 
}
 

	
 
void OrderList::InsertOrderAt(Order *new_order, int index)
 
{
 
	if (this->first == NULL) {
 
		this->first = new_order;
 
	} else {
 
		if (index == 0) {
 
			/* Insert as first or only order */
 
			new_order->next = this->first;
 
			this->first = new_order;
 
		} else if (index >= this->num_orders) {
 
			/* index is after the last order, add it to the end */
 
			this->GetLastOrder()->next = new_order;
 
		} else {
 
			/* Put the new order in between */
 
			Order *order = this->GetOrderAt(index - 1);
 
			new_order->next = order->next;
 
			order->next = new_order;
 
		}
 
	}
 
	++this->num_orders;
 
	this->timetable_duration += new_order->wait_time + new_order->travel_time;
 
}
 

	
 

	
 
void OrderList::DeleteOrderAt(int index)
 
{
 
	if (index >= this->num_orders) return;
 

	
 
	Order *to_remove;
 

	
 
	if (index == 0) {
 
		to_remove = this->first;
 
		this->first = to_remove->next;
 
	} else {
 
		Order *prev = GetOrderAt(index - 1);
 
		to_remove = prev->next;
 
		prev->next = to_remove->next;
 
	}
 
	--this->num_orders;
 
	this->timetable_duration -= (to_remove->wait_time + to_remove->travel_time);
 
	delete to_remove;
 
}
 

	
 
void OrderList::MoveOrder(int from, int to)
 
{
 
	if (from >= this->num_orders || to >= this->num_orders || from == to) return;
 

	
 
	Order *moving_one;
 

	
 
	/* Take the moving order out of the pointer-chain */
 
	if (from == 0) {
 
		moving_one = this->first;
 
		this->first = moving_one->next;
 
	} else {
 
		Order *one_before = GetOrderAt(from - 1);
 
		moving_one = one_before->next;
 
		one_before->next = moving_one->next;
 
	}
 

	
 
	/* Insert the moving_order again in the pointer-chain */
 
	if (to == 0) {
 
		moving_one->next = this->first;
 
		this->first = moving_one;
 
	} else {
 
		Order *one_before = GetOrderAt(to - 1);
 
		moving_one->next = one_before->next;
 
		one_before->next = moving_one;
 
	}
 
}
 

	
 
void OrderList::RemoveVehicle(Vehicle *v)
 
{
 
	--this->num_vehicles;
 
	if (v == this->first_shared) this->first_shared = v->NextShared();
 
}
 

	
 
bool OrderList::IsVehicleInSharedOrdersList(const Vehicle *v) const
 
{
 
	for (const Vehicle *v_shared = this->first_shared; v_shared != NULL; v_shared = v_shared->NextShared()) {
 
		if (v_shared == v) return true;
 
	}
 

	
 
	return false;
 
}
 

	
 
int OrderList::GetPositionInSharedOrderList(const Vehicle *v) const
 
{
 
	int count = 0;
 
	for (const Vehicle *v_shared = v->PreviousShared(); v_shared != NULL; v_shared = v_shared->PreviousShared()) count++;
 
	return count;
 
}
 

	
 
bool OrderList::IsCompleteTimetable() const
 
{
 
	for (Order *o = this->first; o != NULL; o = o->next) {
 
		if (!o->IsCompletelyTimetabled()) return false;
 
	}
 
	return true;
 
}
 

	
 
void OrderList::DebugCheckSanity() const
 
{
 
	VehicleOrderID check_num_orders = 0;
 
	unsigned check_num_vehicles = 0;
 
	unsigned check_timetable_duration = 0;
 

	
 
	DEBUG(misc, 6, "Checking OrderList %hu for sanity...", this->index);
 

	
 
	for (const Order *o = this->first; o != NULL; o = o->next) {
 
		++check_num_orders;
 
		check_timetable_duration += o->wait_time + o->travel_time;
 
	}
 
	assert(this->num_orders == check_num_orders);
 
	assert(this->timetable_duration == check_timetable_duration);
 

	
 
	for (const Vehicle *v = this->first_shared; v != NULL; v = v->NextShared()) {
 
		++check_num_vehicles;
 
		assert(v->orders.list == this);
 
	}
 
	assert(this->num_vehicles == check_num_vehicles);
 
	DEBUG(misc, 6, "... detected %u orders, %u vehicles, %u ticks", (unsigned)this->num_orders,
 
	      this->num_vehicles, this->timetable_duration);
 
}
 

	
 
/**
 
 * Delete all news items regarding defective orders about a vehicle
 
 * This could kill still valid warnings (for example about void order when just
 
@@ -315,7 +465,7 @@ static uint GetOrderDistance(const Order
 
		conditional_depth++;
 

	
 
		int dist1 = GetOrderDistance(prev, GetVehicleOrder(v, cur->GetConditionSkipToOrder()), v, conditional_depth);
 
		int dist2 = GetOrderDistance(prev, cur->next == NULL ? v->orders : cur->next, v, conditional_depth);
 
		int dist2 = GetOrderDistance(prev, cur->next == NULL ? v->orders.list->GetFirstOrder() : cur->next, v, conditional_depth);
 
		return max(dist1, dist2);
 
	}
 

	
 
@@ -495,6 +645,7 @@ CommandCost CmdInsertOrder(TileIndex til
 
	if (sel_ord > v->GetNumOrders()) return CMD_ERROR;
 

	
 
	if (!Order::CanAllocateItem()) return_cmd_error(STR_8831_NO_MORE_SPACE_FOR_ORDERS);
 
	if (v->orders.list == NULL && !OrderList::CanAllocateItem()) return_cmd_error(STR_8831_NO_MORE_SPACE_FOR_ORDERS);
 

	
 
	if (v->type == VEH_SHIP && IsHumanCompany(v->owner) && _settings_game.pf.pathfinder_for_ships != VPF_NPF) {
 
		/* Make sure the new destination is not too far away from the previous */
 
@@ -504,7 +655,8 @@ CommandCost CmdInsertOrder(TileIndex til
 
		/* Find the last goto station or depot order before the insert location.
 
		 * If the order is to be inserted at the beginning of the order list this
 
		 * finds the last order in the list. */
 
		for (const Order *o = v->orders; o != NULL; o = o->next) {
 
		const Order *o;
 
		FOR_VEHICLE_ORDERS(v, o) {
 
			if (o->IsType(OT_GOTO_STATION) || o->IsType(OT_GOTO_DEPOT)) prev = o;
 
			if (++n == sel_ord && prev != NULL) break;
 
		}
 
@@ -521,42 +673,16 @@ CommandCost CmdInsertOrder(TileIndex til
 
		new_o->AssignOrder(new_order);
 

	
 
		/* Create new order and link in list */
 
		if (v->orders == NULL) {
 
			v->orders = new_o;
 
		if (v->orders.list == NULL) {
 
			v->orders.list = new OrderList(new_o, v);
 
		} else {
 
			/* Try to get the previous item (we are inserting above the
 
			    selected) */
 
			Order *order = GetVehicleOrder(v, sel_ord - 1);
 

	
 
			if (order == NULL && GetVehicleOrder(v, sel_ord) != NULL) {
 
				/* There is no previous item, so we are altering v->orders itself
 
				    But because the orders can be shared, we copy the info over
 
				    the v->orders, so we don't have to change the pointers of
 
				    all vehicles */
 
				SwapOrders(v->orders, new_o);
 
				/* Now update the next pointers */
 
				v->orders->next = new_o;
 
			} else if (order == NULL) {
 
				/* 'sel' is a non-existing order, add him to the end */
 
				order = GetLastVehicleOrder(v);
 
				order->next = new_o;
 
			} else {
 
				/* Put the new order in between */
 
				new_o->next = order->next;
 
				order->next = new_o;
 
			}
 
			v->orders.list->InsertOrderAt(new_o, sel_ord);
 
		}
 

	
 
		Vehicle *u = v->FirstShared();
 
		DeleteOrderWarnings(u);
 
		for (; u != NULL; u = u->NextShared()) {
 
			/* Increase amount of orders */
 
			u->num_orders++;
 

	
 
			/* If the orderlist was empty, assign it */
 
			if (u->orders == NULL) u->orders = v->orders;
 

	
 
			assert(v->orders == u->orders);
 
			assert(v->orders.list == u->orders.list);
 

	
 
			/* If there is added an order before the current one, we need
 
			to update the selected order */
 
@@ -634,37 +760,15 @@ CommandCost CmdDeleteOrder(TileIndex til
 
	if (order == NULL) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		if (GetVehicleOrder(v, sel_ord - 1) == NULL) {
 
			if (GetVehicleOrder(v, sel_ord + 1) != NULL) {
 
				/* First item, but not the last, so we need to alter v->orders
 
				    Because we can have shared order, we copy the data
 
				    from the next item over the deleted */
 
				order = GetVehicleOrder(v, sel_ord + 1);
 
				SwapOrders(v->orders, order);
 
			} else {
 
				/* Last item, so clean the list */
 
				v->orders = NULL;
 
			}
 
		} else {
 
			GetVehicleOrder(v, sel_ord - 1)->next = order->next;
 
		}
 

	
 
		/* Give the item free */
 
		delete order;
 
		v->orders.list->DeleteOrderAt(sel_ord);
 

	
 
		Vehicle *u = v->FirstShared();
 
		DeleteOrderWarnings(u);
 
		for (; u != NULL; u = u->NextShared()) {
 
			u->num_orders--;
 

	
 
			if (sel_ord < u->cur_order_index)
 
				u->cur_order_index--;
 

	
 
			/* If we removed the last order, make sure the shared vehicles
 
			 * also set their orders to NULL */
 
			if (v->orders == NULL) u->orders = NULL;
 

	
 
			assert(v->orders == u->orders);
 
			assert(v->orders.list == u->orders.list);
 

	
 
			/* NON-stop flag is misused to see if a train is in a station that is
 
			 * on his order list or not */
 
@@ -764,30 +868,7 @@ CommandCost CmdMoveOrder(TileIndex tile,
 
	if (moving_one == NULL) return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		/* Take the moving order out of the pointer-chain */
 
		Order *one_before = GetVehicleOrder(v, moving_order - 1);
 
		Order *one_past = GetVehicleOrder(v, moving_order + 1);
 

	
 
		if (one_before == NULL) {
 
			/* First order edit */
 
			v->orders = moving_one->next;
 
		} else {
 
			one_before->next = moving_one->next;
 
		}
 

	
 
		/* Insert the moving_order again in the pointer-chain */
 
		one_before = GetVehicleOrder(v, target_order - 1);
 
		one_past = GetVehicleOrder(v, target_order);
 

	
 
		moving_one->next = one_past;
 

	
 
		if (one_before == NULL) {
 
			/* first order edit */
 
			SwapOrders(v->orders, moving_one);
 
			v->orders->next = moving_one;
 
		} else {
 
			one_before->next = moving_one;
 
		}
 
		v->orders.list->MoveOrder(moving_order, target_order);
 

	
 
		/* Update shared list */
 
		Vehicle *u = v->FirstShared();
 
@@ -795,9 +876,6 @@ CommandCost CmdMoveOrder(TileIndex tile,
 
		DeleteOrderWarnings(u);
 

	
 
		for (; u != NULL; u = u->NextShared()) {
 
			/* Update the first order */
 
			if (u->orders != v->orders) u->orders = v->orders;
 

	
 
			/* Update the current order */
 
			if (u->cur_order_index == moving_order) {
 
				u->cur_order_index = target_order;
 
@@ -807,7 +885,7 @@ CommandCost CmdMoveOrder(TileIndex tile,
 
				u->cur_order_index++;
 
			}
 

	
 
			assert(v->orders == u->orders);
 
			assert(v->orders.list == u->orders.list);
 
			/* Update any possible open window of the vehicle */
 
			InvalidateVehicleOrder(u, moving_order | (target_order << 8));
 
		}
 
@@ -1101,8 +1179,7 @@ CommandCost CmdCloneOrder(TileIndex tile
 
				/* If the destination vehicle had a OrderList, destroy it */
 
				DeleteVehicleOrders(dst);
 

	
 
				dst->orders = src->orders;
 
				dst->num_orders = src->GetNumOrders();
 
				dst->orders.list = src->orders.list;
 

	
 
				/* Link this vehicle in the shared-list */
 
				dst->AddToShared(src);
 
@@ -1148,25 +1225,30 @@ CommandCost CmdCloneOrder(TileIndex tile
 

	
 
			/* make sure there are orders available */
 
			delta = dst->IsOrderListShared() ? src->GetNumOrders() + 1 : src->GetNumOrders() - dst->GetNumOrders();
 
			if (!Order::CanAllocateItem(delta)) {
 
			if (!Order::CanAllocateItem(delta) ||
 
					((dst->orders.list == NULL || dst->IsOrderListShared()) && !OrderList::CanAllocateItem())) {
 
				return_cmd_error(STR_8831_NO_MORE_SPACE_FOR_ORDERS);
 
			}
 

	
 
			if (flags & DC_EXEC) {
 
				const Order *order;
 
				Order *first = NULL;
 
				Order **order_dst;
 

	
 
				/* If the destination vehicle had a OrderList, destroy it */
 
				DeleteVehicleOrders(dst);
 
				/* If the destination vehicle had an order list, destroy the chain but keep the OrderList */
 
				DeleteVehicleOrders(dst, true);
 

	
 
				order_dst = &dst->orders;
 
				order_dst = &first;
 
				FOR_VEHICLE_ORDERS(src, order) {
 
					*order_dst = new Order();
 
					(*order_dst)->AssignOrder(*order);
 
					order_dst = &(*order_dst)->next;
 
				}
 

	
 
				dst->num_orders = src->GetNumOrders();
 
				if (dst->orders.list == NULL) dst->orders.list = new OrderList(first, dst);
 
				else {
 
					assert(dst->orders.list->GetFirstOrder() == NULL);
 
					new (dst->orders.list) OrderList(first, dst);
 
				}
 

	
 
				InvalidateVehicleOrder(dst, -1);
 

	
 
@@ -1435,7 +1517,7 @@ void CheckOrders(const Vehicle* v)
 
		if (v->GetNumOrders() > 1) {
 
			const Order* last = GetLastVehicleOrder(v);
 

	
 
			if (v->orders->Equals(*last)) {
 
			if (v->orders.list->GetFirstOrder()->Equals(*last)) {
 
				problem_type = 2;
 
			}
 
		}
 
@@ -1443,6 +1525,11 @@ void CheckOrders(const Vehicle* v)
 
		/* Do we only have 1 station in our order list? */
 
		if (n_st < 2 && problem_type == -1) problem_type = 0;
 

	
 
		assert(v->orders.list); // otherwise the check for v->FirstShared() != v would have been true
 
#ifndef NDEBUG
 
		v->orders.list->DebugCheckSanity();
 
#endif
 

	
 
		/* We don't have a problem */
 
		if (problem_type < 0) return;
 

	
 
@@ -1530,20 +1617,19 @@ bool VehicleHasDepotOrders(const Vehicle
 
 * Delete all orders from a vehicle
 
 *
 
 */
 
void DeleteVehicleOrders(Vehicle *v)
 
void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist)
 
{
 
	DeleteOrderWarnings(v);
 

	
 
	if (v->IsOrderListShared()) {
 
		/* Remove ourself from the shared order list. */
 
		v->RemoveFromShared();
 
	} else if (v->orders != NULL) {
 
		v->orders.list = NULL;
 
	} else if (v->orders.list != NULL) {
 
		/* Remove the orders */
 
		v->orders->FreeChain();
 
		v->orders.list->FreeChain(keep_orderlist);
 
		if (!keep_orderlist) v->orders.list = NULL;
 
	}
 

	
 
	v->orders = NULL;
 
	v->num_orders = 0;
 
}
 

	
 
Date GetServiceIntervalClamped(uint index)
 
@@ -1807,6 +1893,9 @@ void InitializeOrders()
 
	_Order_pool.CleanPool();
 
	_Order_pool.AddBlockToPool();
 

	
 
	_OrderList_pool.CleanPool();
 
	_OrderList_pool.AddBlockToPool();
 

	
 
	_backup_orders_tile = 0;
 
}
 

	
 
@@ -1892,6 +1981,35 @@ static void Load_ORDR()
 
	}
 
}
 

	
 
const SaveLoad *GetOrderListDescription() {
 
static const SaveLoad _orderlist_desc[] = {
 
	SLE_REF(OrderList, first,              REF_ORDER),
 
	SLE_END()
 
};
 
	return _orderlist_desc;
 
}
 

	
 
static void Save_ORDL()
 
{
 
	OrderList *list;
 

	
 
	FOR_ALL_ORDER_LISTS(list) {
 
		SlSetArrayIndex(list->index);
 
		SlObject(list, GetOrderListDescription());
 
	}
 
}
 

	
 
static void Load_ORDL()
 
{
 
	int index;
 

	
 
	while ((index = SlIterateArray()) != -1) {
 
		OrderList *list = new (index) OrderList();
 
		SlObject(list, GetOrderListDescription());
 
	}
 
}
 

	
 
extern const ChunkHandler _order_chunk_handlers[] = {
 
	{ 'ORDR', Save_ORDR, Load_ORDR, CH_ARRAY | CH_LAST},
 
	{ 'ORDR', Save_ORDR, Load_ORDR, CH_ARRAY},
 
	{ 'ORDL', Save_ORDL, Load_ORDL, CH_ARRAY | CH_LAST},
 
};
src/order_func.h
Show inline comments
 
@@ -34,7 +34,7 @@ void RemoveOrderFromAllVehicles(OrderTyp
 
void InvalidateVehicleOrder(const Vehicle *v, int data);
 
bool VehicleHasDepotOrders(const Vehicle *v);
 
void CheckOrders(const Vehicle*);
 
void DeleteVehicleOrders(Vehicle *v);
 
void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist = false);
 
bool ProcessOrders(Vehicle *v);
 
bool UpdateOrderDest(Vehicle *v, const Order *order, int conditional_depth = 0);
 
VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v);
src/order_type.h
Show inline comments
 
@@ -9,6 +9,7 @@
 

	
 
typedef byte VehicleOrderID;  ///< The index of an order within its current vehicle (not pool related)
 
typedef uint16 OrderID;
 
typedef uint16 OrderListID;
 
typedef uint16 DestinationID;
 

	
 
enum {
 
@@ -149,5 +150,6 @@ enum {
 
};
 

	
 
struct Order;
 
struct OrderList;
 

	
 
#endif /* ORDER_TYPE_H */
src/saveload.cpp
Show inline comments
 
@@ -39,7 +39,7 @@
 

	
 
#include "table/strings.h"
 

	
 
extern const uint16 SAVEGAME_VERSION = 104;
 
extern const uint16 SAVEGAME_VERSION = 105;
 

	
 
SavegameType _savegame_type; ///< type of savegame we are loading
 

	
 
@@ -1367,6 +1367,7 @@ static uint ReferenceToInt(const void *o
 
		case REF_ROADSTOPS: return ((const RoadStop*)obj)->index + 1;
 
		case REF_ENGINE_RENEWS: return ((const EngineRenew*)obj)->index + 1;
 
		case REF_CARGO_PACKET:  return ((const CargoPacket*)obj)->index + 1;
 
		case REF_ORDERLIST:     return ((const   OrderList*)obj)->index + 1;
 
		default: NOT_REACHED();
 
	}
 

	
 
@@ -1399,6 +1400,10 @@ static void *IntToReference(uint index, 
 
	index--; // correct for the NULL index
 

	
 
	switch (rt) {
 
		case REF_ORDERLIST:
 
			if (_OrderList_pool.AddBlockIfNeeded(index)) return GetOrderList(index);
 
			error("Orders: failed loading savegame: too many order lists");
 

	
 
		case REF_ORDER:
 
			if (_Order_pool.AddBlockIfNeeded(index)) return GetOrder(index);
 
			error("Orders: failed loading savegame: too many orders");
src/saveload.h
Show inline comments
 
@@ -66,6 +66,7 @@ enum SLRefType {
 
	REF_ROADSTOPS     = 5,
 
	REF_ENGINE_RENEWS = 6,
 
	REF_CARGO_PACKET  = 7,
 
	REF_ORDERLIST     = 8,
 
};
 

	
 
#define SL_MAX_VERSION 255
src/timetable_cmd.cpp
Show inline comments
 
@@ -17,12 +17,16 @@
 
static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16 time, bool is_journey)
 
{
 
	Order *order = GetVehicleOrder(v, order_number);
 
	int delta;
 

	
 
	if (is_journey) {
 
		delta = time - order->travel_time;
 
		order->travel_time = time;
 
	} else {
 
		delta = time - order->wait_time;
 
		order->wait_time = time;
 
	}
 
	v->orders.list->UpdateOrderTimetable(delta);
 

	
 
	for (v = v->FirstShared(); v != NULL; v = v->NextShared()) {
 
		if (v->cur_order_index == order_number && v->current_order.Equals(*order)) {
src/train_cmd.cpp
Show inline comments
 
@@ -1274,8 +1274,7 @@ CommandCost CmdMoveRailVehicle(TileIndex
 
				if (!IsFrontEngine(src)) {
 
					/* setting the type to 0 also involves setting up the orders field. */
 
					SetFrontEngine(src);
 
					assert(src->orders == NULL);
 
					src->num_orders = 0;
 
					assert(src->orders.list == NULL);
 

	
 
					/* Decrease the engines number of the src engine_type */
 
					if (!IsDefaultGroupID(src->group_id) && IsValidGroupID(src->group_id)) {
 
@@ -1453,8 +1452,7 @@ CommandCost CmdSellRailWagon(TileIndex t
 
							first->group_id        = DEFAULT_GROUP;
 

	
 
							/* Copy orders (by sharing) */
 
							new_f->orders          = first->orders;
 
							new_f->num_orders      = first->GetNumOrders();
 
							new_f->orders.list     = first->orders.list;
 
							new_f->AddToShared(first);
 
							DeleteVehicleOrders(first);
 

	
src/vehicle.cpp
Show inline comments
 
@@ -59,6 +59,8 @@
 
#include "table/sprites.h"
 
#include "table/strings.h"
 

	
 
#include <map>
 

	
 
#define INVALID_COORD (0x7fffffff)
 
#define GEN_HASH(x, y) ((GB((y), 6, 6) << 6) + GB((x), 7, 6))
 

	
 
@@ -221,7 +223,7 @@ void VehiclePositionChanged(Vehicle *v)
 
}
 

	
 
/** Called after load to update coordinates */
 
void AfterLoadVehicles(bool clear_te_id)
 
void AfterLoadVehicles(bool part_of_load)
 
{
 
	Vehicle *v;
 

	
 
@@ -232,7 +234,7 @@ void AfterLoadVehicles(bool clear_te_id)
 

	
 
		v->UpdateDeltaXY(v->direction);
 

	
 
		if (clear_te_id) v->fill_percent_te_id = INVALID_TE_ID;
 
		if (part_of_load) v->fill_percent_te_id = INVALID_TE_ID;
 
		v->first = NULL;
 
		if (v->type == VEH_TRAIN) v->u.rail.first_engine = INVALID_ENGINE;
 
		if (v->type == VEH_ROAD)  v->u.road.first_engine = INVALID_ENGINE;
 
@@ -240,19 +242,45 @@ void AfterLoadVehicles(bool clear_te_id)
 
		v->cargo.InvalidateCache();
 
	}
 

	
 
	/* AfterLoadVehicles may also be called in case of NewGRF reload, in this
 
	 * case we may not convert orders again. */
 
	if (part_of_load) {
 
		/* Create shared vehicle chain for very old games (pre 5,2) and create
 
		 * OrderList from shared vehicle chains. For this to work correctly, the
 
		 * following conditions must be fulfilled:
 
		 * a) both next_shared and previous_shared are not set for pre 5,2 games
 
		 * b) both next_shared and previous_shared are set for later games
 
		 */
 
		std::map<Order*, OrderList*> mapping;
 

	
 
		FOR_ALL_VEHICLES(v) {
 
			if (v->orders.old != NULL) {
 
				if (CheckSavegameVersion(105)) { // Pre-105 didn't save an OrderList
 
					if (mapping[v->orders.old] == NULL) {
 
						/* This adds the whole shared vehicle chain for case b */
 
						v->orders.list = mapping[v->orders.old] = new OrderList(v->orders.old, v);
 
					} else {
 
						v->orders.list = mapping[v->orders.old];
 
						/* For old games (case a) we must create the shared vehicle chain */
 
						if (CheckSavegameVersionOldStyle(5, 2)) {
 
							v->AddToShared(v->orders.list->GetFirstSharedVehicle());
 
						}
 
					}
 
				} else { // OrderList was saved as such, only recalculate not saved values
 
					if (v->PreviousShared() == NULL) {
 
						new (v->orders.list) OrderList(v->orders.list->GetFirstOrder(), v);
 
					}
 
				}
 
			}
 
		}
 
	}
 

	
 
	FOR_ALL_VEHICLES(v) {
 
		/* Fill the first pointers */
 
		if (v->Previous() == NULL) {
 
			for (Vehicle *u = v; u != NULL; u = u->Next()) {
 
				u->first = v;
 
			}
 

	
 
			/* Shared orders are only valid for first vehicles in chains. */
 
			if (v->previous_shared == NULL) {
 
				for (Vehicle *u = v; u != NULL; u = u->NextShared()) {
 
					u->first_shared = v;
 
				}
 
			}
 
		}
 
	}
 

	
 
@@ -315,7 +343,6 @@ Vehicle::Vehicle()
 
	this->group_id           = DEFAULT_GROUP;
 
	this->fill_percent_te_id = INVALID_TE_ID;
 
	this->first              = this;
 
	this->first_shared       = this;
 
	this->colormap           = PAL_NONE;
 
}
 

	
 
@@ -2168,7 +2195,8 @@ static const SaveLoad _common_veh_desc[]
 
	SLE_CONDVAR(Vehicle, running_ticks,        SLE_UINT8,                   88, SL_MAX_VERSION),
 

	
 
	    SLE_VAR(Vehicle, cur_order_index,      SLE_UINT8),
 
	    SLE_VAR(Vehicle, num_orders,           SLE_UINT8),
 
	/* 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
 
@@ -2189,7 +2217,8 @@ static const SaveLoad _common_veh_desc[]
 
	SLE_CONDVARX(cpp_offsetof(Vehicle, current_order) + cpp_offsetof(Order, wait_time),      SLE_UINT16, 67, SL_MAX_VERSION),
 
	SLE_CONDVARX(cpp_offsetof(Vehicle, current_order) + cpp_offsetof(Order, travel_time),    SLE_UINT16, 67, SL_MAX_VERSION),
 

	
 
	    SLE_REF(Vehicle, orders,               REF_ORDER),
 
	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),
 
@@ -2409,7 +2438,6 @@ void Load_VEHS()
 
	_vehicles_to_autoreplace.Reset();
 

	
 
	int index;
 
	Vehicle *v;
 

	
 
	_cargo_count = 0;
 

	
 
@@ -2456,22 +2484,6 @@ void Load_VEHS()
 
		/* Advanced vehicle lists got added */
 
		if (CheckSavegameVersion(60)) v->group_id = DEFAULT_GROUP;
 
	}
 

	
 
	/* Check for shared order-lists (we now use pointers for that) */
 
	if (CheckSavegameVersionOldStyle(5, 2)) {
 
		FOR_ALL_VEHICLES(v) {
 
			Vehicle *u;
 

	
 
			FOR_ALL_VEHICLES_FROM(u, v->index + 1) {
 
				/* If a vehicle has the same orders, add the link to eachother
 
				 *  in both vehicles */
 
				if (v->orders == u->orders) {
 
					u->AddToShared(v);
 
					break;
 
				}
 
			}
 
		}
 
	}
 
}
 

	
 
extern const ChunkHandler _veh_chunk_handlers[] = {
 
@@ -2651,47 +2663,51 @@ void Vehicle::SetNext(Vehicle *next)
 

	
 
void Vehicle::AddToShared(Vehicle *shared_chain)
 
{
 
	assert(!this->IsOrderListShared());
 
	assert(this->previous_shared == NULL && this->next_shared == NULL);
 

	
 
	if (!shared_chain->orders.list) {
 
		assert(shared_chain->previous_shared == NULL);
 
		assert(shared_chain->next_shared == NULL);
 
		this->orders.list = shared_chain->orders.list = new OrderList(NULL, shared_chain);
 
	}
 

	
 
	this->next_shared     = shared_chain->next_shared;
 
	this->previous_shared = shared_chain;
 
	this->first_shared    = shared_chain->first_shared;
 

	
 
	shared_chain->next_shared = this;
 

	
 
	if (this->next_shared != NULL) this->next_shared->previous_shared = this;
 

	
 
	shared_chain->orders.list->AddVehicle(this);
 
}
 

	
 
void Vehicle::RemoveFromShared()
 
{
 
	Vehicle *new_first;
 

	
 
	if (this->FirstShared() == this) {
 
		/* We are the first shared one, so update all the first pointers of our next shared ones. */
 
		new_first = this->NextShared();
 
		for (Vehicle *u = new_first; u != NULL; u = u->NextShared()) {
 
			u->first_shared = new_first;
 
		}
 
	} else {
 
	/* Remember if we were first and the old window number before RemoveVehicle()
 
	 * as this changes first if needed. */
 
	bool were_first = (this->FirstShared() == this);
 
	uint32 old_window_number = (this->FirstShared()->index << 16) | (this->type << 11) | VLW_SHARED_ORDERS | this->owner;
 

	
 
	this->orders.list->RemoveVehicle(this);
 

	
 
	if (!were_first) {
 
		/* We are not the first shared one, so only relink our previous one. */
 
		new_first = this->FirstShared();
 
		this->previous_shared->next_shared = this->NextShared();
 
	}
 

	
 
	if (this->next_shared != NULL) this->next_shared->previous_shared = this->previous_shared;
 

	
 
	uint32 old_window_number = (this->FirstShared()->index << 16) | (this->type << 11) | VLW_SHARED_ORDERS | this->owner;
 

	
 
	if (new_first->NextShared() == NULL) {
 

	
 
	if (this->orders.list->GetNumVehicles() == 1) {
 
		/* When there is only one vehicle, remove the shared order list window. */
 
		DeleteWindowById(GetWindowClassForVehicleType(this->type), old_window_number);
 
		InvalidateVehicleOrder(new_first, 0);
 
	} else if (this->FirstShared() == this) {
 
		/* If we were the first one, update to the new first one. */
 
		InvalidateWindowData(GetWindowClassForVehicleType(this->type), old_window_number, (new_first->index << 16) | (1 << 15));
 
		InvalidateVehicleOrder(this->FirstShared(), 0);
 
	} else if (were_first) {
 
		/* If we were the first one, update to the new first one.
 
		 * Note: FirstShared() is already the new first */
 
		InvalidateWindowData(GetWindowClassForVehicleType(this->type), old_window_number, (this->FirstShared()->index << 16) | (1 << 15));
 
	}
 

	
 
	this->first_shared    = this;
 
	this->next_shared     = NULL;
 
	this->previous_shared = NULL;
 
}
src/vehicle_base.h
Show inline comments
 
@@ -194,7 +194,7 @@ DECLARE_OLD_POOL(Vehicle, Vehicle, 9, 12
 
/* Some declarations of functions, so we can make them friendly */
 
struct SaveLoad;
 
extern const SaveLoad *GetVehicleDescription(VehicleType vt);
 
extern void AfterLoadVehicles(bool clear_te_id);
 
extern void AfterLoadVehicles(bool part_of_load);
 
struct LoadgameState;
 
extern bool LoadOldVehicle(LoadgameState *ls, int num);
 

	
 
@@ -206,10 +206,9 @@ private:
 

	
 
	Vehicle *next_shared;     ///< pointer to the next vehicle that shares the order
 
	Vehicle *previous_shared; ///< NOSAVE: pointer to the previous vehicle in the shared order chain
 
	Vehicle *first_shared;    ///< NOSAVE: pointer to the first vehicle in the shared order chain
 
public:
 
	friend const SaveLoad *GetVehicleDescription(VehicleType vt); ///< So we can use private/protected variables in the saveload code
 
	friend void AfterLoadVehicles(bool clear_te_id);              ///< So we can set the previous and first pointers while loading
 
	friend void AfterLoadVehicles(bool part_of_load);              ///< So we can set the previous and first pointers while loading
 
	friend bool LoadOldVehicle(LoadgameState *ls, int num);       ///< So we can set the proper next pointer while loading
 

	
 
	char *name;              ///< Name of vehicle
 
@@ -302,10 +301,12 @@ public:
 

	
 
	byte vehstatus;                 ///< Status
 
	Order current_order;            ///< The current order (+ status, like: loading)
 
	VehicleOrderID num_orders;      ///< How many orders there are in the list
 
	VehicleOrderID cur_order_index; ///< The index to the current order
 

	
 
	Order *orders;                  ///< Pointer to the first order for this vehicle
 
	union {
 
		OrderList *list;              ///< Pointer to the order list for this vehicle
 
		Order     *old;               ///< Only used during conversion of old save games
 
	} orders;
 

	
 
	byte vehicle_flags;             ///< Used for gradual loading and other miscellaneous things (@see VehicleFlags enum)
 
	uint16 load_unload_time_rem;
 
@@ -482,6 +483,12 @@ public:
 

	
 

	
 
	/**
 
	 * Get the first order of the vehicles order list.
 
	 * @return first order of order list.
 
	 */
 
	inline Order *GetFirstOrder() const { return (this->orders.list == NULL) ? NULL : this->orders.list->GetFirstOrder(); }
 

	
 
	/**
 
	 * Adds this vehicle to a shared vehicle chain.
 
	 * @param shared_chain a vehicle of the chain with shared vehicles.
 
	 * @pre !this->IsOrderListShared()
 
@@ -494,29 +501,34 @@ public:
 
	void RemoveFromShared();
 

	
 
	/**
 
	 * Get the next vehicle of this vehicle.
 
	 * @note articulated parts are also counted as vehicles.
 
	 * @return the next vehicle or NULL when there isn't a next vehicle.
 
	 * Get the next vehicle of the shared vehicle chain.
 
	 * @return the next shared vehicle or NULL when there isn't a next vehicle.
 
	 */
 
	inline Vehicle *NextShared() const { return this->next_shared; }
 

	
 
	/**
 
	 * Get the previous vehicle of the shared vehicle chain
 
	 * @return the previous shared vehicle or NULL when there isn't a previous vehicle.
 
	 */
 
	inline Vehicle *PreviousShared() const { return this->previous_shared; }
 

	
 
	/**
 
	 * Get the first vehicle of this vehicle chain.
 
	 * @return the first vehicle of the chain.
 
	 */
 
	inline Vehicle *FirstShared() const { return this->first_shared; }
 
	inline Vehicle *FirstShared() const { return (this->orders.list == NULL) ? NULL : this->orders.list->GetFirstSharedVehicle(); }
 

	
 
	/**
 
	 * Check if we share our orders with another vehicle.
 
	 * @return true if there are other vehicles sharing the same order
 
	 */
 
	inline bool IsOrderListShared() const { return this->previous_shared != NULL || this->next_shared != NULL; };
 
	inline bool IsOrderListShared() const { return this->orders.list != NULL && this->orders.list->IsShared(); }
 

	
 
  /**
 
	/**
 
	 * Get the number of orders this vehicle has.
 
	 * @return the number of orders this vehicle has.
 
	 */
 
	inline VehicleOrderID GetNumOrders() const { return this->num_orders; }
 
	inline VehicleOrderID GetNumOrders() const { return (this->orders.list == NULL) ? 0 : this->orders.list->GetNumOrders(); }
 

	
 
	/**
 
	 * Copy certain configurations and statistics of a vehicle after successful autoreplace/renew
 
@@ -676,34 +688,14 @@ struct FreeUnitIDGenerator {
 
};
 

	
 
/* Returns order 'index' of a vehicle or NULL when it doesn't exists */
 
static inline Order *GetVehicleOrder(const Vehicle *v, int index)
 
{
 
	Order *order = v->orders;
 

	
 
	if (index < 0) return NULL;
 

	
 
	while (order != NULL && index-- > 0)
 
		order = order->next;
 

	
 
	return order;
 
}
 
static inline Order *GetVehicleOrder(const Vehicle *v, int index) { return (v->orders.list == NULL) ? NULL : v->orders.list->GetOrderAt(index); }
 

	
 
/**
 
 * Returns the last order of a vehicle, or NULL if it doesn't exists
 
 * @param v Vehicle to query
 
 * @return last order of a vehicle, if available
 
 */
 
static inline Order *GetLastVehicleOrder(const Vehicle *v)
 
{
 
	Order *order = v->orders;
 

	
 
	if (order == NULL) return NULL;
 

	
 
	while (order->next != NULL)
 
		order = order->next;
 

	
 
	return order;
 
}
 
static inline Order *GetLastVehicleOrder(const Vehicle *v) { return (v->orders.list == NULL) ? NULL : v->orders.list->GetLastOrder(); }
 

	
 
/**
 
 * Returns the Trackdir on which the vehicle is currently located.
0 comments (0 inline, 0 general)