From d4e89ad573aefb7653207e3f719f2cf4c1dd5dff Mon Sep 17 00:00:00 2001 From: J0anJosep Date: Thu, 24 Dec 2020 01:38:04 +0100 Subject: [PATCH] Change: Changes related with crashed trains in extended depots. --- src/train_cmd.cpp | 43 +++++++++++++++++++++++++++++++++++++++---- src/vehicle.cpp | 18 ++++++++++++++++++ src/vehicle_func.h | 1 + 3 files changed, 58 insertions(+), 4 deletions(-) diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index e89f98c0c3..f9bc2fdf9b 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -3270,6 +3270,7 @@ static bool TrainMovedChangeSignals(TileIndex tile, DiagDirection dir) void Train::ReserveTrackUnderConsist() const { for (const Train *u = this; u != nullptr; u = u->Next()) { + if (u->vehstatus & VS_HIDDEN) continue; switch (u->track) { case TRACK_BIT_WORMHOLE: TryReserveRailTrack(u->tile, DiagDirToDiagTrack(GetTunnelBridgeDirection(u->tile))); @@ -3298,6 +3299,23 @@ uint Train::Crash(bool flooded) /* Remove the reserved path in front of the train if it is not stuck. * Also clear all reserved tracks the train is currently on. */ if (!HasBit(this->flags, VRF_TRAIN_STUCK)) FreeTrainTrackReservation(this); + + if (IsExtendedRailDepotTile(this->tile)) { + if (this->track & ~TRACK_BIT_DEPOT) { + for (Train *v = this; v != nullptr; v = v->Next()) { + v->track &= ~TRACK_BIT_DEPOT; + } + InvalidateWindowData(WC_VEHICLE_DEPOT, GetDepotIndex(this->tile)); + } + /* Remove reserved tracks of platform ahead. */ + TileIndexDiff diff = TileOffsByDiagDir(TrackdirToExitdir(this->GetVehicleTrackdir())); + for (TileIndex pt_tile = this->tile + diff; IsCompatiblePlatformTile(pt_tile, this->tile) && HasDepotReservation(pt_tile); pt_tile += diff) { + if (EnsureNoVisibleVehicleOnGround(pt_tile).Failed()) break; + SetDepotReservation(pt_tile, false); + MarkTileDirtyByTile(pt_tile); + } + } + for (const Train *v = this; v != nullptr; v = v->Next()) { ClearPathReservation(v, v->tile, v->GetVehicleTrackdir()); if (IsTileType(v->tile, MP_TUNNELBRIDGE)) { @@ -3305,6 +3323,23 @@ uint Train::Crash(bool flooded) * if the train has just entered the wormhole. */ SetTunnelBridgeReservation(GetOtherTunnelBridgeEnd(v->tile), false); } + + if (v->Next() == nullptr && (IsRailStationTile(v->tile) || IsExtendedRailDepotTile(v->tile))) { + /* Remove reserved tracks of platform tiles behind the train. */ + TileIndexDiff diff = TileOffsByDiagDir(TrackdirToExitdir(ReverseTrackdir(v->GetVehicleTrackdir()))); + for (TileIndex pt_tile = v->tile + diff; IsCompatiblePlatformTile(pt_tile, v->tile); pt_tile += diff) { + if (IsExtendedRailDepotTile(pt_tile)) { + if (!HasDepotReservation(pt_tile)) break; + if (EnsureNoVisibleVehicleOnGround(pt_tile).Failed()) break; + SetDepotReservation(pt_tile, false); + } else { + if (!HasStationReservation(pt_tile)) break; + if (EnsureNoVisibleVehicleOnGround(pt_tile).Failed()) break; + SetRailStationReservation(pt_tile, false); + } + MarkTileDirtyByTile(pt_tile); + } + } } /* we may need to update crossing we were approaching, @@ -3317,6 +3352,7 @@ uint Train::Crash(bool flooded) } pass += this->GroundVehicleBase::Crash(flooded); + this->ReserveTrackUnderConsist(); this->crash_anim_pos = flooded ? 4000 : 1; // max 4440, disappear pretty fast when flooded return pass; @@ -3339,10 +3375,6 @@ static uint TrainCrashed(Train *v) Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, ScriptEventVehicleCrashed::CRASH_TRAIN)); } - /* Try to re-reserve track under already crashed train too. - * Crash() clears the reservation! */ - v->ReserveTrackUnderConsist(); - return num; } @@ -3395,6 +3427,9 @@ static Vehicle *FindTrainCollideEnum(Vehicle *v, void *data) tcc->num += TrainCrashed(tcc->v); tcc->num += TrainCrashed(coll); + /* The crashing of the coll train frees reservation of train v: Reserve again for train v. */ + tcc->v->ReserveTrackUnderConsist(); + return nullptr; // continue searching } diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 83518b4b91..76dc88afd0 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -667,6 +667,24 @@ CommandCost EnsureNoVehicleOnGround(TileIndex tile) return CommandCost(); } +/** + * Ensure there is no visible vehicle at the ground at the given position. + * @param tile Position to examine. + * @return Succeeded command (ground is free) or failed command (a visible vehicle is found). + */ +CommandCost EnsureNoVisibleVehicleOnGround(TileIndex tile) +{ + int z = GetTileMaxPixelZ(tile); + + /* Value v is not safe in MP games, however, it is used to generate a local + * error message only (which may be different for different machines). + * Such a message does not affect MP synchronisation. + */ + Vehicle *v = VehicleFromPos(tile, &z, &EnsureNoVehicleProcZ, true); + if (v != nullptr && (v->vehstatus & VS_HIDDEN) == 0) return_cmd_error(STR_ERROR_TRAIN_IN_THE_WAY + v->type); + return CommandCost(); +} + /** Procedure called for every vehicle found in tunnel/bridge in the hash map */ static Vehicle *GetVehicleTunnelBridgeProc(Vehicle *v, void *data) { diff --git a/src/vehicle_func.h b/src/vehicle_func.h index eedd4c4a6d..d92b6b1703 100644 --- a/src/vehicle_func.h +++ b/src/vehicle_func.h @@ -165,6 +165,7 @@ inline StringID GetCmdSendToDepotMsg(const BaseVehicle *v) } CommandCost EnsureNoVehicleOnGround(TileIndex tile); +CommandCost EnsureNoVisibleVehicleOnGround(TileIndex tile); CommandCost EnsureNoTrainOnTrackBits(TileIndex tile, TrackBits track_bits); bool CanVehicleUseStation(EngineID engine_type, const struct Station *st);