changeset 8827:095c429c5fa7 draft

(svn r12575) -Codechange: unduplicate Process*Orders for trains, ships and road vehicles.
author rubidium <rubidium@openttd.org>
date Sat, 05 Apr 2008 10:55:50 +0000
parents 7532ee3295c9
children f8c143a8cd90
files src/order_cmd.cpp src/order_func.h src/roadveh.h src/roadveh_cmd.cpp src/ship.h src/ship_cmd.cpp src/train.h src/train_cmd.cpp src/vehicle_base.h
diffstat 9 files changed, 157 insertions(+), 226 deletions(-) [+]
line wrap: on
line diff
--- a/src/order_cmd.cpp
+++ b/src/order_cmd.cpp
@@ -23,6 +23,8 @@
 #include "settings_type.h"
 #include "string_func.h"
 #include "newgrf_cargo.h"
+#include "timetable.h"
+#include "vehicle_func.h"
 
 #include "table/strings.h"
 
@@ -1275,6 +1277,118 @@
 	return (_patches.servint_ispercent) ? Clamp(index, MIN_SERVINT_PERCENT, MAX_SERVINT_PERCENT) : Clamp(index, MIN_SERVINT_DAYS, MAX_SERVINT_DAYS);
 }
 
+/**
+ * Handle the orders of a vehicle and determine the next place
+ * to go to if needed.
+ * @param v the vehicle to do this for.
+ * @return true *if* the vehicle is eligible for reversing
+ *              (basically only when leaving a station).
+ */
+bool ProcessOrders(Vehicle *v)
+{
+	switch (v->current_order.type) {
+		case OT_GOTO_DEPOT:
+			/* Let a depot order in the orderlist interrupt. */
+			if (!(v->current_order.flags & OFB_PART_OF_ORDERS)) return false;
+
+			if ((v->current_order.flags & OFB_SERVICE_IF_NEEDED) && !VehicleNeedsService(v)) {
+				UpdateVehicleTimetable(v, true);
+				v->cur_order_index++;
+			}
+			break;
+
+		case OT_LOADING:
+		case OT_LEAVESTATION:
+			return false;
+
+		default: break;
+	}
+
+	/**
+	 * Reversing because of order change is allowed only just after leaving a
+	 * station (and the difficulty setting to allowed, of course)
+	 * this can be detected because only after OT_LEAVESTATION, current_order
+	 * will be reset to nothing. (That also happens if no order, but in that case
+	 * it won't hit the point in code where may_reverse is checked)
+	 */
+	bool may_reverse = v->current_order.type == OT_NOTHING;
+
+	/* Check if we've reached the waypoint? */
+	if (v->current_order.type == OT_GOTO_WAYPOINT && v->tile == v->dest_tile) {
+		UpdateVehicleTimetable(v, true);
+		v->cur_order_index++;
+	}
+
+	/* Check if we've reached a non-stop station while TTDPatch nonstop is enabled.. */
+	if (_patches.new_nonstop &&
+			v->current_order.flags & OFB_NON_STOP &&
+			IsTileType(v->tile, MP_STATION) &&
+			v->current_order.dest == GetStationIndex(v->tile)) {
+		UpdateVehicleTimetable(v, true);
+		v->cur_order_index++;
+	}
+
+	/* Get the current order */
+	if (v->cur_order_index >= v->num_orders) v->cur_order_index = 0;
+
+	const Order *order = GetVehicleOrder(v, v->cur_order_index);
+
+	/* If no order, do nothing. */
+	if (order == NULL) {
+		v->current_order.Free();
+		v->dest_tile = 0;
+		if (v->type == VEH_ROAD) ClearSlot(v);
+		return false;
+	}
+
+	/* If it is unchanged, keep it. */
+	if (order->type  == v->current_order.type &&
+			order->flags == v->current_order.flags &&
+			order->dest  == v->current_order.dest &&
+			(v->type != VEH_SHIP || order->type != OT_GOTO_STATION || GetStation(order->dest)->dock_tile != 0)) {
+		return false;
+	}
+
+	/* Otherwise set it, and determine the destination tile. */
+	v->current_order = *order;
+
+	InvalidateVehicleOrder(v);
+	switch (v->type) {
+		default:
+			NOT_REACHED();
+
+		case VEH_ROAD:
+		case VEH_TRAIN:
+			break;
+
+		case VEH_SHIP:
+			InvalidateWindowClasses(v->GetVehicleListWindowClass());
+			break;
+	}
+
+	switch (order->type) {
+		case OT_GOTO_STATION:
+			if (order->dest == v->last_station_visited) {
+				v->last_station_visited = INVALID_STATION;
+			}
+			v->dest_tile = v->GetOrderStationLocation(order->dest);
+			break;
+
+		case OT_GOTO_DEPOT:
+			v->dest_tile = GetDepot(order->dest)->xy;
+			break;
+
+		case OT_GOTO_WAYPOINT:
+			v->dest_tile = GetWaypoint(order->dest)->xy;
+			break;
+
+		default:
+			v->dest_tile = 0;
+			return false;
+	}
+
+	return may_reverse;
+}
 
 /**
  *
--- a/src/order_func.h
+++ b/src/order_func.h
@@ -36,6 +36,7 @@
 void CheckOrders(const Vehicle*);
 void DeleteVehicleOrders(Vehicle *v);
 bool CheckForValidOrders(const Vehicle* v);
+bool ProcessOrders(Vehicle *v);
 
 #define MIN_SERVINT_PERCENT  5
 #define MAX_SERVINT_PERCENT 90
--- a/src/roadveh.h
+++ b/src/roadveh.h
@@ -76,6 +76,7 @@
 	bool IsInDepot() const { return this->u.road.state == RVSB_IN_DEPOT; }
 	void Tick();
 	void OnNewDay();
+	TileIndex GetOrderStationLocation(StationID station);
 };
 
 byte GetRoadVehLength(const Vehicle *v);
--- a/src/roadveh_cmd.cpp
+++ b/src/roadveh_cmd.cpp
@@ -10,7 +10,6 @@
 #include "road_map.h"
 #include "roadveh.h"
 #include "station_map.h"
-#include "timetable.h"
 #include "command_func.h"
 #include "station_base.h"
 #include "news_func.h"
@@ -755,89 +754,31 @@
 	}
 }
 
-static void ProcessRoadVehOrder(Vehicle *v)
+TileIndex RoadVehicle::GetOrderStationLocation(StationID station)
 {
-	const Order *order;
+	TileIndex dest = INVALID_TILE;
 
-	switch (v->current_order.type) {
-		case OT_GOTO_DEPOT:
-			/* Let a depot order in the orderlist interrupt. */
-			if (!(v->current_order.flags & OFB_PART_OF_ORDERS)) return;
-			if (v->current_order.flags & OFB_SERVICE_IF_NEEDED &&
-					!VehicleNeedsService(v)) {
-				UpdateVehicleTimetable(v, true);
-				v->cur_order_index++;
-			}
-			break;
-
-		case OT_LOADING:
-		case OT_LEAVESTATION:
-			return;
+	const RoadStop *rs = GetStation(station)->GetPrimaryRoadStop(this);
+	if (rs != NULL) {
+		uint mindist = MAX_UVALUE(uint);
 
-		default: break;
-	}
-
-	if (v->cur_order_index >= v->num_orders) v->cur_order_index = 0;
-
-	order = GetVehicleOrder(v, v->cur_order_index);
+		for (; rs != NULL; rs = rs->GetNextRoadStop(this)) {
+			uint dist = DistanceManhattan(this->tile, rs->xy);
 
-	if (order == NULL) {
-		v->current_order.Free();
-		v->dest_tile = 0;
-		ClearSlot(v);
-		return;
-	}
-
-	if (order->type  == v->current_order.type &&
-			order->flags == v->current_order.flags &&
-			order->dest  == v->current_order.dest) {
-		return;
+			if (dist < mindist) {
+				mindist = dist;
+				dest = rs->xy;
+			}
+		}
 	}
 
-	v->current_order = *order;
-
-	switch (order->type) {
-		case OT_GOTO_STATION: {
-			if (order->dest == v->last_station_visited) {
-				v->last_station_visited = INVALID_STATION;
-			}
-
-			const RoadStop *rs = GetStation(order->dest)->GetPrimaryRoadStop(v);
-
-			TileIndex dest = INVALID_TILE;
-			if (rs != NULL) {
-				uint mindist = MAX_UVALUE(uint);
-
-				for (; rs != NULL; rs = rs->GetNextRoadStop(v)) {
-					uint dist = DistanceManhattan(v->tile, rs->xy);
-
-					if (dist < mindist) {
-						mindist = dist;
-						dest = rs->xy;
-					}
-				}
-			}
-
-			if (dest != INVALID_TILE) {
-					v->dest_tile = dest;
-			} else {
-				/* There is no stop left at the station, so don't even TRY to go there */
-				v->cur_order_index++;
-				v->dest_tile = 0;
-			}
-			break;
-		}
-
-		case OT_GOTO_DEPOT:
-			v->dest_tile = GetDepot(order->dest)->xy;
-			break;
-
-		default:
-			v->dest_tile = 0;
-			break;
+	if (dest != INVALID_TILE) {
+		return dest;
+	} else {
+		/* There is no stop left at the station, so don't even TRY to go there */
+		this->cur_order_index++;
+		return 0;
 	}
-
-	InvalidateVehicleOrder(v);
 }
 
 static void StartRoadVehSound(const Vehicle* v)
@@ -1939,7 +1880,7 @@
 
 	if (v->vehstatus & VS_STOPPED) return;
 
-	ProcessRoadVehOrder(v);
+	ProcessOrders(v);
 	v->HandleLoading();
 
 	if (v->current_order.type == OT_LOADING) return;
--- a/src/ship.h
+++ b/src/ship.h
@@ -42,6 +42,7 @@
 	bool IsInDepot() const { return this->u.ship.state == 0x80; }
 	void Tick();
 	void OnNewDay();
+	TileIndex GetOrderStationLocation(StationID station);
 };
 
 #endif /* SHIP_H */
--- a/src/ship_cmd.cpp
+++ b/src/ship_cmd.cpp
@@ -242,66 +242,15 @@
 	PlayShipSound(this);
 }
 
-static void ProcessShipOrder(Vehicle *v)
+TileIndex Ship::GetOrderStationLocation(StationID station)
 {
-	const Order *order;
-
-	switch (v->current_order.type) {
-		case OT_GOTO_DEPOT:
-			if (!(v->current_order.flags & OFB_PART_OF_ORDERS)) return;
-			if (v->current_order.flags & OFB_SERVICE_IF_NEEDED &&
-					!VehicleNeedsService(v)) {
-				UpdateVehicleTimetable(v, true);
-				v->cur_order_index++;
-			}
-			break;
-
-		case OT_LOADING:
-		case OT_LEAVESTATION:
-			return;
-
-		default: break;
-	}
-
-	if (v->cur_order_index >= v->num_orders) v->cur_order_index = 0;
-
-	order = GetVehicleOrder(v, v->cur_order_index);
-
-	if (order == NULL) {
-		v->current_order.Free();
-		v->dest_tile = 0;
-		return;
+	Station *st = GetStation(station);
+	if (st->dock_tile != 0) {
+		return TILE_ADD(st->dock_tile, ToTileIndexDiff(GetDockOffset(st->dock_tile)));
+	} else {
+		this->cur_order_index++;
+		return 0;
 	}
-
-	if (order->type  == v->current_order.type &&
-			order->flags == v->current_order.flags &&
-			order->dest  == v->current_order.dest &&
-			(order->type != OT_GOTO_STATION || GetStation(order->dest)->dock_tile != 0))
-		return;
-
-	v->current_order = *order;
-
-	if (order->type == OT_GOTO_STATION) {
-		const Station *st;
-
-		if (order->dest == v->last_station_visited)
-			v->last_station_visited = INVALID_STATION;
-
-		st = GetStation(order->dest);
-		if (st->dock_tile != 0) {
-			v->dest_tile = TILE_ADD(st->dock_tile, ToTileIndexDiff(GetDockOffset(st->dock_tile)));
-		} else {
-			v->cur_order_index++;
-		}
-	} else if (order->type == OT_GOTO_DEPOT) {
-		v->dest_tile = GetDepot(order->dest)->xy;
-	} else {
-		v->dest_tile = 0;
-	}
-
-	InvalidateVehicleOrder(v);
-
-	InvalidateWindowClasses(WC_SHIPS_LIST);
 }
 
 void Ship::UpdateDeltaXY(Direction direction)
@@ -650,7 +599,7 @@
 
 	if (v->vehstatus & VS_STOPPED) return;
 
-	ProcessShipOrder(v);
+	ProcessOrders(v);
 	v->HandleLoading();
 
 	if (v->current_order.type == OT_LOADING) return;
--- a/src/train.h
+++ b/src/train.h
@@ -306,6 +306,7 @@
 	bool IsStoppedInDepot() const { return CheckTrainStoppedInDepot(this) >= 0; }
 	void Tick();
 	void OnNewDay();
+	TileIndex GetOrderStationLocation(StationID station);
 };
 
 #endif /* TRAIN_H */
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -11,7 +11,6 @@
 #include "gui.h"
 #include "station_map.h"
 #include "tunnel_map.h"
-#include "timetable.h"
 #include "articulated_vehicles.h"
 #include "command_func.h"
 #include "pathfind.h"
@@ -2616,94 +2615,9 @@
 	return reverse_best != 0;
 }
 
-static bool ProcessTrainOrder(Vehicle *v)
+TileIndex Train::GetOrderStationLocation(StationID station)
 {
-	switch (v->current_order.type) {
-		case OT_GOTO_DEPOT:
-			if (!(v->current_order.flags & OFB_PART_OF_ORDERS)) return false;
-			if ((v->current_order.flags & OFB_SERVICE_IF_NEEDED) &&
-					!VehicleNeedsService(v)) {
-				UpdateVehicleTimetable(v, true);
-				v->cur_order_index++;
-			}
-			break;
-
-		case OT_LOADING:
-		case OT_LEAVESTATION:
-			return false;
-
-		default: break;
-	}
-
-	/**
-	 * Reversing because of order change is allowed only just after leaving a
-	 * station (and the difficulty setting to allowed, of course)
-	 * this can be detected because only after OT_LEAVESTATION, current_order
-	 * will be reset to nothing. (That also happens if no order, but in that case
-	 * it won't hit the point in code where may_reverse is checked)
-	 */
-	bool may_reverse = v->current_order.type == OT_NOTHING;
-
-	/* check if we've reached the waypoint? */
-	if (v->current_order.type == OT_GOTO_WAYPOINT && v->tile == v->dest_tile) {
-		UpdateVehicleTimetable(v, true);
-		v->cur_order_index++;
-	}
-
-	/* check if we've reached a non-stop station while TTDPatch nonstop is enabled.. */
-	if (_patches.new_nonstop &&
-			v->current_order.flags & OFB_NON_STOP &&
-			IsTileType(v->tile, MP_STATION) &&
-			v->current_order.dest == GetStationIndex(v->tile)) {
-		UpdateVehicleTimetable(v, true);
-		v->cur_order_index++;
-	}
-
-	/* Get the current order */
-	if (v->cur_order_index >= v->num_orders) v->cur_order_index = 0;
-
-	const Order *order = GetVehicleOrder(v, v->cur_order_index);
-
-	/* If no order, do nothing. */
-	if (order == NULL) {
-		v->current_order.Free();
-		v->dest_tile = 0;
-		return false;
-	}
-
-	/* If it is unchanged, keep it. */
-	if (order->type  == v->current_order.type &&
-			order->flags == v->current_order.flags &&
-			order->dest  == v->current_order.dest)
-		return false;
-
-	/* Otherwise set it, and determine the destination tile. */
-	v->current_order = *order;
-
-	v->dest_tile = 0;
-
-	InvalidateVehicleOrder(v);
-
-	switch (order->type) {
-		case OT_GOTO_STATION:
-			if (order->dest == v->last_station_visited)
-				v->last_station_visited = INVALID_STATION;
-			v->dest_tile = GetStation(order->dest)->xy;
-			break;
-
-		case OT_GOTO_DEPOT:
-			v->dest_tile = GetDepot(order->dest)->xy;
-			break;
-
-		case OT_GOTO_WAYPOINT:
-			v->dest_tile = GetWaypoint(order->dest)->xy;
-			break;
-
-		default:
-			return false;
-	}
-
-	return may_reverse && CheckReverseTrain(v);
+	return GetStation(station)->xy;
 }
 
 void Train::MarkDirty()
@@ -3565,7 +3479,7 @@
 	/* exit if train is stopped */
 	if (v->vehstatus & VS_STOPPED && v->cur_speed == 0) return;
 
-	if (ProcessTrainOrder(v)) {
+	if (ProcessOrders(v) && CheckReverseTrain(v)) {
 		v->load_unload_time_rem = 0;
 		v->cur_speed = 0;
 		v->subspeed = 0;
--- a/src/vehicle_base.h
+++ b/src/vehicle_base.h
@@ -488,6 +488,15 @@
 	inline bool IsOrderListShared() const { return this->next_shared != NULL || this->prev_shared != NULL; };
 
 	bool NeedsAutorenewing(const Player *p) const;
+
+	/**
+	 * Determine the location for the station where the vehicle goes to next.
+	 * Things done for example are allocating slots in a road stop or exact
+	 * location of the platform is determined for ships.
+	 * @param station the station to make the next location of the vehicle.
+	 * @return the location (tile) to aim for.
+	 */
+	virtual TileIndex GetOrderStationLocation(StationID station) { return INVALID_TILE; }
 };
 
 /**