From ccfd187677e0b28aeb366e0da3d050d921379eab Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Tue, 11 Jun 2019 01:59:50 +0100 Subject: [PATCH] TBTR: Avoid built virtual wagons which can't be attached being orphaned (cherry picked from commit f3daada67f20eaf41a340a38fcf69795960d309f) --- src/build_vehicle_gui.cpp | 2 +- src/train_cmd.cpp | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index 972e5df705..d5393146e2 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -1521,7 +1521,7 @@ struct BuildVehicleWindow : Window { } else { VehicleID target = (*(this->virtual_train_out))->GetLastUnit()->index; - DoCommandP(0, (1 << 21) | toadd->index, target, CMD_MOVE_RAIL_VEHICLE); + DoCommandP(0, (1 << 23) | (1 << 21) | toadd->index, target, CMD_MOVE_RAIL_VEHICLE); } InvalidateWindowClassesData(WC_CREATE_TEMPLATE); InvalidateWindowClassesData(WC_TEMPLATEGUI_MAIN); diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 762b268554..793e99d5ad 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -1175,6 +1175,7 @@ static void NormaliseTrainHead(Train *head) * - p1 (bit 20) move all vehicles following the source vehicle * - p1 (bit 21) this is a virtual vehicle (for creating TemplateVehicles) * - p1 (bit 22) when moving a head vehicle, always reset the head state + * - p1 (bit 23) if move fails, and source vehicle is virtual, delete it * @param p2 what wagon to put the source wagon AFTER, XXX - INVALID_VEHICLE to make a new line * @param text unused * @return the cost of this operation or an error @@ -1185,12 +1186,21 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u VehicleID d = GB(p2, 0, 20); bool move_chain = HasBit(p1, 20); bool new_head = HasBit(p1, 22); + bool delete_failed_virtual = HasBit(p1, 23); Train *src = Train::GetIfValid(s); if (src == NULL) return CMD_ERROR; + auto check_on_failure = [&](CommandCost cost) -> CommandCost { + if (delete_failed_virtual && src->IsVirtual()) { + return DoCommand(src->tile, src->index | (1 << 21), 0, flags, CMD_SELL_VEHICLE); + } else { + return cost; + } + }; + CommandCost ret = CheckOwnership(src->owner); - if (ret.Failed()) return ret; + if (ret.Failed()) return check_on_failure(ret); /* Do not allow moving crashed vehicles inside the depot, it is likely to cause asserts later */ if (src->vehstatus & VS_CRASHED) return CMD_ERROR; @@ -1201,10 +1211,10 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u dst = src->IsEngine() ? NULL : FindGoodVehiclePos(src); } else { dst = Train::GetIfValid(d); - if (dst == NULL) return CMD_ERROR; + if (dst == nullptr) return check_on_failure(CMD_ERROR); CommandCost ret = CheckOwnership(dst->owner); - if (ret.Failed()) return ret; + if (ret.Failed()) return check_on_failure(ret); /* Do not allow appending to crashed vehicles, too */ if (dst->vehstatus & VS_CRASHED) return CMD_ERROR; @@ -1286,7 +1296,7 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u /* Restore the train we had. */ RestoreTrainBackup(original_src); RestoreTrainBackup(original_dst); - return ret; + return check_on_failure(ret); } }