MCPcopy Create free account
hub / github.com/OpenTTD/OpenTTD / CmdMoveRailVehicle

Function CmdMoveRailVehicle

src/train_cmd.cpp:1221–1405  ·  view source on GitHub ↗

* Move a rail vehicle around inside the depot. * @param flags type of operation * Note: DoCommandFlag::AutoReplace is set when autoreplace tries to undo its modifications or moves vehicles to temporary locations inside the depot. * @param src_veh source vehicle index * @param dest_veh what wagon to put the source wagon AFTER, XXX - VehicleID::Invalid() to make a new line * @param

Source from the content-addressed store, hash-verified

1219 * @return the cost of this operation or an error
1220 */
1221CommandCost CmdMoveRailVehicle(DoCommandFlags flags, VehicleID src_veh, VehicleID dest_veh, bool move_chain)
1222{
1223 Train *src = Train::GetIfValid(src_veh);
1224 if (src == nullptr) return CMD_ERROR;
1225
1226 CommandCost ret = CheckOwnership(src->owner);
1227 if (ret.Failed()) return ret;
1228
1229 /* Do not allow moving crashed vehicles inside the depot, it is likely to cause asserts later */
1230 if (src->vehstatus.Test(VehState::Crashed)) return CMD_ERROR;
1231
1232 /* if nothing is selected as destination, try and find a matching vehicle to drag to. */
1233 Train *dst;
1234 if (dest_veh == VehicleID::Invalid()) {
1235 dst = (src->IsEngine() || flags.Test(DoCommandFlag::AutoReplace)) ? nullptr : FindGoodVehiclePos(src);
1236 } else {
1237 dst = Train::GetIfValid(dest_veh);
1238 if (dst == nullptr) return CMD_ERROR;
1239
1240 ret = CheckOwnership(dst->owner);
1241 if (ret.Failed()) return ret;
1242
1243 /* Do not allow appending to crashed vehicles, too */
1244 if (dst->vehstatus.Test(VehState::Crashed)) return CMD_ERROR;
1245 }
1246
1247 /* if an articulated part is being handled, deal with its parent vehicle */
1248 src = src->GetFirstEnginePart();
1249 if (dst != nullptr) {
1250 dst = dst->GetFirstEnginePart();
1251 }
1252
1253 /* don't move the same vehicle.. */
1254 if (src == dst) return CommandCost();
1255
1256 /* locate the head of the two chains */
1257 Train *src_head = src->First();
1258 Train *dst_head;
1259 if (dst != nullptr) {
1260 dst_head = dst->First();
1261 if (dst_head->tile != src_head->tile) return CMD_ERROR;
1262 /* Now deal with articulated part of destination wagon */
1263 dst = dst->GetLastEnginePart();
1264 } else {
1265 dst_head = nullptr;
1266 }
1267
1268 if (src->IsRearDualheaded()) return CommandCost(STR_ERROR_REAR_ENGINE_FOLLOW_FRONT);
1269
1270 /* When moving all wagons, we can't have the same src_head and dst_head */
1271 if (move_chain && src_head == dst_head) return CommandCost();
1272
1273 /* When moving a multiheaded part to be place after itself, bail out. */
1274 if (!move_chain && dst != nullptr && dst->IsRearDualheaded() && src == dst->other_multiheaded_part) return CommandCost();
1275
1276 /* Check if all vehicles in the source train are stopped inside a depot. */
1277 if (!src_head->IsStoppedInDepot()) return CommandCost(STR_ERROR_TRAINS_CAN_ONLY_BE_ALTERED_INSIDE_A_DEPOT);
1278

Callers

nothing calls this directly

Calls 15

CheckOwnershipFunction · 0.85
InvalidFunction · 0.85
FindGoodVehiclePosFunction · 0.85
CommandCostClass · 0.85
MakeTrainBackupFunction · 0.85
ArrangeTrainsFunction · 0.85
ValidateTrainsFunction · 0.85
RestoreTrainBackupFunction · 0.85
NormaliseSubtypesFunction · 0.85
CloseWindowByIdFunction · 0.85
SetWindowDirtyFunction · 0.85
DeleteVehicleOrdersFunction · 0.85

Tested by

no test coverage detected