(svn r16717) -Codechange: make IsFrontEngine() member of Train

This commit is contained in:
smatz 2009-07-01 22:22:01 +00:00
parent 15990079ce
commit adc5363202
17 changed files with 114 additions and 106 deletions

View File

@ -617,9 +617,10 @@ CommandCost CmdAutoreplaceVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1
bool free_wagon = false; bool free_wagon = false;
if (v->type == VEH_TRAIN) { if (v->type == VEH_TRAIN) {
if (IsArticulatedPart(v) || IsRearDualheaded(v)) return CMD_ERROR; Train *t = Train::From(v);
free_wagon = !IsFrontEngine(v); if (IsArticulatedPart(t) || IsRearDualheaded(t)) return CMD_ERROR;
if (free_wagon && IsFrontEngine(v->First())) return CMD_ERROR; free_wagon = !t->IsFrontEngine();
if (free_wagon && t->First()->IsFrontEngine()) return CMD_ERROR;
} else { } else {
if (!v->IsPrimaryVehicle()) return CMD_ERROR; if (!v->IsPrimaryVehicle()) return CMD_ERROR;
} }

View File

@ -437,11 +437,11 @@ struct DepotWindow : Window {
switch (this->type) { switch (this->type) {
case VEH_TRAIN: { case VEH_TRAIN: {
const Vehicle *v = *veh; const Train *v = Train::From(*veh);
d->head = d->wagon = v; d->head = d->wagon = v;
/* either pressed the flag or the number, but only when it's a loco */ /* either pressed the flag or the number, but only when it's a loco */
if (x < 0 && IsFrontEngine(v)) return (x >= -10) ? MODE_START_STOP : MODE_SHOW_VEHICLE; if (x < 0 && v->IsFrontEngine()) return (x >= -10) ? MODE_START_STOP : MODE_SHOW_VEHICLE;
skip = (skip * 8) / _traininfo_vehicle_width; skip = (skip * 8) / _traininfo_vehicle_width;
x = (x * 8) / _traininfo_vehicle_width; x = (x * 8) / _traininfo_vehicle_width;
@ -450,7 +450,7 @@ struct DepotWindow : Window {
x += skip; x += skip;
/* find the vehicle in this row that was clicked */ /* find the vehicle in this row that was clicked */
while (v != NULL && (x -= Train::From(v)->tcache.cached_veh_length) >= 0) v = v->Next(); while (v != NULL && (x -= v->tcache.cached_veh_length) >= 0) v = v->Next();
/* if an articulated part was selected, find its parent */ /* if an articulated part was selected, find its parent */
while (v != NULL && IsArticulatedPart(v)) v = v->Previous(); while (v != NULL && IsArticulatedPart(v)) v = v->Previous();
@ -564,7 +564,7 @@ struct DepotWindow : Window {
if (!v->IsPrimaryVehicle()) { if (!v->IsPrimaryVehicle()) {
v = v->First(); v = v->First();
/* Do nothing when clicking on a train in depot with no loc attached */ /* Do nothing when clicking on a train in depot with no loc attached */
if (v->type == VEH_TRAIN && !IsFrontEngine(v)) return; if (v->type == VEH_TRAIN && !Train::From(v)->IsFrontEngine()) return;
} }
switch (v->type) { switch (v->type) {
@ -950,7 +950,7 @@ struct DepotWindow : Window {
DoCommandP(Vehicle::Get(sel)->tile, Vehicle::Get(sel)->index, true, CMD_REVERSE_TRAIN_DIRECTION | CMD_MSG(STR_ERROR_CAN_T_MAKE_VEHICLE_TURN)); DoCommandP(Vehicle::Get(sel)->tile, Vehicle::Get(sel)->index, true, CMD_REVERSE_TRAIN_DIRECTION | CMD_MSG(STR_ERROR_CAN_T_MAKE_VEHICLE_TURN));
} else if (gdvp.wagon == NULL || gdvp.wagon->index != sel) { } else if (gdvp.wagon == NULL || gdvp.wagon->index != sel) {
TrainDepotMoveVehicle(gdvp.wagon, sel, gdvp.head); TrainDepotMoveVehicle(gdvp.wagon, sel, gdvp.head);
} else if (gdvp.head != NULL && IsFrontEngine(gdvp.head)) { } else if (gdvp.head != NULL && Train::From(gdvp.head)->IsFrontEngine()) {
ShowVehicleViewWindow(gdvp.head); ShowVehicleViewWindow(gdvp.head);
} }
} }
@ -977,7 +977,7 @@ struct DepotWindow : Window {
int sell_cmd = (v->type == VEH_TRAIN && (widget == DEPOT_WIDGET_SELL_CHAIN || _ctrl_pressed)) ? 1 : 0; int sell_cmd = (v->type == VEH_TRAIN && (widget == DEPOT_WIDGET_SELL_CHAIN || _ctrl_pressed)) ? 1 : 0;
bool is_engine = (!(v->type == VEH_TRAIN && !IsFrontEngine(v))); bool is_engine = (v->type != VEH_TRAIN || Train::From(v)->IsFrontEngine());
if (is_engine) { if (is_engine) {
_backup_orders_tile = v->tile; _backup_orders_tile = v->tile;

View File

@ -568,7 +568,7 @@ bool SettingsDisableElrail(int32 p1)
/* Fix the total power and acceleration for trains */ /* Fix the total power and acceleration for trains */
FOR_ALL_TRAINS(t) { FOR_ALL_TRAINS(t) {
/* power and acceleration is cached only for front engines */ /* power and acceleration is cached only for front engines */
if (IsFrontEngine(t)) { if (t->IsFrontEngine()) {
TrainPowerChanged(t); TrainPowerChanged(t);
UpdateTrainAcceleration(t); UpdateTrainAcceleration(t);
} }

View File

@ -83,8 +83,8 @@ static inline void DecreaseGroupNumVehicle(GroupID id_g)
void InitializeGroup(); void InitializeGroup();
void SetTrainGroupID(Vehicle *v, GroupID grp); void SetTrainGroupID(Train *v, GroupID grp);
void UpdateTrainGroupID(Vehicle *v); void UpdateTrainGroupID(Train *v);
void RemoveVehicleFromGroup(const Vehicle *v); void RemoveVehicleFromGroup(const Vehicle *v);
void RemoveAllGroupsForCompany(const CompanyID company); void RemoveAllGroupsForCompany(const CompanyID company);

View File

@ -210,7 +210,7 @@ CommandCost CmdAddVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, u
switch (v->type) { switch (v->type) {
default: NOT_REACHED(); default: NOT_REACHED();
case VEH_TRAIN: case VEH_TRAIN:
SetTrainGroupID(v, new_g); SetTrainGroupID(Train::From(v), new_g);
break; break;
case VEH_ROAD: case VEH_ROAD:
case VEH_SHIP: case VEH_SHIP:
@ -342,11 +342,11 @@ void RemoveVehicleFromGroup(const Vehicle *v)
* @param v First vehicle of the chain. * @param v First vehicle of the chain.
* @param new_g index of array group * @param new_g index of array group
*/ */
void SetTrainGroupID(Vehicle *v, GroupID new_g) void SetTrainGroupID(Train *v, GroupID new_g)
{ {
if (!Group::IsValidID(new_g) && !IsDefaultGroupID(new_g)) return; if (!Group::IsValidID(new_g) && !IsDefaultGroupID(new_g)) return;
assert(v->type == VEH_TRAIN && IsFrontEngine(v)); assert(v->IsFrontEngine());
for (Vehicle *u = v; u != NULL; u = u->Next()) { for (Vehicle *u = v; u != NULL; u = u->Next()) {
if (IsEngineCountable(u)) UpdateNumEngineGroup(u->engine_type, u->group_id, new_g); if (IsEngineCountable(u)) UpdateNumEngineGroup(u->engine_type, u->group_id, new_g);
@ -366,11 +366,11 @@ void SetTrainGroupID(Vehicle *v, GroupID new_g)
* @note Called in CmdBuildRailVehicle, CmdBuildRailWagon, CmdMoveRailVehicle, CmdSellRailWagon * @note Called in CmdBuildRailVehicle, CmdBuildRailWagon, CmdMoveRailVehicle, CmdSellRailWagon
* @param v First vehicle of the chain. * @param v First vehicle of the chain.
*/ */
void UpdateTrainGroupID(Vehicle *v) void UpdateTrainGroupID(Train *v)
{ {
assert(v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))); assert(v->IsFrontEngine() || IsFreeWagon(v));
GroupID new_g = IsFrontEngine(v) ? v->group_id : (GroupID)DEFAULT_GROUP; GroupID new_g = v->IsFrontEngine() ? v->group_id : (GroupID)DEFAULT_GROUP;
for (Vehicle *u = v; u != NULL; u = u->Next()) { for (Vehicle *u = v; u != NULL; u = u->Next()) {
if (IsEngineCountable(u)) UpdateNumEngineGroup(u->engine_type, u->group_id, new_g); if (IsEngineCountable(u)) UpdateNumEngineGroup(u->engine_type, u->group_id, new_g);

View File

@ -2023,7 +2023,7 @@ int WhoCanServiceIndustry(Industry *ind)
/* Check whether it accepts the right kind of cargo */ /* Check whether it accepts the right kind of cargo */
bool c_accepts = false; bool c_accepts = false;
bool c_produces = false; bool c_produces = false;
if (v->type == VEH_TRAIN && IsFrontEngine(v)) { if (v->type == VEH_TRAIN && Train::From(v)->IsFrontEngine()) {
for (const Vehicle *u = v; u != NULL; u = u->Next()) { for (const Vehicle *u = v; u != NULL; u = u->Next()) {
CanCargoServiceIndustry(u->cargo_type, ind, &c_accepts, &c_produces); CanCargoServiceIndustry(u->cargo_type, ind, &c_accepts, &c_produces);
} }

View File

@ -985,7 +985,7 @@ bool AfterLoadGame()
} }
FOR_ALL_TRAINS(v) { FOR_ALL_TRAINS(v) {
if (IsFrontEngine(v) || IsFreeWagon(v)) TrainConsistChanged(v, true); if (v->IsFrontEngine() || IsFreeWagon(v)) TrainConsistChanged(v, true);
} }
} }
@ -1344,7 +1344,7 @@ bool AfterLoadGame()
Vehicle *v; Vehicle *v;
/* Added a FIFO queue of vehicles loading at stations */ /* Added a FIFO queue of vehicles loading at stations */
FOR_ALL_VEHICLES(v) { FOR_ALL_VEHICLES(v) {
if ((v->type != VEH_TRAIN || IsFrontEngine(v)) && // for all locs if ((v->type != VEH_TRAIN || Train::From(v)->IsFrontEngine()) && // for all locs
!(v->vehstatus & (VS_STOPPED | VS_CRASHED)) && // not stopped or crashed !(v->vehstatus & (VS_STOPPED | VS_CRASHED)) && // not stopped or crashed
v->current_order.IsType(OT_LOADING)) { // loading v->current_order.IsType(OT_LOADING)) { // loading
Station::Get(v->last_station_visited)->loading_vehicles.push_back(v); Station::Get(v->last_station_visited)->loading_vehicles.push_back(v);

View File

@ -28,7 +28,7 @@ void ConnectMultiheadedTrains()
} }
FOR_ALL_TRAINS(v) { FOR_ALL_TRAINS(v) {
if (IsFrontEngine(v) || IsFreeWagon(v)) { if (v->IsFrontEngine() || IsFreeWagon(v)) {
/* Two ways to associate multiheaded parts to each other: /* Two ways to associate multiheaded parts to each other:
* sequential-matching: Trains shall be arranged to look like <..>..<..>..<..>.. * sequential-matching: Trains shall be arranged to look like <..>..<..>..<..>..
* bracket-matching: Free vehicle chains shall be arranged to look like ..<..<..>..<..>..>.. * bracket-matching: Free vehicle chains shall be arranged to look like ..<..<..>..<..>..>..
@ -42,7 +42,7 @@ void ConnectMultiheadedTrains()
* This is why two matching strategies are needed. * This is why two matching strategies are needed.
*/ */
bool sequential_matching = IsFrontEngine(v); bool sequential_matching = v->IsFrontEngine();
for (Train *u = v; u != NULL; u = GetNextVehicle(u)) { for (Train *u = v; u != NULL; u = GetNextVehicle(u)) {
if (u->other_multiheaded_part != NULL) continue; // we already linked this one if (u->other_multiheaded_part != NULL) continue; // we already linked this one
@ -308,9 +308,12 @@ void AfterLoadVehicles(bool part_of_load)
FOR_ALL_VEHICLES(v) { FOR_ALL_VEHICLES(v) {
assert(v->first != NULL); assert(v->first != NULL);
if (v->type == VEH_TRAIN && (IsFrontEngine(v) || IsFreeWagon(v))) { if (v->type == VEH_TRAIN) {
if (IsFrontEngine(v)) Train::From(v)->tcache.last_speed = v->cur_speed; // update displayed train speed Train *t = Train::From(v);
TrainConsistChanged(Train::From(v), false); if (t->IsFrontEngine() || IsFreeWagon(t)) {
t->tcache.last_speed = t->cur_speed; // update displayed train speed
TrainConsistChanged(t, false);
}
} else if (v->type == VEH_ROAD && IsRoadVehFront(v)) { } else if (v->type == VEH_ROAD && IsRoadVehFront(v)) {
RoadVehUpdateCache(RoadVehicle::From(v)); RoadVehUpdateCache(RoadVehicle::From(v));
} }
@ -319,7 +322,7 @@ void AfterLoadVehicles(bool part_of_load)
/* Stop non-front engines */ /* Stop non-front engines */
if (CheckSavegameVersion(112)) { if (CheckSavegameVersion(112)) {
FOR_ALL_VEHICLES(v) { FOR_ALL_VEHICLES(v) {
if (v->type == VEH_TRAIN && !IsFrontEngine(v)) { if (v->type == VEH_TRAIN && !Train::From(v)->IsFrontEngine()) {
if (IsTrainEngine(v)) v->vehstatus |= VS_STOPPED; if (IsTrainEngine(v)) v->vehstatus |= VS_STOPPED;
/* cur_speed is now relevant for non-front parts - nonzero breaks /* cur_speed is now relevant for non-front parts - nonzero breaks
* moving-wagons-inside-depot- and autoreplace- code */ * moving-wagons-inside-depot- and autoreplace- code */

View File

@ -700,7 +700,7 @@ static bool UpdateConsists(int32 p1)
Train *t; Train *t;
FOR_ALL_TRAINS(t) { FOR_ALL_TRAINS(t) {
/* Update the consist of all trains so the maximum speed is set correctly. */ /* Update the consist of all trains so the maximum speed is set correctly. */
if (IsFrontEngine(t) || IsFreeWagon(t)) TrainConsistChanged(t, true); if (t->IsFrontEngine() || IsFreeWagon(t)) TrainConsistChanged(t, true);
} }
return true; return true;
} }
@ -736,7 +736,7 @@ static bool TrainAccelerationModelChanged(int32 p1)
{ {
Train *t; Train *t;
FOR_ALL_TRAINS(t) { FOR_ALL_TRAINS(t) {
if (IsFrontEngine(t)) { if (t->IsFrontEngine()) {
t->tcache.cached_max_curve_speed = GetTrainCurveSpeedLimit(t); t->tcache.cached_max_curve_speed = GetTrainCurveSpeedLimit(t);
UpdateTrainAcceleration(t); UpdateTrainAcceleration(t);
} }

View File

@ -2508,7 +2508,7 @@ static VehicleEnterTileStatus VehicleEnter_Station(Vehicle *v, TileIndex tile, i
if (v->type == VEH_TRAIN) { if (v->type == VEH_TRAIN) {
if (!v->current_order.ShouldStopAtStation(v, station_id)) return VETSB_CONTINUE; if (!v->current_order.ShouldStopAtStation(v, station_id)) return VETSB_CONTINUE;
if (!IsRailwayStation(tile) || !IsFrontEngine(v)) return VETSB_CONTINUE; if (!IsRailwayStation(tile) || !Train::From(v)->IsFrontEngine()) return VETSB_CONTINUE;
int station_ahead; int station_ahead;
int station_length; int station_length;

View File

@ -51,17 +51,6 @@ enum TrainSubtype {
TS_MULTIHEADED = 5, ///< Engine is a multiheaded TS_MULTIHEADED = 5, ///< Engine is a multiheaded
}; };
/** Check if a vehicle is front engine
* @param v vehicle to check
* @return Returns true if vehicle is a front engine
*/
static inline bool IsFrontEngine(const Vehicle *v)
{
assert(v->type == VEH_TRAIN);
return HasBit(v->subtype, TS_FRONT);
}
/** Set front engine state /** Set front engine state
* @param v vehicle to change * @param v vehicle to change
*/ */
@ -324,7 +313,7 @@ struct Train : public SpecializedVehicle<Train, VEH_TRAIN> {
void UpdateDeltaXY(Direction direction); void UpdateDeltaXY(Direction direction);
ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_TRAIN_INC : EXPENSES_TRAIN_RUN; } ExpensesType GetExpenseType(bool income) const { return income ? EXPENSES_TRAIN_INC : EXPENSES_TRAIN_RUN; }
void PlayLeaveStationSound() const; void PlayLeaveStationSound() const;
bool IsPrimaryVehicle() const { return IsFrontEngine(this); } bool IsPrimaryVehicle() const { return this->IsFrontEngine(); }
SpriteID GetImage(Direction direction) const; SpriteID GetImage(Direction direction) const;
int GetDisplaySpeed() const { return this->tcache.last_speed; } int GetDisplaySpeed() const { return this->tcache.last_speed; }
int GetDisplayMaxSpeed() const { return this->tcache.cached_max_speed; } int GetDisplayMaxSpeed() const { return this->tcache.cached_max_speed; }
@ -336,6 +325,13 @@ struct Train : public SpecializedVehicle<Train, VEH_TRAIN> {
Trackdir GetVehicleTrackdir() const; Trackdir GetVehicleTrackdir() const;
TileIndex GetOrderStationLocation(StationID station); TileIndex GetOrderStationLocation(StationID station);
bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse); bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse);
/**
* Check if a vehicle is front engine
* @param v vehicle to check
* @return Returns true if vehicle is a front engine
*/
FORCEINLINE bool IsFrontEngine() const { return HasBit(this->subtype, TS_FRONT); }
}; };
#define FOR_ALL_TRAINS(var) FOR_ALL_VEHICLES_OF_TYPE(Train, var) #define FOR_ALL_TRAINS(var) FOR_ALL_VEHICLES_OF_TYPE(Train, var)

View File

@ -217,11 +217,10 @@ void TrainConsistChanged(Train *v, bool same_length)
{ {
uint16 max_speed = UINT16_MAX; uint16 max_speed = UINT16_MAX;
assert(v->type == VEH_TRAIN); assert(v->IsFrontEngine() || IsFreeWagon(v));
assert(IsFrontEngine(v) || IsFreeWagon(v));
const RailVehicleInfo *rvi_v = RailVehInfo(v->engine_type); const RailVehicleInfo *rvi_v = RailVehInfo(v->engine_type);
EngineID first_engine = IsFrontEngine(v) ? v->engine_type : INVALID_ENGINE; EngineID first_engine = v->IsFrontEngine() ? v->engine_type : INVALID_ENGINE;
v->tcache.cached_total_length = 0; v->tcache.cached_total_length = 0;
v->compatible_railtypes = RAILTYPES_NONE; v->compatible_railtypes = RAILTYPES_NONE;
@ -347,7 +346,7 @@ void TrainConsistChanged(Train *v, bool same_length)
/* recalculate cached weights and power too (we do this *after* the rest, so it is known which wagons are powered and need extra weight added) */ /* recalculate cached weights and power too (we do this *after* the rest, so it is known which wagons are powered and need extra weight added) */
TrainCargoChanged(v); TrainCargoChanged(v);
if (IsFrontEngine(v)) { if (v->IsFrontEngine()) {
UpdateTrainAcceleration(v); UpdateTrainAcceleration(v);
InvalidateWindow(WC_VEHICLE_DETAILS, v->index); InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
} }
@ -483,7 +482,7 @@ static int GetTrainAcceleration(Train *v, bool mode)
assert(max_speed == GetTrainCurveSpeedLimit(v)); // safety check, will be removed later assert(max_speed == GetTrainCurveSpeedLimit(v)); // safety check, will be removed later
int speed = v->cur_speed * 10 / 16; // km-ish/h -> mp/h int speed = v->cur_speed * 10 / 16; // km-ish/h -> mp/h
if (IsTileType(v->tile, MP_STATION) && IsFrontEngine(v)) { if (IsTileType(v->tile, MP_STATION) && v->IsFrontEngine()) {
StationID sid = GetStationIndex(v->tile); StationID sid = GetStationIndex(v->tile);
if (v->current_order.ShouldStopAtStation(v, sid)) { if (v->current_order.ShouldStopAtStation(v, sid)) {
int station_ahead; int station_ahead;
@ -577,7 +576,7 @@ static int GetTrainAcceleration(Train *v, bool mode)
void UpdateTrainAcceleration(Train *v) void UpdateTrainAcceleration(Train *v)
{ {
assert(IsFrontEngine(v)); assert(v->IsFrontEngine());
v->max_speed = v->tcache.cached_max_speed; v->max_speed = v->tcache.cached_max_speed;
@ -939,7 +938,7 @@ int CheckTrainInDepot(const Train *v, bool needs_to_be_stopped)
* Also skip counting rear ends of multiheaded engines */ * Also skip counting rear ends of multiheaded engines */
if (!IsArticulatedPart(v) && !IsRearDualheaded(v)) count++; if (!IsArticulatedPart(v) && !IsRearDualheaded(v)) count++;
if (v->track != TRACK_BIT_DEPOT || v->tile != tile || if (v->track != TRACK_BIT_DEPOT || v->tile != tile ||
(IsFrontEngine(v) && needs_to_be_stopped && !(v->vehstatus & VS_STOPPED))) { (v->IsFrontEngine() && needs_to_be_stopped && !(v->vehstatus & VS_STOPPED))) {
return -1; return -1;
} }
} }
@ -1033,7 +1032,7 @@ static void NormaliseTrainConsist(Train *v)
{ {
if (IsFreeWagon(v)) return; if (IsFreeWagon(v)) return;
assert(IsFrontEngine(v)); assert(v->IsFrontEngine());
for (; v != NULL; v = GetNextVehicle(v)) { for (; v != NULL; v = GetNextVehicle(v)) {
if (!IsMultiheaded(v) || !IsTrainEngine(v)) continue; if (!IsMultiheaded(v) || !IsTrainEngine(v)) continue;
@ -1136,7 +1135,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u
if (src_len + dst_len > max_len) { if (src_len + dst_len > max_len) {
/* Abort if we're adding too many wagons to a train. */ /* Abort if we're adding too many wagons to a train. */
if (dst_head != NULL && IsFrontEngine(dst_head)) return_cmd_error(STR_ERROR_TRAIN_TOO_LONG); if (dst_head != NULL && dst_head->IsFrontEngine()) return_cmd_error(STR_ERROR_TRAIN_TOO_LONG);
/* Abort if we're making a train on a new row. */ /* Abort if we're making a train on a new row. */
if (dst_head == NULL && IsTrainEngine(src)) return_cmd_error(STR_ERROR_TRAIN_TOO_LONG); if (dst_head == NULL && IsTrainEngine(src)) return_cmd_error(STR_ERROR_TRAIN_TOO_LONG);
} }
@ -1148,7 +1147,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u
} }
/* moving a loco to a new line?, then we need to assign a unitnumber. */ /* moving a loco to a new line?, then we need to assign a unitnumber. */
if (dst == NULL && !IsFrontEngine(src) && IsTrainEngine(src)) { if (dst == NULL && !src->IsFrontEngine() && IsTrainEngine(src)) {
UnitID unit_num = ((flags & DC_AUTOREPLACE) != 0 ? 0 : GetFreeUnitNumber(VEH_TRAIN)); UnitID unit_num = ((flags & DC_AUTOREPLACE) != 0 ? 0 : GetFreeUnitNumber(VEH_TRAIN));
if (unit_num > _settings_game.vehicle.max_trains) if (unit_num > _settings_game.vehicle.max_trains)
return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME); return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME);
@ -1157,7 +1156,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u
} }
/* When we move the front vehicle, the second vehicle might need a unitnumber */ /* When we move the front vehicle, the second vehicle might need a unitnumber */
if (!HasBit(p2, 0) && (IsFreeWagon(src) || (IsFrontEngine(src) && dst == NULL)) && (flags & DC_AUTOREPLACE) == 0) { if (!HasBit(p2, 0) && (IsFreeWagon(src) || (src->IsFrontEngine() && dst == NULL)) && (flags & DC_AUTOREPLACE) == 0) {
Vehicle *second = GetNextUnit(src); Vehicle *second = GetNextUnit(src);
if (second != NULL && IsTrainEngine(second) && GetFreeUnitNumber(VEH_TRAIN) > _settings_game.vehicle.max_trains) { if (second != NULL && IsTrainEngine(second) && GetFreeUnitNumber(VEH_TRAIN) > _settings_game.vehicle.max_trains) {
return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME); return_cmd_error(STR_ERROR_TOO_MANY_VEHICLES_IN_GAME);
@ -1268,7 +1267,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
/* If we move the front Engine and if the second vehicle is not an engine /* If we move the front Engine and if the second vehicle is not an engine
add the whole vehicle to the DEFAULT_GROUP */ add the whole vehicle to the DEFAULT_GROUP */
if (IsFrontEngine(src) && !IsDefaultGroupID(src->group_id)) { if (src->IsFrontEngine() && !IsDefaultGroupID(src->group_id)) {
Vehicle *v = GetNextVehicle(src); Vehicle *v = GetNextVehicle(src);
if (v != NULL && IsTrainEngine(v)) { if (v != NULL && IsTrainEngine(v)) {
@ -1301,7 +1300,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u
/* move the train to an empty line. for locomotives, we set the type to TS_Front. for wagons, 4. */ /* move the train to an empty line. for locomotives, we set the type to TS_Front. for wagons, 4. */
if (IsTrainEngine(src)) { if (IsTrainEngine(src)) {
if (!IsFrontEngine(src)) { if (!src->IsFrontEngine()) {
/* setting the type to 0 also involves setting up the orders field. */ /* setting the type to 0 also involves setting up the orders field. */
SetFrontEngine(src); SetFrontEngine(src);
assert(src->orders.list == NULL); assert(src->orders.list == NULL);
@ -1319,7 +1318,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u
} }
dst_head = src; dst_head = src;
} else { } else {
if (IsFrontEngine(src)) { if (src->IsFrontEngine()) {
/* the vehicle was previously a loco. need to free the order list and delete vehicle windows etc. */ /* the vehicle was previously a loco. need to free the order list and delete vehicle windows etc. */
DeleteWindowById(WC_VEHICLE_VIEW, src->index); DeleteWindowById(WC_VEHICLE_VIEW, src->index);
DeleteWindowById(WC_VEHICLE_ORDERS, src->index); DeleteWindowById(WC_VEHICLE_ORDERS, src->index);
@ -1330,7 +1329,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u
RemoveVehicleFromGroup(src); RemoveVehicleFromGroup(src);
} }
if (IsFrontEngine(src) || IsFreeWagon(src)) { if (src->IsFrontEngine() || IsFreeWagon(src)) {
InvalidateWindowData(WC_VEHICLE_DEPOT, src->tile); InvalidateWindowData(WC_VEHICLE_DEPOT, src->tile);
ClearFrontEngine(src); ClearFrontEngine(src);
ClearFreeWagon(src); ClearFreeWagon(src);
@ -1357,7 +1356,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u
/* If there is an engine behind first_engine we moved away, it should become new first_engine /* If there is an engine behind first_engine we moved away, it should become new first_engine
* To do this, CmdMoveRailVehicle must be called once more * To do this, CmdMoveRailVehicle must be called once more
* we can't loop forever here because next time we reach this line we will have a front engine */ * we can't loop forever here because next time we reach this line we will have a front engine */
if (src_head != NULL && !IsFrontEngine(src_head) && IsTrainEngine(src_head)) { if (src_head != NULL && !src_head->IsFrontEngine() && IsTrainEngine(src_head)) {
/* As in CmdMoveRailVehicle src_head->group_id will be equal to DEFAULT_GROUP /* As in CmdMoveRailVehicle src_head->group_id will be equal to DEFAULT_GROUP
* we need to save the group and reaffect it to src_head */ * we need to save the group and reaffect it to src_head */
const GroupID tmp_g = src_head->group_id; const GroupID tmp_g = src_head->group_id;
@ -1370,7 +1369,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u
NormaliseTrainConsist(src_head); NormaliseTrainConsist(src_head);
TrainConsistChanged(src_head, false); TrainConsistChanged(src_head, false);
UpdateTrainGroupID(src_head); UpdateTrainGroupID(src_head);
if (IsFrontEngine(src_head)) { if (src_head->IsFrontEngine()) {
/* Update the refit button and window */ /* Update the refit button and window */
InvalidateWindow(WC_VEHICLE_REFIT, src_head->index); InvalidateWindow(WC_VEHICLE_REFIT, src_head->index);
InvalidateWindowWidget(WC_VEHICLE_VIEW, src_head->index, VVW_WIDGET_REFIT_VEH); InvalidateWindowWidget(WC_VEHICLE_VIEW, src_head->index, VVW_WIDGET_REFIT_VEH);
@ -1383,7 +1382,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u
NormaliseTrainConsist(dst_head); NormaliseTrainConsist(dst_head);
TrainConsistChanged(dst_head, false); TrainConsistChanged(dst_head, false);
UpdateTrainGroupID(dst_head); UpdateTrainGroupID(dst_head);
if (IsFrontEngine(dst_head)) { if (dst_head->IsFrontEngine()) {
/* Update the refit button and window */ /* Update the refit button and window */
InvalidateWindowWidget(WC_VEHICLE_VIEW, dst_head->index, VVW_WIDGET_REFIT_VEH); InvalidateWindowWidget(WC_VEHICLE_VIEW, dst_head->index, VVW_WIDGET_REFIT_VEH);
InvalidateWindow(WC_VEHICLE_REFIT, dst_head->index); InvalidateWindow(WC_VEHICLE_REFIT, dst_head->index);
@ -1429,7 +1428,7 @@ CommandCost CmdSellRailWagon(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
if (IsRearDualheaded(v)) return_cmd_error(STR_ERROR_REAR_ENGINE_FOLLOW_FRONT); if (IsRearDualheaded(v)) return_cmd_error(STR_ERROR_REAR_ENGINE_FOLLOW_FRONT);
if (flags & DC_EXEC) { if (flags & DC_EXEC) {
if (v == first && IsFrontEngine(first)) { if (v == first && first->IsFrontEngine()) {
DeleteWindowById(WC_VEHICLE_VIEW, first->index); DeleteWindowById(WC_VEHICLE_VIEW, first->index);
DeleteWindowById(WC_VEHICLE_ORDERS, first->index); DeleteWindowById(WC_VEHICLE_ORDERS, first->index);
DeleteWindowById(WC_VEHICLE_REFIT, first->index); DeleteWindowById(WC_VEHICLE_REFIT, first->index);
@ -1512,7 +1511,7 @@ CommandCost CmdSellRailWagon(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
NormaliseTrainConsist(first); NormaliseTrainConsist(first);
TrainConsistChanged(first, false); TrainConsistChanged(first, false);
UpdateTrainGroupID(first); UpdateTrainGroupID(first);
if (IsFrontEngine(first)) InvalidateWindow(WC_VEHICLE_REFIT, first->index); if (first->IsFrontEngine()) InvalidateWindow(WC_VEHICLE_REFIT, first->index);
} }
} }
@ -1720,14 +1719,16 @@ static Vehicle *TrainOnTileEnum(Vehicle *v, void *)
*/ */
static Vehicle *TrainApproachingCrossingEnum(Vehicle *v, void *data) static Vehicle *TrainApproachingCrossingEnum(Vehicle *v, void *data)
{ {
/* not a train || not front engine || crashed */ if (v->type != VEH_TRAIN || (v->vehstatus & VS_CRASHED)) return NULL;
if (v->type != VEH_TRAIN || !IsFrontEngine(v) || (v->vehstatus & VS_CRASHED)) return NULL;
TileIndex tile = *(TileIndex*)data; Train *t = Train::From(v);
if (!t->IsFrontEngine()) return NULL;
if (TrainApproachingCrossingTile(Train::From(v)) != tile) return NULL; TileIndex tile = *(TileIndex *)data;
return v; if (TrainApproachingCrossingTile(t) != tile) return NULL;
return t;
} }
@ -2512,7 +2513,7 @@ static void ClearPathReservation(const Train *v, TileIndex tile, Trackdir track_
/** Free the reserved path in front of a vehicle. */ /** Free the reserved path in front of a vehicle. */
void FreeTrainTrackReservation(const Train *v, TileIndex origin, Trackdir orig_td) void FreeTrainTrackReservation(const Train *v, TileIndex origin, Trackdir orig_td)
{ {
assert(IsFrontEngine(v)); assert(v->IsFrontEngine());
TileIndex tile = origin != INVALID_TILE ? origin : v->tile; TileIndex tile = origin != INVALID_TILE ? origin : v->tile;
Trackdir td = orig_td != INVALID_TRACKDIR ? orig_td : v->GetVehicleTrackdir(); Trackdir td = orig_td != INVALID_TRACKDIR ? orig_td : v->GetVehicleTrackdir();
@ -3098,7 +3099,7 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir,
*/ */
bool TryPathReserve(Train *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)); assert(v->IsFrontEngine());
/* We have to handle depots specially as the track follower won't look /* 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 * at the depot tile itself but starts from the next tile. If we are still
@ -3419,7 +3420,7 @@ static inline bool CheckCompatibleRail(const Train *v, TileIndex tile)
{ {
return return
IsTileOwner(tile, v->owner) && ( IsTileOwner(tile, v->owner) && (
!IsFrontEngine(v) || !v->IsFrontEngine() ||
HasBit(v->compatible_railtypes, GetRailType(tile)) HasBit(v->compatible_railtypes, GetRailType(tile))
); );
} }
@ -3473,7 +3474,7 @@ static void SetVehicleCrashed(Train *v)
if (v->crash_anim_pos != 0) return; if (v->crash_anim_pos != 0) return;
/* Free a possible path reservation and try to mark all tiles occupied by the train reserved. */ /* Free a possible path reservation and try to mark all tiles occupied by the train reserved. */
if (IsFrontEngine(v)) { if (v->IsFrontEngine()) {
/* Remove all reservations, also the ones currently under the train /* Remove all reservations, also the ones currently under the train
* and any railway station paltform reservation. */ * and any railway station paltform reservation. */
FreeTrainTrackReservation(v); FreeTrainTrackReservation(v);
@ -3631,16 +3632,19 @@ static bool CheckTrainCollision(Train *v)
return true; return true;
} }
static Vehicle *CheckVehicleAtSignal(Vehicle *v, void *data) static Vehicle *CheckTrainAtSignal(Vehicle *v, void *data)
{ {
if (v->type != VEH_TRAIN || (v->vehstatus & VS_CRASHED)) return NULL;
Train *t = Train::From(v);
DiagDirection exitdir = *(DiagDirection *)data; DiagDirection exitdir = *(DiagDirection *)data;
/* front engine of a train, not inside wormhole or depot, not crashed */ /* not front engine of a train, inside wormhole or depot, crashed */
if (v->type == VEH_TRAIN && IsFrontEngine(v) && (Train::From(v)->track & TRACK_BIT_MASK) && !(v->vehstatus & VS_CRASHED)) { if (!t->IsFrontEngine() || !(t->track & TRACK_BIT_MASK)) return NULL;
if (v->cur_speed <= 5 && TrainExitDir(v->direction, Train::From(v)->track) == exitdir) return v;
}
return NULL; if (t->cur_speed > 5 || TrainExitDir(t->direction, t->track) != exitdir) return NULL;
return t;
} }
static void TrainController(Train *v, Vehicle *nomove) static void TrainController(Train *v, Vehicle *nomove)
@ -3667,7 +3671,7 @@ static void TrainController(Train *v, Vehicle *nomove)
/* Not inside depot */ /* Not inside depot */
/* Reverse when we are at the end of the track already, do not move to the new position */ /* Reverse when we are at the end of the track already, do not move to the new position */
if (IsFrontEngine(v) && !TrainCheckIfLineEnds(v)) return; if (v->IsFrontEngine() && !TrainCheckIfLineEnds(v)) return;
uint32 r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y); uint32 r = VehicleEnterTile(v, gp.new_tile, gp.x, gp.y);
if (HasBit(r, VETS_CANNOT_ENTER)) { if (HasBit(r, VETS_CANNOT_ENTER)) {
@ -3737,7 +3741,7 @@ static void TrainController(Train *v, Vehicle *nomove)
exitdir = ReverseDiagDir(exitdir); exitdir = ReverseDiagDir(exitdir);
/* check if a train is waiting on the other side */ /* check if a train is waiting on the other side */
if (!HasVehicleOnPos(o_tile, &exitdir, &CheckVehicleAtSignal)) return; if (!HasVehicleOnPos(o_tile, &exitdir, &CheckTrainAtSignal)) return;
} }
} }
@ -3805,7 +3809,7 @@ static void TrainController(Train *v, Vehicle *nomove)
if (!HasBit(r, VETS_ENTERED_WORMHOLE)) { if (!HasBit(r, VETS_ENTERED_WORMHOLE)) {
Track track = FindFirstTrack(chosen_track); Track track = FindFirstTrack(chosen_track);
Trackdir tdir = TrackDirectionToTrackdir(track, chosen_dir); Trackdir tdir = TrackDirectionToTrackdir(track, chosen_dir);
if (IsFrontEngine(v) && HasPbsSignalOnTrackdir(gp.new_tile, tdir)) { if (v->IsFrontEngine() && HasPbsSignalOnTrackdir(gp.new_tile, tdir)) {
SetSignalStateByTrackdir(gp.new_tile, tdir, SIGNAL_STATE_RED); SetSignalStateByTrackdir(gp.new_tile, tdir, SIGNAL_STATE_RED);
MarkTileDirtyByTile(gp.new_tile); MarkTileDirtyByTile(gp.new_tile);
} }
@ -3837,7 +3841,7 @@ static void TrainController(Train *v, Vehicle *nomove)
v->direction = chosen_dir; v->direction = chosen_dir;
} }
if (IsFrontEngine(v)) { if (v->IsFrontEngine()) {
v->load_unload_time_rem = 0; v->load_unload_time_rem = 0;
/* If we are approching a crossing that is reserved, play the sound now. */ /* If we are approching a crossing that is reserved, play the sound now. */
@ -3864,7 +3868,7 @@ static void TrainController(Train *v, Vehicle *nomove)
if (IsTileType(gp.new_tile, MP_TUNNELBRIDGE) && HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) { if (IsTileType(gp.new_tile, MP_TUNNELBRIDGE) && HasBit(VehicleEnterTile(v, gp.new_tile, gp.x, gp.y), VETS_ENTERED_WORMHOLE)) {
/* Perform look-ahead on tunnel exit. */ /* Perform look-ahead on tunnel exit. */
if (IsFrontEngine(v)) { if (v->IsFrontEngine()) {
TryReserveRailTrack(gp.new_tile, DiagDirToDiagTrack(GetTunnelBridgeDirection(gp.new_tile))); TryReserveRailTrack(gp.new_tile, DiagDirToDiagTrack(GetTunnelBridgeDirection(gp.new_tile)));
CheckNextTrainTile(v); CheckNextTrainTile(v);
} }
@ -3891,7 +3895,7 @@ static void TrainController(Train *v, Vehicle *nomove)
} }
if (update_signals_crossing) { if (update_signals_crossing) {
if (IsFrontEngine(v)) { if (v->IsFrontEngine()) {
if (TrainMovedChangeSignals(gp.new_tile, enterdir)) { if (TrainMovedChangeSignals(gp.new_tile, enterdir)) {
/* We are entering a block with PBS signals right now, but /* We are entering a block with PBS signals right now, but
* not through a PBS signal. This means we don't have a * not through a PBS signal. This means we don't have a
@ -3918,7 +3922,7 @@ static void TrainController(Train *v, Vehicle *nomove)
} }
/* Do not check on every tick to save some computing time. */ /* Do not check on every tick to save some computing time. */
if (IsFrontEngine(v) && v->tick_counter % _settings_game.pf.path_backoff_interval == 0) CheckNextTrainTile(v); if (v->IsFrontEngine() && v->tick_counter % _settings_game.pf.path_backoff_interval == 0) CheckNextTrainTile(v);
} }
if (direction_changed) first->tcache.cached_max_curve_speed = GetTrainCurveSpeedLimit(first); if (direction_changed) first->tcache.cached_max_curve_speed = GetTrainCurveSpeedLimit(first);
@ -4202,7 +4206,7 @@ static bool TrainCanLeaveTile(const Train *v)
*/ */
static TileIndex TrainApproachingCrossingTile(const Train *v) static TileIndex TrainApproachingCrossingTile(const Train *v)
{ {
assert(IsFrontEngine(v)); assert(v->IsFrontEngine());
assert(!(v->vehstatus & VS_CRASHED)); assert(!(v->vehstatus & VS_CRASHED));
if (!TrainCanLeaveTile(v)) return INVALID_TILE; if (!TrainCanLeaveTile(v)) return INVALID_TILE;
@ -4447,7 +4451,7 @@ bool Train::Tick()
this->tick_counter++; this->tick_counter++;
if (IsFrontEngine(this)) { if (this->IsFrontEngine()) {
if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++; if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
this->current_order_time++; this->current_order_time++;
@ -4506,7 +4510,7 @@ void Train::OnNewDay()
{ {
if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this); if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this);
if (IsFrontEngine(this)) { if (this->IsFrontEngine()) {
CheckVehicleBreakdown(this); CheckVehicleBreakdown(this);
AgeVehicle(this); AgeVehicle(this);

View File

@ -26,7 +26,7 @@ void CcBuildWagon(bool success, TileIndex tile, uint32 p1, uint32 p2)
const Vehicle *found = NULL; const Vehicle *found = NULL;
const Train *t; const Train *t;
FOR_ALL_TRAINS(t) { FOR_ALL_TRAINS(t) {
if (IsFrontEngine(t) && t->tile == tile && if (t->IsFrontEngine() && t->tile == tile &&
t->track == TRACK_BIT_DEPOT) { t->track == TRACK_BIT_DEPOT) {
if (found != NULL) return; // must be exactly one. if (found != NULL) return; // must be exactly one.
found = t; found = t;

View File

@ -1374,7 +1374,7 @@ static VehicleEnterTileStatus VehicleEnter_TunnelBridge(Vehicle *v, TileIndex ti
vdir = DirToDiagDir(t->direction); vdir = DirToDiagDir(t->direction);
if (t->track != TRACK_BIT_WORMHOLE && dir == vdir) { if (t->track != TRACK_BIT_WORMHOLE && dir == vdir) {
if (IsFrontEngine(t) && fc == _tunnel_fractcoord_1[dir]) { if (t->IsFrontEngine() && fc == _tunnel_fractcoord_1[dir]) {
if (!PlayVehicleSound(t, VSE_TUNNEL) && RailVehInfo(t->engine_type)->engclass == 0) { if (!PlayVehicleSound(t, VSE_TUNNEL) && RailVehInfo(t->engine_type)->engclass == 0) {
SndPlayVehicleFx(SND_05_TRAIN_THROUGH_TUNNEL, v); SndPlayVehicleFx(SND_05_TRAIN_THROUGH_TUNNEL, v);
} }

View File

@ -518,7 +518,7 @@ void Vehicle::PreDestructor()
} }
} }
if (this->type != VEH_TRAIN || (this->type == VEH_TRAIN && (IsFrontEngine(this) || IsFreeWagon(this)))) { if (this->type != VEH_TRAIN || (this->type == VEH_TRAIN && (Train::From(this)->IsFrontEngine() || IsFreeWagon(this)))) {
InvalidateWindowData(WC_VEHICLE_DEPOT, this->tile); InvalidateWindowData(WC_VEHICLE_DEPOT, this->tile);
} }
@ -959,18 +959,20 @@ uint8 CalcPercentVehicleFilled(const Vehicle *v, StringID *colour)
void VehicleEnterDepot(Vehicle *v) void VehicleEnterDepot(Vehicle *v)
{ {
switch (v->type) { switch (v->type) {
case VEH_TRAIN: case VEH_TRAIN: {
Train *t = Train::From(v);
InvalidateWindowClasses(WC_TRAINS_LIST); InvalidateWindowClasses(WC_TRAINS_LIST);
/* Clear path reservation */ /* Clear path reservation */
SetDepotWaypointReservation(v->tile, false); SetDepotWaypointReservation(t->tile, false);
if (_settings_client.gui.show_track_reservation) MarkTileDirtyByTile(v->tile); if (_settings_client.gui.show_track_reservation) MarkTileDirtyByTile(t->tile);
if (!IsFrontEngine(v)) v = v->First(); if (!t->IsFrontEngine()) t = t->First();
UpdateSignalsOnSegment(v->tile, INVALID_DIAGDIR, v->owner); UpdateSignalsOnSegment(t->tile, INVALID_DIAGDIR, t->owner);
v->load_unload_time_rem = 0; t->load_unload_time_rem = 0;
ClrBit(Train::From(v)->flags, VRF_TOGGLE_REVERSE); ClrBit(t->flags, VRF_TOGGLE_REVERSE);
TrainConsistChanged(Train::From(v), true); TrainConsistChanged(t, true);
break; break;
}
case VEH_ROAD: case VEH_ROAD:
InvalidateWindowClasses(WC_ROADVEH_LIST); InvalidateWindowClasses(WC_ROADVEH_LIST);

View File

@ -350,7 +350,7 @@ CommandCost CmdCloneVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
if (!CheckOwnership(v->owner)) return CMD_ERROR; if (!CheckOwnership(v->owner)) return CMD_ERROR;
if (v->type == VEH_TRAIN && (!IsFrontEngine(v) || Train::From(v)->crash_anim_pos >= 4400)) return CMD_ERROR; if (v->type == VEH_TRAIN && (!Train::From(v)->IsFrontEngine() || Train::From(v)->crash_anim_pos >= 4400)) return CMD_ERROR;
/* check that we can allocate enough vehicles */ /* check that we can allocate enough vehicles */
if (!(flags & DC_EXEC)) { if (!(flags & DC_EXEC)) {
@ -386,7 +386,7 @@ CommandCost CmdCloneVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
SetBit(Train::From(w)->flags, VRF_REVERSE_DIRECTION); SetBit(Train::From(w)->flags, VRF_REVERSE_DIRECTION);
} }
if (v->type == VEH_TRAIN && !IsFrontEngine(v)) { if (v->type == VEH_TRAIN && !Train::From(v)->IsFrontEngine()) {
/* this s a train car /* this s a train car
* add this unit to the end of the train */ * 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); CommandCost result = DoCommand(0, (w_rear->index << 16) | w->index, 1, flags, CMD_MOVE_RAIL_VEHICLE);

View File

@ -798,18 +798,20 @@ static void FloodVehicle(Vehicle *v)
switch (v->type) { switch (v->type) {
default: NOT_REACHED(); default: NOT_REACHED();
case VEH_TRAIN: case VEH_TRAIN: {
if (IsFrontEngine(v)) { Train *t = Train::From(v);
if (t->IsFrontEngine()) {
pass += 4; // driver pass += 4; // driver
/* FreeTrainTrackReservation() calls GetVehicleTrackdir() that doesn't like crashed vehicles. /* 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) */ * In this case, v->direction matches v->u.rail.track, so we can do this (it wasn't crashed before) */
v->vehstatus &= ~VS_CRASHED; t->vehstatus &= ~VS_CRASHED;
FreeTrainTrackReservation(Train::From(v)); FreeTrainTrackReservation(t);
v->vehstatus |= VS_CRASHED; t->vehstatus |= VS_CRASHED;
} }
Train::From(v)->crash_anim_pos = 4000; // max 4440, disappear pretty fast t->crash_anim_pos = 4000; // max 4440, disappear pretty fast
InvalidateWindowClassesData(WC_TRAINS_LIST, 0); InvalidateWindowClassesData(WC_TRAINS_LIST, 0);
break; break;
}
case VEH_ROAD: case VEH_ROAD:
if (IsRoadVehFront(v)) pass += 1; // driver if (IsRoadVehFront(v)) pass += 1; // driver