Index: src/autoreplace_cmd.cpp
===================================================================
--- src/autoreplace_cmd.cpp	(revision 10908)
+++ 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 10908)
+++ 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 10908)
+++ 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)
 
@@ -830,7 +831,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 +934,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;
@@ -1196,7 +1197,7 @@
 
 	/* 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 +1242,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 10908)
+++ 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/timetable_cmd.cpp
===================================================================
--- src/timetable_cmd.cpp	(revision 10908)
+++ 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 10908)
+++ src/vehicle.cpp	(working copy)
@@ -598,6 +598,133 @@
 	}
 }
 
+/**
+ * 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.
+ */
+int Vehicle::GetFirstSharedSeparation()
+{
+	if (this->prev_shared == NULL) return 0;
+
+	Vehicle *first;
+	/// Gets the first vehicle in the chain
+	for (first = this->prev_shared; first->prev_shared != NULL; first = first->prev_shared);
+
+	return this->GetVehicleSeparation(first);
+}
+
+/**
+ * Get the current theorical separation with the given vehicle.
+ * This includes its lateness_counter.
+ * The vehicle must be in a station for this function to work.
+ */
+int Vehicle::GetVehicleSeparation(Vehicle *v)
+{
+	if (this == v) return 0;
+
+	Order *o;
+
+	/// Adds current_order_time plus lateness_counter
+	int total = v->current_order_time + v->lateness_counter;
+
+	if (v->cur_order_index == 0 && v->current_order.type != OT_LOADING) {
+		for (o = v->orders->next; o != NULL; o = o->next) total += o->travel_time + o->wait_time;
+	} else if (v->cur_order_index > 0) {
+		/// Then all travel_time and wait_time for orders between first and current
+		byte order_index = 1;
+		for (o = v->orders->next; order_index++ < v->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 (v->current_order.type == OT_LOADING) total += v->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->next;
+	for (int i = 1, cpt = this->cur_order_index; i <= cpt; i++) {
+		total -= o->wait_time;
+		total -= o->travel_time;
+		o = o->next;
+	}
+
+	if (total < 0) total += this->GetTimetableTotalDuration();
+
+	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 then 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 +3231,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->prev_shared != NULL && this->IsOrderListShared() && this->FirstStopStationOrderID() == this->cur_order_index) {
+			/**
+			 * Find the previous vehicle of the shared order that visited the station
+			 */
+			int min_separation = -1;
+			int tmp_separation = 0;
+			Vehicle *previous = NULL;
+			/// Check for previous vehicles
+			for (Vehicle *v = this->prev_shared; v != NULL; v = v->prev_shared) {
+				tmp_separation = this->GetVehicleSeparation(v);
+				if (tmp_separation < min_separation || min_separation == -1) {
+					min_separation = tmp_separation;
+					previous = v;
+				}
+			}
+			/// Check for next vehicles
+			for (Vehicle *v = this->next_shared; v != NULL; v = v->next_shared) {
+				tmp_separation = this->GetVehicleSeparation(v);
+				if (tmp_separation < min_separation || min_separation == -1) {
+					min_separation = tmp_separation;
+					previous = v;
+				}
+			}
+
+			/// Check if prev_shared vehicle is really the previous one and reorder the chain if needed
+			if (this->prev_shared != previous) {
+				// 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;
+			}
+		}
 	} else {
 		/* This is just an unordered intermediate stop */
 		this->current_order.flags = 0;
@@ -3144,12 +3314,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 10908)
+++ src/vehicle.h	(working copy)
@@ -420,6 +420,20 @@
 	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();
+	int GetVehicleSeparation(Vehicle *v);
+	VehicleOrderID FirstStopStationOrderID();
 };
 
 /**
