changeset 11976:7f11f2a71193 draft

(svn r16382) -Codechange: make GetVehicleTrackdir a member function of Vehicle.
author rubidium <rubidium@openttd.org>
date Fri, 22 May 2009 18:17:20 +0000
parents 40dd9637a575
children 5a2c559ba843
files src/pbs.cpp src/roadveh.h src/roadveh_cmd.cpp src/saveload/oldloader_sl.cpp src/saveload/vehicle_sl.cpp src/ship.h src/ship_cmd.cpp src/station_cmd.cpp src/train.h src/train_cmd.cpp src/tunnelbridge_cmd.cpp src/vehicle.cpp src/vehicle_base.h src/yapf/yapf_rail.cpp src/yapf/yapf_road.cpp src/yapf/yapf_ship.cpp
diffstat 16 files changed, 126 insertions(+), 110 deletions(-) [+]
line wrap: on
line diff
--- a/src/pbs.cpp
+++ b/src/pbs.cpp
@@ -256,7 +256,7 @@
 	assert(v->type == VEH_TRAIN);
 
 	TileIndex tile = v->tile;
-	Trackdir  trackdir = GetVehicleTrackdir(v);
+	Trackdir  trackdir = v->GetVehicleTrackdir();
 
 	if (IsRailDepotTile(tile) && !GetRailDepotReservation(tile)) return PBSTileInfo(tile, trackdir, false);
 
--- a/src/roadveh.h
+++ b/src/roadveh.h
@@ -101,6 +101,7 @@
 	bool IsStoppedInDepot() const;
 	bool Tick();
 	void OnNewDay();
+	Trackdir GetVehicleTrackdir() const;
 	TileIndex GetOrderStationLocation(StationID station);
 	bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
 };
--- a/src/roadveh_cmd.cpp
+++ b/src/roadveh_cmd.cpp
@@ -364,7 +364,7 @@
 
 		case VPF_NPF: { // NPF
 			/* See where we are now */
-			Trackdir trackdir = GetVehicleTrackdir(v);
+			Trackdir trackdir = v->GetVehicleTrackdir();
 
 			NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, false, v->tile, ReverseTrackdir(trackdir), false, TRANSPORT_ROAD, v->u.road.compatible_roadtypes, v->owner, INVALID_RAILTYPES, 0);
 
@@ -1174,7 +1174,7 @@
 	}
 
 	/* use NPF */
-	Trackdir trackdir = GetVehicleTrackdir(v);
+	Trackdir trackdir = v->GetVehicleTrackdir();
 	assert(trackdir != INVALID_TRACKDIR);
 
 	NPFFindStationOrTileData fstd;
@@ -1950,6 +1950,29 @@
 	InvalidateWindowClasses(WC_ROADVEH_LIST);
 }
 
+Trackdir RoadVehicle::GetVehicleTrackdir() const
+{
+	if (this->vehstatus & VS_CRASHED) return INVALID_TRACKDIR;
+
+	if (this->IsInDepot()) {
+		/* We'll assume the road vehicle is facing outwards */
+		return DiagDirToDiagTrackdir(GetRoadDepotDirection(this->tile));
+	}
+
+	if (IsStandardRoadStopTile(this->tile)) {
+		/* We'll assume the road vehicle is facing outwards */
+		return DiagDirToDiagTrackdir(GetRoadStopDir(this->tile)); // Road vehicle in a station
+	}
+
+	/* Drive through road stops / wormholes (tunnels) */
+	if (this->u.road.state > RVSB_TRACKDIR_MASK) return DiagDirToDiagTrackdir(DirToDiagDir(this->direction));
+
+	/* If vehicle's state is a valid track direction (vehicle is not turning around) return it,
+	 * otherwise transform it into a valid track direction */
+	return (Trackdir)((IsReversingRoadTrackdir((Trackdir)this->u.road.state)) ? (this->u.road.state - 6) : this->u.road.state);
+}
+
+
 /** Refit a road vehicle to the specified cargo type
  * @param tile unused
  * @param flags operation to perform
--- a/src/saveload/oldloader_sl.cpp
+++ b/src/saveload/oldloader_sl.cpp
@@ -1103,7 +1103,7 @@
 };
 
 static const OldChunks vehicle_ship_chunk[] = {
-	OCL_SVAR(  OC_UINT8, VehicleShip, state ),
+	OCL_SVAR(  OC_UINT8, Ship, state ),
 
 	OCL_NULL( 9 ), ///< Junk
 
@@ -1158,7 +1158,7 @@
 			default: NOT_REACHED();
 			case VEH_TRAIN   : res = LoadChunk(ls, &v->u.rail,     vehicle_train_chunk);    break;
 			case VEH_ROAD    : res = LoadChunk(ls, &v->u.road,     vehicle_road_chunk);     break;
-			case VEH_SHIP    : res = LoadChunk(ls, &v->u.ship,     vehicle_ship_chunk);     break;
+			case VEH_SHIP    : res = LoadChunk(ls, v, vehicle_ship_chunk);     break;
 			case VEH_AIRCRAFT: res = LoadChunk(ls, &v->u.air,      vehicle_air_chunk);      break;
 			case VEH_EFFECT  : res = LoadChunk(ls, &v->u.effect,   vehicle_effect_chunk);   break;
 			case VEH_DISASTER: res = LoadChunk(ls, &v->u.disaster, vehicle_disaster_chunk); break;
--- a/src/saveload/vehicle_sl.cpp
+++ b/src/saveload/vehicle_sl.cpp
@@ -560,7 +560,7 @@
 	static const SaveLoad _ship_desc[] = {
 		SLE_WRITEBYTE(Vehicle, type, VEH_SHIP),
 		SLE_VEH_INCLUDEX(),
-		    SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleShip, state),  SLE_UINT8),
+		     SLE_VAR(Ship, state, SLE_UINT8),
 
 		/* reserve extra space in savegame here. (currently 16 bytes) */
 		SLE_CONDNULL(16, 2, SL_MAX_VERSION),
--- a/src/ship.h
+++ b/src/ship.h
@@ -23,6 +23,8 @@
  * As side-effect the vehicle type is set correctly.
  */
 struct Ship: public Vehicle {
+	TrackBitsByte state;
+
 	/** Initializes the Vehicle to a ship */
 	Ship() { this->type = VEH_SHIP; }
 
@@ -39,9 +41,10 @@
 	int GetDisplaySpeed() const { return this->cur_speed / 2; }
 	int GetDisplayMaxSpeed() const { return this->max_speed / 2; }
 	Money GetRunningCost() const;
-	bool IsInDepot() const { return this->u.ship.state == TRACK_BIT_DEPOT; }
+	bool IsInDepot() const { return this->state == TRACK_BIT_DEPOT; }
 	bool Tick();
 	void OnNewDay();
+	Trackdir GetVehicleTrackdir() const;
 	TileIndex GetOrderStationLocation(StationID station);
 	bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
 };
--- a/src/ship_cmd.cpp
+++ b/src/ship_cmd.cpp
@@ -97,7 +97,7 @@
 static const Depot *FindClosestShipDepot(const Vehicle *v)
 {
 	if (_settings_game.pf.pathfinder_for_ships == VPF_NPF) { // NPF is used
-		Trackdir trackdir = GetVehicleTrackdir(v);
+		Trackdir trackdir = v->GetVehicleTrackdir();
 		NPFFoundTargetData ftd = NPFRouteToDepotTrialError(v->tile, trackdir, false, TRANSPORT_WATER, 0, v->owner, INVALID_RAILTYPES);
 
 		if (ftd.best_bird_dist == 0) return GetDepotByTile(ftd.node.tile); // Found target
@@ -178,6 +178,23 @@
 	InvalidateWindowClasses(WC_SHIPS_LIST);
 }
 
+Trackdir Ship::GetVehicleTrackdir() const
+{
+	if (this->vehstatus & VS_CRASHED) return INVALID_TRACKDIR;
+
+	if (this->IsInDepot()) {
+		/* We'll assume the ship is facing outwards */
+		return DiagDirToDiagTrackdir(GetShipDepotDirection(this->tile));
+	}
+
+	if (this->state == TRACK_BIT_WORMHOLE) {
+		/* ship on aqueduct, so just use his direction and assume a diagonal track */
+		return DiagDirToDiagTrackdir(DirToDiagDir(this->direction));
+	}
+
+	return TrackDirectionToTrackdir(FindFirstTrack(this->state), this->direction);
+}
+
 static void HandleBrokenShip(Vehicle *v)
 {
 	if (v->breakdown_ctr != 1) {
@@ -276,7 +293,7 @@
 	{ 0, -1}
 };
 
-static void CheckShipLeaveDepot(Vehicle *v)
+static void CheckShipLeaveDepot(Ship *v)
 {
 	if (!v->IsInDepot()) return;
 
@@ -293,7 +310,7 @@
 		return;
 	}
 
-	v->u.ship.state = AxisToTrackBits(axis);
+	v->state = AxisToTrackBits(axis);
 	v->vehstatus &= ~VS_HIDDEN;
 
 	v->cur_speed = 0;
@@ -447,7 +464,7 @@
 /** returns the track to choose on the next tile, or -1 when it's better to
  * reverse. The tile given is the tile we are about to enter, enterdir is the
  * direction in which we are entering the tile */
-static Track ChooseShipTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
+static Track ChooseShipTrack(Ship *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
 {
 	assert(IsValidDiagDirection(enterdir));
 
@@ -459,7 +476,7 @@
 
 		case VPF_NPF: { // NPF
 			NPFFindStationOrTileData fstd;
-			Trackdir trackdir = GetVehicleTrackdir(v);
+			Trackdir trackdir = v->GetVehicleTrackdir();
 			assert(trackdir != INVALID_TRACKDIR); // Check that we are not in a depot
 
 			NPFFillWithOrderData(&fstd, v);
@@ -479,7 +496,7 @@
 			Track track;
 
 			/* Let's find out how far it would be if we would reverse first */
-			TrackBits b = GetTileShipTrackStatus(tile2) & _ship_sometracks[ReverseDiagDir(enterdir)] & v->u.ship.state;
+			TrackBits b = GetTileShipTrackStatus(tile2) & _ship_sometracks[ReverseDiagDir(enterdir)] & v->state;
 
 			uint distr = UINT_MAX; // distance if we reversed
 			if (b != 0) {
@@ -558,7 +575,7 @@
 	}
 };
 
-static void ShipController(Vehicle *v)
+static void ShipController(Ship *v)
 {
 	uint32 r;
 	const byte *b;
@@ -589,7 +606,7 @@
 	if (!ShipAccelerate(v)) return;
 
 	GetNewVehiclePosResult gp = GetNewVehiclePos(v);
-	if (v->u.ship.state != TRACK_BIT_WORMHOLE) {
+	if (v->state != TRACK_BIT_WORMHOLE) {
 		/* Not on a bridge */
 		if (gp.old_tile == gp.new_tile) {
 			/* Staying in tile */
@@ -669,7 +686,7 @@
 
 			if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
 				v->tile = gp.new_tile;
-				v->u.ship.state = TrackToTrackBits(track);
+				v->state = TrackToTrackBits(track);
 			}
 
 			v->direction = (Direction)b[2];
@@ -754,7 +771,7 @@
 
 		const ShipVehicleInfo *svi = ShipVehInfo(p1);
 
-		Vehicle *v = new Ship();
+		Ship *v = new Ship();
 		v->unitnumber = unit_num;
 
 		v->owner = _current_company;
@@ -786,7 +803,7 @@
 		_new_vehicle_id = v->index;
 
 		v->name = NULL;
-		v->u.ship.state = TRACK_BIT_DEPOT;
+		v->state = TRACK_BIT_DEPOT;
 
 		v->service_interval = _settings_game.vehicle.servint_ships;
 		v->date_of_last_service = _date;
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -1027,9 +1027,9 @@
 					if (v != NULL) {
 						FreeTrainTrackReservation(v);
 						*affected_vehicles.Append() = v;
-						if (IsRailwayStationTile(v->tile)) SetRailwayStationPlatformReservation(v->tile, TrackdirToExitdir(GetVehicleTrackdir(v)), false);
+						if (IsRailwayStationTile(v->tile)) SetRailwayStationPlatformReservation(v->tile, TrackdirToExitdir(v->GetVehicleTrackdir()), false);
 						for (; v->Next() != NULL; v = v->Next()) ;
-						if (IsRailwayStationTile(v->tile)) SetRailwayStationPlatformReservation(v->tile, TrackdirToExitdir(ReverseTrackdir(GetVehicleTrackdir(v))), false);
+						if (IsRailwayStationTile(v->tile)) SetRailwayStationPlatformReservation(v->tile, TrackdirToExitdir(ReverseTrackdir(v->GetVehicleTrackdir())), false);
 					}
 				}
 
@@ -1064,10 +1064,10 @@
 		for (uint i = 0; i < affected_vehicles.Length(); ++i) {
 			/* Restore reservations of trains. */
 			Vehicle *v = affected_vehicles[i];
-			if (IsRailwayStationTile(v->tile)) SetRailwayStationPlatformReservation(v->tile, TrackdirToExitdir(GetVehicleTrackdir(v)), true);
+			if (IsRailwayStationTile(v->tile)) SetRailwayStationPlatformReservation(v->tile, TrackdirToExitdir(v->GetVehicleTrackdir()), true);
 			TryPathReserve(v, true, true);
 			for (; v->Next() != NULL; v = v->Next()) ;
-			if (IsRailwayStationTile(v->tile)) SetRailwayStationPlatformReservation(v->tile, TrackdirToExitdir(ReverseTrackdir(GetVehicleTrackdir(v))), true);
+			if (IsRailwayStationTile(v->tile)) SetRailwayStationPlatformReservation(v->tile, TrackdirToExitdir(ReverseTrackdir(v->GetVehicleTrackdir())), true);
 		}
 
 		st->MarkTilesDirty(false);
@@ -1203,10 +1203,10 @@
 				if (v != NULL) {
 					/* Free train reservation. */
 					FreeTrainTrackReservation(v);
-					if (IsRailwayStationTile(v->tile)) SetRailwayStationPlatformReservation(v->tile, TrackdirToExitdir(GetVehicleTrackdir(v)), false);
+					if (IsRailwayStationTile(v->tile)) SetRailwayStationPlatformReservation(v->tile, TrackdirToExitdir(v->GetVehicleTrackdir()), false);
 					Vehicle *temp = v;
 					for (; temp->Next() != NULL; temp = temp->Next()) ;
-					if (IsRailwayStationTile(temp->tile)) SetRailwayStationPlatformReservation(temp->tile, TrackdirToExitdir(ReverseTrackdir(GetVehicleTrackdir(temp))), false);
+					if (IsRailwayStationTile(temp->tile)) SetRailwayStationPlatformReservation(temp->tile, TrackdirToExitdir(ReverseTrackdir(temp->GetVehicleTrackdir())), false);
 				}
 			}
 
@@ -1226,10 +1226,10 @@
 
 			if (v != NULL) {
 				/* Restore station reservation. */
-				if (IsRailwayStationTile(v->tile)) SetRailwayStationPlatformReservation(v->tile, TrackdirToExitdir(GetVehicleTrackdir(v)), true);
+				if (IsRailwayStationTile(v->tile)) SetRailwayStationPlatformReservation(v->tile, TrackdirToExitdir(v->GetVehicleTrackdir()), true);
 				TryPathReserve(v, true, true);
 				for (; v->Next() != NULL; v = v->Next()) ;
-				if (IsRailwayStationTile(v->tile)) SetRailwayStationPlatformReservation(v->tile, TrackdirToExitdir(ReverseTrackdir(GetVehicleTrackdir(v))), true);
+				if (IsRailwayStationTile(v->tile)) SetRailwayStationPlatformReservation(v->tile, TrackdirToExitdir(ReverseTrackdir(v->GetVehicleTrackdir())), true);
 			}
 
 			/* if we deleted the whole station, delete the train facility. */
--- a/src/train.h
+++ b/src/train.h
@@ -331,6 +331,7 @@
 	bool IsStoppedInDepot() const { return CheckTrainStoppedInDepot(this) >= 0; }
 	bool Tick();
 	void OnNewDay();
+	Trackdir GetVehicleTrackdir() const;
 	TileIndex GetOrderStationLocation(StationID station);
 	bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
 };
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -1920,10 +1920,10 @@
 		/* If we are currently on a tile with conventional signals, we can't treat the
 		 * current tile as a safe tile or we would enter a PBS block without a reservation. */
 		bool first_tile_okay = !(IsTileType(v->tile, MP_RAILWAY) &&
-			HasSignalOnTrackdir(v->tile, GetVehicleTrackdir(v)) &&
+			HasSignalOnTrackdir(v->tile, v->GetVehicleTrackdir()) &&
 			!IsPbsSignal(GetSignalType(v->tile, FindFirstTrack(v->u.rail.track))));
 
-		if (IsRailwayStationTile(v->tile)) SetRailwayStationPlatformReservation(v->tile, TrackdirToExitdir(GetVehicleTrackdir(v)), true);
+		if (IsRailwayStationTile(v->tile)) SetRailwayStationPlatformReservation(v->tile, TrackdirToExitdir(v->GetVehicleTrackdir()), true);
 		if (TryPathReserve(v, false, first_tile_okay)) {
 			/* Do a look-ahead now in case our current tile was already a safe tile. */
 			CheckNextTrainTile(v);
@@ -2169,8 +2169,8 @@
 
 		case VPF_NPF: { // NPF
 			const Vehicle *last = GetLastVehicleInChain(v);
-			Trackdir trackdir = GetVehicleTrackdir(v);
-			Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
+			Trackdir trackdir = v->GetVehicleTrackdir();
+			Trackdir trackdir_rev = ReverseTrackdir(last->GetVehicleTrackdir());
 
 			assert(trackdir != INVALID_TRACKDIR);
 			NPFFoundTargetData ftd = NPFRouteToDepotBreadthFirstTwoWay(v->tile, trackdir, false, last->tile, trackdir_rev, false, TRANSPORT_RAIL, 0, v->owner, v->u.rail.compatible_railtypes, NPF_INFINITE_PENALTY);
@@ -2353,7 +2353,7 @@
 	/* Exit if the current order doesn't have a destination, but the train has orders. */
 	if ((v->current_order.IsType(OT_NOTHING) || v->current_order.IsType(OT_LEAVESTATION) || v->current_order.IsType(OT_LOADING)) && v->GetNumOrders() > 0) return;
 
-	Trackdir td = GetVehicleTrackdir(v);
+	Trackdir td = v->GetVehicleTrackdir();
 
 	/* On a tile with a red non-pbs signal, don't look ahead. */
 	if (IsTileType(v->tile, MP_RAILWAY) && HasSignalOnTrackdir(v->tile, td) &&
@@ -2493,7 +2493,7 @@
 	assert(IsFrontEngine(v));
 
 	TileIndex tile = origin != INVALID_TILE ? origin : v->tile;
-	Trackdir  td = orig_td != INVALID_TRACKDIR ? orig_td : GetVehicleTrackdir(v);
+	Trackdir  td = orig_td != INVALID_TRACKDIR ? orig_td : v->GetVehicleTrackdir();
 	bool      free_tile = tile != v->tile || !(IsRailwayStationTile(v->tile) || IsTileType(v->tile, MP_TUNNELBRIDGE));
 	StationID station_id = IsRailwayStationTile(v->tile) ? GetStationIndex(v->tile) : INVALID_STATION;
 
@@ -3013,7 +3013,7 @@
 		if (TryReserveSafeTrack(v, origin.tile, origin.trackdir, false)) {
 			TrackBits res = GetReservedTrackbits(tile) & DiagdirReachesTracks(enterdir);
 			best_track = FindFirstTrack(res);
-			TryReserveRailTrack(v->tile, TrackdirToTrack(GetVehicleTrackdir(v)));
+			TryReserveRailTrack(v->tile, TrackdirToTrack(v->GetVehicleTrackdir()));
 			if (got_reservation != NULL) *got_reservation = true;
 			if (changed_signal) MarkTileDirtyByTile(tile);
 		} else {
@@ -3060,7 +3060,7 @@
 		break;
 	}
 
-	TryReserveRailTrack(v->tile, TrackdirToTrack(GetVehicleTrackdir(v)));
+	TryReserveRailTrack(v->tile, TrackdirToTrack(v->GetVehicleTrackdir()));
 
 	if (changed_signal) MarkTileDirtyByTile(tile);
 
@@ -3179,8 +3179,8 @@
 
 			NPFFillWithOrderData(&fstd, v);
 
-			Trackdir trackdir = GetVehicleTrackdir(v);
-			Trackdir trackdir_rev = ReverseTrackdir(GetVehicleTrackdir(last));
+			Trackdir trackdir = v->GetVehicleTrackdir();
+			Trackdir trackdir_rev = ReverseTrackdir(last->GetVehicleTrackdir());
 			assert(trackdir != INVALID_TRACKDIR);
 			assert(trackdir_rev != INVALID_TRACKDIR);
 
@@ -3471,7 +3471,7 @@
 		 * and any railway station paltform reservation. */
 		FreeTrainTrackReservation(v);
 		for (const Vehicle *u = v; u != NULL; u = u->Next()) {
-			ClearPathReservation(u, u->tile, GetVehicleTrackdir(u));
+			ClearPathReservation(u, u->tile, u->GetVehicleTrackdir());
 			if (IsTileType(u->tile, MP_TUNNELBRIDGE)) {
 				/* ClearPathReservation will not free the wormhole exit
 				 * if the train has just entered the wormhole. */
@@ -3796,7 +3796,7 @@
 					}
 
 					/* Clear any track reservation when the last vehicle leaves the tile */
-					if (v->Next() == NULL) ClearPathReservation(v, v->tile, GetVehicleTrackdir(v));
+					if (v->Next() == NULL) ClearPathReservation(v, v->tile, v->GetVehicleTrackdir());
 
 					v->tile = gp.new_tile;
 
@@ -4520,6 +4520,23 @@
 	}
 }
 
+Trackdir Train::GetVehicleTrackdir() const
+{
+	if (this->vehstatus & VS_CRASHED) return INVALID_TRACKDIR;
+
+	if (this->u.rail.track == TRACK_BIT_DEPOT) {
+		/* We'll assume the train is facing outwards */
+		return DiagDirToDiagTrackdir(GetRailDepotDirection(this->tile)); // Train in depot
+	}
+
+	if (this->u.rail.track == TRACK_BIT_WORMHOLE) {
+		/* train in tunnel or on bridge, so just use his direction and assume a diagonal track */
+		return DiagDirToDiagTrackdir(DirToDiagDir(this->direction));
+	}
+
+	return TrackDirectionToTrackdir(FindFirstTrack(this->u.rail.track), this->direction);
+}
+
 void InitializeTrains()
 {
 	_age_cargo_skip_counter = 1;
--- a/src/tunnelbridge_cmd.cpp
+++ b/src/tunnelbridge_cmd.cpp
@@ -15,6 +15,7 @@
 #include "town.h"
 #include "variables.h"
 #include "train.h"
+#include "ship.h"
 #include "water_map.h"
 #include "yapf/yapf.h"
 #include "newgrf_sound.h"
@@ -1470,7 +1471,7 @@
 					break;
 
 				case VEH_SHIP:
-					v->u.ship.state = TRACK_BIT_WORMHOLE;
+					static_cast<Ship*>(v)->state = TRACK_BIT_WORMHOLE;
 					break;
 
 				default: NOT_REACHED();
@@ -1495,8 +1496,8 @@
 					break;
 
 				case VEH_SHIP:
-					if (v->u.ship.state == TRACK_BIT_WORMHOLE) {
-						v->u.ship.state = (DiagDirToAxis(dir) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y);
+					if (static_cast<Ship*>(v)->state == TRACK_BIT_WORMHOLE) {
+						static_cast<Ship*>(v)->state = (DiagDirToAxis(dir) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y);
 						return VETSB_ENTERED_WORMHOLE;
 					}
 					break;
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -992,7 +992,7 @@
 
 		case VEH_SHIP:
 			InvalidateWindowClasses(WC_SHIPS_LIST);
-			v->u.ship.state = TRACK_BIT_DEPOT;
+			static_cast<Ship*>(v)->state = TRACK_BIT_DEPOT;
 			RecalcShipStuff(v);
 			break;
 
@@ -1173,49 +1173,6 @@
 	return ChangeDir(dir, dirdiff > DIRDIFF_REVERSE ? DIRDIFF_45LEFT : DIRDIFF_45RIGHT);
 }
 
-Trackdir GetVehicleTrackdir(const Vehicle *v)
-{
-	if (v->vehstatus & VS_CRASHED) return INVALID_TRACKDIR;
-
-	switch (v->type) {
-		case VEH_TRAIN:
-			if (v->u.rail.track == TRACK_BIT_DEPOT) // We'll assume the train is facing outwards
-				return DiagDirToDiagTrackdir(GetRailDepotDirection(v->tile)); // Train in depot
-
-			if (v->u.rail.track == TRACK_BIT_WORMHOLE) // train in tunnel or on bridge, so just use his direction and assume a diagonal track
-				return DiagDirToDiagTrackdir(DirToDiagDir(v->direction));
-
-			return TrackDirectionToTrackdir(FindFirstTrack(v->u.rail.track), v->direction);
-
-		case VEH_SHIP:
-			if (v->IsInDepot())
-				/* We'll assume the ship is facing outwards */
-				return DiagDirToDiagTrackdir(GetShipDepotDirection(v->tile));
-
-			if (v->u.ship.state == TRACK_BIT_WORMHOLE) // ship on aqueduct, so just use his direction and assume a diagonal track
-				return DiagDirToDiagTrackdir(DirToDiagDir(v->direction));
-
-			return TrackDirectionToTrackdir(FindFirstTrack(v->u.ship.state), v->direction);
-
-		case VEH_ROAD:
-			if (v->IsInDepot()) // We'll assume the road vehicle is facing outwards
-				return DiagDirToDiagTrackdir(GetRoadDepotDirection(v->tile));
-
-			if (IsStandardRoadStopTile(v->tile)) // We'll assume the road vehicle is facing outwards
-				return DiagDirToDiagTrackdir(GetRoadStopDir(v->tile)); // Road vehicle in a station
-
-			/* Drive through road stops / wormholes (tunnels) */
-			if (v->u.road.state > RVSB_TRACKDIR_MASK) return DiagDirToDiagTrackdir(DirToDiagDir(v->direction));
-
-			/* If vehicle's state is a valid track direction (vehicle is not turning around) return it,
-			 * otherwise transform it into a valid track direction */
-			return (Trackdir)((IsReversingRoadTrackdir((Trackdir)v->u.road.state)) ? (v->u.road.state - 6) : v->u.road.state);
-
-		/* case VEH_AIRCRAFT: case VEH_EFFECT: case VEH_DISASTER: */
-		default: return INVALID_TRACKDIR;
-	}
-}
-
 /**
  * Call the tile callback function for a vehicle entering a tile
  * @param v    Vehicle entering the tile
@@ -1529,7 +1486,7 @@
 		/* Try to reserve a path when leaving the station as we
 		 * might not be marked as wanting a reservation, e.g.
 		 * when an overlength train gets turned around in a station. */
-		if (UpdateSignalsOnSegment(this->tile, TrackdirToExitdir(GetVehicleTrackdir(this)), this->owner) == SIGSEG_PBS || _settings_game.pf.reserve_paths) {
+		if (UpdateSignalsOnSegment(this->tile, TrackdirToExitdir(this->GetVehicleTrackdir()), this->owner) == SIGSEG_PBS || _settings_game.pf.reserve_paths) {
 			TryPathReserve(this, true, true);
 		}
 	}
--- a/src/vehicle_base.h
+++ b/src/vehicle_base.h
@@ -185,10 +185,6 @@
 	VehicleID big_ufo_destroyer_target;
 };
 
-struct VehicleShip {
-	TrackBitsByte state;
-};
-
 typedef Pool<Vehicle, VehicleID, 512, 64000> VehiclePool;
 extern VehiclePool _vehicle_pool;
 
@@ -322,7 +318,6 @@
 		VehicleRoad road;
 		VehicleEffect effect;
 		VehicleDisaster disaster;
-		VehicleShip ship;
 	} u;
 
 	/* cached oftenly queried NewGRF values */
@@ -438,6 +433,20 @@
 	virtual void OnNewDay() {};
 
 	/**
+	 * Returns the Trackdir on which the vehicle is currently located.
+	 * Works for trains and ships.
+	 * Currently works only sortof for road vehicles, since they have a fuzzy
+	 * concept of being "on" a trackdir. Dunno really what it returns for a road
+	 * vehicle that is halfway a tile, never really understood that part. For road
+	 * vehicles that are at the beginning or end of the tile, should just return
+	 * the diagonal trackdir on which they are driving. I _think_.
+	 * For other vehicles types, or vehicles with no clear trackdir (such as those
+	 * in depots), returns 0xFF.
+	 * @return the trackdir of the vehicle
+	 */
+	virtual Trackdir GetVehicleTrackdir() const { return INVALID_TRACKDIR; }
+
+	/**
 	 * Gets the running cost of a vehicle  that can be sent into SetDParam for string processing.
 	 * @return the vehicle's running cost
 	 */
@@ -663,19 +672,6 @@
  */
 static inline Order *GetLastVehicleOrder(const Vehicle *v) { return (v->orders.list == NULL) ? NULL : v->orders.list->GetLastOrder(); }
 
-/**
- * Returns the Trackdir on which the vehicle is currently located.
- * Works for trains and ships.
- * Currently works only sortof for road vehicles, since they have a fuzzy
- * concept of being "on" a trackdir. Dunno really what it returns for a road
- * vehicle that is halfway a tile, never really understood that part. For road
- * vehicles that are at the beginning or end of the tile, should just return
- * the diagonal trackdir on which they are driving. I _think_.
- * For other vehicles types, or vehicles with no clear trackdir (such as those
- * in depots), returns 0xFF.
- */
-Trackdir GetVehicleTrackdir(const Vehicle *v);
-
 void CheckVehicle32Day(Vehicle *v);
 
 static const int32 INVALID_COORD = 0x7fffffff;
--- a/src/yapf/yapf_rail.cpp
+++ b/src/yapf/yapf_rail.cpp
@@ -540,8 +540,8 @@
 	const Vehicle *last_veh = GetLastVehicleInChain(v);
 
 	/* get trackdirs of both ends */
-	Trackdir td = GetVehicleTrackdir(v);
-	Trackdir td_rev = ReverseTrackdir(GetVehicleTrackdir(last_veh));
+	Trackdir td = v->GetVehicleTrackdir();
+	Trackdir td_rev = ReverseTrackdir(last_veh->GetVehicleTrackdir());
 
 	/* tiles where front and back are */
 	TileIndex tile = v->tile;
@@ -603,7 +603,7 @@
 
 	PBSTileInfo origin = FollowTrainReservation(v);
 	TileIndex last_tile = last_veh->tile;
-	Trackdir td_rev = ReverseTrackdir(GetVehicleTrackdir(last_veh));
+	Trackdir td_rev = ReverseTrackdir(last_veh->GetVehicleTrackdir());
 
 	typedef bool (*PfnFindNearestDepotTwoWay)(const Vehicle*, TileIndex, Trackdir, TileIndex, Trackdir, int, int, TileIndex*, bool*);
 	PfnFindNearestDepotTwoWay pfnFindNearestDepotTwoWay = &CYapfAnyDepotRail1::stFindNearestDepotTwoWay;
--- a/src/yapf/yapf_road.cpp
+++ b/src/yapf/yapf_road.cpp
@@ -372,7 +372,7 @@
 	{
 		/* set origin (tile, trackdir) */
 		TileIndex src_tile = v->tile;
-		Trackdir src_td = GetVehicleTrackdir(v);
+		Trackdir src_td = v->GetVehicleTrackdir();
 		if ((TrackStatusToTrackdirBits(GetTileTrackStatus(src_tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes)) & TrackdirToTrackdirBits(src_td)) == 0) {
 			/* sometimes the roadveh is not on the road (it resides on non-existing track)
 			 * how should we handle that situation? */
@@ -469,7 +469,7 @@
 Depot *YapfFindNearestRoadDepot(const Vehicle *v)
 {
 	TileIndex tile = v->tile;
-	Trackdir trackdir = GetVehicleTrackdir(v);
+	Trackdir trackdir = v->GetVehicleTrackdir();
 	if ((TrackStatusToTrackdirBits(GetTileTrackStatus(tile, TRANSPORT_ROAD, v->u.road.compatible_roadtypes)) & TrackdirToTrackdirBits(trackdir)) == 0) {
 		return NULL;
 	}
--- a/src/yapf/yapf_ship.cpp
+++ b/src/yapf/yapf_ship.cpp
@@ -54,7 +54,7 @@
 
 		/* move back to the old tile/trackdir (where ship is coming from) */
 		TileIndex src_tile = TILE_ADD(tile, TileOffsByDiagDir(ReverseDiagDir(enterdir)));
-		Trackdir trackdir = GetVehicleTrackdir(v);
+		Trackdir trackdir = v->GetVehicleTrackdir();
 		assert(IsValidTrackdir(trackdir));
 
 		/* convert origin trackdir to TrackdirBits */