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/>.
8 /** @file articulated_vehicles.cpp Implementation of articulated vehicles. */
11 #include "core/bitmath_func.hpp"
12 #include "core/random_func.hpp"
15 #include "vehicle_func.h"
16 #include "engine_func.h"
17 #include "company_func.h"
20 #include "table/strings.h"
22 #include "safeguards.h"
24 static const uint MAX_ARTICULATED_PARTS
= 100; ///< Maximum of articulated parts per vehicle, i.e. when to abort calling the articulated vehicle callback.
27 * Determines the next articulated part to attach
28 * @param index Position in chain
29 * @param front_type Front engine type
30 * @param front Front engine
31 * @param mirrored Returns whether the part shall be flipped.
32 * @return engine to add or INVALID_ENGINE
34 static EngineID
GetNextArticulatedPart(uint index
, EngineID front_type
, Vehicle
*front
= nullptr, bool *mirrored
= nullptr)
36 assert(front
== nullptr || front
->engine_type
== front_type
);
38 const Engine
*front_engine
= Engine::Get(front_type
);
40 uint16_t callback
= GetVehicleCallback(CBID_VEHICLE_ARTIC_ENGINE
, index
, 0, front_type
, front
);
41 if (callback
== CALLBACK_FAILED
) return INVALID_ENGINE
;
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);
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);
56 return GetNewEngineID(front_engine
->GetGRF(), front_engine
->type
, callback
);
60 * Does a NewGRF report that this should be an articulated vehicle?
61 * @param engine_type The engine to check.
62 * @return True iff the articulated engine callback flag is set.
64 bool IsArticulatedEngine(EngineID engine_type
)
66 return HasBit(EngInfo(engine_type
)->callback_mask
, CBM_VEHICLE_ARTIC_ENGINE
);
70 * Count the number of articulated parts of an engine.
71 * @param engine_type The engine to get the number of parts of.
72 * @param purchase_window Whether we are in the scope of the purchase window or not, i.e. whether we cannot allocate vehicles.
73 * @return The number of parts.
75 uint
CountArticulatedParts(EngineID engine_type
, bool purchase_window
)
77 if (!HasBit(EngInfo(engine_type
)->callback_mask
, CBM_VEHICLE_ARTIC_ENGINE
)) return 0;
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;
84 if (!purchase_window
) {
86 v
->engine_type
= engine_type
;
87 v
->owner
= _current_company
;
91 for (i
= 1; i
< MAX_ARTICULATED_PARTS
; i
++) {
92 if (GetNextArticulatedPart(i
, engine_type
, v
) == INVALID_ENGINE
) break;
102 * Returns the default (non-refitted) capacity of a specific EngineID.
103 * @param engine the EngineID of interest
104 * @param cargo_type returns the default cargo type, if needed
107 static inline uint16_t GetVehicleDefaultCapacity(EngineID engine
, CargoID
*cargo_type
)
109 const Engine
*e
= Engine::Get(engine
);
110 CargoID cargo
= (e
->CanCarryCargo() ? e
->GetDefaultCargoType() : INVALID_CARGO
);
111 if (cargo_type
!= nullptr) *cargo_type
= cargo
;
112 if (!IsValidCargoID(cargo
)) return 0;
113 return e
->GetDisplayDefaultCapacity();
117 * Returns all cargoes a vehicle can carry.
118 * @param engine the EngineID of interest
119 * @param include_initial_cargo_type if true the default cargo type of the vehicle is included; if false only the refit_mask
120 * @return bit set of CargoIDs
122 static inline CargoTypes
GetAvailableVehicleCargoTypes(EngineID engine
, bool include_initial_cargo_type
)
124 const Engine
*e
= Engine::Get(engine
);
125 if (!e
->CanCarryCargo()) return 0;
127 CargoTypes cargoes
= e
->info
.refit_mask
;
129 if (include_initial_cargo_type
) {
130 SetBit(cargoes
, e
->GetDefaultCargoType());
137 * Get the capacity of the parts of a given engine.
138 * @param engine The engine to get the capacities from.
139 * @return The cargo capacities.
141 CargoArray
GetCapacityOfArticulatedParts(EngineID engine
)
143 CargoArray capacity
{};
144 const Engine
*e
= Engine::Get(engine
);
147 uint16_t cargo_capacity
= GetVehicleDefaultCapacity(engine
, &cargo_type
);
148 if (cargo_type
< NUM_CARGO
) capacity
[cargo_type
] = cargo_capacity
;
150 if (!e
->IsGroundVehicle()) return capacity
;
152 if (!HasBit(e
->info
.callback_mask
, CBM_VEHICLE_ARTIC_ENGINE
)) return capacity
;
154 for (uint i
= 1; i
< MAX_ARTICULATED_PARTS
; i
++) {
155 EngineID artic_engine
= GetNextArticulatedPart(i
, engine
);
156 if (artic_engine
== INVALID_ENGINE
) break;
158 cargo_capacity
= GetVehicleDefaultCapacity(artic_engine
, &cargo_type
);
159 if (cargo_type
< NUM_CARGO
) capacity
[cargo_type
] += cargo_capacity
;
166 * Get the cargo mask of the parts of a given engine.
167 * @param engine The engine to get the capacities from.
168 * @return The cargo mask.
170 CargoTypes
GetCargoTypesOfArticulatedParts(EngineID engine
)
172 CargoTypes cargoes
= 0;
173 const Engine
*e
= Engine::Get(engine
);
176 uint16_t cargo_capacity
= GetVehicleDefaultCapacity(engine
, &cargo_type
);
177 if (cargo_type
< NUM_CARGO
&& cargo_capacity
> 0) SetBit(cargoes
, cargo_type
);
179 if (!e
->IsGroundVehicle()) return cargoes
;
181 if (!HasBit(e
->info
.callback_mask
, CBM_VEHICLE_ARTIC_ENGINE
)) return cargoes
;
183 for (uint i
= 1; i
< MAX_ARTICULATED_PARTS
; i
++) {
184 EngineID artic_engine
= GetNextArticulatedPart(i
, engine
);
185 if (artic_engine
== INVALID_ENGINE
) break;
187 cargo_capacity
= GetVehicleDefaultCapacity(artic_engine
, &cargo_type
);
188 if (cargo_type
< NUM_CARGO
&& cargo_capacity
> 0) SetBit(cargoes
, cargo_type
);
195 * Checks whether any of the articulated parts is refittable
196 * @param engine the first part
197 * @return true if refittable
199 bool IsArticulatedVehicleRefittable(EngineID engine
)
201 if (IsEngineRefittable(engine
)) return true;
203 const Engine
*e
= Engine::Get(engine
);
204 if (!e
->IsGroundVehicle()) return false;
206 if (!HasBit(e
->info
.callback_mask
, CBM_VEHICLE_ARTIC_ENGINE
)) return false;
208 for (uint i
= 1; i
< MAX_ARTICULATED_PARTS
; i
++) {
209 EngineID artic_engine
= GetNextArticulatedPart(i
, engine
);
210 if (artic_engine
== INVALID_ENGINE
) break;
212 if (IsEngineRefittable(artic_engine
)) return true;
219 * Merges the refit_masks of all articulated parts.
220 * @param engine the first part
221 * @param include_initial_cargo_type if true the default cargo type of the vehicle is included; if false only the refit_mask
222 * @param union_mask returns bit mask of CargoIDs which are a refit option for at least one articulated part
223 * @param intersection_mask returns bit mask of CargoIDs which are a refit option for every articulated part (with default capacity > 0)
225 void GetArticulatedRefitMasks(EngineID engine
, bool include_initial_cargo_type
, CargoTypes
*union_mask
, CargoTypes
*intersection_mask
)
227 const Engine
*e
= Engine::Get(engine
);
228 CargoTypes veh_cargoes
= GetAvailableVehicleCargoTypes(engine
, include_initial_cargo_type
);
229 *union_mask
= veh_cargoes
;
230 *intersection_mask
= (veh_cargoes
!= 0) ? veh_cargoes
: ALL_CARGOTYPES
;
232 if (!e
->IsGroundVehicle()) return;
233 if (!HasBit(e
->info
.callback_mask
, CBM_VEHICLE_ARTIC_ENGINE
)) return;
235 for (uint i
= 1; i
< MAX_ARTICULATED_PARTS
; i
++) {
236 EngineID artic_engine
= GetNextArticulatedPart(i
, engine
);
237 if (artic_engine
== INVALID_ENGINE
) break;
239 veh_cargoes
= GetAvailableVehicleCargoTypes(artic_engine
, include_initial_cargo_type
);
240 *union_mask
|= veh_cargoes
;
241 if (veh_cargoes
!= 0) *intersection_mask
&= veh_cargoes
;
246 * Ors the refit_masks of all articulated parts.
247 * @param engine the first part
248 * @param include_initial_cargo_type if true the default cargo type of the vehicle is included; if false only the refit_mask
249 * @return bit mask of CargoIDs which are a refit option for at least one articulated part
251 CargoTypes
GetUnionOfArticulatedRefitMasks(EngineID engine
, bool include_initial_cargo_type
)
253 CargoTypes union_mask
, intersection_mask
;
254 GetArticulatedRefitMasks(engine
, include_initial_cargo_type
, &union_mask
, &intersection_mask
);
259 * Get cargo mask of all cargoes carried by an articulated vehicle.
260 * Note: Vehicles not carrying anything are ignored
261 * @param v the first vehicle in the chain
262 * @param cargo_type returns the common CargoID if needed. (INVALID_CARGO if no part is carrying something or they are carrying different things)
263 * @return cargo mask, may be 0 if the no vehicle parts have cargo capacity
265 CargoTypes
GetCargoTypesOfArticulatedVehicle(const Vehicle
*v
, CargoID
*cargo_type
)
267 CargoTypes cargoes
= 0;
268 CargoID first_cargo
= INVALID_CARGO
;
271 if (IsValidCargoID(v
->cargo_type
) && v
->GetEngine()->CanCarryCargo()) {
272 SetBit(cargoes
, v
->cargo_type
);
273 if (!IsValidCargoID(first_cargo
)) first_cargo
= v
->cargo_type
;
274 if (first_cargo
!= v
->cargo_type
) {
275 if (cargo_type
!= nullptr) {
276 *cargo_type
= INVALID_CARGO
;
277 cargo_type
= nullptr;
282 v
= v
->HasArticulatedPart() ? v
->GetNextArticulatedPart() : nullptr;
283 } while (v
!= nullptr);
285 if (cargo_type
!= nullptr) *cargo_type
= first_cargo
;
290 * Checks whether the specs of freshly build articulated vehicles are consistent with the information specified in the purchase list.
291 * Only essential information is checked to leave room for magic tricks/workarounds to grfcoders.
293 * For autoreplace/-renew:
294 * - Default cargo type (without capacity)
295 * - intersection and union of refit masks.
297 void CheckConsistencyOfArticulatedVehicle(const Vehicle
*v
)
299 const Engine
*engine
= v
->GetEngine();
301 CargoTypes purchase_refit_union
, purchase_refit_intersection
;
302 GetArticulatedRefitMasks(v
->engine_type
, true, &purchase_refit_union
, &purchase_refit_intersection
);
303 CargoArray purchase_default_capacity
= GetCapacityOfArticulatedParts(v
->engine_type
);
305 CargoTypes real_refit_union
= 0;
306 CargoTypes real_refit_intersection
= ALL_CARGOTYPES
;
307 CargoTypes real_default_cargoes
= 0;
310 CargoTypes refit_mask
= GetAvailableVehicleCargoTypes(v
->engine_type
, true);
311 real_refit_union
|= refit_mask
;
312 if (refit_mask
!= 0) real_refit_intersection
&= refit_mask
;
314 assert(v
->cargo_type
< NUM_CARGO
);
315 if (v
->cargo_cap
> 0) SetBit(real_default_cargoes
, v
->cargo_type
);
317 v
= v
->HasArticulatedPart() ? v
->GetNextArticulatedPart() : nullptr;
318 } while (v
!= nullptr);
320 /* Check whether the vehicle carries more cargoes than expected */
321 bool carries_more
= false;
322 for (CargoID cid
: SetCargoBitIterator(real_default_cargoes
)) {
323 if (purchase_default_capacity
[cid
] == 0) {
329 /* show a warning once for each GRF after each game load */
330 if (real_refit_union
!= purchase_refit_union
|| real_refit_intersection
!= purchase_refit_intersection
|| carries_more
) {
331 ShowNewGrfVehicleError(engine
->index
, STR_NEWGRF_BUGGY
, STR_NEWGRF_BUGGY_ARTICULATED_CARGO
, GBUG_VEH_REFIT
, false);
336 * Add the remaining articulated parts to the given vehicle.
337 * @param first The head of the articulated bit.
339 void AddArticulatedParts(Vehicle
*first
)
341 VehicleType type
= first
->type
;
342 if (!HasBit(EngInfo(first
->engine_type
)->callback_mask
, CBM_VEHICLE_ARTIC_ENGINE
)) return;
345 for (uint i
= 1; i
< MAX_ARTICULATED_PARTS
; i
++) {
347 EngineID engine_type
= GetNextArticulatedPart(i
, first
->engine_type
, first
, &flip_image
);
348 if (engine_type
== INVALID_ENGINE
) return;
350 /* In the (very rare) case the GRF reported wrong number of articulated parts
351 * and we run out of available vehicles, bail out. */
352 if (!Vehicle::CanAllocateItem()) return;
354 GroundVehicleCache
*gcache
= v
->GetGroundVehicleCache();
355 gcache
->first_engine
= v
->engine_type
; // Needs to be set before first callback
357 const Engine
*e_artic
= Engine::Get(engine_type
);
359 default: NOT_REACHED();
362 Train
*front
= Train::From(first
);
363 Train
*t
= new Train();
368 t
->track
= front
->track
;
369 t
->railtype
= front
->railtype
;
371 t
->spritenum
= e_artic
->u
.rail
.image_index
;
372 if (e_artic
->CanCarryCargo()) {
373 t
->cargo_type
= e_artic
->GetDefaultCargoType();
374 t
->cargo_cap
= e_artic
->u
.rail
.capacity
; // Callback 36 is called when the consist is finished
376 t
->cargo_type
= front
->cargo_type
; // Needed for livery selection
381 t
->SetArticulatedPart();
386 RoadVehicle
*front
= RoadVehicle::From(first
);
387 RoadVehicle
*rv
= new RoadVehicle();
392 gcache
->cached_veh_length
= VEHICLE_LENGTH
; // Callback is called when the consist is finished
393 rv
->state
= RVSB_IN_DEPOT
;
395 rv
->roadtype
= front
->roadtype
;
396 rv
->compatible_roadtypes
= front
->compatible_roadtypes
;
398 rv
->spritenum
= e_artic
->u
.road
.image_index
;
399 if (e_artic
->CanCarryCargo()) {
400 rv
->cargo_type
= e_artic
->GetDefaultCargoType();
401 assert(IsValidCargoID(rv
->cargo_type
));
402 rv
->cargo_cap
= e_artic
->u
.road
.capacity
; // Callback 36 is called when the consist is finished
404 rv
->cargo_type
= front
->cargo_type
; // Needed for livery selection
409 rv
->SetArticulatedPart();
414 /* get common values from first engine */
415 v
->direction
= first
->direction
;
416 v
->owner
= first
->owner
;
417 v
->tile
= first
->tile
;
418 v
->x_pos
= first
->x_pos
;
419 v
->y_pos
= first
->y_pos
;
420 v
->z_pos
= first
->z_pos
;
421 v
->date_of_last_service
= first
->date_of_last_service
;
422 v
->date_of_last_service_newgrf
= first
->date_of_last_service_newgrf
;
423 v
->build_year
= first
->build_year
;
424 v
->vehstatus
= first
->vehstatus
& ~VS_STOPPED
;
426 v
->cargo_subtype
= 0;
428 v
->engine_type
= engine_type
;
430 v
->sprite_cache
.sprite_seq
.Set(SPR_IMG_QUERY
);
431 v
->random_bits
= Random();
433 if (flip_image
) v
->spritenum
++;
435 if (v
->type
== VEH_TRAIN
&& TestVehicleBuildProbability(v
, v
->engine_type
, BuildProbabilityType::Reversed
)) SetBit(Train::From(v
)->flags
, VRF_REVERSE_DIRECTION
);