changeset 11985:e05790b0a6c6 draft

(svn r16391) -Codechange: use Train instead of Vehicle where appropriate.
author rubidium <rubidium@openttd.org>
date Fri, 22 May 2009 22:22:46 +0000
parents b6d3e583be86
children 78abb48a4fba
files src/ai/api/ai_vehicle.cpp src/articulated_vehicles.cpp src/autoreplace_cmd.cpp src/elrail.cpp src/newgrf_engine.cpp src/npf.cpp src/npf.h src/openttd.cpp src/pbs.cpp src/pbs.h src/rail_cmd.cpp src/saveload/afterload.cpp src/saveload/oldloader_sl.cpp src/saveload/vehicle_sl.cpp src/settings.cpp src/signal.cpp src/station_cmd.cpp src/train.h src/train_cmd.cpp src/train_gui.cpp src/tunnelbridge_cmd.cpp src/vehicle.cpp src/vehicle_base.h src/vehicle_cmd.cpp src/vehicle_func.h src/vehicle_gui.cpp src/vehicle_type.h src/vehiclelist.cpp src/water_cmd.cpp src/waypoint_cmd.cpp src/yapf/follow_track.hpp src/yapf/yapf_destrail.hpp src/yapf/yapf_rail.cpp
diffstat 33 files changed, 430 insertions(+), 388 deletions(-) [+]
line wrap: on
line diff
--- a/src/ai/api/ai_vehicle.cpp
+++ b/src/ai/api/ai_vehicle.cpp
@@ -29,7 +29,7 @@
 
 	int num = 1;
 	if (::Vehicle::Get(vehicle_id)->type == VEH_TRAIN) {
-		const Vehicle *v = ::Vehicle::Get(vehicle_id);
+		const Train *v = (Train *)::Vehicle::Get(vehicle_id);
 		while ((v = GetNextUnit(v)) != NULL) num++;
 	}
 
@@ -85,11 +85,11 @@
 	EnforcePrecondition(false, ::Vehicle::Get(source_vehicle_id)->type == VEH_TRAIN);
 	EnforcePrecondition(false, dest_vehicle_id == -1 || ::Vehicle::Get(dest_vehicle_id)->type == VEH_TRAIN);
 
-	const Vehicle *v = ::Vehicle::Get(source_vehicle_id);
+	const Train *v = (Train *)::Vehicle::Get(source_vehicle_id);
 	while (source_wagon-- > 0) v = GetNextUnit(v);
-	const Vehicle *w = NULL;
+	const Train *w = NULL;
 	if (dest_vehicle_id != -1) {
-		w = ::Vehicle::Get(dest_vehicle_id);
+		w = (Train *)::Vehicle::Get(dest_vehicle_id);
 		while (dest_wagon-- > 0) w = GetNextUnit(w);
 	}
 
@@ -136,7 +136,7 @@
 	EnforcePrecondition(false, IsValidVehicle(vehicle_id) && wagon < GetNumWagons(vehicle_id));
 	EnforcePrecondition(false, ::Vehicle::Get(vehicle_id)->type == VEH_TRAIN);
 
-	const Vehicle *v = ::Vehicle::Get(vehicle_id);
+	const Train *v = (Train *)::Vehicle::Get(vehicle_id);
 	while (wagon-- > 0) v = GetNextUnit(v);
 
 	return AIObject::DoCommand(0, v->index, sell_attached_wagons ? 1 : 0, CMD_SELL_RAIL_WAGON);
@@ -243,7 +243,7 @@
 
 	const Vehicle *v = ::Vehicle::Get(vehicle_id);
 	if (v->type == VEH_TRAIN) {
-		while (wagon-- > 0) v = GetNextUnit(v);
+		while (wagon-- > 0) v = GetNextUnit((Train *)v);
 	}
 	return v->engine_type;
 }
@@ -281,7 +281,7 @@
 
 	const Vehicle *v = ::Vehicle::Get(vehicle_id);
 	if (v->type == VEH_TRAIN) {
-		while (wagon-- > 0) v = GetNextUnit(v);
+		while (wagon-- > 0) v = GetNextUnit((Train *)v);
 	}
 	return v->age;
 }
--- a/src/articulated_vehicles.cpp
+++ b/src/articulated_vehicles.cpp
@@ -208,7 +208,7 @@
 
 		switch (v->type) {
 			case VEH_TRAIN:
-				v = (EngineHasArticPart(v) ? GetNextArticPart(v) : NULL);
+				v = (EngineHasArticPart((Train *)v) ? GetNextArticPart((Train *)v) : NULL);
 				break;
 
 			case VEH_ROAD:
@@ -256,7 +256,7 @@
 
 		switch (v->type) {
 			case VEH_TRAIN:
-				v = (EngineHasArticPart(v) ? GetNextArticPart(v) : NULL);
+				v = (EngineHasArticPart((Train *)v) ? GetNextArticPart((Train *)v) : NULL);
 				break;
 
 			case VEH_ROAD:
@@ -307,25 +307,27 @@
 		switch (type) {
 			default: NOT_REACHED();
 
-			case VEH_TRAIN:
-				u = new Train();
-				u->subtype = 0;
-				previous->SetNext(u);
-				u->u.rail.track = v->u.rail.track;
-				u->u.rail.railtype = v->u.rail.railtype;
-				u->u.rail.first_engine = v->engine_type;
+			case VEH_TRAIN: {
+				Train *front = (Train *)v;
+				Train *t = new Train();
+				t->subtype = 0;
+				previous->SetNext(t);
+				t->u.rail.track = front->u.rail.track;
+				t->u.rail.railtype = front->u.rail.railtype;
+				t->u.rail.first_engine = front->engine_type;
 
-				u->spritenum = e_artic->u.rail.image_index;
+				t->spritenum = e_artic->u.rail.image_index;
 				if (e_artic->CanCarryCargo()) {
-					u->cargo_type = e_artic->GetDefaultCargoType();
-					u->cargo_cap = e_artic->u.rail.capacity;  // Callback 36 is called when the consist is finished
+					t->cargo_type = e_artic->GetDefaultCargoType();
+					t->cargo_cap = e_artic->u.rail.capacity;  // Callback 36 is called when the consist is finished
 				} else {
-					u->cargo_type = v->cargo_type; // Needed for livery selection
-					u->cargo_cap = 0;
+					t->cargo_type = front->cargo_type; // Needed for livery selection
+					t->cargo_cap = 0;
 				}
 
-				SetArticulatedPart(u);
-				break;
+				SetArticulatedPart(t);
+				u = t;
+			} break;
 
 			case VEH_ROAD: {
 				RoadVehicle *front = (RoadVehicle *)v;
--- a/src/autoreplace_cmd.cpp
+++ b/src/autoreplace_cmd.cpp
@@ -92,18 +92,18 @@
 	assert(!part_of_chain || new_head->IsPrimaryVehicle());
 	/* Loop through source parts */
 	for (Vehicle *src = old_veh; src != NULL; src = src->Next()) {
-		if (!part_of_chain && src->type == VEH_TRAIN && src != old_veh && src != old_veh->u.rail.other_multiheaded_part && !IsArticulatedPart(src)) {
+		if (!part_of_chain && src->type == VEH_TRAIN && src != old_veh && src != ((Train *)old_veh)->u.rail.other_multiheaded_part && !IsArticulatedPart(src)) {
 			/* Skip vehicles, which do not belong to old_veh */
-			src = GetLastEnginePart(src);
+			src = GetLastEnginePart((Train *)src);
 			continue;
 		}
 		if (src->cargo_type >= NUM_CARGO || src->cargo.Count() == 0) continue;
 
 		/* Find free space in the new chain */
 		for (Vehicle *dest = new_head; dest != NULL && src->cargo.Count() > 0; dest = dest->Next()) {
-			if (!part_of_chain && dest->type == VEH_TRAIN && dest != new_head && dest != new_head->u.rail.other_multiheaded_part && !IsArticulatedPart(dest)) {
+			if (!part_of_chain && dest->type == VEH_TRAIN && dest != new_head && dest != ((Train *)new_head)->u.rail.other_multiheaded_part && !IsArticulatedPart(dest)) {
 				/* Skip vehicles, which do not belong to new_head */
-				dest = GetLastEnginePart(dest);
+				dest = GetLastEnginePart((Train *)dest);
 				continue;
 			}
 			if (dest->cargo_type != src->cargo_type) continue;
@@ -116,7 +116,7 @@
 	}
 
 	/* Update train weight etc., the old vehicle will be sold anyway */
-	if (part_of_chain && new_head->type == VEH_TRAIN) TrainConsistChanged(new_head, true);
+	if (part_of_chain && new_head->type == VEH_TRAIN) TrainConsistChanged((Train *)new_head, true);
 }
 
 /**
@@ -269,7 +269,7 @@
 	}
 
 	/* Try to reverse the vehicle, but do not care if it fails as the new type might not be reversible */
-	if (new_veh->type == VEH_TRAIN && HasBit(old_veh->u.rail.flags, VRF_REVERSE_DIRECTION)) {
+	if (new_veh->type == VEH_TRAIN && HasBit(((Train *)old_veh)->u.rail.flags, VRF_REVERSE_DIRECTION)) {
 		DoCommand(0, new_veh->index, true, DC_EXEC, CMD_REVERSE_TRAIN_DIRECTION);
 	}
 
@@ -406,33 +406,33 @@
 		uint16 old_total_length = (old_head->u.rail.cached_total_length + TILE_SIZE - 1) / TILE_SIZE * TILE_SIZE;
 
 		int num_units = 0; ///< Number of units in the chain
-		for (Vehicle *w = old_head; w != NULL; w = GetNextUnit(w)) num_units++;
+		for (Train *w = (Train *)old_head; w != NULL; w = GetNextUnit(w)) num_units++;
 
-		Vehicle **old_vehs = CallocT<Vehicle *>(num_units); ///< Will store vehicles of the old chain in their order
-		Vehicle **new_vehs = CallocT<Vehicle *>(num_units); ///< New vehicles corresponding to old_vehs or NULL if no replacement
-		Money *new_costs = MallocT<Money>(num_units);       ///< Costs for buying and refitting the new vehicles
+		Train **old_vehs = CallocT<Train *>(num_units); ///< Will store vehicles of the old chain in their order
+		Train **new_vehs = CallocT<Train *>(num_units); ///< New vehicles corresponding to old_vehs or NULL if no replacement
+		Money *new_costs = MallocT<Money>(num_units);   ///< Costs for buying and refitting the new vehicles
 
 		/* Collect vehicles and build replacements
 		 * Note: The replacement vehicles can only successfully build as long as the old vehicles are still in their chain */
 		int i;
-		Vehicle *w;
-		for (w = old_head, i = 0; w != NULL; w = GetNextUnit(w), i++) {
+		Train *w;
+		for (w = (Train *)old_head, i = 0; w != NULL; w = GetNextUnit(w), i++) {
 			assert(i < num_units);
 			old_vehs[i] = w;
 
-			CommandCost ret = BuildReplacementVehicle(old_vehs[i], &new_vehs[i], true);
+			CommandCost ret = BuildReplacementVehicle(old_vehs[i], (Vehicle**)&new_vehs[i], true);
 			cost.AddCost(ret);
 			if (cost.Failed()) break;
 
 			new_costs[i] = ret.GetCost();
 			if (new_vehs[i] != NULL) *nothing_to_do = false;
 		}
-		Vehicle *new_head = (new_vehs[0] != NULL ? new_vehs[0] : old_vehs[0]);
+		Train *new_head = (new_vehs[0] != NULL ? new_vehs[0] : old_vehs[0]);
 
 		/* Note: When autoreplace has already failed here, old_vehs[] is not completely initialized. But it is also not needed. */
 		if (cost.Succeeded()) {
 			/* Separate the head, so we can start constructing the new chain */
-			Vehicle *second = GetNextUnit(old_head);
+			Train *second = GetNextUnit((Train *)old_head);
 			if (second != NULL) cost.AddCost(MoveVehicle(second, NULL, DC_EXEC | DC_AUTOREPLACE, true));
 
 			assert(GetNextUnit(new_head) == NULL);
@@ -440,10 +440,10 @@
 			/* Append engines to the new chain
 			 * We do this from back to front, so that the head of the temporary vehicle chain does not change all the time.
 			 * OTOH the vehicle attach callback is more expensive this way :s */
-			Vehicle *last_engine = NULL; ///< Shall store the last engine unit after this step
+			Train *last_engine = NULL; ///< Shall store the last engine unit after this step
 			if (cost.Succeeded()) {
 				for (int i = num_units - 1; i > 0; i--) {
-					Vehicle *append = (new_vehs[i] != NULL ? new_vehs[i] : old_vehs[i]);
+					Train *append = (new_vehs[i] != NULL ? new_vehs[i] : old_vehs[i]);
 
 					if (RailVehInfo(append->engine_type)->railveh_type == RAILVEH_WAGON) continue;
 
@@ -538,10 +538,10 @@
 			 * Note: The vehicle attach callback is disabled here :) */
 			if ((flags & DC_EXEC) == 0) {
 				/* Separate the head, so we can reattach the old vehicles */
-				Vehicle *second = GetNextUnit(old_head);
+				Train *second = GetNextUnit((Train *)old_head);
 				if (second != NULL) MoveVehicle(second, NULL, DC_EXEC | DC_AUTOREPLACE, true);
 
-				assert(GetNextUnit(old_head) == NULL);
+				assert(GetNextUnit((Train *)old_head) == NULL);
 
 				for (int i = num_units - 1; i > 0; i--) {
 					CommandCost ret = MoveVehicle(old_vehs[i], old_head, DC_EXEC | DC_AUTOREPLACE, false);
@@ -632,7 +632,7 @@
 	bool any_replacements = false;
 	while (w != NULL && !any_replacements) {
 		any_replacements = (GetNewEngineType(w, c) != INVALID_ENGINE);
-		w = (!free_wagon && w->type == VEH_TRAIN ? GetNextUnit(w) : NULL);
+		w = (!free_wagon && w->type == VEH_TRAIN ? GetNextUnit((Train *)w) : NULL);
 	}
 
 	if (any_replacements) {
--- a/src/elrail.cpp
+++ b/src/elrail.cpp
@@ -555,12 +555,15 @@
 	 *  normal rail too */
 	if (disable) {
 		FOR_ALL_VEHICLES(v) {
-			if (v->type == VEH_TRAIN && v->u.rail.railtype == RAILTYPE_ELECTRIC) {
+			if (v->type != VEH_TRAIN) continue;
+
+			Train *t = (Train *)v;
+			if (t->u.rail.railtype == RAILTYPE_ELECTRIC) {
 				/* this railroad vehicle is now compatible only with elrail,
 				 *  so add there also normal rail compatibility */
-				v->u.rail.compatible_railtypes |= RAILTYPES_RAIL;
-				v->u.rail.railtype = RAILTYPE_RAIL;
-				SetBit(v->u.rail.flags, VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL);
+				t->u.rail.compatible_railtypes |= RAILTYPES_RAIL;
+				t->u.rail.railtype = RAILTYPE_RAIL;
+				SetBit(t->u.rail.flags, VRF_EL_ENGINE_ALLOWED_NORMAL_RAIL);
 			}
 		}
 	}
@@ -569,8 +572,9 @@
 	FOR_ALL_VEHICLES(v) {
 		/* power and acceleration is cached only for front engines */
 		if (v->type == VEH_TRAIN && IsFrontEngine(v)) {
-			TrainPowerChanged(v);
-			UpdateTrainAcceleration(v);
+			Train *t = (Train *)v;
+			TrainPowerChanged(t);
+			UpdateTrainAcceleration(t);
 		}
 	}
 
--- a/src/newgrf_engine.cpp
+++ b/src/newgrf_engine.cpp
@@ -668,7 +668,8 @@
 			uint16 modflags = 0;
 
 			if (v->type == VEH_TRAIN) {
-				const Vehicle *u = IsTrainWagon(v) && HasBit(v->vehicle_flags, VRF_POWEREDWAGON) ? v->First() : v;
+				const Train *t = (const Train *)v;
+				const Train *u = IsTrainWagon(v) && HasBit(v->vehicle_flags, VRF_POWEREDWAGON) ? t->First() : t;
 				RailType railtype = GetRailType(v->tile);
 				bool powered = IsTrainEngine(v) || (IsTrainWagon(v) && HasBit(v->vehicle_flags, VRF_POWEREDWAGON));
 				bool has_power = powered && HasPowerOnRail(u->u.rail.railtype, railtype);
@@ -676,7 +677,7 @@
 
 				if (has_power) SetBit(modflags, 5);
 				if (is_electric && !has_power) SetBit(modflags, 6);
-				if (HasBit(v->u.rail.flags, VRF_TOGGLE_REVERSE)) SetBit(modflags, 8);
+				if (HasBit(t->u.rail.flags, VRF_TOGGLE_REVERSE)) SetBit(modflags, 8);
 			}
 			if (HasBit(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE)) SetBit(modflags, 10);
 
@@ -735,7 +736,7 @@
 		case 0x47: return GB(Engine::Get(v->engine_type)->internal_id, 8, 8);
 		case 0x48:
 			if (v->type != VEH_TRAIN || v->spritenum != 0xFD) return v->spritenum;
-			return HasBit(v->u.rail.flags, VRF_REVERSE_DIRECTION) ? 0xFE : 0xFD;
+			return HasBit(((Train *)v)->u.rail.flags, VRF_REVERSE_DIRECTION) ? 0xFE : 0xFD;
 
 		case 0x49: return v->day_counter;
 		case 0x4A: return v->breakdowns_since_last_service;
@@ -766,20 +767,21 @@
 
 	/* Vehicle specific properties */
 	switch (v->type) {
-		case VEH_TRAIN:
+		case VEH_TRAIN: {
+			Train *t = (Train *)v;
 			switch (variable - 0x80) {
-				case 0x62: return v->u.rail.track;
-				case 0x66: return v->u.rail.railtype;
-				case 0x73: return v->u.rail.cached_veh_length;
-				case 0x74: return v->u.rail.cached_power;
-				case 0x75: return GB(v->u.rail.cached_power,  8, 24);
-				case 0x76: return GB(v->u.rail.cached_power, 16, 16);
-				case 0x77: return GB(v->u.rail.cached_power, 24,  8);
-				case 0x7C: return v->First()->index;
-				case 0x7D: return GB(v->First()->index, 8, 8);
+				case 0x62: return t->u.rail.track;
+				case 0x66: return t->u.rail.railtype;
+				case 0x73: return t->u.rail.cached_veh_length;
+				case 0x74: return t->u.rail.cached_power;
+				case 0x75: return GB(t->u.rail.cached_power,  8, 24);
+				case 0x76: return GB(t->u.rail.cached_power, 16, 16);
+				case 0x77: return GB(t->u.rail.cached_power, 24,  8);
+				case 0x7C: return t->First()->index;
+				case 0x7D: return GB(t->First()->index, 8, 8);
 				case 0x7F: return 0; // Used for vehicle reversing hack in TTDP
 			}
-			break;
+		} break;
 
 		case VEH_ROAD: {
 			RoadVehicle *rv = (RoadVehicle *)v;
--- a/src/npf.cpp
+++ b/src/npf.cpp
@@ -16,6 +16,7 @@
 #include "pbs.h"
 #include "settings_type.h"
 #include "pathfind.h"
+#include "train.h"
 
 static AyStar _npf_aystar;
 
@@ -424,7 +425,7 @@
 /** Find any safe and free tile. */
 static int32 NPFFindSafeTile(AyStar *as, OpenListNode *current)
 {
-	const Vehicle *v = ((NPFFindStationOrTileData*)as->user_target)->v;
+	const Train *v = (Train *)((NPFFindStationOrTileData*)as->user_target)->v;
 
 	return
 		IsSafeWaitingPosition(v, current->path.node.tile, current->path.node.direction, true, _settings_game.pf.forbid_90_deg) &&
@@ -458,7 +459,7 @@
  * the second signal is returnd. If no suitable signal is present, the
  * last node of the path is returned.
  */
-static const PathNode *FindSafePosition(PathNode *path, const Vehicle *v)
+static const PathNode *FindSafePosition(PathNode *path, const Train *v)
 {
 	/* If there is no signal, reserve the whole path. */
 	PathNode *sig = path;
@@ -505,7 +506,7 @@
 
 	if (as->user_target != NULL && ((NPFFindStationOrTileData*)as->user_target)->reserve_path && as->user_data[NPF_TYPE] == TRANSPORT_RAIL) {
 		/* Path reservation is requested. */
-		const Vehicle  *v = ((NPFFindStationOrTileData*)as->user_target)->v;
+		const Train *v = (Train *)((NPFFindStationOrTileData*)as->user_target)->v;
 
 		const PathNode *target = FindSafePosition(&current->path, v);
 		ftd->node = target->node;
@@ -1053,7 +1054,7 @@
 	return best_result;
 }
 
-NPFFoundTargetData NPFRouteToSafeTile(const Vehicle *v, TileIndex tile, Trackdir trackdir, bool override_railtype)
+NPFFoundTargetData NPFRouteToSafeTile(const Train *v, TileIndex tile, Trackdir trackdir, bool override_railtype)
 {
 	assert(v->type == VEH_TRAIN);
 
--- a/src/npf.h
+++ b/src/npf.h
@@ -115,7 +115,7 @@
 /**
  * Search for any safe tile using a breadth first search and try to reserve a path.
  */
-NPFFoundTargetData NPFRouteToSafeTile(const Vehicle *v, TileIndex tile, Trackdir trackdir,bool override_railtype);
+NPFFoundTargetData NPFRouteToSafeTile(const struct Train *v, TileIndex tile, Trackdir trackdir, bool override_railtype);
 
 
 void NPFFillWithOrderData(NPFFindStationOrTileData *fstd, Vehicle *v, bool reserve_path = false);
--- a/src/openttd.cpp
+++ b/src/openttd.cpp
@@ -31,6 +31,7 @@
 #include "fios.h"
 #include "aircraft.h"
 #include "roadveh.h"
+#include "train.h"
 #include "console_func.h"
 #include "screenshot.h"
 #include "network/network.h"
@@ -1132,7 +1133,7 @@
 						length = 0;
 						for (Vehicle *u = v; u != NULL; u = u->Next()) wagons[length++] = u->u.rail;
 
-						TrainConsistChanged(v, true);
+						TrainConsistChanged((Train *)v, true);
 
 						length = 0;
 						for (Vehicle *u = v; u != NULL; u = u->Next()) {
--- a/src/pbs.cpp
+++ b/src/pbs.cpp
@@ -222,7 +222,7 @@
  */
 struct FindTrainOnTrackInfo {
 	PBSTileInfo res; ///< Information about the track.
-	Vehicle *best;   ///< The currently "best" vehicle we have found.
+	Train *best;     ///< The currently "best" vehicle we have found.
 
 	/** Init the best location to NULL always! */
 	FindTrainOnTrackInfo() : best(NULL) {}
@@ -233,12 +233,15 @@
 {
 	FindTrainOnTrackInfo *info = (FindTrainOnTrackInfo *)data;
 
-	if (v->type == VEH_TRAIN && !(v->vehstatus & VS_CRASHED) && HasBit((TrackBits)v->u.rail.track, TrackdirToTrack(info->res.trackdir))) {
-		v = v->First();
+	if (v->type != VEH_TRAIN || (v->vehstatus & VS_CRASHED)) return NULL;
+
+	Train *t = (Train *)v;
+	if (HasBit((TrackBits)t->u.rail.track, TrackdirToTrack(info->res.trackdir))) {
+		t = t->First();
 
 		/* ALWAYS return the lowest ID (anti-desync!) */
-		if (info->best == NULL || v->index < info->best->index) info->best = v;
-		return v;
+		if (info->best == NULL || t->index < info->best->index) info->best = t;
+		return t;
 	}
 
 	return NULL;
@@ -251,7 +254,7 @@
  * @param train_on_res Is set to a train we might encounter
  * @returns The last tile of the reservation or the current train tile if no reservation present.
  */
-PBSTileInfo FollowTrainReservation(const Vehicle *v, bool *train_on_res)
+PBSTileInfo FollowTrainReservation(const Train *v, bool *train_on_res)
 {
 	assert(v->type == VEH_TRAIN);
 
@@ -274,7 +277,7 @@
  * @param track A reserved track on the tile.
  * @return The vehicle holding the reservation or NULL if the path is stray.
  */
-Vehicle *GetTrainForReservation(TileIndex tile, Track track)
+Train *GetTrainForReservation(TileIndex tile, Track track)
 {
 	assert(HasReservedTracks(tile, TrackToTrackBits(track)));
 	Trackdir  trackdir = TrackToTrackdir(track);
@@ -320,7 +323,7 @@
  * @param forbid_90def Don't allow trains to make 90 degree turns
  * @return True if it is a safe position
  */
-bool IsSafeWaitingPosition(const Vehicle *v, TileIndex tile, Trackdir trackdir, bool include_line_end, bool forbid_90deg)
+bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bool include_line_end, bool forbid_90deg)
 {
 	if (IsRailDepotTile(tile)) return true;
 
@@ -360,7 +363,7 @@
  * @param forbid_90def Don't allow trains to make 90 degree turns
  * @return True if the position is free
  */
-bool IsWaitingPositionFree(const Vehicle *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg)
+bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg)
 {
 	Track     track = TrackdirToTrack(trackdir);
 	TrackBits reserved = GetReservedTrackbits(tile);
--- a/src/pbs.h
+++ b/src/pbs.h
@@ -27,11 +27,11 @@
 	PBSTileInfo(TileIndex _t, Trackdir _td, bool _okay) : tile(_t), trackdir(_td), okay(_okay) {}
 };
 
-PBSTileInfo FollowTrainReservation(const Vehicle *v, bool *train_on_res = NULL);
-bool IsSafeWaitingPosition(const Vehicle *v, TileIndex tile, Trackdir trackdir, bool include_line_end, bool forbid_90deg = false);
-bool IsWaitingPositionFree(const Vehicle *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg = false);
+PBSTileInfo FollowTrainReservation(const Train *v, bool *train_on_res = NULL);
+bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bool include_line_end, bool forbid_90deg = false);
+bool IsWaitingPositionFree(const Train *v, TileIndex tile, Trackdir trackdir, bool forbid_90deg = false);
 
-Vehicle *GetTrainForReservation(TileIndex tile, Track track);
+Train *GetTrainForReservation(TileIndex tile, Track track);
 
 /**
  * Check whether some of tracks is reserved on a tile.
--- a/src/rail_cmd.cpp
+++ b/src/rail_cmd.cpp
@@ -92,7 +92,8 @@
 
 	if (v->type != VEH_TRAIN) return NULL;
 
-	if ((v->u.rail.track != rail_bits) && !TracksOverlap(v->u.rail.track | rail_bits)) return NULL;
+	Train *t = (Train *)v;
+	if ((t->u.rail.track != rail_bits) && !TracksOverlap(t->u.rail.track | rail_bits)) return NULL;
 
 	_error_message = VehicleInTheWayErrMsg(v);
 	return v;
@@ -456,7 +457,7 @@
 	 * so do not call GetTileOwner(tile) in any case here */
 	Owner owner = INVALID_OWNER;
 
-	Vehicle *v = NULL;
+	Train *v = NULL;
 
 	switch (GetTileType(tile)) {
 		case MP_ROAD: {
@@ -877,7 +878,7 @@
 	}
 
 	if (flags & DC_EXEC) {
-		Vehicle *v = NULL;
+		Train *v = NULL;
 		/* The new/changed signal could block our path. As this can lead to
 		 * stale reservations, we clear the path reservation here and try
 		 * to redo it later on. */
@@ -1184,7 +1185,7 @@
 
 	/* Do it? */
 	if (flags & DC_EXEC) {
-		Vehicle *v = NULL;
+		Train *v = NULL;
 		if (HasReservedTracks(tile, TrackToTrackBits(track))) {
 			v = GetTrainForReservation(tile, track);
 		}
@@ -1234,7 +1235,7 @@
 
 	if (v->type == VEH_TRAIN && !IsArticulatedPart(v)) {
 		const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
-		if (GetVehicleProperty(v, 0x0B, rvi->power) != 0) TrainPowerChanged(v->First());
+		if (GetVehicleProperty(v, 0x0B, rvi->power) != 0) TrainPowerChanged((Train *)v->First());
 	}
 
 	return NULL;
@@ -1296,7 +1297,7 @@
 			/* Trying to convert other's rail */
 			if (!CheckTileOwnership(tile)) continue;
 
-			SmallVector<Vehicle*, 2> vehicles_affected;
+			SmallVector<Train *, 2> vehicles_affected;
 
 			/* Vehicle on the tile when not converting Rail <-> ElRail
 			 * Tunnels and bridges have special check later */
@@ -1306,7 +1307,7 @@
 					TrackBits reserved = GetReservedTrackbits(tile);
 					Track     track;
 					while ((track = RemoveFirstTrack(&reserved)) != INVALID_TRACK) {
-						Vehicle *v = GetTrainForReservation(tile, track);
+						Train *v = GetTrainForReservation(tile, track);
 						if (v != NULL && !HasPowerOnRail(v->u.rail.railtype, totype)) {
 							/* No power on new rail type, reroute. */
 							FreeTrainTrackReservation(v);
@@ -1372,7 +1373,7 @@
 					if (flags & DC_EXEC) {
 						Track track = DiagDirToDiagTrack(GetTunnelBridgeDirection(tile));
 						if (GetTunnelBridgeReservation(tile)) {
-							Vehicle *v = GetTrainForReservation(tile, track);
+							Train *v = GetTrainForReservation(tile, track);
 							if (v != NULL && !HasPowerOnRail(v->u.rail.railtype, totype)) {
 								/* No power on new rail type, reroute. */
 								FreeTrainTrackReservation(v);
@@ -1432,7 +1433,7 @@
 		/* read variables before the depot is removed */
 		DiagDirection dir = GetRailDepotDirection(tile);
 		Owner owner = GetTileOwner(tile);
-		Vehicle *v = NULL;
+		Train *v = NULL;
 
 		if (GetDepotWaypointReservation(tile)) {
 			v = GetTrainForReservation(tile, DiagDirToDiagTrack(dir));
@@ -2450,7 +2451,7 @@
 
 /** Tile callback routine when vehicle enters tile
  * @see vehicle_enter_tile_proc */
-static VehicleEnterTileStatus VehicleEnter_Track(Vehicle *v, TileIndex tile, int x, int y)
+static VehicleEnterTileStatus VehicleEnter_Track(Vehicle *u, TileIndex tile, int x, int y)
 {
 	byte fract_coord;
 	byte fract_coord_leave;
@@ -2458,7 +2459,9 @@
 	int length;
 
 	/* this routine applies only to trains in depot tiles */
-	if (v->type != VEH_TRAIN || !IsRailDepotTile(tile)) return VETSB_CONTINUE;
+	if (u->type != VEH_TRAIN || !IsRailDepotTile(tile)) return VETSB_CONTINUE;
+
+	Train *v = (Train *)u;
 
 	/* depot direction */
 	dir = GetRailDepotDirection(tile);
--- a/src/saveload/afterload.cpp
+++ b/src/saveload/afterload.cpp
@@ -912,7 +912,7 @@
 				continue;
 			}
 			if (v->type == VEH_TRAIN) {
-				v->u.rail.track = TRACK_BIT_WORMHOLE;
+				((Train *)v)->u.rail.track = TRACK_BIT_WORMHOLE;
 			} else {
 				((RoadVehicle *)v)->state = RVSB_WORMHOLE;
 			}
@@ -928,7 +928,7 @@
 			if (v->type == VEH_TRAIN) {
 				RailType rt = RailVehInfo(v->engine_type)->railtype;
 
-				v->u.rail.railtype = rt;
+				((Train *)v)->u.rail.railtype = rt;
 				if (rt == RAILTYPE_ELECTRIC) min_rail = RAILTYPE_RAIL;
 			}
 		}
@@ -964,7 +964,7 @@
 		}
 
 		FOR_ALL_VEHICLES(v) {
-			if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) TrainConsistChanged(v, true);
+			if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) TrainConsistChanged((Train *)v, true);
 		}
 
 	}
@@ -1700,9 +1700,10 @@
 
 	/* Reserve all tracks trains are currently on. */
 	if (CheckSavegameVersion(101)) {
-		Vehicle *v;
-		FOR_ALL_VEHICLES(v) {
-			if (v->type == VEH_TRAIN) {
+		Vehicle *u;
+		FOR_ALL_VEHICLES(u) {
+			if (u->type == VEH_TRAIN) {
+				Train *v = (Train *)u;
 				if ((v->u.rail.track & TRACK_BIT_WORMHOLE) == TRACK_BIT_WORMHOLE) {
 					TryReserveRailTrack(v->tile, DiagDirToDiagTrack(GetTunnelBridgeDirection(v->tile)));
 				} else if ((v->u.rail.track & TRACK_BIT_MASK) != TRACK_BIT_NONE) {
--- a/src/saveload/oldloader_sl.cpp
+++ b/src/saveload/oldloader_sl.cpp
@@ -1315,7 +1315,7 @@
 					};
 					if (v->spritenum / 2 >= lengthof(spriteset_rail)) return false;
 					v->spritenum = spriteset_rail[v->spritenum / 2]; // adjust railway sprite set offset
-					v->u.rail.railtype = type == 0x25 ? 1 : 0; // monorail / rail
+					((Train *)v)->u.rail.railtype = type == 0x25 ? 1 : 0; // monorail / rail
 					break;
 				}
 
--- a/src/saveload/vehicle_sl.cpp
+++ b/src/saveload/vehicle_sl.cpp
@@ -24,7 +24,7 @@
 
 	FOR_ALL_VEHICLES(v) {
 		if (v->type == VEH_TRAIN) {
-			v->u.rail.other_multiheaded_part = NULL;
+			((Train *)v)->u.rail.other_multiheaded_part = NULL;
 		}
 	}
 
@@ -45,7 +45,7 @@
 
 			bool sequential_matching = IsFrontEngine(v);
 
-			for (Vehicle *u = v; u != NULL; u = GetNextVehicle(u)) {
+			for (Train *u = (Train *)v; u != NULL; u = (Train *)GetNextVehicle(u)) {
 				if (u->u.rail.other_multiheaded_part != NULL) continue; // we already linked this one
 
 				if (IsMultiheaded(u)) {
@@ -57,7 +57,7 @@
 
 					/* Find a matching back part */
 					EngineID eid = u->engine_type;
-					Vehicle *w;
+					Train *w;
 					if (sequential_matching) {
 						for (w = GetNextVehicle(u); w != NULL; w = GetNextVehicle(w)) {
 							if (w->engine_type != eid || w->u.rail.other_multiheaded_part != NULL || !IsMultiheaded(w)) continue;
@@ -318,8 +318,8 @@
 		assert(v->first != NULL);
 
 		if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) {
-			if (IsFrontEngine(v)) v->u.rail.last_speed = v->cur_speed; // update displayed train speed
-			TrainConsistChanged(v, false);
+			if (IsFrontEngine(v)) ((Train *)v)->u.rail.last_speed = v->cur_speed; // update displayed train speed
+			TrainConsistChanged((Train *)v, false);
 		} else if (v->type == VEH_ROAD && IsRoadVehFront(v)) {
 			RoadVehUpdateCache((RoadVehicle *)v);
 		}
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -697,7 +697,7 @@
 	Vehicle *v;
 	FOR_ALL_VEHICLES(v) {
 		/* Update the consist of all trains so the maximum speed is set correctly. */
-		if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) TrainConsistChanged(v, true);
+		if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) TrainConsistChanged((Train *)v, true);
 	}
 	return true;
 }
@@ -747,7 +747,7 @@
 	Vehicle *v;
 
 	FOR_ALL_VEHICLES(v) {
-		if (v->type == VEH_TRAIN && IsFrontEngine(v)) UpdateTrainAcceleration(v);
+		if (v->type == VEH_TRAIN && IsFrontEngine(v)) UpdateTrainAcceleration((Train *)v);
 	}
 
 	return true;
--- a/src/signal.cpp
+++ b/src/signal.cpp
@@ -7,8 +7,8 @@
 #include "station_map.h"
 #include "tunnelbridge_map.h"
 #include "vehicle_func.h"
-#include "vehicle_base.h"
 #include "functions.h"
+#include "train.h"
 
 
 /** these are the maximums used for updating signal blocks */
@@ -185,7 +185,7 @@
 /** Check whether there is a train on rail, not in a depot */
 static Vehicle *TrainOnTileEnum(Vehicle *v, void *)
 {
-	if (v->type != VEH_TRAIN || v->u.rail.track == TRACK_BIT_DEPOT) return NULL;
+	if (v->type != VEH_TRAIN || ((Train *)v)->u.rail.track == TRACK_BIT_DEPOT) return NULL;
 
 	return v;
 }
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -1015,7 +1015,7 @@
 
 		numtracks_orig = numtracks;
 
-		SmallVector<Vehicle*, 4> affected_vehicles;
+		SmallVector<Train*, 4> affected_vehicles;
 		do {
 			TileIndex tile = tile_org;
 			int w = plat_len;
@@ -1023,7 +1023,7 @@
 				byte layout = *layout_ptr++;
 				if (IsRailwayStationTile(tile) && GetRailwayStationReservation(tile)) {
 					/* Check for trains having a reservation for this tile. */
-					Vehicle *v = GetTrainForReservation(tile, AxisToTrack(GetRailStationAxis(tile)));
+					Train *v = GetTrainForReservation(tile, AxisToTrack(GetRailStationAxis(tile)));
 					if (v != NULL) {
 						FreeTrainTrackReservation(v);
 						*affected_vehicles.Append() = v;
@@ -1063,7 +1063,7 @@
 
 		for (uint i = 0; i < affected_vehicles.Length(); ++i) {
 			/* Restore reservations of trains. */
-			Vehicle *v = affected_vehicles[i];
+			Train *v = affected_vehicles[i];
 			if (IsRailwayStationTile(v->tile)) SetRailwayStationPlatformReservation(v->tile, TrackdirToExitdir(v->GetVehicleTrackdir()), true);
 			TryPathReserve(v, true, true);
 			for (; v->Next() != NULL; v = v->Next()) ;
@@ -1196,7 +1196,7 @@
 			uint specindex = GetCustomStationSpecIndex(tile2);
 			Track track = GetRailStationTrack(tile2);
 			Owner owner = GetTileOwner(tile2);
-			Vehicle *v = NULL;
+			Train *v = NULL;
 
 			if (GetRailwayStationReservation(tile2)) {
 				v = GetTrainForReservation(tile2, track);
@@ -1280,7 +1280,7 @@
 					/* read variables before the station tile is removed */
 					Track track = GetRailStationTrack(tile);
 					Owner owner = GetTileOwner(tile); // _current_company can be OWNER_WATER
-					Vehicle *v = NULL;
+					Train *v = NULL;
 					if (GetRailwayStationReservation(tile)) {
 						v = GetTrainForReservation(tile, track);
 						if (v != NULL) FreeTrainTrackReservation(v);
@@ -2621,7 +2621,7 @@
 
 		int station_ahead;
 		int station_length;
-		int stop = GetTrainStopLocation(station_id, tile, v, &station_ahead, &station_length);
+		int stop = GetTrainStopLocation(station_id, tile, (Train *)v, &station_ahead, &station_length);
 
 		/* Stop whenever that amount of station ahead + the distance from the
 		 * begin of the platform to the stop location is longer than the length
--- a/src/train.h
+++ b/src/train.h
@@ -9,6 +9,7 @@
 #include "core/bitmath_func.hpp"
 #include "vehicle_base.h"
 
+struct Train;
 
 /** enum to handle train subtypes
  * Do not access it directly unless you have to. Use the access functions below
@@ -202,28 +203,6 @@
 	return (v->Next() != NULL && IsArticulatedPart(v->Next()));
 }
 
-/**
- * Get the next part of a multi-part engine.
- * Will only work on a multi-part engine (EngineHasArticPart(v) == true),
- * Result is undefined for normal engine.
- */
-static inline Vehicle *GetNextArticPart(const Vehicle *v)
-{
-	assert(EngineHasArticPart(v));
-	return v->Next();
-}
-
-/** Get the last part of a multi-part engine.
- * @param v Vehicle.
- * @return Last part of the engine.
- */
-static inline Vehicle *GetLastEnginePart(Vehicle *v)
-{
-	assert(v->type == VEH_TRAIN);
-	while (EngineHasArticPart(v)) v = GetNextArticPart(v);
-	return v;
-}
-
 /** Tell if we are dealing with the rear end of a multiheaded engine.
  * @param v Vehicle.
  * @return True if the engine is the rear part of a dualheaded engine.
@@ -234,73 +213,24 @@
 	return (IsMultiheaded(v) && !IsTrainEngine(v));
 }
 
-/** Get the next real (non-articulated part) vehicle in the consist.
- * @param v Vehicle.
- * @return Next vehicle in the consist.
- */
-static inline Vehicle *GetNextVehicle(const Vehicle *v)
-{
-	assert(v->type == VEH_TRAIN);
-	while (EngineHasArticPart(v)) v = GetNextArticPart(v);
-
-	/* v now contains the last artic part in the engine */
-	return v->Next();
-}
-
-/** Get the previous real (non-articulated part) vehicle in the consist.
- * @param w Vehicle.
- * @return Previous vehicle in the consist.
- */
-static inline Vehicle *GetPrevVehicle(const Vehicle *w)
-{
-	assert(w->type == VEH_TRAIN);
-
-	Vehicle *v = w->Previous();
-	while (v != NULL && IsArticulatedPart(v)) v = v->Previous();
-
-	return v;
-}
-
-/** Get the next real (non-articulated part and non rear part of dualheaded engine) vehicle in the consist.
- * @param v Vehicle.
- * @return Next vehicle in the consist.
- */
-static inline Vehicle *GetNextUnit(const Vehicle *v)
-{
-	assert(v->type == VEH_TRAIN);
-	Vehicle *w = GetNextVehicle(v);
-	if (w != NULL && IsRearDualheaded(w)) w = GetNextVehicle(w);
-
-	return w;
-}
-
-/** Get the previous real (non-articulated part and non rear part of dualheaded engine) vehicle in the consist.
- * @param v Vehicle.
- * @return Previous vehicle in the consist.
- */
-static inline Vehicle *GetPrevUnit(const Vehicle *v)
-{
-	assert(v->type == VEH_TRAIN);
-	Vehicle *w = GetPrevVehicle(v);
-	if (w != NULL && IsRearDualheaded(w)) w = GetPrevVehicle(w);
-
-	return w;
-}
-
 void CcBuildLoco(bool success, TileIndex tile, uint32 p1, uint32 p2);
 void CcBuildWagon(bool success, TileIndex tile, uint32 p1, uint32 p2);
 
 byte FreightWagonMult(CargoID cargo);
 
-int CheckTrainInDepot(const Vehicle *v, bool needs_to_be_stopped);
-int CheckTrainStoppedInDepot(const Vehicle *v);
-void UpdateTrainAcceleration(Vehicle *v);
+int CheckTrainInDepot(const Train *v, bool needs_to_be_stopped);
+int CheckTrainStoppedInDepot(const Train *v);
+void UpdateTrainAcceleration(Train *v);
 void CheckTrainsLengths();
 
-void FreeTrainTrackReservation(const Vehicle *v, TileIndex origin = INVALID_TILE, Trackdir orig_td = INVALID_TRACKDIR);
-bool TryPathReserve(Vehicle *v, bool mark_as_stuck = false, bool first_tile_okay = false);
+void FreeTrainTrackReservation(const Train *v, TileIndex origin = INVALID_TILE, Trackdir orig_td = INVALID_TRACKDIR);
+bool TryPathReserve(Train *v, bool mark_as_stuck = false, bool first_tile_okay = false);
 
-int GetTrainStopLocation(StationID station_id, TileIndex tile, const Vehicle *v, int *station_ahead, int *station_length);
+int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, int *station_ahead, int *station_length);
+
+void TrainConsistChanged(Train *v, bool same_length);
+void TrainPowerChanged(Train *v);
+Money GetTrainRunningCost(const Train *v);
 
 /**
  * This class 'wraps' Vehicle; you do not actually instantiate this class.
@@ -334,6 +264,87 @@
 	Trackdir GetVehicleTrackdir() const;
 	TileIndex GetOrderStationLocation(StationID station);
 	bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
+	Train *First() { return (Train *)this->Vehicle::First(); }
+	Train *First() const { return (Train *)this->Vehicle::First(); }
+	Train *Next() { return (Train *)this->Vehicle::Next(); }
+	Train *Next() const { return (Train *)this->Vehicle::Next(); }
+	Train *Previous() { return (Train *)this->Vehicle::Previous(); }
+	Train *Previous() const { return (Train *)this->Vehicle::Previous(); }
 };
 
+/**
+ * Get the next part of a multi-part engine.
+ * Will only work on a multi-part engine (EngineHasArticPart(v) == true),
+ * Result is undefined for normal engine.
+ */
+static inline Train *GetNextArticPart(const Train *v)
+{
+	assert(EngineHasArticPart(v));
+	return v->Next();
+}
+
+/** Get the last part of a multi-part engine.
+ * @param v Vehicle.
+ * @return Last part of the engine.
+ */
+static inline Train *GetLastEnginePart(Train *v)
+{
+	assert(v->type == VEH_TRAIN);
+	while (EngineHasArticPart(v)) v = GetNextArticPart(v);
+	return v;
+}
+
+/** Get the next real (non-articulated part) vehicle in the consist.
+ * @param v Vehicle.
+ * @return Next vehicle in the consist.
+ */
+static inline Train *GetNextVehicle(const Train *v)
+{
+	assert(v->type == VEH_TRAIN);
+	while (EngineHasArticPart(v)) v = GetNextArticPart(v);
+
+	/* v now contains the last artic part in the engine */
+	return v->Next();
+}
+
+/** Get the previous real (non-articulated part) vehicle in the consist.
+ * @param w Vehicle.
+ * @return Previous vehicle in the consist.
+ */
+static inline Train *GetPrevVehicle(const Train *w)
+{
+	assert(w->type == VEH_TRAIN);
+
+	Train *v = w->Previous();
+	while (v != NULL && IsArticulatedPart(v)) v = v->Previous();
+
+	return v;
+}
+
+/** Get the next real (non-articulated part and non rear part of dualheaded engine) vehicle in the consist.
+ * @param v Vehicle.
+ * @return Next vehicle in the consist.
+ */
+static inline Train *GetNextUnit(const Train *v)
+{
+	assert(v->type == VEH_TRAIN);
+	Train *w = GetNextVehicle(v);
+	if (w != NULL && IsRearDualheaded(w)) w = GetNextVehicle(w);
+
+	return w;
+}
+
+/** Get the previous real (non-articulated part and non rear part of dualheaded engine) vehicle in the consist.
+ * @param v Vehicle.
+ * @return Previous vehicle in the consist.
+ */
+static inline Train *GetPrevUnit(const Train *v)
+{
+	assert(v->type == VEH_TRAIN);
+	Train *w = GetPrevVehicle(v);
+	if (w != NULL && IsRearDualheaded(w)) w = GetPrevVehicle(w);
+
+	return w;
+}
+
 #endif /* TRAIN_H */
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -37,12 +37,12 @@
 #include "table/strings.h"
 #include "table/train_cmd.h"
 
-static Track ChooseTrainTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *got_reservation, bool mark_stuck);
-static bool TrainCheckIfLineEnds(Vehicle *v);
-static void TrainController(Vehicle *v, Vehicle *nomove);
-static TileIndex TrainApproachingCrossingTile(const Vehicle *v);
-static void CheckIfTrainNeedsService(Vehicle *v);
-static void CheckNextTrainTile(Vehicle *v);
+static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *got_reservation, bool mark_stuck);
+static bool TrainCheckIfLineEnds(Train *v);
+static void TrainController(Train *v, Vehicle *nomove);
+static TileIndex TrainApproachingCrossingTile(const Train *v);
+static void CheckIfTrainNeedsService(Train *v);
+static void CheckNextTrainTile(Train *v);
 
 static const byte _vehicle_initial_x_fract[4] = {10, 8, 4,  8};
 static const byte _vehicle_initial_y_fract[4] = { 8, 4, 8, 10};
@@ -85,12 +85,12 @@
  * Recalculates the cached total power of a train. Should be called when the consist is changed
  * @param v First vehicle of the consist.
  */
-void TrainPowerChanged(Vehicle *v)
+void TrainPowerChanged(Train *v)
 {
 	uint32 total_power = 0;
 	uint32 max_te = 0;
 
-	for (const Vehicle *u = v; u != NULL; u = u->Next()) {
+	for (const Train *u = v; u != NULL; u = u->Next()) {
 		RailType railtype = GetRailType(u->tile);
 
 		/* Power is not added for articulated parts */
@@ -134,11 +134,11 @@
  * the consist changes.
  * @param v First vehicle of the consist.
  */
-static void TrainCargoChanged(Vehicle *v)
+static void TrainCargoChanged(Train *v)
 {
 	uint32 weight = 0;
 
-	for (Vehicle *u = v; u != NULL; u = u->Next()) {
+	for (Train *u = v; u != NULL; u = u->Next()) {
 		uint32 vweight = GetCargo(u->cargo_type)->weight * u->cargo.Count() * FreightWagonMult(u->cargo_type) / 16;
 
 		/* Vehicle weight is not added for articulated parts. */
@@ -171,7 +171,7 @@
  * is for the first time this happened.
  * @param u first vehicle of chain
  */
-static void RailVehicleLengthChanged(const Vehicle *u)
+static void RailVehicleLengthChanged(const Train *u)
 {
 	/* show a warning once for each engine in whole game and once for each GRF after each game load */
 	const Engine *engine = Engine::Get(u->engine_type);
@@ -189,7 +189,7 @@
 
 	FOR_ALL_VEHICLES(v) {
 		if (v->type == VEH_TRAIN && v->First() == v && !(v->vehstatus & VS_CRASHED)) {
-			for (const Vehicle *u = v, *w = v->Next(); w != NULL; u = w, w = w->Next()) {
+			for (const Train *u = (Train *)v, *w = (Train *)v->Next(); w != NULL; u = w, w = w->Next()) {
 				if (u->u.rail.track != TRACK_BIT_DEPOT) {
 					if ((w->u.rail.track != TRACK_BIT_DEPOT &&
 							max(abs(u->x_pos - w->x_pos), abs(u->y_pos - w->y_pos)) != u->u.rail.cached_veh_length) ||
@@ -213,7 +213,7 @@
  * @param v First vehicle of the chain.
  * @param same_length should length of vehicles stay the same?
  */
-void TrainConsistChanged(Vehicle *v, bool same_length)
+void TrainConsistChanged(Train *v, bool same_length)
 {
 	uint16 max_speed = UINT16_MAX;
 
@@ -227,7 +227,7 @@
 
 	bool train_can_tilt = true;
 
-	for (Vehicle *u = v; u != NULL; u = u->Next()) {
+	for (Train *u = v; u != NULL; u = u->Next()) {
 		const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type);
 
 		/* Check the v->first cache. */
@@ -244,13 +244,13 @@
 		u->cache_valid = 0;
 	}
 
-	for (Vehicle *u = v; u != NULL; u = u->Next()) {
+	for (Train *u = v; u != NULL; u = u->Next()) {
 		/* Update user defined data (must be done before other properties) */
 		u->u.rail.user_def_data = GetVehicleProperty(u, 0x25, u->u.rail.user_def_data);
 		u->cache_valid = 0;
 	}
 
-	for (Vehicle *u = v; u != NULL; u = u->Next()) {
+	for (Train *u = v; u != NULL; u = u->Next()) {
 		const Engine *e_u = Engine::Get(u->engine_type);
 		const RailVehicleInfo *rvi_u = &e_u->u.rail;
 
@@ -364,7 +364,7 @@
  * @param station_length 'return' the station length in 1/16th tiles
  * @return the location, calculated from the begin of the station to stop at.
  */
-int GetTrainStopLocation(StationID station_id, TileIndex tile, const Vehicle *v, int *station_ahead, int *station_length)
+int GetTrainStopLocation(StationID station_id, TileIndex tile, const Train *v, int *station_ahead, int *station_length)
 {
 	const Station *st = Station::Get(station_id);
 	*station_ahead  = st->GetPlatformLength(tile, DirToDiagDir(v->direction)) * TILE_SIZE;
@@ -404,7 +404,7 @@
 }
 
 /** new acceleration*/
-static int GetTrainAcceleration(Vehicle *v, bool mode)
+static int GetTrainAcceleration(Train *v, bool mode)
 {
 	static const int absolute_max_speed = UINT16_MAX;
 	int max_speed = absolute_max_speed;
@@ -496,7 +496,7 @@
 	int num = 0; // number of vehicles, change this into the number of axles later
 	int incl = 0;
 	int drag_coeff = 20; //[1e-4]
-	for (const Vehicle *u = v; u != NULL; u = u->Next()) {
+	for (const Train *u = v; u != NULL; u = u->Next()) {
 		num++;
 		drag_coeff += 3;
 
@@ -556,7 +556,7 @@
 	}
 }
 
-void UpdateTrainAcceleration(Vehicle *v)
+void UpdateTrainAcceleration(Train *v)
 {
 	assert(IsFrontEngine(v));
 
@@ -660,7 +660,7 @@
 			}
 		}
 
-		Vehicle *v = new Train();
+		Train *v = new Train();
 		v->spritenum = rvi->image_index;
 
 		v->engine_type = engine;
@@ -725,14 +725,14 @@
 }
 
 /** Move all free vehicles in the depot to the train */
-static void NormalizeTrainVehInDepot(const Vehicle *u)
+static void NormalizeTrainVehInDepot(const Train *u)
 {
 	const Vehicle *v;
 
 	FOR_ALL_VEHICLES(v) {
 		if (v->type == VEH_TRAIN && IsFreeWagon(v) &&
 				v->tile == u->tile &&
-				v->u.rail.track == TRACK_BIT_DEPOT) {
+				((Train *)v)->u.rail.track == TRACK_BIT_DEPOT) {
 			if (CmdFailed(DoCommand(0, v->index | (u->index << 16), 1, DC_EXEC,
 					CMD_MOVE_RAIL_VEHICLE)))
 				break;
@@ -740,9 +740,9 @@
 	}
 }
 
-static void AddRearEngineToMultiheadedTrain(Vehicle *v)
+static void AddRearEngineToMultiheadedTrain(Train *v)
 {
-	Vehicle *u = new Train();
+	Train *u = new Train();
 	v->value >>= 1;
 	u->value = v->value;
 	u->direction = v->direction;
@@ -823,7 +823,7 @@
 		int x = TileX(tile) * TILE_SIZE + _vehicle_initial_x_fract[dir];
 		int y = TileY(tile) * TILE_SIZE + _vehicle_initial_y_fract[dir];
 
-		Vehicle *v = new Train();
+		Train *v = new Train();
 		v->unitnumber = unit_num;
 		v->direction = DiagDirToDir(dir);
 		v->tile = tile;
@@ -901,7 +901,7 @@
 
 /* Check if all the wagons of the given train are in a depot, returns the
  * number of cars (including loco) then. If not it returns -1 */
-int CheckTrainInDepot(const Vehicle *v, bool needs_to_be_stopped)
+int CheckTrainInDepot(const Train *v, bool needs_to_be_stopped)
 {
 	TileIndex tile = v->tile;
 
@@ -926,13 +926,13 @@
 }
 
 /* Used to check if the train is inside the depot and verifying that the VS_STOPPED flag is set */
-int CheckTrainStoppedInDepot(const Vehicle *v)
+int CheckTrainStoppedInDepot(const Train *v)
 {
 	return CheckTrainInDepot(v, true);
 }
 
 /* Used to check if the train is inside the depot, but not checking the VS_STOPPED flag */
-inline bool CheckTrainIsInsideDepot(const Vehicle *v)
+inline bool CheckTrainIsInsideDepot(const Train *v)
 {
 	return CheckTrainInDepot(v, false) > 0;
 }
@@ -943,7 +943,7 @@
  * @param first The first vehicle of the consist.
  * @return The first vehicle of the consist.
  */
-static Vehicle *UnlinkWagon(Vehicle *v, Vehicle *first)
+static Train *UnlinkWagon(Train *v, Train *first)
 {
 	/* unlinking the first vehicle of the chain? */
 	if (v == first) {
@@ -960,13 +960,13 @@
 		return v;
 	}
 
-	Vehicle *u;
+	Train *u;
 	for (u = first; GetNextVehicle(u) != v; u = GetNextVehicle(u)) {}
 	GetLastEnginePart(u)->SetNext(GetNextVehicle(v));
 	return first;
 }
 
-static Vehicle *FindGoodVehiclePos(const Vehicle *src)
+static Train *FindGoodVehiclePos(const Train *src)
 {
 	Vehicle *dst;
 	EngineID eng = src->engine_type;
@@ -979,7 +979,7 @@
 
 			while (v->engine_type == eng) {
 				v = v->Next();
-				if (v == NULL) return dst;
+				if (v == NULL) return (Train *)dst;
 			}
 		}
 	}
@@ -991,12 +991,12 @@
  * add a vehicle v behind vehicle dest
  * use this function since it sets flags as needed
  */
-static void AddWagonToConsist(Vehicle *v, Vehicle *dest)
+static void AddWagonToConsist(Train *v, Train *dest)
 {
 	UnlinkWagon(v, v->First());
 	if (dest == NULL) return;
 
-	Vehicle *next = dest->Next();
+	Train *next = dest->Next();
 	v->SetNext(NULL);
 	dest->SetNext(v);
 	v->SetNext(next);
@@ -1008,7 +1008,7 @@
  * move around on the train so rear engines are placed correctly according to the other engines
  * always call with the front engine
  */
-static void NormaliseTrainConsist(Vehicle *v)
+static void NormaliseTrainConsist(Train *v)
 {
 	if (IsFreeWagon(v)) return;
 
@@ -1018,7 +1018,7 @@
 		if (!IsMultiheaded(v) || !IsTrainEngine(v)) continue;
 
 		/* make sure that there are no free cars before next engine */
-		Vehicle *u;
+		Train *u;
 		for (u = v; u->Next() != NULL && !IsTrainEngine(u->Next()); u = u->Next()) {}
 
 		if (u == v->u.rail.other_multiheaded_part) continue;
@@ -1040,22 +1040,25 @@
 	VehicleID s = GB(p1, 0, 16);
 	VehicleID d = GB(p1, 16, 16);
 
-	Vehicle *src = Vehicle::GetIfValid(s);
-	if (src == NULL || src->type != VEH_TRAIN || !CheckOwnership(src->owner)) return CMD_ERROR;
+	Vehicle *src_v = Vehicle::GetIfValid(s);
+	if (src_v == NULL || src_v->type != VEH_TRAIN || !CheckOwnership(src_v->owner)) return CMD_ERROR;
 
 	/* Do not allow moving crashed vehicles inside the depot, it is likely to cause asserts later */
-	if (HASBITS(src->vehstatus, VS_CRASHED)) return CMD_ERROR;
+	if (HASBITS(src_v->vehstatus, VS_CRASHED)) return CMD_ERROR;
+
+	Train *src = (Train *)src_v;
 
 	/* if nothing is selected as destination, try and find a matching vehicle to drag to. */
-	Vehicle *dst;
+	Train *dst;
 	if (d == INVALID_VEHICLE) {
 		dst = IsTrainEngine(src) ? NULL : FindGoodVehiclePos(src);
 	} else {
-		dst = Vehicle::GetIfValid(d);
-		if (dst == NULL || dst->type != VEH_TRAIN || !CheckOwnership(dst->owner)) return CMD_ERROR;
+		Vehicle *dst_v = Vehicle::GetIfValid(d);
+		if (dst_v == NULL || dst_v->type != VEH_TRAIN || !CheckOwnership(dst_v->owner)) return CMD_ERROR;
 
 		/* Do not allow appending to crashed vehicles, too */
-		if (HASBITS(dst->vehstatus, VS_CRASHED)) return CMD_ERROR;
+		if (HASBITS(dst_v->vehstatus, VS_CRASHED)) return CMD_ERROR;
+		dst = (Train *)dst_v;
 	}
 
 	/* if an articulated part is being handled, deal with its parent vehicle */
@@ -1068,8 +1071,8 @@
 	if (src == dst) return CommandCost();
 
 	/* locate the head of the two chains */
-	Vehicle *src_head = src->First();
-	Vehicle *dst_head;
+	Train *src_head = src->First();
+	Train *dst_head;
 	if (dst != NULL) {
 		dst_head = dst->First();
 		if (dst_head->tile != src_head->tile) return CMD_ERROR;
@@ -1105,7 +1108,7 @@
 			/* We are moving between rows, so only count the wagons from the source
 			 * row that are being moved. */
 			if (HasBit(p2, 0)) {
-				const Vehicle *u;
+				const Train *u;
 				for (u = src_head; u != src && u != NULL; u = GetNextVehicle(u))
 					src_len--;
 			} else {
@@ -1151,7 +1154,7 @@
 	 * v->Next()->Previous() == v holds (assuming v->Next() != NULL).
 	 */
 	bool src_in_dst = false;
-	for (Vehicle *v = dst_head; !src_in_dst && v != NULL; v = v->Next()) src_in_dst = v == src;
+	for (Train *v = dst_head; !src_in_dst && v != NULL; v = v->Next()) src_in_dst = v == src;
 
 	/*
 	 * If the source chain is in the destination chain then the user is
@@ -1171,12 +1174,12 @@
 		 * attaching fails or succeeds because we are not 'only' doing this
 		 * in the DC_EXEC state.
 		 */
-		Vehicle *dst_tail = dst_head;
+		Train *dst_tail = dst_head;
 		while (dst_tail->Next() != NULL) dst_tail = dst_tail->Next();
 
-		Vehicle *orig_tail = dst_tail;
-		Vehicle *next_to_attach = src;
-		Vehicle *src_previous = src->Previous();
+		Train *orig_tail = dst_tail;
+		Train *next_to_attach = src;
+		Train *src_previous = src->Previous();
 
 		while (next_to_attach != NULL) {
 			/* Don't check callback for articulated or rear dual headed parts */
@@ -1224,7 +1227,7 @@
 			 * to the next wagon. Then add that to the tail of the destination
 			 * train and update the tail with the new vehicle.
 			 */
-			Vehicle *to_add = next_to_attach;
+			Train *to_add = next_to_attach;
 			next_to_attach = next_to_attach->Next();
 
 			to_add->SetNext(NULL);
@@ -1259,7 +1262,7 @@
 		if (HasBit(p2, 0)) {
 			/* unlink ALL wagons */
 			if (src != src_head) {
-				Vehicle *v = src_head;
+				Train *v = src_head;
 				while (GetNextVehicle(v) != src) v = GetNextVehicle(v);
 				GetLastEnginePart(v)->SetNext(NULL);
 			} else {
@@ -1318,7 +1321,7 @@
 
 			/* link in the wagon(s) in the chain. */
 			{
-				Vehicle *v;
+				Train *v;
 
 				for (v = src; GetNextVehicle(v) != NULL; v = GetNextVehicle(v)) {}
 				GetLastEnginePart(v)->SetNext(dst->Next());
@@ -1391,14 +1394,15 @@
 	/* Check if we deleted a vehicle window */
 	Window *w = NULL;
 
-	Vehicle *v = Vehicle::GetIfValid(p1);
-	if (v == NULL || v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
+	Vehicle *vt = Vehicle::GetIfValid(p1);
+	if (vt == NULL || vt->type != VEH_TRAIN || !CheckOwnership(vt->owner)) return CMD_ERROR;
 	if (p2 > 1) return CMD_ERROR;
 
-	if (HASBITS(v->vehstatus, VS_CRASHED)) return_cmd_error(STR_CAN_T_SELL_DESTROYED_VEHICLE);
-
+	if (HASBITS(vt->vehstatus, VS_CRASHED)) return_cmd_error(STR_CAN_T_SELL_DESTROYED_VEHICLE);
+
+	Train *v = (Train *)vt;
 	while (IsArticulatedPart(v)) v = v->Previous();
-	Vehicle *first = v->First();
+	Train *first = v->First();
 
 	/* make sure the vehicle is stopped in the depot */
 	if (CheckTrainStoppedInDepot(first) < 0) {
@@ -1426,7 +1430,7 @@
 
 			/* 1. Delete the engine, if it is dualheaded also delete the matching
 			 * rear engine of the loco (from the point of deletion onwards) */
-			Vehicle *rear = (IsMultiheaded(v) &&
+			Train *rear = (IsMultiheaded(v) &&
 				IsTrainEngine(v)) ? v->u.rail.other_multiheaded_part : NULL;
 
 			if (rear != NULL) {
@@ -1440,7 +1444,7 @@
 			/* 2. We are selling the front vehicle, some special action might be required
 			 * here, so take attention */
 			if (v == first) {
-				Vehicle *new_f = GetNextVehicle(first);
+				Train *new_f = GetNextVehicle(first);
 
 				/* 2.2 If there are wagons present after the deleted front engine, check
 				 * if the second wagon (which will be first) is an engine. If it is one,
@@ -1500,13 +1504,13 @@
 			/* Start deleting every vehicle after the selected one
 			 * If we encounter a matching rear-engine to a front-engine
 			 * earlier in the chain (before deletion), leave it alone */
-			for (Vehicle *tmp; v != NULL; v = tmp) {
+			for (Train *tmp; v != NULL; v = tmp) {
 				tmp = GetNextVehicle(v);
 
 				if (IsMultiheaded(v)) {
 					if (IsTrainEngine(v)) {
 						/* We got a front engine of a multiheaded set. Now we will sell the rear end too */
-						Vehicle *rear = v->u.rail.other_multiheaded_part;
+						Train *rear = v->u.rail.other_multiheaded_part;
 
 						if (rear != NULL) {
 							cost.AddCost(-rear->value);
@@ -1572,14 +1576,14 @@
 	this->z_extent      = 6;
 }
 
-static void UpdateVarsAfterSwap(Vehicle *v)
+static void UpdateVarsAfterSwap(Train *v)
 {
 	v->UpdateDeltaXY(v->direction);
 	v->cur_image = v->GetImage(v->direction);
 	VehicleMove(v, true);
 }
 
-static inline void SetLastSpeed(Vehicle *v, int spd)
+static inline void SetLastSpeed(Train *v, int spd)
 {
 	int old = v->u.rail.last_speed;
 	if (spd != old) {
@@ -1591,7 +1595,7 @@
 }
 
 /** Mark a train as stuck and stop it if it isn't stopped right now. */
-static void MarkTrainAsStuck(Vehicle *v)
+static void MarkTrainAsStuck(Train *v)
 {
 	if (!HasBit(v->u.rail.flags, VRF_TRAIN_STUCK)) {
 		/* It is the first time the problem occured, set the "train stuck" flag. */
@@ -1631,9 +1635,9 @@
 	}
 }
 
-static void ReverseTrainSwapVeh(Vehicle *v, int l, int r)
+static void ReverseTrainSwapVeh(Train *v, int l, int r)
 {
-	Vehicle *a, *b;
+	Train *a, *b;
 
 	/* locate vehicles to swap */
 	for (a = v; l != 0; l--) a = a->Next();
@@ -1704,7 +1708,7 @@
 
 	TileIndex tile = *(TileIndex*)data;
 
-	if (TrainApproachingCrossingTile(v) != tile) return NULL;
+	if (TrainApproachingCrossingTile((Train *)v) != tile) return NULL;
 
 	return v;
 }
@@ -1775,11 +1779,11 @@
  * This one is called before the train is reversed.
  * @param v First vehicle in chain
  */
-static void AdvanceWagonsBeforeSwap(Vehicle *v)
+static void AdvanceWagonsBeforeSwap(Train *v)
 {
-	Vehicle *base = v;
-	Vehicle *first = base;                    // first vehicle to move
-	Vehicle *last = GetLastVehicleInChain(v); // last vehicle to move
+	Train *base = v;
+	Train *first = base; // first vehicle to move
+	Train *last = (Train *)GetLastVehicleInChain(v); // last vehicle to move
 	uint length = CountVehiclesInChain(v);
 
 	while (length > 2) {
@@ -1803,15 +1807,15 @@
  * This one is called after the train is reversed.
  * @param v First vehicle in chain
  */
-static void AdvanceWagonsAfterSwap(Vehicle *v)
+static void AdvanceWagonsAfterSwap(Train *v)
 {
 	/* first of all, fix the situation when the train was entering a depot */
-	Vehicle *dep = v; // last vehicle in front of just left depot
+	Train *dep = v; // last vehicle in front of just left depot
 	while (dep->Next() != NULL && (dep->u.rail.track == TRACK_BIT_DEPOT || dep->Next()->u.rail.track != TRACK_BIT_DEPOT)) {
 		dep = dep->Next(); // find first vehicle outside of a depot, with next vehicle inside a depot
 	}
 
-	Vehicle *leave = dep->Next(); // first vehicle in a depot we are leaving now
+	Train *leave = dep->Next(); // first vehicle in a depot we are leaving now
 
 	if (leave != NULL) {
 		/* 'pull' next wagon out of the depot, so we won't miss it (it could stay in depot forever) */
@@ -1826,9 +1830,9 @@
 		dep = NULL; // no vehicle in a depot, so no vehicle leaving a depot
 	}
 
-	Vehicle *base = v;
-	Vehicle *first = base;                    // first vehicle to move
-	Vehicle *last = GetLastVehicleInChain(v); // last vehicle to move
+	Train *base = v;
+	Train *first = base; // first vehicle to move
+	Train *last = (Train *)GetLastVehicleInChain(v); // last vehicle to move
 	uint length = CountVehiclesInChain(v);
 
 	/* we have to make sure all wagons that leave a depot because of train reversing are moved coorectly
@@ -1857,7 +1861,7 @@
 }
 
 
-static void ReverseTrainDirection(Vehicle *v)
+static void ReverseTrainDirection(Train *v)
 {
 	if (IsRailDepotTile(v->tile)) {
 		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
@@ -1946,8 +1950,10 @@
  */
 CommandCost CmdReverseTrainDirection(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 {
-	Vehicle *v = Vehicle::GetIfValid(p1);
-	if (v == NULL || v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
+	Vehicle *vt = Vehicle::GetIfValid(p1);
+	if (vt == NULL || vt->type != VEH_TRAIN || !CheckOwnership(vt->owner)) return CMD_ERROR;
+
+	Train *v = (Train *)vt;
 
 	if (p2 != 0) {
 		/* turn a single unit around */
@@ -1956,7 +1962,7 @@
 			return_cmd_error(STR_ONLY_TURN_SINGLE_UNIT);
 		}
 
-		Vehicle *front = v->First();
+		Train *front = v->First();
 		/* make sure the vehicle is stopped in the depot */
 		if (CheckTrainStoppedInDepot(front) < 0) {
 			return_cmd_error(STR_ERROR_TRAINS_CAN_ONLY_BE_ALTERED_INSIDE_A_DEPOT);
@@ -2007,7 +2013,7 @@
 	Vehicle *v = Vehicle::GetIfValid(p1);
 	if (v == NULL || v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
 
-	if (flags & DC_EXEC) v->u.rail.force_proceed = 0x50;
+	if (flags & DC_EXEC) ((Train *)v)->u.rail.force_proceed = 0x50;
 
 	return CommandCost();
 }
@@ -2028,8 +2034,10 @@
 	byte new_subtype = GB(p2, 8, 8);
 	bool only_this = HasBit(p2, 16);
 
-	Vehicle *v = Vehicle::GetIfValid(p1);
-	if (v == NULL || v->type != VEH_TRAIN || !CheckOwnership(v->owner)) return CMD_ERROR;
+	Vehicle *vt = Vehicle::GetIfValid(p1);
+	if (vt == NULL || vt->type != VEH_TRAIN || !CheckOwnership(vt->owner)) return CMD_ERROR;
+
+	Train *v = (Train *)vt;
 	if (CheckTrainStoppedInDepot(v) < 0) return_cmd_error(STR_TRAIN_MUST_BE_STOPPED);
 	if (v->vehstatus & VS_CRASHED) return_cmd_error(STR_CAN_T_REFIT_DESTROYED_VEHICLE);
 
@@ -2103,7 +2111,7 @@
 	_returned_refit_capacity = num;
 
 	/* Update the train's cached variables */
-	if (flags & DC_EXEC) TrainConsistChanged(Vehicle::Get(p1)->First(), false);
+	if (flags & DC_EXEC) TrainConsistChanged((Train *)Vehicle::Get(p1)->First(), false);
 
 	return cost;
 }
@@ -2135,7 +2143,7 @@
 
 /** returns the tile of a depot to goto to. The given vehicle must not be
  * crashed! */
-static TrainFindDepotData FindClosestTrainDepot(Vehicle *v, int max_distance)
+static TrainFindDepotData FindClosestTrainDepot(Train *v, int max_distance)
 {
 	assert(!(v->vehstatus & VS_CRASHED));
 
@@ -2247,7 +2255,7 @@
 	1, 1, 1, 0, -1, -1, -1, 0
 };
 
-static void HandleLocomotiveSmokeCloud(const Vehicle *v)
+static void HandleLocomotiveSmokeCloud(const Train *v)
 {
 	bool sound = false;
 
@@ -2255,7 +2263,7 @@
 		return;
 	}
 
-	const Vehicle *u = v;
+	const Train *u = v;
 
 	do {
 		const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
@@ -2341,7 +2349,7 @@
 }
 
 /** Check if the train is on the last reserved tile and try to extend the path then. */
-static void CheckNextTrainTile(Vehicle *v)
+static void CheckNextTrainTile(Train *v)
 {
 	/* Don't do any look-ahead if path_backoff_interval is 255. */
 	if (_settings_game.pf.path_backoff_interval == 255) return;
@@ -2378,10 +2386,10 @@
 	}
 }
 
-static bool CheckTrainStayInDepot(Vehicle *v)
+static bool CheckTrainStayInDepot(Train *v)
 {
 	/* bail out if not all wagons are in the same depot or not in a depot at all */
-	for (const Vehicle *u = v; u != NULL; u = u->Next()) {
+	for (const Train *u = v; u != NULL; u = u->Next()) {
 		if (u->u.rail.track != TRACK_BIT_DEPOT || u->tile != v->tile) return false;
 	}
 
@@ -2454,7 +2462,7 @@
 }
 
 /** Clear the reservation of a tile that was just left by a wagon on track_dir. */
-static void ClearPathReservation(const Vehicle *v, TileIndex tile, Trackdir track_dir)
+static void ClearPathReservation(const Train *v, TileIndex tile, Trackdir track_dir)
 {
 	DiagDirection dir = TrackdirToExitdir(track_dir);
 
@@ -2488,7 +2496,7 @@
 }
 
 /** Free the reserved path in front of a vehicle. */
-void FreeTrainTrackReservation(const Vehicle *v, TileIndex origin, Trackdir orig_td)
+void FreeTrainTrackReservation(const Train *v, TileIndex origin, Trackdir orig_td)
 {
 	assert(IsFrontEngine(v));
 
@@ -2613,7 +2621,7 @@
  * @param dest [out] State and destination of the requested path
  * @return The best track the train should follow
  */
-static Track DoTrainPathfind(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool do_track_reservation, PBSTileInfo *dest)
+static Track DoTrainPathfind(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool do_track_reservation, PBSTileInfo *dest)
 {
 	Track best_track;
 
@@ -2714,7 +2722,7 @@
  * another reservation or a track choice.
  * @return INVALID_TILE indicates that the reservation failed.
  */
-static PBSTileInfo ExtendTrainReservation(const Vehicle *v, TrackBits *new_tracks, DiagDirection *enterdir)
+static PBSTileInfo ExtendTrainReservation(const Train *v, TrackBits *new_tracks, DiagDirection *enterdir)
 {
 	bool no_90deg_turns = _settings_game.pf.pathfinder_for_trains != VPF_NTP && _settings_game.pf.forbid_90_deg;
 	PBSTileInfo origin = FollowTrainReservation(v);
@@ -2807,7 +2815,7 @@
  * @param override_tailtype Whether all physically compatible railtypes should be followed.
  * @return True if a path to a safe stopping tile could be reserved.
  */
-static bool TryReserveSafeTrack(const Vehicle *v, TileIndex tile, Trackdir td, bool override_tailtype)
+static bool TryReserveSafeTrack(const Train *v, TileIndex tile, Trackdir td, bool override_tailtype)
 {
 	if (_settings_game.pf.pathfinder_for_trains == VPF_YAPF) {
 		return YapfRailFindNearestSafeTile(v, tile, td, override_tailtype);
@@ -2896,7 +2904,7 @@
 };
 
 /* choose a track */
-static Track ChooseTrainTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *got_reservation, bool mark_stuck)
+static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool force_res, bool *got_reservation, bool mark_stuck)
 {
 	Track best_track = INVALID_TRACK;
 	bool do_track_reservation = _settings_game.pf.reserve_paths || force_res;
@@ -3075,7 +3083,7 @@
  * @param first_tile_okay True if no path should be reserved if the current tile is a safe position.
  * @return True if a path could be reserved.
  */
-bool TryPathReserve(Vehicle *v, bool mark_as_stuck, bool first_tile_okay)
+bool TryPathReserve(Train *v, bool mark_as_stuck, bool first_tile_okay)
 {
 	assert(v->type == VEH_TRAIN && IsFrontEngine(v));
 
@@ -3155,7 +3163,7 @@
 }
 
 
-static bool CheckReverseTrain(Vehicle *v)
+static bool CheckReverseTrain(Train *v)
 {
 	if (_settings_game.difficulty.line_reverse_mode != 0 ||
 			v->u.rail.track == TRACK_BIT_DEPOT || v->u.rail.track == TRACK_BIT_WORMHOLE ||
@@ -3295,7 +3303,7 @@
  * @param v The vehicle to update the speed of.
  * @return distance to drive.
  */
-static int UpdateTrainSpeed(Vehicle *v)
+static int UpdateTrainSpeed(Train *v)
 {
 	uint accel;
 
@@ -3340,7 +3348,7 @@
 	return scaled_spd;
 }
 
-static void TrainEnterStation(Vehicle *v, StationID station)
+static void TrainEnterStation(Train *v, StationID station)
 {
 	v->last_station_visited = station;
 
@@ -3363,7 +3371,7 @@
 	StationAnimationTrigger(st, v->tile, STAT_ANIM_TRAIN_ARRIVES);
 }
 
-static byte AfterSetTrainPos(Vehicle *v, bool new_tile)
+static byte AfterSetTrainPos(Train *v, bool new_tile)
 {
 	byte old_z = v->z_pos;
 	v->z_pos = GetSlopeZ(v->x_pos, v->y_pos);
@@ -3396,7 +3404,7 @@
 }
 
 /* Check if the vehicle is compatible with the specified tile */
-static inline bool CheckCompatibleRail(const Vehicle *v, TileIndex tile)
+static inline bool CheckCompatibleRail(const Train *v, TileIndex tile)
 {
 	return
 		IsTileOwner(tile, v->owner) && (
@@ -3420,7 +3428,7 @@
 };
 
 /** Modify the speed of the vehicle due to a turn */
-static inline void AffectSpeedByDirChange(Vehicle *v, Direction new_dir)
+static inline void AffectSpeedByDirChange(Train *v, Direction new_dir)
 {
 	if (_settings_game.vehicle.train_acceleration_model != TAM_ORIGINAL) return;
 
@@ -3432,7 +3440,7 @@
 }
 
 /** Modify the speed of the vehicle due to a change in altitude */
-static inline void AffectSpeedByZChange(Vehicle *v, byte old_z)
+static inline void AffectSpeedByZChange(Train *v, byte old_z)
 {
 	if (old_z == v->z_pos || _settings_game.vehicle.train_acceleration_model != TAM_ORIGINAL) return;
 
@@ -3461,7 +3469,7 @@
 }
 
 
-static void SetVehicleCrashed(Vehicle *v)
+static void SetVehicleCrashed(Train *v)
 {
 	if (v->u.rail.crash_anim_pos != 0) return;
 
@@ -3470,7 +3478,7 @@
 		/* Remove all reservations, also the ones currently under the train
 		 * and any railway station paltform reservation. */
 		FreeTrainTrackReservation(v);
-		for (const Vehicle *u = v; u != NULL; u = u->Next()) {
+		for (const Train *u = v; u != NULL; u = u->Next()) {
 			ClearPathReservation(u, u->tile, u->GetVehicleTrackdir());
 			if (IsTileType(u->tile, MP_TUNNELBRIDGE)) {
 				/* ClearPathReservation will not free the wormhole exit
@@ -3503,7 +3511,7 @@
 	if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing);
 }
 
-static uint CountPassengersInTrain(const Vehicle *v)
+static uint CountPassengersInTrain(const Train *v)
 {
 	uint num = 0;
 
@@ -3520,7 +3528,7 @@
  * @param v first vehicle of chain
  * @return number of victims (including 2 drivers; zero if train was already crashed)
  */
-static uint TrainCrashed(Vehicle *v)
+static uint TrainCrashed(Train *v)
 {
 	/* do not crash train twice */
 	if (v->vehstatus & VS_CRASHED) return 0;
@@ -3549,7 +3557,7 @@
 	Vehicle *coll = v->First();
 
 	/* can't collide with own wagons && can't crash in depot && the same height level */
-	if (coll != tcc->v && v->u.rail.track != TRACK_BIT_DEPOT && abs(v->z_pos - tcc->v->z_pos) < 6) {
+	if (coll != tcc->v && ((Train *)v)->u.rail.track != TRACK_BIT_DEPOT && abs(v->z_pos - tcc->v->z_pos) < 6) {
 		int x_diff = v->x_pos - tcc->v->x_pos;
 		int y_diff = v->y_pos - tcc->v->y_pos;
 
@@ -3557,15 +3565,15 @@
 		if (x_diff * x_diff + y_diff * y_diff > 25) return NULL;
 
 		/* crash both trains */
-		tcc->num += TrainCrashed(tcc->v);
-		tcc->num += TrainCrashed(coll);
+		tcc->num += TrainCrashed((Train *)tcc->v);
+		tcc->num += TrainCrashed((Train *)coll);
 
 		/* Try to reserve all tiles directly under the crashed trains.
 		 * As there might be more than two trains involved, we have to do that for all vehicles */
 		const Vehicle *u;
 		FOR_ALL_VEHICLES(u) {
-			if (u->type == VEH_TRAIN && HASBITS(u->vehstatus, VS_CRASHED) && (u->u.rail.track & TRACK_BIT_DEPOT) == TRACK_BIT_NONE) {
-				TrackBits trackbits = u->u.rail.track;
+			if (u->type == VEH_TRAIN && HASBITS(u->vehstatus, VS_CRASHED) && (((Train *)u)->u.rail.track & TRACK_BIT_DEPOT) == TRACK_BIT_NONE) {
+				TrackBits trackbits = ((Train *)u)->u.rail.track;
 				if ((trackbits & TRACK_BIT_WORMHOLE) == TRACK_BIT_WORMHOLE) {
 					/* Vehicle is inside a wormhole, v->u.rail.track contains no useful value then. */
 					trackbits |= DiagDirToDiagTrackBits(GetTunnelBridgeDirection(u->tile));
@@ -3584,7 +3592,7 @@
  * Reports the incident in a flashy news item, modifies station ratings and
  * plays a sound.
  */
-static bool CheckTrainCollision(Vehicle *v)
+static bool CheckTrainCollision(Train *v)
 {
 	/* can't collide in depot */
 	if (v->u.rail.track == TRACK_BIT_DEPOT) return false;
@@ -3623,16 +3631,16 @@
 	DiagDirection exitdir = *(DiagDirection *)data;
 
 	/* front engine of a train, not inside wormhole or depot, not crashed */
-	if (v->type == VEH_TRAIN && IsFrontEngine(v) && (v->u.rail.track & TRACK_BIT_MASK) != 0 && !(v->vehstatus & VS_CRASHED)) {
-		if (v->cur_speed <= 5 && TrainExitDir(v->direction, v->u.rail.track) == exitdir) return v;
+	if (v->type == VEH_TRAIN && IsFrontEngine(v) && (((Train *)v)->u.rail.track & TRACK_BIT_MASK) != 0 && !(v->vehstatus & VS_CRASHED)) {
+		if (v->cur_speed <= 5 && TrainExitDir(v->direction, ((Train *)v)->u.rail.track) == exitdir) return v;
 	}
 
 	return NULL;
 }
 
-static void TrainController(Vehicle *v, Vehicle *nomove)
+static void TrainController(Train *v, Vehicle *nomove)
 {
-	Vehicle *prev;
+	Train *prev;
 
 	/* For every vehicle after and including the given vehicle */
 	for (prev = v->Previous(); v != nomove; prev = v, v = v->Next()) {
@@ -3922,11 +3930,11 @@
 	TrackBits *trackbits = (TrackBits *)data;
 
 	if (v->type == VEH_TRAIN && (v->vehstatus & VS_CRASHED) != 0) {
-		if ((v->u.rail.track & TRACK_BIT_WORMHOLE) == TRACK_BIT_WORMHOLE) {
+		if ((((Train *)v)->u.rail.track & TRACK_BIT_WORMHOLE) == TRACK_BIT_WORMHOLE) {
 			/* Vehicle is inside a wormhole, v->u.rail.track contains no useful value then. */
 			*trackbits |= DiagDirToDiagTrackBits(GetTunnelBridgeDirection(v->tile));
 		} else {
-			*trackbits |= v->u.rail.track;
+			*trackbits |= ((Train *)v)->u.rail.track;
 		}
 	}
 
@@ -3940,14 +3948,14 @@
  * or inside a tunnel/bridge, recalculate the signals as they might need updating
  * @param v the Vehicle of which last wagon is to be removed
  */
-static void DeleteLastWagon(Vehicle *v)
+static void DeleteLastWagon(Train *v)
 {
-	Vehicle *first = v->First();
+	Train *first = v->First();
 
 	/* Go to the last wagon and delete the link pointing there
 	 * *u is then the one-before-last wagon, and *v the last
 	 * one which will physicially be removed */
-	Vehicle *u = v;
+	Train *u = v;
 	for (; v->Next() != NULL; v = v->Next()) u = v;
 	u->SetNext(NULL);
 
@@ -4002,7 +4010,7 @@
 	}
 }
 
-static void ChangeTrainDirRandomly(Vehicle *v)
+static void ChangeTrainDirRandomly(Train *v)
 {
 	static const DirDiff delta[] = {
 		DIRDIFF_45LEFT, DIRDIFF_SAME, DIRDIFF_SAME, DIRDIFF_45RIGHT
@@ -4022,7 +4030,7 @@
 	} while ((v = v->Next()) != NULL);
 }
 
-static bool HandleCrashedTrain(Vehicle *v)
+static bool HandleCrashedTrain(Train *v)
 {
 	int state = ++v->u.rail.crash_anim_pos;
 
@@ -4061,7 +4069,7 @@
 	return true;
 }
 
-static void HandleBrokenTrain(Vehicle *v)
+static void HandleBrokenTrain(Train *v)
 {
 	if (v->breakdown_ctr != 1) {
 		v->breakdown_ctr = 1;
@@ -4105,7 +4113,7 @@
  * @param signal not line end, just a red signal
  * @return true iff we did NOT have to reverse
  */
-static bool TrainApproachingLineEnd(Vehicle *v, bool signal)
+static bool TrainApproachingLineEnd(Train *v, bool signal)
 {
 	/* Calc position within the current tile */
 	uint x = v->x_pos & 0xF;
@@ -4146,7 +4154,7 @@
  * @param v train to test
  * @return true iff vehicle is NOT entering or inside a depot or tunnel/bridge
  */
-static bool TrainCanLeaveTile(const Vehicle *v)
+static bool TrainCanLeaveTile(const Train *v)
 {
 	/* Exit if inside a tunnel/bridge or a depot */
 	if (v->u.rail.track == TRACK_BIT_WORMHOLE || v->u.rail.track == TRACK_BIT_DEPOT) return false;
@@ -4176,7 +4184,7 @@
  * @return TileIndex of crossing the train is approaching, else INVALID_TILE
  * @pre v in non-crashed front engine
  */
-static TileIndex TrainApproachingCrossingTile(const Vehicle *v)
+static TileIndex TrainApproachingCrossingTile(const Train *v)
 {
 	assert(IsFrontEngine(v));
 	assert(!(v->vehstatus & VS_CRASHED));
@@ -4202,7 +4210,7 @@
  * @param v vehicle we are checking
  * @return true iff we did NOT have to reverse
  */
-static bool TrainCheckIfLineEnds(Vehicle *v)
+static bool TrainCheckIfLineEnds(Train *v)
 {
 	/* First, handle broken down train */
 
@@ -4253,7 +4261,7 @@
 }
 
 
-static bool TrainLocoHandler(Vehicle *v, bool mode)
+static bool TrainLocoHandler(Train *v, bool mode)
 {
 	/* train has crashed? */
 	if (v->vehstatus & VS_CRASHED) {
@@ -4381,7 +4389,7 @@
 		SetLastSpeed(v, v->cur_speed);
 	}
 
-	for (Vehicle *u = v; u != NULL; u = u->Next()) {
+	for (Train *u = v; u != NULL; u = u->Next()) {
 		if ((u->vehstatus & VS_HIDDEN) != 0) continue;
 
 		uint16 old_image = u->cur_image;
@@ -4399,7 +4407,7 @@
 Money Train::GetRunningCost() const
 {
 	Money cost = 0;
-	const Vehicle *v = this;
+	const Train *v = this;
 
 	do {
 		const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
@@ -4448,7 +4456,7 @@
 	return true;
 }
 
-static void CheckIfTrainNeedsService(Vehicle *v)
+static void CheckIfTrainNeedsService(Train *v)
 {
 	static const uint MAX_ACCEPTABLE_DEPOT_DIST = 16;
 
--- a/src/train_gui.cpp
+++ b/src/train_gui.cpp
@@ -28,7 +28,7 @@
 	FOR_ALL_VEHICLES(v) {
 		if (v->type == VEH_TRAIN && IsFrontEngine(v) &&
 				v->tile == tile &&
-				v->u.rail.track == TRACK_BIT_DEPOT) {
+				((Train *)v)->u.rail.track == TRACK_BIT_DEPOT) {
 			if (found != NULL) return; // must be exactly one.
 			found = v;
 		}
--- a/src/tunnelbridge_cmd.cpp
+++ b/src/tunnelbridge_cmd.cpp
@@ -647,7 +647,7 @@
 			Track track = DiagDirToDiagTrack(dir);
 			Owner owner = GetTileOwner(tile);
 
-			Vehicle *v = NULL;
+			Train *v = NULL;
 			if (GetTunnelBridgeReservation(tile)) {
 				v = GetTrainForReservation(tile, track);
 				if (v != NULL) FreeTrainTrackReservation(v);
@@ -711,7 +711,7 @@
 		bool rail = GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL;
 		Owner owner = GetTileOwner(tile);
 		uint height = GetBridgeHeight(tile);
-		Vehicle *v = NULL;
+		Train *v = NULL;
 
 		if (rail && GetTunnelBridgeReservation(tile)) {
 			v = GetTrainForReservation(tile, DiagDirToDiagTrack(direction));
@@ -1385,31 +1385,32 @@
 		DiagDirection vdir;
 
 		if (v->type == VEH_TRAIN) {
+			Train *t = (Train *)v;
 			fc = (x & 0xF) + (y << 4);
 
-			vdir = DirToDiagDir(v->direction);
+			vdir = DirToDiagDir(t->direction);
 
-			if (v->u.rail.track != TRACK_BIT_WORMHOLE && dir == vdir) {
-				if (IsFrontEngine(v) && fc == _tunnel_fractcoord_1[dir]) {
-					if (!PlayVehicleSound(v, VSE_TUNNEL) && RailVehInfo(v->engine_type)->engclass == 0) {
+			if (t->u.rail.track != TRACK_BIT_WORMHOLE && dir == vdir) {
+				if (IsFrontEngine(t) && fc == _tunnel_fractcoord_1[dir]) {
+					if (!PlayVehicleSound(t, VSE_TUNNEL) && RailVehInfo(t->engine_type)->engclass == 0) {
 						SndPlayVehicleFx(SND_05_TRAIN_THROUGH_TUNNEL, v);
 					}
 					return VETSB_CONTINUE;
 				}
 				if (fc == _tunnel_fractcoord_2[dir]) {
-					v->tile = tile;
-					v->u.rail.track = TRACK_BIT_WORMHOLE;
-					v->vehstatus |= VS_HIDDEN;
+					t->tile = tile;
+					t->u.rail.track = TRACK_BIT_WORMHOLE;
+					t->vehstatus |= VS_HIDDEN;
 					return VETSB_ENTERED_WORMHOLE;
 				}
 			}
 
 			if (dir == ReverseDiagDir(vdir) && fc == _tunnel_fractcoord_3[dir] && z == 0) {
 				/* We're at the tunnel exit ?? */
-				v->tile = tile;
-				v->u.rail.track = (TrackBits)_exit_tunnel_track[dir];
-				assert(v->u.rail.track);
-				v->vehstatus &= ~VS_HIDDEN;
+				t->tile = tile;
+				t->u.rail.track = (TrackBits)_exit_tunnel_track[dir];
+				assert(t->u.rail.track);
+				t->vehstatus &= ~VS_HIDDEN;
 				return VETSB_ENTERED_WORMHOLE;
 			}
 		} else if (v->type == VEH_ROAD) {
@@ -1462,11 +1463,12 @@
 				case DIAGDIR_NW: if ((y & 0xF) != 0)             return VETSB_CONTINUE; break;
 			}
 			switch (v->type) {
-				case VEH_TRAIN:
-					v->u.rail.track = TRACK_BIT_WORMHOLE;
-					ClrBit(v->u.rail.flags, VRF_GOINGUP);
-					ClrBit(v->u.rail.flags, VRF_GOINGDOWN);
-					break;
+				case VEH_TRAIN: {
+					Train *t = (Train *)v;
+					t->u.rail.track = TRACK_BIT_WORMHOLE;
+					ClrBit(t->u.rail.flags, VRF_GOINGUP);
+					ClrBit(t->u.rail.flags, VRF_GOINGDOWN);
+				} break;
 
 				case VEH_ROAD:
 					((RoadVehicle *)v)->state = RVSB_WORMHOLE;
@@ -1482,12 +1484,13 @@
 		} else if (DirToDiagDir(v->direction) == ReverseDiagDir(dir)) {
 			v->tile = tile;
 			switch (v->type) {
-				case VEH_TRAIN:
-					if (v->u.rail.track == TRACK_BIT_WORMHOLE) {
-						v->u.rail.track = (DiagDirToAxis(dir) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y);
+				case VEH_TRAIN: {
+					Train *t = (Train *)v;
+					if (t->u.rail.track == TRACK_BIT_WORMHOLE) {
+						t->u.rail.track = (DiagDirToAxis(dir) == AXIS_X ? TRACK_BIT_X : TRACK_BIT_Y);
 						return VETSB_ENTERED_WORMHOLE;
 					}
-					break;
+				} break;
 
 				case VEH_ROAD: {
 					RoadVehicle *rv = (RoadVehicle *)v;
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -982,8 +982,8 @@
 			if (!IsFrontEngine(v)) v = v->First();
 			UpdateSignalsOnSegment(v->tile, INVALID_DIAGDIR, v->owner);
 			v->load_unload_time_rem = 0;
-			ClrBit(v->u.rail.flags, VRF_TOGGLE_REVERSE);
-			TrainConsistChanged(v, true);
+			ClrBit(((Train *)v)->u.rail.flags, VRF_TOGGLE_REVERSE);
+			TrainConsistChanged((Train *)v, true);
 			break;
 
 		case VEH_ROAD:
@@ -1488,7 +1488,7 @@
 		 * 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(this->GetVehicleTrackdir()), this->owner) == SIGSEG_PBS || _settings_game.pf.reserve_paths) {
-			TryPathReserve(this, true, true);
+			TryPathReserve((Train *)this, true, true);
 		}
 	}
 }
--- a/src/vehicle_base.h
+++ b/src/vehicle_base.h
@@ -46,7 +46,7 @@
 
 struct VehicleRail {
 	/* Link between the two ends of a multiheaded engine */
-	Vehicle *other_multiheaded_part;
+	Train *other_multiheaded_part;
 
 	/* Cached wagon override spritegroup */
 	const struct SpriteGroup *cached_override;
--- a/src/vehicle_cmd.cpp
+++ b/src/vehicle_cmd.cpp
@@ -152,7 +152,7 @@
 
 		if (!vehicle_list_window) {
 			if (vehicle_type == VEH_TRAIN) {
-				if (CheckTrainInDepot(v, false) == -1) continue;
+				if (CheckTrainInDepot((Train *)v, false) == -1) continue;
 			} else {
 				if (!(v->vehstatus & VS_HIDDEN)) continue;
 			}
@@ -381,8 +381,8 @@
 		if (flags & DC_EXEC) {
 			w = Vehicle::Get(_new_vehicle_id);
 
-			if (v->type == VEH_TRAIN && HasBit(v->u.rail.flags, VRF_REVERSE_DIRECTION)) {
-				SetBit(w->u.rail.flags, VRF_REVERSE_DIRECTION);
+			if (v->type == VEH_TRAIN && HasBit(((Train *)v)->u.rail.flags, VRF_REVERSE_DIRECTION)) {
+				SetBit(((Train *)w)->u.rail.flags, VRF_REVERSE_DIRECTION);
 			}
 
 			if (v->type == VEH_TRAIN && !IsFrontEngine(v)) {
@@ -403,7 +403,7 @@
 			}
 			w_rear = w; // trains needs to know the last car in the train, so they can add more in next loop
 		}
-	} while (v->type == VEH_TRAIN && (v = GetNextVehicle(v)) != NULL);
+	} while (v->type == VEH_TRAIN && (v = GetNextVehicle((Train *)v)) != NULL);
 
 	if (flags & DC_EXEC && v_front->type == VEH_TRAIN) {
 		/* for trains this needs to be the front engine due to the callback function */
@@ -437,7 +437,7 @@
 				}
 
 				if (w->type == VEH_TRAIN && EngineHasArticPart(w)) {
-					w = GetNextArticPart(w);
+					w = GetNextArticPart((Train *)w);
 				} else if (w->type == VEH_ROAD && RoadVehHasArticPart(w)) {
 					w = w->Next();
 				} else {
@@ -453,7 +453,7 @@
 			}
 
 			if (v->type == VEH_TRAIN && EngineHasArticPart(v)) {
-				v = GetNextArticPart(v);
+				v = GetNextArticPart((Train *)v);
 			} else if (v->type == VEH_ROAD && RoadVehHasArticPart(v)) {
 				v = v->Next();
 			} else {
@@ -461,8 +461,8 @@
 			}
 		} while (v != NULL);
 
-		if ((flags & DC_EXEC) && v->type == VEH_TRAIN) w = GetNextVehicle(w);
-	} while (v->type == VEH_TRAIN && (v = GetNextVehicle(v)) != NULL);
+		if ((flags & DC_EXEC) && v->type == VEH_TRAIN) w = GetNextVehicle((Train *)w);
+	} while (v->type == VEH_TRAIN && (v = GetNextVehicle((Train *)v)) != NULL);
 
 	if (flags & DC_EXEC) {
 		/*
--- a/src/vehicle_func.h
+++ b/src/vehicle_func.h
@@ -59,10 +59,6 @@
 
 UnitID GetFreeUnitNumber(VehicleType type);
 
-void TrainConsistChanged(Vehicle *v, bool same_length);
-void TrainPowerChanged(Vehicle *v);
-Money GetTrainRunningCost(const Vehicle *v);
-
 CommandCost SendAllVehiclesToDepot(VehicleType type, DoCommandFlag flags, bool service, Owner owner, uint16 vlw_flag, uint32 id);
 void VehicleEnterDepot(Vehicle *v);
 
--- a/src/vehicle_gui.cpp
+++ b/src/vehicle_gui.cpp
@@ -18,6 +18,7 @@
 #include "newgrf_text.h"
 #include "station_map.h"
 #include "roadveh.h"
+#include "train.h"
 #include "depot_base.h"
 #include "group_gui.h"
 #include "strings_func.h"
@@ -1468,7 +1469,7 @@
 				SetDParam(1, v->u.rail.cached_power);
 				SetDParam(0, v->u.rail.cached_weight);
 				SetDParam(3, v->u.rail.cached_max_te / 1000);
-				DrawString(2, this->width - 2, 25, (_settings_game.vehicle.train_acceleration_model != TAM_ORIGINAL && v->u.rail.railtype != RAILTYPE_MAGLEV) ?
+				DrawString(2, this->width - 2, 25, (_settings_game.vehicle.train_acceleration_model != TAM_ORIGINAL && ((Train *)v)->u.rail.railtype != RAILTYPE_MAGLEV) ?
 					STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE :
 					STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED);
 				break;
@@ -1948,7 +1949,7 @@
 			} else { // no train
 				str = STR_VEHICLE_STATUS_STOPPED;
 			}
-		} else if (v->type == VEH_TRAIN && HasBit(v->u.rail.flags, VRF_TRAIN_STUCK)) {
+		} else if (v->type == VEH_TRAIN && HasBit(((Train *)v)->u.rail.flags, VRF_TRAIN_STUCK)) {
 			str = STR_TRAIN_STUCK;
 		} else { // vehicle is in a "normal" state, show current order
 			switch (v->current_order.GetType()) {
--- a/src/vehicle_type.h
+++ b/src/vehicle_type.h
@@ -24,6 +24,10 @@
 typedef TinyEnumT<VehicleType> VehicleTypeByte;
 
 struct Vehicle;
+struct Train;
+struct RoadVehicle;
+struct Ship;
+struct Aircraft;
 
 struct BaseVehicle
 {
--- a/src/vehiclelist.cpp
+++ b/src/vehiclelist.cpp
@@ -29,7 +29,7 @@
 		switch (type) {
 			case VEH_TRAIN:
 				if (IsArticulatedPart(v) || IsRearDualheaded(v)) continue;
-				if (v->u.rail.track != TRACK_BIT_DEPOT) continue;
+				if (((Train *)v)->u.rail.track != TRACK_BIT_DEPOT) continue;
 				if (wagons != NULL && IsFreeWagon(v->First())) {
 					if (individual_wagons || IsFreeWagon(v)) *wagons->Append() = v;
 					continue;
--- a/src/water_cmd.cpp
+++ b/src/water_cmd.cpp
@@ -813,7 +813,7 @@
 						/* FreeTrainTrackReservation() calls GetVehicleTrackdir() that doesn't like crashed vehicles.
 						 * In this case, v->direction matches v->u.rail.track, so we can do this (it wasn't crashed before) */
 						v->vehstatus &= ~VS_CRASHED;
-						FreeTrainTrackReservation(v);
+						FreeTrainTrackReservation((Train *)v);
 						v->vehstatus |= VS_CRASHED;
 					}
 					v->u.rail.crash_anim_pos = 4000; // max 4440, disappear pretty fast
--- a/src/waypoint_cmd.cpp
+++ b/src/waypoint_cmd.cpp
@@ -258,7 +258,7 @@
 		wp->deleted = 30; // let it live for this many days before we do the actual deletion.
 		RedrawWaypointSign(wp);
 
-		Vehicle *v = NULL;
+		Train *v = NULL;
 		if (justremove) {
 			TrackBits tracks = GetRailWaypointBits(tile);
 			bool reserved = GetDepotWaypointReservation(tile);
--- a/src/yapf/follow_track.hpp
+++ b/src/yapf/follow_track.hpp
@@ -8,6 +8,7 @@
 #include "yapf.hpp"
 #include "../depot_map.h"
 #include "../roadveh.h"
+#include "../train.h"
 
 /** Track follower helper template class (can serve pathfinders and vehicle
  *  controllers). See 6 different typedefs below for 3 different transport
@@ -54,7 +55,7 @@
 	{
 		assert(!IsRailTT() || (v != NULL && v->type == VEH_TRAIN));
 		m_veh = v;
-		Init(v != NULL ? v->owner : INVALID_OWNER, railtype_override == INVALID_RAILTYPES ? v->u.rail.compatible_railtypes : railtype_override, pPerf);
+		Init(v != NULL ? v->owner : INVALID_OWNER, railtype_override == INVALID_RAILTYPES ? ((Train *)v)->u.rail.compatible_railtypes : railtype_override, pPerf);
 	}
 
 	FORCEINLINE void Init(Owner o, RailTypes railtype_override, CPerformanceTimer *pPerf)
@@ -105,7 +106,7 @@
 		m_old_tile = old_tile;
 		m_old_td = old_td;
 		m_err = EC_NONE;
-		assert(((TrackStatusToTrackdirBits(GetTileTrackStatus(m_old_tile, TT(), m_veh ? m_veh->u.road.compatible_roadtypes : 0)) & TrackdirToTrackdirBits(m_old_td)) != 0) ||
+		assert(((TrackStatusToTrackdirBits(GetTileTrackStatus(m_old_tile, TT(), m_veh ? ((RoadVehicle *)m_veh)->compatible_roadtypes : 0)) & TrackdirToTrackdirBits(m_old_td)) != 0) ||
 		       (IsTram() && GetSingleTramBit(m_old_tile) != INVALID_DIAGDIR)); // Disable the assertion for single tram bits
 		m_exitdir = TrackdirToExitdir(m_old_td);
 		if (ForcedReverse()) return true;
--- a/src/yapf/yapf_destrail.hpp
+++ b/src/yapf/yapf_destrail.hpp
@@ -91,8 +91,8 @@
 	FORCEINLINE bool PfDetectDestination(TileIndex tile, Trackdir td)
 	{
 		return
-			IsSafeWaitingPosition(Yapf().GetVehicle(), tile, td, true, !TrackFollower::Allow90degTurns()) &&
-			IsWaitingPositionFree(Yapf().GetVehicle(), tile, td, !TrackFollower::Allow90degTurns());
+			IsSafeWaitingPosition((Train *)Yapf().GetVehicle(), tile, td, true, !TrackFollower::Allow90degTurns()) &&
+			IsWaitingPositionFree((Train *)Yapf().GetVehicle(), tile, td, !TrackFollower::Allow90degTurns());
 	}
 
 	/** Called by YAPF to calculate cost estimate. Calculates distance to the destination
--- a/src/yapf/yapf_rail.cpp
+++ b/src/yapf/yapf_rail.cpp
@@ -54,7 +54,7 @@
 
 	bool FindSafePositionProc(TileIndex tile, Trackdir td)
 	{
-		if (IsSafeWaitingPosition(Yapf().GetVehicle(), tile, td, true, !TrackFollower::Allow90degTurns())) {
+		if (IsSafeWaitingPosition((Train *)Yapf().GetVehicle(), tile, td, true, !TrackFollower::Allow90degTurns())) {
 			m_res_dest = tile;
 			m_res_dest_td = td;
 			return false;   // Stop iterating segment
@@ -149,7 +149,7 @@
 		}
 
 		/* Don't bother if the target is reserved. */
-		if (!IsWaitingPositionFree(Yapf().GetVehicle(), m_res_dest, m_res_dest_td)) return false;
+		if (!IsWaitingPositionFree((Train *)Yapf().GetVehicle(), m_res_dest, m_res_dest_td)) return false;
 
 		for (Node *node = m_res_node; node->m_parent != NULL; node = node->m_parent) {
 			node->IterateTiles(Yapf().GetVehicle(), Yapf(), *this, &CYapfReserveTrack<Types>::ReserveSingleTrack);
@@ -411,7 +411,7 @@
 		if (target != NULL) target->tile = INVALID_TILE;
 
 		/* set origin and destination nodes */
-		PBSTileInfo origin = FollowTrainReservation(v);
+		PBSTileInfo origin = FollowTrainReservation((Train *)v);
 		Yapf().SetOrigin(origin.tile, origin.trackdir, INVALID_TILE, INVALID_TRACKDIR, 1, true);
 		Yapf().SetDestination(v);
 
@@ -534,10 +534,11 @@
 	return td_ret;
 }
 
-bool YapfCheckReverseTrain(const Vehicle *v)
+bool YapfCheckReverseTrain(const Vehicle *vt)
 {
+	Train *v = (Train *)vt;
 	/* last wagon */
-	const Vehicle *last_veh = GetLastVehicleInChain(v);
+	const Train *last_veh = (Train *)GetLastVehicleInChain(v);
 
 	/* get trackdirs of both ends */
 	Trackdir td = v->GetVehicleTrackdir();
@@ -601,7 +602,7 @@
 
 	const Vehicle *last_veh = GetLastVehicleInChain(v);
 
-	PBSTileInfo origin = FollowTrainReservation(v);
+	PBSTileInfo origin = FollowTrainReservation((Train *)v);
 	TileIndex last_tile = last_veh->tile;
 	Trackdir td_rev = ReverseTrackdir(last_veh->GetVehicleTrackdir());