OpenTTD Source 20250205-master-gfd85ab1e2c
articulated_vehicles.cpp
Go to the documentation of this file.
1/*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
7
10#include "stdafx.h"
11#include "core/bitmath_func.hpp"
12#include "core/random_func.hpp"
13#include "train.h"
14#include "roadveh.h"
15#include "vehicle_func.h"
16#include "engine_func.h"
17#include "company_func.h"
18#include "newgrf.h"
19
20#include "table/strings.h"
21
22#include "safeguards.h"
23
24static const uint MAX_ARTICULATED_PARTS = 100;
25
34static EngineID GetNextArticulatedPart(uint index, EngineID front_type, Vehicle *front = nullptr, bool *mirrored = nullptr)
35{
36 assert(front == nullptr || front->engine_type == front_type);
37
38 const Engine *front_engine = Engine::Get(front_type);
39
40 uint16_t callback = GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE, index, 0, front_type, front);
41 if (callback == CALLBACK_FAILED) return INVALID_ENGINE;
42
43 if (front_engine->GetGRF()->grf_version < 8) {
44 /* 8 bits, bit 7 for mirroring */
45 callback = GB(callback, 0, 8);
46 if (callback == 0xFF) return INVALID_ENGINE;
47 if (mirrored != nullptr) *mirrored = HasBit(callback, 7);
48 callback = GB(callback, 0, 7);
49 } else {
50 /* 15 bits, bit 14 for mirroring */
51 if (callback == 0x7FFF) return INVALID_ENGINE;
52 if (mirrored != nullptr) *mirrored = HasBit(callback, 14);
53 callback = GB(callback, 0, 14);
54 }
55
56 return GetNewEngineID(front_engine->GetGRF(), front_engine->type, callback);
57}
58
65{
66 return EngInfo(engine_type)->callback_mask.Test(VehicleCallbackMask::ArticEngine);
67}
68
75uint CountArticulatedParts(EngineID engine_type, bool purchase_window)
76{
77 if (!EngInfo(engine_type)->callback_mask.Test(VehicleCallbackMask::ArticEngine)) return 0;
78
79 /* If we can't allocate a vehicle now, we can't allocate it in the command
80 * either, so it doesn't matter how many articulated parts there are. */
81 if (!Vehicle::CanAllocateItem()) return 0;
82
83 Vehicle *v = nullptr;
84 if (!purchase_window) {
85 v = new Vehicle();
86 v->engine_type = engine_type;
88 }
89
90 uint i;
91 for (i = 1; i < MAX_ARTICULATED_PARTS; i++) {
92 if (GetNextArticulatedPart(i, engine_type, v) == INVALID_ENGINE) break;
93 }
94
95 delete v;
96
97 return i - 1;
98}
99
100
106static inline std::pair<CargoType, uint16_t> GetVehicleDefaultCapacity(EngineID engine)
107{
108 const Engine *e = Engine::Get(engine);
109 CargoType cargo = e->CanCarryCargo() ? e->GetDefaultCargoType() : INVALID_CARGO;
110 return {cargo, IsValidCargoType(cargo) ? e->GetDisplayDefaultCapacity() : 0};
111}
112
119static inline CargoTypes GetAvailableVehicleCargoTypes(EngineID engine, bool include_initial_cargo_type)
120{
121 const Engine *e = Engine::Get(engine);
122 if (!e->CanCarryCargo()) return 0;
123
124 CargoTypes cargoes = e->info.refit_mask;
125
126 if (include_initial_cargo_type) {
127 SetBit(cargoes, e->GetDefaultCargoType());
128 }
129
130 return cargoes;
131}
132
139{
140 CargoArray capacity{};
141 const Engine *e = Engine::Get(engine);
142
143 if (auto [cargo, cap] = GetVehicleDefaultCapacity(engine); IsValidCargoType(cargo)) {
144 capacity[cargo] = cap;
145 }
146
147 if (!e->IsGroundVehicle()) return capacity;
148
149 if (!e->info.callback_mask.Test(VehicleCallbackMask::ArticEngine)) return capacity;
150
151 for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
152 EngineID artic_engine = GetNextArticulatedPart(i, engine);
153 if (artic_engine == INVALID_ENGINE) break;
154
155 if (auto [cargo, cap] = GetVehicleDefaultCapacity(artic_engine); IsValidCargoType(cargo)) {
156 capacity[cargo] += cap;
157 }
158 }
159
160 return capacity;
161}
162
169{
170 CargoTypes cargoes = 0;
171 const Engine *e = Engine::Get(engine);
172
173 if (auto [cargo, cap] = GetVehicleDefaultCapacity(engine); IsValidCargoType(cargo) && cap > 0) {
174 SetBit(cargoes, cargo);
175 }
176
177 if (!e->IsGroundVehicle()) return cargoes;
178
179 if (!e->info.callback_mask.Test(VehicleCallbackMask::ArticEngine)) return cargoes;
180
181 for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
182 EngineID artic_engine = GetNextArticulatedPart(i, engine);
183 if (artic_engine == INVALID_ENGINE) break;
184
185 if (auto [cargo, cap] = GetVehicleDefaultCapacity(artic_engine); IsValidCargoType(cargo) && cap > 0) {
186 SetBit(cargoes, cargo);
187 }
188 }
189
190 return cargoes;
191}
192
199{
200 if (IsEngineRefittable(engine)) return true;
201
202 const Engine *e = Engine::Get(engine);
203 if (!e->IsGroundVehicle()) return false;
204
205 if (!e->info.callback_mask.Test(VehicleCallbackMask::ArticEngine)) return false;
206
207 for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
208 EngineID artic_engine = GetNextArticulatedPart(i, engine);
209 if (artic_engine == INVALID_ENGINE) break;
210
211 if (IsEngineRefittable(artic_engine)) return true;
212 }
213
214 return false;
215}
216
224void GetArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type, CargoTypes *union_mask, CargoTypes *intersection_mask)
225{
226 const Engine *e = Engine::Get(engine);
227 CargoTypes veh_cargoes = GetAvailableVehicleCargoTypes(engine, include_initial_cargo_type);
228 *union_mask = veh_cargoes;
229 *intersection_mask = (veh_cargoes != 0) ? veh_cargoes : ALL_CARGOTYPES;
230
231 if (!e->IsGroundVehicle()) return;
233
234 for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
235 EngineID artic_engine = GetNextArticulatedPart(i, engine);
236 if (artic_engine == INVALID_ENGINE) break;
237
238 veh_cargoes = GetAvailableVehicleCargoTypes(artic_engine, include_initial_cargo_type);
239 *union_mask |= veh_cargoes;
240 if (veh_cargoes != 0) *intersection_mask &= veh_cargoes;
241 }
242}
243
250CargoTypes GetUnionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type)
251{
252 CargoTypes union_mask, intersection_mask;
253 GetArticulatedRefitMasks(engine, include_initial_cargo_type, &union_mask, &intersection_mask);
254 return union_mask;
255}
256
264CargoTypes GetCargoTypesOfArticulatedVehicle(const Vehicle *v, CargoType *cargo_type)
265{
266 CargoTypes cargoes = 0;
267 CargoType first_cargo = INVALID_CARGO;
268
269 do {
271 SetBit(cargoes, v->cargo_type);
272 if (!IsValidCargoType(first_cargo)) first_cargo = v->cargo_type;
273 if (first_cargo != v->cargo_type) {
274 if (cargo_type != nullptr) {
275 *cargo_type = INVALID_CARGO;
276 cargo_type = nullptr;
277 }
278 }
279 }
280
281 v = v->HasArticulatedPart() ? v->GetNextArticulatedPart() : nullptr;
282 } while (v != nullptr);
283
284 if (cargo_type != nullptr) *cargo_type = first_cargo;
285 return cargoes;
286}
287
297{
298 const Engine *engine = v->GetEngine();
299
300 CargoTypes purchase_refit_union, purchase_refit_intersection;
301 GetArticulatedRefitMasks(v->engine_type, true, &purchase_refit_union, &purchase_refit_intersection);
302 CargoArray purchase_default_capacity = GetCapacityOfArticulatedParts(v->engine_type);
303
304 CargoTypes real_refit_union = 0;
305 CargoTypes real_refit_intersection = ALL_CARGOTYPES;
306 CargoTypes real_default_cargoes = 0;
307
308 do {
309 CargoTypes refit_mask = GetAvailableVehicleCargoTypes(v->engine_type, true);
310 real_refit_union |= refit_mask;
311 if (refit_mask != 0) real_refit_intersection &= refit_mask;
312
313 assert(v->cargo_type < NUM_CARGO);
314 if (v->cargo_cap > 0) SetBit(real_default_cargoes, v->cargo_type);
315
316 v = v->HasArticulatedPart() ? v->GetNextArticulatedPart() : nullptr;
317 } while (v != nullptr);
318
319 /* Check whether the vehicle carries more cargoes than expected */
320 bool carries_more = false;
321 for (CargoType cargo_type : SetCargoBitIterator(real_default_cargoes)) {
322 if (purchase_default_capacity[cargo_type] == 0) {
323 carries_more = true;
324 break;
325 }
326 }
327
328 /* show a warning once for each GRF after each game load */
329 if (real_refit_union != purchase_refit_union || real_refit_intersection != purchase_refit_intersection || carries_more) {
330 ShowNewGrfVehicleError(engine->index, STR_NEWGRF_BUGGY, STR_NEWGRF_BUGGY_ARTICULATED_CARGO, GRFBug::VehRefit, false);
331 }
332}
333
339{
340 VehicleType type = first->type;
341 if (!EngInfo(first->engine_type)->callback_mask.Test(VehicleCallbackMask::ArticEngine)) return;
342
343 Vehicle *v = first;
344 for (uint i = 1; i < MAX_ARTICULATED_PARTS; i++) {
345 bool flip_image;
346 EngineID engine_type = GetNextArticulatedPart(i, first->engine_type, first, &flip_image);
347 if (engine_type == INVALID_ENGINE) return;
348
349 /* In the (very rare) case the GRF reported wrong number of articulated parts
350 * and we run out of available vehicles, bail out. */
351 if (!Vehicle::CanAllocateItem()) return;
352
354 gcache->first_engine = v->engine_type; // Needs to be set before first callback
355
356 const Engine *e_artic = Engine::Get(engine_type);
357 switch (type) {
358 default: NOT_REACHED();
359
360 case VEH_TRAIN: {
361 Train *front = Train::From(first);
362 Train *t = new Train();
363 v->SetNext(t);
364 v = t;
365
366 t->subtype = 0;
367 t->track = front->track;
368 t->railtype = front->railtype;
369
370 t->spritenum = e_artic->u.rail.image_index;
371 if (e_artic->CanCarryCargo()) {
372 t->cargo_type = e_artic->GetDefaultCargoType();
373 t->cargo_cap = e_artic->u.rail.capacity; // Callback 36 is called when the consist is finished
374 } else {
375 t->cargo_type = front->cargo_type; // Needed for livery selection
376 t->cargo_cap = 0;
377 }
378 t->refit_cap = 0;
379
381 break;
382 }
383
384 case VEH_ROAD: {
385 RoadVehicle *front = RoadVehicle::From(first);
386 RoadVehicle *rv = new RoadVehicle();
387 v->SetNext(rv);
388 v = rv;
389
390 rv->subtype = 0;
391 gcache->cached_veh_length = VEHICLE_LENGTH; // Callback is called when the consist is finished
392 rv->state = RVSB_IN_DEPOT;
393
394 rv->roadtype = front->roadtype;
396
397 rv->spritenum = e_artic->u.road.image_index;
398 if (e_artic->CanCarryCargo()) {
399 rv->cargo_type = e_artic->GetDefaultCargoType();
400 assert(IsValidCargoType(rv->cargo_type));
401 rv->cargo_cap = e_artic->u.road.capacity; // Callback 36 is called when the consist is finished
402 } else {
403 rv->cargo_type = front->cargo_type; // Needed for livery selection
404 rv->cargo_cap = 0;
405 }
406 rv->refit_cap = 0;
407
408 rv->SetArticulatedPart();
409 break;
410 }
411 }
412
413 /* get common values from first engine */
414 v->direction = first->direction;
415 v->owner = first->owner;
416 v->tile = first->tile;
417 v->x_pos = first->x_pos;
418 v->y_pos = first->y_pos;
419 v->z_pos = first->z_pos;
422 v->build_year = first->build_year;
423 v->vehstatus = first->vehstatus & ~VS_STOPPED;
424
425 v->cargo_subtype = 0;
427 v->engine_type = engine_type;
428 v->value = 0;
429 v->sprite_cache.sprite_seq.Set(SPR_IMG_QUERY);
430 v->random_bits = Random();
431
432 if (flip_image) v->spritenum++;
433
434 if (v->type == VEH_TRAIN && TestVehicleBuildProbability(v, v->engine_type, BuildProbabilityType::Reversed)) SetBit(Train::From(v)->flags, VRF_REVERSE_DIRECTION);
435 v->UpdatePosition();
436 }
437}
CargoTypes GetUnionOfArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type)
Ors the refit_masks of all articulated parts.
bool IsArticulatedEngine(EngineID engine_type)
Does a NewGRF report that this should be an articulated vehicle?
static const uint MAX_ARTICULATED_PARTS
Maximum of articulated parts per vehicle, i.e. when to abort calling the articulated vehicle callback...
void AddArticulatedParts(Vehicle *first)
Add the remaining articulated parts to the given vehicle.
CargoArray GetCapacityOfArticulatedParts(EngineID engine)
Get the capacity of the parts of a given engine.
bool IsArticulatedVehicleRefittable(EngineID engine)
Checks whether any of the articulated parts is refittable.
CargoTypes GetCargoTypesOfArticulatedVehicle(const Vehicle *v, CargoType *cargo_type)
Get cargo mask of all cargoes carried by an articulated vehicle.
static std::pair< CargoType, uint16_t > GetVehicleDefaultCapacity(EngineID engine)
Returns the default (non-refitted) cargo and capacity of a specific EngineID.
void GetArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type, CargoTypes *union_mask, CargoTypes *intersection_mask)
Merges the refit_masks of all articulated parts.
void CheckConsistencyOfArticulatedVehicle(const Vehicle *v)
Checks whether the specs of freshly build articulated vehicles are consistent with the information sp...
CargoTypes GetCargoTypesOfArticulatedParts(EngineID engine)
Get the cargo mask of the parts of a given engine.
static EngineID GetNextArticulatedPart(uint index, EngineID front_type, Vehicle *front=nullptr, bool *mirrored=nullptr)
Determines the next articulated part to attach.
uint CountArticulatedParts(EngineID engine_type, bool purchase_window)
Count the number of articulated parts of an engine.
static CargoTypes GetAvailableVehicleCargoTypes(EngineID engine, bool include_initial_cargo_type)
Returns all cargoes a vehicle can carry.
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 T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
debug_inline static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
uint8_t CargoType
Cargo slots to indicate a cargo type within a game.
Definition cargo_type.h:22
bool IsValidCargoType(CargoType t)
Test whether cargo type is not INVALID_CARGO.
Definition cargo_type.h:105
static const CargoType NUM_CARGO
Maximum number of cargo types in a game.
Definition cargo_type.h:74
constexpr bool Test(Tenum value) const
Test if the enum value is set.
static constexpr TimerGame< struct Calendar >::Date MIN_DATE
The date on January 1, year 0.
CompanyID _current_company
Company currently doing an action.
Functions related to companies.
bool IsEngineRefittable(EngineID engine)
Check if an engine is refittable.
Definition engine.cpp:1295
Functions related to engines.
static const EngineID INVALID_ENGINE
Constant denoting an invalid engine.
uint16_t EngineID
Unique identification number of an engine.
Definition engine_type.h:23
@ Random
Randomise borders.
EngineID GetNewEngineID(const GRFFile *file, VehicleType type, uint16_t internal_id)
Return the ID of a new engine.
Definition newgrf.cpp:711
Base for the NewGRF implementation.
@ ArticEngine
Add articulated engines (trains and road vehicles)
@ CBID_VEHICLE_ARTIC_ENGINE
Builds articulated engines for trains and RVs.
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
@ VehRefit
Articulated vehicles carry different cargoes resp. are differently refittable than specified in purch...
bool TestVehicleBuildProbability(Vehicle *v, EngineID engine, BuildProbabilityType type)
Test for vehicle build probablity type.
uint16_t GetVehicleCallback(CallbackID callback, uint32_t param1, uint32_t param2, EngineID engine, const Vehicle *v)
Evaluate a newgrf callback for vehicles.
Pseudo random number generator.
Road vehicle states.
@ RVSB_IN_DEPOT
The vehicle is in a depot.
Definition roadveh.h:38
A number of safeguards to prevent using unsafe methods.
Definition of base types and functions in a cross-platform compatible way.
VehicleType type
Type of vehicle.
Class for storing amounts of cargo.
Definition cargo_type.h:112
VehicleCallbackMasks callback_mask
Bitmask of vehicle callbacks that have to be called.
const GRFFile * GetGRF() const
Retrieve the NewGRF the engine is tied to.
VehicleType type
Vehicle type, ie VEH_ROAD, VEH_TRAIN, etc.
Definition engine_base.h:61
uint GetDisplayDefaultCapacity(uint16_t *mail_capacity=nullptr) const
Determines the default cargo capacity of an engine for display purposes.
CargoType GetDefaultCargoType() const
Determines the default cargo type of an engine.
bool CanCarryCargo() const
Determines whether an engine can carry something.
Definition engine.cpp:168
bool IsGroundVehicle() const
Check if the engine is a ground vehicle.
Cached, frequently calculated values.
EngineID first_engine
Cached EngineID of the front vehicle. INVALID_ENGINE for the front vehicle itself.
uint8_t cached_veh_length
Length of this vehicle in units of 1/VEHICLE_LENGTH of normal length. It is cached because this can b...
void SetArticulatedPart()
Set a vehicle to be an articulated part.
VehicleSpriteSeq sprite_seq
Vehicle appearance.
Tindex index
Index of this pool item.
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
static Titem * Get(size_t index)
Returns Titem with given index.
uint8_t capacity
Cargo capacity of vehicle; For multiheaded engines the capacity of each single engine.
Definition engine_type.h:57
Buses, trucks and trams belong to this class.
Definition roadveh.h:98
uint8_t state
Definition roadveh.h:100
RoadTypes compatible_roadtypes
NOSAVE: Roadtypes this consist is powered on.
Definition roadveh.h:110
RoadType roadtype
NOSAVE: Roadtype of this vehicle.
Definition roadveh.h:108
Iterable ensemble of each set bit in a value.
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
'Train' is either a loco or a wagon.
Definition train.h:89
void Set(SpriteID sprite)
Assign a single sprite to the sequence.
Vehicle data structure.
EngineID engine_type
The type of engine used for this vehicle.
int32_t z_pos
z coordinate.
Direction direction
facing
const Engine * GetEngine() const
Retrieves the engine of the vehicle.
Definition vehicle.cpp:747
Vehicle * GetNextArticulatedPart() const
Get the next part of an articulated engine.
TimerGameEconomy::Date date_of_last_service
Last economy date the vehicle had a service at a depot.
uint16_t cargo_cap
total capacity
uint8_t subtype
subtype (Filled with values from AircraftSubType/DisasterSubType/EffectVehicleType/GroundVehicleSubty...
uint16_t random_bits
Bits used for randomized variational spritegroups.
bool HasArticulatedPart() const
Check if an engine has an articulated part.
TimerGameCalendar::Date date_of_last_service_newgrf
Last calendar date the vehicle had a service at a depot, unchanged by the date cheat to protect again...
CargoType cargo_type
type of cargo this vehicle is carrying
int32_t y_pos
y coordinate.
int32_t x_pos
x coordinate.
Money value
Value of the vehicle.
uint16_t refit_cap
Capacity left over from before last refit.
uint8_t vehstatus
Status.
GroundVehicleCache * GetGroundVehicleCache()
Access the ground vehicle cache of the vehicle.
Definition vehicle.cpp:3155
uint8_t spritenum
currently displayed sprite index 0xfd == custom sprite, 0xfe == custom second head sprite 0xff == res...
uint8_t cargo_subtype
Used for livery refits (NewGRF variations)
void SetNext(Vehicle *next)
Set the next vehicle of this vehicle.
Definition vehicle.cpp:2937
TimerGameCalendar::Date max_age
Maximum age.
MutableSpriteCache sprite_cache
Cache of sprites and values related to recalculating them, see MutableSpriteCache.
TileIndex tile
Current tile index.
void UpdatePosition()
Update the position of the vehicle.
Definition vehicle.cpp:1693
TimerGameCalendar::Year build_year
Year the vehicle has been built.
Owner owner
Which company owns the vehicle?
Base for the train class.
@ VRF_REVERSE_DIRECTION
Reverse the visible direction of the vehicle.
Definition train.h:28
void ShowNewGrfVehicleError(EngineID engine, StringID part1, StringID part2, GRFBug bug_type, bool critical)
Displays a "NewGrf Bug" error message for a engine, and pauses the game if not networking.
Definition vehicle.cpp:317
Functions related to vehicles.
VehicleType
Available vehicle types.
@ VEH_ROAD
Road vehicle type.
@ VEH_TRAIN
Train vehicle type.
static const uint VEHICLE_LENGTH
The length of a vehicle in tile units.