(svn r1525) -Codechange: rewrote the _order_array, now it can be made dynamic.
authortruelight
Sat, 15 Jan 2005 19:06:22 +0000
changeset 1024 9b06b01490a4
parent 1023 8df956881058
child 1025 882be6e4ad19
(svn r1525) -Codechange: rewrote the _order_array, now it can be made dynamic.
-Codechange: renamed all 'schedule' stuff to 'order(list)'
-Codechange: moved all order-stuff to order_cmd.c / order.h
-Codechange: vehicles that share orders are now linked to eachother
with next_shared/prev_shared in Vehicle

Developers: please use AssignOrder to assign data to an order. If not,
you _WILL_ make the save-routine to assert!
ai.c
ai_new.c
aircraft_cmd.c
aircraft_gui.c
misc.c
oldloader.c
order.h
order_cmd.c
order_gui.c
rail_cmd.c
roadveh_cmd.c
saveload.c
saveload.h
ship_cmd.c
ship_gui.c
station.h
station_cmd.c
train_cmd.c
ttd.c
vehicle.c
vehicle.h
vehicle_gui.c
--- a/ai.c	Sat Jan 15 16:38:10 2005 +0000
+++ b/ai.c	Sat Jan 15 19:06:22 2005 +0000
@@ -3618,7 +3618,7 @@
 
 	// Get a list of all stations that are in use by a vehicle
 	memset(in_use, 0, sizeof(in_use));
-	for (ord = _order_array; ord != _ptr_to_next_order; ++ord) {
+	FOR_ALL_ORDERS(ord) {
 		if (ord->type == OT_GOTO_STATION)
 			in_use[ord->station] = 1;
 	}
--- a/ai_new.c	Sat Jan 15 16:38:10 2005 +0000
+++ b/ai_new.c	Sat Jan 15 19:06:22 2005 +0000
@@ -502,14 +502,12 @@
 	// Also check if we don't have already a lot of busses to this city...
 	FOR_ALL_VEHICLES(v) {
 		if (v->owner == _current_player) {
-			const Order *sched = v->schedule_ptr;
-			if (sched != NULL) {
-				for (; sched->type != OT_NOTHING; ++sched) {
-					if (sched->type == OT_GOTO_STATION &&
-							GetStation(sched->station) == st) {
-						// This vehicle has this city in his list
-						count++;
-					}
+			const Order *order;
+
+			FOR_VEHICLE_ORDERS(v, order) {
+				if (order->type == OT_GOTO_STATION && GetStation(order->station) == st) {
+					// This vehicle has this city in its list
+					count++;
 				}
 			}
 		}
--- a/aircraft_cmd.c	Sat Jan 15 16:38:10 2005 +0000
+++ b/aircraft_cmd.c	Sat Jan 15 19:06:22 2005 +0000
@@ -126,7 +126,7 @@
 
 	// allocate 2 or 3 vehicle structs, depending on type
 	if (!AllocateVehicles(vl, (avi->subtype & 1) == 0 ? 3 : 2) ||
-			_ptr_to_next_order >= endof(_order_array))
+				IsOrderPoolFull())
 					return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
 
 	unit_num = GetFreeUnitNumber(VEH_Aircraft);
@@ -200,9 +200,6 @@
 
 		_new_aircraft_id = v->index;
 
-		_ptr_to_next_order->type = OT_NOTHING;
-		_ptr_to_next_order->flags = 0;
-		v->schedule_ptr = _ptr_to_next_order++;
 		// the AI doesn't click on a tile to build airplanes, so the below code will
 		// never work. Therefore just assume the AI's planes always come from Hangar0
 		// On hold for NewAI
@@ -490,7 +487,7 @@
 			v->current_order.flags & OF_FULL_LOAD)
 		return;
 
- 	if (_patches.gotodepot && ScheduleHasDepotOrders(v->schedule_ptr))
+	if (_patches.gotodepot && VehicleHasDepotOrders(v))
  		return;
 
 	st = GetStation(v->current_order.station);
@@ -510,13 +507,13 @@
 
 void InvalidateAircraftWindows(const Vehicle *v)
 {
-	const Order *o;
+	const Order *order;
 
 	InvalidateWindow(WC_AIRCRAFT_LIST, v->owner);
 
-	for ( o = v->schedule_ptr; o->type != OT_NOTHING; o++) {
-		if (o->type == OT_GOTO_STATION ) {
-			InvalidateWindow(WC_AIRCRAFT_LIST, o->station << 16 | v->owner);
+	FOR_VEHICLE_ORDERS(v, order) {
+		if (order->type == OT_GOTO_STATION ) {
+			InvalidateWindow(WC_AIRCRAFT_LIST, (order->station << 16) | v->owner);
 		}
 	}
 }
@@ -1024,21 +1021,9 @@
 	}
 }
 
-// returns true if the vehicle does have valid orders
-// false if none are valid
-static bool CheckForValidOrders(Vehicle *v)
-{
-	int i;
-	for (i = 0; i < v->num_orders; i++) {
-		if( v->schedule_ptr[i].type != OT_DUMMY )
-			return true;
-	}
-	return false;
-}
-
 static void ProcessAircraftOrder(Vehicle *v)
 {
-	Order order;
+	Order *order;
 
 	// OT_GOTO_DEPOT, OT_LOADING
 	if (v->current_order.type == OT_GOTO_DEPOT ||
@@ -1057,32 +1042,32 @@
 	if (v->cur_order_index >= v->num_orders)
 		v->cur_order_index = 0;
 
-	order = v->schedule_ptr[v->cur_order_index];
+	order = GetVehicleOrder(v, v->cur_order_index);
 
-	if (order.type == OT_NOTHING) {
+	if (order == NULL) {
 		v->current_order.type = OT_NOTHING;
 		v->current_order.flags = 0;
 		return;
 	}
 
-	if ( order.type == OT_DUMMY && !CheckForValidOrders(v))
+	if (order->type == OT_DUMMY && !CheckForValidOrders(v))
 		CrashAirplane(v);
 
-	if (order.type == v->current_order.type &&
-			order.flags == v->current_order.flags &&
-			order.station == v->current_order.station)
+	if (order->type    == v->current_order.type   &&
+			order->flags   == v->current_order.flags  &&
+			order->station == v->current_order.station)
 		return;
 
-	v->current_order = order;
+	v->current_order = *order;
 
 	// orders are changed in flight, ensure going to the right station
-	if (order.type == OT_GOTO_STATION && v->u.air.state == FLYING) {
+	if (order->type == OT_GOTO_STATION && v->u.air.state == FLYING) {
 		AircraftNextAirportPos_and_Order(v);
-		v->u.air.targetairport = order.station;
+		v->u.air.targetairport = order->station;
 	}
 
-	InvalidateVehicleOrderWidget(v);
-	
+	InvalidateVehicleOrder(v);
+
 	InvalidateAircraftWindows(v);
 }
 
@@ -1116,7 +1101,7 @@
 		}
 	}
 	v->cur_order_index++;
-	InvalidateVehicleOrderWidget(v);
+	InvalidateVehicleOrder(v);
 }
 
 static void CrashAirplane(Vehicle *v)
--- a/aircraft_gui.c	Sat Jan 15 16:38:10 2005 +0000
+++ b/aircraft_gui.c	Sat Jan 15 19:06:22 2005 +0000
@@ -920,16 +920,13 @@
 	}
 }
 
-static void DrawSmallSchedule(Vehicle *v, int x, int y) {
-	const Order *sched;
-	int sel;
-	Order ord;
-	int i = 0;
+static void DrawSmallOrderList(Vehicle *v, int x, int y) {
+	const Order *order;
+	int sel, i = 0;
 
-	sched = v->schedule_ptr;
 	sel = v->cur_order_index;
 
-	while ((ord = *sched++).type != OT_NOTHING) {
+	FOR_VEHICLE_ORDERS(v, order) {
 		if (sel == 0) {
 			_stringwidth_base = 0xE0;
 			DoDrawString( "\xAF", x-6, y, 16);
@@ -937,8 +934,8 @@
 		}
 		sel--;
 
-		if (ord.type == OT_GOTO_STATION) {
-			SetDParam(0, ord.station);
+		if (order->type == OT_GOTO_STATION) {
+			SetDParam(0, order->station);
 			DrawString(x, y, STR_A036, 0);
 
 			y += 6;
@@ -1052,7 +1049,7 @@
 				DrawString(x + 19, y, STR_01AB, 0);
 			}
 
-			DrawSmallSchedule(v, x + 136, y);
+			DrawSmallOrderList(v, x + 136, y);
 
 			y += PLY_WND_PRC__SIZE_OF_ROW_BIG;
 		}
--- a/misc.c	Sat Jan 15 16:38:10 2005 +0000
+++ b/misc.c	Sat Jan 15 19:06:22 2005 +0000
@@ -150,6 +150,8 @@
 	#endif
 }
 
+void InitializeVehicles();
+void InitializeOrders();
 void InitializeClearLand();
 void InitializeRail();
 void InitializeRailGui();
@@ -206,7 +208,7 @@
 	}
 
 	InitializeVehicles();
-	_backup_orders_tile = 0;
+	InitializeOrders();
 
 	InitNewsItemStructs();
 	InitializeLandscape();
--- a/oldloader.c	Sat Jan 15 16:38:10 2005 +0000
+++ b/oldloader.c	Sat Jan 15 19:06:22 2005 +0000
@@ -752,6 +752,22 @@
 	} while (n++,o++,--num);
 }
 
+static void FixOrder(uint16 *o, int num)
+{
+	Order *order;
+	int i;
+
+	for (i = 0; i < num; ++i) {
+		order = GetOrder(i);
+		AssignOrder(order, UnpackOldOrder(*o));
+		/* Recover the next list */
+		if (i > 0 && order->type != OT_NOTHING)
+			GetOrder(i - 1)->next = order;
+
+		o++;
+	}
+}
+
 static void FixVehicle(OldVehicle *o, int num)
 {
 	Vehicle *n;
@@ -767,10 +783,9 @@
 		n->subtype = o->subtype;
 
 		if (o->schedule_ptr == 0xFFFFFFFF || o->schedule_ptr == 0) {
-			n->schedule_ptr = NULL;
+			n->orders = NULL;
 		} else {
-			n->schedule_ptr = _order_array + REMAP_ORDER_IDX(o->schedule_ptr);
-			assert(n->schedule_ptr >= _order_array && n->schedule_ptr < _ptr_to_next_order);
+			n->orders = GetOrder(REMAP_ORDER_IDX(o->schedule_ptr));
 		}
 
 		n->current_order.type = o->next_order & 0x0f;
@@ -870,6 +885,31 @@
 			break;
 		}
 	} while (i++,o++,--num);
+
+	/* Check for shared orders, and link them correctly */
+	{
+		Vehicle *v;
+
+		FOR_ALL_VEHICLES(v) {
+			Vehicle *u;
+
+			if (v->type == 0)
+				continue;
+
+			FOR_ALL_VEHICLES_FROM(u, v->index + 1) {
+				if (u->type == 0)
+					continue;
+
+					/* If a vehicle has the same orders, add the link to eachother
+				in both vehicles */
+				if (v->orders == u->orders) {
+					v->next_shared = u;
+					u->prev_shared = v;
+					break;
+				}
+			}
+		}
+	}
 }
 
 static void FixSubsidy(Subsidy *n, OldSubsidy *o, int num)
@@ -1447,15 +1487,12 @@
 		}
 	}
 
-	for (i = 0; i < lengthof(m->order_list); ++i)
-		_order_array[i] = UnpackOldOrder(m->order_list[i]);
-	_ptr_to_next_order = _order_array + REMAP_ORDER_IDX(m->ptr_to_next_order);
-
 	FixTown(m->town_list, lengthof(m->town_list), m->town_name_type);
 	FixIndustry(m->industries, lengthof(m->industries));
 	FixStation(m->stations, lengthof(m->stations));
 
 	FixDepot(_depots, m->depots, lengthof(m->depots));
+	FixOrder(m->order_list, lengthof(m->order_list));
 	FixVehicle(m->vehicles, lengthof(m->vehicles));
 	FixSubsidy(_subsidies, m->subsidies, lengthof(m->subsidies));
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/order.h	Sat Jan 15 19:06:22 2005 +0000
@@ -0,0 +1,124 @@
+#ifndef ORDER_H
+#define ORDER_H
+
+/* Order types */
+enum {
+	OT_NOTHING       = 0,
+	OT_GOTO_STATION  = 1,
+	OT_GOTO_DEPOT    = 2,
+	OT_LOADING       = 3,
+	OT_LEAVESTATION  = 4,
+	OT_DUMMY         = 5,
+	OT_GOTO_WAYPOINT = 6
+};
+
+/* Order flags -- please use OFB instead OF and use HASBIT/SETBIT/CLEARBIT */
+enum {
+	OF_UNLOAD    = 0x2,
+	OF_FULL_LOAD = 0x4, // Also used when to force an aircraft into a depot
+	OF_NON_STOP  = 0x8
+};
+
+/* Order flags bits */
+enum {
+	OFB_UNLOAD    = 1,
+	OFB_FULL_LOAD = 2,
+	OFB_NON_STOP  = 3
+};
+
+/* Possible clone options */
+enum {
+	CO_SHARE   = 0,
+	CO_COPY    = 1,
+	CO_UNSHARE = 2
+};
+
+/* If you change this, keep in mind that it is saved on 3 places:
+    - Load_ORDR, all the global orders
+    - Vehicle -> current_order
+    - REF_SHEDULE (all REFs are currently limited to 16 bits!!) */
+typedef struct Order {
+	uint8  type;
+	uint8  flags;
+	uint16 station;
+
+	struct Order *next;   //! Pointer to next order. If NULL, end of list
+
+	uint16 index;         //! Index of the order, is not saved or anything, just for reference
+} Order;
+
+typedef struct {
+	VehicleID clone;
+	byte orderindex;
+	Order order[41];
+	uint16 service_interval;
+	char name[32];
+} BackuppedOrders;
+
+VARDEF TileIndex _backup_orders_tile;
+VARDEF BackuppedOrders _backup_orders_data[1];
+
+VARDEF Order _orders[5000];
+VARDEF uint32 _orders_size;
+
+static inline Order *GetOrder(uint index)
+{
+	assert(index < _orders_size);
+	return &_orders[index];
+}
+
+#define FOR_ALL_ORDERS_FROM(o, from) for(o = GetOrder(from); o != &_orders[_orders_size]; o++)
+#define FOR_ALL_ORDERS(o) FOR_ALL_ORDERS_FROM(o, 0)
+
+#define FOR_VEHICLE_ORDERS(v, order) for (order = v->orders; order != NULL; order = order->next)
+
+static inline bool HasOrderPoolFree(uint amount)
+{
+	Order *order;
+
+	FOR_ALL_ORDERS(order)
+		if (order->type == OT_NOTHING)
+			if (--amount == 0)
+				return true;
+
+	return false;
+}
+
+static inline bool IsOrderPoolFull()
+{
+	return !HasOrderPoolFree(1);
+}
+
+/* Pack and unpack routines */
+
+static inline uint32 PackOrder(const Order *order)
+{
+	return order->station << 16 | order->flags << 8 | order->type;
+}
+
+static inline Order UnpackOrder(uint32 packed)
+{
+	Order order;
+	order.type    = (packed & 0x000000FF);
+	order.flags   = (packed & 0x0000FF00) >> 8;
+	order.station = (packed & 0xFFFF0000) >> 16;
+	order.next    = NULL;
+	return order;
+}
+
+/* Functions */
+void BackupVehicleOrders(Vehicle *v, BackuppedOrders *order);
+void RestoreVehicleOrders(Vehicle *v, BackuppedOrders *order);
+void DeleteDestinationFromVehicleOrder(Order dest);
+void InvalidateVehicleOrder(const Vehicle *v);
+bool VehicleHasDepotOrders(const Vehicle *v);
+bool CheckOrders(const Vehicle *v);
+void DeleteVehicleOrders(Vehicle *v);
+bool IsOrderListShared(const Vehicle *v);
+void AssignOrder(Order *order, Order data);
+bool CheckForValidOrders(Vehicle *v);
+
+Order UnpackVersion4Order(uint16 packed);
+Order UnpackOldOrder(uint16 packed);
+
+#endif /* ORDER_H */
--- a/order_cmd.c	Sat Jan 15 16:38:10 2005 +0000
+++ b/order_cmd.c	Sat Jan 15 19:06:22 2005 +0000
@@ -6,27 +6,139 @@
 #include "station.h"
 #include "player.h"
 #include "news.h"
+#include "saveload.h"
 
-/* p1 & 0xFFFF = vehicle
- * p1 >> 16 = index in order list
- * p2 = order command to insert
+/**
+ *
+ * Unpacks a order from savegames made with TTD(Patch)
+ *
  */
-int32 CmdInsertOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
+Order UnpackOldOrder(uint16 packed)
 {
-	Vehicle *v = GetVehicle(p1 & 0xFFFF);
-	int sel = p1 >> 16;
-	Order new_order = UnpackOrder(p2);
+	Order order;
+	order.type    = (packed & 0x000F);
+	order.flags   = (packed & 0x00F0) >> 4;
+	order.station = (packed & 0xFF00) >> 8;
+	order.next    = NULL;
 
-	if (sel > v->num_orders) return_cmd_error(STR_EMPTY);
-	if (_ptr_to_next_order == endof(_order_array)) return_cmd_error(STR_8831_NO_MORE_SPACE_FOR_ORDERS);
-	if (v->num_orders >= 40) return_cmd_error(STR_8832_TOO_MANY_ORDERS);
+	// Sanity check
+	// TTD stores invalid orders as OT_NOTHING with non-zero flags/station
+	if (order.type == OT_NOTHING && (order.flags != 0 || order.station != 0)) {
+		order.type = OT_DUMMY;
+		order.flags = 0;
+	}
 
-	// for ships, make sure that the station is not too far away from the previous destination.
+	return order;
+}
+
+/**
+ *
+ * Unpacks a order from savegames with version 4 and lower
+ *
+ */
+Order UnpackVersion4Order(uint16 packed)
+{
+	Order order;
+	order.type    = (packed & 0x000F);
+	order.flags   = (packed & 0x00F0) >> 4;
+	order.station = (packed & 0xFF00) >> 8;
+	order.next    = NULL;
+	return order;
+}
+
+/**
+ *
+ * Updates the widgets of a vehicle which contains the order-data
+ *
+ */
+void InvalidateVehicleOrder(const Vehicle *v)
+{
+	InvalidateWindow(WC_VEHICLE_VIEW,   v->index);
+	InvalidateWindow(WC_VEHICLE_ORDERS, v->index);
+}
+
+/**
+ *
+ * Swap two orders
+ *
+ */
+static void SwapOrders(Order *order1, Order *order2)
+{
+	Order temp_order;
+
+	temp_order = *order1;
+	*order1 = *order2;
+	*order2 = temp_order;
+}
+
+/**
+ *
+ * Allocate a new order
+ *
+ * @return Order* if a free space is found, else NULL.
+ *
+ */
+static Order *AllocateOrder()
+{
+	Order *order;
+
+	FOR_ALL_ORDERS(order) {
+		if (order->type == OT_NOTHING) {
+			uint index = order->index;
+			memset(order, 0, sizeof(Order));
+			order->index = index;
+			return order;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ *
+ * Assign data to an order (from an other order)
+ *   This function makes sure that the index is maintained correctly
+ *
+ */
+void AssignOrder(Order *order, Order data)
+{
+	order->type    = data.type;
+	order->flags   = data.flags;
+	order->station = data.station;
+}
+
+/**
+ *
+ * Add an order to the orderlist of a vehicle
+ *
+ * @param veh_sel      First 16 bits are the ID of the vehicle. The next 16 are the selected order (if any)
+ *                       If the lastone is given, order will be inserted above thatone
+ * @param packed_order Packed order to insert
+ *
+ */
+int32 CmdInsertOrder(int x, int y, uint32 flags, uint32 veh_sel, uint32 packed_order)
+{
+	Vehicle *v      = GetVehicle(veh_sel & 0xFFFF);
+	int sel         = veh_sel >> 16;
+	Order new_order = UnpackOrder(packed_order);
+
+	if (sel > v->num_orders)
+		return_cmd_error(STR_EMPTY);
+
+	if (IsOrderPoolFull())
+		return_cmd_error(STR_8831_NO_MORE_SPACE_FOR_ORDERS);
+
+	/* XXX - This limit is only here because the backuppedorders can't
+	    handle any more then this.. */
+	if (v->num_orders >= 40)
+		return_cmd_error(STR_8832_TOO_MANY_ORDERS);
+
+	/* For ships, make sure that the station is not too far away from the previous destination. */
 	if (v->type == VEH_Ship && IS_HUMAN_PLAYER(v->owner) &&
-			sel != 0 && v->schedule_ptr[sel - 1].type == OT_GOTO_STATION) {
+		sel != 0 && GetVehicleOrder(v, sel - 1)->type == OT_GOTO_STATION) {
 
 		int dist = GetTileDist(
-			GetStation(v->schedule_ptr[sel - 1].station)->xy,
+			GetStation(GetVehicleOrder(v, sel - 1)->station)->xy,
 			GetStation(new_order.station)->xy
 		);
 		if (dist >= 130)
@@ -34,101 +146,158 @@
 	}
 
 	if (flags & DC_EXEC) {
-		Order *s1;
-		Order *s2;
+		Order *new;
 		Vehicle *u;
 
-		s1 = &v->schedule_ptr[sel];
-		s2 = _ptr_to_next_order++;
-		do s2[1] = s2[0]; while (--s2 >= s1);
-		*s1 = new_order;
-
-		s1 = v->schedule_ptr;
+		new = AllocateOrder();
+		AssignOrder(new, new_order);
 
-		FOR_ALL_VEHICLES(u) {
-			if (u->type != 0 && u->schedule_ptr != NULL) {
-				if (s1 < u->schedule_ptr) {
-					u->schedule_ptr++;
-				} else if (s1 == u->schedule_ptr) { // handle shared orders
-					u->num_orders++;
+		/* Create new order and link in list */
+		if (v->orders == NULL) {
+			v->orders = new;
+		} else {
+			/* Try to get the previous item (we are inserting above the
+			    selected) */
+			Order *order = GetVehicleOrder(v, sel - 1);
 
-					if ((byte)sel <= u->cur_order_index) {
-						sel++;
-						if ((byte)sel < u->num_orders)
-							u->cur_order_index = sel;
-					}
-					InvalidateWindow(WC_VEHICLE_VIEW, u->index);
-					InvalidateWindow(WC_VEHICLE_ORDERS, u->index);
-				}
+			if (order == NULL && GetVehicleOrder(v, sel) != 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);
+				/* Now update the next pointers */
+				v->orders->next = new;
+			} else if (order == NULL) {
+				/* 'sel' is a non-existing order, add him to the end */
+				order = GetLastVehicleOrder(v);
+				order->next = new;
+			} else {
+				/* Put the new order in between */
+				new->next = order->next;
+				order->next = new;
 			}
 		}
 
+		u = GetFirstVehicleFromSharedList(v);
+		while (u != NULL) {
+			/* 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);
+
+			/* If there is added an order before the current one, we need
+			to update the selected order */
+			if (sel <= u->cur_order_index) {
+				uint cur = u->cur_order_index + 1;
+				/* Check if we don't go out of bound */
+				if (cur < u->num_orders)
+					u->cur_order_index = cur;
+			}
+			/* Update any possible open window of the vehicle */
+			InvalidateVehicleOrder(u);
+
+			u = u->next_shared;
+		}
+
+		/* Make sure to rebuild the whole list */
 		RebuildVehicleLists();
 	}
 
 	return 0;
 }
 
+/**
+ *
+ * Declone an order-list
+ *
+ */
 static int32 DecloneOrder(Vehicle *dst, uint32 flags)
 {
-	if (_ptr_to_next_order == endof(_order_array))
-		return_cmd_error(STR_8831_NO_MORE_SPACE_FOR_ORDERS);
-
 	if (flags & DC_EXEC) {
-		DeleteVehicleSchedule(dst);
+		/* Delete orders from vehicle */
+		DeleteVehicleOrders(dst);
 
-		dst->num_orders = 0;
-		_ptr_to_next_order->type = OT_NOTHING;
-		_ptr_to_next_order->flags = 0;
-		dst->schedule_ptr = _ptr_to_next_order++;
-
-		InvalidateWindow(WC_VEHICLE_ORDERS, dst->index);
-
+		InvalidateVehicleOrder(dst);
 		RebuildVehicleLists();
 	}
 	return 0;
 }
 
-/* p1 = vehicle
- * p2 = sel
+/**
+ *
+ * Delete an order from the orderlist of a vehicle
+ *
+ * @param vehicle_id The ID of the vehicle
+ * @param selected   The order to delete
+ *
  */
-int32 CmdDeleteOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
+int32 CmdDeleteOrder(int x, int y, uint32 flags, uint32 vehicle_id, uint32 selected)
 {
-	Vehicle *v = GetVehicle(p1), *u;
-	uint sel = (uint)p2;
+	Vehicle *v = GetVehicle(vehicle_id), *u;
+	uint sel   = selected;
+	Order *order;
 
+	/* XXX -- Why is this here? :s */
 	_error_message = STR_EMPTY;
+
+	/* If we did not select an order, we maybe want to de-clone the orders */
 	if (sel >= v->num_orders)
 		return DecloneOrder(v, flags);
 
-	if (flags & DC_EXEC) {
-		Order *s1 = &v->schedule_ptr[sel];
-
-		// copy all orders to get rid of the hole
-		do s1[0] = s1[1]; while (++s1 != _ptr_to_next_order);
-		_ptr_to_next_order--;
-
-		s1 = v->schedule_ptr;
+	order = GetVehicleOrder(v, sel);
+	if (order == NULL)
+		return CMD_ERROR;
 
-		FOR_ALL_VEHICLES(u) {
-			if (u->type != 0 && u->schedule_ptr != NULL) {
-				if (s1 < u->schedule_ptr) {
-					u->schedule_ptr--;
-				} else if (s1 == u->schedule_ptr) {// handle shared orders
-					u->num_orders--;
-					if ((byte)sel < u->cur_order_index)
-						u->cur_order_index--;
+	if (flags & DC_EXEC) {
+		if (GetVehicleOrder(v, sel - 1) == NULL) {
+			if (GetVehicleOrder(v, sel + 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 + 1);
+				SwapOrders(v->orders, order);
+			} else {
+				/* Last item, so clean the list */
+				v->orders = NULL;
+			}
+		} else {
+			GetVehicleOrder(v, sel - 1)->next = order->next;
+		}
 
-					if ((byte)sel == u->cur_order_index &&
-							u->current_order.type == OT_LOADING &&
-							u->current_order.flags & OF_NON_STOP) {
-						u->current_order.flags = 0;
-					}
+		/* Give the item free */
+		order->type = OT_NOTHING;
 
-					InvalidateWindow(WC_VEHICLE_VIEW, u->index);
-					InvalidateWindow(WC_VEHICLE_ORDERS, u->index);
-				}
+		u = GetFirstVehicleFromSharedList(v);
+		while (u != NULL) {
+			u->num_orders--;
+
+			if (sel < 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);
+
+			/* NON-stop flag is misused to see if a train is in a station that is
+			    on his order list or not */
+			if (sel == u->cur_order_index &&
+					u->current_order.type == OT_LOADING &&
+					HASBIT(u->current_order.flags, OFB_NON_STOP)) {
+				u->current_order.flags = 0;
 			}
+
+			/* Update any possible open window of the vehicle */
+			InvalidateVehicleOrder(u);
+
+			u = u->next_shared;
 		}
 
 		RebuildVehicleLists();
@@ -137,321 +306,651 @@
 	return 0;
 }
 
-/* p1 = vehicle */
-int32 CmdSkipOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
+/**
+ *
+ * Goto next order of order-list
+ *
+ * @param vehicle_id The ID of the vehicle
+ *
+ */
+int32 CmdSkipOrder(int x, int y, uint32 flags, uint32 vehicle_id, uint32 not_used)
 {
-	Vehicle *v = GetVehicle(p1);
+	Vehicle *v = GetVehicle(vehicle_id);
 
 	if (flags & DC_EXEC) {
+		/* Goto next order */
 		{
 			byte b = v->cur_order_index + 1;
-			if (b >= v->num_orders) b = 0;
+			if (b >= v->num_orders)
+				b = 0;
+
 			v->cur_order_index = b;
 
 			if (v->type == VEH_Train)
 				v->u.rail.days_since_order_progr = 0;
 		}
 
+		/* NON-stop flag is misused to see if a train is in a station that is
+		    on his order list or not */
 		if (v->current_order.type == OT_LOADING &&
-				v->current_order.flags & OF_NON_STOP) {
+				HASBIT(v->current_order.flags, OFB_NON_STOP)) {
 			v->current_order.flags = 0;
 		}
 
-		InvalidateWindow(WC_VEHICLE_ORDERS, v->index);
+		InvalidateVehicleOrder(v);
 	}
 
-	//we have an aircraft, they have a mini-schedule, so update them all
+	/* We have an aircraft/ship, they have a mini-schedule, so update them all */
 	if (v->type == VEH_Aircraft) InvalidateAircraftWindows(v);
-
-	//same goes for ships
 	if (v->type == VEH_Ship) InvalidateShipWindows(v);
 
 	return 0;
 }
 
-/* p1 = vehicle
- * p2&0xFF = sel
- * p2>>8 = mode
+
+/**
+ *
+ * Add an order to the orderlist of a vehicle
+ *
+ * @param veh_sel      First 16 bits are the ID of the vehicle. The next 16 are the selected order (if any)
+ *                       If the lastone is given, order will be inserted above thatone
+ * @param mode         Mode to change the order to
+ *
  */
-int32 CmdModifyOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
+int32 CmdModifyOrder(int x, int y, uint32 flags, uint32 veh_sel, uint32 mode)
 {
-	Vehicle *v = GetVehicle(p1);
-	byte sel = (byte)p2;
-	Order *sched;
+	Vehicle *v = GetVehicle(veh_sel & 0xFFFF);
+	byte sel = veh_sel >> 16;
+	Order *order;
 
+	/* Is it a valid order? */
 	if (sel >= v->num_orders)
 		return CMD_ERROR;
 
-	sched = &v->schedule_ptr[sel];
-	if (sched->type != OT_GOTO_STATION &&
-			(sched->type != OT_GOTO_DEPOT || (p2 >> 8) == 1) &&
-			(sched->type != OT_GOTO_WAYPOINT || (p2 >> 8) != 2))
+	order = GetVehicleOrder(v, sel);
+	if (order->type != OT_GOTO_STATION &&
+			(order->type != OT_GOTO_DEPOT || mode == OFB_UNLOAD) &&
+			(order->type != OT_GOTO_WAYPOINT || mode != OFB_NON_STOP))
 		return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
-		switch (p2 >> 8) {
-		case 0: // full load
-			sched->flags ^= OF_FULL_LOAD;
-			if (sched->type != OT_GOTO_DEPOT) sched->flags &= ~OF_UNLOAD;
+		switch (mode) {
+		case OFB_FULL_LOAD:
+			TOGGLEBIT(order->flags, OFB_FULL_LOAD);
+			if (order->type != OT_GOTO_DEPOT)
+				CLRBIT(order->flags, OFB_UNLOAD);
 			break;
-		case 1: // unload
-			sched->flags ^= OF_UNLOAD;
-			sched->flags &= ~OF_FULL_LOAD;
+		case OFB_UNLOAD:
+			TOGGLEBIT(order->flags, OFB_UNLOAD);
+			CLRBIT(order->flags, OFB_FULL_LOAD);
 			break;
-		case 2: // non stop
-			sched->flags ^= OF_NON_STOP;
+		case OFB_NON_STOP:
+			TOGGLEBIT(order->flags, OFB_NON_STOP);
 			break;
 		}
-		sched = v->schedule_ptr;
 
-		FOR_ALL_VEHICLES(v) {
-			if (v->schedule_ptr == sched)
-				InvalidateWindow(WC_VEHICLE_ORDERS, v->index);
+		/* Update the windows, also for vehicles that share the same order list */
+		{
+			Vehicle *u = GetFirstVehicleFromSharedList(v);
+			while (u != NULL) {
+				InvalidateVehicleOrder(u);
+				u = u->next_shared;
+			}
 		}
-
 	}
 
 	return 0;
 }
 
-// Clone an order
-// p1 & 0xFFFF is destination vehicle
-// p1 >> 16 is source vehicle
+/**
+ *
+ * Clone/share/copy an order-list of an other vehicle
+ *
+ * @param veh1_veh2 First 16 bits are of destination vehicle, last 16 of source vehicle
+ * @param mode      Mode of cloning (CO_SHARE, CO_COPY, CO_UNSHARE)
+ *
+ */
+int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 veh1_veh2, uint32 mode)
+{
+	Vehicle *dst = GetVehicle(veh1_veh2 & 0xFFFF);
 
-// p2 is
-//   0 - clone
-//   1 - copy
-//   2 - unclone
-
-
-int32 CmdCloneOrder(int x, int y, uint32 flags, uint32 p1, uint32 p2)
-{
-	Vehicle *dst = GetVehicle(p1 & 0xFFFF);
-
-	if (!(dst->type && dst->owner == _current_player))
+	if (dst->type == 0 || dst->owner != _current_player)
 		return CMD_ERROR;
 
-	switch(p2) {
-
-	// share vehicle orders?
-	case 0: {
-		Vehicle *src = GetVehicle(p1 >> 16);
-
-		// sanity checks
-		if (!(src->owner == _current_player && dst->type == src->type && dst != src))
-			return CMD_ERROR;
-
-		// let's see what happens with road vehicles
-		if (src->type == VEH_Road) {
-			if (src->cargo_type != dst->cargo_type && (src->cargo_type == CT_PASSENGERS || dst->cargo_type == CT_PASSENGERS))
-				return CMD_ERROR;
-		}
-
-		if (flags & DC_EXEC) {
-			DeleteVehicleSchedule(dst);
-			dst->schedule_ptr = src->schedule_ptr;
-			dst->num_orders = src->num_orders;
-
-			InvalidateWindow(WC_VEHICLE_ORDERS, src->index);
-			InvalidateWindow(WC_VEHICLE_ORDERS, dst->index);
+	switch(mode) {
+		case CO_SHARE: {
+			Vehicle *src = GetVehicle(veh1_veh2 >> 16);
 
-			RebuildVehicleLists();
-		}
-		break;
-	}
-
-	// copy vehicle orders?
-	case 1: {
-		Vehicle *src = GetVehicle(p1 >> 16);
-		int delta;
+			/* Sanity checks */
+			if (src->type == 0 || src->owner != _current_player || dst->type != src->type || dst == src)
+				return CMD_ERROR;
 
-		// sanity checks
-		if (!(src->owner == _current_player && dst->type == src->type && dst != src))
-			return CMD_ERROR;
+			/* Trucks can't share orders with busses (and visa versa) */
+			if (src->type == VEH_Road) {
+				if (src->cargo_type != dst->cargo_type && (src->cargo_type == CT_PASSENGERS || dst->cargo_type == CT_PASSENGERS))
+					return CMD_ERROR;
+			}
 
-		// let's see what happens with road vehicles
-		if (src->type == VEH_Road) {
-			const Order *i;
-			TileIndex required_dst;
-
-			for (i = src->schedule_ptr; i->type != OT_NOTHING; ++i) {
-				if (i->type == OT_GOTO_STATION) {
-					const Station *st = GetStation(i->station);
-					required_dst = (dst->cargo_type == CT_PASSENGERS) ? st->bus_tile : st->lorry_tile;
-					if ( !required_dst )
+			/* Is the vehicle already in the shared list? */
+			{
+				Vehicle *u = GetFirstVehicleFromSharedList(src);
+				while (u != NULL) {
+					if (u == dst)
 						return CMD_ERROR;
+					u = u->next_shared;
 				}
 			}
-		}
-
-		// make sure there's orders available
-		delta = IsScheduleShared(dst) ? src->num_orders + 1 : src->num_orders - dst->num_orders;
-		if (delta > endof(_order_array) - _ptr_to_next_order)
-			return_cmd_error(STR_8831_NO_MORE_SPACE_FOR_ORDERS);
 
-		if (flags & DC_EXEC) {
-			DeleteVehicleSchedule(dst);
-			dst->schedule_ptr = _ptr_to_next_order;
-			dst->num_orders = src->num_orders;
-			_ptr_to_next_order += src->num_orders + 1;
-			memcpy(dst->schedule_ptr, src->schedule_ptr, (src->num_orders + 1) * sizeof(Order));
+			if (flags & DC_EXEC) {
+				/* If the destination vehicle had a OrderList, destroy it */
+				DeleteVehicleOrders(dst);
 
-			InvalidateWindow(WC_VEHICLE_ORDERS, dst->index);
+				dst->orders = src->orders;
+				dst->num_orders = src->num_orders;
 
-			RebuildVehicleLists();
-		}
-		break;
-	}
+				/* Link this vehicle in the shared-list */
+				dst->next_shared = src->next_shared;
+				dst->prev_shared = src;
+				if (src->next_shared != NULL)
+					src->next_shared->prev_shared = dst;
+				src->next_shared = dst;
 
-	// declone vehicle orders?
-	case 2: return DecloneOrder(dst, flags);
+				InvalidateVehicleOrder(dst);
+				InvalidateVehicleOrder(src);
+
+				RebuildVehicleLists();
+			}
+		} break;
+
+		case CO_COPY: {
+			Vehicle *src = GetVehicle(veh1_veh2 >> 16);
+			int delta;
+
+			/* Sanity checks */
+			if (src->type == 0 || src->owner != _current_player || dst->type != src->type || dst == src)
+				return CMD_ERROR;
+
+			/* Trucks can't copy all the orders from busses (and visa versa) */
+			if (src->type == VEH_Road) {
+				const Order *order;
+				TileIndex required_dst;
+
+				FOR_VEHICLE_ORDERS(src, order) {
+					if (order->type == OT_GOTO_STATION) {
+						const Station *st = GetStation(order->station);
+						required_dst = (dst->cargo_type == CT_PASSENGERS) ? st->bus_tile : st->lorry_tile;
+						/* This station has not the correct road-bay, so we can't copy! */
+						if (!required_dst)
+							return CMD_ERROR;
+					}
+				}
+			}
+
+			/* make sure there are orders available */
+			delta = IsOrderListShared(dst) ? src->num_orders + 1 : src->num_orders - dst->num_orders;
+			if (!HasOrderPoolFree(delta))
+				return_cmd_error(STR_8831_NO_MORE_SPACE_FOR_ORDERS);
+
+			if (flags & DC_EXEC) {
+				const Order *order;
+				Order **order_dst;
+
+				/* If the destination vehicle had a OrderList, destroy it */
+				DeleteVehicleOrders(dst);
+
+				order_dst = &dst->orders;
+				FOR_VEHICLE_ORDERS(src, order) {
+					*order_dst = AllocateOrder();
+					AssignOrder(*order_dst, *order);
+					order_dst = &(*order_dst)->next;
+				}
+
+				dst->num_orders = src->num_orders;
+
+				InvalidateVehicleOrder(dst);
+
+				RebuildVehicleLists();
+			}
+		} break;
+
+		case CO_UNSHARE:
+			return DecloneOrder(dst, flags);
 	}
 
 	return 0;
 }
 
+/**
+ *
+ * Backup a vehicle order-list, so you can replace a vehicle
+ *  without loosing the order-list
+ *
+ */
 void BackupVehicleOrders(Vehicle *v, BackuppedOrders *bak)
 {
-	Vehicle *u = IsScheduleShared(v);
+	bool shared = IsOrderListShared(v);
 
-	bak->orderindex = v->cur_order_index;
+	/* Save general info */
+	bak->orderindex       = v->cur_order_index;
 	bak->service_interval = v->service_interval;
 
+	/* Safe custom string, if any */
 	if ((v->string_id & 0xF800) != 0x7800) {
 		bak->name[0] = 0;
 	} else {
 		GetName(v->string_id & 0x7FF, bak->name);
 	}
 
-	// stored shared orders in this special way?
-	if (u != NULL) {
+	/* If we have shared orders, store it on a special way */
+	if (shared) {
+		Vehicle *u;
+		if (v->next_shared)
+			u = v->next_shared;
+		else
+			u = v->prev_shared;
+
 		bak->clone = u->index;
 	} else {
-		Order *sched = v->schedule_ptr;
-		Order *os = bak->order;
+		/* Else copy the orders */
+		Order *order, *dest;
 
+		dest  = bak->order;
+
+		/* We do not have shared orders */
 		bak->clone = INVALID_VEHICLE;
 
-		do {
-			*os++ = *sched++;
-		} while (sched->type != OT_NOTHING);
-		/* Make sure the last item is OT_NOTHING */
-		os->type = OT_NOTHING;
+		/* Copy the orders */
+		FOR_VEHICLE_ORDERS(v, order) {
+			*dest = *order;
+			dest++;
+		}
+		/* End the list with an OT_NOTHING */
+		dest->type = OT_NOTHING;
 	}
 }
 
+/**
+ *
+ * Restore vehicle orders that are backupped via BackupVehicleOrders
+ *
+ */
 void RestoreVehicleOrders(Vehicle *v, BackuppedOrders *bak)
 {
 	int i;
 
-	if (bak->name[0]) {
+	/* If we have a custom name, process that */
+	if (bak->name[0] != 0) {
 		strcpy((char*)_decode_parameters, bak->name);
 		DoCommandP(0, v->index, 0, NULL, CMD_NAME_VEHICLE);
 	}
 
-	DoCommandP(0, v->index, bak->orderindex|(bak->service_interval<<16) , NULL, CMD_RESTORE_ORDER_INDEX);
+	/* Restore vehicle number and service interval */
+	DoCommandP(0, v->index, bak->orderindex | (bak->service_interval << 16) , NULL, CMD_RESTORE_ORDER_INDEX);
 
+	/* If we had shared orders, recover that */
 	if (bak->clone != INVALID_VEHICLE) {
-		DoCommandP(0, v->index | bak->clone << 16, 0, NULL, CMD_CLONE_ORDER);
+		DoCommandP(0, v->index | (bak->clone << 16), 0, NULL, CMD_CLONE_ORDER);
 		return;
 	}
 
-	// CMD_NO_TEST_IF_IN_NETWORK is used here, because CMD_INSERT_ORDER checks if the
-	//  order number is one more than the current amount of orders, and because
-	//  in network the commands are queued before send, the second insert always
-	//  fails in test mode. By bypassing the test-mode, that no longer is a problem.
-	for (i = 0; bak->order[i].type != OT_NOTHING; ++i)
+	/* CMD_NO_TEST_IF_IN_NETWORK is used here, because CMD_INSERT_ORDER checks if the
+	    order number is one more than the current amount of orders, and because
+	    in network the commands are queued before send, the second insert always
+	    fails in test mode. By bypassing the test-mode, that no longer is a problem. */
+	for (i = 0; bak->order[i].type != OT_NOTHING; i++)
 		if (!DoCommandP(0, v->index + (i << 16), PackOrder(&bak->order[i]), NULL, CMD_INSERT_ORDER | CMD_NO_TEST_IF_IN_NETWORK))
 			break;
 }
 
-/*	p1 = vehicle
- *	upper 16 bits p2 = service_interval
- *	lower 16 bits p2 = cur_order_index
+/**
+ *
+ * Restore the current-order-index of a vehicle and sets service-interval
+ *
+ * @param vehicle_id The ID of the vehicle
+ * @param data       First 16 bits are the current-order-index
+ *                   The last 16 bits are the service-interval
+ *
  */
-int32 CmdRestoreOrderIndex(int x, int y, uint32 flags, uint32 p1, uint32 p2)
+int32 CmdRestoreOrderIndex(int x, int y, uint32 flags, uint32 vehicle_id, uint32 data)
 {
-	// nonsense to update the windows, since, train rebought will have its window deleted
 	if (flags & DC_EXEC) {
-		Vehicle *v = GetVehicle(p1);
-		v->service_interval = (uint16)(p2>>16);
-		v->cur_order_index = (byte)(p2&0xFFFF);
+		Vehicle *v = GetVehicle(vehicle_id);
+		v->service_interval = data >> 16;
+		v->cur_order_index = data & 0xFFFF;
 	}
+
 	return 0;
 }
 
-int CheckOrders(Vehicle *v)
+/**
+ *
+ * Check the orders of a vehicle, to see if there are invalid orders and stuff
+ *
+ */
+bool CheckOrders(const Vehicle *v)
 {
-	if (!_patches.order_review_system)	//User doesn't want things to be checked
-		return 0;
-
-	if(v->vehstatus & VS_CRASHED)
-		return 0;
-
-	if ( (_patches.order_review_system == 1) && (v->vehstatus & VS_STOPPED) )
-		return 0;
+	/* Does the user wants us to check things? */
+	if (_patches.order_review_system == 0)
+		return false;
 
-	/* only check every 20 days, so that we don't flood the message log */
+	/* Do nothing for crashed vehicles */
+	if(v->vehstatus & VS_CRASHED)
+		return false;
+
+	/* Do nothing for stopped vehicles if setting is '1' */
+	if ( (_patches.order_review_system == 1) && (v->vehstatus & VS_STOPPED) )
+		return false;
+
+	/* Only check every 20 days, so that we don't flood the message log */
 	if ( ( ( v->day_counter % 20) == 0 ) && (v->owner == _local_player) ) {
-		Order order;
-		Order old_order;
-		int i, n_st, problem_type = -1;
-		Station *st;
-		int message=0;
-		TileIndex required_tile=-1;
+		int n_st, problem_type = -1;
+		const Order *order;
+		const Station *st;
+		int message = 0;
 
-		/* check the order list */
-		order = v->schedule_ptr[0];
+		/* Check the order list */
 		n_st = 0;
 
-		old_order.type = OT_NOTHING;
-		old_order.flags = 0;
-		for (i = 0; order.type != OT_NOTHING; i++) {
-			order = v->schedule_ptr[i];
-			if (order.type == old_order.type &&
-					order.flags == old_order.flags &&
-					order.station == old_order.station) {
-				problem_type = 2;
-				break;
-			}
-			if (order.type == OT_DUMMY) {
+		FOR_VEHICLE_ORDERS(v, order) {
+			/* Dummy order? */
+			if (order->type == OT_DUMMY) {
 				problem_type = 1;
 				break;
 			}
-			if (order.type == OT_GOTO_STATION /*&& (order != old_order) */) {
-				//I uncommented this in order not to get two error messages
-				//when two identical entries are in the list
+			/* Does station have a load-bay for this vehicle? */
+			if (order->type == OT_GOTO_STATION) {
+				TileIndex required_tile;
+
 				n_st++;
-				st = GetStation(order.station);
-				required_tile = GetStationTileForVehicle(v,st);
-				if (!required_tile) problem_type = 3;
+				st = GetStation(order->station);
+				required_tile = GetStationTileForVehicle(v, st);
+				if (!required_tile)
+					problem_type = 3;
 			}
-			old_order = order; //store the old order
 		}
 
-		//Now, check the last and the first order
-		//as the last order is the end of order marker, jump back 2
-		if (i > 2 &&
-				v->schedule_ptr[0].type == v->schedule_ptr[i - 2].type &&
-				v->schedule_ptr[0].flags == v->schedule_ptr[i - 2].flags &&
-				v->schedule_ptr[0].station == v->schedule_ptr[i - 2].station)
+		/* Check if the last and the first order are the same */
+		if (v->num_orders > 1 &&
+				v->orders->type    == GetLastVehicleOrder(v)->type &&
+				v->orders->flags   == GetLastVehicleOrder(v)->flags &&
+				v->orders->station == GetLastVehicleOrder(v)->station)
 			problem_type = 2;
 
-		if ( (n_st < 2) && (problem_type == -1) ) problem_type = 0;
+		/* Do we only have 1 station in our order list? */
+		if ((n_st < 2) && (problem_type == -1))
+			problem_type = 0;
 
-		SetDParam(0, v->unitnumber);
+		/* We don't have a problem */
+		if (problem_type < 0)
+			return false;
 
 		message = (STR_TRAIN_HAS_TOO_FEW_ORDERS) + (((v->type) - VEH_Train) << 2) + problem_type;
 
-		if (problem_type < 0) return 0;
-
+		SetDParam(0, v->unitnumber);
 		AddNewsItem(
 			message,
-			NEWS_FLAGS(NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, 0),
+			NEWS_FLAGS(NM_SMALL, NF_VIEWPORT | NF_VEHICLE, NT_ADVICE, 0),
 			v->index,
 			0);
 	}
-	// End of order check
 
-	return 1;
+	return true;
 }
+
+/**
+ *
+ * Delete a destination (like station, waypoint, ..) from the orders of vehicles
+ *
+ * @param dest type and station has to be set. This order will be removed from all orders of vehicles
+ *
+ */
+void DeleteDestinationFromVehicleOrder(Order dest)
+{
+	Vehicle *v;
+	Order *order;
+	bool need_invalidate;
+
+	/* Go through all vehicles */
+	FOR_ALL_VEHICLES(v) {
+		if (v->type == 0 || v->orders == NULL)
+			continue;
+
+		/* Forget about this station if this station is removed */
+		if (v->last_station_visited == dest.station && dest.type == OT_GOTO_STATION)
+			v->last_station_visited = 0xFFFF;
+
+		/* Check the current order */
+		if (v->current_order.type    == dest.type &&
+				v->current_order.station == dest.station) {
+			/* Mark the order as DUMMY */
+			v->current_order.type = OT_DUMMY;
+			v->current_order.flags = 0;
+			InvalidateWindow(WC_VEHICLE_VIEW, v->index);
+		}
+
+		/* Clear the order from the order-list */
+		need_invalidate = false;
+		FOR_VEHICLE_ORDERS(v, order) {
+			if (order->type == dest.type && order->station == dest.station) {
+				/* Mark the order as DUMMY */
+				order->type = OT_DUMMY;
+				order->flags = 0;
+
+				need_invalidate = true;
+			}
+		}
+
+		/* Only invalidate once, and if needed */
+		if (need_invalidate)
+			InvalidateWindow(WC_VEHICLE_ORDERS, v->index);
+	}
+}
+
+/**
+ *
+ * Checks if a vehicle has a GOTO_DEPOT in his order list
+ *
+ * @return True if this is true (lol ;))
+ *
+ */
+bool VehicleHasDepotOrders(const Vehicle *v)
+{
+	const Order *order;
+
+	FOR_VEHICLE_ORDERS(v, order) {
+		if (order->type == OT_GOTO_DEPOT)
+			return true;
+	}
+
+	return false;
+}
+
+/**
+ *
+ * Delete all orders from a vehicle
+ *
+ */
+void DeleteVehicleOrders(Vehicle *v)
+{
+	Order *order, *cur;
+
+	/* If we have a shared order-list, don't delete the list, but just
+	    remove our pointer */
+	if (IsOrderListShared(v)) {
+		const Vehicle *u = v;
+
+		v->orders = NULL;
+		v->num_orders = 0;
+
+		/* Unlink ourself */
+		if (v->prev_shared != NULL) {
+			v->prev_shared->next_shared = v->next_shared;
+			u = v->prev_shared;
+		}
+		if (v->next_shared != NULL) {
+			v->next_shared->prev_shared = v->prev_shared;
+			u = v->next_shared;
+		}
+		v->prev_shared = NULL;
+		v->next_shared = NULL;
+
+		/* We only need to update this-one, because if there is a third
+		    vehicle which shares the same order-list, nothing will change. If
+		    this is the last vehicle, the last line of the order-window
+		    will change from Shared order list, to Order list, so it needs
+		    an update */
+		InvalidateVehicleOrder(u);
+		return;
+	}
+
+	/* Remove the orders */
+	cur = v->orders;
+	v->orders = NULL;
+	v->num_orders = 0;
+
+	order = NULL;
+	while (cur != NULL) {
+		if (order != NULL) {
+			order->type = OT_NOTHING;
+			order->next = NULL;
+		}
+
+		order = cur;
+		cur = cur->next;
+	}
+
+	if (order != NULL) {
+		order->type = OT_NOTHING;
+		order->next = NULL;
+	}
+}
+
+/**
+ *
+ * Check if we share our orders with an other vehicle
+ *
+ * @return Returns the vehicle who has the same order
+ *
+ */
+bool IsOrderListShared(const Vehicle *v)
+{
+	if (v->next_shared != NULL)
+		return true;
+
+	if (v->prev_shared != NULL)
+		return true;
+
+	return false;
+}
+
+/**
+ *
+ * Check if a vehicle has any valid orders
+ *
+ * @return false if there are no valid orders
+ *
+ */
+bool CheckForValidOrders(Vehicle *v)
+{
+	const Order *order;
+
+	FOR_VEHICLE_ORDERS(v, order)
+		if (order->type != OT_DUMMY)
+			return true;
+
+	return false;
+}
+
+void InitializeOrders(void)
+{
+	Order *order;
+	int i;
+
+	memset(&_orders, 0, sizeof(_orders[0]) * _orders_size);
+
+	i = 0;
+	FOR_ALL_ORDERS(order)
+		order->index = i++;
+
+	_backup_orders_tile = 0;
+}
+
+static const byte _order_desc[] = {
+	SLE_VAR(Order,type,					SLE_UINT8),
+	SLE_VAR(Order,flags,				SLE_UINT8),
+	SLE_VAR(Order,station,			SLE_UINT16),
+	SLE_REF(Order,next,					REF_ORDER),
+
+	// reserve extra space in savegame here. (currently 10 bytes)
+	SLE_CONDARR(NullStruct,null,SLE_FILE_U8 | SLE_VAR_NULL, 10, 5, 255),
+	SLE_END()
+};
+
+static void Save_ORDR()
+{
+	Order *order;
+
+	FOR_ALL_ORDERS(order) {
+		if (order->type != OT_NOTHING) {
+			SlSetArrayIndex(order->index);
+			SlObject(order, _order_desc);
+		}
+	}
+}
+
+static void Load_ORDR()
+{
+	if (_sl.full_version <= 0x501) {
+		/* Version older than 0x502 did not have a ->next pointer. Convert them
+		    (in the old days, the orderlist was 5000 items big) */
+		uint len = SlGetFieldLength();
+		uint i;
+
+		if (_sl.version < 5) {
+			/* Pre-version 5 had an other layout for orders
+			    (uint16 instead of uint32) */
+			uint16 orders[5000];
+
+			len /= sizeof(uint16);
+			assert (len <= _orders_size);
+
+			SlArray(orders, len, SLE_UINT16);
+
+			for (i = 0; i < len; ++i) {
+				AssignOrder(GetOrder(i), UnpackVersion4Order(orders[i]));
+			}
+		} else if (_sl.full_version <= 0x501) {
+			uint32 orders[5000];
+
+			len /= sizeof(uint32);
+			assert (len <= _orders_size);
+
+			SlArray(orders, len, SLE_UINT32);
+
+			for (i = 0; i < len; ++i) {
+				AssignOrder(GetOrder(i), UnpackOrder(orders[i]));
+			}
+		}
+
+		/* Update all the next pointer */
+		for (i = 1; i < len; ++i) {
+			/* The orders were built like this:
+			     Vehicle one had order[0], and as long as order++.type was not
+			     OT_NOTHING, it was part of the order-list of that vehicle */
+			if (GetOrder(i)->type != OT_NOTHING)
+				GetOrder(i - 1)->next = GetOrder(i);
+		}
+	} else {
+		int index;
+
+		while ((index = SlIterateArray()) != -1) {
+			Order *order = GetOrder(index);
+
+			SlObject(order, _order_desc);
+		}
+	}
+}
+
+const ChunkHandler _order_chunk_handlers[] = {
+	{ 'ORDR', Save_ORDR, Load_ORDR, CH_ARRAY | CH_LAST},
+};
--- a/order_gui.c	Sat Jan 15 16:38:10 2005 +0000
+++ b/order_gui.c	Sat Jan 15 19:06:22 2005 +0000
@@ -14,32 +14,23 @@
 static int OrderGetSel(Window *w)
 {
 	Vehicle *v = GetVehicle(w->window_number);
-	const Order *sched = v->schedule_ptr;
 	int num = WP(w,order_d).sel;
-	int count = 0;
-
-	if (num == 0)
-		return 0;
 
-	while (sched->type != OT_NOTHING) {
-		sched++;
-		count++;
-		if (--num == 0)
-			break;
-	}
+	if (num < 0 || num > v->num_orders)
+		return v->num_orders;
 
-	return count;
+	return num;
 }
 
 static void DrawOrdersWindow(Window *w)
 {
-	Vehicle *v;
-	int num, sel;
-	const Order *sched;
-	Order ord;
+	const Vehicle *v;
+	const Order *order;
+	StringID str;
+	int sel;
 	int y, i;
-	StringID str;
-	bool shared_schedule;
+	bool shared_orders;
+	byte color;
 
 	v = GetVehicle(w->window_number);
 
@@ -57,40 +48,41 @@
 		w->disabled_state |= 1 << 6;
 	}
 
-	shared_schedule = IsScheduleShared(v) != NULL;
+	shared_orders = IsOrderListShared(v);
 
-	sched = v->schedule_ptr;
-	num=0;
-	while (sched->type != OT_NOTHING) {
-		sched++;
-		num++;
-	}
-
-	if ((uint)num + shared_schedule <= (uint)WP(w,order_d).sel)
+	if ((uint)v->num_orders + shared_orders <= (uint)WP(w,order_d).sel)
 		SETBIT(w->disabled_state, 5); /* delete */
 
-	if (num == 0)
+	if (v->num_orders == 0)
 		SETBIT(w->disabled_state, 4); /* skip */
 
-	SetVScrollCount(w, num+1);
+	SetVScrollCount(w, v->num_orders + 1);
 
 	sel = OrderGetSel(w);
+	SetDParam(2, STR_8827_FULL_LOAD);
 
-	SetDParam(2,STR_8827_FULL_LOAD);
-	switch (v->schedule_ptr[sel].type) {
-	case OT_GOTO_STATION:
-		break;
-	case OT_GOTO_DEPOT:
-		SETBIT(w->disabled_state, 9);	/* unload */
-		SetDParam(2,STR_SERVICE);
-		break;
+	order = GetVehicleOrder(v, sel);
 
-	case OT_GOTO_WAYPOINT:
-		SETBIT(w->disabled_state, 8); /* full load */
-		SETBIT(w->disabled_state, 9); /* unload */
-		break;
+	if (order != NULL) {
+		switch (order->type) {
+			case OT_GOTO_STATION:
+				break;
+			case OT_GOTO_DEPOT:
+				SETBIT(w->disabled_state, 9);	/* unload */
+				SetDParam(2,STR_SERVICE);
+				break;
 
-	default:
+			case OT_GOTO_WAYPOINT:
+				SETBIT(w->disabled_state, 8); /* full load */
+				SETBIT(w->disabled_state, 9); /* unload */
+				break;
+
+			default:
+				SETBIT(w->disabled_state, 6); /* nonstop */
+				SETBIT(w->disabled_state, 8);	/* full load */
+				SETBIT(w->disabled_state, 9);	/* unload */
+		}
+	} else {
 		SETBIT(w->disabled_state, 6); /* nonstop */
 		SETBIT(w->disabled_state, 8);	/* full load */
 		SETBIT(w->disabled_state, 9);	/* unload */
@@ -102,61 +94,62 @@
 
 	y = 15;
 
-	i = 0;
-	for(;;) {
-		str = ((byte)v->cur_order_index == i) ? STR_8805 : STR_8804;
-
-		ord = v->schedule_ptr[i];
-
-		if ( (uint)(i - w->vscroll.pos) < 6) {
-
-			if (ord.type == OT_NOTHING) {
-				str = shared_schedule ? STR_END_OF_SHARED_ORDERS : STR_882A_END_OF_ORDERS;
-			} else {
-				SetDParam(1, 6);
+	i = w->vscroll.pos;
+	order = GetVehicleOrder(v, i);
+	while (order != NULL) {
+		str = (v->cur_order_index == i) ? STR_8805 : STR_8804;
 
-				if (ord.type == OT_GOTO_STATION) {
-					SetDParam(1, STR_8806_GO_TO + (ord.flags >> 1));
-					SetDParam(2, ord.station);
-				} else if (ord.type == OT_GOTO_DEPOT) {
-					StringID s = STR_NULL;
-					if (v->type == VEH_Aircraft) {
-						s = STR_GO_TO_AIRPORT_HANGAR;
-					  SetDParam(2, ord.station);
-					} else {
-						SetDParam(2, _depots[ord.station].town_index);
-						switch (v->type) {
-						case VEH_Train:	s = STR_880E_GO_TO_TRAIN_DEPOT; break;
-						case VEH_Road:	s = STR_9038_GO_TO_ROADVEH_DEPOT; break;
-						case VEH_Ship:	s = STR_GO_TO_SHIP_DEPOT; break;
-						}
+		if (i - w->vscroll.pos < 6) {
+			SetDParam(1, 6);
+
+			if (order->type == OT_GOTO_STATION) {
+				SetDParam(1, STR_8806_GO_TO + (order->flags >> 1));
+				SetDParam(2, order->station);
+			} else if (order->type == OT_GOTO_DEPOT) {
+				StringID s = STR_NULL;
+				if (v->type == VEH_Aircraft) {
+					s = STR_GO_TO_AIRPORT_HANGAR;
+					SetDParam(2, order->station);
+				} else {
+					SetDParam(2, _depots[order->station].town_index);
+					switch (v->type) {
+						case VEH_Train: s = STR_880E_GO_TO_TRAIN_DEPOT;   break;
+						case VEH_Road:  s = STR_9038_GO_TO_ROADVEH_DEPOT; break;
+						case VEH_Ship:  s = STR_GO_TO_SHIP_DEPOT;         break;
 					}
-					if (v->type == VEH_Train && ord.flags & OF_NON_STOP) s += 2;
-					if (ord.flags & OF_FULL_LOAD) ++s; /* XXX service */
-					SetDParam(1, s);
-				} else if (ord.type == OT_GOTO_WAYPOINT) {
-					SetDParam(2, ord.station);
-					SetDParam(1, (ord.flags & OF_NON_STOP) ? STR_GO_NON_STOP_TO_WAYPOINT : STR_GO_TO_WAYPOINT);
 				}
+				if (v->type == VEH_Train && order->flags & OF_NON_STOP)
+					s += 2;
+
+				if (order->flags & OF_FULL_LOAD)
+					s++; /* XXX service */
+
+				SetDParam(1, s);
+			} else if (order->type == OT_GOTO_WAYPOINT) {
+				SetDParam(1, (order->flags & OF_NON_STOP) ? STR_GO_NON_STOP_TO_WAYPOINT : STR_GO_TO_WAYPOINT);
+				SetDParam(2, order->station);
 			}
-			{
-				byte color = (i == WP(w,order_d).sel) ? 0xC : 0x10;
-				SetDParam(0, i+1);
-				if (ord.type != OT_DUMMY) {
-					DrawString(2, y, str, color);
-				} else {
-					SetDParam(1, STR_INVALID_ORDER);
-					SetDParam(2, ord.station);
-					DrawString(2, y, str, color);
-				}
+
+			color = (i == WP(w,order_d).sel) ? 0xC : 0x10;
+			SetDParam(0, i + 1);
+			if (order->type != OT_DUMMY) {
+				DrawString(2, y, str, color);
+			} else {
+				SetDParam(1, STR_INVALID_ORDER);
+				SetDParam(2, order->station);
+				DrawString(2, y, str, color);
 			}
 			y += 10;
 		}
 
 		i++;
+		order = order->next;
+	}
 
-		if (ord.type == OT_NOTHING)
-			break;
+	if (i - w->vscroll.pos < 6) {
+		str = shared_orders ? STR_END_OF_SHARED_ORDERS : STR_882A_END_OF_ORDERS;
+		color = (i == WP(w,order_d).sel) ? 0xC : 0x10;
+		DrawString(2, y, str, color);
 	}
 }
 
@@ -317,12 +310,6 @@
 	}
 }
 
-enum OrderFlags {
-	FULL_LOAD = 0,
-	UNLOAD = 1,
-	NON_STOP = 2
-};
-
 static void OrderClick_Goto(Window *w, Vehicle *v)
 {
 	InvalidateWidget(w, 7);
@@ -337,27 +324,27 @@
 
 static void OrderClick_FullLoad(Window *w, Vehicle *v)
 {
-	DoCommandP(v->tile, v->index, OrderGetSel(w) | (FULL_LOAD << 8), NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
+	DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), OFB_FULL_LOAD, NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
 }
 
 static void OrderClick_Unload(Window *w, Vehicle *v)
 {
-	DoCommandP(v->tile, v->index, OrderGetSel(w) | (UNLOAD << 8), NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
+	DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), OFB_UNLOAD,    NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
+}
+
+static void OrderClick_Nonstop(Window *w, Vehicle *v)
+{
+	DoCommandP(v->tile, v->index + (OrderGetSel(w) << 16), OFB_NON_STOP,  NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
 }
 
 static void OrderClick_Skip(Window *w, Vehicle *v)
 {
-	DoCommandP(v->tile,v->index, 0, NULL, CMD_SKIP_ORDER);
+	DoCommandP(v->tile, v->index, 0, NULL, CMD_SKIP_ORDER);
 }
 
 static void OrderClick_Delete(Window *w, Vehicle *v)
 {
-	DoCommandP(v->tile,v->index, OrderGetSel(w), NULL, CMD_DELETE_ORDER | CMD_MSG(STR_8834_CAN_T_DELETE_THIS_ORDER));
-}
-
-static void OrderClick_Nonstop(Window *w, Vehicle *v)
-{
-	DoCommandP(v->tile, v->index, OrderGetSel(w) | (NON_STOP << 8), NULL, CMD_MODIFY_ORDER | CMD_MSG(STR_8835_CAN_T_MODIFY_THIS_ORDER));
+	DoCommandP(v->tile, v->index, OrderGetSel(w), NULL, CMD_DELETE_ORDER | CMD_MSG(STR_8834_CAN_T_DELETE_THIS_ORDER));
 }
 
 typedef void OnButtonClick(Window *w, Vehicle *v);
@@ -399,18 +386,18 @@
 
 			sel += w->vscroll.pos;
 
-			if (_ctrl_pressed && sel < v->num_orders) { // watch out for schedule_ptr overflow
-				Order ord = v->schedule_ptr[sel];
+			if (_ctrl_pressed && sel < v->num_orders) {
+				Order *ord = GetVehicleOrder(v, sel);
 				int xy = 0;
-				switch (ord.type) {
+				switch (ord->type) {
 				case OT_GOTO_STATION:			/* station order */
-					xy = GetStation(ord.station)->xy ;
+					xy = GetStation(ord->station)->xy ;
 					break;
 				case OT_GOTO_DEPOT:				/* goto depot order */
-					xy = _depots[ord.station].xy;
+					xy = _depots[ord->station].xy;
 					break;
 				case OT_GOTO_WAYPOINT:	/* goto waypoint order */
-					xy = _waypoints[ord.station].xy;
+					xy = _waypoints[ord->station].xy;
 				}
 
 				if (xy)
@@ -447,7 +434,6 @@
 		case 9: /* unload button */
 			OrderClick_Unload(w, v);
 			break;
-
 		}
 	} break;
 
@@ -473,7 +459,7 @@
 	case WE_RCLICK: {
 		Vehicle *v = GetVehicle(w->window_number);
 		if (e->click.widget != 8) break;
-		if (v->schedule_ptr[OrderGetSel(w)].type == OT_GOTO_DEPOT)
+		if (GetVehicleOrder(v, OrderGetSel(w))->type == OT_GOTO_DEPOT)
 			GuiShowTooltips(STR_SERVICE_HINT);
 		else
 			GuiShowTooltips(STR_8857_MAKE_THE_HIGHLIGHTED_ORDER);
--- a/rail_cmd.c	Sat Jan 15 16:38:10 2005 +0000
+++ b/rail_cmd.c	Sat Jan 15 19:06:22 2005 +0000
@@ -768,10 +768,11 @@
 {
 	Order order;
 	cp->xy = 0;
+
 	order.type = OT_GOTO_WAYPOINT;
-	order.flags = 0;
 	order.station = cp - _waypoints;
-	DeleteCommandFromVehicleSchedule(order);
+	DeleteDestinationFromVehicleOrder(order);
+
 	if (~cp->town_or_string & 0xC000) DeleteName(cp->town_or_string);
 	RedrawWaypointSign(cp);
 }
--- a/roadveh_cmd.c	Sat Jan 15 16:38:10 2005 +0000
+++ b/roadveh_cmd.c	Sat Jan 15 19:06:22 2005 +0000
@@ -122,7 +122,7 @@
 		return cost;
 
 	v = AllocateVehicle();
-	if (v == NULL || _ptr_to_next_order >= endof(_order_array))
+	if (v == NULL || IsOrderPoolFull())
 		return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
 
 	/* find the first free roadveh id */
@@ -172,9 +172,6 @@
 		_new_roadveh_id = v->index;
 
 		v->string_id = STR_SV_ROADVEH_NAME;
-		_ptr_to_next_order->type = OT_NOTHING;
-		_ptr_to_next_order->flags = 0;
-		v->schedule_ptr = _ptr_to_next_order++;
 
 		v->service_interval = _patches.servint_roadveh;
 
@@ -554,11 +551,11 @@
 
 static void ProcessRoadVehOrder(Vehicle *v)
 {
-	Order order;
-	Station *st;
+	const Order *order;
+	const Station *st;
 
 	if (v->current_order.type >= OT_GOTO_DEPOT && v->current_order.type <= OT_LEAVESTATION) {
-		// Let a depot order in the schedule interrupt.
+		// Let a depot order in the orderlist interrupt.
 		if (v->current_order.type != OT_GOTO_DEPOT ||
 				!(v->current_order.flags & OF_UNLOAD))
 			return;
@@ -573,34 +570,35 @@
 	if (v->cur_order_index >= v->num_orders)
 		v->cur_order_index = 0;
 
-	order = v->schedule_ptr[v->cur_order_index];
+	order = GetVehicleOrder(v, v->cur_order_index);
 
-	if (order.type == OT_NOTHING) {
+	if (order == NULL) {
 		v->current_order.type = OT_NOTHING;
 		v->current_order.flags = 0;
 		v->dest_tile = 0;
 		return;
 	}
 
-	if (order.type == v->current_order.type &&
-			order.flags == v->current_order.flags &&
-			order.station == v->current_order.station)
+	if (order->type    == v->current_order.type &&
+			order->flags   == v->current_order.flags &&
+			order->station == v->current_order.station)
 		return;
 
-	v->current_order = order;
+	v->current_order = *order;
 
 	v->dest_tile = 0;
 
-	if (order.type == OT_GOTO_STATION) {
-		if (order.station == v->last_station_visited)
+	if (order->type == OT_GOTO_STATION) {
+		if (order->station == v->last_station_visited)
 			v->last_station_visited = 0xFFFF;
-		st = GetStation(order.station);
-		v->dest_tile = v->cargo_type==CT_PASSENGERS ? st->bus_tile : st->lorry_tile;
-	} else if (order.type == OT_GOTO_DEPOT) {
-		v->dest_tile = _depots[order.station].xy;
+
+		st = GetStation(order->station);
+		v->dest_tile = v->cargo_type == CT_PASSENGERS ? st->bus_tile : st->lorry_tile;
+	} else if (order->type == OT_GOTO_DEPOT) {
+		v->dest_tile = _depots[order->station].xy;
 	}
 
-	InvalidateVehicleOrderWidget(v);
+	InvalidateVehicleOrder(v);
 }
 
 static void HandleRoadVehLoading(Vehicle *v)
@@ -634,7 +632,7 @@
 	}
 
 	v->cur_order_index++;
-	InvalidateVehicleOrderWidget(v);
+	InvalidateVehicleOrder(v);
 }
 
 static void StartRoadVehSound(Vehicle *v)
@@ -1390,7 +1388,7 @@
 		v->current_order.type = OT_DUMMY;
 		v->current_order.flags = 0;
 
-		// Part of the schedule?
+		// Part of the orderlist?
 		if (t.flags & OF_UNLOAD) {
 			v->cur_order_index++;
 		} else if (t.flags & OF_FULL_LOAD) {
@@ -1436,7 +1434,7 @@
 	if (v->vehstatus & VS_STOPPED)
 		return;
 
-	if (_patches.gotodepot && ScheduleHasDepotOrders(v->schedule_ptr))
+	if (_patches.gotodepot && VehicleHasDepotOrders(v))
 		return;
 
 	// Don't interfere with a depot visit scheduled by the user, or a
--- a/saveload.c	Sat Jan 15 16:38:10 2005 +0000
+++ b/saveload.c	Sat Jan 15 19:06:22 2005 +0000
@@ -8,7 +8,7 @@
 
 enum {
 	SAVEGAME_MAJOR_VERSION = 5,
-	SAVEGAME_MINOR_VERSION = 1,
+	SAVEGAME_MINOR_VERSION = 2,
 
 	SAVEGAME_LOADABLE_VERSION = (SAVEGAME_MAJOR_VERSION << 8) + SAVEGAME_MINOR_VERSION
 };
@@ -869,6 +869,7 @@
 extern const ChunkHandler _misc_chunk_handlers[];
 extern const ChunkHandler _player_chunk_handlers[];
 extern const ChunkHandler _veh_chunk_handlers[];
+extern const ChunkHandler _order_chunk_handlers[];
 extern const ChunkHandler _town_chunk_handlers[];
 extern const ChunkHandler _sign_chunk_handlers[];
 extern const ChunkHandler _station_chunk_handlers[];
@@ -880,6 +881,7 @@
 static const ChunkHandler * const _chunk_handlers[] = {
 	_misc_chunk_handlers,
 	_veh_chunk_handlers,
+	_order_chunk_handlers,
 	_industry_chunk_handlers,
 	_economy_chunk_handlers,
 	_engine_chunk_handlers,
@@ -912,9 +914,7 @@
 		case REF_VEHICLE: return ((Vehicle *)v)->index + 1;
 		case REF_STATION: return ((Station *)v)->index + 1;
 		case REF_TOWN:    return ((Town *)v)->index + 1;
-
-		case REF_SCHEDULE:
-			return ((byte*)v - (byte*)_order_array) / sizeof(_order_array[0]) + 1;
+		case REF_ORDER:   return ((Order *)v)->index + 1;
 
 		default:
 			NOT_REACHED();
@@ -935,13 +935,11 @@
 		return NULL;
 
 	switch (t) {
+		case REF_ORDER:   return GetOrder(r - 1);
 		case REF_VEHICLE: return GetVehicle(r - 1);
 		case REF_STATION: return GetStation(r - 1);
 		case REF_TOWN:    return GetTown(r - 1);
 
-		case REF_SCHEDULE:
-			return (byte*)_order_array + (r - 1) * sizeof(_order_array[0]);
-
 		case REF_VEHICLE_OLD: {
 			/* Old vehicles were saved differently: invalid vehicle was 0xFFFF,
 			    and the index was not - 1.. correct for this */
--- a/saveload.h	Sat Jan 15 16:38:10 2005 +0000
+++ b/saveload.h	Sat Jan 15 19:06:22 2005 +0000
@@ -70,11 +70,11 @@
 extern SaverLoader _sl;
 
 enum {
-	REF_SCHEDULE = 0,
-	REF_VEHICLE = 1,
-	REF_STATION = 2,
-	REF_TOWN = 3,
-	REF_VEHICLE_OLD = 4,
+	REF_ORDER       = 0,
+	REF_VEHICLE     = 1,
+	REF_STATION     = 2,
+	REF_TOWN        = 3,
+	REF_VEHICLE_OLD = 4
 };
 
 
--- a/ship_cmd.c	Sat Jan 15 16:38:10 2005 +0000
+++ b/ship_cmd.c	Sat Jan 15 19:06:22 2005 +0000
@@ -23,13 +23,13 @@
 
 void InvalidateShipWindows(const Vehicle *v)
 {
-	const Order *o;
+	const Order *order;
 
 	InvalidateWindow(WC_SHIPS_LIST, v->owner);
 
-	for ( o = v->schedule_ptr; o->type != OT_NOTHING; o++) {
-		if (o->type == OT_GOTO_STATION ) {
-			InvalidateWindow(WC_SHIPS_LIST, o->station << 16 | v->owner);
+	FOR_VEHICLE_ORDERS(v, order) {
+			if (order->type == OT_GOTO_STATION ) {
+			InvalidateWindow(WC_SHIPS_LIST, (order->station << 16) | v->owner);
 		}
 	}
 }
@@ -113,7 +113,7 @@
 			v->current_order.flags & OF_FULL_LOAD)
 		return;
 
-	if (_patches.gotodepot && ScheduleHasDepotOrders(v->schedule_ptr))
+	if (_patches.gotodepot && VehicleHasDepotOrders(v))
 		return;
 
 	i = FindClosestShipDepot(v);
@@ -215,8 +215,7 @@
 
 static void ProcessShipOrder(Vehicle *v)
 {
-	Order order;
-	Station *st;
+	const Order *order;
 
 	if (v->current_order.type >= OT_GOTO_DEPOT &&
 			v->current_order.type <= OT_LEAVESTATION) {
@@ -235,36 +234,39 @@
 	if (v->cur_order_index >= v->num_orders)
 		v->cur_order_index = 0;
 
-	order = v->schedule_ptr[v->cur_order_index];
+	order = GetVehicleOrder(v, v->cur_order_index);
 
-	if (order.type == OT_NOTHING) {
-		v->current_order.type = OT_NOTHING;
+	if (order == NULL) {
+		v->current_order.type  = OT_NOTHING;
 		v->current_order.flags = 0;
 		v->dest_tile = 0;
 		return;
 	}
 
-	if (order.type == v->current_order.type &&
-			order.flags == v->current_order.flags &&
-			order.station == v->current_order.station)
+	if (order->type    == v->current_order.type &&
+			order->flags   == v->current_order.flags &&
+			order->station == v->current_order.station)
 		return;
 
-	v->current_order = order;
+	v->current_order = *order;
 
-	if (order.type == OT_GOTO_STATION) {
-		if (order.station == v->last_station_visited)
+	if (order->type == OT_GOTO_STATION) {
+		const Station *st;
+
+		if (order->station == v->last_station_visited)
 			v->last_station_visited = 0xFFFF;
 
-		st = GetStation(order.station);
+		st = GetStation(order->station);
 		if (st->dock_tile != 0) {
 			v->dest_tile = TILE_ADD(st->dock_tile, ToTileIndexDiff(_dock_offs[_map5[st->dock_tile]-0x4B]));
 		}
-	} else if (order.type == OT_GOTO_DEPOT) {
-		v->dest_tile = _depots[order.station].xy;
+	} else if (order->type == OT_GOTO_DEPOT) {
+		v->dest_tile = _depots[order->station].xy;
 	} else {
 		v->dest_tile = 0;
 	}
-	InvalidateVehicleOrderWidget(v);
+
+	InvalidateVehicleOrder(v);
 
 	InvalidateShipWindows(v);
 }
@@ -301,7 +303,7 @@
 	}
 
 	v->cur_order_index++;
-	InvalidateVehicleOrderWidget(v);
+	InvalidateVehicleOrder(v);
 }
 
 static void UpdateShipDeltaXY(Vehicle *v, int dir)
@@ -692,7 +694,7 @@
 
 					v->last_station_visited = v->current_order.station;
 
-					/* Process station in the schedule. Don't do that for buoys (HVOT_BUOY) */
+					/* Process station in the orderlist. Don't do that for buoys (HVOT_BUOY) */
 					st = GetStation(v->current_order.station);
 					if (!(st->had_vehicle_of_type & HVOT_BUOY)
 							&& (st->facilities & FACIL_DOCK)) { /* ugly, ugly workaround for problem with ships able to drop off cargo at wrong stations */
@@ -711,7 +713,7 @@
 						v->current_order.type = OT_LEAVESTATION;
 						v->current_order.flags = 0;
 						v->cur_order_index++;
-						InvalidateVehicleOrderWidget(v);
+						InvalidateVehicleOrder(v);
 					}
 					goto else_end;
 				}
@@ -830,7 +832,7 @@
 		return value;
 
 	v = AllocateVehicle();
-	if (v == NULL || _ptr_to_next_order >= endof(_order_array) ||
+	if (v == NULL || IsOrderPoolFull() ||
 			(unit_num = GetFreeUnitNumber(VEH_Ship)) > _patches.max_ships)
 		return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
 
@@ -871,9 +873,6 @@
 
 		v->string_id = STR_SV_SHIP_NAME;
 		v->u.ship.state = 0x80;
-		_ptr_to_next_order->type = OT_NOTHING;
-		_ptr_to_next_order->flags = 0;
-		v->schedule_ptr = _ptr_to_next_order++;
 
 		v->service_interval = _patches.servint_ships;
 		v->date_of_last_service = _date;
--- a/ship_gui.c	Sat Jan 15 16:38:10 2005 +0000
+++ b/ship_gui.c	Sat Jan 15 19:06:22 2005 +0000
@@ -863,15 +863,14 @@
 }
 
 
-static void DrawSmallShipSchedule(Vehicle *v, int x, int y) {
-	Order *sched;
-	int sel;
-	Station *st;
-	int i = 0;
+static void DrawSmallOrderList(Vehicle *v, int x, int y) {
+	const Order *order;
+	int sel, i = 0;
 
 	sel = v->cur_order_index;
+	order = v->orders;
 
-	for (sched = v->schedule_ptr; sched->type != OT_NOTHING; ++sched) {
+	while (order != NULL) {
 		if (sel == 0) {
 			_stringwidth_base = 0xE0;
 			DoDrawString( "\xAF", x-6, y, 16);
@@ -879,11 +878,9 @@
 		}
 		sel--;
 
-		if (sched->type == OT_GOTO_STATION) {
-			st = GetStation(sched->station);
-
-			if (!(st->had_vehicle_of_type & HVOT_BUOY)) {
-				SetDParam(0, sched->station);
+		if (order->type == OT_GOTO_STATION) {
+			if (!(GetStation(order->station)->had_vehicle_of_type & HVOT_BUOY)) {
+				SetDParam(0, order->station);
 				DrawString(x, y, STR_A036, 0);
 
 				y += 6;
@@ -891,6 +888,8 @@
 					break;
 			}
 		}
+
+		order = order->next;
 	}
 }
 
@@ -998,7 +997,7 @@
 				DrawString(x + 12, y, STR_01AB, 0);
 			}
 
-			DrawSmallShipSchedule(v, x + 138, y);
+			DrawSmallOrderList(v, x + 138, y);
 
 			y += PLY_WND_PRC__SIZE_OF_ROW_BIG;
 		}
--- a/station.h	Sat Jan 15 16:38:10 2005 +0000
+++ b/station.h	Sat Jan 15 19:06:22 2005 +0000
@@ -88,7 +88,7 @@
 
 void ModifyStationRatingAround(TileIndex tile, byte owner, int amount, uint radius);
 
-TileIndex GetStationTileForVehicle(Vehicle *v, Station *st);
+TileIndex GetStationTileForVehicle(const Vehicle *v, const Station *st);
 
 void ShowStationViewWindow(int station);
 void UpdateAllStationVirtCoord();
--- a/station_cmd.c	Sat Jan 15 16:38:10 2005 +0000
+++ b/station_cmd.c	Sat Jan 15 19:06:22 2005 +0000
@@ -94,7 +94,7 @@
 	return (closest_station == -1) ? NULL : GetStation(closest_station);
 }
 
-TileIndex GetStationTileForVehicle(Vehicle *v, Station *st)
+TileIndex GetStationTileForVehicle(const Vehicle *v, const Station *st)
 {
 	switch (v->type) {
 		case VEH_Train: 		return st->train_tile;
@@ -2257,10 +2257,11 @@
 
 	index = st->index;
 	DeleteWindowById(WC_STATION_VIEW, index);
+
 	order.type = OT_GOTO_STATION;
-	order.flags = 0;
 	order.station = index;
-	DeleteCommandFromVehicleSchedule(order);
+	DeleteDestinationFromVehicleOrder(order);
+
 	DeleteSubsidyWithStation(index);
 }
 
--- a/train_cmd.c	Sat Jan 15 16:38:10 2005 +0000
+++ b/train_cmd.c	Sat Jan 15 19:06:22 2005 +0000
@@ -395,7 +395,7 @@
 
 	if (!(flags & DC_QUERY_COST)) {
 		v = AllocateVehicle();
-		if (v == NULL || _ptr_to_next_order >= endof(_order_array))
+		if (v == NULL || IsOrderPoolFull())
 			return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
 
 		unit_num = GetFreeUnitNumber(VEH_Train);
@@ -417,24 +417,13 @@
 			v->u.rail.track = 0x80;
 			v->u.rail.first_engine = 0xffff;
 			v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
-//			v->subtype = 0;
 			v->spritenum = rvi->image_index;
 			v->cargo_type = rvi->cargo_type;
 			v->cargo_cap = rvi->capacity;
 			v->max_speed = rvi->max_speed;
-//			v->cargo_count = 0;
 			v->value = value;
-//			v->day_counter = 0;
-//			v->current_order = 0;
-//			v->next_station = 0;
-//			v->load_unload_time_rem = 0;
-//			v->progress = 0;
-//			v->targetairport = 0;
-//			v->crash_anim_pos = 0;
 			v->last_station_visited = 0xFFFF;
 			v->dest_tile = 0;
-//			v->profit_last_year = 0;
-//			v->profit_this_year = 0;
 
 			v->engine_type = (byte)p1;
 			e = &_engines[p1];
@@ -444,23 +433,10 @@
 			v->max_age = e->lifelength * 366;
 
 			v->string_id = STR_SV_TRAIN_NAME;
-//			v->cur_speed = 0;
-//			v->subspeed = 0;
 			v->u.rail.railtype = e->railtype;
 			_new_train_id = v->index;
-//			v->cur_order_index = 0;
-//			v->num_orders = 0;
-
-			_ptr_to_next_order->type = OT_NOTHING;
-			_ptr_to_next_order->flags = 0;
-			v->schedule_ptr = _ptr_to_next_order++;
-//			v->next_in_chain = 0xffff;
-//			v->next = NULL;
 
 			v->service_interval = _patches.servint_trains;
-//			v->breakdown_ctr = 0;
-//			v->breakdowns_since_last_service = 0;
-//			v->unk4D = 0;
 			v->date_of_last_service = _date;
 			v->build_year = _cur_year;
 			v->type = VEH_Train;
@@ -680,12 +656,9 @@
 			// move the train to an empty line. for locomotives, we set the type to 0. for wagons, 4.
 			if (is_loco) {
 				if (src->subtype != 0) {
-					// setting the type to 0 also involves setting up the schedule_ptr field.
+					// setting the type to 0 also involves setting up the orders field.
 					src->subtype = 0;
-					assert(src->schedule_ptr == NULL);
-					_ptr_to_next_order->type = OT_NOTHING;
-					_ptr_to_next_order->flags = 0;
-					src->schedule_ptr = _ptr_to_next_order++;
+					assert(src->orders == NULL);
 					src->num_orders = 0;
 				}
 				dst_head = src;
@@ -695,9 +668,9 @@
 			src->u.rail.first_engine = 0xffff;
 		} else {
 			if (src->subtype == 0) {
-				// the vehicle was previously a loco. need to free the schedule list and delete vehicle windows etc.
+				// the vehicle was previously a loco. need to free the order list and delete vehicle windows etc.
 				DeleteWindowById(WC_VEHICLE_VIEW, src->index);
-				DeleteVehicleSchedule(src);
+				DeleteVehicleOrders(src);
 			}
 
 			src->subtype = 2;
@@ -1644,13 +1617,13 @@
 
 static bool ProcessTrainOrder(Vehicle *v)
 {
-	Order order;
+	const Order *order;
 	bool result;
 
 	// These are un-interruptible
 	if (v->current_order.type >= OT_GOTO_DEPOT &&
 			v->current_order.type <= OT_LEAVESTATION) {
-		// Let a depot order in the schedule interrupt.
+		// Let a depot order in the orderlist interrupt.
 		if (v->current_order.type != OT_GOTO_DEPOT ||
 				!(v->current_order.flags & OF_UNLOAD))
 			return false;
@@ -1676,10 +1649,11 @@
 	// Get the current order
 	if (v->cur_order_index >= v->num_orders)
 		v->cur_order_index = 0;
-	order = v->schedule_ptr[v->cur_order_index];
+
+	order = GetVehicleOrder(v, v->cur_order_index);
 
 	// If no order, do nothing.
-	if (order.type == OT_NOTHING) {
+	if (order == NULL) {
 		v->current_order.type = OT_NOTHING;
 		v->current_order.flags = 0;
 		v->dest_tile = 0;
@@ -1687,31 +1661,37 @@
 	}
 
 	// If it is unchanged, keep it.
-	if (order.type == v->current_order.type &&
-			order.flags == v->current_order.flags &&
-			order.station == v->current_order.station)
+	if (order->type    == v->current_order.type &&
+			order->flags   == v->current_order.flags &&
+			order->station == v->current_order.station)
 		return false;
 
 	// Otherwise set it, and determine the destination tile.
-	v->current_order = order;
+	v->current_order = *order;
 
 	v->dest_tile = 0;
 
 	result = false;
-	if (order.type == OT_GOTO_STATION) {
-		if (order.station == v->last_station_visited)
-			v->last_station_visited = 0xFFFF;
-		v->dest_tile = GetStation(order.station)->xy;
-		result = CheckReverseTrain(v);
-	} else if (order.type == OT_GOTO_DEPOT) {
-		v->dest_tile = _depots[order.station].xy;
-		result = CheckReverseTrain(v);
-	} else if (order.type == OT_GOTO_WAYPOINT) {
-		v->dest_tile = _waypoints[order.station].xy;
-		result = CheckReverseTrain(v);
+	switch (order->type) {
+		case OT_GOTO_STATION:
+			if (order->station == v->last_station_visited)
+				v->last_station_visited = 0xFFFF;
+			v->dest_tile = GetStation(order->station)->xy;
+			result = CheckReverseTrain(v);
+			break;
+
+		case OT_GOTO_DEPOT:
+			v->dest_tile = _depots[order->station].xy;
+			result = CheckReverseTrain(v);
+			break;
+
+		case OT_GOTO_WAYPOINT:
+			v->dest_tile = _waypoints[order->station].xy;
+			result = CheckReverseTrain(v);
+			break;
 	}
 
-	InvalidateVehicleOrderWidget(v);
+	InvalidateVehicleOrder(v);
 
 	return result;
 }
@@ -1771,7 +1751,7 @@
 
 	v->u.rail.days_since_order_progr = 0;
 	v->cur_order_index++;
-	InvalidateVehicleOrderWidget(v);
+	InvalidateVehicleOrder(v);
 }
 
 static int UpdateTrainSpeed(Vehicle *v)
@@ -2669,7 +2649,7 @@
 		v->current_order.type = OT_DUMMY;
 		v->current_order.flags = 0;
 
-		if (t.flags & OF_UNLOAD) { // Part of the schedule?
+		if (t.flags & OF_UNLOAD) { // Part of the orderlist?
 			v->u.rail.days_since_order_progr = 0;
 			v->cur_order_index++;
 		} else if (t.flags & OF_FULL_LOAD) { // User initiated?
@@ -2701,7 +2681,7 @@
 	if (v->vehstatus & VS_STOPPED)
 		return;
 
-	if (_patches.gotodepot && ScheduleHasDepotOrders(v->schedule_ptr))
+	if (_patches.gotodepot && VehicleHasDepotOrders(v))
 		return;
 
 	// Don't interfere with a depot visit scheduled by the user, or a
@@ -2834,11 +2814,3 @@
 {
 	_age_cargo_skip_counter = 1;
 }
-
-int ScheduleHasDepotOrders(const Order *schedule)
-{
-	for (; schedule->type != OT_NOTHING; schedule++)
-		if (schedule->type == OT_GOTO_DEPOT)
-			return true;
-	return false;
-}
--- a/ttd.c	Sat Jan 15 16:38:10 2005 +0000
+++ b/ttd.c	Sat Jan 15 19:06:22 2005 +0000
@@ -496,6 +496,7 @@
 	_industry_sort = NULL;
 
 	_sign_size = lengthof(_sign_list);
+	_orders_size = lengthof(_orders);
 }
 
 static void UnInitializeDynamicVariables(void)
--- a/vehicle.c	Sat Jan 15 16:38:10 2005 +0000
+++ b/vehicle.c	Sat Jan 15 19:06:22 2005 +0000
@@ -33,24 +33,6 @@
 		(v->date_of_last_service + v->service_interval < _date);
 }
 
-Order UnpackOldOrder(uint16 packed)
-{
-	Order order;
-	order.type    = (packed & 0x000f);
-	order.flags   = (packed & 0x00f0) >> 4;
-	order.station = (packed & 0xff00) >> 8;
-
-	// Sanity check
-	// TTD stores invalid orders as OT_NOTHING with non-zero flags/station
-	if (order.type == OT_NOTHING && (order.flags != 0 || order.station != 0)) {
-		order.type = OT_DUMMY;
-		order.flags = 0;
-	}
-
-	return order;
-}
-
-
 void VehicleInTheWayErrMsg(Vehicle *v)
 {
 	StringID id;
@@ -177,11 +159,6 @@
 				if (v->subtype == 0)
 					UpdateTrainAcceleration(v);
 			}
-
-#if defined(_DEBUG)
-			if (!(v->schedule_ptr == NULL || (v->schedule_ptr >= _order_array && v->schedule_ptr < _ptr_to_next_order)))
-				v->schedule_ptr = NULL;
-#endif
 		}
 	}
 
@@ -196,7 +173,7 @@
 	memset(v, 0, sizeof(Vehicle));
 	v->index = index;
 
-	assert(v->schedule_ptr == NULL);
+	assert(v->orders == NULL);
 
 	v->left_coord = INVALID_COORD;
 	v->next = NULL;
@@ -353,8 +330,6 @@
 		v->index = i++;
 
 	memset(_vehicle_position_hash, -1, sizeof(_vehicle_position_hash));
-
-	_ptr_to_next_order = _order_array;
 }
 
 Vehicle *GetLastVehicleInChain(Vehicle *v)
@@ -439,91 +414,6 @@
 	return i;
 }
 
-
-Vehicle *IsScheduleShared(Vehicle *u)
-{
-	const Order *sched = u->schedule_ptr;
-	Vehicle *v;
-
-	FOR_ALL_VEHICLES(v) {
-		if (v->schedule_ptr == sched && u != v && v->type != 0)
-			return v;
-	}
-	return NULL;
-}
-
-void DeleteVehicleSchedule(Vehicle *v)
-{
-	Order *sched;
-	Order *cur;
-	int num;
-	Vehicle *u;
-
-	// if the schedule is shared, don't delete it.
-	if ((u = IsScheduleShared(v)) != NULL) {
-		v->schedule_ptr = NULL;
-		InvalidateWindow(WC_VEHICLE_ORDERS, u->index);
-		return;
-	}
-
-	sched = v->schedule_ptr;
-	v->schedule_ptr = NULL;
-
-	num = v->num_orders + 1;
-
-	_ptr_to_next_order -= num;
-
-	cur = sched;
-	while (cur != _ptr_to_next_order) {
-		assert(cur < _ptr_to_next_order);
-		cur[0] = cur[num];
-		cur++;
-	}
-
-	FOR_ALL_VEHICLES(v) {
-		if (v->schedule_ptr != NULL && sched < v->schedule_ptr) {
-			v->schedule_ptr -= num;
-		}
-	}
-}
-
-void DeleteCommandFromVehicleSchedule(Order cmd)
-{
-	Vehicle *v;
-	bool need_invalidate;
-
-	FOR_ALL_VEHICLES(v) {
-		if (v->type != 0 && v->schedule_ptr != NULL) {
-			Order *sched;
-
-			// clear last station visited
-			if (v->last_station_visited == cmd.station && cmd.type == OT_GOTO_STATION)
-				v->last_station_visited = 0xFFFF;
-
-			// check the next order
-			if (v->current_order.type == cmd.type &&
-					v->current_order.station == cmd.station) {
-				v->current_order.type = OT_DUMMY;
-				v->current_order.flags = 0;
-				InvalidateWindow(WC_VEHICLE_VIEW, v->index);
-			}
-
-			// clear the order list
-			need_invalidate = false;
-			for (sched = v->schedule_ptr; sched->type != OT_NOTHING; ++sched) {
-				if (sched->type == cmd.type && sched->station == cmd.station) {
-					sched->type = OT_DUMMY;
-					sched->flags = 0;
-					need_invalidate = true;
-				}
-			}
-
-			if (need_invalidate)
-				InvalidateWindow(WC_VEHICLE_ORDERS, v->index);
-		}
-	}
-}
-
 void DoDeleteDepot(uint tile)
 {
 	Order order;
@@ -538,9 +428,8 @@
 	d->xy = 0;
 
 	order.type = OT_GOTO_DEPOT;
-	order.flags = 0;
 	order.station = dep_index;
-	DeleteCommandFromVehicleSchedule(order);
+	DeleteDestinationFromVehicleOrder(order);
 
 	// Delete the depot
 	DeleteWindowById(WC_VEHICLE_DEPOT, tile);
@@ -553,8 +442,8 @@
 	UpdateVehiclePosHash(v, INVALID_COORD, 0);
 	v->next_hash = 0xffff;
 
-	if (v->schedule_ptr != NULL)
-		DeleteVehicleSchedule(v);
+	if (v->orders != NULL)
+		DeleteVehicleOrders(v);
 }
 
 void DeleteVehicleChain(Vehicle *v)
@@ -1699,12 +1588,6 @@
 	);
 }
 
-void InvalidateVehicleOrderWidget(Vehicle *v)
-{
-	InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, STATUS_BAR);
-	InvalidateWindowWidget(WC_VEHICLE_ORDERS, v->index, 2);
-}
-
 /* returns true if staying in the same tile */
 bool GetNewVehiclePos(Vehicle *v, GetNewVehiclePosResult *gp)
 {
@@ -1846,7 +1729,7 @@
 	SLE_CONDVARX(offsetof(Vehicle, current_order) + offsetof(Order, flags),   SLE_UINT8,  5, 255),
 	SLE_CONDVARX(offsetof(Vehicle, current_order) + offsetof(Order, station), SLE_UINT16, 5, 255),
 
-	SLE_REF(Vehicle,schedule_ptr,			REF_SCHEDULE),
+	SLE_REF(Vehicle,orders,						REF_ORDER),
 
 	SLE_VAR(Vehicle,age,							SLE_UINT16),
 	SLE_VAR(Vehicle,max_age,					SLE_UINT16),
@@ -1869,9 +1752,11 @@
 	SLE_VAR(Vehicle,random_bits,       SLE_UINT8),
 	SLE_VAR(Vehicle,waiting_triggers,  SLE_UINT8),
 
-	// reserve extra space in savegame here. (currently 14 bytes)
+	SLE_REF(Vehicle,next_shared,				REF_VEHICLE),
+	SLE_REF(Vehicle,prev_shared,				REF_VEHICLE),
+
+	// reserve extra space in savegame here. (currently 10 bytes)
 	SLE_CONDARR(NullStruct,null,SLE_FILE_U8 | SLE_VAR_NULL, 2, 2, 255), /* 2 */
-	SLE_CONDARR(NullStruct,null,SLE_FILE_U16 | SLE_VAR_NULL, 2, 2, 255), /* 4 */
 	SLE_CONDARR(NullStruct,null,SLE_FILE_U32 | SLE_VAR_NULL, 2, 2, 255), /* 8 */
 
 	SLE_END()
@@ -2068,6 +1953,29 @@
 			w->u.rail.first_engine = v->engine_type;
 	}
 
+	/* Check for shared order-lists (we now use pointers for that) */
+	if (_sl.full_version < 0x502) {
+		FOR_ALL_VEHICLES(v) {
+			Vehicle *u;
+
+			if (v->type == 0)
+				continue;
+
+			FOR_ALL_VEHICLES_FROM(u, v->index + 1) {
+				if (u->type == 0)
+					continue;
+
+				/* If a vehicle has the same orders, add the link to eachother
+				    in both vehicles */
+				if (v->orders == u->orders) {
+					v->next_shared = u;
+					u->prev_shared = v;
+					break;
+				}
+			}
+		}
+	}
+
 	/* This is to ensure all pointers are within the limits of
 	    _vehicles_size */
 	if (_vehicle_id_ctr_day >= _vehicles_size)
@@ -2131,55 +2039,8 @@
 	}
 }
 
-
-static void Save_ORDR()
-{
-	uint32 orders[lengthof(_order_array)];
-	uint len = _ptr_to_next_order - _order_array;
-	uint i;
-
-	assert (len <= lengthof(orders));
-
-	for (i = 0; i < len; ++i)
-		orders[i] = PackOrder(&_order_array[i]);
-
-	SlArray(orders, len, SLE_UINT32);
-}
-
-static void Load_ORDR()
-{
-	uint len = SlGetFieldLength();
-	uint i;
-
-	if (_sl.version < 5) {
-		/* Older version had an other layout for orders.. convert them correctly */
-		uint16 orders[lengthof(_order_array)];
-
-		len /= sizeof(uint16);
-		assert (len <= lengthof(orders));
-
-		SlArray(orders, len, SLE_UINT16);
-
-		for (i = 0; i < len; ++i)
-			_order_array[i] = UnpackVersion4Order(orders[i]);
-	} else {
-		uint32 orders[lengthof(_order_array)];
-
-		len /= sizeof(uint32);
-		assert (len <= lengthof(orders));
-
-		SlArray(orders, len, SLE_UINT32);
-
-		for (i = 0; i < len; ++i)
-			_order_array[i] = UnpackOrder(orders[i]);
-	}
-
-	_ptr_to_next_order = _order_array + len;
-}
-
 const ChunkHandler _veh_chunk_handlers[] = {
 	{ 'VEHS', Save_VEHS, Load_VEHS, CH_SPARSE_ARRAY},
-	{ 'ORDR', Save_ORDR, Load_ORDR, CH_RIFF},
 	{ 'DEPT', Save_DEPT, Load_DEPT, CH_ARRAY},
 	{ 'CHKP', Save_CHKP, Load_CHKP, CH_ARRAY | CH_LAST},
 };
--- a/vehicle.h	Sat Jan 15 16:38:10 2005 +0000
+++ b/vehicle.h	Sat Jan 15 19:06:22 2005 +0000
@@ -2,42 +2,7 @@
 #define VEHICLE_H
 
 #include "vehicle_gui.h"
-
-/* If you change this, keep in mind that it is saved on 3 places:
-    - Load_ORDR, all the global orders
-    - Vehicle -> current_order
-    - REF_SHEDULE (all REFs are currently limited to 16 bits!!) */
-typedef struct Order {
-	uint8 type;
-	uint8 flags;
-	uint16 station;
-} Order;
-
-static inline uint32 PackOrder(const Order *order)
-{
-	return order->station << 16 | order->flags << 8 | order->type;
-}
-
-static inline Order UnpackOrder(uint32 packed)
-{
-	Order order;
-	order.type    = (packed & 0x000000FF);
-	order.flags   = (packed & 0x0000FF00) >> 8;
-	order.station = (packed & 0xFFFF0000) >> 16;
-	return order;
-}
-
-static inline Order UnpackVersion4Order(uint16 packed)
-{
-	Order order;
-	order.type    = (packed & 0x000F);
-	order.flags   = (packed & 0x00F0) >> 4;
-	order.station = (packed & 0xFF00) >> 8;
-	return order;
-}
-
-Order UnpackOldOrder(uint16 packed);
-
+#include "order.h"
 
 typedef struct VehicleRail {
 	uint16 last_speed;		// NOSAVE: only used in UI
@@ -177,11 +142,16 @@
 	byte day_counter; // increased by one for each day
 	byte tick_counter;// increased by one for each tick
 
-	// related to the current order
-	byte cur_order_index;
-	byte num_orders;
-	Order current_order;
-	Order *schedule_ptr;
+	/* Begin Order-stuff */
+	Order current_order;  //! The current order (+ status, like: loading)
+	byte cur_order_index; //! The index to the current order
+
+	Order *orders;        //! Pointer to the first order for this vehicle
+	byte num_orders;      //! How many orders there are in the list
+
+	Vehicle *next_shared; //! If not NULL, this points to the next vehicle that shared the order
+	Vehicle *prev_shared; //! If not NULL, this points to the prev vehicle that shared the order
+	/* End Order-stuff */
 
 	// Boundaries for the current position in the world and a next hash link.
 	// NOSAVE: All of those can be updated with VehiclePositionChanged()
@@ -248,25 +218,6 @@
 	VEH_Disaster = 0x15,
 };
 
-/* Order types */
-enum {
-	OT_NOTHING = 0,
-	OT_GOTO_STATION = 1,
-	OT_GOTO_DEPOT = 2,
-	OT_LOADING = 3,
-	OT_LEAVESTATION = 4,
-	OT_DUMMY = 5,
-	OT_GOTO_WAYPOINT = 6,
-};
-
-/* Order flags */
-enum {
-	OF_UNLOAD    = 0x2,
-	OF_FULL_LOAD = 0x4, // Also used when to force an aircraft into a depot
-	OF_NON_STOP  = 0x8
-};
-
-
 enum VehStatus {
 	VS_HIDDEN = 1,
 	VS_STOPPED = 2,
@@ -302,22 +253,11 @@
 typedef void VehicleTickProc(Vehicle *v);
 typedef void *VehicleFromPosProc(Vehicle *v, void *data);
 
-typedef struct {
-	VehicleID clone;
-	byte orderindex;
-	Order order[41];
-	uint16 service_interval;
-	char name[32];
-} BackuppedOrders;
-
 void VehicleServiceInDepot(Vehicle *v);
-void BackupVehicleOrders(Vehicle *v, BackuppedOrders *order);
-void RestoreVehicleOrders(Vehicle *v, BackuppedOrders *order);
 Vehicle *AllocateVehicle();
 Vehicle *ForceAllocateVehicle();
 Vehicle *ForceAllocateSpecialVehicle();
 void UpdateVehiclePosHash(Vehicle *v, int x, int y);
-void InitializeVehicles();
 void VehiclePositionChanged(Vehicle *v);
 void AfterLoadVehicles();
 Vehicle *GetLastVehicleInChain(Vehicle *v);
@@ -328,8 +268,6 @@
 void DeleteVehicleChain(Vehicle *v);
 void *VehicleFromPos(TileIndex tile, void *data, VehicleFromPosProc *proc);
 void CallVehicleTicks();
-void DeleteVehicleSchedule(Vehicle *v);
-Vehicle *IsScheduleShared(Vehicle *v);
 
 Depot *AllocateDepot();
 Waypoint *AllocateWaypoint();
@@ -373,16 +311,12 @@
 void AgeVehicle(Vehicle *v);
 void MaybeReplaceVehicle(Vehicle *v);
 
-void DeleteCommandFromVehicleSchedule(Order cmd);
-
 void BeginVehicleMove(Vehicle *v);
 void EndVehicleMove(Vehicle *v);
 
 bool IsAircraftHangarTile(TileIndex tile);
 void ShowAircraftViewWindow(Vehicle *v);
 
-void InvalidateVehicleOrderWidget(Vehicle *v);
-
 bool IsShipDepotTile(TileIndex tile);
 uint GetFreeUnitNumber(byte type);
 
@@ -397,9 +331,6 @@
 
 int CheckStoppedInDepot(Vehicle *v);
 
-int ScheduleHasDepotOrders(const Order *schedule);
-int CheckOrders(Vehicle *v);
-
 bool VehicleNeedsService(const Vehicle *v);
 
 void InvalidateAircraftWindows(const Vehicle *v);
@@ -439,8 +370,43 @@
 #define FOR_ALL_VEHICLES(v) for(v = _vehicles; v != &_vehicles[_vehicles_size]; v++)
 #define FOR_ALL_VEHICLES_FROM(v, from) for(v = GetVehicle(from); v != &_vehicles[_vehicles_size]; v++)
 
-VARDEF Order _order_array[5000];
-VARDEF Order *_ptr_to_next_order;
+/* 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;
+}
+
+/* Returns the last order of a vehicle, or NULL if it doesn't exists */
+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;
+}
+
+/* Get the first vehicle of a shared-list, so we only have to walk forwards */
+static inline Vehicle *GetFirstVehicleFromSharedList(Vehicle *v)
+{
+	Vehicle *u = v;
+	while (u->prev_shared != NULL)
+		u = u->prev_shared;
+
+	return u;
+}
 
 VARDEF Depot _depots[255];
 
@@ -465,8 +431,6 @@
 VARDEF TileIndex _last_built_road_depot_tile;
 VARDEF TileIndex _last_built_aircraft_depot_tile;
 VARDEF TileIndex _last_built_ship_depot_tile;
-VARDEF TileIndex _backup_orders_tile;
-VARDEF BackuppedOrders _backup_orders_data[1];
 
 // for each player, for each vehicle type, keep a list of the vehicles.
 //VARDEF Vehicle *_vehicle_arr[8][4];
--- a/vehicle_gui.c	Sat Jan 15 16:38:10 2005 +0000
+++ b/vehicle_gui.c	Sat Jan 15 19:06:22 2005 +0000
@@ -90,14 +90,16 @@
 		const Vehicle *v;
 		FOR_ALL_VEHICLES(v) {
 			if (v->type == type && v->subtype <= subtype) {
-				const Order *ord;
-				for (ord = v->schedule_ptr; ord->type != OT_NOTHING; ++ord)
-					if (ord->type == OT_GOTO_STATION && ord->station == station) {
+				const Order *order;
+
+				FOR_VEHICLE_ORDERS(v, order) {
+					if (order->type == OT_GOTO_STATION && order->station == station) {
 						_vehicle_sort[n].index = v->index;
 						_vehicle_sort[n].owner = v->owner;
 						++n;
 						break;
 					}
+				}
 			}
 		}
 	} else {