32#include "table/strings.h"
50 return (available_cargoes_a == 0 || available_cargoes_b == 0 || (available_cargoes_a & available_cargoes_b) != 0);
109 assert(v ==
nullptr || v->
First() == v);
111 for (
Vehicle *src = v; src !=
nullptr; src = src->
Next()) {
115 if (src->cargo.TotalCount() <= src->cargo_cap)
continue;
118 uint to_spread = src->cargo.TotalCount() - src->cargo_cap;
119 for (
Vehicle *dest = v; dest !=
nullptr && to_spread != 0; dest = dest->
Next()) {
121 if (dest->cargo.TotalCount() >= dest->cargo_cap || dest->cargo_type != src->cargo_type)
continue;
123 uint amount = std::min(to_spread, dest->cargo_cap - dest->cargo.TotalCount());
124 src->cargo.Shift(amount, &dest->cargo);
129 if (src->cargo_cap < src->cargo.TotalCount()) src->cargo.Truncate(src->cargo.TotalCount() - src->cargo_cap);
146 for (
Vehicle *src = old_veh; src !=
nullptr; src = src->
Next()) {
150 src = src->GetLastEnginePart();
153 if (src->cargo_type >=
NUM_CARGO || src->cargo.TotalCount() == 0)
continue;
160 dest = dest->GetLastEnginePart();
163 if (dest->cargo_type != src->cargo_type)
continue;
165 uint amount = std::min(src->cargo.TotalCount(), dest->cargo_cap - dest->cargo.TotalCount());
166 if (amount <= 0)
continue;
168 src->cargo.Shift(amount, &dest->cargo);
189 if (!o->IsRefit() || o->IsAutoRefit())
continue;
190 CargoType cargo_type = o->GetRefitCargo();
192 if (!
HasBit(union_refit_mask_a, cargo_type))
continue;
193 if (!
HasBit(union_refit_mask_b, cargo_type))
return false;
213 if (orders ==
nullptr)
return -1;
234 CargoTypes available_cargo_types, union_mask;
243 if ((cargo_mask & new_engine_default_cargoes) == cargo_mask) {
247 return INVALID_CARGO;
258 for (v = v->
First(); v !=
nullptr; v = v->
Next()) {
266 if (!
HasBit(available_cargo_types, cargo_type))
return INVALID_CARGO;
286 e = EngineID::Invalid();
293 bool replace_when_old;
295 if (!always_replace && replace_when_old && !v->
NeedsAutorenewing(c,
false)) e = EngineID::Invalid();
323 *new_vehicle =
nullptr;
329 if (cost.
Failed())
return cost;
330 if (e == EngineID::Invalid())
return CommandCost();
341 if (order_id != -1) {
345 STR_ERROR_AUTOREPLACE_INCOMPATIBLE_REFIT,
351 STR_ERROR_AUTOREPLACE_INCOMPATIBLE_CARGO,
361 std::tie(cost, new_veh_id, std::ignore, std::ignore, std::ignore) =
Command<CMD_BUILD_VEHICLE>::Do({
DoCommandFlag::Execute,
DoCommandFlag::AutoReplace}, old_veh->
tile, e,
true, INVALID_CARGO,
INVALID_CLIENT_ID);
362 if (cost.
Failed())
return cost;
365 *new_vehicle = new_veh;
467 if (cost.
Succeeded() && new_v !=
nullptr) {
468 *nothing_to_do =
false;
482 *single_unit = new_v;
533 std::vector<ReplaceChainItem> replacements;
544 replacement.cost = ret.
GetCost();
545 if (replacement.
new_veh !=
nullptr) *nothing_to_do =
false;
547 Vehicle *new_head = replacements.front().GetVehicle();
555 assert(
Train::From(new_head)->GetNextUnit() ==
nullptr);
561 Vehicle *last_engine =
nullptr;
563 for (
auto it = std::rbegin(replacements); it != std::rend(replacements); ++it) {
564 Vehicle *append = it->GetVehicle();
568 if (it->new_veh !=
nullptr) {
572 CmdMoveVehicle(it->old_veh,
nullptr, {DoCommandFlag::Execute, DoCommandFlag::AutoReplace},
false);
575 if (last_engine ==
nullptr) last_engine = append;
579 if (last_engine ==
nullptr) last_engine = new_head;
583 if (cost.
Succeeded() && wagon_removal &&
Train::From(new_head)->gcache.cached_total_length > old_total_length) cost =
CommandCost(STR_ERROR_TRAIN_TOO_LONG_AFTER_REPLACEMENT);
589 for (
auto it = std::rbegin(replacements); it != std::rend(replacements); ++it) {
590 assert(last_engine !=
nullptr);
591 Vehicle *append = it->GetVehicle();
600 if (wagon_removal && (res.
Failed() ? res.
GetErrorMessage() == STR_ERROR_TRAIN_TOO_LONG :
Train::From(new_head)->gcache.cached_total_length > old_total_length)) {
609 assert(append == last_engine);
610 last_engine =
Train::From(last_engine)->GetPrevUnit();
618 for (
auto it = std::next(std::begin(replacements)); it != std::end(replacements); ++it) {
620 if (wagon ==
nullptr)
continue;
621 if (wagon->
First() == new_head)
break;
628 it->new_veh =
nullptr;
647 for (
auto it = std::begin(replacements); it != std::end(replacements); ++it) {
651 if (w->
First() == new_head)
continue;
660 it->old_veh =
nullptr;
661 if (it == std::begin(replacements)) old_head =
nullptr;
676 assert(
Train::From(old_head)->GetNextUnit() ==
nullptr);
678 for (
auto it = std::rbegin(replacements); it != std::rend(replacements); ++it) {
679 [[maybe_unused]]
CommandCost ret =
CmdMoveVehicle(it->old_veh, old_head, {DoCommandFlag::Execute, DoCommandFlag::AutoReplace},
false);
687 for (
auto it = std::rbegin(replacements); it != std::rend(replacements); ++it) {
688 if (it->new_veh !=
nullptr) {
690 it->new_veh =
nullptr;
700 if (cost.
Succeeded() && new_head !=
nullptr) {
701 *nothing_to_do =
false;
742 if (ret.
Failed())
return ret;
746 bool free_wagon =
false;
765 bool any_replacements =
false;
766 while (w !=
nullptr) {
769 if (cost.
Failed())
return cost;
770 any_replacements |= (e != EngineID::Invalid());
775 bool nothing_to_do =
true;
777 if (any_replacements) {
782 if (cost.
Failed())
return cost;
802 ret =
ReplaceChain(&v, flags, wagon_removal, ¬hing_to_do);
835 if (new_engine_type != EngineID::Invalid()) {
Base functions for all AIs.
CargoTypes GetUnionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type)
Ors the refit_masks of all articulated parts.
CargoTypes GetCargoTypesOfArticulatedVehicle(const Vehicle *v, CargoType *cargo_type)
Get cargo mask of all cargoes carried by an articulated vehicle.
void GetArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type, CargoTypes *union_mask, CargoTypes *intersection_mask)
Merges the refit_masks of all articulated parts.
CargoTypes GetCargoTypesOfArticulatedParts(EngineID engine)
Get the cargo mask of the parts of a given engine.
Functions related to articulated vehicles.
static int GetIncompatibleRefitOrderIdForAutoreplace(const Vehicle *v, EngineID engine_type)
Gets the index of the first refit order that is incompatible with the requested engine type.
static CommandCost DoCmdStartStopVehicle(const Vehicle *v, bool evaluate_callback)
Issue a start/stop command.
void CheckCargoCapacity(Vehicle *v)
Check the capacity of all vehicles in a chain and spread cargo if needed.
static CargoType GetNewCargoTypeForReplace(Vehicle *v, EngineID engine_type, bool part_of_chain)
Function to find what type of cargo to refit to when autoreplacing.
void ChangeVehicleViewports(VehicleID from_index, VehicleID to_index)
Switches viewports following vehicles, which get autoreplaced.
static CommandCost CmdMoveVehicle(const Vehicle *v, const Vehicle *after, DoCommandFlags flags, bool whole_chain)
Issue a train vehicle move command.
CommandCost CmdSetAutoReplace(DoCommandFlags flags, GroupID id_g, EngineID old_engine_type, EngineID new_engine_type, bool when_old)
Change engine renewal parameters.
void ChangeVehicleNews(VehicleID from_index, VehicleID to_index)
Report a change in vehicle IDs (due to autoreplace) to affected vehicle news.
void ChangeVehicleViewWindow(VehicleID from_index, VehicleID to_index)
Report a change in vehicle IDs (due to autoreplace) to affected vehicle windows.
static bool EnginesHaveCargoInCommon(EngineID engine_a, EngineID engine_b)
Figure out if two engines got at least one type of cargo in common (refitting if needed)
static bool VerifyAutoreplaceRefitForOrders(const Vehicle *v, EngineID engine_type)
Tests whether refit orders that applied to v will also apply to the new vehicle type.
bool CheckAutoreplaceValidity(EngineID from, EngineID to, CompanyID company)
Checks some basic properties whether autoreplace is allowed.
static CommandCost CopyHeadSpecificThings(Vehicle *old_head, Vehicle *new_head, DoCommandFlags flags)
Copy head specific things to the new vehicle chain after it was successfully constructed.
static CommandCost GetNewEngineType(const Vehicle *v, const Company *c, bool always_replace, EngineID &e)
Get the EngineID of the replacement for a vehicle.
static void TransferCargo(Vehicle *old_veh, Vehicle *new_head, bool part_of_chain)
Transfer cargo from a single (articulated )old vehicle to the new vehicle chain.
static CommandCost ReplaceFreeUnit(Vehicle **single_unit, DoCommandFlags flags, bool *nothing_to_do)
Replace a single unit in a free wagon chain.
static CommandCost BuildReplacementVehicle(Vehicle *old_veh, Vehicle **new_vehicle, bool part_of_chain, DoCommandFlags flags)
Builds and refits a replacement vehicle Important: The old vehicle is still in the original vehicle c...
static CommandCost ReplaceChain(Vehicle **chain, DoCommandFlags flags, bool wagon_removal, bool *nothing_to_do)
Replace a whole vehicle chain.
CommandCost CmdAutoreplaceVehicle(DoCommandFlags flags, VehicleID veh_id)
Autoreplaces a vehicle Trains are replaced as a whole chain, free wagons in depot are replaced on the...
Command definitions related to autoreplace.
Functions related to autoreplacing.
CommandCost AddEngineReplacementForCompany(Company *c, EngineID old_engine, EngineID new_engine, GroupID group, bool replace_when_old, DoCommandFlags flags)
Add an engine replacement for the company.
EngineID EngineReplacementForCompany(const Company *c, EngineID engine, GroupID group, bool *replace_when_old=nullptr)
Retrieve the engine replacement for the given company and original engine type.
CommandCost RemoveEngineReplacementForCompany(Company *c, EngineID engine, GroupID group, DoCommandFlags flags)
Remove an engine replacement for the company.
void InvalidateAutoreplaceWindow(EngineID e, GroupID id_g)
Rebuild the left autoreplace list if an engine is removed or added.
Functions related to the autoreplace GUIs.
Functions related to bit mathematics.
debug_inline constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
constexpr bool HasAtMostOneBit(T value)
Test whether value has at most 1 bit set.
uint8_t CargoType
Cargo slots to indicate a cargo type within a game.
bool IsValidCargoType(CargoType t)
Test whether cargo type is not INVALID_CARGO.
static const CargoType NUM_CARGO
Maximum number of cargo types in a game.
static const CargoType CARGO_NO_REFIT
Do not refit cargo of a vehicle (used in vehicle orders and auto-replace/auto-renew).
static void NewEvent(CompanyID company, ScriptEvent *event)
Queue a new event for an AI.
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
constexpr Timpl & Set()
Set all bits.
constexpr Timpl & Reset(Tvalue_type value)
Reset the value-th bit.
@ MTA_KEEP
Keep the cargo in the vehicle.
Common return value for all commands.
bool Succeeded() const
Did this command succeed?
void AddCost(const Money &cost)
Adds the given cost to the cost of the command.
Money GetCost() const
The costs as made up to this moment.
bool Failed() const
Did this command fail?
StringID GetErrorMessage() const
Returns the error message of a command.
Container for an encoded string, created by GetEncodedString.
RailTypes compatible_railtypes
bitmask to the OTHER railtypes on which an engine of THIS railtype can physically travel
RoadTypes powered_roadtypes
bitmask to the OTHER roadtypes on which a vehicle of THIS roadtype generates power
uint TotalCount() const
Returns sum of cargo, including reserved cargo.
Functions related to commands.
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
@ Execute
execute the given command
@ NoCargoCapacityCheck
when autoreplace/autorenew is in progress, this shall prevent truncating the amount of cargo in the v...
@ AutoReplace
autoreplace/autorenew is in progress, this shall disable vehicle limits when building,...
CommandCost CheckOwnership(Owner owner, TileIndex tile)
Check whether the current owner owns something.
CompanyID _current_company
Company currently doing an action.
Functions related to companies.
bool IsLocalCompany()
Is the current company the local company?
@ EXPENSES_NEW_VEHICLES
New vehicles.
bool IsEngineBuildable(EngineID engine, VehicleType type, CompanyID company)
Check if an engine is buildable.
Functions related to engines.
@ AIR_CTOL
Conventional Take Off and Landing, i.e. planes.
@ RoadIsTram
Road vehicle is a tram/light rail vehicle.
@ RAILVEH_WAGON
simple wagon, not motorized
@ ReplaceWagonRemoval
If set, autoreplace will perform wagon removal on vehicles in this group.
bool IsAllGroupID(GroupID id_g)
Checks if a GroupID stands for all vehicles of a company.
Command definitions related to engine groups.
constexpr uint CeilDiv(uint a, uint b)
Computes ceil(a / b) for non-negative a and b.
@ INVALID_CLIENT_ID
Client is not part of anything.
Functions related to news.
void AddVehicleAdviceNewsItem(AdviceType advice_type, EncodedString &&headline, VehicleID vehicle)
Adds a vehicle-advice news item.
@ AutorenewFailed
Autorenew or autoreplace failed.
Command definitions related to orders.
uint8_t VehicleOrderID
The index of an order within its current vehicle (not pool related)
const RailTypeInfo * GetRailTypeInfo(RailType railtype)
Returns a pointer to the Railtype information for a given railtype.
Pseudo random number generator.
void SaveRandomSeeds(SavedRandomSeeds *storage)
Saves the current seeds.
void RestoreRandomSeeds(const SavedRandomSeeds &storage)
Restores previously saved seeds.
const RoadTypeInfo * GetRoadTypeInfo(RoadType roadtype)
Returns a pointer to the Roadtype information for a given roadtype.
@ ROADTYPES_NONE
No roadtypes.
A number of safeguards to prevent using unsafe methods.
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition of base types and functions in a cross-platform compatible way.
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Functions related to OTTD's strings.
uint8_t subtype
Type of aircraft.
VehicleType type
Type of vehicle.
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo type.
StringID name
Name of this type of cargo.
CompanySettings settings
settings specific for each company
bool renew_keep_length
sell some wagons if after autoreplace the train is longer than before
EngineMiscFlags misc_flags
Miscellaneous flags.
VehicleType type
Vehicle type, ie VEH_ROAD, VEH_TRAIN, etc.
bool CanCarryCargo() const
Determines whether an engine can carry something.
VehicleSettings vehicle
options for vehicles
bool IsRearDualheaded() const
Tell if we are dealing with the rear end of a multiheaded engine.
static void AddProfitLastYear(const Vehicle *v)
Add a vehicle's last year profit to the profit sum of its group.
static void UpdateAutoreplace(CompanyID company)
Update autoreplace_defined and autoreplace_finished of all statistics of a company.
GroupFlags flags
Group flags.
Shared order list linking together the linked list of orders and the list of vehicles sharing this or...
Order * GetOrderAt(int index) const
Get a certain order of the order chain.
VehicleOrderID GetNumOrders() const
Get number of orders in the order list.
CargoType GetRefitCargo() const
Get the cargo to to refit to.
bool IsRefit() const
Is this order a refit order.
static Titem * Get(auto index)
Returns Titem with given index.
Tindex index
Index of this pool item.
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
static Titem * GetIfValid(auto index)
Returns Titem with given index.
RailType railtype
Railtype, mangled if elrail is disabled.
Struct for recording vehicle chain replacement information.
Vehicle * GetVehicle() const
Get vehicle to use for this position.
Vehicle * new_veh
Replacement vehicle, or nullptr if no replacement.
ReplaceChainItem(Vehicle *old_veh, Vehicle *new_veh, Money cost)
Cost of buying and refitting replacement.
Vehicle * old_veh
Old vehicle to replace.
RoadType roadtype
Road type.
Stores the state of all random number generators.
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
T * First() const
Get the first vehicle in the chain.
'Train' is either a loco or a wagon.
Train * GetNextUnit() const
Get the next real (non-articulated part and non rear part of dualheaded engine) vehicle in the consis...
The information about a vehicle list.
uint8_t max_train_length
maximum length for trains
EngineID engine_type
The type of engine used for this vehicle.
const Engine * GetEngine() const
Retrieves the engine of the vehicle.
bool IsStoppedInDepot() const
Check whether the vehicle is in the depot and stopped.
virtual bool IsChainInDepot() const
Check whether the whole vehicle chain is in the depot.
VehicleCargoList cargo
The cargo this vehicle is carrying.
GroupID group_id
Index of group Pool array.
VehStates vehstatus
Status.
bool IsArticulatedPart() const
Check if the vehicle is an articulated part of an engine.
bool NeedsAutorenewing(const Company *c, bool use_renew_setting=true) const
Function to tell if a vehicle needs to be autorenewed.
CargoType cargo_type
type of cargo this vehicle is carrying
debug_inline bool IsFrontEngine() const
Check if the vehicle is a front engine.
Vehicle * First() const
Get the first vehicle of this vehicle chain.
Vehicle * Next() const
Get the next vehicle of this vehicle.
OrderList * orders
Pointer to the order list for this vehicle.
virtual bool IsPrimaryVehicle() const
Whether this is the primary vehicle in the chain.
IterateWrapper Orders() const
Returns an iterable ensemble of orders of a vehicle.
TileIndex tile
Current tile index.
void CopyVehicleConfigAndStatistics(Vehicle *src)
Copy certain configurations and statistics of a vehicle after successful autoreplace/renew The functi...
Owner owner
Which company owns the vehicle?
static const uint TILE_SIZE
Tile size in world coordinates.
Base for the train class.
@ VRF_REVERSE_DIRECTION
Reverse the visible direction of the vehicle.
static constexpr ConsistChangeFlags CCF_LOADUNLOAD
Valid changes while vehicle is loading/unloading.
Command definitions related to trains.
@ Crashed
Vehicle is crashed.
@ Stopped
Vehicle is stopped by the player.
Command definitions for vehicles.
Functions related to vehicles.
uint8_t GetBestFittingSubType(Vehicle *v_from, Vehicle *v_for, CargoType dest_cargo_type)
Get the best fitting subtype when 'cloning'/'replacing' v_from with v_for.
WindowClass GetWindowClassForVehicleType(VehicleType vt)
Get WindowClass for vehicle list of given vehicle type.
VehicleType
Available vehicle types.
@ VEH_ROAD
Road vehicle type.
@ VEH_AIRCRAFT
Aircraft vehicle type.
@ VEH_TRAIN
Train vehicle type.
Functions and type for generating vehicle lists.
@ VL_GROUP_LIST
Index is the group.
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
@ WC_REPLACE_VEHICLE
Replace vehicle window; Window numbers: