31#include "script/api/script_event_types.hpp"
33#include "table/strings.h"
51 return available_cargoes_a.
None() || available_cargoes_b.
None() || available_cargoes_a.
Any(available_cargoes_b);
110 assert(v ==
nullptr || v->
First() == v);
112 for (
Vehicle *src = v; src !=
nullptr; src = src->
Next()) {
113 assert(src->cargo.TotalCount() == src->cargo.ActionCount(VehicleCargoList::MoveToAction::Keep));
116 if (src->cargo.TotalCount() <= src->cargo_cap)
continue;
119 uint to_spread = src->cargo.TotalCount() - src->cargo_cap;
120 for (
Vehicle *dest = v; dest !=
nullptr && to_spread != 0; dest = dest->
Next()) {
121 assert(dest->cargo.TotalCount() == dest->cargo.ActionCount(VehicleCargoList::MoveToAction::Keep));
122 if (dest->cargo.TotalCount() >= dest->cargo_cap || dest->cargo_type != src->cargo_type)
continue;
124 uint amount = std::min(to_spread, dest->cargo_cap - dest->cargo.TotalCount());
125 src->cargo.Shift(amount, &dest->cargo);
130 if (src->cargo_cap < src->cargo.TotalCount()) src->cargo.Truncate(src->cargo.TotalCount() - src->cargo_cap);
147 for (
Vehicle *src = old_veh; src !=
nullptr; src = src->
Next()) {
148 assert(src->cargo.TotalCount() == src->cargo.ActionCount(VehicleCargoList::MoveToAction::Keep));
149 if (!part_of_chain && src->type ==
VehicleType::Train && src != old_veh && src !=
Train::From(old_veh)->other_multiheaded_part && !src->IsArticulatedPart()) {
151 src = src->GetLastEnginePart();
154 if (src->cargo_type >=
NUM_CARGO || src->cargo.TotalCount() == 0)
continue;
158 assert(dest->cargo.TotalCount() == dest->cargo.ActionCount(VehicleCargoList::MoveToAction::Keep));
159 if (!part_of_chain && dest->type ==
VehicleType::Train && dest != new_head && dest !=
Train::From(new_head)->other_multiheaded_part && !dest->IsArticulatedPart()) {
161 dest = dest->GetLastEnginePart();
164 if (dest->cargo_type != src->cargo_type)
continue;
166 uint amount = std::min(src->cargo.TotalCount(), dest->cargo_cap - dest->cargo.TotalCount());
167 if (amount <= 0)
continue;
169 src->cargo.Shift(amount, &dest->cargo);
189 for (
const Order &o : u->Orders()) {
190 if (!o.IsRefit() || o.IsAutoRefit())
continue;
191 CargoType cargo_type = o.GetRefitCargo();
193 if (!union_refit_mask_a.
Test(cargo_type))
continue;
194 if (!union_refit_mask_b.
Test(cargo_type))
return false;
213 if (orders ==
nullptr)
return -1;
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 (!available_cargo_types.
Test(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<Commands::BuildVehicle>::Do({
DoCommandFlag::Execute,
DoCommandFlag::AutoReplace}, old_veh->
tile, e,
true, INVALID_CARGO,
ClientID::Invalid);
362 if (cost.
Failed())
return cost;
365 *new_vehicle = new_veh;
472 if (cost.
Succeeded() && new_v !=
nullptr) {
473 *nothing_to_do =
false;
487 *single_unit = new_v;
489 AI::NewEvent(old_v->
owner,
new ScriptEventVehicleAutoReplaced(old_v->index, new_v->index));
544 std::vector<ReplaceChainItem> replacements;
548 for (
Train *w =
Train::From(old_head); w !=
nullptr; w = w->GetNextUnit()) {
556 if (replacement.
new_veh !=
nullptr) *nothing_to_do =
false;
558 Vehicle *new_head = replacements.front().GetVehicle();
566 assert(
Train::From(new_head)->GetNextUnit() ==
nullptr);
572 Vehicle *last_engine =
nullptr;
574 for (
auto it = std::rbegin(replacements); it != std::rend(replacements); ++it) {
575 Vehicle *append = it->GetVehicle();
579 if (it->new_veh !=
nullptr) {
583 CmdMoveVehicle(it->old_veh,
nullptr, {DoCommandFlag::Execute, DoCommandFlag::AutoReplace},
false);
586 if (last_engine ==
nullptr) last_engine = append;
590 if (last_engine ==
nullptr) last_engine = new_head;
594 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);
600 for (
auto it = std::rbegin(replacements); it != std::rend(replacements); ++it) {
601 assert(last_engine !=
nullptr);
602 Vehicle *append = it->GetVehicle();
611 if (wagon_removal && (res.
Failed() ? res.
GetErrorMessage() == STR_ERROR_TRAIN_TOO_LONG :
Train::From(new_head)->gcache.cached_total_length > old_total_length)) {
620 assert(append == last_engine);
629 for (
auto it = std::next(std::begin(replacements)); it != std::end(replacements); ++it) {
631 if (wagon ==
nullptr)
continue;
632 if (wagon->
First() == new_head)
break;
639 it->new_veh =
nullptr;
654 AI::NewEvent(old_head->
owner,
new ScriptEventVehicleAutoReplaced(old_head->index, new_head->index));
658 for (
auto it = std::begin(replacements); it != std::end(replacements); ++it) {
662 if (w->
First() == new_head)
continue;
671 it->old_veh =
nullptr;
672 if (it == std::begin(replacements)) old_head =
nullptr;
687 assert(
Train::From(old_head)->GetNextUnit() ==
nullptr);
689 for (
auto it = std::rbegin(replacements); it != std::rend(replacements); ++it) {
690 [[maybe_unused]]
CommandCost ret =
CmdMoveVehicle(it->old_veh, old_head, {DoCommandFlag::Execute, DoCommandFlag::AutoReplace},
false);
698 for (
auto it = std::rbegin(replacements); it != std::rend(replacements); ++it) {
699 if (it->new_veh !=
nullptr) {
701 it->new_veh =
nullptr;
711 if (cost.
Succeeded() && new_head !=
nullptr) {
712 *nothing_to_do =
false;
723 AI::NewEvent(old_head->
owner,
new ScriptEventVehicleAutoReplaced(old_head->index, new_head->index));
753 if (ret.
Failed())
return ret;
757 bool free_wagon =
false;
776 bool any_replacements =
false;
777 while (w !=
nullptr) {
780 if (cost.
Failed())
return cost;
781 any_replacements |= (e != EngineID::Invalid());
786 bool nothing_to_do =
true;
788 if (any_replacements) {
793 if (cost.
Failed())
return cost;
813 ret =
ReplaceChain(&v, flags, wagon_removal, ¬hing_to_do);
846 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.
constexpr bool HasAtMostOneBit(T value)
Test whether value has at most 1 bit set.
bool IsValidCargoType(CargoType cargo)
Test whether cargo type is not INVALID_CARGO.
EnumBitSet< CargoType, uint64_t > CargoTypes
Bitset of CargoType elements.
static constexpr CargoType NUM_CARGO
Maximum number of cargo types in a game.
static constexpr CargoType CARGO_NO_REFIT
Do not refit cargo of a vehicle (used in vehicle orders and auto-replace/auto-renew).
CargoType
Cargo slots to indicate a cargo type within a game.
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 Tstorage base() const noexcept
Retrieve the raw value behind this bit set.
constexpr bool None() const
Test if none of the values are set.
constexpr Timpl & Set()
Set all bits.
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
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.
VehicleType type
Vehicle type, ie VehicleType::Road, VehicleType::Train, etc.
bool CanCarryCargo() const
Determines whether an engine can carry something.
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.
CommandCost & ExtractCommandCost(Tret &ret)
Extract the CommandCost from a command proc result.
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,...
EnumBitSet< DoCommandFlag, uint16_t > DoCommandFlags
Bitset of DoCommandFlag elements.
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?
@ NewVehicles
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.
PoolID< uint16_t, struct EngineIDTag, 64000, 0xFFFF > EngineID
Unique identification number of an engine.
@ Wagon
simple wagon, not motorized
constexpr std::underlying_type_t< enum_type > to_underlying(enum_type e)
Implementation of std::to_underlying (from C++23).
@ 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 is not part of anything.
std::optional< bool > TestVehicleBuildProbability(Vehicle *v, BuildProbabilityType type)
Test for vehicle build probability type.
@ Reversed
Change the rail vehicle should be reversed when purchased.
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).
RailTypes GetAllCompatibleRailTypes(RailTypes railtypes)
Returns all compatible railtypes for a set of railtypes.
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.
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.
Information about a aircraft vehicle.
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.
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.
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...
VehicleOrderID GetNumOrders() const
Get number of orders in the order list.
const Order * GetOrderAt(VehicleOrderID index) const
Get a certain order of the order chain.
If you change this, keep in mind that it is also saved in 2 other places:
CargoType GetRefitCargo() const
Get the cargo to to refit to.
bool IsRefit() const
Is this order a refit order.
static Engine * Get(auto index)
static bool IsValidID(auto index)
static Vehicle * GetIfValid(auto index)
Information about a rail vehicle.
RailTypes railtypes
Railtypes, mangled if elrail is disabled.
RailVehicleType railveh_type
Type of rail vehicle.
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)
Create a new item.
Money cost
Cost of buying and refitting replacement.
Vehicle * old_veh
Old vehicle to replace.
Information about a road vehicle.
RoadType roadtype
Road type.
Stores the state of all random number generators.
static Train * From(Vehicle *v)
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...
Train * GetPrevUnit()
Get the previous real (non-articulated part and non rear part of dualheaded engine) vehicle in the co...
void ConsistChanged(ConsistChangeFlags allowed_changes)
Recalculates the cached stuff of a train.
The information about a vehicle list.
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
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.
bool IsFrontEngine() const
Check if the vehicle is a front engine.
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 constexpr uint TILE_SIZE
Tile size in world coordinates.
Base for the train class.
static constexpr ConsistChangeFlags CCF_LOADUNLOAD
Valid changes while vehicle is loading/unloading.
@ Flipped
Reverse the visible direction of the vehicle.
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.
bool IsCompanyBuildableVehicleType(VehicleType type)
Is the given vehicle type buildable by a company?
WindowClass GetWindowClassForVehicleType(VehicleType vt)
Get WindowClass for vehicle list of given vehicle type.
PoolID< uint32_t, struct VehicleIDTag, 0xFF000, 0xFFFFF > VehicleID
The type all our vehicle IDs have.
VehicleType
Available vehicle types.
@ Aircraft
Aircraft vehicle type.
@ Train
Train vehicle type.
Functions and type for generating vehicle lists.
@ Group
Index is the group.
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting).