* 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 */
| 3633 | * @param v the Vehicle of which last wagon is to be removed |
| 3634 | */ |
| 3635 | static void DeleteLastWagon(Train *v) |
| 3636 | { |
| 3637 | Train *first = v->First(); |
| 3638 | |
| 3639 | /* Go to the last wagon and delete the link pointing there |
| 3640 | * new_last is then the one-before-last wagon, and v the last |
| 3641 | * one which will physically be removed */ |
| 3642 | Train *new_last = v; |
| 3643 | for (; v->Next() != nullptr; v = v->Next()) new_last = v; |
| 3644 | new_last->SetNext(nullptr); |
| 3645 | |
| 3646 | if (first != v) { |
| 3647 | /* Recalculate cached train properties */ |
| 3648 | first->ConsistChanged(CCF_ARRANGE); |
| 3649 | /* Update the depot window if the first vehicle is in depot - |
| 3650 | * if v == first, then it is updated in PreDestructor() */ |
| 3651 | if (first->track == TRACK_BIT_DEPOT) { |
| 3652 | SetWindowDirty(WC_VEHICLE_DEPOT, first->tile); |
| 3653 | } |
| 3654 | v->last_station_visited = first->last_station_visited; // for PreDestructor |
| 3655 | } |
| 3656 | |
| 3657 | /* 'v' shouldn't be accessed after it has been deleted */ |
| 3658 | TrackBits trackbits = v->track; |
| 3659 | TileIndex tile = v->tile; |
| 3660 | Owner owner = v->owner; |
| 3661 | |
| 3662 | delete v; |
| 3663 | v = nullptr; // make sure nobody will try to read 'v' anymore |
| 3664 | |
| 3665 | if (trackbits == TRACK_BIT_WORMHOLE) { |
| 3666 | /* Vehicle is inside a wormhole, v->track contains no useful value then. */ |
| 3667 | trackbits = DiagDirToDiagTrackBits(GetTunnelBridgeDirection(tile)); |
| 3668 | } |
| 3669 | |
| 3670 | Track track = TrackBitsToTrack(trackbits); |
| 3671 | if (HasReservedTracks(tile, trackbits)) { |
| 3672 | UnreserveRailTrack(tile, track); |
| 3673 | |
| 3674 | /* If there are still crashed vehicles on the tile, give the track reservation to them */ |
| 3675 | TrackBits remaining_trackbits = TRACK_BIT_NONE; |
| 3676 | for (const Vehicle *u : VehiclesOnTile(tile)) { |
| 3677 | if (u->type != VEH_TRAIN || !u->vehstatus.Test(VehState::Crashed)) continue; |
| 3678 | TrackBits train_tbits = Train::From(u)->track; |
| 3679 | if (train_tbits == TRACK_BIT_WORMHOLE) { |
| 3680 | /* Vehicle is inside a wormhole, u->track contains no useful value then. */ |
| 3681 | remaining_trackbits |= DiagDirToDiagTrackBits(GetTunnelBridgeDirection(u->tile)); |
| 3682 | } else if (train_tbits != TRACK_BIT_DEPOT) { |
| 3683 | remaining_trackbits |= train_tbits; |
| 3684 | } |
| 3685 | } |
| 3686 | |
| 3687 | /* It is important that these two are the first in the loop, as reservation cannot deal with every trackbit combination */ |
| 3688 | assert(TRACK_BEGIN == TRACK_X && TRACK_Y == TRACK_BEGIN + 1); |
| 3689 | for (Track t : SetTrackBitIterator(remaining_trackbits)) TryReserveRailTrack(tile, t); |
| 3690 | } |
| 3691 | |
| 3692 | /* check if the wagon was on a road/rail-crossing */ |
no test coverage detected