diff options
-rw-r--r-- | src/autoreplace_cmd.cpp | 31 | ||||
-rw-r--r-- | src/command_type.h | 7 | ||||
-rw-r--r-- | src/train_cmd.cpp | 5 | ||||
-rw-r--r-- | src/vehicle_func.h | 2 |
4 files changed, 41 insertions, 4 deletions
diff --git a/src/autoreplace_cmd.cpp b/src/autoreplace_cmd.cpp index ea4124e1f..264354085 100644 --- a/src/autoreplace_cmd.cpp +++ b/src/autoreplace_cmd.cpp @@ -90,6 +90,33 @@ bool CheckAutoreplaceValidity(EngineID from, EngineID to, CompanyID company) } /** + * Check the capacity of all vehicles in a chain and spread cargo if needed. + * @param v The vehicle to check. + */ +void CheckCargoCapacity(Vehicle *v) +{ + assert(v == NULL || v->First() == v); + + for (Vehicle *src = v; src != NULL; src = src->Next()) { + /* Do we need to more cargo away? */ + if (src->cargo.Count() <= src->cargo_cap) continue; + + /* We need to move a particular amount. Try that on the other vehicles. */ + uint to_spread = src->cargo.Count() - src->cargo_cap; + for (Vehicle *dest = v; dest != NULL && to_spread != 0; dest = dest->Next()) { + if (dest->cargo.Count() >= dest->cargo_cap || dest->cargo_type != src->cargo_type) continue; + + uint amount = min(to_spread, dest->cargo_cap - dest->cargo.Count()); + src->cargo.MoveTo(&dest->cargo, amount, VehicleCargoList::MTA_UNLOAD, NULL); + to_spread -= amount; + } + + /* Any left-overs will be thrown away, but not their feeder share. */ + src->cargo.Truncate(src->cargo_cap); + } +} + +/** * Transfer cargo from a single (articulated )old vehicle to the new vehicle chain * @param old_veh Old vehicle that will be sold * @param new_head Head of the completely constructed new vehicle chain @@ -297,7 +324,7 @@ static inline CommandCost CmdStartStopVehicle(const Vehicle *v, bool evaluate_ca */ static inline CommandCost CmdMoveVehicle(const Vehicle *v, const Vehicle *after, DoCommandFlag flags, bool whole_chain) { - return DoCommand(0, v->index | (whole_chain ? 1 : 0) << 20, after != NULL ? after->index : INVALID_VEHICLE, flags, CMD_MOVE_RAIL_VEHICLE); + return DoCommand(0, v->index | (whole_chain ? 1 : 0) << 20, after != NULL ? after->index : INVALID_VEHICLE, flags | DC_NO_CARGO_CAP_CHECK, CMD_MOVE_RAIL_VEHICLE); } /** @@ -551,6 +578,8 @@ static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlag flags, bool wagon if (i == 0) old_head = NULL; } } + + if ((flags & DC_EXEC) != 0) CheckCargoCapacity(new_head); } /* If we are not in DC_EXEC undo everything, i.e. rearrange old vehicles. diff --git a/src/command_type.h b/src/command_type.h index 152f66618..406f58364 100644 --- a/src/command_type.h +++ b/src/command_type.h @@ -318,9 +318,10 @@ enum DoCommandFlag { DC_NO_TEST_TOWN_RATING = 0x020, ///< town rating does not disallow you from building DC_BANKRUPT = 0x040, ///< company bankrupts, skip money check, skip vehicle on tile check in some cases DC_AUTOREPLACE = 0x080, ///< autoreplace/autorenew is in progress, this shall disable vehicle limits when building, and ignore certain restrictions when undoing things (like vehicle attach callback) - DC_ALL_TILES = 0x100, ///< allow this command also on MP_VOID tiles - DC_NO_MODIFY_TOWN_RATING = 0x200, ///< do not change town rating - DC_FORCE_CLEAR_TILE = 0x400, ///< do not only remove the object on the tile, but also clear any water left on it + DC_NO_CARGO_CAP_CHECK = 0x100, ///< when autoreplace/autorenew is in progress, this shall prevent truncating the amount of cargo in the vehicle to prevent testing the command to remove cargo + DC_ALL_TILES = 0x200, ///< allow this command also on MP_VOID tiles + DC_NO_MODIFY_TOWN_RATING = 0x400, ///< do not change town rating + DC_FORCE_CLEAR_TILE = 0x800, ///< do not only remove the object on the tile, but also clear any water left on it }; DECLARE_ENUM_AS_BIT_SET(DoCommandFlag) diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 5bdef09a7..c3eb8c1fa 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -1281,6 +1281,11 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u NormaliseTrainHead(src_head); NormaliseTrainHead(dst_head); + if ((flags & DC_NO_CARGO_CAP_CHECK) == 0) { + CheckCargoCapacity(src_head); + CheckCargoCapacity(dst_head); + } + /* We are undoubtedly changing something in the depot and train list. */ InvalidateWindowData(WC_VEHICLE_DEPOT, src->tile); InvalidateWindowClassesData(WC_TRAINS_LIST, 0); diff --git a/src/vehicle_func.h b/src/vehicle_func.h index a41f3c466..283d420a4 100644 --- a/src/vehicle_func.h +++ b/src/vehicle_func.h @@ -173,4 +173,6 @@ void ReleaseDisastersTargetingVehicle(VehicleID vehicle); typedef SmallVector<VehicleID, 2> VehicleSet; void GetVehicleSet(VehicleSet &set, Vehicle *v, uint8 num_vehicles); +void CheckCargoCapacity(Vehicle *v); + #endif /* VEHICLE_FUNC_H */ |