From b6946fb17f0a3430c94ef769c6be1283c5b54682 Mon Sep 17 00:00:00 2001 From: J0anJosep Date: Sat, 22 Apr 2023 21:18:59 +0200 Subject: [PATCH] Change: Adapt VehicleEnter_Track and handle trains entering extended depots. # Conflicts: # src/vehicle.cpp --- src/rail_cmd.cpp | 37 +++++++++++++++++++++++--- src/train.h | 1 + src/train_cmd.cpp | 68 ++++++++++++++++++++++++++++++++++++++++------- src/vehicle.cpp | 3 +-- 4 files changed, 94 insertions(+), 15 deletions(-) diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 2868d174b5..a759ee8236 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -33,6 +33,7 @@ #include "object_map.h" #include "rail_cmd.h" #include "landscape_cmd.h" +#include "platform_func.h" #include "table/strings.h" #include "table/railtypes.h" @@ -3076,6 +3077,38 @@ static VehicleEnterTileStatus VehicleEnter_Track(Vehicle *u, TileIndex tile, int /* This routine applies only to trains in depot tiles. */ if (u->type != VEH_TRAIN || !IsRailDepotTile(tile)) return VETSB_CONTINUE; + Train *v = Train::From(u); + + if (IsExtendedRailDepot(tile)) { + DepotID depot_id = GetDepotIndex(tile); + if (!v->current_order.ShouldStopAtDepot(depot_id)) return VETSB_CONTINUE; + + /* Stop position on platform is half the front vehicle length of the train. */ + int stop_pos = v->gcache.cached_veh_length / 2; + + int depot_ahead = (GetPlatformLength(tile, DirToDiagDir(v->direction)) - 1) * TILE_SIZE; + if (depot_ahead > stop_pos) return VETSB_CONTINUE; + + DiagDirection dir = DirToDiagDir(v->direction); + + x &= 0xF; + y &= 0xF; + + if (DiagDirToAxis(dir) != AXIS_X) Swap(x, y); + if (y == TILE_SIZE / 2) { + if (dir == DIAGDIR_SE || dir == DIAGDIR_SW) x = TILE_SIZE - 1 - x; + + if (stop_pos == x) { + return VETSB_ENTERED_DEPOT_PLATFORM; + } else if (stop_pos < x) { + v->vehstatus |= VS_TRAIN_SLOWING; + uint16_t spd = std::max(0, stop_pos * 20 - 15); + if (spd < v->cur_speed) v->cur_speed = spd; + } + } + return VETSB_CONTINUE; + } + /* Depot direction. */ DiagDirection dir = GetRailDepotDirection(tile); @@ -3084,8 +3117,6 @@ static VehicleEnterTileStatus VehicleEnter_Track(Vehicle *u, TileIndex tile, int /* Make sure a train is not entering the tile from behind. */ if (_fractcoords_behind[dir] == fract_coord) return VETSB_CANNOT_ENTER; - Train *v = Train::From(u); - /* Leaving depot? */ if (v->direction == DiagDirToDir(dir)) { /* Calculate the point where the following wagon should be activated. */ @@ -3110,7 +3141,7 @@ static VehicleEnterTileStatus VehicleEnter_Track(Vehicle *u, TileIndex tile, int v->track = TRACK_BIT_DEPOT, v->vehstatus |= VS_HIDDEN; v->direction = ReverseDir(v->direction); - if (v->Next() == nullptr) VehicleEnterDepot(v->First()); + if (v->Next() == nullptr) HandleTrainEnterDepot(v->First()); v->tile = tile; InvalidateWindowData(WC_VEHICLE_DEPOT, GetDepotIndex(v->tile)); diff --git a/src/train.h b/src/train.h index 677ead8d1a..65fd1503c1 100644 --- a/src/train.h +++ b/src/train.h @@ -354,5 +354,6 @@ protected: // These functions should not be called outside acceleration code. }; bool HasCompatibleDepotTile(TileIndex tile, const Train *t); +bool HandleTrainEnterDepot(Train *v); #endif /* TRAIN_H */ diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index c82dc1c2d9..66ef11c055 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -2411,6 +2411,31 @@ static void CheckNextTrainTile(Train *v) } } +bool HandleTrainEnterDepot(Train *v) +{ + assert(IsRailDepotTile(v->tile)); + + if (IsExtendedRailDepot(v->tile)) { + v->cur_speed = 0; + Train *t = Train::From(v); + for (Train *u = t; u != nullptr; u = u->Next()) u->track |= TRACK_BIT_DEPOT; + t->force_proceed = TFP_NONE; + ClrBit(t->flags, VRF_TOGGLE_REVERSE); + v->UpdateViewport(true, true); + SetWindowClassesDirty(WC_TRAINS_LIST); + SetWindowDirty(WC_VEHICLE_VIEW, v->index); + + InvalidateWindowData(WC_VEHICLE_DEPOT, GetDepotIndex(v->tile)); + v->StartService(); + } else { + /* Clear path reservation */ + SetDepotReservation(v->tile, false); + VehicleEnterDepot(v); + } + + return true; +} + /** * Will the train stay in the depot the next tick? * @param v %Train to check. @@ -2419,15 +2444,30 @@ static void CheckNextTrainTile(Train *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 Train *u = v; u != nullptr; u = u->Next()) { - if (!u->IsInDepot() || u->tile != v->tile) return false; - } + if (!v->IsInDepot()) return false; + assert(IsRailDepotTile(v->tile)); - /* if the train got no power, then keep it in the depot */ - if (v->gcache.cached_power == 0) { - v->vehstatus |= VS_STOPPED; - SetWindowDirty(WC_VEHICLE_DEPOT, GetDepotIndex(v->tile)); - return true; + DepotID depot_id = GetDepotIndex(v->tile); + if (IsExtendedRailDepot(v->tile)) { + for (Train *u = v; u != nullptr; u = u->Next()) u->track &= ~TRACK_BIT_DEPOT; + v->cur_speed = 0; + + v->UpdatePosition(); + v->UpdateViewport(true, true); + v->UpdateAcceleration(); + InvalidateWindowData(WC_VEHICLE_DEPOT, depot_id); + return false; + } else { + for (const Train *u = v; u != nullptr; u = u->Next()) { + if (!u->IsInDepot() || u->tile != v->tile) return false; + } + + /* if the train got no power, then keep it in the depot */ + if (v->gcache.cached_power == 0) { + v->vehstatus |= VS_STOPPED; + SetWindowDirty(WC_VEHICLE_DEPOT, depot_id); + return true; + } } /* Check if we should wait here for unbunching. */ @@ -2459,7 +2499,7 @@ static bool CheckTrainStayInDepot(Train *v) IsRailDepotTile(v->tile) && v->current_order.GetDestination() == GetDepotIndex(v->tile)) { /* Service when depot has no reservation. */ - if (!HasDepotReservation(v->tile)) VehicleEnterDepot(v); + if (!HasDepotReservation(v->tile)) HandleTrainEnterDepot(v); return true; } @@ -2489,7 +2529,7 @@ static bool CheckTrainStayInDepot(Train *v) v->UpdatePosition(); UpdateSignalsOnSegment(v->tile, INVALID_DIAGDIR, v->owner); v->UpdateAcceleration(); - InvalidateWindowData(WC_VEHICLE_DEPOT, GetDepotIndex(v->tile)); + InvalidateWindowData(WC_VEHICLE_DEPOT, depot_id); return false; } @@ -3442,6 +3482,12 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) if (HasBit(r, VETS_ENTERED_STATION)) { /* The new position is the end of the platform */ TrainEnterStation(v, r >> VETS_STATION_ID_OFFSET); + } else if (HasBit(r, VETS_ENTERED_DEPOT_PLATFORM)) { + if (HandleTrainEnterDepot(first)) { + v->UpdatePosition(); + v->UpdateViewport(true, true); + return false; + } } } } else { @@ -4098,6 +4144,8 @@ static bool TrainLocoHandler(Train *v, bool mode) /* exit if train is stopped */ if ((v->vehstatus & VS_STOPPED) && v->cur_speed == 0) return true; + if (v->ContinueServicing()) return true; + bool valid_order = !v->current_order.IsType(OT_NOTHING) && v->current_order.GetType() != OT_CONDITIONAL; if (ProcessOrders(v) && CheckReverseTrain(v)) { v->wait_counter = 0; diff --git a/src/vehicle.cpp b/src/vehicle.cpp index a787f89b25..83518b4b91 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -1201,6 +1201,7 @@ void CallVehicleTicks() if (it.second) { v->vehstatus &= ~VS_STOPPED; } else if (IsExtendedDepotTile(v->tile)){ + if (v->type == VEH_TRAIN) FreeTrainTrackReservation(Train::From(v)); UpdateExtendedDepotReservation(v, true); } @@ -1683,8 +1684,6 @@ void VehicleEnterDepot(Vehicle *v) case VEH_TRAIN: { Train *t = Train::From(v); SetWindowClassesDirty(WC_TRAINS_LIST); - /* Clear path reservation */ - SetDepotReservation(t->tile, false); if (_settings_client.gui.show_track_reservation) MarkTileDirtyByTile(t->tile); UpdateSignalsOnSegment(t->tile, INVALID_DIAGDIR, t->owner);