Changeset - r11980:193f7a6b6e37
[Not reviewed]
src/ai/api/ai_vehicle.cpp
Show inline comments
 
@@ -26,13 +26,13 @@
 
/* static */ int32 AIVehicle::GetNumWagons(VehicleID vehicle_id)
 
{
 
	if (!IsValidVehicle(vehicle_id)) return -1;
 

	
 
	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++;
 
	}
 

	
 
	return num;
 
}
 

	
 
@@ -82,17 +82,17 @@
 
{
 
	EnforcePrecondition(false, IsValidVehicle(source_vehicle_id) && source_wagon < GetNumWagons(source_vehicle_id));
 
	EnforcePrecondition(false, dest_vehicle_id == -1 || (IsValidVehicle(dest_vehicle_id) && dest_wagon < GetNumWagons(dest_vehicle_id)));
 
	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);
 
	}
 

	
 
	return AIObject::DoCommand(0, v->index | ((w == NULL ? INVALID_VEHICLE : w->index) << 16), move_attached_wagons ? 1 : 0, CMD_MOVE_RAIL_VEHICLE);
 
}
 

	
 
@@ -133,13 +133,13 @@
 

	
 
/* static */ bool AIVehicle::_SellWagonInternal(VehicleID vehicle_id, int wagon, bool sell_attached_wagons)
 
{
 
	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);
 
}
 

	
 
/* static */ bool AIVehicle::SellWagon(VehicleID vehicle_id, int wagon)
 
@@ -240,13 +240,13 @@
 
{
 
	if (!IsValidVehicle(vehicle_id)) return INVALID_ENGINE;
 
	if (wagon >= GetNumWagons(vehicle_id)) return INVALID_ENGINE;
 

	
 
	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;
 
}
 

	
 
/* static */ int32 AIVehicle::GetUnitNumber(VehicleID vehicle_id)
 
{
 
@@ -278,13 +278,13 @@
 
{
 
	if (!IsValidVehicle(vehicle_id)) return -1;
 
	if (wagon >= GetNumWagons(vehicle_id)) return -1;
 

	
 
	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;
 
}
 

	
 
/* static */ int32 AIVehicle::GetMaxAge(VehicleID vehicle_id)
 
{
src/articulated_vehicles.cpp
Show inline comments
 
@@ -205,13 +205,13 @@ bool IsArticulatedVehicleCarryingDiffere
 
				return true;
 
			}
 
		}
 

	
 
		switch (v->type) {
 
			case VEH_TRAIN:
 
				v = (EngineHasArticPart(v) ? GetNextArticPart(v) : NULL);
 
				v = (EngineHasArticPart((Train *)v) ? GetNextArticPart((Train *)v) : NULL);
 
				break;
 

	
 
			case VEH_ROAD:
 
				v = (RoadVehHasArticPart(v) ? v->Next() : NULL);
 
				break;
 

	
 
@@ -253,13 +253,13 @@ void CheckConsistencyOfArticulatedVehicl
 

	
 
		assert(v->cargo_type < NUM_CARGO);
 
		real_default_capacity[v->cargo_type] += v->cargo_cap;
 

	
 
		switch (v->type) {
 
			case VEH_TRAIN:
 
				v = (EngineHasArticPart(v) ? GetNextArticPart(v) : NULL);
 
				v = (EngineHasArticPart((Train *)v) ? GetNextArticPart((Train *)v) : NULL);
 
				break;
 

	
 
			case VEH_ROAD:
 
				v = (RoadVehHasArticPart(v) ? v->Next() : NULL);
 
				break;
 

	
 
@@ -304,31 +304,33 @@ void AddArticulatedParts(Vehicle *first,
 

	
 
		Vehicle *previous = u;
 
		const Engine *e_artic = Engine::Get(engine_type);
 
		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;
 
				RoadVehicle *rv = new RoadVehicle();
 
				rv->subtype = 0;
 
				previous->SetNext(u);
src/autoreplace_cmd.cpp
Show inline comments
 
@@ -89,37 +89,37 @@ bool CheckAutoreplaceValidity(EngineID f
 
 */
 
static void TransferCargo(Vehicle *old_veh, Vehicle *new_head, bool part_of_chain)
 
{
 
	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;
 

	
 
			uint amount = min(src->cargo.Count(), dest->cargo_cap - dest->cargo.Count());
 
			if (amount <= 0) continue;
 

	
 
			src->cargo.MoveTo(&dest->cargo, amount);
 
		}
 
	}
 

	
 
	/* 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);
 
}
 

	
 
/**
 
 * Tests whether refit orders that applied to v will also apply to the new vehicle type
 
 * @param v The vehicle to be replaced
 
 * @param engine_type The type we want to replace with
 
@@ -266,13 +266,13 @@ static CommandCost BuildReplacementVehic
 
	if (refit_cargo != CT_NO_REFIT) {
 
		cost.AddCost(DoCommand(0, new_veh->index, refit_cargo, DC_EXEC, GetCmdRefitVeh(new_veh)));
 
		assert(cost.Succeeded()); // This should be ensured by GetNewCargoTypeForReplace()
 
	}
 

	
 
	/* 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);
 
	}
 

	
 
	return cost;
 
}
 

	
 
@@ -403,50 +403,50 @@ static CommandCost ReplaceChain(Vehicle 
 

	
 
	if (old_head->type == VEH_TRAIN) {
 
		/* Store the length of the old vehicle chain, rounded up to whole tiles */
 
		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
 
		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);
 

	
 
			/* 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;
 

	
 
					if (last_engine == NULL) last_engine = append;
 
					cost.AddCost(MoveVehicle(append, new_head, DC_EXEC, false));
 
					if (cost.Failed()) break;
 
@@ -535,16 +535,16 @@ static CommandCost ReplaceChain(Vehicle 
 

	
 
			/* If we are not in DC_EXEC undo everything, i.e. rearrange old vehicles.
 
			 * We do this from back to front, so that the head of the temporary vehicle chain does not change all the time.
 
			 * 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);
 
					assert(ret.Succeeded());
 
				}
 
			}
 
@@ -629,13 +629,13 @@ CommandCost CmdAutoreplaceVehicle(TileIn
 

	
 
	/* Test whether any replacement is set, before issuing a whole lot of commands that would end in nothing changed */
 
	Vehicle *w = v;
 
	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) {
 
		bool was_stopped = free_wagon || ((v->vehstatus & VS_STOPPED) != 0);
 

	
 
		/* Stop the vehicle */
src/elrail.cpp
Show inline comments
 
@@ -552,28 +552,32 @@ bool SettingsDisableElrail(int32 p1)
 
	}
 

	
 
	/* when disabling elrails, make sure that all existing trains can run on
 
	 *  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);
 
			}
 
		}
 
	}
 

	
 
	/* Fix the total power and acceleration for trains */
 
	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);
 
		}
 
	}
 

	
 
	FOR_ALL_COMPANIES(c) c->avail_railtypes = GetCompanyRailtypes(c->index);
 

	
 
	/* This resets the _last_built_railtype, which will be invalid for electric
src/newgrf_engine.cpp
Show inline comments
 
@@ -665,21 +665,22 @@ static uint32 VehicleGetVariable(const R
 

	
 
		case 0xFE:
 
		case 0xFF: {
 
			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);
 
				bool is_electric = powered && u->u.rail.railtype == RAILTYPE_ELECTRIC;
 

	
 
				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);
 

	
 
			return variable == 0xFE ? modflags : GB(modflags, 8, 8);
 
		}
 
	}
 
@@ -732,13 +733,13 @@ static uint32 VehicleGetVariable(const R
 
		case 0x44: return Clamp(v->build_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR;
 
		case 0x45: return v->unitnumber;
 
		case 0x46: return Engine::Get(v->engine_type)->internal_id;
 
		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;
 
		case 0x4B: return v->breakdown_ctr;
 
		case 0x4C: return v->breakdown_delay;
 
		case 0x4D: return v->breakdown_chance;
 
@@ -763,26 +764,27 @@ static uint32 VehicleGetVariable(const R
 
		case 0x7A: return v->random_bits;
 
		case 0x7B: return v->waiting_triggers;
 
	}
 

	
 
	/* 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;
 
			switch (variable - 0x80) {
 
				case 0x62: return rv->state;
 
				case 0x64: return rv->blocked_ctr;
src/npf.cpp
Show inline comments
 
@@ -13,12 +13,13 @@
 
#include "functions.h"
 
#include "vehicle_base.h"
 
#include "tunnelbridge.h"
 
#include "pbs.h"
 
#include "settings_type.h"
 
#include "pathfind.h"
 
#include "train.h"
 

	
 
static AyStar _npf_aystar;
 

	
 
/* The cost of each trackdir. A diagonal piece is the full NPF_TILE_LENGTH,
 
 * the shorter piece is sqrt(2)/2*NPF_TILE_LENGTH =~ 0.7071
 
 */
 
@@ -421,13 +422,13 @@ static int32 NPFFindDepot(AyStar *as, Op
 
		AYSTAR_FOUND_END_NODE : AYSTAR_DONE;
 
}
 

	
 
/** 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) &&
 
		IsWaitingPositionFree(v, current->path.node.tile, current->path.node.direction, _settings_game.pf.forbid_90_deg) ?
 
			AYSTAR_FOUND_END_NODE : AYSTAR_DONE;
 
}
 
@@ -455,13 +456,13 @@ static int32 NPFFindStationOrTile(AyStar
 
 * Find the node containing the first signal on the path.
 
 *
 
 * If the first signal is on the very first two tiles of the path,
 
 * 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;
 

	
 
	for(; path->parent != NULL; path = path->parent) {
 
		if (IsSafeWaitingPosition(v, path->node.tile, path->node.direction, true, _settings_game.pf.forbid_90_deg)) {
 
@@ -502,13 +503,13 @@ static void NPFSaveTargetData(AyStar *as
 
	ftd->best_bird_dist = 0;
 
	ftd->node = current->path.node;
 
	ftd->res_okay = false;
 

	
 
	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;
 

	
 
		/* If the target is a station skip to platform end. */
 
		if (IsRailwayStationTile(target->node.tile)) {
 
@@ -1050,13 +1051,13 @@ NPFFoundTargetData NPFRouteToDepotTrialE
 
	if (result.best_bird_dist != 0) {
 
		DEBUG(npf, 1, "Could not find route to any depot from tile 0x%X.", tile);
 
	}
 
	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);
 

	
 
	NPFFindStationOrTileData fstd;
 
	fstd.v = v;
 
	fstd.reserve_path = true;
src/npf.h
Show inline comments
 
@@ -112,13 +112,13 @@ NPFFoundTargetData NPFRouteToDepotBreadt
 
 * of choices and accurate heuristics, such as water. */
 
NPFFoundTargetData NPFRouteToDepotTrialError(TileIndex tile, Trackdir trackdir, bool ignore_start_tile, TransportType type, uint sub_type, Owner owner, RailTypes railtypes);
 

	
 
/**
 
 * 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);
 

	
 

	
 
/*
src/openttd.cpp
Show inline comments
 
@@ -28,12 +28,13 @@
 
#include "command_func.h"
 
#include "news_func.h"
 
#include "fileio_func.h"
 
#include "fios.h"
 
#include "aircraft.h"
 
#include "roadveh.h"
 
#include "train.h"
 
#include "console_func.h"
 
#include "screenshot.h"
 
#include "network/network.h"
 
#include "network/network_func.h"
 
#include "signs_base.h"
 
#include "ai/ai.hpp"
 
@@ -1129,13 +1130,13 @@ void StateGameLoop()
 
						for (Vehicle *u = v; u != NULL; u = u->Next()) length++;
 

	
 
						VehicleRail *wagons = MallocT<VehicleRail>(length);
 
						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()) {
 
							if (memcmp(&wagons[length], &u->u.rail, sizeof(VehicleRail)) != 0) {
 
								DEBUG(desync, 2, "cache mismatch: vehicle %i, company %i, unit number %i, wagon %i\n", v->index, (int)v->owner, v->unitnumber, length);
 
							}
src/pbs.cpp
Show inline comments
 
@@ -219,42 +219,45 @@ static PBSTileInfo FollowReservation(Own
 

	
 
/**
 
 * Helper struct for finding the best matching vehicle on a specific track.
 
 */
 
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) {}
 
};
 

	
 
/** Callback for Has/FindVehicleOnPos to find a train on a specific track. */
 
static Vehicle *FindTrainOnTrackEnum(Vehicle *v, void *data)
 
{
 
	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;
 
}
 

	
 
/**
 
 * Follow a train reservation to the last tile.
 
 *
 
 * @param v the vehicle
 
 * @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);
 

	
 
	TileIndex tile = v->tile;
 
	Trackdir  trackdir = v->GetVehicleTrackdir();
 

	
 
@@ -271,13 +274,13 @@ PBSTileInfo FollowTrainReservation(const
 
 * Find the train which has reserved a specific path.
 
 *
 
 * @param tile A tile on the path.
 
 * @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);
 

	
 
	RailTypes rts = GetRailTypeInfo(GetTileRailType(tile))->compatible_railtypes;
 

	
 
@@ -317,13 +320,13 @@ Vehicle *GetTrainForReservation(TileInde
 
 * @param tile The tile
 
 * @param trackdir The trackdir to test
 
 * @param include_line_end Should end-of-line tiles be considered safe?
 
 * @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;
 

	
 
	if (IsTileType(tile, MP_RAILWAY)) {
 
		/* For non-pbs signals, stop on the signal tile. */
 
		if (HasSignalOnTrackdir(tile, trackdir) && !IsPbsSignal(GetSignalType(tile, TrackdirToTrack(trackdir)))) return true;
 
@@ -357,13 +360,13 @@ bool IsSafeWaitingPosition(const Vehicle
 
 * @param v the vehicle to test for
 
 * @param tile The tile
 
 * @param trackdir The trackdir to test
 
 * @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);
 

	
 
	/* Tile reserved? Can never be a free waiting position. */
 
	if (TrackOverlapsTracks(reserved, track)) return false;
src/pbs.h
Show inline comments
 
@@ -24,17 +24,17 @@ struct PBSTileInfo {
 
	bool      okay;      ///< True if tile is a safe waiting position, false otherwise.
 

	
 
	PBSTileInfo() : tile(INVALID_TILE), trackdir(INVALID_TRACKDIR), okay(false) {}
 
	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.
 
 *
 
 * @param tile the tile
 
 * @param tracks the tracks to test
src/rail_cmd.cpp
Show inline comments
 
@@ -89,13 +89,14 @@ const byte _track_sloped_sprites[14] = {
 
Vehicle *EnsureNoTrainOnTrackProc(Vehicle *v, void *data)
 
{
 
	TrackBits rail_bits = *(TrackBits *)data;
 

	
 
	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;
 
}
 

	
 
/**
 
@@ -453,13 +454,13 @@ CommandCost CmdRemoveSingleRail(TileInde
 
	/* Need to read tile owner now because it may change when the rail is removed
 
	 * Also, in case of floods, _current_company != owner
 
	 * There may be invalid tiletype even in exec run (when removing long track),
 
	 * 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: {
 
			if (!IsLevelCrossing(tile) ||
 
					GetCrossingRailBits(tile) != trackbit ||
 
					(_current_company != OWNER_WATER && !CheckTileOwnership(tile)) ||
 
@@ -874,13 +875,13 @@ CommandCost CmdBuildSingleSignal(TileInd
 
			/* it is free to change orientation/pre-exit-combo signals */
 
			cost = CommandCost();
 
		}
 
	}
 

	
 
	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. */
 
		if (HasReservedTracks(tile, TrackToTrackBits(track))) {
 
			v = GetTrainForReservation(tile, track);
 
			if (v != NULL) FreeTrainTrackReservation(v);
 
@@ -1181,13 +1182,13 @@ CommandCost CmdRemoveSingleSignal(TileIn
 

	
 
	/* Only water can remove signals from anyone */
 
	if (_current_company != OWNER_WATER && !CheckTileOwnership(tile)) return CMD_ERROR;
 

	
 
	/* Do it? */
 
	if (flags & DC_EXEC) {
 
		Vehicle *v = NULL;
 
		Train *v = NULL;
 
		if (HasReservedTracks(tile, TrackToTrackBits(track))) {
 
			v = GetTrainForReservation(tile, track);
 
		}
 
		SetPresentSignals(tile, GetPresentSignals(tile) & ~SignalOnTrack(track));
 

	
 
		/* removed last signal from tile? */
 
@@ -1231,13 +1232,13 @@ CommandCost CmdRemoveSignalTrack(TileInd
 
Vehicle *UpdateTrainPowerProc(Vehicle *v, void *data)
 
{
 
	/* Similiar checks as in TrainPowerChanged() */
 

	
 
	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;
 
}
 

	
 
/** Convert one rail type to the other. You can convert normal rail to
 
@@ -1293,23 +1294,23 @@ CommandCost CmdConvertRail(TileIndex til
 
			/* Converting to the same type or converting 'hidden' elrail -> rail */
 
			if (type == totype || (_settings_game.vehicle.disable_elrails && totype == RAILTYPE_RAIL && type == RAILTYPE_ELECTRIC)) continue;
 

	
 
			/* 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 */
 
			if (tt != MP_TUNNELBRIDGE) {
 
				if (!IsCompatibleRail(type, totype) && !EnsureNoVehicleOnGround(tile)) continue;
 
				if (flags & DC_EXEC) { // we can safely convert, too
 
					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);
 
							*vehicles_affected.Append() = v;
 
						}
 
					}
 
@@ -1369,13 +1370,13 @@ CommandCost CmdConvertRail(TileIndex til
 
					if (!IsCompatibleRail(GetRailType(tile), totype) &&
 
							HasVehicleOnTunnelBridge(tile, endtile)) continue;
 

	
 
					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);
 
								*vehicles_affected.Append() = v;
 
							}
 
						}
 
@@ -1429,13 +1430,13 @@ static CommandCost RemoveTrainDepot(Tile
 
		return CMD_ERROR;
 

	
 
	if (flags & DC_EXEC) {
 
		/* 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));
 
			if (v != NULL) FreeTrainTrackReservation(v);
 
		}
 

	
 
@@ -2447,21 +2448,23 @@ int TicksToLeaveDepot(const Vehicle *v)
 

	
 
	return 0; // make compilers happy
 
}
 

	
 
/** 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;
 
	DiagDirection dir;
 
	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);
 

	
 
	/* calculate the point where the following wagon should be activated
 
	 * this depends on the length of the current vehicle */
src/saveload/afterload.cpp
Show inline comments
 
@@ -909,13 +909,13 @@ bool AfterLoadGame()
 
			} else if (v->z_pos > GetSlopeZ(v->x_pos, v->y_pos)) {
 
				v->tile = GetNorthernBridgeEnd(v->tile);
 
			} else {
 
				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;
 
			}
 
		}
 
	}
 

	
 
@@ -925,13 +925,13 @@ bool AfterLoadGame()
 
		RailType min_rail = RAILTYPE_ELECTRIC;
 

	
 
		FOR_ALL_VEHICLES(v) {
 
			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;
 
			}
 
		}
 

	
 
		/* .. so we convert the entire map from normal to elrail (so maintain "fairness") */
 
		for (TileIndex t = 0; t < map_size; t++) {
 
@@ -961,13 +961,13 @@ bool AfterLoadGame()
 
				default:
 
					break;
 
			}
 
		}
 

	
 
		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);
 
		}
 

	
 
	}
 

	
 
	/* In version 16.1 of the savegame a company can decide if trains, which get
 
	 * replaced, shall keep their old length. In all prior versions, just default
 
@@ -1697,15 +1697,16 @@ bool AfterLoadGame()
 
			}
 
		}
 
	}
 

	
 
	/* 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) {
 
					TryReserveRailTrack(v->tile, TrackBitsToTrack(v->u.rail.track));
 
				}
 
			}
src/saveload/oldloader_sl.cpp
Show inline comments
 
@@ -1312,13 +1312,13 @@ bool LoadOldVehicle(LoadgameState *ls, i
 
						  0,   2,   4,   4,   8,  10,  12,  14,  16,  18,  20,  22,  40,  42,  44,  46,
 
						 48,  52,  54,  66,  68,  70,  72,  74,  76,  78,  80,  82,  84,  86, 120, 122,
 
						124, 126, 128, 130, 132, 134, 136, 138, 140
 
					};
 
					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;
 
				}
 

	
 
				case VEH_ROAD:
 
					if (v->spritenum >= 22) v->spritenum += 12;
 
					break;
src/saveload/vehicle_sl.cpp
Show inline comments
 
@@ -21,13 +21,13 @@
 
void ConnectMultiheadedTrains()
 
{
 
	Vehicle *v;
 

	
 
	FOR_ALL_VEHICLES(v) {
 
		if (v->type == VEH_TRAIN) {
 
			v->u.rail.other_multiheaded_part = NULL;
 
			((Train *)v)->u.rail.other_multiheaded_part = NULL;
 
		}
 
	}
 

	
 
	FOR_ALL_VEHICLES(v) {
 
		if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) {
 
			/* Two ways to associate multiheaded parts to each other:
 
@@ -42,25 +42,25 @@ void ConnectMultiheadedTrains()
 
			 * Note: The multiheaded parts need to be matched exactly like they are matched on the server, else desyncs will occur.
 
			 *   This is why two matching strategies are needed.
 
			 */
 

	
 
			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)) {
 
					if (!IsTrainEngine(u)) {
 
						/* we got a rear car without a front car. We will convert it to a front one */
 
						SetTrainEngine(u);
 
						u->spritenum--;
 
					}
 

	
 
					/* 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;
 

	
 
							/* we found a car to partner with this engine. Now we will make sure it face the right way */
 
							if (IsTrainEngine(w)) {
 
@@ -315,14 +315,14 @@ void AfterLoadVehicles(bool part_of_load
 
	CheckValidVehicles();
 

	
 
	FOR_ALL_VEHICLES(v) {
 
		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);
 
		}
 
	}
 

	
 
	/* Stop non-front engines */
src/settings.cpp
Show inline comments
 
@@ -694,13 +694,13 @@ static bool DeleteSelectStationWindow(in
 

	
 
static bool UpdateConsists(int32 p1)
 
{
 
	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;
 
}
 

	
 
/* Check service intervals of vehicles, p1 is value of % or day based servicing */
 
static bool CheckInterval(int32 p1)
 
@@ -744,13 +744,13 @@ static bool EngineRenewMoneyUpdate(int32
 

	
 
static bool TrainAccelerationModelChanged(int32 p1)
 
{
 
	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;
 
}
 

	
 
static bool DragSignalsDensityChanged(int32)
src/signal.cpp
Show inline comments
 
@@ -4,14 +4,14 @@
 

	
 
#include "stdafx.h"
 
#include "debug.h"
 
#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 */
 
enum {
 
	SIG_TBU_SIZE    =  64, ///< number of signals entering to block
 
	SIG_TBD_SIZE    = 256, ///< number of intersections - open nodes in current block
 
@@ -182,13 +182,13 @@ static SmallSet<DiagDirection, SIG_TBD_S
 
static SmallSet<DiagDirection, SIG_GLOB_SIZE> _globset("_globset"); ///< set of places to be updated in following runs
 

	
 

	
 
/** 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;
 
}
 

	
 

	
 
/**
src/station_cmd.cpp
Show inline comments
 
@@ -1012,21 +1012,21 @@ CommandCost CmdBuildRailroadStation(Tile
 

	
 
		layout_ptr = AllocaM(byte, numtracks * plat_len);
 
		GetStationLayout(layout_ptr, numtracks, plat_len, statspec);
 

	
 
		numtracks_orig = numtracks;
 

	
 
		SmallVector<Vehicle*, 4> affected_vehicles;
 
		SmallVector<Train*, 4> affected_vehicles;
 
		do {
 
			TileIndex tile = tile_org;
 
			int w = plat_len;
 
			do {
 
				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;
 
						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(v->GetVehicleTrackdir())), false);
 
@@ -1060,13 +1060,13 @@ CommandCost CmdBuildRailroadStation(Tile
 
			YapfNotifyTrackLayoutChange(tile_org, track);
 
			tile_org += tile_delta ^ TileDiffXY(1, 1); // perpendicular to tile_delta
 
		} while (--numtracks);
 

	
 
		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()) ;
 
			if (IsRailwayStationTile(v->tile)) SetRailwayStationPlatformReservation(v->tile, TrackdirToExitdir(ReverseTrackdir(v->GetVehicleTrackdir())), true);
 
		}
 

	
 
@@ -1193,13 +1193,13 @@ CommandCost CmdRemoveFromRailroadStation
 

	
 
		if (flags & DC_EXEC) {
 
			/* read variables before the station tile is removed */
 
			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);
 
				if (v != NULL) {
 
					/* Free train reservation. */
 
					FreeTrainTrackReservation(v);
 
@@ -1277,13 +1277,13 @@ static CommandCost RemoveRailroadStation
 
					return CMD_ERROR;
 
				cost.AddCost(_price.remove_rail_station);
 
				if (flags & DC_EXEC) {
 
					/* 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);
 
					}
 
					DoClearSquare(tile);
 
					AddTrackToSignalBuffer(tile, track, owner);
 
@@ -2618,13 +2618,13 @@ static VehicleEnterTileStatus VehicleEnt
 
	if (v->type == VEH_TRAIN) {
 
		if (!v->current_order.ShouldStopAtStation(v, station_id)) return VETSB_CONTINUE;
 
		if (!IsRailwayStation(tile) || !IsFrontEngine(v)) return VETSB_CONTINUE;
 

	
 
		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
 
		 * of the platform. Station ahead 'includes' the current tile where the
 
		 * vehicle is on, so we need to substract that. */
 
		if (!IsInsideBS(stop + station_ahead, station_length, TILE_SIZE)) return VETSB_CONTINUE;
src/train.h
Show inline comments
 
@@ -6,12 +6,13 @@
 
#define TRAIN_H
 

	
 
#include "stdafx.h"
 
#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
 
 * This is an enum to tell what bit to access as it is a bitmask
 
 */
 
enum TrainSubtype {
 
@@ -199,111 +200,40 @@ static inline void ClearMultiheaded(Vehi
 
static inline bool EngineHasArticPart(const Vehicle *v)
 
{
 
	assert(v->type == VEH_TRAIN);
 
	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.
 
 */
 
static inline bool IsRearDualheaded(const Vehicle *v)
 
{
 
	assert(v->type == VEH_TRAIN);
 
	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.
 
 * You create a Vehicle using AllocateVehicle, so it is added to the pool
 
 * and you reinitialize that to a Train using:
 
 *   v = new (v) Train();
 
@@ -331,9 +261,90 @@ struct Train : public Vehicle {
 
	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);
 
	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 */
src/train_cmd.cpp
Show inline comments
 
@@ -34,18 +34,18 @@
 
#include "gamelog.h"
 
#include "network/network.h"
 

	
 
#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};
 

	
 

	
 
/**
 
@@ -82,18 +82,18 @@ byte FreightWagonMult(CargoID cargo)
 

	
 

	
 
/**
 
 * 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 */
 
		if (!IsArticulatedPart(u)) {
 
			bool engine_has_power = HasPowerOnRail(u->u.rail.railtype, railtype);
 

	
 
@@ -131,17 +131,17 @@ void TrainPowerChanged(Vehicle *v)
 

	
 
/**
 
 * Recalculates the cached weight of a train and its vehicles. Should be called each time the cargo on
 
 * 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. */
 
		if (!IsArticulatedPart(u)) {
 
			/* vehicle weight is the sum of the weight of the vehicle and the weight of its cargo */
 
			vweight += GetVehicleProperty(u, 0x16, RailVehInfo(u->engine_type)->weight);
 
@@ -168,13 +168,13 @@ static void TrainCargoChanged(Vehicle *v
 

	
 

	
 
/** Logs a bug in GRF and shows a warning message if this
 
 * 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);
 
	uint32 grfid = engine->grffile->grfid;
 
	GRFConfig *grfconfig = GetGRFConfig(grfid);
 
	if (GamelogGRFBugReverse(grfid, engine->internal_id) || !HasBit(grfconfig->grf_bugs, GBUG_VEH_LENGTH)) {
 
@@ -186,13 +186,13 @@ static void RailVehicleLengthChanged(con
 
void CheckTrainsLengths()
 
{
 
	const Vehicle *v;
 

	
 
	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) ||
 
							(w->u.rail.track == TRACK_BIT_DEPOT && TicksToLeaveDepot(u) <= 0)) {
 
						SetDParam(0, v->index);
 
						SetDParam(1, v->owner);
 
@@ -210,13 +210,13 @@ void CheckTrainsLengths()
 
 * Recalculates the cached stuff of a train. Should be called each time a vehicle is added
 
 * to/removed from the chain, and when the game is loaded.
 
 * Note: this needs to be called too for 'wagon chains' (in the depot, without an engine)
 
 * @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;
 

	
 
	assert(v->type == VEH_TRAIN);
 
	assert(IsFrontEngine(v) || IsFreeWagon(v));
 

	
 
@@ -224,13 +224,13 @@ void TrainConsistChanged(Vehicle *v, boo
 
	EngineID first_engine = IsFrontEngine(v) ? v->engine_type : INVALID_ENGINE;
 
	v->u.rail.cached_total_length = 0;
 
	v->u.rail.compatible_railtypes = RAILTYPES_NONE;
 

	
 
	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. */
 
		assert(u->First() == v);
 

	
 
		/* update the 'first engine' */
 
@@ -241,19 +241,19 @@ void TrainConsistChanged(Vehicle *v, boo
 

	
 
		/* Set user defined data to its default value */
 
		u->u.rail.user_def_data = rvi_u->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()) {
 
		/* 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;
 

	
 
		if (!HasBit(EngInfo(u->engine_type)->misc_flags, EF_RAIL_TILTS)) train_can_tilt = false;
 

	
 
		/* Cache wagon override sprite group. NULL is returned if there is none */
 
@@ -361,13 +361,13 @@ enum AccelType {
 
 * @param tile           the tile where the vehicle currently is
 
 * @param v              the vehicle to get the stop location of
 
 * @param station_ahead  'return' the amount of 1/16th tiles in front of the train
 
 * @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;
 
	*station_length = st->GetPlatformLength(tile) * TILE_SIZE;
 

	
 
	/* Default to the middle of the station for stations stops that are not in
 
@@ -401,13 +401,13 @@ int GetTrainStopLocation(StationID stati
 
	/* Substract half the front vehicle length of the train so we get the real
 
	 * stop location of the train. */
 
	return stop - (v->u.rail.cached_veh_length + 1) / 2;
 
}
 

	
 
/** 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;
 
	int speed = v->cur_speed * 10 / 16; // km-ish/h -> mp/h
 
	int curvecount[2] = {0, 0};
 

	
 
@@ -493,13 +493,13 @@ static int GetTrainAcceleration(Vehicle 
 
	int power = v->u.rail.cached_power * 746;
 
	max_speed = min(max_speed, v->u.rail.cached_max_speed);
 

	
 
	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;
 

	
 
		if (u->u.rail.track == TRACK_BIT_DEPOT) max_speed = min(max_speed, 61);
 

	
 
		if (HasBit(u->u.rail.flags, VRF_GOINGUP)) {
 
@@ -553,13 +553,13 @@ static int GetTrainAcceleration(Vehicle 
 
		return (force - resistance) / (mass * 2);
 
	} else {
 
		return min(-force - resistance, -10000) / mass;
 
	}
 
}
 

	
 
void UpdateTrainAcceleration(Vehicle *v)
 
void UpdateTrainAcceleration(Train *v)
 
{
 
	assert(IsFrontEngine(v));
 

	
 
	v->max_speed = v->u.rail.cached_max_speed;
 

	
 
	uint power = v->u.rail.cached_power;
 
@@ -657,13 +657,13 @@ static CommandCost CmdBuildRailWagon(Eng
 
					!HASBITS(w->vehstatus, VS_CRASHED)) {
 
				u = GetLastVehicleInChain(w);
 
				break;
 
			}
 
		}
 

	
 
		Vehicle *v = new Train();
 
		Train *v = new Train();
 
		v->spritenum = rvi->image_index;
 

	
 
		v->engine_type = engine;
 

	
 
		DiagDirection dir = GetRailDepotDirection(tile);
 

	
 
@@ -722,30 +722,30 @@ static CommandCost CmdBuildRailWagon(Eng
 
	}
 

	
 
	return value;
 
}
 

	
 
/** 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;
 
		}
 
	}
 
}
 

	
 
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;
 
	u->owner = v->owner;
 
	u->tile = v->tile;
 
	u->x_pos = v->x_pos;
 
@@ -820,13 +820,13 @@ CommandCost CmdBuildRailVehicle(TileInde
 

	
 
	if (flags & DC_EXEC) {
 
		DiagDirection dir = GetRailDepotDirection(tile);
 
		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;
 
		v->owner = _current_company;
 
		v->x_pos = x;
 
		v->y_pos = y;
 
@@ -898,13 +898,13 @@ CommandCost CmdBuildRailVehicle(TileInde
 
	return value;
 
}
 

	
 

	
 
/* 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;
 

	
 
	/* check if stopped in a depot */
 
	if (!IsRailDepotTile(tile) || v->cur_speed != 0) return -1;
 

	
 
@@ -923,30 +923,30 @@ int CheckTrainInDepot(const Vehicle *v, 
 
	}
 

	
 
	return count;
 
}
 

	
 
/* 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;
 
}
 

	
 
/**
 
 * Unlink a rail wagon from the consist.
 
 * @param v Vehicle to remove.
 
 * @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) {
 
		v = GetNextVehicle(v);
 
		if (v == NULL) return NULL;
 

	
 
@@ -957,71 +957,71 @@ static Vehicle *UnlinkWagon(Vehicle *v, 
 
		 * and the last articulated part is just before the next vehicle (v). */
 
		v->Previous()->SetNext(NULL);
 

	
 
		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;
 
	TileIndex tile = src->tile;
 

	
 
	FOR_ALL_VEHICLES(dst) {
 
		if (dst->type == VEH_TRAIN && IsFreeWagon(dst) && dst->tile == tile && !HASBITS(dst->vehstatus, VS_CRASHED)) {
 
			/* check so all vehicles in the line have the same engine. */
 
			Vehicle *v = dst;
 

	
 
			while (v->engine_type == eng) {
 
				v = v->Next();
 
				if (v == NULL) return dst;
 
				if (v == NULL) return (Train *)dst;
 
			}
 
		}
 
	}
 

	
 
	return NULL;
 
}
 

	
 
/*
 
 * 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);
 
	ClearFreeWagon(v);
 
	ClearFrontEngine(v);
 
}
 

	
 
/*
 
 * 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;
 

	
 
	assert(IsFrontEngine(v));
 

	
 
	for (; v != NULL; v = GetNextVehicle(v)) {
 
		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;
 
		AddWagonToConsist(v->u.rail.other_multiheaded_part, u);
 
	}
 
}
 
@@ -1037,42 +1037,45 @@ static void NormaliseTrainConsist(Vehicl
 
 */
 
CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	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 */
 
	while (IsArticulatedPart(src)) src = src->Previous();
 
	if (dst != NULL) {
 
		while (IsArticulatedPart(dst)) dst = dst->Previous();
 
	}
 

	
 
	/* don't move the same vehicle.. */
 
	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;
 
		/* Now deal with articulated part of destination wagon */
 
		dst = GetLastEnginePart(dst);
 
	} else {
 
@@ -1102,13 +1105,13 @@ CommandCost CmdMoveRailVehicle(TileIndex
 
				if (dst_len < 0) return_cmd_error(STR_ERROR_TRAINS_CAN_ONLY_BE_ALTERED_INSIDE_A_DEPOT);
 
			}
 

	
 
			/* 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 {
 
				/* If moving only one vehicle, just count that. */
 
				src_len = 1;
 
			}
 
@@ -1148,13 +1151,13 @@ CommandCost CmdMoveRailVehicle(TileIndex
 
	 * chain. This can easily be done by checking whether the first vehicle
 
	 * of the source chain is in the destination chain as the Next/Previous
 
	 * pointers always make a doubly linked list of it where the assumption
 
	 * 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
 
	 * only reordering the vehicles, thus not attaching a new vehicle.
 
	 * Therefor the 'allow wagon attach' callback does not need to be
 
	 * called. If it would be called strange things would happen because
 
@@ -1168,18 +1171,18 @@ CommandCost CmdMoveRailVehicle(TileIndex
 
		 * that we have to test one wagon, attach it to the train and then test
 
		 * the next wagon till we have reached the end. We have to restore it
 
		 * to the state it was before we 'tried' attaching the train when the
 
		 * 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 */
 
			if (!IsArticulatedPart(next_to_attach) && !IsRearDualheaded(next_to_attach)) {
 
				/* Back up and clear the first_engine data to avoid using wagon override group */
 
				EngineID first_engine = next_to_attach->u.rail.first_engine;
 
@@ -1221,13 +1224,13 @@ CommandCost CmdMoveRailVehicle(TileIndex
 
			/*
 
			 * Adding a next wagon to the chain so we can test the other wagons.
 
			 * First 'take' the first wagon from 'next_to_attach' and move it
 
			 * 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);
 
			dst_tail->SetNext(to_add);
 
			dst_tail = dst_tail->Next();
 
		}
 
@@ -1256,13 +1259,13 @@ CommandCost CmdMoveRailVehicle(TileIndex
 
			}
 
		}
 

	
 
		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 {
 
				InvalidateWindowData(WC_VEHICLE_DEPOT, src_head->tile); // We removed a line
 
				src_head = NULL;
 
			}
 
@@ -1315,13 +1318,13 @@ CommandCost CmdMoveRailVehicle(TileIndex
 
				ClearFreeWagon(src);
 
				src->unitnumber = 0; // doesn't occupy a unitnumber anymore.
 
			}
 

	
 
			/* 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());
 
			}
 
			dst->SetNext(src);
 
		}
 
@@ -1388,20 +1391,21 @@ CommandCost CmdMoveRailVehicle(TileIndex
 
 */
 
CommandCost CmdSellRailWagon(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	/* 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) {
 
		return_cmd_error(STR_ERROR_TRAINS_CAN_ONLY_BE_ALTERED_INSIDE_A_DEPOT);
 
	}
 

	
 
@@ -1423,13 +1427,13 @@ CommandCost CmdSellRailWagon(TileIndex t
 
	switch (p2) {
 
		case 0: { // Delete given wagon
 
			bool switch_engine = false;    // update second wagon to engine?
 

	
 
			/* 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) {
 
				cost.AddCost(-rear->value);
 
				if (flags & DC_EXEC) {
 
					UnlinkWagon(rear, first);
 
@@ -1437,13 +1441,13 @@ CommandCost CmdSellRailWagon(TileIndex t
 
				}
 
			}
 

	
 
			/* 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,
 
				 * promote it as a new train, retaining the unitnumber, orders */
 
				if (new_f != NULL && IsTrainEngine(new_f)) {
 
					if (IsTrainEngine(first)) {
 
@@ -1497,19 +1501,19 @@ CommandCost CmdSellRailWagon(TileIndex t
 
			}
 
		} break;
 
		case 1: { // Delete wagon and all wagons after it given certain criteria
 
			/* 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);
 

	
 
							/* If this is a multiheaded vehicle with nothing
 
							 * between the parts, tmp will be pointing to the
 
@@ -1569,32 +1573,32 @@ void Train::UpdateDeltaXY(Direction dire
 
	this->y_offs        = GB(x,  8, 8);
 
	this->x_extent      = GB(x, 16, 8);
 
	this->y_extent      = GB(x, 24, 8);
 
	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) {
 
		v->u.rail.last_speed = spd;
 
		if (_settings_client.gui.vehicle_speed || (old == 0) != (spd == 0)) {
 
			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
		}
 
	}
 
}
 

	
 
/** 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. */
 
		SetBit(v->u.rail.flags, VRF_TRAIN_STUCK);
 
		v->load_unload_time_rem = 0;
 

	
 
@@ -1628,15 +1632,15 @@ static void SwapTrainFlags(uint16 *swap_
 
		SetBit(*swap_flag1, VRF_GOINGDOWN);
 
	} else if (HasBit(flag2, VRF_GOINGDOWN)) {
 
		SetBit(*swap_flag1, VRF_GOINGUP);
 
	}
 
}
 

	
 
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();
 
	for (b = v; r != 0; r--) b = b->Next();
 

	
 
	if (a != b) {
 
@@ -1701,13 +1705,13 @@ static Vehicle *TrainApproachingCrossing
 
{
 
	/* not a train || not front engine || crashed */
 
	if (v->type != VEH_TRAIN || !IsFrontEngine(v) || v->vehstatus & VS_CRASHED) return NULL;
 

	
 
	TileIndex tile = *(TileIndex*)data;
 

	
 
	if (TrainApproachingCrossingTile(v) != tile) return NULL;
 
	if (TrainApproachingCrossingTile((Train *)v) != tile) return NULL;
 

	
 
	return v;
 
}
 

	
 

	
 
/**
 
@@ -1772,17 +1776,17 @@ static inline void MaybeBarCrossingWithS
 

	
 
/**
 
 * Advances wagons for train reversing, needed for variable length wagons.
 
 * 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) {
 
		last = last->Previous();
 
		first = first->Next();
 

	
 
@@ -1800,21 +1804,21 @@ static void AdvanceWagonsBeforeSwap(Vehi
 

	
 
/**
 
 * Advances wagons for train reversing, needed for variable length wagons.
 
 * 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) */
 
		int d = TicksToLeaveDepot(dep);
 

	
 
		if (d <= 0) {
 
@@ -1823,15 +1827,15 @@ static void AdvanceWagonsAfterSwap(Vehic
 
			for (int i = 0; i >= d; i--) TrainController(leave, NULL); // maybe move it, and maybe let another wagon leave
 
		}
 
	} else {
 
		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
 
	 * they have already correct spacing, so we have to make sure they are moved how they should */
 
	bool nomove = (dep == NULL); // if there is no vehicle leaving a depot, limit the number of wagons moved immediatelly
 

	
 
@@ -1854,13 +1858,13 @@ static void AdvanceWagonsAfterSwap(Vehic
 
		base = first; // == base->Next()
 
		length -= 2;
 
	}
 
}
 

	
 

	
 
static void ReverseTrainDirection(Vehicle *v)
 
static void ReverseTrainDirection(Train *v)
 
{
 
	if (IsRailDepotTile(v->tile)) {
 
		InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
 
	}
 

	
 
	/* Clear path reservation in front. */
 
@@ -1943,23 +1947,25 @@ static void ReverseTrainDirection(Vehicl
 
 * @param flags type of operation
 
 * @param p1 train to reverse
 
 * @param p2 if true, reverse a unit in a train (needs to be in a depot)
 
 */
 
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 */
 

	
 
		if (IsMultiheaded(v) || HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_ARTIC_ENGINE)) {
 
			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);
 
		}
 

	
 
		if (flags & DC_EXEC) {
 
@@ -2004,13 +2010,13 @@ CommandCost CmdReverseTrainDirection(Til
 
 */
 
CommandCost CmdForceTrainProceed(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;
 

	
 
	if (flags & DC_EXEC) v->u.rail.force_proceed = 0x50;
 
	if (flags & DC_EXEC) ((Train *)v)->u.rail.force_proceed = 0x50;
 

	
 
	return CommandCost();
 
}
 

	
 
/** Refits a train to the specified cargo type.
 
 * @param tile unused
 
@@ -2025,14 +2031,16 @@ CommandCost CmdForceTrainProceed(TileInd
 
CommandCost CmdRefitRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	CargoID new_cid = GB(p2, 0, 8);
 
	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);
 

	
 
	/* Check cargo */
 
	if (new_cid >= NUM_CARGO) return CMD_ERROR;
 

	
 
@@ -2100,13 +2108,13 @@ CommandCost CmdRefitRailVehicle(TileInde
 
		}
 
	} while ((v = v->Next()) != NULL && !only_this);
 

	
 
	_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;
 
}
 

	
 
struct TrainFindDepotData {
 
	uint best_length;
 
@@ -2132,13 +2140,13 @@ static bool NtpCallbFindDepot(TileIndex 
 

	
 
	return false;
 
}
 

	
 
/** 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));
 

	
 
	TrainFindDepotData tfdd;
 
	tfdd.owner = v->owner;
 
	tfdd.reverse = false;
 
@@ -2244,21 +2252,21 @@ void OnTick_Train()
 
}
 

	
 
static const int8 _vehicle_smoke_pos[8] = {
 
	1, 1, 1, 0, -1, -1, -1, 0
 
};
 

	
 
static void HandleLocomotiveSmokeCloud(const Vehicle *v)
 
static void HandleLocomotiveSmokeCloud(const Train *v)
 
{
 
	bool sound = false;
 

	
 
	if (v->vehstatus & VS_TRAIN_SLOWING || v->load_unload_time_rem != 0 || v->cur_speed < 2) {
 
		return;
 
	}
 

	
 
	const Vehicle *u = v;
 
	const Train *u = v;
 

	
 
	do {
 
		const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
 
		int effect_offset = GB(v->u.rail.cached_vis_effect, 0, 4) - 8;
 
		byte effect_type = GB(v->u.rail.cached_vis_effect, 4, 2);
 
		bool disable_effect = HasBit(v->u.rail.cached_vis_effect, 6);
 
@@ -2338,13 +2346,13 @@ void Train::PlayLeaveStationSound() cons
 

	
 
	EngineID engtype = this->engine_type;
 
	SndPlayVehicleFx(sfx[RailVehInfo(engtype)->engclass], this);
 
}
 

	
 
/** 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;
 

	
 
	/* Exit if we reached our destination depot or are inside a depot. */
 
	if ((v->tile == v->dest_tile && v->current_order.IsType(OT_GOTO_DEPOT)) || v->u.rail.track & TRACK_BIT_DEPOT) return;
 
@@ -2375,16 +2383,16 @@ static void CheckNextTrainTile(Vehicle *
 
				ChooseTrainTrack(v, ft.m_new_tile, ft.m_exitdir, tracks, false, NULL, false);
 
			}
 
		}
 
	}
 
}
 

	
 
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;
 
	}
 

	
 
	/* if the train got no power, then keep it in the depot */
 
	if (v->u.rail.cached_power == 0) {
 
		v->vehstatus |= VS_STOPPED;
 
@@ -2451,13 +2459,13 @@ static bool CheckTrainStayInDepot(Vehicl
 
	InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
 

	
 
	return false;
 
}
 

	
 
/** 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);
 

	
 
	if (IsTileType(tile, MP_TUNNELBRIDGE)) {
 
		/* Are we just leaving a tunnel/bridge? */
 
		if (GetTunnelBridgeDirection(tile) == ReverseDiagDir(dir)) {
 
@@ -2485,13 +2493,13 @@ static void ClearPathReservation(const V
 
		/* Any other tile */
 
		UnreserveRailTrack(tile, TrackdirToTrack(track_dir));
 
	}
 
}
 

	
 
/** 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));
 

	
 
	TileIndex tile = origin != INVALID_TILE ? origin : v->tile;
 
	Trackdir  td = orig_td != INVALID_TRACKDIR ? orig_td : v->GetVehicleTrackdir();
 
	bool      free_tile = tile != v->tile || !(IsRailwayStationTile(v->tile) || IsTileType(v->tile, MP_TUNNELBRIDGE));
 
@@ -2610,13 +2618,13 @@ static const byte _pick_track_table[6] =
 
 * @param tracks Usable tracks on the new tile
 
 * @param path_not_found [out] Set to false if the pathfinder couldn't find a way to the destination
 
 * @param do_track_reservation Path reservation is requested
 
 * @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;
 

	
 
#ifdef PF_BENCHMARK
 
	TIC()
 
#endif
 
@@ -2711,13 +2719,13 @@ static Track DoTrainPathfind(Vehicle *v,
 

	
 
/**
 
 * Extend a train path as far as possible. Stops on encountering a safe tile,
 
 * 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);
 

	
 
	CFollowTrackRail ft(v);
 

	
 
@@ -2804,13 +2812,13 @@ static PBSTileInfo ExtendTrainReservatio
 
 * @param v The vehicle.
 
 * @param tile The tile the search should start from.
 
 * @param td The trackdir the search should start from.
 
 * @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);
 
	} else {
 
		return NPFRouteToSafeTile(v, tile, td, override_tailtype).res_okay;
 
	}
 
@@ -2893,13 +2901,13 @@ public:
 

	
 
		return false;
 
	}
 
};
 

	
 
/* 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;
 
	bool changed_signal = false;
 

	
 
	assert((tracks & ~TRACK_BIT_MASK) == 0);
 
@@ -3072,13 +3080,13 @@ static Track ChooseTrainTrack(Vehicle *v
 
 *
 
 * @param v The vehicle
 
 * @param mark_as_stuck Should the train be marked as stuck on a failed reservation?
 
 * @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));
 

	
 
	/* We have to handle depots specially as the track follower won't look
 
	 * at the depot tile itself but starts from the next tile. If we are still
 
	 * inside the depot, a depot reservation can never be ours. */
 
@@ -3152,13 +3160,13 @@ bool TryPathReserve(Vehicle *v, bool mar
 
	}
 
	ClrBit(v->u.rail.flags, VRF_TRAIN_STUCK);
 
	return true;
 
}
 

	
 

	
 
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 ||
 
			!(v->direction & 1)) {
 
		return false;
 
	}
 
@@ -3292,13 +3300,13 @@ void Train::MarkDirty()
 
 * where n is the number of straight (long) tracks the train can
 
 * traverse. This means that moving along a straight track costs 256
 
 * "speed" and a diagonal track costs 192 "speed".
 
 * @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;
 

	
 
	if (v->vehstatus & VS_STOPPED || HasBit(v->u.rail.flags, VRF_REVERSING) || HasBit(v->u.rail.flags, VRF_TRAIN_STUCK)) {
 
		switch (_settings_game.vehicle.train_acceleration_model) {
 
			default: NOT_REACHED();
 
@@ -3337,13 +3345,13 @@ static int UpdateTrainSpeed(Vehicle *v)
 

	
 
	scaled_spd += v->progress;
 
	v->progress = 0; // set later in TrainLocoHandler or TrainController
 
	return scaled_spd;
 
}
 

	
 
static void TrainEnterStation(Vehicle *v, StationID station)
 
static void TrainEnterStation(Train *v, StationID station)
 
{
 
	v->last_station_visited = station;
 

	
 
	/* check if a train ever visited this station before */
 
	Station *st = Station::Get(station);
 
	if (!(st->had_vehicle_of_type & HVOT_TRAIN)) {
 
@@ -3360,13 +3368,13 @@ static void TrainEnterStation(Vehicle *v
 

	
 
	v->BeginLoading();
 

	
 
	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);
 

	
 
	if (new_tile) {
 
		ClrBit(v->u.rail.flags, VRF_GOINGUP);
 
@@ -3393,13 +3401,13 @@ static byte AfterSetTrainPos(Vehicle *v,
 

	
 
	VehicleMove(v, true);
 
	return old_z;
 
}
 

	
 
/* 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) && (
 
			!IsFrontEngine(v) ||
 
			HasBit(v->u.rail.compatible_railtypes, GetRailType(tile))
 
		);
 
@@ -3417,25 +3425,25 @@ static const RailtypeSlowdownParams _rai
 
	{256 / 4, 256 / 2, 256 / 4, 2}, ///< electrified
 
	{256 / 4, 256 / 2, 256 / 4, 2}, ///< monorail
 
	{0,       256 / 2, 256 / 4, 2}, ///< maglev
 
};
 

	
 
/** 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;
 

	
 
	DirDiff diff = DirDifference(v->direction, new_dir);
 
	if (diff == DIRDIFF_SAME) return;
 

	
 
	const RailtypeSlowdownParams *rsp = &_railtype_slowdown[v->u.rail.railtype];
 
	v->cur_speed -= (diff == DIRDIFF_45RIGHT || diff == DIRDIFF_45LEFT ? rsp->small_turn : rsp->large_turn) * v->cur_speed >> 8;
 
}
 

	
 
/** 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;
 

	
 
	const RailtypeSlowdownParams *rsp = &_railtype_slowdown[v->u.rail.railtype];
 

	
 
	if (old_z < v->z_pos) {
 
@@ -3458,22 +3466,22 @@ static bool TrainMovedChangeSignals(Tile
 
		}
 
	}
 
	return false;
 
}
 

	
 

	
 
static void SetVehicleCrashed(Vehicle *v)
 
static void SetVehicleCrashed(Train *v)
 
{
 
	if (v->u.rail.crash_anim_pos != 0) return;
 

	
 
	/* Free a possible path reservation and try to mark all tiles occupied by the train reserved. */
 
	if (IsFrontEngine(v)) {
 
		/* 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
 
				 * if the train has just entered the wormhole. */
 
				SetTunnelBridgeReservation(GetOtherTunnelBridgeEnd(u->tile), false);
 
			}
 
@@ -3500,13 +3508,13 @@ static void SetVehicleCrashed(Vehicle *v
 
	}
 

	
 
	/* must be updated after the train has been marked crashed */
 
	if (crossing != INVALID_TILE) UpdateLevelCrossing(crossing);
 
}
 

	
 
static uint CountPassengersInTrain(const Vehicle *v)
 
static uint CountPassengersInTrain(const Train *v)
 
{
 
	uint num = 0;
 

	
 
	for (; v != NULL; v = v->Next()) {
 
		if (IsCargoInClass(v->cargo_type, CC_PASSENGERS)) num += v->cargo.Count();
 
	}
 
@@ -3517,13 +3525,13 @@ static uint CountPassengersInTrain(const
 
/**
 
 * Marks train as crashed and creates an AI event.
 
 * Doesn't do anything if the train is crashed already.
 
 * @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;
 

	
 
	/* two drivers + passengers */
 
	uint num = 2 + CountPassengersInTrain(v);
 
@@ -3546,29 +3554,29 @@ static Vehicle *FindTrainCollideEnum(Veh
 
	if (v->type != VEH_TRAIN) return NULL;
 

	
 
	/* get first vehicle now to make most usual checks faster */
 
	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;
 

	
 
		/* needed to disable possible crash of competitor train in station by building diagonal track at its end */
 
		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));
 
				}
 
				TryReserveRailTrack(u->tile, TrackBitsToTrack(trackbits));
 
			}
 
@@ -3581,13 +3589,13 @@ static Vehicle *FindTrainCollideEnum(Veh
 
/**
 
 * Checks whether the specified train has a collision with another vehicle. If
 
 * so, destroys this vehicle, and the other vehicle if its subtype has TS_Front.
 
 * 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;
 

	
 
	assert(v->u.rail.track == TRACK_BIT_WORMHOLE || TileVirtXY(v->x_pos, v->y_pos) == v->tile);
 

	
 
@@ -3620,22 +3628,22 @@ static bool CheckTrainCollision(Vehicle 
 

	
 
static Vehicle *CheckVehicleAtSignal(Vehicle *v, void *data)
 
{
 
	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()) {
 
		DiagDirection enterdir = DIAGDIR_BEGIN;
 
		bool update_signals_crossing = false; // will we update signals or crossing state?
 

	
 
@@ -3919,17 +3927,17 @@ reverse_train_direction:
 
 */
 
static Vehicle *CollectTrackbitsFromCrashedVehiclesEnum(Vehicle *v, void *data)
 
{
 
	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;
 
		}
 
	}
 

	
 
	return NULL;
 
}
 

	
 
@@ -3937,20 +3945,20 @@ static Vehicle *CollectTrackbitsFromCras
 
 * Deletes/Clears the last wagon of a crashed train. It takes the engine of the
 
 * train, then goes to the last wagon and deletes that. Each call to this function
 
 * will remove the last wagon of a crashed train. If this wagon was on a crossing,
 
 * 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);
 

	
 
	if (first != v) {
 
		/* Recalculate cached train properties */
 
		TrainConsistChanged(first, false);
 
@@ -3999,13 +4007,13 @@ static void DeleteLastWagon(Vehicle *v)
 
		UpdateSignalsOnSegment(tile, INVALID_DIAGDIR, owner);
 
	} else {
 
		SetSignalsOnBothDir(tile, track, owner);
 
	}
 
}
 

	
 
static void ChangeTrainDirRandomly(Vehicle *v)
 
static void ChangeTrainDirRandomly(Train *v)
 
{
 
	static const DirDiff delta[] = {
 
		DIRDIFF_45LEFT, DIRDIFF_SAME, DIRDIFF_SAME, DIRDIFF_45RIGHT
 
	};
 

	
 
	do {
 
@@ -4019,13 +4027,13 @@ static void ChangeTrainDirRandomly(Vehic
 
			 * the bridge in that case */
 
			if (v->u.rail.track != TRACK_BIT_WORMHOLE) AfterSetTrainPos(v, false);
 
		}
 
	} while ((v = v->Next()) != NULL);
 
}
 

	
 
static bool HandleCrashedTrain(Vehicle *v)
 
static bool HandleCrashedTrain(Train *v)
 
{
 
	int state = ++v->u.rail.crash_anim_pos;
 

	
 
	if (state == 4 && !(v->vehstatus & VS_HIDDEN)) {
 
		CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
 
	}
 
@@ -4058,13 +4066,13 @@ static bool HandleCrashedTrain(Vehicle *
 
		return ret;
 
	}
 

	
 
	return true;
 
}
 

	
 
static void HandleBrokenTrain(Vehicle *v)
 
static void HandleBrokenTrain(Train *v)
 
{
 
	if (v->breakdown_ctr != 1) {
 
		v->breakdown_ctr = 1;
 
		v->cur_speed = 0;
 

	
 
		if (v->breakdowns_since_last_service != 255)
 
@@ -4102,13 +4110,13 @@ static const uint16 _breakdown_speeds[16
 
 * Train is approaching line end, slow down and possibly reverse
 
 *
 
 * @param v front train engine
 
 * @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;
 
	uint y = v->y_pos & 0xF;
 

	
 
	/* for diagonal directions, 'x' will be 0..15 -
 
@@ -4143,13 +4151,13 @@ static bool TrainApproachingLineEnd(Vehi
 

	
 
/**
 
 * Determines whether train would like to leave the tile
 
 * @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;
 

	
 
	TileIndex tile = v->tile;
 

	
 
@@ -4173,13 +4181,13 @@ static bool TrainCanLeaveTile(const Vehi
 
 * Determines whether train is approaching a rail-road crossing
 
 *   (thus making it barred)
 
 * @param v front engine of train
 
 * @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));
 

	
 
	if (!TrainCanLeaveTile(v)) return INVALID_TILE;
 

	
 
@@ -4199,13 +4207,13 @@ static TileIndex TrainApproachingCrossin
 
/**
 
 * Checks for line end. Also, bars crossing at next tile if needed
 
 *
 
 * @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 */
 

	
 
	int t = v->breakdown_ctr;
 
	if (t > 1) {
 
		v->vehstatus |= VS_TRAIN_SLOWING;
 
@@ -4250,13 +4258,13 @@ static bool TrainCheckIfLineEnds(Vehicle
 
	if (IsLevelCrossingTile(tile)) MaybeBarCrossingWithSound(tile);
 

	
 
	return true;
 
}
 

	
 

	
 
static bool TrainLocoHandler(Vehicle *v, bool mode)
 
static bool TrainLocoHandler(Train *v, bool mode)
 
{
 
	/* train has crashed? */
 
	if (v->vehstatus & VS_CRASHED) {
 
		return mode ? true : HandleCrashedTrain(v); // 'this' can be deleted here
 
	}
 

	
 
@@ -4378,13 +4386,13 @@ static bool TrainLocoHandler(Vehicle *v,
 
				ProcessOrders(v);
 
			}
 
		}
 
		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;
 
		u->cur_image = u->GetImage(u->direction);
 
		if (old_image != u->cur_image) VehicleMove(u, true);
 
	}
 
@@ -4396,13 +4404,13 @@ static bool TrainLocoHandler(Vehicle *v,
 

	
 

	
 

	
 
Money Train::GetRunningCost() const
 
{
 
	Money cost = 0;
 
	const Vehicle *v = this;
 
	const Train *v = this;
 

	
 
	do {
 
		const RailVehicleInfo *rvi = RailVehInfo(v->engine_type);
 

	
 
		byte cost_factor = GetVehicleProperty(v, 0x0D, rvi->running_cost);
 
		if (cost_factor == 0) continue;
 
@@ -4445,13 +4453,13 @@ bool Train::Tick()
 
		}
 
	}
 

	
 
	return true;
 
}
 

	
 
static void CheckIfTrainNeedsService(Vehicle *v)
 
static void CheckIfTrainNeedsService(Train *v)
 
{
 
	static const uint MAX_ACCEPTABLE_DEPOT_DIST = 16;
 

	
 
	if (_settings_game.vehicle.servint_trains == 0 || !v->NeedsAutomaticServicing()) return;
 
	if (v->IsInDepot()) {
 
		VehicleServiceInDepot(v);
src/train_gui.cpp
Show inline comments
 
@@ -25,13 +25,13 @@ void CcBuildWagon(bool success, TileInde
 
	/* find a locomotive in the depot. */
 
	const Vehicle *found = NULL;
 
	const Vehicle *v;
 
	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;
 
		}
 
	}
 

	
 
	/* if we found a loco, */
src/tunnelbridge_cmd.cpp
Show inline comments
 
@@ -644,13 +644,13 @@ static CommandCost DoClearTunnel(TileInd
 
		if (GetTunnelBridgeTransportType(tile) == TRANSPORT_RAIL) {
 
			/* We first need to request values before calling DoClearSquare */
 
			DiagDirection dir = GetTunnelBridgeDirection(tile);
 
			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);
 
			}
 

	
 
			DoClearSquare(tile);
 
@@ -708,13 +708,13 @@ static CommandCost DoClearBridge(TileInd
 

	
 
	if (flags & DC_EXEC) {
 
		/* read this value before actual removal of bridge */
 
		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));
 
			if (v != NULL) FreeTrainTrackReservation(v);
 
		}
 

	
 
@@ -1382,37 +1382,38 @@ static VehicleEnterTileStatus VehicleEnt
 

	
 
	if (IsTunnel(tile)) {
 
		byte fc;
 
		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) {
 
			RoadVehicle *rv = (RoadVehicle *)v;
 
			fc = (x & 0xF) + (y << 4);
 
			vdir = DirToDiagDir(v->direction);
 
@@ -1459,17 +1460,18 @@ static VehicleEnterTileStatus VehicleEnt
 
				case DIAGDIR_NE: if ((x & 0xF) != 0)             return VETSB_CONTINUE; break;
 
				case DIAGDIR_SE: if ((y & 0xF) != TILE_SIZE - 1) return VETSB_CONTINUE; break;
 
				case DIAGDIR_SW: if ((x & 0xF) != TILE_SIZE - 1) return VETSB_CONTINUE; break;
 
				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;
 
					break;
 

	
 
				case VEH_SHIP:
 
@@ -1479,18 +1481,19 @@ static VehicleEnterTileStatus VehicleEnt
 
				default: NOT_REACHED();
 
			}
 
			return VETSB_ENTERED_WORMHOLE;
 
		} 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;
 
					if (rv->state == RVSB_WORMHOLE) {
 
						rv->state = _road_exit_tunnel_state[dir];
 
						rv->frame = 0;
src/vehicle.cpp
Show inline comments
 
@@ -979,14 +979,14 @@ void VehicleEnterDepot(Vehicle *v)
 
			SetDepotWaypointReservation(v->tile, false);
 
			if (_settings_client.gui.show_track_reservation) MarkTileDirtyByTile(v->tile);
 

	
 
			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:
 
			InvalidateWindowClasses(WC_ROADVEH_LIST);
 
			if (!IsRoadVehFront(v)) v = v->First();
 
			break;
 
@@ -1485,13 +1485,13 @@ void Vehicle::LeaveStation()
 
		if (IsTileType(this->tile, MP_STATION)) StationAnimationTrigger(st, this->tile, STAT_ANIM_TRAIN_DEPARTS);
 

	
 
		/* 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(this->GetVehicleTrackdir()), this->owner) == SIGSEG_PBS || _settings_game.pf.reserve_paths) {
 
			TryPathReserve(this, true, true);
 
			TryPathReserve((Train *)this, true, true);
 
		}
 
	}
 
}
 

	
 

	
 
void Vehicle::HandleLoading(bool mode)
src/vehicle_base.h
Show inline comments
 
@@ -43,13 +43,13 @@ enum VehicleFlags {
 
	VF_AUTOFILL_TIMETABLE,      ///< Whether the vehicle should fill in the timetable automatically.
 
	VF_AUTOFILL_PRES_WAIT_TIME, ///< Whether non-destructive auto-fill should preserve waiting times
 
};
 

	
 
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;
 

	
 
	uint16 last_speed; // NOSAVE: only used in UI
 
	uint16 crash_anim_pos;
src/vehicle_cmd.cpp
Show inline comments
 
@@ -149,13 +149,13 @@ CommandCost CmdMassStartStopVehicle(Tile
 
		const Vehicle *v = list[i];
 

	
 
		if (!!(v->vehstatus & VS_STOPPED) != start_stop) continue;
 

	
 
		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;
 
			}
 
		}
 

	
 
		CommandCost ret = DoCommand(tile, v->index, 0, flags, CMD_START_STOP_VEHICLE);
 
@@ -378,14 +378,14 @@ CommandCost CmdCloneVehicle(TileIndex ti
 

	
 
		total_cost.AddCost(cost);
 

	
 
		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)) {
 
				/* this s a train car
 
				 * add this unit to the end of the train */
 
				CommandCost result = DoCommand(0, (w_rear->index << 16) | w->index, 1, flags, CMD_MOVE_RAIL_VEHICLE);
 
@@ -400,13 +400,13 @@ CommandCost CmdCloneVehicle(TileIndex ti
 
				/* this is a front engine or not a train. */
 
				w_front = w;
 
				w->service_interval = v->service_interval;
 
			}
 
			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 */
 
		_new_vehicle_id = w_front->index;
 
	}
 

	
 
@@ -434,13 +434,13 @@ CommandCost CmdCloneVehicle(TileIndex ti
 
				if (w->cargo_type != v->cargo_type || w->cargo_subtype != v->cargo_subtype) {
 
					CommandCost cost = DoCommand(0, w->index, v->cargo_type | (v->cargo_subtype << 8) | 1U << 16 , flags, GetCmdRefitVeh(v));
 
					if (CmdSucceeded(cost)) total_cost.AddCost(cost);
 
				}
 

	
 
				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 {
 
					break;
 
				}
 
			} else {
 
@@ -450,22 +450,22 @@ CommandCost CmdCloneVehicle(TileIndex ti
 
				if (v->cargo_type != initial_cargo && initial_cargo != CT_INVALID) {
 
					total_cost.AddCost(GetRefitCost(v->engine_type));
 
				}
 
			}
 

	
 
			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 {
 
				break;
 
			}
 
		} 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) {
 
		/*
 
		 * Set the orders of the vehicle. Cannot do it earlier as we need
 
		 * the vehicle refitted before doing this, otherwise the moved
 
		 * cargo types might not match (passenger vs non-passenger)
src/vehicle_func.h
Show inline comments
 
@@ -56,16 +56,12 @@ void VehicleEnteredDepotThisTick(Vehicle
 

	
 
void VehicleMove(Vehicle *v, bool update_viewport);
 
void MarkSingleVehicleDirty(const Vehicle *v);
 

	
 
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);
 

	
 
bool CanBuildVehicleInfrastructure(VehicleType type);
 

	
 
void CcCloneVehicle(bool success, TileIndex tile, uint32 p1, uint32 p2);
src/vehicle_gui.cpp
Show inline comments
 
@@ -15,12 +15,13 @@
 
#include "viewport_func.h"
 
#include "gfx_func.h"
 
#include "newgrf_engine.h"
 
#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"
 
#include "window_func.h"
 
#include "vehicle_func.h"
 
#include "autoreplace_gui.h"
 
@@ -1465,13 +1466,13 @@ struct VehicleDetailsWindow : Window {
 
		switch (v->type) {
 
			case VEH_TRAIN:
 
				SetDParam(2, v->GetDisplayMaxSpeed());
 
				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;
 

	
 
			case VEH_ROAD:
 
			case VEH_SHIP:
 
@@ -1945,13 +1946,13 @@ struct VehicleViewWindow : Window {
 
					SetDParam(0, v->GetDisplaySpeed());
 
					str = STR_TRAIN_STOPPING + _settings_client.gui.vehicle_speed;
 
				}
 
			} 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()) {
 
				case OT_GOTO_STATION: {
 
					SetDParam(0, v->current_order.GetDestination());
 
					SetDParam(1, v->GetDisplaySpeed());
src/vehicle_type.h
Show inline comments
 
@@ -21,12 +21,16 @@ enum VehicleType {
 
};
 
DECLARE_POSTFIX_INCREMENT(VehicleType);
 
template <> struct EnumPropsT<VehicleType> : MakeEnumPropsT<VehicleType, byte, VEH_TRAIN, VEH_END, VEH_INVALID> {};
 
typedef TinyEnumT<VehicleType> VehicleTypeByte;
 

	
 
struct Vehicle;
 
struct Train;
 
struct RoadVehicle;
 
struct Ship;
 
struct Aircraft;
 

	
 
struct BaseVehicle
 
{
 
	VehicleTypeByte type;    ///< Type of vehicle
 
};
 

	
src/vehiclelist.cpp
Show inline comments
 
@@ -26,13 +26,13 @@ void BuildDepotVehicleList(VehicleType t
 
		if (v->type != type) continue;
 
		if (v->tile != tile) continue;
 

	
 
		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;
 
				}
 
				break;
 

	
src/water_cmd.cpp
Show inline comments
 
@@ -810,13 +810,13 @@ static void FloodVehicle(Vehicle *v)
 
				case VEH_TRAIN:
 
					if (IsFrontEngine(v)) {
 
						pass += 4; // driver
 
						/* 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
 
					InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
 
					break;
 

	
src/waypoint_cmd.cpp
Show inline comments
 
@@ -255,13 +255,13 @@ CommandCost RemoveTrainWaypoint(TileInde
 
		Track track = GetRailWaypointTrack(tile);
 
		wp = GetWaypointByTile(tile);
 

	
 
		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);
 
			MakeRailNormal(tile, wp->owner, tracks, GetRailType(tile));
 
			if (reserved) SetTrackReservation(tile, tracks);
 
			MarkTileDirtyByTile(tile);
src/yapf/follow_track.hpp
Show inline comments
 
@@ -5,12 +5,13 @@
 
#ifndef  FOLLOW_TRACK_HPP
 
#define  FOLLOW_TRACK_HPP
 

	
 
#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
 
 *  types w/ or w/o 90-deg turns allowed */
 
template <TransportType Ttr_type_, bool T90deg_turns_allowed_ = true, bool Tmask_reserved_tracks = false>
 
struct CFollowTrackT
 
@@ -51,13 +52,13 @@ struct CFollowTrackT
 
	}
 

	
 
	FORCEINLINE void Init(const Vehicle *v, RailTypes railtype_override, CPerformanceTimer *pPerf)
 
	{
 
		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)
 
	{
 
		assert((!IsRoadTT() || m_veh != NULL) && (!IsRailTT() || railtype_override != INVALID_RAILTYPES));
 
		m_veh_owner = o;
 
@@ -102,13 +103,13 @@ struct CFollowTrackT
 
	 *  Otherwise returns false if track can't be followed. */
 
	inline bool Follow(TileIndex old_tile, Trackdir old_td)
 
	{
 
		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;
 
		if (!CanExitOldTile()) return false;
 
		FollowTileExit();
 
		if (!QueryNewTileTrackStatus()) return TryReverse();
src/yapf/yapf_destrail.hpp
Show inline comments
 
@@ -88,14 +88,14 @@ public:
 
	}
 

	
 
	/** Called by YAPF to detect if node ends in the desired destination */
 
	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
 
	 *  adds it to the actual cost from origin and stores the sum to the Node::m_estimate. */
 
	FORCEINLINE bool PfCalcEstimate(Node& n)
 
	{
src/yapf/yapf_rail.cpp
Show inline comments
 
@@ -51,13 +51,13 @@ private:
 
	Node      *m_res_node;        ///< The reservation target node
 
	TileIndex m_res_fail_tile;    ///< The tile where the reservation failed
 
	Trackdir  m_res_fail_td;      ///< The trackdir where the reservation failed
 

	
 
	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
 
		}
 
		return true;
 
	}
 
@@ -146,13 +146,13 @@ public:
 
			target->tile = m_res_dest;
 
			target->trackdir = m_res_dest_td;
 
			target->okay = false;
 
		}
 

	
 
		/* 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);
 
			if (m_res_fail_tile != INVALID_TILE) {
 
				/* Reservation failed, undo. */
 
				Node *fail_node = m_res_node;
 
@@ -408,13 +408,13 @@ public:
 

	
 
	FORCEINLINE Trackdir ChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found, bool reserve_track, PBSTileInfo *target)
 
	{
 
		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);
 

	
 
		/* find the best path */
 
		bool path_found = Yapf().FindPath(v);
 
		if (path_not_found != NULL) {
 
@@ -531,16 +531,17 @@ Trackdir YapfChooseRailTrack(const Vehic
 

	
 
	Trackdir td_ret = pfnChooseRailTrack(v, tile, enterdir, tracks, path_not_found, reserve_track, target);
 

	
 
	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();
 
	Trackdir td_rev = ReverseTrackdir(last_veh->GetVehicleTrackdir());
 

	
 
	/* tiles where front and back are */
 
@@ -598,13 +599,13 @@ bool YapfFindNearestRailDepotTwoWay(cons
 
{
 
	*depot_tile = INVALID_TILE;
 
	*reversed = false;
 

	
 
	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());
 

	
 
	typedef bool (*PfnFindNearestDepotTwoWay)(const Vehicle*, TileIndex, Trackdir, TileIndex, Trackdir, int, int, TileIndex*, bool*);
 
	PfnFindNearestDepotTwoWay pfnFindNearestDepotTwoWay = &CYapfAnyDepotRail1::stFindNearestDepotTwoWay;
 

	
0 comments (0 inline, 0 general)