Index: src/autoreplace_cmd.cpp
===================================================================
--- src/autoreplace_cmd.cpp	(revision 10887)
+++ src/autoreplace_cmd.cpp	(working copy)
@@ -209,7 +209,7 @@
 			DoCommand(0, (front->index << 16) | new_v->index, 1, DC_EXEC, CMD_MOVE_RAIL_VEHICLE);
 		} else {
 			// copy/clone the orders
-			DoCommand(0, (old_v->index << 16) | new_v->index, IsOrderListShared(old_v) ? CO_SHARE : CO_COPY, DC_EXEC, CMD_CLONE_ORDER);
+			DoCommand(0, (old_v->index << 16) | new_v->index, old_v->IsOrderListShared() ? CO_SHARE : CO_COPY, DC_EXEC, CMD_CLONE_ORDER);
 			new_v->cur_order_index = old_v->cur_order_index;
 			ChangeVehicleViewWindow(old_v, new_v);
 			new_v->profit_this_year = old_v->profit_this_year;
Index: src/order.h
===================================================================
--- src/order.h	(revision 10887)
+++ src/order.h	(working copy)
@@ -211,7 +211,6 @@
 bool VehicleHasDepotOrders(const Vehicle *v);
 void CheckOrders(const Vehicle*);
 void DeleteVehicleOrders(Vehicle *v);
-bool IsOrderListShared(const Vehicle *v);
 void AssignOrder(Order *order, Order data);
 bool CheckForValidOrders(const Vehicle* v);
 
Index: src/order_cmd.cpp
===================================================================
--- src/order_cmd.cpp	(revision 10887)
+++ src/order_cmd.cpp	(working copy)
@@ -19,6 +19,7 @@
 #include "vehicle_gui.h"
 #include "cargotype.h"
 #include "strings.h"
+#include "station_map.h"
 
 DEFINE_OLD_POOL_GENERIC(Order, Order)
 
@@ -367,6 +368,15 @@
 				SwapOrders(v->orders, new_o);
 				/* Now update the next pointers */
 				v->orders->next = new_o;
+				
+				/**
+				 * We have to clean up the Station->shared_order_previous_vehicles list
+				 * We should check also for non shared vehicles as it can be the last one from a old shared list
+				 */
+				if (IsTileType(v->orders->dest, MP_STATION)) {
+					Station *st = GetStationByTile(v->orders->next->dest);
+					st->shared_order_previous_vehicles.remove(v);
+				}
 			} else if (order == NULL) {
 				/* 'sel' is a non-existing order, add him to the end */
 				order = GetLastVehicleOrder(v);
@@ -467,6 +477,15 @@
 	order = GetVehicleOrder(v, sel_ord);
 	if (order == NULL) return CMD_ERROR;
 
+	/**
+	 * We have to clean up the Station->shared_order_previous_vehicles list
+	 * We should check also for non shared vehicles as it can be the last one from a old shared list
+	 */
+	if (IsTileType(order->dest, MP_STATION) && v->orders == order) {
+		Station *st = GetStationByTile(v->orders->dest);
+		st->shared_order_previous_vehicles.remove(v);
+	}
+
 	if (flags & DC_EXEC) {
 		if (GetVehicleOrder(v, sel_ord - 1) == NULL) {
 			if (GetVehicleOrder(v, sel_ord + 1) != NULL) {
@@ -599,6 +618,16 @@
 
 		if (one_before == NULL) {
 			/* First order edit */
+			
+			/**
+			 * We have to clean up the Station->shared_order_previous_vehicles list
+			 * We should check also for non shared vehicles as it can be the last one from a old shared list
+			 */
+			if (IsTileType(v->orders->dest, MP_STATION)) {
+				Station *st = GetStationByTile(v->orders->dest);
+				st->shared_order_previous_vehicles.remove(v);
+			}
+
 			v->orders = moving_one->next;
 		} else {
 			one_before->next = moving_one->next;
@@ -614,6 +643,15 @@
 			/* first order edit */
 			SwapOrders(v->orders, moving_one);
 			v->orders->next = moving_one;
+
+			/**
+			 * We have to clean up the Station->shared_order_previous_vehicles list
+			 * We should check also for non shared vehicles as it can be the last one from a old shared list
+			 */
+			if (IsTileType(moving_one->dest, MP_STATION)) {
+				Station *st = GetStationByTile(moving_one->dest);
+				st->shared_order_previous_vehicles.remove(v);
+			}
 		} else {
 			one_before->next = moving_one;
 		}
@@ -682,6 +720,15 @@
 		return CMD_ERROR;
 	}
 
+	/**
+	 * We have to clean up the Station->shared_order_previous_vehicles list
+	 * We should check also for non shared vehicles as it can be the last one from a old shared list
+	 */
+	if (v->orders == order && IsTileType(v->orders->dest, MP_STATION)) {
+		Station *st = GetStationByTile(order->dest);
+		st->shared_order_previous_vehicles.remove(v);
+	}
+
 	if (flags & DC_EXEC) {
 		switch (p2) {
 		case OFB_FULL_LOAD:
@@ -830,7 +877,7 @@
 			}
 
 			/* make sure there are orders available */
-			delta = IsOrderListShared(dst) ? src->num_orders + 1 : src->num_orders - dst->num_orders;
+			delta = dst->IsOrderListShared() ? src->num_orders + 1 : src->num_orders - dst->num_orders;
 			if (!HasOrderPoolFree(delta))
 				return_cmd_error(STR_8831_NO_MORE_SPACE_FOR_ORDERS);
 
@@ -933,7 +980,7 @@
 	}
 
 	/* If we have shared orders, store it on a special way */
-	if (IsOrderListShared(v)) {
+	if (v->IsOrderListShared()) {
 		const Vehicle *u = (v->next_shared) ? v->next_shared : v->prev_shared;
 
 		bak->clone = u->index;
@@ -1194,9 +1241,18 @@
 {
 	DeleteOrderWarnings(v);
 
+	/**
+	 * We have to clean up the Station->shared_order_previous_vehicles list
+	 * We should check also for non shared vehicles as it can be the last one from a old shared list
+	 */
+	if (v->orders != NULL && IsTileType(v->orders->dest, MP_STATION)) {
+		Station *st = GetStationByTile(v->orders->dest);
+		st->shared_order_previous_vehicles.remove(v);
+	}
+
 	/* If we have a shared order-list, don't delete the list, but just
 	    remove our pointer */
-	if (IsOrderListShared(v)) {
+	if (v->IsOrderListShared()) {
 		Vehicle *u = v;
 
 		v->orders = NULL;
@@ -1241,18 +1297,6 @@
 
 /**
  *
- * Check if we share our orders with an other vehicle
- *
- * @return Returns the vehicle who has the same order
- *
- */
-bool IsOrderListShared(const Vehicle *v)
-{
-	return v->next_shared != NULL || v->prev_shared != NULL;
-}
-
-/**
- *
  * Check if a vehicle has any valid orders
  *
  * @return false if there are no valid orders
Index: src/order_gui.cpp
===================================================================
--- src/order_gui.cpp	(revision 10887)
+++ src/order_gui.cpp	(working copy)
@@ -118,7 +118,7 @@
 
 	v = GetVehicle(w->window_number);
 
-	shared_orders = IsOrderListShared(v);
+	shared_orders = v->IsOrderListShared();
 
 	SetVScrollCount(w, v->num_orders + 1);
 
Index: src/station.h
===================================================================
--- src/station.h	(revision 10887)
+++ src/station.h	(working copy)
@@ -147,6 +147,7 @@
 
 	byte last_vehicle_type;
 	std::list<Vehicle *> loading_vehicles;
+	std::list<Vehicle *> shared_order_previous_vehicles; ///< No need to save this as it should be rebuilt shortly
 	GoodsEntry goods[NUM_CARGO];
 
 	uint16 random_bits;
Index: src/timetable_cmd.cpp
===================================================================
--- src/timetable_cmd.cpp	(revision 10887)
+++ src/timetable_cmd.cpp	(working copy)
@@ -11,8 +11,8 @@
 #include "date.h"
 #include "player.h"
 #include "vehicle.h"
+#include "station_map.h"
 
-
 static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16 time, bool is_journey)
 {
 	Order *order = GetVehicleOrder(v, order_number);
Index: src/vehicle.cpp
===================================================================
--- src/vehicle.cpp	(revision 10887)
+++ src/vehicle.cpp	(working copy)
@@ -598,6 +598,120 @@
 	}
 }
 
+/**
+ * Checks if the vehicle is part of the shared orders list
+ */
+bool Vehicle::IsVehicleInSharedOrdersList(Vehicle *v)
+{
+	for (Vehicle *vShared = this->prev_shared; vShared != NULL; vShared = vShared->prev_shared) {
+		if (vShared == v) return true;
+	}
+
+	for (Vehicle *vShared = this->next_shared; vShared != NULL; vShared = vShared->next_shared) {
+		if (vShared == v) return true;
+	}
+
+	return false;
+}
+
+/**
+ * Counts the vehicles that share it's orders list
+ */
+int Vehicle::CountSharedOrderdList()
+{
+	int count = 1; ///< Includes this one first
+	for (Vehicle *v = this->prev_shared; v != NULL; v = v->prev_shared) count++;
+	for (Vehicle *v = this->next_shared; v != NULL; v = v->next_shared) count++;
+	return count;
+}
+
+/**
+ * Finds this vehicle position in the shared order list chain
+ */
+int Vehicle::GetPositionInSharedOrderList()
+{
+	int count = 0; ///< Do not include this one
+	for (Vehicle *v = this->prev_shared; v != NULL; v = v->prev_shared) count++;
+	return count;
+}
+
+/**
+ * Gets the total timetable duration
+ */
+int Vehicle::GetTimetableTotalDuration()
+{
+	int total = 0;
+	for (Order *o = this->orders; o != NULL; o = o->next) {
+		total += o->wait_time + o->travel_time;
+	}
+	return total;
+}
+
+/**
+ * Get the current theorical separation with the first shared order vehicle.
+ * This includes its lateness_counter.
+ * The vehicle must be in the first order station for this function to work.
+ * The vehicle must not be the first vehicle of the chain.
+ */
+int Vehicle::GetFirstSharedSeparation()
+{
+	Vehicle *first;
+	Order *o;
+	/// Gets the first vehicle in the chain
+	for (first = this->prev_shared; first->prev_shared != NULL; first = first->prev_shared);
+
+	/// Adds current_order_time plus lateness_counter
+	int total = first->current_order_time + first->lateness_counter;
+
+	if (first->cur_order_index == 0 && first->current_order.type != OT_LOADING) {
+		/// If it's travelling to the first order, we have to add all times but the travel_time for the first order
+		for (o = first->orders->next; o != NULL; o = o->next) total += o->travel_time + o->wait_time;
+		total += first->orders->wait_time;
+	} else if (first->cur_order_index > 0) {
+		/// If it's not at first order, we add the first order wait_time plus all orders times between first and current
+		total += first->orders->wait_time;
+		/// Then all travel_time and wait_time for orders between first and current
+		byte order_index = 0;
+		for (o = first->orders->next; ++order_index < first->cur_order_index; o = o->next) total += o->travel_time + o->wait_time;
+		/// Adds the current order travel time if it's already loading
+		if (first->current_order.type == OT_LOADING) total += first->current_order.travel_time;
+	}
+
+	/**
+	 * As now the station where the separation is computed can be different from the first one
+	 * we have to remove the time needed to go order 0 to first stop station order
+	 */
+	o = this->orders;
+	for (int i = 1, cpt = this->FirstStopStationOrderID(); i <= cpt; i++) {
+		total -= o->wait_time;
+		o = o->next;
+		total -= o->travel_time;
+	}
+	return total;
+}
+
+/**
+ * Returns the vehicle order index where it first stops at a station
+ */
+VehicleOrderID Vehicle::FirstStopStationOrderID()
+{
+	VehicleOrderID index = 0;
+	for (Order *first = this->orders; first != NULL; first = first->next) {
+		if (first->type == OT_GOTO_STATION && first->wait_time > 0) {
+			/**
+			 * Take it easy : if wait_time is 0 they it means the train won't wait here
+			 * because user choice or because station type (waypoint, buoy) or because
+			 * order type (non-stop, etc.)
+			 * This test is quite filthy, but it should always work unlikely all my previous
+			 * attempts of cleaner code.
+			 */
+			return index;
+		}
+		++index;
+	}
+	return INVALID_VEH_ORDER_ID;
+}
+
 Vehicle::~Vehicle()
 {
 	DeleteName(this->string_id);
@@ -3104,6 +3218,49 @@
 		 * that arrives at random stations is bad. */
 		this->current_order.flags |= OF_NON_STOP;
 		UpdateVehicleTimetable(this, true);
+
+		/**
+		 * We ensure the vehicle is well positionned in the shared order list
+		 * This means the last vehicle from this shared order list that visited the 
+		 * station must be its ->prev_shared
+		 */
+		if (_patches.timetabling && this->IsOrderListShared() && this->FirstStopStationOrderID() == this->cur_order_index) {
+			/// Find the previous vehicle of the shared order that visited the station
+			Station *st = GetStation(this->current_order.dest);
+			std::list<Vehicle *>::iterator iter;
+			Vehicle *vehicle_to_remove = NULL;
+			for (iter = st->shared_order_previous_vehicles.begin(); iter != st->shared_order_previous_vehicles.end(); ++iter) {
+				Vehicle *previous = *iter;
+				if (this->IsVehicleInSharedOrdersList(previous)) {
+					/**
+					 * This vehicle is in the shared order list.
+					 * If it's not this previous one, we have to reorder the chain
+					 */
+					if (this->prev_shared != previous && this->prev_shared != NULL) {
+						// Remove this vehicle from the list
+						this->prev_shared->next_shared = this->next_shared;
+						if (this->next_shared != NULL) this->next_shared->prev_shared = this->prev_shared;
+						// Insert in the list
+						this->prev_shared = previous;
+						this->next_shared = previous->next_shared;
+						// Update previous and next
+						if (previous->next_shared != NULL) previous->next_shared->prev_shared = this;
+						previous->next_shared = this;
+					}
+
+					/**
+					 * Remove the previous vehicle from the shared_order_previous_vehicles
+					 */
+					vehicle_to_remove = previous;
+					break;
+				}
+			}
+			/**
+			 * Remove the previous vehicle and add this vehicle to the shared_order_previous_vehicles
+			 */
+			if (vehicle_to_remove != NULL) st->shared_order_previous_vehicles.remove(vehicle_to_remove);
+			st->shared_order_previous_vehicles.push_back(this);
+		}
 	} else {
 		/* This is just an unordered intermediate stop */
 		this->current_order.flags = 0;
@@ -3144,12 +3301,29 @@
 {
 	switch (this->current_order.type) {
 		case OT_LOADING: {
-			uint wait_time = max(this->current_order.wait_time - this->lateness_counter, 0);
+			/**
+			 * For shared orders vehicles other than the first in chain arriving to the
+			 * first order station, we have to recompute the separation
+			 */
+			if (_patches.timetabling && this->IsOrderListShared() && this->prev_shared != NULL && this->cur_order_index == this->FirstStopStationOrderID()) {
+				/**
+				 * This vehicle have to ensure separation
+				 */
+				/// Compute wait_time for auto-separation system
+				int wait_time = ((this->GetTimetableTotalDuration() * this->GetPositionInSharedOrderList()) / this->CountSharedOrderdList()) - this->GetFirstSharedSeparation();
+				/// Check if the vehicle can leave the station now or not
+				if (mode || !HASBIT(this->vehicle_flags, VF_LOADING_FINISHED) || wait_time > 0) return;
+				/// The vehicle can leave the station. Fill the lateness counter with separation informations, and override the actual waiting time.
+				this->lateness_counter = -wait_time;
+				this->current_order_time = this->current_order.wait_time;
+			} else {
+				/// Uses standard timetable system (no timetable, no shared orders, first vehicle, etc.)
+				uint wait_time = max(this->current_order.wait_time - this->lateness_counter, 0);
+				/* Not the first call for this tick, or still loading */
+				if (mode || !HASBIT(this->vehicle_flags, VF_LOADING_FINISHED) ||
+						(_patches.timetabling && this->current_order_time < wait_time)) return;
+			}
 
-			/* Not the first call for this tick, or still loading */
-			if (mode || !HASBIT(this->vehicle_flags, VF_LOADING_FINISHED) ||
-					(_patches.timetabling && this->current_order_time < wait_time)) return;
-
 			this->PlayLeaveStationSound();
 
 			Order b = this->current_order;
Index: src/vehicle.h
===================================================================
--- src/vehicle.h	(revision 10887)
+++ src/vehicle.h	(working copy)
@@ -420,6 +420,19 @@
 	virtual void Tick() {};
 
 	bool IsValid() const { return this->type != VEH_INVALID; }
+
+	/**
+	 * Check if we share our orders with an other vehicle
+	 *
+	 * @return Returns the vehicle who has the same order
+	 */
+	bool IsOrderListShared() const { return this->prev_shared != NULL || this->next_shared != NULL; }
+	bool IsVehicleInSharedOrdersList(Vehicle *v);
+	int CountSharedOrderdList();
+	int GetPositionInSharedOrderList();
+	int GetTimetableTotalDuration();
+	int GetFirstSharedSeparation();
+	VehicleOrderID FirstStopStationOrderID();
 };
 
 /**
