OpenTTD Source: src/vehicle.cpp Source File

OpenTTD Source 15.0-RC2

vehicle.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 <https://www.gnu.org/licenses/old-licenses/gpl-2.0>.
6 */
7
10#include "stdafx.h"
11#include "error.h"
12#include "roadveh.h"
13#include "ship.h"
14#include "spritecache.h"
15#include "timetable.h"
16#include "viewport_func.h"
17#include "news_func.h"
18#include "command_func.h"
19#include "company_func.h"
20#include "train.h"
21#include "aircraft.h"
22#include "newgrf_debug.h"
23#include "newgrf_sound.h"
24#include "newgrf_station.h"
25#include "group_gui.h"
26#include "strings_func.h"
27#include "zoom_func.h"
28#include "vehicle_func.h"
29#include "autoreplace_func.h"
30#include "autoreplace_gui.h"
31#include "station_base.h"
32#include "ai/ai.hpp"
33#include "depot_func.h"
34#include "network/network.h"
35#include "core/pool_func.hpp"
36#include "economy_base.h"
37#include "articulated_vehicles.h"
38#include "roadstop_base.h"
39#include "core/random_func.hpp"
40#include "core/backup_type.hpp"
41#include "core/container_func.hpp"
42#include "order_backup.h"
43#include "sound_func.h"
44#include "effectvehicle_func.h"
45#include "effectvehicle_base.h"
46#include "vehiclelist.h"
47#include "bridge_map.h"
48#include "tunnel_map.h"
49#include "depot_map.h"
50#include "gamelog.h"
51#include "linkgraph/linkgraph.h"
52#include "linkgraph/refresh.h"
53#include "framerate_type.h"
54#include "autoreplace_cmd.h"
55#include "misc_cmd.h"
56#include "train_cmd.h"
57#include "vehicle_cmd.h"
58#include "newgrf_roadstop.h"
59#include "timer/timer.h"
60#include "timer/timer_game_calendar.h"
61#include "timer/timer_game_economy.h"
62#include "timer/timer_game_tick.h"
63
64#include "table/strings.h"
65
66#include "safeguards.h"
67
68/* Number of bits in the hash to use from each vehicle coord */
69static const uint GEN_HASHX_BITS = 6;
70static const uint GEN_HASHY_BITS = 6;
71
72/* Size of each hash bucket */
73static const uint GEN_HASHX_BUCKET_BITS = 7;
74static const uint GEN_HASHY_BUCKET_BITS = 6;
75
76/* Compute hash for vehicle coord */
77static inline uint GetViewportHashX(int x)
78{
79 return GB(x, GEN_HASHX_BUCKET_BITS + ZOOM_BASE_SHIFT, GEN_HASHX_BITS);
80}
81
82static inline uint GetViewportHashY(int y)
83{
84 return GB(y, GEN_HASHY_BUCKET_BITS + ZOOM_BASE_SHIFT, GEN_HASHY_BITS) << GEN_HASHX_BITS;
85}
86
87static inline uint GetViewportHash(int x, int y)
88{
89 return GetViewportHashX(x) + GetViewportHashY(y);
90}
91
92/* Maximum size until hash repeats */
93static const uint GEN_HASHX_SIZE = 1 << (GEN_HASHX_BUCKET_BITS + GEN_HASHX_BITS + ZOOM_BASE_SHIFT);
94static const uint GEN_HASHY_SIZE = 1 << (GEN_HASHY_BUCKET_BITS + GEN_HASHY_BITS + ZOOM_BASE_SHIFT);
95
96/* Increments to reach next bucket in hash table */
97static const uint GEN_HASHX_INC = 1;
98static const uint GEN_HASHY_INC = 1 << GEN_HASHX_BITS;
99
100/* Mask to wrap-around buckets */
101static const uint GEN_HASHX_MASK = (1 << GEN_HASHX_BITS) - 1;
102static const uint GEN_HASHY_MASK = ((1 << GEN_HASHY_BITS) - 1) << GEN_HASHX_BITS;
103
104
106 VehiclePool _vehicle_pool("Vehicle");
107 INSTANTIATE_POOL_METHODS(Vehicle)
108
109
110
114void VehicleSpriteSeq::GetBounds(Rect *bounds) const
115{
116 bounds->left = bounds->top = bounds->right = bounds->bottom = 0;
117 for (uint i = 0; i < this->count; ++i) {
118 const Sprite *spr = GetSprite(this->seq[i].sprite, SpriteType::Normal);
119 if (i == 0) {
120 bounds->left = spr->x_offs;
121 bounds->top = spr->y_offs;
122 bounds->right = spr->width + spr->x_offs - 1;
123 bounds->bottom = spr->height + spr->y_offs - 1;
124 } else {
125 if (spr->x_offs < bounds->left) bounds->left = spr->x_offs;
126 if (spr->y_offs < bounds->top) bounds->top = spr->y_offs;
127 int right = spr->width + spr->x_offs - 1;
128 int bottom = spr->height + spr->y_offs - 1;
129 if (right > bounds->right) bounds->right = right;
130 if (bottom > bounds->bottom) bounds->bottom = bottom;
131 }
132 }
133}
134
142 void VehicleSpriteSeq::Draw(int x, int y, PaletteID default_pal, bool force_pal) const
143{
144 for (uint i = 0; i < this->count; ++i) {
145 PaletteID pal = force_pal || !this->seq[i].pal ? default_pal : this->seq[i].pal;
146 DrawSprite(this->seq[i].sprite, pal, x, y);
147 }
148}
149
156 bool Vehicle::NeedsAutorenewing(const Company *c, bool use_renew_setting) const
157{
158 /* We can always generate the Company pointer when we have the vehicle.
159 * However this takes time and since the Company pointer is often present
160 * when this function is called then it's faster to pass the pointer as an
161 * argument rather than finding it again. */
162 assert(c == Company::Get(this->owner));
163
164 if (use_renew_setting && !c->settings.engine_renew) return false;
165 if (this->age - this->max_age < (c->settings.engine_renew_months * 30)) return false;
166
167 /* Only engines need renewing */
168 if (this->type == VEH_TRAIN && !Train::From(this)->IsEngine()) return false;
169
170 return true;
171}
172
178 void VehicleServiceInDepot(Vehicle *v)
179{
180 assert(v != nullptr);
181 SetWindowDirty(WC_VEHICLE_DETAILS, v->index); // ensure that last service date and reliability are updated
182
183 do {
184 v->date_of_last_service = TimerGameEconomy::date;
185 v->date_of_last_service_newgrf = TimerGameCalendar::date;
186 v->breakdowns_since_last_service = 0;
187 v->reliability = v->GetEngine()->reliability;
188 /* Prevent vehicles from breaking down directly after exiting the depot. */
189 v->breakdown_chance /= 4;
190 if (_settings_game.difficulty.vehicle_breakdowns == 1) v->breakdown_chance = 0; // on reduced breakdown
191 v = v->Next();
192 } while (v != nullptr && v->HasEngineType());
193}
194
201 bool Vehicle::NeedsServicing() const
202{
203 /* Stopped or crashed vehicles will not move, as such making unmovable
204 * vehicles to go for service is lame. */
205 if (this->vehstatus.Any({VehState::Stopped, VehState::Crashed})) return false;
206
207 /* Are we ready for the next service cycle? */
208 const Company *c = Company::Get(this->owner);
209
210 /* Service intervals can be measured in different units, which we handle individually. */
211 if (this->ServiceIntervalIsPercent()) {
212 /* Service interval is in percents. */
213 if (this->reliability >= this->GetEngine()->reliability * (100 - this->GetServiceInterval()) / 100) return false;
214 } else if (TimerGameEconomy::UsingWallclockUnits()) {
215 /* Service interval is in minutes. */
216 if (this->date_of_last_service + (this->GetServiceInterval() * EconomyTime::DAYS_IN_ECONOMY_MONTH) >= TimerGameEconomy::date) return false;
217 } else {
218 /* Service interval is in days. */
219 if (this->date_of_last_service + this->GetServiceInterval() >= TimerGameEconomy::date) return false;
220 }
221
222 /* If we're servicing anyway, because we have not disabled servicing when
223 * there are no breakdowns or we are playing with breakdowns, bail out. */
224 if (!_settings_game.order.no_servicing_if_no_breakdowns ||
225 _settings_game.difficulty.vehicle_breakdowns != 0) {
226 return true;
227 }
228
229 /* Test whether there is some pending autoreplace.
230 * Note: We do this after the service-interval test.
231 * There are a lot more reasons for autoreplace to fail than we can test here reasonably. */
232 bool pending_replace = false;
233 Money needed_money = c->settings.engine_renew_money;
234 if (needed_money > GetAvailableMoney(c->index)) return false;
235
236 for (const Vehicle *v = this; v != nullptr; v = (v->type == VEH_TRAIN) ? Train::From(v)->GetNextUnit() : nullptr) {
237 bool replace_when_old = false;
238 EngineID new_engine = EngineReplacementForCompany(c, v->engine_type, v->group_id, &replace_when_old);
239
240 /* Check engine availability */
241 if (new_engine == EngineID::Invalid() || !Engine::Get(new_engine)->company_avail.Test(v->owner)) continue;
242 /* Is the vehicle old if we are not always replacing? */
243 if (replace_when_old && !v->NeedsAutorenewing(c, false)) continue;
244
245 /* Check refittability */
246 CargoTypes available_cargo_types, union_mask;
247 GetArticulatedRefitMasks(new_engine, true, &union_mask, &available_cargo_types);
248 /* Is there anything to refit? */
249 if (union_mask != 0) {
250 CargoType cargo_type;
251 CargoTypes cargo_mask = GetCargoTypesOfArticulatedVehicle(v, &cargo_type);
252 if (!HasAtMostOneBit(cargo_mask)) {
253 CargoTypes new_engine_default_cargoes = GetCargoTypesOfArticulatedParts(new_engine);
254 if ((cargo_mask & new_engine_default_cargoes) != cargo_mask) {
255 /* We cannot refit to mixed cargoes in an automated way */
256 continue;
257 }
258 /* engine_type is already a mixed cargo type which matches the incoming vehicle by default, no refit required */
259 } else {
260 /* Did the old vehicle carry anything? */
261 if (IsValidCargoType(cargo_type)) {
262 /* We can't refit the vehicle to carry the cargo we want */
263 if (!HasBit(available_cargo_types, cargo_type)) continue;
264 }
265 }
266 }
267
268 /* Check money.
269 * We want 2*(the price of the new vehicle) without looking at the value of the vehicle we are going to sell. */
270 pending_replace = true;
271 needed_money += 2 * Engine::Get(new_engine)->GetCost();
272 if (needed_money > GetAvailableMoney(c->index)) return false;
273 }
274
275 return pending_replace;
276}
277
283 bool Vehicle::NeedsAutomaticServicing() const
284{
285 if (this->HasDepotOrder()) return false;
286 if (this->current_order.IsType(OT_LOADING)) return false;
287 if (this->current_order.IsType(OT_GOTO_DEPOT) && !this->current_order.GetDepotOrderType().Test(OrderDepotTypeFlag::Service)) return false;
288 return NeedsServicing();
289}
290
291uint Vehicle::Crash(bool)
292{
293 assert(!this->vehstatus.Test(VehState::Crashed));
294 assert(this->Previous() == nullptr); // IsPrimaryVehicle fails for free-wagon-chains
295
296 uint pass = 0;
297 /* Stop the vehicle. */
298 if (this->IsPrimaryVehicle()) this->vehstatus.Set(VehState::Stopped);
299 /* crash all wagons, and count passengers */
300 for (Vehicle *v = this; v != nullptr; v = v->Next()) {
301 /* We do not transfer reserver cargo back, so TotalCount() instead of StoredCount() */
302 if (IsCargoInClass(v->cargo_type, CargoClass::Passengers)) pass += v->cargo.TotalCount();
303 v->vehstatus.Set(VehState::Crashed);
304 v->MarkAllViewportsDirty();
305 }
306
307 /* Dirty some windows */
308 InvalidateWindowClassesData(GetWindowClassForVehicleType(this->type), 0);
309 SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, WID_VV_START_STOP);
310 SetWindowDirty(WC_VEHICLE_DETAILS, this->index);
311 SetWindowDirty(WC_VEHICLE_DEPOT, this->tile);
312
313 delete this->cargo_payment;
314 assert(this->cargo_payment == nullptr); // cleared by ~CargoPayment
315
316 return RandomRange(pass + 1); // Randomise deceased passengers.
317}
318
319
328 void ShowNewGrfVehicleError(EngineID engine, StringID part1, StringID part2, GRFBug bug_type, bool critical)
329{
330 const Engine *e = Engine::Get(engine);
331 GRFConfig *grfconfig = GetGRFConfig(e->GetGRFID());
332
333 /* Missing GRF. Nothing useful can be done in this situation. */
334 if (grfconfig == nullptr) return;
335
336 if (!grfconfig->grf_bugs.Test(bug_type)) {
337 grfconfig->grf_bugs.Set(bug_type);
338 ShowErrorMessage(GetEncodedString(part1, grfconfig->GetName()),
339 GetEncodedString(part2, std::monostate{}, engine), WL_CRITICAL);
340 if (!_networking) Command<CMD_PAUSE>::Do(DoCommandFlag::Execute, critical ? PauseMode::Error : PauseMode::Normal, true);
341 }
342
343 /* debug output */
344 Debug(grf, 0, "{}", StrMakeValid(GetString(part1, grfconfig->GetName())));
345
346 Debug(grf, 0, "{}", StrMakeValid(GetString(part2, std::monostate{}, engine)));
347}
348
354 void VehicleLengthChanged(const Vehicle *u)
355{
356 /* show a warning once for each engine in whole game and once for each GRF after each game load */
357 const Engine *engine = u->GetEngine();
358 uint32_t grfid = engine->grf_prop.grfid;
359 GRFConfig *grfconfig = GetGRFConfig(grfid);
360 if (_gamelog.GRFBugReverse(grfid, engine->grf_prop.local_id) || !grfconfig->grf_bugs.Test(GRFBug::VehLength)) {
361 ShowNewGrfVehicleError(u->engine_type, STR_NEWGRF_BROKEN, STR_NEWGRF_BROKEN_VEHICLE_LENGTH, GRFBug::VehLength, true);
362 }
363}
364
369Vehicle::Vehicle(VehicleType type)
370{
371 this->type = type;
372 this->coord.left = INVALID_COORD;
373 this->sprite_cache.old_coord.left = INVALID_COORD;
374 this->group_id = DEFAULT_GROUP;
375 this->fill_percent_te_id = INVALID_TE_ID;
376 this->first = this;
377 this->colourmap = PAL_NONE;
378 this->cargo_age_counter = 1;
379 this->last_station_visited = StationID::Invalid();
380 this->last_loading_station = StationID::Invalid();
381}
382
383/* Size of the hash, 6 = 64 x 64, 7 = 128 x 128. Larger sizes will (in theory) reduce hash
384 * lookup times at the expense of memory usage. */
385constexpr uint TILE_HASH_BITS = 7;
386constexpr uint TILE_HASH_SIZE = 1 << TILE_HASH_BITS;
387constexpr uint TILE_HASH_MASK = TILE_HASH_SIZE - 1;
388constexpr uint TOTAL_TILE_HASH_SIZE = 1 << (TILE_HASH_BITS * 2);
389
390/* Resolution of the hash, 0 = 1*1 tile, 1 = 2*2 tiles, 2 = 4*4 tiles, etc.
391 * Profiling results show that 0 is fastest. */
392constexpr uint TILE_HASH_RES = 0;
393
397 static inline uint GetTileHash1D(uint p)
398{
399 return GB(p, TILE_HASH_RES, TILE_HASH_BITS);
400}
401
405 static inline uint IncTileHash1D(uint h)
406{
407 return (h + 1) & TILE_HASH_MASK;
408}
409
413 static inline uint ComposeTileHash(uint hx, uint hy)
414{
415 return hx | hy << TILE_HASH_BITS;
416}
417
421 static inline uint GetTileHash(uint x, uint y)
422{
423 return ComposeTileHash(GetTileHash1D(x), GetTileHash1D(y));
424}
425
426static std::array<Vehicle *, TOTAL_TILE_HASH_SIZE> _vehicle_tile_hash{};
427
432VehiclesNearTileXY::Iterator::Iterator(int32_t x, int32_t y, uint max_dist)
433{
434 /* There are no negative tile coordinates */
435 this->pos_rect.left = std::max<int>(0, x - max_dist);
436 this->pos_rect.right = std::max<int>(0, x + max_dist);
437 this->pos_rect.top = std::max<int>(0, y - max_dist);
438 this->pos_rect.bottom = std::max<int>(0, y + max_dist);
439
440 if (2 * max_dist < TILE_HASH_MASK * TILE_SIZE) {
441 /* Hash area to scan */
442 this->hxmin = this->hx = GetTileHash1D(this->pos_rect.left / TILE_SIZE);
443 this->hxmax = GetTileHash1D(this->pos_rect.right / TILE_SIZE);
444 this->hymin = this->hy = GetTileHash1D(this->pos_rect.top / TILE_SIZE);
445 this->hymax = GetTileHash1D(this->pos_rect.bottom / TILE_SIZE);
446 } else {
447 /* Scan all */
448 this->hxmin = this->hx = 0;
449 this->hxmax = TILE_HASH_MASK;
450 this->hymin = this->hy = 0;
451 this->hymax = TILE_HASH_MASK;
452 }
453
454 this->current_veh = _vehicle_tile_hash[ComposeTileHash(this->hx, this->hy)];
455 this->SkipEmptyBuckets();
456 this->SkipFalseMatches();
457}
458
462 void VehiclesNearTileXY::Iterator::Increment()
463{
464 assert(this->current_veh != nullptr);
465 this->current_veh = this->current_veh->hash_tile_next;
466 this->SkipEmptyBuckets();
467}
468
472 void VehiclesNearTileXY::Iterator::SkipEmptyBuckets()
473{
474 while (this->current_veh == nullptr) {
475 if (this->hx != this->hxmax) {
476 this->hx = IncTileHash1D(this->hx);
477 } else if (this->hy != this->hymax) {
478 this->hx = this->hxmin;
479 this->hy = IncTileHash1D(this->hy);
480 } else {
481 return;
482 }
483 this->current_veh = _vehicle_tile_hash[ComposeTileHash(this->hx, this->hy)];
484 }
485}
486
490 void VehiclesNearTileXY::Iterator::SkipFalseMatches()
491{
492 while (this->current_veh != nullptr && !this->pos_rect.Contains({this->current_veh->x_pos, this->current_veh->y_pos})) this->Increment();
493}
494
499VehiclesOnTile::Iterator::Iterator(TileIndex tile) : tile(tile)
500{
501 this->current = _vehicle_tile_hash[GetTileHash(TileX(tile), TileY(tile))];
502 this->SkipFalseMatches();
503}
504
509 void VehiclesOnTile::Iterator::Increment()
510{
511 this->current = this->current->hash_tile_next;
512}
513
517 void VehiclesOnTile::Iterator::SkipFalseMatches()
518{
519 while (this->current != nullptr && this->current->tile != this->tile) this->Increment();
520}
521
527 CommandCost EnsureNoVehicleOnGround(TileIndex tile)
528{
529 int z = GetTileMaxPixelZ(tile);
530
531 /* Value v is not safe in MP games, however, it is used to generate a local
532 * error message only (which may be different for different machines).
533 * Such a message does not affect MP synchronisation.
534 */
535 for (const Vehicle *v : VehiclesOnTile(tile)) {
536 if (v->type == VEH_DISASTER || (v->type == VEH_AIRCRAFT && v->subtype == AIR_SHADOW)) continue;
537 if (v->z_pos > z) continue;
538
539 return CommandCost(STR_ERROR_TRAIN_IN_THE_WAY + v->type);
540 }
541 return CommandCost();
542}
543
551 CommandCost TunnelBridgeIsFree(TileIndex tile, TileIndex endtile, const Vehicle *ignore)
552{
553 for (TileIndex t : {tile, endtile}) {
554 /* Value v is not safe in MP games, however, it is used to generate a local
555 * error message only (which may be different for different machines).
556 * Such a message does not affect MP synchronisation.
557 */
558 for (const Vehicle *v : VehiclesOnTile(t)) {
559 if (v->type != VEH_TRAIN && v->type != VEH_ROAD && v->type != VEH_SHIP) continue;
560 if (v == ignore) continue;
561 return CommandCost(STR_ERROR_TRAIN_IN_THE_WAY + v->type);
562 }
563 }
564 return CommandCost();
565}
566
575 CommandCost EnsureNoTrainOnTrackBits(TileIndex tile, TrackBits track_bits)
576{
577 /* Value v is not safe in MP games, however, it is used to generate a local
578 * error message only (which may be different for different machines).
579 * Such a message does not affect MP synchronisation.
580 */
581 for (const Vehicle *v : VehiclesOnTile(tile)) {
582 if (v->type != VEH_TRAIN) continue;
583
584 const Train *t = Train::From(v);
585 if ((t->track != track_bits) && !TracksOverlap(t->track | track_bits)) continue;
586
587 return CommandCost(STR_ERROR_TRAIN_IN_THE_WAY + v->type);
588 }
589 return CommandCost();
590}
591
592static void UpdateVehicleTileHash(Vehicle *v, bool remove)
593{
594 Vehicle **old_hash = v->hash_tile_current;
595 Vehicle **new_hash;
596
597 if (remove) {
598 new_hash = nullptr;
599 } else {
600 new_hash = &_vehicle_tile_hash[GetTileHash(TileX(v->tile), TileY(v->tile))];
601 }
602
603 if (old_hash == new_hash) return;
604
605 /* Remove from the old position in the hash table */
606 if (old_hash != nullptr) {
607 if (v->hash_tile_next != nullptr) v->hash_tile_next->hash_tile_prev = v->hash_tile_prev;
608 *v->hash_tile_prev = v->hash_tile_next;
609 }
610
611 /* Insert vehicle at beginning of the new position in the hash table */
612 if (new_hash != nullptr) {
613 v->hash_tile_next = *new_hash;
614 if (v->hash_tile_next != nullptr) v->hash_tile_next->hash_tile_prev = &v->hash_tile_next;
615 v->hash_tile_prev = new_hash;
616 *new_hash = v;
617 }
618
619 /* Remember current hash position */
620 v->hash_tile_current = new_hash;
621}
622
623static std::array<Vehicle *, 1 << (GEN_HASHX_BITS + GEN_HASHY_BITS)> _vehicle_viewport_hash{};
624
625static void UpdateVehicleViewportHash(Vehicle *v, int x, int y, int old_x, int old_y)
626{
627 Vehicle **old_hash, **new_hash;
628
629 new_hash = (x == INVALID_COORD) ? nullptr : &_vehicle_viewport_hash[GetViewportHash(x, y)];
630 old_hash = (old_x == INVALID_COORD) ? nullptr : &_vehicle_viewport_hash[GetViewportHash(old_x, old_y)];
631
632 if (old_hash == new_hash) return;
633
634 /* remove from hash table? */
635 if (old_hash != nullptr) {
636 if (v->hash_viewport_next != nullptr) v->hash_viewport_next->hash_viewport_prev = v->hash_viewport_prev;
637 *v->hash_viewport_prev = v->hash_viewport_next;
638 }
639
640 /* insert into hash table? */
641 if (new_hash != nullptr) {
642 v->hash_viewport_next = *new_hash;
643 if (v->hash_viewport_next != nullptr) v->hash_viewport_next->hash_viewport_prev = &v->hash_viewport_next;
644 v->hash_viewport_prev = new_hash;
645 *new_hash = v;
646 }
647}
648
649void ResetVehicleHash()
650{
651 for (Vehicle *v : Vehicle::Iterate()) { v->hash_tile_current = nullptr; }
652 _vehicle_viewport_hash.fill(nullptr);
653 _vehicle_tile_hash.fill(nullptr);
654}
655
656void ResetVehicleColourMap()
657{
658 for (Vehicle *v : Vehicle::Iterate()) { v->colourmap = PAL_NONE; }
659}
660
665 using AutoreplaceMap = std::map<VehicleID, bool>;
666static AutoreplaceMap _vehicles_to_autoreplace;
667
668void InitializeVehicles()
669{
670 _vehicles_to_autoreplace.clear();
671 ResetVehicleHash();
672}
673
674uint CountVehiclesInChain(const Vehicle *v)
675{
676 uint count = 0;
677 do count++; while ((v = v->Next()) != nullptr);
678 return count;
679}
680
685 bool Vehicle::IsEngineCountable() const
686{
687 switch (this->type) {
688 case VEH_AIRCRAFT: return Aircraft::From(this)->IsNormalAircraft(); // don't count plane shadows and helicopter rotors
689 case VEH_TRAIN:
690 return !this->IsArticulatedPart() && // tenders and other articulated parts
691 !Train::From(this)->IsRearDualheaded(); // rear parts of multiheaded engines
692 case VEH_ROAD: return RoadVehicle::From(this)->IsFrontEngine();
693 case VEH_SHIP: return true;
694 default: return false; // Only count company buildable vehicles
695 }
696}
697
702 bool Vehicle::HasEngineType() const
703{
704 switch (this->type) {
705 case VEH_AIRCRAFT: return Aircraft::From(this)->IsNormalAircraft();
706 case VEH_TRAIN:
707 case VEH_ROAD:
708 case VEH_SHIP: return true;
709 default: return false;
710 }
711}
712
718 const Engine *Vehicle::GetEngine() const
719{
720 return Engine::Get(this->engine_type);
721}
722
728 const GRFFile *Vehicle::GetGRF() const
729{
730 return this->GetEngine()->GetGRF();
731}
732
738uint32_t Vehicle::GetGRFID() const
739{
740 return this->GetEngine()->GetGRFID();
741}
742
748 void Vehicle::ShiftDates(TimerGameEconomy::Date interval)
749{
750 this->date_of_last_service = std::max(this->date_of_last_service + interval, TimerGameEconomy::Date(0));
751 /* date_of_last_service_newgrf is not updated here as it must stay stable
752 * for vehicles outside of a depot. */
753}
754
762 void Vehicle::HandlePathfindingResult(bool path_found)
763{
764 if (path_found) {
765 /* Route found, is the vehicle marked with "lost" flag? */
766 if (!this->vehicle_flags.Test(VehicleFlag::PathfinderLost)) return;
767
768 /* Clear the flag as the PF's problem was solved. */
769 this->vehicle_flags.Reset(VehicleFlag::PathfinderLost);
770 SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, WID_VV_START_STOP);
771 InvalidateWindowClassesData(GetWindowClassForVehicleType(this->type));
772 /* Delete the news item. */
773 DeleteVehicleNews(this->index, AdviceType::VehicleLost);
774 return;
775 }
776
777 /* Were we already lost? */
778 if (this->vehicle_flags.Test(VehicleFlag::PathfinderLost)) return;
779
780 /* It is first time the problem occurred, set the "lost" flag. */
781 this->vehicle_flags.Set(VehicleFlag::PathfinderLost);
782 SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, WID_VV_START_STOP);
783 InvalidateWindowClassesData(GetWindowClassForVehicleType(this->type));
784
785 /* Unbunching data is no longer valid. */
786 this->ResetDepotUnbunching();
787
788 /* Notify user about the event. */
789 AI::NewEvent(this->owner, new ScriptEventVehicleLost(this->index));
790 if (_settings_client.gui.lost_vehicle_warn && this->owner == _local_company) {
791 AddVehicleAdviceNewsItem(AdviceType::VehicleLost, GetEncodedString(STR_NEWS_VEHICLE_IS_LOST, this->index), this->index);
792 }
793}
794
796 void Vehicle::PreDestructor()
797{
798 if (CleaningPool()) return;
799
800 if (Station::IsValidID(this->last_station_visited)) {
801 Station *st = Station::Get(this->last_station_visited);
802 st->loading_vehicles.remove(this);
803
804 HideFillingPercent(&this->fill_percent_te_id);
805 this->CancelReservation(StationID::Invalid(), st);
806 delete this->cargo_payment;
807 assert(this->cargo_payment == nullptr); // cleared by ~CargoPayment
808 }
809
810 if (this->IsEngineCountable()) {
811 GroupStatistics::CountEngine(this, -1);
812 if (this->IsPrimaryVehicle()) GroupStatistics::CountVehicle(this, -1);
813 GroupStatistics::UpdateAutoreplace(this->owner);
814
815 if (this->owner == _local_company) InvalidateAutoreplaceWindow(this->engine_type, this->group_id);
816 DeleteGroupHighlightOfVehicle(this);
817 }
818
819 Company::Get(this->owner)->freeunits[this->type].ReleaseID(this->unitnumber);
820
821 if (this->type == VEH_AIRCRAFT && this->IsPrimaryVehicle()) {
822 Aircraft *a = Aircraft::From(this);
823 Station *st = GetTargetAirportIfValid(a);
824 if (st != nullptr) {
825 const auto &layout = st->airport.GetFTA()->layout;
826 st->airport.blocks.Reset(layout[a->previous_pos].blocks | layout[a->pos].blocks);
827 }
828 }
829
830
831 if (this->type == VEH_ROAD && this->IsPrimaryVehicle()) {
832 RoadVehicle *v = RoadVehicle::From(this);
833 if (!v->vehstatus.Test(VehState::Crashed) && IsInsideMM(v->state, RVSB_IN_DT_ROAD_STOP, RVSB_IN_DT_ROAD_STOP_END)) {
834 /* Leave the drive through roadstop, when you have not already left it. */
835 RoadStop::GetByTile(v->tile, GetRoadStopType(v->tile))->Leave(v);
836 }
837
838 if (v->disaster_vehicle != VehicleID::Invalid()) ReleaseDisasterVehicle(v->disaster_vehicle);
839 }
840
841 if (this->Previous() == nullptr) {
842 InvalidateWindowData(WC_VEHICLE_DEPOT, this->tile);
843 }
844
845 if (this->IsPrimaryVehicle()) {
846 CloseWindowById(WC_VEHICLE_VIEW, this->index);
847 CloseWindowById(WC_VEHICLE_ORDERS, this->index);
848 CloseWindowById(WC_VEHICLE_REFIT, this->index);
849 CloseWindowById(WC_VEHICLE_DETAILS, this->index);
850 CloseWindowById(WC_VEHICLE_TIMETABLE, this->index);
851 SetWindowDirty(WC_COMPANY, this->owner);
852 OrderBackup::ClearVehicle(this);
853 }
854 InvalidateWindowClassesData(GetWindowClassForVehicleType(this->type), 0);
855
856 this->cargo.Truncate();
857 DeleteVehicleOrders(this);
858 DeleteDepotHighlightOfVehicle(this);
859
860 StopGlobalFollowVehicle(this);
861}
862
863Vehicle::~Vehicle()
864{
865 if (CleaningPool()) {
866 this->cargo.OnCleanPool();
867 return;
868 }
869
870 /* sometimes, eg. for disaster vehicles, when company bankrupts, when removing crashed/flooded vehicles,
871 * it may happen that vehicle chain is deleted when visible */
872 if (!this->vehstatus.Test(VehState::Hidden)) this->MarkAllViewportsDirty();
873
874 Vehicle *v = this->Next();
875 this->SetNext(nullptr);
876
877 delete v;
878
879 UpdateVehicleTileHash(this, true);
880 UpdateVehicleViewportHash(this, INVALID_COORD, 0, this->sprite_cache.old_coord.left, this->sprite_cache.old_coord.top);
881 if (this->type != VEH_EFFECT) {
882 DeleteVehicleNews(this->index);
883 DeleteNewGRFInspectWindow(GetGrfSpecFeature(this->type), this->index);
884 }
885}
886
891 static void VehicleEnteredDepotThisTick(Vehicle *v)
892{
893 /* Vehicle should stop in the depot if it was in 'stopping' state */
894 _vehicles_to_autoreplace[v->index] = !v->vehstatus.Test(VehState::Stopped);
895
896 /* We ALWAYS set the stopped state. Even when the vehicle does not plan on
897 * stopping in the depot, so we stop it to ensure that it will not reserve
898 * the path out of the depot before we might autoreplace it to a different
899 * engine. The new engine would not own the reserved path we store that we
900 * stopped the vehicle, so autoreplace can start it again */
901 v->vehstatus.Set(VehState::Stopped);
902}
903
907 void RunVehicleCalendarDayProc()
908{
909 if (_game_mode != GM_NORMAL) return;
910
911 /* Run the calendar day proc for every DAY_TICKS vehicle starting at TimerGameCalendar::date_fract. */
912 for (size_t i = TimerGameCalendar::date_fract; i < Vehicle::GetPoolSize(); i += Ticks::DAY_TICKS) {
913 Vehicle *v = Vehicle::Get(i);
914 if (v == nullptr) continue;
915 v->OnNewCalendarDay();
916 }
917}
918
924 static void RunEconomyVehicleDayProc()
925{
926 if (_game_mode != GM_NORMAL) return;
927
928 /* Run the economy day proc for every DAY_TICKS vehicle starting at TimerGameEconomy::date_fract. */
929 for (size_t i = TimerGameEconomy::date_fract; i < Vehicle::GetPoolSize(); i += Ticks::DAY_TICKS) {
930 Vehicle *v = Vehicle::Get(i);
931 if (v == nullptr) continue;
932
933 /* Call the 32-day callback if needed */
934 if ((v->day_counter & 0x1F) == 0 && v->HasEngineType()) {
935 uint16_t callback = GetVehicleCallback(CBID_VEHICLE_32DAY_CALLBACK, 0, 0, v->engine_type, v);
936 if (callback != CALLBACK_FAILED) {
937 if (HasBit(callback, 0)) {
938 TriggerVehicleRandomisation(v, VehicleRandomTrigger::Callback32); // Trigger vehicle trigger 10
939 }
940
941 /* After a vehicle trigger, the graphics and properties of the vehicle could change.
942 * Note: MarkDirty also invalidates the palette, which is the meaning of bit 1. So, nothing special there. */
943 if (callback != 0) v->First()->MarkDirty();
944
945 if (callback & ~3) ErrorUnknownCallbackResult(v->GetGRFID(), CBID_VEHICLE_32DAY_CALLBACK, callback);
946 }
947 }
948
949 /* This is called once per day for each vehicle, but not in the first tick of the day */
950 v->OnNewEconomyDay();
951 }
952}
953
954void CallVehicleTicks()
955{
956 _vehicles_to_autoreplace.clear();
957
958 RunEconomyVehicleDayProc();
959
960 {
961 PerformanceMeasurer framerate(PFE_GL_ECONOMY);
962 for (Station *st : Station::Iterate()) LoadUnloadStation(st);
963 }
964 PerformanceAccumulator::Reset(PFE_GL_TRAINS);
965 PerformanceAccumulator::Reset(PFE_GL_ROADVEHS);
966 PerformanceAccumulator::Reset(PFE_GL_SHIPS);
967 PerformanceAccumulator::Reset(PFE_GL_AIRCRAFT);
968
969 for (Vehicle *v : Vehicle::Iterate()) {
970 [[maybe_unused]] VehicleID vehicle_index = v->index;
971
972 /* Vehicle could be deleted in this tick */
973 if (!v->Tick()) {
974 assert(Vehicle::Get(vehicle_index) == nullptr);
975 continue;
976 }
977
978 assert(Vehicle::Get(vehicle_index) == v);
979
980 switch (v->type) {
981 default: break;
982
983 case VEH_TRAIN:
984 case VEH_ROAD:
985 case VEH_AIRCRAFT:
986 case VEH_SHIP: {
987 Vehicle *front = v->First();
988
989 if (v->vcache.cached_cargo_age_period != 0) {
990 v->cargo_age_counter = std::min(v->cargo_age_counter, v->vcache.cached_cargo_age_period);
991 if (--v->cargo_age_counter == 0) {
992 v->cargo.AgeCargo();
993 v->cargo_age_counter = v->vcache.cached_cargo_age_period;
994 }
995 }
996
997 /* Do not play any sound when crashed */
998 if (front->vehstatus.Test(VehState::Crashed)) continue;
999
1000 /* Do not play any sound when in depot or tunnel */
1001 if (v->vehstatus.Test(VehState::Hidden)) continue;
1002
1003 /* Do not play any sound when stopped */
1004 if (front->vehstatus.Test(VehState::Stopped) && (front->type != VEH_TRAIN || front->cur_speed == 0)) continue;
1005
1006 /* Update motion counter for animation purposes. */
1007 v->motion_counter += front->cur_speed;
1008
1009 /* Check vehicle type specifics */
1010 switch (v->type) {
1011 case VEH_TRAIN:
1012 if (!Train::From(v)->IsEngine()) continue;
1013 break;
1014
1015 case VEH_ROAD:
1016 if (!RoadVehicle::From(v)->IsFrontEngine()) continue;
1017 break;
1018
1019 case VEH_AIRCRAFT:
1020 if (!Aircraft::From(v)->IsNormalAircraft()) continue;
1021 break;
1022
1023 default:
1024 break;
1025 }
1026
1027 /* Play a running sound if the motion counter passes 256 (Do we not skip sounds?) */
1028 if (GB(v->motion_counter, 0, 8) < front->cur_speed) PlayVehicleSound(v, VSE_RUNNING);
1029
1030 /* Play an alternating running sound every 16 ticks */
1031 if (GB(v->tick_counter, 0, 4) == 0) {
1032 /* Play running sound when speed > 0 and not braking */
1033 bool running = (front->cur_speed > 0) && !front->vehstatus.Any({VehState::Stopped, VehState::TrainSlowing});
1034 PlayVehicleSound(v, running ? VSE_RUNNING_16 : VSE_STOPPED_16);
1035 }
1036
1037 break;
1038 }
1039 }
1040 }
1041
1042 Backup<CompanyID> cur_company(_current_company);
1043 for (auto &it : _vehicles_to_autoreplace) {
1044 Vehicle *v = Vehicle::Get(it.first);
1045 /* Autoreplace needs the current company set as the vehicle owner */
1046 cur_company.Change(v->owner);
1047
1048 /* Start vehicle if we stopped them in VehicleEnteredDepotThisTick()
1049 * We need to stop them between VehicleEnteredDepotThisTick() and here or we risk that
1050 * they are already leaving the depot again before being replaced. */
1051 if (it.second) v->vehstatus.Reset(VehState::Stopped);
1052
1053 /* Store the position of the effect as the vehicle pointer will become invalid later */
1054 int x = v->x_pos;
1055 int y = v->y_pos;
1056 int z = v->z_pos;
1057
1058 const Company *c = Company::Get(_current_company);
1059 SubtractMoneyFromCompany(CommandCost(EXPENSES_NEW_VEHICLES, (Money)c->settings.engine_renew_money));
1060 CommandCost res = Command<CMD_AUTOREPLACE_VEHICLE>::Do(DoCommandFlag::Execute, v->index);
1061 SubtractMoneyFromCompany(CommandCost(EXPENSES_NEW_VEHICLES, -(Money)c->settings.engine_renew_money));
1062
1063 if (!IsLocalCompany()) continue;
1064
1065 if (res.Succeeded()) {
1066 ShowCostOrIncomeAnimation(x, y, z, res.GetCost());
1067 continue;
1068 }
1069
1070 StringID error_message = res.GetErrorMessage();
1071 if (error_message == STR_ERROR_AUTOREPLACE_NOTHING_TO_DO || error_message == INVALID_STRING_ID) continue;
1072
1073 if (error_message == STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY) error_message = STR_ERROR_AUTOREPLACE_MONEY_LIMIT;
1074
1075 EncodedString headline;
1076 if (error_message == STR_ERROR_TRAIN_TOO_LONG_AFTER_REPLACEMENT) {
1077 headline = GetEncodedString(error_message, v->index);
1078 } else {
1079 headline = GetEncodedString(STR_NEWS_VEHICLE_AUTORENEW_FAILED, v->index, error_message, std::monostate{});
1080 }
1081
1082 AddVehicleAdviceNewsItem(AdviceType::AutorenewFailed, std::move(headline), v->index);
1083 }
1084
1085 cur_company.Restore();
1086}
1087
1092 static void DoDrawVehicle(const Vehicle *v)
1093{
1094 PaletteID pal = PAL_NONE;
1095
1096 if (v->vehstatus.Test(VehState::DefaultPalette)) pal = v->vehstatus.Test(VehState::Crashed) ? PALETTE_CRASH : GetVehiclePalette(v);
1097
1098 /* Check whether the vehicle shall be transparent due to the game state */
1099 bool shadowed = v->vehstatus.Test(VehState::Shadow);
1100
1101 if (v->type == VEH_EFFECT) {
1102 /* Check whether the vehicle shall be transparent/invisible due to GUI settings.
1103 * However, transparent smoke and bubbles look weird, so always hide them. */
1104 TransparencyOption to = EffectVehicle::From(v)->GetTransparencyOption();
1105 if (to != TO_INVALID && (IsTransparencySet(to) || IsInvisibilitySet(to))) return;
1106 }
1107
1108 StartSpriteCombine();
1109 for (uint i = 0; i < v->sprite_cache.sprite_seq.count; ++i) {
1110 PaletteID pal2 = v->sprite_cache.sprite_seq.seq[i].pal;
1111 if (!pal2 || v->vehstatus.Test(VehState::Crashed)) pal2 = pal;
1112 AddSortableSpriteToDraw(v->sprite_cache.sprite_seq.seq[i].sprite, pal2, v->x_pos, v->y_pos, v->z_pos, v->bounds, shadowed);
1113 }
1114 EndSpriteCombine();
1115}
1116
1121 void ViewportAddVehicles(DrawPixelInfo *dpi)
1122{
1123 /* The bounding rectangle */
1124 const int l = dpi->left;
1125 const int r = dpi->left + dpi->width;
1126 const int t = dpi->top;
1127 const int b = dpi->top + dpi->height;
1128
1129 /* Border size of MAX_VEHICLE_PIXEL_xy */
1130 const int xb = MAX_VEHICLE_PIXEL_X * ZOOM_BASE;
1131 const int yb = MAX_VEHICLE_PIXEL_Y * ZOOM_BASE;
1132
1133 /* The hash area to scan */
1134 uint xl, xu, yl, yu;
1135
1136 if (static_cast<uint>(dpi->width + xb) < GEN_HASHX_SIZE) {
1137 xl = GetViewportHashX(l - xb);
1138 xu = GetViewportHashX(r);
1139 } else {
1140 /* scan whole hash row */
1141 xl = 0;
1142 xu = GEN_HASHX_MASK;
1143 }
1144
1145 if (static_cast<uint>(dpi->height + yb) < GEN_HASHY_SIZE) {
1146 yl = GetViewportHashY(t - yb);
1147 yu = GetViewportHashY(b);
1148 } else {
1149 /* scan whole column */
1150 yl = 0;
1151 yu = GEN_HASHY_MASK;
1152 }
1153
1154 for (uint y = yl;; y = (y + GEN_HASHY_INC) & GEN_HASHY_MASK) {
1155 for (uint x = xl;; x = (x + GEN_HASHX_INC) & GEN_HASHX_MASK) {
1156 const Vehicle *v = _vehicle_viewport_hash[x + y]; // already masked & 0xFFF
1157
1158 while (v != nullptr) {
1159
1160 if (!v->vehstatus.Test(VehState::Hidden) &&
1161 l <= v->coord.right + xb &&
1162 t <= v->coord.bottom + yb &&
1163 r >= v->coord.left - xb &&
1164 b >= v->coord.top - yb)
1165 {
1166 /*
1167 * This vehicle can potentially be drawn as part of this viewport and
1168 * needs to be revalidated, as the sprite may not be correct.
1169 */
1170 if (v->sprite_cache.revalidate_before_draw) {
1171 VehicleSpriteSeq seq;
1172 v->GetImage(v->direction, EIT_ON_MAP, &seq);
1173
1174 if (seq.IsValid() && v->sprite_cache.sprite_seq != seq) {
1175 v->sprite_cache.sprite_seq = seq;
1176 /*
1177 * A sprite change may also result in a bounding box change,
1178 * so we need to update the bounding box again before we
1179 * check to see if the vehicle should be drawn. Note that
1180 * we can't interfere with the viewport hash at this point,
1181 * so we keep the original hash on the assumption there will
1182 * not be a significant change in the top and left coordinates
1183 * of the vehicle.
1184 */
1185 v->UpdateBoundingBoxCoordinates(false);
1186
1187 }
1188
1189 v->sprite_cache.revalidate_before_draw = false;
1190 }
1191
1192 if (l <= v->coord.right &&
1193 t <= v->coord.bottom &&
1194 r >= v->coord.left &&
1195 b >= v->coord.top) DoDrawVehicle(v);
1196 }
1197
1198 v = v->hash_viewport_next;
1199 }
1200
1201 if (x == xu) break;
1202 }
1203
1204 if (y == yu) break;
1205 }
1206}
1207
1215 Vehicle *CheckClickOnVehicle(const Viewport &vp, int x, int y)
1216{
1217 Vehicle *found = nullptr;
1218 uint dist, best_dist = UINT_MAX;
1219
1220 x -= vp.left;
1221 y -= vp.top;
1222 if (!IsInsideMM(x, 0, vp.width) || !IsInsideMM(y, 0, vp.height)) return nullptr;
1223
1224 x = ScaleByZoom(x, vp.zoom) + vp.virtual_left;
1225 y = ScaleByZoom(y, vp.zoom) + vp.virtual_top;
1226
1227 /* Border size of MAX_VEHICLE_PIXEL_xy */
1228 const int xb = MAX_VEHICLE_PIXEL_X * ZOOM_BASE;
1229 const int yb = MAX_VEHICLE_PIXEL_Y * ZOOM_BASE;
1230
1231 /* The hash area to scan */
1232 uint xl = GetViewportHashX(x - xb);
1233 uint xu = GetViewportHashX(x);
1234 uint yl = GetViewportHashY(y - yb);
1235 uint yu = GetViewportHashY(y);
1236
1237 for (uint hy = yl;; hy = (hy + GEN_HASHY_INC) & GEN_HASHY_MASK) {
1238 for (uint hx = xl;; hx = (hx + GEN_HASHX_INC) & GEN_HASHX_MASK) {
1239 Vehicle *v = _vehicle_viewport_hash[hx + hy]; // already masked & 0xFFF
1240
1241 while (v != nullptr) {
1242 if (!v->vehstatus.Any({VehState::Hidden, VehState::Unclickable}) &&
1243 x >= v->coord.left && x <= v->coord.right &&
1244 y >= v->coord.top && y <= v->coord.bottom) {
1245
1246 dist = std::max(
1247 abs(((v->coord.left + v->coord.right) >> 1) - x),
1248 abs(((v->coord.top + v->coord.bottom) >> 1) - y)
1249 );
1250
1251 if (dist < best_dist) {
1252 found = v;
1253 best_dist = dist;
1254 }
1255 }
1256 v = v->hash_viewport_next;
1257 }
1258 if (hx == xu) break;
1259 }
1260 if (hy == yu) break;
1261 }
1262
1263 return found;
1264}
1265
1270 void DecreaseVehicleValue(Vehicle *v)
1271{
1272 v->value -= v->value >> 8;
1273 SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
1274}
1275
1276static const uint8_t _breakdown_chance[64] = {
1277 3, 3, 3, 3, 3, 3, 3, 3,
1278 4, 4, 5, 5, 6, 6, 7, 7,
1279 8, 8, 9, 9, 10, 10, 11, 11,
1280 12, 13, 13, 13, 13, 14, 15, 16,
1281 17, 19, 21, 25, 28, 31, 34, 37,
1282 40, 44, 48, 52, 56, 60, 64, 68,
1283 72, 80, 90, 100, 110, 120, 130, 140,
1284 150, 170, 190, 210, 230, 250, 250, 250,
1285};
1286
1287void CheckVehicleBreakdown(Vehicle *v)
1288{
1289 int rel, rel_old;
1290
1291 /* decrease reliability */
1292 if (!_settings_game.order.no_servicing_if_no_breakdowns ||
1293 _settings_game.difficulty.vehicle_breakdowns != 0) {
1294 v->reliability = rel = std::max((rel_old = v->reliability) - v->reliability_spd_dec, 0);
1295 if ((rel_old >> 8) != (rel >> 8)) SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
1296 }
1297
1298 if (v->breakdown_ctr != 0 || v->vehstatus.Test(VehState::Stopped) ||
1299 _settings_game.difficulty.vehicle_breakdowns < 1 ||
1300 v->cur_speed < 5 || _game_mode == GM_MENU) {
1301 return;
1302 }
1303
1304 uint32_t r = Random();
1305
1306 /* increase chance of failure */
1307 int chance = v->breakdown_chance + 1;
1308 if (Chance16I(1, 25, r)) chance += 25;
1309 v->breakdown_chance = ClampTo<uint8_t>(chance);
1310
1311 /* calculate reliability value to use in comparison */
1312 rel = v->reliability;
1313 if (v->type == VEH_SHIP) rel += 0x6666;
1314
1315 /* reduced breakdowns? */
1316 if (_settings_game.difficulty.vehicle_breakdowns == 1) rel += 0x6666;
1317
1318 /* check if to break down */
1319 if (_breakdown_chance[ClampTo<uint16_t>(rel) >> 10] <= v->breakdown_chance) {
1320 v->breakdown_ctr = GB(r, 16, 6) + 0x3F;
1321 v->breakdown_delay = GB(r, 24, 7) + 0x80;
1322 v->breakdown_chance = 0;
1323 }
1324}
1325
1332 bool Vehicle::HandleBreakdown()
1333{
1334 /* Possible states for Vehicle::breakdown_ctr
1335 * 0 - vehicle is running normally
1336 * 1 - vehicle is currently broken down
1337 * 2 - vehicle is going to break down now
1338 * >2 - vehicle is counting down to the actual breakdown event */
1339 switch (this->breakdown_ctr) {
1340 case 0:
1341 return false;
1342
1343 case 2:
1344 this->breakdown_ctr = 1;
1345
1346 if (this->breakdowns_since_last_service != 255) {
1347 this->breakdowns_since_last_service++;
1348 }
1349
1350 if (this->type == VEH_AIRCRAFT) {
1351 /* Aircraft just need this flag, the rest is handled elsewhere */
1352 this->vehstatus.Set(VehState::AircraftBroken);
1353 } else {
1354 this->cur_speed = 0;
1355
1356 if (!PlayVehicleSound(this, VSE_BREAKDOWN)) {
1357 bool train_or_ship = this->type == VEH_TRAIN || this->type == VEH_SHIP;
1358 SndPlayVehicleFx((_settings_game.game_creation.landscape != LandscapeType::Toyland) ?
1359 (train_or_ship ? SND_10_BREAKDOWN_TRAIN_SHIP : SND_0F_BREAKDOWN_ROADVEHICLE) :
1360 (train_or_ship ? SND_3A_BREAKDOWN_TRAIN_SHIP_TOYLAND : SND_35_BREAKDOWN_ROADVEHICLE_TOYLAND), this);
1361 }
1362
1363 if (!this->vehstatus.Test(VehState::Hidden) && !EngInfo(this->engine_type)->misc_flags.Test(EngineMiscFlag::NoBreakdownSmoke)) {
1364 EffectVehicle *u = CreateEffectVehicleRel(this, 4, 4, 5, EV_BREAKDOWN_SMOKE);
1365 if (u != nullptr) u->animation_state = this->breakdown_delay * 2;
1366 }
1367 }
1368
1369 this->MarkDirty(); // Update graphics after speed is zeroed
1370 SetWindowDirty(WC_VEHICLE_VIEW, this->index);
1371 SetWindowDirty(WC_VEHICLE_DETAILS, this->index);
1372
1373 [[fallthrough]];
1374 case 1:
1375 /* Aircraft breakdowns end only when arriving at the airport */
1376 if (this->type == VEH_AIRCRAFT) return false;
1377
1378 /* For trains this function is called twice per tick, so decrease v->breakdown_delay at half the rate */
1379 if ((this->tick_counter & (this->type == VEH_TRAIN ? 3 : 1)) == 0) {
1380 if (--this->breakdown_delay == 0) {
1381 this->breakdown_ctr = 0;
1382 this->MarkDirty();
1383 SetWindowDirty(WC_VEHICLE_VIEW, this->index);
1384 }
1385 }
1386 return true;
1387
1388 default:
1389 if (!this->current_order.IsType(OT_LOADING)) this->breakdown_ctr--;
1390 return false;
1391 }
1392}
1393
1398 void EconomyAgeVehicle(Vehicle *v)
1399{
1400 if (v->economy_age < EconomyTime::MAX_DATE) {
1401 v->economy_age++;
1402 if (v->IsPrimaryVehicle() && v->economy_age == VEHICLE_PROFIT_MIN_AGE + 1) GroupStatistics::VehicleReachedMinAge(v);
1403 }
1404}
1405
1410 void AgeVehicle(Vehicle *v)
1411{
1412 if (v->age < CalendarTime::MAX_DATE) v->age++;
1413
1414 if (!v->IsPrimaryVehicle() && (v->type != VEH_TRAIN || !Train::From(v)->IsEngine())) return;
1415
1416 auto age = v->age - v->max_age;
1417 for (int32_t i = 0; i <= 4; i++) {
1418 if (age == TimerGameCalendar::DateAtStartOfYear(TimerGameCalendar::Year{i})) {
1419 v->reliability_spd_dec <<= 1;
1420 break;
1421 }
1422 }
1423
1424 SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
1425
1426 /* Don't warn if warnings are disabled */
1427 if (!_settings_client.gui.old_vehicle_warn) return;
1428
1429 /* Don't warn about vehicles which are non-primary (e.g., part of an articulated vehicle), don't belong to us, are crashed, or are stopped */
1430 if (v->Previous() != nullptr || v->owner != _local_company || v->vehstatus.Any({VehState::Crashed, VehState::Stopped})) return;
1431
1432 const Company *c = Company::Get(v->owner);
1433 /* Don't warn if a renew is active */
1434 if (c->settings.engine_renew && v->GetEngine()->company_avail.Any()) return;
1435 /* Don't warn if a replacement is active */
1436 if (EngineHasReplacementForCompany(c, v->engine_type, v->group_id)) return;
1437
1438 StringID str;
1439 if (age == TimerGameCalendar::DateAtStartOfYear(TimerGameCalendar::Year{-1})) {
1440 str = STR_NEWS_VEHICLE_IS_GETTING_OLD;
1441 } else if (age == TimerGameCalendar::DateAtStartOfYear(TimerGameCalendar::Year{0})) {
1442 str = STR_NEWS_VEHICLE_IS_GETTING_VERY_OLD;
1443 } else if (age > TimerGameCalendar::DateAtStartOfYear(TimerGameCalendar::Year{0}) && (age.base() % CalendarTime::DAYS_IN_LEAP_YEAR) == 0) {
1444 str = STR_NEWS_VEHICLE_IS_GETTING_VERY_OLD_AND;
1445 } else {
1446 return;
1447 }
1448
1449 AddVehicleAdviceNewsItem(AdviceType::VehicleOld, GetEncodedString(str, v->index), v->index);
1450}
1451
1461uint8_t CalcPercentVehicleFilled(const Vehicle *front, StringID *colour)
1462{
1463 int count = 0;
1464 int max = 0;
1465 int cars = 0;
1466 int unloading = 0;
1467 bool loading = false;
1468
1469 bool is_loading = front->current_order.IsType(OT_LOADING);
1470
1471 /* The station may be nullptr when the (colour) string does not need to be set. */
1472 const Station *st = Station::GetIfValid(front->last_station_visited);
1473 assert(colour == nullptr || (st != nullptr && is_loading));
1474
1475 bool order_no_load = is_loading && front->current_order.GetLoadType() == OrderLoadType::NoLoad;
1476 bool order_full_load = is_loading && front->current_order.IsFullLoadOrder();
1477
1478 /* Count up max and used */
1479 for (const Vehicle *v = front; v != nullptr; v = v->Next()) {
1480 count += v->cargo.StoredCount();
1481 max += v->cargo_cap;
1482 if (v->cargo_cap != 0 && colour != nullptr) {
1483 unloading += v->vehicle_flags.Test(VehicleFlag::CargoUnloading) ? 1 : 0;
1484 loading |= !order_no_load &&
1485 (order_full_load || st->goods[v->cargo_type].HasRating()) &&
1486 !front->vehicle_flags.Test(VehicleFlag::LoadingFinished) && !front->vehicle_flags.Test(VehicleFlag::StopLoading);
1487 cars++;
1488 }
1489 }
1490
1491 if (colour != nullptr) {
1492 if (unloading == 0 && loading) {
1493 *colour = STR_PERCENT_UP;
1494 } else if (unloading == 0 && !loading) {
1495 *colour = STR_PERCENT_NONE;
1496 } else if (cars == unloading || !loading) {
1497 *colour = STR_PERCENT_DOWN;
1498 } else {
1499 *colour = STR_PERCENT_UP_DOWN;
1500 }
1501 }
1502
1503 /* Train without capacity */
1504 if (max == 0) return 100;
1505
1506 /* Return the percentage */
1507 if (count * 2 < max) {
1508 /* Less than 50%; round up, so that 0% means really empty. */
1509 return CeilDiv(count * 100, max);
1510 } else {
1511 /* More than 50%; round down, so that 100% means really full. */
1512 return (count * 100) / max;
1513 }
1514}
1515
1520 void VehicleEnterDepot(Vehicle *v)
1521{
1522 /* Always work with the front of the vehicle */
1523 assert(v == v->First());
1524
1525 switch (v->type) {
1526 case VEH_TRAIN: {
1527 Train *t = Train::From(v);
1528 SetWindowClassesDirty(WC_TRAINS_LIST);
1529 /* Clear path reservation */
1530 SetDepotReservation(t->tile, false);
1531 if (_settings_client.gui.show_track_reservation) MarkTileDirtyByTile(t->tile);
1532
1533 UpdateSignalsOnSegment(t->tile, INVALID_DIAGDIR, t->owner);
1534 t->wait_counter = 0;
1535 t->force_proceed = TFP_NONE;
1536 t->flags.Reset(VehicleRailFlag::Reversed);
1537 t->ConsistChanged(CCF_ARRANGE);
1538 break;
1539 }
1540
1541 case VEH_ROAD:
1542 SetWindowClassesDirty(WC_ROADVEH_LIST);
1543 break;
1544
1545 case VEH_SHIP: {
1546 SetWindowClassesDirty(WC_SHIPS_LIST);
1547 Ship *ship = Ship::From(v);
1548 ship->state = TRACK_BIT_DEPOT;
1549 ship->UpdateCache();
1550 ship->UpdateViewport(true, true);
1551 SetWindowDirty(WC_VEHICLE_DEPOT, v->tile);
1552 break;
1553 }
1554
1555 case VEH_AIRCRAFT:
1556 SetWindowClassesDirty(WC_AIRCRAFT_LIST);
1557 HandleAircraftEnterHangar(Aircraft::From(v));
1558 break;
1559 default: NOT_REACHED();
1560 }
1561 SetWindowDirty(WC_VEHICLE_VIEW, v->index);
1562
1563 if (v->type != VEH_TRAIN) {
1564 /* Trains update the vehicle list when the first unit enters the depot and calls VehicleEnterDepot() when the last unit enters.
1565 * We only increase the number of vehicles when the first one enters, so we will not need to search for more vehicles in the depot */
1566 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
1567 }
1568 SetWindowDirty(WC_VEHICLE_DEPOT, v->tile);
1569
1570 v->vehstatus.Set(VehState::Hidden);
1571 v->cur_speed = 0;
1572
1573 VehicleServiceInDepot(v);
1574
1575 /* Store that the vehicle entered a depot this tick */
1576 VehicleEnteredDepotThisTick(v);
1577
1578 /* After a vehicle trigger, the graphics and properties of the vehicle could change. */
1579 TriggerVehicleRandomisation(v, VehicleRandomTrigger::Depot);
1580 v->MarkDirty();
1581
1582 InvalidateWindowData(WC_VEHICLE_VIEW, v->index);
1583
1584 if (v->current_order.IsType(OT_GOTO_DEPOT)) {
1585 SetWindowDirty(WC_VEHICLE_VIEW, v->index);
1586
1587 const Order *real_order = v->GetOrder(v->cur_real_order_index);
1588
1589 /* Test whether we are heading for this depot. If not, do nothing.
1590 * Note: The target depot for nearest-/manual-depot-orders is only updated on junctions, but we want to accept every depot. */
1591 if (v->current_order.GetDepotOrderType().Test(OrderDepotTypeFlag::PartOfOrders) &&
1592 real_order != nullptr && !real_order->GetDepotActionType().Test(OrderDepotActionFlag::NearestDepot) &&
1593 (v->type == VEH_AIRCRAFT ? v->current_order.GetDestination() != GetStationIndex(v->tile) : v->dest_tile != v->tile)) {
1594 /* We are heading for another depot, keep driving. */
1595 return;
1596 }
1597
1598 if (v->current_order.IsRefit()) {
1599 Backup<CompanyID> cur_company(_current_company, v->owner);
1600 CommandCost cost = std::get<0>(Command<CMD_REFIT_VEHICLE>::Do(DoCommandFlag::Execute, v->index, v->current_order.GetRefitCargo(), 0xFF, false, false, 0));
1601 cur_company.Restore();
1602
1603 if (cost.Failed()) {
1604 _vehicles_to_autoreplace[v->index] = false;
1605 if (v->owner == _local_company) {
1606 /* Notify the user that we stopped the vehicle */
1607 AddVehicleAdviceNewsItem(AdviceType::RefitFailed, GetEncodedString(STR_NEWS_ORDER_REFIT_FAILED, v->index), v->index);
1608 }
1609 } else if (cost.GetCost() != 0) {
1610 v->profit_this_year -= cost.GetCost() << 8;
1611 if (v->owner == _local_company) {
1612 ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost.GetCost());
1613 }
1614 }
1615 }
1616
1617 if (v->current_order.GetDepotOrderType().Test(OrderDepotTypeFlag::PartOfOrders)) {
1618 /* Part of orders */
1619 v->DeleteUnreachedImplicitOrders();
1620 UpdateVehicleTimetable(v, true);
1621 v->IncrementImplicitOrderIndex();
1622 }
1623 if (v->current_order.GetDepotActionType().Test(OrderDepotActionFlag::Halt)) {
1624 /* Vehicles are always stopped on entering depots. Do not restart this one. */
1625 _vehicles_to_autoreplace[v->index] = false;
1626 /* Invalidate last_loading_station. As the link from the station
1627 * before the stop to the station after the stop can't be predicted
1628 * we shouldn't construct it when the vehicle visits the next stop. */
1629 v->last_loading_station = StationID::Invalid();
1630
1631 /* Clear unbunching data. */
1632 v->ResetDepotUnbunching();
1633
1634 /* Announce that the vehicle is waiting to players and AIs. */
1635 if (v->owner == _local_company) {
1636 AddVehicleAdviceNewsItem(AdviceType::VehicleWaiting, GetEncodedString(STR_NEWS_TRAIN_IS_WAITING + v->type, v->index), v->index);
1637 }
1638 AI::NewEvent(v->owner, new ScriptEventVehicleWaitingInDepot(v->index));
1639 }
1640
1641 /* If we've entered our unbunching depot, record the round trip duration. */
1642 if (v->current_order.GetDepotActionType().Test(OrderDepotActionFlag::Unbunch) && v->depot_unbunching_last_departure > 0) {
1643 TimerGameTick::Ticks measured_round_trip = TimerGameTick::counter - v->depot_unbunching_last_departure;
1644 if (v->round_trip_time == 0) {
1645 /* This might be our first round trip. */
1646 v->round_trip_time = measured_round_trip;
1647 } else {
1648 /* If we have a previous trip, smooth the effects of outlier trip calculations caused by jams or other interference. */
1649 v->round_trip_time = Clamp(measured_round_trip, (v->round_trip_time / 2), ClampTo<TimerGameTick::Ticks>(v->round_trip_time * 2));
1650 }
1651 }
1652
1653 v->current_order.MakeDummy();
1654 }
1655}
1656
1657
1662 void Vehicle::UpdatePosition()
1663{
1664 UpdateVehicleTileHash(this, false);
1665}
1666
1671 void Vehicle::UpdateBoundingBoxCoordinates(bool update_cache) const
1672{
1673 Rect new_coord;
1674 this->sprite_cache.sprite_seq.GetBounds(&new_coord);
1675
1676 /* z-bounds are not used. */
1677 Point pt = RemapCoords(this->x_pos + this->bounds.origin.x + this->bounds.offset.x, this->y_pos + this->bounds.origin.y + this->bounds.offset.y, this->z_pos);
1678 new_coord.left += pt.x;
1679 new_coord.top += pt.y;
1680 new_coord.right += pt.x + 2 * ZOOM_BASE;
1681 new_coord.bottom += pt.y + 2 * ZOOM_BASE;
1682
1683 extern bool _draw_bounding_boxes;
1684 if (_draw_bounding_boxes) {
1685 int x = this->x_pos + this->bounds.origin.x;
1686 int y = this->y_pos + this->bounds.origin.y;
1687 int z = this->z_pos + this->bounds.origin.z;
1688 new_coord.left = std::min(new_coord.left, RemapCoords(x + bounds.extent.x, y, z).x);
1689 new_coord.right = std::max(new_coord.right, RemapCoords(x, y + bounds.extent.y, z).x + 1);
1690 new_coord.top = std::min(new_coord.top, RemapCoords(x, y, z + bounds.extent.z).y);
1691 new_coord.bottom = std::max(new_coord.bottom, RemapCoords(x + bounds.extent.x, y + bounds.extent.y, z).y + 1);
1692 }
1693
1694 if (update_cache) {
1695 /*
1696 * If the old coordinates are invalid, set the cache to the new coordinates for correct
1697 * behaviour the next time the coordinate cache is checked.
1698 */
1699 this->sprite_cache.old_coord = this->coord.left == INVALID_COORD ? new_coord : this->coord;
1700 }
1701 else {
1702 /* Extend the bounds of the existing cached bounding box so the next dirty window is correct */
1703 this->sprite_cache.old_coord.left = std::min(this->sprite_cache.old_coord.left, this->coord.left);
1704 this->sprite_cache.old_coord.top = std::min(this->sprite_cache.old_coord.top, this->coord.top);
1705 this->sprite_cache.old_coord.right = std::max(this->sprite_cache.old_coord.right, this->coord.right);
1706 this->sprite_cache.old_coord.bottom = std::max(this->sprite_cache.old_coord.bottom, this->coord.bottom);
1707 }
1708
1709 this->coord = new_coord;
1710}
1711
1716 void Vehicle::UpdateViewport(bool dirty)
1717{
1718 /* If the existing cache is invalid we should ignore it, as it will be set to the current coords by UpdateBoundingBoxCoordinates */
1719 bool ignore_cached_coords = this->sprite_cache.old_coord.left == INVALID_COORD;
1720
1721 this->UpdateBoundingBoxCoordinates(true);
1722
1723 if (ignore_cached_coords) {
1724 UpdateVehicleViewportHash(this, this->coord.left, this->coord.top, INVALID_COORD, INVALID_COORD);
1725 } else {
1726 UpdateVehicleViewportHash(this, this->coord.left, this->coord.top, this->sprite_cache.old_coord.left, this->sprite_cache.old_coord.top);
1727 }
1728
1729 if (dirty) {
1730 if (ignore_cached_coords) {
1731 this->sprite_cache.is_viewport_candidate = this->MarkAllViewportsDirty();
1732 } else {
1733 this->sprite_cache.is_viewport_candidate = ::MarkAllViewportsDirty(
1734 std::min(this->sprite_cache.old_coord.left, this->coord.left),
1735 std::min(this->sprite_cache.old_coord.top, this->coord.top),
1736 std::max(this->sprite_cache.old_coord.right, this->coord.right),
1737 std::max(this->sprite_cache.old_coord.bottom, this->coord.bottom));
1738 }
1739 }
1740}
1741
1745 void Vehicle::UpdatePositionAndViewport()
1746{
1747 if (this->type != VEH_EFFECT) this->UpdatePosition();
1748 this->UpdateViewport(true);
1749}
1750
1755 bool Vehicle::MarkAllViewportsDirty() const
1756{
1757 return ::MarkAllViewportsDirty(this->coord.left, this->coord.top, this->coord.right, this->coord.bottom);
1758}
1759
1765 GetNewVehiclePosResult GetNewVehiclePos(const Vehicle *v)
1766{
1767 static const int8_t _delta_coord[16] = {
1768 -1,-1,-1, 0, 1, 1, 1, 0, /* x */
1769 -1, 0, 1, 1, 1, 0,-1,-1, /* y */
1770 };
1771
1772 int x = v->x_pos + _delta_coord[v->direction];
1773 int y = v->y_pos + _delta_coord[v->direction + 8];
1774
1775 GetNewVehiclePosResult gp;
1776 gp.x = x;
1777 gp.y = y;
1778 gp.old_tile = v->tile;
1779 gp.new_tile = TileVirtXY(x, y);
1780 return gp;
1781}
1782
1783static const Direction _new_direction_table[] = {
1784 DIR_N, DIR_NW, DIR_W,
1785 DIR_NE, DIR_SE, DIR_SW,
1786 DIR_E, DIR_SE, DIR_S
1787};
1788
1789 Direction GetDirectionTowards(const Vehicle *v, int x, int y)
1790{
1791 int i = 0;
1792
1793 if (y >= v->y_pos) {
1794 if (y != v->y_pos) i += 3;
1795 i += 3;
1796 }
1797
1798 if (x >= v->x_pos) {
1799 if (x != v->x_pos) i++;
1800 i++;
1801 }
1802
1803 Direction dir = v->direction;
1804
1805 DirDiff dirdiff = DirDifference(_new_direction_table[i], dir);
1806 if (dirdiff == DIRDIFF_SAME) return dir;
1807 return ChangeDir(dir, dirdiff > DIRDIFF_REVERSE ? DIRDIFF_45LEFT : DIRDIFF_45RIGHT);
1808}
1809
1819 VehicleEnterTileStates VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y)
1820{
1821 return _tile_type_procs[GetTileType(tile)]->vehicle_enter_tile_proc(v, tile, x, y);
1822}
1823
1829 UnitID FreeUnitIDGenerator::NextID() const
1830{
1831 for (auto it = std::begin(this->used_bitmap); it != std::end(this->used_bitmap); ++it) {
1832 BitmapStorage available = ~(*it);
1833 if (available == 0) continue;
1834 return static_cast<UnitID>(std::distance(std::begin(this->used_bitmap), it) * BITMAP_SIZE + FindFirstBit(available) + 1);
1835 }
1836 return static_cast<UnitID>(this->used_bitmap.size() * BITMAP_SIZE + 1);
1837}
1838
1844 UnitID FreeUnitIDGenerator::UseID(UnitID index)
1845{
1846 if (index == 0 || index == UINT16_MAX) return index;
1847
1848 index--;
1849
1850 size_t slot = index / BITMAP_SIZE;
1851 if (slot >= this->used_bitmap.size()) this->used_bitmap.resize(slot + 1);
1852 SetBit(this->used_bitmap[index / BITMAP_SIZE], index % BITMAP_SIZE);
1853
1854 return index + 1;
1855}
1856
1861 void FreeUnitIDGenerator::ReleaseID(UnitID index)
1862{
1863 if (index == 0 || index == UINT16_MAX) return;
1864
1865 index--;
1866
1867 assert(index / BITMAP_SIZE < this->used_bitmap.size());
1868 ClrBit(this->used_bitmap[index / BITMAP_SIZE], index % BITMAP_SIZE);
1869}
1870
1876 UnitID GetFreeUnitNumber(VehicleType type)
1877{
1878 /* Check whether it is allowed to build another vehicle. */
1879 uint max_veh;
1880 switch (type) {
1881 case VEH_TRAIN: max_veh = _settings_game.vehicle.max_trains; break;
1882 case VEH_ROAD: max_veh = _settings_game.vehicle.max_roadveh; break;
1883 case VEH_SHIP: max_veh = _settings_game.vehicle.max_ships; break;
1884 case VEH_AIRCRAFT: max_veh = _settings_game.vehicle.max_aircraft; break;
1885 default: NOT_REACHED();
1886 }
1887
1888 const Company *c = Company::Get(_current_company);
1889 if (c->group_all[type].num_vehicle >= max_veh) return UINT16_MAX; // Currently already at the limit, no room to make a new one.
1890
1891 return c->freeunits[type].NextID();
1892}
1893
1894
1903 bool CanBuildVehicleInfrastructure(VehicleType type, uint8_t subtype)
1904{
1905 assert(IsCompanyBuildableVehicleType(type));
1906
1907 if (!Company::IsValidID(_local_company)) return false;
1908
1909 UnitID max;
1910 switch (type) {
1911 case VEH_TRAIN:
1912 if (!HasAnyRailTypesAvail(_local_company)) return false;
1913 max = _settings_game.vehicle.max_trains;
1914 break;
1915 case VEH_ROAD:
1916 if (!HasAnyRoadTypesAvail(_local_company, (RoadTramType)subtype)) return false;
1917 max = _settings_game.vehicle.max_roadveh;
1918 break;
1919 case VEH_SHIP: max = _settings_game.vehicle.max_ships; break;
1920 case VEH_AIRCRAFT: max = _settings_game.vehicle.max_aircraft; break;
1921 default: NOT_REACHED();
1922 }
1923
1924 /* We can build vehicle infrastructure when we may build the vehicle type */
1925 if (max > 0) {
1926 /* Can we actually build the vehicle type? */
1927 for (const Engine *e : Engine::IterateType(type)) {
1928 if (type == VEH_ROAD && GetRoadTramType(e->VehInfo<RoadVehicleInfo>().roadtype) != (RoadTramType)subtype) continue;
1929 if (e->company_avail.Test(_local_company)) return true;
1930 }
1931 return false;
1932 }
1933
1934 /* We should be able to build infrastructure when we have the actual vehicle type */
1935 for (const Vehicle *v : Vehicle::Iterate()) {
1936 if (v->type == VEH_ROAD && GetRoadTramType(RoadVehicle::From(v)->roadtype) != (RoadTramType)subtype) continue;
1937 if (v->owner == _local_company && v->type == type) return true;
1938 }
1939
1940 return false;
1941}
1942
1943
1951 LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_type, const Vehicle *v)
1952{
1953 CargoType cargo_type = v == nullptr ? INVALID_CARGO : v->cargo_type;
1954 const Engine *e = Engine::Get(engine_type);
1955 switch (e->type) {
1956 default: NOT_REACHED();
1957 case VEH_TRAIN:
1958 if (v != nullptr && parent_engine_type != EngineID::Invalid() && (UsesWagonOverride(v) || (v->IsArticulatedPart() && e->VehInfo<RailVehicleInfo>().railveh_type != RAILVEH_WAGON))) {
1959 /* Wagonoverrides use the colour scheme of the front engine.
1960 * Articulated parts use the colour scheme of the first part. (Not supported for articulated wagons) */
1961 engine_type = parent_engine_type;
1962 e = Engine::Get(engine_type);
1963 /* Note: Luckily cargo_type is not needed for engines */
1964 }
1965
1966 if (!IsValidCargoType(cargo_type)) cargo_type = e->GetDefaultCargoType();
1967 if (!IsValidCargoType(cargo_type)) cargo_type = GetCargoTypeByLabel(CT_GOODS); // The vehicle does not carry anything, let's pick some freight cargo
1968 assert(IsValidCargoType(cargo_type));
1969 if (e->VehInfo<RailVehicleInfo>().railveh_type == RAILVEH_WAGON) {
1970 if (!CargoSpec::Get(cargo_type)->is_freight) {
1971 if (parent_engine_type == EngineID::Invalid()) {
1972 return LS_PASSENGER_WAGON_STEAM;
1973 } else {
1974 bool is_mu = EngInfo(parent_engine_type)->misc_flags.Test(EngineMiscFlag::RailIsMU);
1975 switch (RailVehInfo(parent_engine_type)->engclass) {
1976 default: NOT_REACHED();
1977 case EC_STEAM: return LS_PASSENGER_WAGON_STEAM;
1978 case EC_DIESEL: return is_mu ? LS_DMU : LS_PASSENGER_WAGON_DIESEL;
1979 case EC_ELECTRIC: return is_mu ? LS_EMU : LS_PASSENGER_WAGON_ELECTRIC;
1980 case EC_MONORAIL: return LS_PASSENGER_WAGON_MONORAIL;
1981 case EC_MAGLEV: return LS_PASSENGER_WAGON_MAGLEV;
1982 }
1983 }
1984 } else {
1985 return LS_FREIGHT_WAGON;
1986 }
1987 } else {
1988 bool is_mu = e->info.misc_flags.Test(EngineMiscFlag::RailIsMU);
1989
1990 switch (e->VehInfo<RailVehicleInfo>().engclass) {
1991 default: NOT_REACHED();
1992 case EC_STEAM: return LS_STEAM;
1993 case EC_DIESEL: return is_mu ? LS_DMU : LS_DIESEL;
1994 case EC_ELECTRIC: return is_mu ? LS_EMU : LS_ELECTRIC;
1995 case EC_MONORAIL: return LS_MONORAIL;
1996 case EC_MAGLEV: return LS_MAGLEV;
1997 }
1998 }
1999
2000 case VEH_ROAD:
2001 /* Always use the livery of the front */
2002 if (v != nullptr && parent_engine_type != EngineID::Invalid()) {
2003 engine_type = parent_engine_type;
2004 e = Engine::Get(engine_type);
2005 cargo_type = v->First()->cargo_type;
2006 }
2007 if (!IsValidCargoType(cargo_type)) cargo_type = e->GetDefaultCargoType();
2008 if (!IsValidCargoType(cargo_type)) cargo_type = GetCargoTypeByLabel(CT_GOODS); // The vehicle does not carry anything, let's pick some freight cargo
2009 assert(IsValidCargoType(cargo_type));
2010
2011 /* Important: Use Tram Flag of front part. Luckily engine_type refers to the front part here. */
2012 if (e->info.misc_flags.Test(EngineMiscFlag::RoadIsTram)) {
2013 /* Tram */
2014 return IsCargoInClass(cargo_type, CargoClass::Passengers) ? LS_PASSENGER_TRAM : LS_FREIGHT_TRAM;
2015 } else {
2016 /* Bus or truck */
2017 return IsCargoInClass(cargo_type, CargoClass::Passengers) ? LS_BUS : LS_TRUCK;
2018 }
2019
2020 case VEH_SHIP:
2021 if (!IsValidCargoType(cargo_type)) cargo_type = e->GetDefaultCargoType();
2022 if (!IsValidCargoType(cargo_type)) cargo_type = GetCargoTypeByLabel(CT_GOODS); // The vehicle does not carry anything, let's pick some freight cargo
2023 assert(IsValidCargoType(cargo_type));
2024 return IsCargoInClass(cargo_type, CargoClass::Passengers) ? LS_PASSENGER_SHIP : LS_FREIGHT_SHIP;
2025
2026 case VEH_AIRCRAFT:
2027 switch (e->VehInfo<AircraftVehicleInfo>().subtype) {
2028 case AIR_HELI: return LS_HELICOPTER;
2029 case AIR_CTOL: return LS_SMALL_PLANE;
2030 case AIR_CTOL | AIR_FAST: return LS_LARGE_PLANE;
2031 default: NOT_REACHED();
2032 }
2033 }
2034}
2035
2045 const Livery *GetEngineLivery(EngineID engine_type, CompanyID company, EngineID parent_engine_type, const Vehicle *v, uint8_t livery_setting)
2046{
2047 const Company *c = Company::Get(company);
2048 LiveryScheme scheme = LS_DEFAULT;
2049
2050 if (livery_setting == LIT_ALL || (livery_setting == LIT_COMPANY && company == _local_company)) {
2051 if (v != nullptr) {
2052 const Group *g = Group::GetIfValid(v->First()->group_id);
2053 if (g != nullptr) {
2054 /* Traverse parents until we find a livery or reach the top */
2055 while (!g->livery.in_use.Any({Livery::Flag::Primary, Livery::Flag::Secondary}) && g->parent != GroupID::Invalid()) {
2056 g = Group::Get(g->parent);
2057 }
2058 if (g->livery.in_use.Any({Livery::Flag::Primary, Livery::Flag::Secondary})) return &g->livery;
2059 }
2060 }
2061
2062 /* The default livery is always available for use, but its in_use flag determines
2063 * whether any _other_ liveries are in use. */
2064 if (c->livery[LS_DEFAULT].in_use.Any({Livery::Flag::Primary, Livery::Flag::Secondary})) {
2065 /* Determine the livery scheme to use */
2066 scheme = GetEngineLiveryScheme(engine_type, parent_engine_type, v);
2067 }
2068 }
2069
2070 return &c->livery[scheme];
2071}
2072
2073
2074static PaletteID GetEngineColourMap(EngineID engine_type, CompanyID company, EngineID parent_engine_type, const Vehicle *v)
2075{
2076 PaletteID map = (v != nullptr) ? v->colourmap : PAL_NONE;
2077
2078 /* Return cached value if any */
2079 if (map != PAL_NONE) return map;
2080
2081 const Engine *e = Engine::Get(engine_type);
2082
2083 /* Check if we should use the colour map callback */
2084 if (e->info.callback_mask.Test(VehicleCallbackMask::ColourRemap)) {
2085 uint16_t callback = GetVehicleCallback(CBID_VEHICLE_COLOUR_MAPPING, 0, 0, engine_type, v);
2086 /* Failure means "use the default two-colour" */
2087 if (callback != CALLBACK_FAILED) {
2088 static_assert(PAL_NONE == 0); // Returning 0x4000 (resp. 0xC000) coincidences with default value (PAL_NONE)
2089 map = GB(callback, 0, 14);
2090 /* If bit 14 is set, then the company colours are applied to the
2091 * map else it's returned as-is. */
2092 if (!HasBit(callback, 14)) {
2093 /* Update cache */
2094 if (v != nullptr) const_cast<Vehicle *>(v)->colourmap = map;
2095 return map;
2096 }
2097 }
2098 }
2099
2100 bool twocc = e->info.misc_flags.Test(EngineMiscFlag::Uses2CC);
2101
2102 if (map == PAL_NONE) map = twocc ? (PaletteID)SPR_2CCMAP_BASE : (PaletteID)PALETTE_RECOLOUR_START;
2103
2104 /* Spectator has news shown too, but has invalid company ID - as well as dedicated server */
2105 if (!Company::IsValidID(company)) return map;
2106
2107 const Livery *livery = GetEngineLivery(engine_type, company, parent_engine_type, v, _settings_client.gui.liveries);
2108
2109 map += livery->colour1;
2110 if (twocc) map += livery->colour2 * 16;
2111
2112 /* Update cache */
2113 if (v != nullptr) const_cast<Vehicle *>(v)->colourmap = map;
2114 return map;
2115}
2116
2123 PaletteID GetEnginePalette(EngineID engine_type, CompanyID company)
2124{
2125 return GetEngineColourMap(engine_type, company, EngineID::Invalid(), nullptr);
2126}
2127
2133 PaletteID GetVehiclePalette(const Vehicle *v)
2134{
2135 if (v->IsGroundVehicle()) {
2136 return GetEngineColourMap(v->engine_type, v->owner, v->GetGroundVehicleCache()->first_engine, v);
2137 }
2138
2139 return GetEngineColourMap(v->engine_type, v->owner, EngineID::Invalid(), v);
2140}
2141
2145 void Vehicle::DeleteUnreachedImplicitOrders()
2146{
2147 if (this->IsGroundVehicle()) {
2148 uint16_t &gv_flags = this->GetGroundVehicleFlags();
2149 if (HasBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS)) {
2150 /* Do not delete orders, only skip them */
2151 ClrBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
2152 this->cur_implicit_order_index = this->cur_real_order_index;
2153 InvalidateVehicleOrder(this, 0);
2154 return;
2155 }
2156 }
2157
2158 auto orders = this->Orders();
2159 VehicleOrderID cur = this->cur_implicit_order_index;
2160 while (cur != INVALID_VEH_ORDER_ID) {
2161 if (this->cur_implicit_order_index == this->cur_real_order_index) break;
2162
2163 if (orders[cur].IsType(OT_IMPLICIT)) {
2164 DeleteOrder(this, this->cur_implicit_order_index);
2165 /* DeleteOrder does various magic with order_indices, so resync 'order' with 'cur_implicit_order_index' */
2166 } else {
2167 /* Skip non-implicit orders, e.g. service-orders */
2168 if (cur < this->orders->GetNext(cur)) {
2169 this->cur_implicit_order_index++;
2170 } else {
2171 /* Wrapped around. */
2172 this->cur_implicit_order_index = 0;
2173 }
2174 cur = this->orders->GetNext(cur);
2175 }
2176 }
2177}
2178
2183 void Vehicle::BeginLoading()
2184{
2185 assert(IsTileType(this->tile, MP_STATION) || this->type == VEH_SHIP);
2186
2187 TimerGameTick::Ticks travel_time = TimerGameTick::counter - this->last_loading_tick;
2188 if (this->current_order.IsType(OT_GOTO_STATION) &&
2189 this->current_order.GetDestination() == this->last_station_visited) {
2190 this->DeleteUnreachedImplicitOrders();
2191
2192 /* Now both order indices point to the destination station, and we can start loading */
2193 this->current_order.MakeLoading(true);
2194 UpdateVehicleTimetable(this, true);
2195
2196 /* Furthermore add the Non Stop flag to mark that this station
2197 * is the actual destination of the vehicle, which is (for example)
2198 * necessary to be known for HandleTrainLoading to determine
2199 * whether the train is lost or not; not marking a train lost
2200 * that arrives at random stations is bad. */
2201 this->current_order.SetNonStopType({OrderNonStopFlag::NoIntermediate, OrderNonStopFlag::NoDestination});
2202
2203 } else {
2204 /* We weren't scheduled to stop here. Insert an implicit order
2205 * to show that we are stopping here.
2206 * While only groundvehicles have implicit orders, e.g. aircraft might still enter
2207 * the 'wrong' terminal when skipping orders etc. */
2208 Order *in_list = this->GetOrder(this->cur_implicit_order_index);
2209 if (this->IsGroundVehicle() &&
2210 (in_list == nullptr || !in_list->IsType(OT_IMPLICIT) ||
2211 in_list->GetDestination() != this->last_station_visited)) {
2212 bool suppress_implicit_orders = HasBit(this->GetGroundVehicleFlags(), GVF_SUPPRESS_IMPLICIT_ORDERS);
2213 /* Do not create consecutive duplicates of implicit orders */
2214 const Order *prev_order = this->cur_implicit_order_index > 0 ? this->GetOrder(this->cur_implicit_order_index - 1) : (this->GetNumOrders() > 1 ? this->GetLastOrder() : nullptr);
2215 if (prev_order == nullptr ||
2216 (!prev_order->IsType(OT_IMPLICIT) && !prev_order->IsType(OT_GOTO_STATION)) ||
2217 prev_order->GetDestination() != this->last_station_visited) {
2218
2219 /* Prefer deleting implicit orders instead of inserting new ones,
2220 * so test whether the right order follows later. In case of only
2221 * implicit orders treat the last order in the list like an
2222 * explicit one, except if the overall number of orders surpasses
2223 * IMPLICIT_ORDER_ONLY_CAP. */
2224 int target_index = this->cur_implicit_order_index;
2225 bool found = false;
2226 while (target_index != this->cur_real_order_index || this->GetNumManualOrders() == 0) {
2227 const Order *order = this->GetOrder(target_index);
2228 if (order == nullptr) break; // No orders.
2229 if (order->IsType(OT_IMPLICIT) && order->GetDestination() == this->last_station_visited) {
2230 found = true;
2231 break;
2232 }
2233 target_index++;
2234 if (target_index >= this->orders->GetNumOrders()) {
2235 if (this->GetNumManualOrders() == 0 &&
2236 this->GetNumOrders() < IMPLICIT_ORDER_ONLY_CAP) {
2237 break;
2238 }
2239 target_index = 0;
2240 }
2241 if (target_index == this->cur_implicit_order_index) break; // Avoid infinite loop.
2242 }
2243
2244 if (found) {
2245 if (suppress_implicit_orders) {
2246 /* Skip to the found order */
2247 this->cur_implicit_order_index = target_index;
2248 InvalidateVehicleOrder(this, 0);
2249 } else {
2250 /* Delete all implicit orders up to the station we just reached */
2251 VehicleOrderID cur = this->cur_implicit_order_index;
2252 auto orders = this->Orders();
2253 while (!orders[cur].IsType(OT_IMPLICIT) || orders[cur].GetDestination() != this->last_station_visited) {
2254 if (orders[cur].IsType(OT_IMPLICIT)) {
2255 DeleteOrder(this, this->cur_implicit_order_index);
2256 /* DeleteOrder does various magic with order_indices, so resync 'order' with 'cur_implicit_order_index' */
2257 } else {
2258 /* Skip non-implicit orders, e.g. service-orders */
2259 if (cur < this->orders->GetNext(cur)) {
2260 this->cur_implicit_order_index++;
2261 } else {
2262 /* Wrapped around. */
2263 this->cur_implicit_order_index = 0;
2264 }
2265 cur = this->orders->GetNext(cur);
2266 }
2267 }
2268 }
2269 } else if (!suppress_implicit_orders &&
2270 (this->orders == nullptr ? OrderList::CanAllocateItem() : this->orders->GetNumOrders() < MAX_VEH_ORDER_ID)) {
2271 /* Insert new implicit order */
2272 Order implicit_order{};
2273 implicit_order.MakeImplicit(this->last_station_visited);
2274 InsertOrder(this, std::move(implicit_order), this->cur_implicit_order_index);
2275 if (this->cur_implicit_order_index > 0) --this->cur_implicit_order_index;
2276
2277 /* InsertOrder disabled creation of implicit orders for all vehicles with the same implicit order.
2278 * Reenable it for this vehicle */
2279 uint16_t &gv_flags = this->GetGroundVehicleFlags();
2280 ClrBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
2281 }
2282 }
2283 }
2284 this->current_order.MakeLoading(false);
2285 }
2286
2287 if (this->last_loading_station != StationID::Invalid() &&
2288 this->last_loading_station != this->last_station_visited &&
2289 (this->current_order.GetLoadType() != OrderLoadType::NoLoad ||
2290 this->current_order.GetUnloadType() != OrderUnloadType::NoUnload)) {
2291 IncreaseStats(Station::Get(this->last_loading_station), this, this->last_station_visited, travel_time);
2292 }
2293
2294 PrepareUnload(this);
2295
2296 SetWindowDirty(GetWindowClassForVehicleType(this->type), this->owner);
2297 SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, WID_VV_START_STOP);
2298 SetWindowDirty(WC_VEHICLE_DETAILS, this->index);
2299 SetWindowDirty(WC_STATION_VIEW, this->last_station_visited);
2300
2301 Station::Get(this->last_station_visited)->MarkTilesDirty(true);
2302 this->cur_speed = 0;
2303 this->MarkDirty();
2304}
2305
2311 void Vehicle::CancelReservation(StationID next, Station *st)
2312{
2313 for (Vehicle *v = this; v != nullptr; v = v->next) {
2314 VehicleCargoList &cargo = v->cargo;
2315 if (cargo.ActionCount(VehicleCargoList::MTA_LOAD) > 0) {
2316 Debug(misc, 1, "cancelling cargo reservation");
2317 cargo.Return(UINT_MAX, &st->goods[v->cargo_type].GetOrCreateData().cargo, next, v->tile);
2318 }
2319 cargo.KeepAll();
2320 }
2321}
2322
2327 void Vehicle::LeaveStation()
2328{
2329 assert(this->current_order.IsType(OT_LOADING));
2330
2331 delete this->cargo_payment;
2332 assert(this->cargo_payment == nullptr); // cleared by ~CargoPayment
2333
2334 /* Only update the timetable if the vehicle was supposed to stop here. */
2335 if (this->current_order.GetNonStopType().Any()) UpdateVehicleTimetable(this, false);
2336
2337 if (this->current_order.GetLoadType() != OrderLoadType::NoLoad ||
2338 this->current_order.GetUnloadType() != OrderUnloadType::NoUnload) {
2339 if (this->current_order.CanLeaveWithCargo(this->last_loading_station != StationID::Invalid())) {
2340 /* Refresh next hop stats to make sure we've done that at least once
2341 * during the stop and that refit_cap == cargo_cap for each vehicle in
2342 * the consist. */
2343 this->ResetRefitCaps();
2344 LinkRefresher::Run(this);
2345
2346 /* if the vehicle could load here or could stop with cargo loaded set the last loading station */
2347 this->last_loading_station = this->last_station_visited;
2348 this->last_loading_tick = TimerGameTick::counter;
2349 } else {
2350 /* if the vehicle couldn't load and had to unload or transfer everything
2351 * set the last loading station to invalid as it will leave empty. */
2352 this->last_loading_station = StationID::Invalid();
2353 }
2354 }
2355
2356 this->current_order.MakeLeaveStation();
2357 Station *st = Station::Get(this->last_station_visited);
2358 this->CancelReservation(StationID::Invalid(), st);
2359 st->loading_vehicles.remove(this);
2360
2361 HideFillingPercent(&this->fill_percent_te_id);
2362 trip_occupancy = CalcPercentVehicleFilled(this, nullptr);
2363
2364 if (this->type == VEH_TRAIN && !this->vehstatus.Test(VehState::Crashed)) {
2365 /* Trigger station animation (trains only) */
2366 if (IsTileType(this->tile, MP_STATION)) {
2367 TriggerStationRandomisation(st, this->tile, StationRandomTrigger::VehicleDeparts);
2368 TriggerStationAnimation(st, this->tile, StationAnimationTrigger::VehicleDeparts);
2369 }
2370
2371 Train::From(this)->flags.Set(VehicleRailFlag::LeavingStation);
2372 }
2373 if (this->type == VEH_ROAD && !this->vehstatus.Test(VehState::Crashed)) {
2374 /* Trigger road stop animation */
2375 if (IsStationRoadStopTile(this->tile)) {
2376 TriggerRoadStopRandomisation(st, this->tile, StationRandomTrigger::VehicleDeparts);
2377 TriggerRoadStopAnimation(st, this->tile, StationAnimationTrigger::VehicleDeparts);
2378 }
2379 }
2380
2381
2382 this->MarkDirty();
2383}
2384
2388 void Vehicle::ResetRefitCaps()
2389{
2390 for (Vehicle *v = this; v != nullptr; v = v->Next()) v->refit_cap = v->cargo_cap;
2391}
2392
2396 void Vehicle::ReleaseUnitNumber()
2397{
2398 Company::Get(this->owner)->freeunits[this->type].ReleaseID(this->unitnumber);
2399 this->unitnumber = 0;
2400}
2401
2407 void Vehicle::HandleLoading(bool mode)
2408{
2409 switch (this->current_order.GetType()) {
2410 case OT_LOADING: {
2411 TimerGameTick::Ticks wait_time = std::max(this->current_order.GetTimetabledWait() - this->lateness_counter, 0);
2412
2413 /* Not the first call for this tick, or still loading */
2414 if (mode || !this->vehicle_flags.Test(VehicleFlag::LoadingFinished) || this->current_order_time < wait_time) return;
2415
2416 this->PlayLeaveStationSound();
2417
2418 this->LeaveStation();
2419
2420 /* Only advance to next order if we just loaded at the current one */
2421 const Order *order = this->GetOrder(this->cur_implicit_order_index);
2422 if (order == nullptr ||
2423 (!order->IsType(OT_IMPLICIT) && !order->IsType(OT_GOTO_STATION)) ||
2424 order->GetDestination() != this->last_station_visited) {
2425 return;
2426 }
2427 break;
2428 }
2429
2430 case OT_DUMMY: break;
2431
2432 default: return;
2433 }
2434
2435 this->IncrementImplicitOrderIndex();
2436}
2437
2442 bool Vehicle::HasFullLoadOrder() const
2443{
2444 return std::ranges::any_of(this->Orders(), [](const Order &o) {
2445 return o.IsType(OT_GOTO_STATION) && o.IsFullLoadOrder();
2446 });
2447}
2448
2453 bool Vehicle::HasConditionalOrder() const
2454{
2455 return std::ranges::any_of(this->Orders(), [](const Order &o) { return o.IsType(OT_CONDITIONAL); });
2456}
2457
2462 bool Vehicle::HasUnbunchingOrder() const
2463{
2464 return std::ranges::any_of(this->Orders(), [](const Order &o) {
2465 return o.IsType(OT_GOTO_DEPOT) && o.GetDepotActionType().Test(OrderDepotActionFlag::Unbunch);
2466 });
2467}
2468
2473 static bool PreviousOrderIsUnbunching(const Vehicle *v)
2474{
2475 /* If we are headed for the first order, we must wrap around back to the last order. */
2476 bool is_first_order = (v->GetOrder(v->cur_implicit_order_index) == v->GetFirstOrder());
2477 const Order *previous_order = (is_first_order) ? v->GetLastOrder() : v->GetOrder(v->cur_implicit_order_index - 1);
2478
2479 if (previous_order == nullptr || !previous_order->IsType(OT_GOTO_DEPOT)) return false;
2480 return previous_order->GetDepotActionType().Test(OrderDepotActionFlag::Unbunch);
2481}
2482
2486 void Vehicle::LeaveUnbunchingDepot()
2487{
2488 /* Don't do anything if this is not our unbunching order. */
2489 if (!PreviousOrderIsUnbunching(this)) return;
2490
2491 /* Set the start point for this round trip time. */
2492 this->depot_unbunching_last_departure = TimerGameTick::counter;
2493
2494 /* Tell the timetable we are now "on time." */
2495 this->lateness_counter = 0;
2496 SetWindowDirty(WC_VEHICLE_TIMETABLE, this->index);
2497
2498 /* Find the average travel time of vehicles that we share orders with. */
2499 int num_vehicles = 0;
2500 TimerGameTick::Ticks total_travel_time = 0;
2501
2502 Vehicle *u = this->FirstShared();
2503 for (; u != nullptr; u = u->NextShared()) {
2504 /* Ignore vehicles that are manually stopped or crashed. */
2505 if (u->vehstatus.Any({VehState::Stopped, VehState::Crashed})) continue;
2506
2507 num_vehicles++;
2508 total_travel_time += u->round_trip_time;
2509 }
2510
2511 /* Make sure we cannot divide by 0. */
2512 num_vehicles = std::max(num_vehicles, 1);
2513
2514 /* Calculate the separation by finding the average travel time, then calculating equal separation (minimum 1 tick) between vehicles. */
2515 TimerGameTick::Ticks separation = std::max((total_travel_time / num_vehicles / num_vehicles), 1);
2516 TimerGameTick::TickCounter next_departure = TimerGameTick::counter + separation;
2517
2518 /* Set the departure time of all vehicles that we share orders with. */
2519 u = this->FirstShared();
2520 for (; u != nullptr; u = u->NextShared()) {
2521 /* Ignore vehicles that are manually stopped or crashed. */
2522 if (u->vehstatus.Any({VehState::Stopped, VehState::Crashed})) continue;
2523
2524 u->depot_unbunching_next_departure = next_departure;
2525 SetWindowDirty(WC_VEHICLE_VIEW, u->index);
2526 }
2527}
2528
2533 bool Vehicle::IsWaitingForUnbunching() const
2534{
2535 assert(this->IsInDepot());
2536
2537 /* Don't bother if there are no vehicles sharing orders. */
2538 if (!this->IsOrderListShared()) return false;
2539
2540 /* Don't do anything if there aren't enough orders. */
2541 if (this->GetNumOrders() <= 1) return false;
2542
2543 /* Don't do anything if this is not our unbunching order. */
2544 if (!PreviousOrderIsUnbunching(this)) return false;
2545
2546 return (this->depot_unbunching_next_departure > TimerGameTick::counter);
2547};
2548
2555 CommandCost Vehicle::SendToDepot(DoCommandFlags flags, DepotCommandFlags command)
2556{
2557 CommandCost ret = CheckOwnership(this->owner);
2558 if (ret.Failed()) return ret;
2559
2560 if (this->vehstatus.Test(VehState::Crashed)) return CMD_ERROR;
2561 if (this->IsStoppedInDepot()) return CMD_ERROR;
2562
2563 /* No matter why we're headed to the depot, unbunching data is no longer valid. */
2564 if (flags.Test(DoCommandFlag::Execute)) this->ResetDepotUnbunching();
2565
2566 if (this->current_order.IsType(OT_GOTO_DEPOT)) {
2567 bool halt_in_depot = this->current_order.GetDepotActionType().Test(OrderDepotActionFlag::Halt);
2568 if (command.Test(DepotCommandFlag::Service) == halt_in_depot) {
2569 /* We called with a different DEPOT_SERVICE setting.
2570 * Now we change the setting to apply the new one and let the vehicle head for the same depot.
2571 * Note: the if is (true for requesting service == true for ordered to stop in depot) */
2572 if (flags.Test(DoCommandFlag::Execute)) {
2573 this->current_order.SetDepotOrderType({});
2574 this->current_order.SetDepotActionType(halt_in_depot ? OrderDepotActionFlags{} : OrderDepotActionFlag::Halt);
2575 SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, WID_VV_START_STOP);
2576 }
2577 return CommandCost();
2578 }
2579
2580 if (command.Test(DepotCommandFlag::DontCancel)) return CMD_ERROR; // Requested no cancellation of depot orders
2581 if (flags.Test(DoCommandFlag::Execute)) {
2582 /* If the orders to 'goto depot' are in the orders list (forced servicing),
2583 * then skip to the next order; effectively cancelling this forced service */
2584 if (this->current_order.GetDepotOrderType().Test(OrderDepotTypeFlag::PartOfOrders)) this->IncrementRealOrderIndex();
2585
2586 if (this->IsGroundVehicle()) {
2587 uint16_t &gv_flags = this->GetGroundVehicleFlags();
2588 SetBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
2589 }
2590
2591 this->current_order.MakeDummy();
2592 SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, WID_VV_START_STOP);
2593 }
2594 return CommandCost();
2595 }
2596
2597 ClosestDepot closest_depot = this->FindClosestDepot();
2598 static const StringID no_depot[] = {STR_ERROR_UNABLE_TO_FIND_ROUTE_TO, STR_ERROR_UNABLE_TO_FIND_LOCAL_DEPOT, STR_ERROR_UNABLE_TO_FIND_LOCAL_DEPOT, STR_ERROR_CAN_T_SEND_AIRCRAFT_TO_HANGAR};
2599 if (!closest_depot.found) return CommandCost(no_depot[this->type]);
2600
2601 if (flags.Test(DoCommandFlag::Execute)) {
2602 if (this->current_order.IsType(OT_LOADING)) this->LeaveStation();
2603
2604 if (this->IsGroundVehicle() && this->GetNumManualOrders() > 0) {
2605 uint16_t &gv_flags = this->GetGroundVehicleFlags();
2606 SetBit(gv_flags, GVF_SUPPRESS_IMPLICIT_ORDERS);
2607 }
2608
2609 this->SetDestTile(closest_depot.location);
2610 this->current_order.MakeGoToDepot(closest_depot.destination.ToDepotID(), {});
2611 if (!command.Test(DepotCommandFlag::Service)) this->current_order.SetDepotActionType(OrderDepotActionFlag::Halt);
2612 SetWindowWidgetDirty(WC_VEHICLE_VIEW, this->index, WID_VV_START_STOP);
2613
2614 /* If there is no depot in front and the train is not already reversing, reverse automatically (trains only) */
2615 if (this->type == VEH_TRAIN && (closest_depot.reverse ^ Train::From(this)->flags.Test(VehicleRailFlag::Reversing))) {
2616 Command<CMD_REVERSE_TRAIN_DIRECTION>::Do(DoCommandFlag::Execute, this->index, false);
2617 }
2618
2619 if (this->type == VEH_AIRCRAFT) {
2620 Aircraft *a = Aircraft::From(this);
2621 if (a->state == FLYING && a->targetairport != closest_depot.destination) {
2622 /* The aircraft is now heading for a different hangar than the next in the orders */
2623 AircraftNextAirportPos_and_Order(a);
2624 }
2625 }
2626 }
2627
2628 return CommandCost();
2629
2630}
2631
2636 void Vehicle::UpdateVisualEffect(bool allow_power_change)
2637{
2638 bool powered_before = HasBit(this->vcache.cached_vis_effect, VE_DISABLE_WAGON_POWER);
2639 const Engine *e = this->GetEngine();
2640
2641 /* Evaluate properties */
2642 uint8_t visual_effect;
2643 switch (e->type) {
2644 case VEH_TRAIN: visual_effect = e->VehInfo<RailVehicleInfo>().visual_effect; break;
2645 case VEH_ROAD: visual_effect = e->VehInfo<RoadVehicleInfo>().visual_effect; break;
2646 case VEH_SHIP: visual_effect = e->VehInfo<ShipVehicleInfo>().visual_effect; break;
2647 default: visual_effect = 1 << VE_DISABLE_EFFECT; break;
2648 }
2649
2650 /* Check powered wagon / visual effect callback */
2651 if (e->info.callback_mask.Test(VehicleCallbackMask::VisualEffect)) {
2652 uint16_t callback = GetVehicleCallback(CBID_VEHICLE_VISUAL_EFFECT, 0, 0, this->engine_type, this);
2653
2654 if (callback != CALLBACK_FAILED) {
2655 if (callback >= 0x100 && e->GetGRF()->grf_version >= 8) ErrorUnknownCallbackResult(e->GetGRFID(), CBID_VEHICLE_VISUAL_EFFECT, callback);
2656
2657 callback = GB(callback, 0, 8);
2658 /* Avoid accidentally setting 'visual_effect' to the default value
2659 * Since bit 6 (disable effects) is set anyways, we can safely erase some bits. */
2660 if (callback == VE_DEFAULT) {
2661 assert(HasBit(callback, VE_DISABLE_EFFECT));
2662 SB(callback, VE_TYPE_START, VE_TYPE_COUNT, 0);
2663 }
2664 visual_effect = callback;
2665 }
2666 }
2667
2668 /* Apply default values */
2669 if (visual_effect == VE_DEFAULT ||
2670 (!HasBit(visual_effect, VE_DISABLE_EFFECT) && GB(visual_effect, VE_TYPE_START, VE_TYPE_COUNT) == VE_TYPE_DEFAULT)) {
2671 /* Only train engines have default effects.
2672 * Note: This is independent of whether the engine is a front engine or articulated part or whatever. */
2673 if (e->type != VEH_TRAIN || e->VehInfo<RailVehicleInfo>().railveh_type == RAILVEH_WAGON || !IsInsideMM(e->VehInfo<RailVehicleInfo>().engclass, EC_STEAM, EC_MONORAIL)) {
2674 if (visual_effect == VE_DEFAULT) {
2675 visual_effect = 1 << VE_DISABLE_EFFECT;
2676 } else {
2677 SetBit(visual_effect, VE_DISABLE_EFFECT);
2678 }
2679 } else {
2680 if (visual_effect == VE_DEFAULT) {
2681 /* Also set the offset */
2682 visual_effect = (VE_OFFSET_CENTRE - (e->VehInfo<RailVehicleInfo>().engclass == EC_STEAM ? 4 : 0)) << VE_OFFSET_START;
2683 }
2684 SB(visual_effect, VE_TYPE_START, VE_TYPE_COUNT, e->VehInfo<RailVehicleInfo>().engclass - EC_STEAM + VE_TYPE_STEAM);
2685 }
2686 }
2687
2688 this->vcache.cached_vis_effect = visual_effect;
2689
2690 if (!allow_power_change && powered_before != HasBit(this->vcache.cached_vis_effect, VE_DISABLE_WAGON_POWER)) {
2691 ToggleBit(this->vcache.cached_vis_effect, VE_DISABLE_WAGON_POWER);
2692 ShowNewGrfVehicleError(this->engine_type, STR_NEWGRF_BROKEN, STR_NEWGRF_BROKEN_POWERED_WAGON, GRFBug::VehPoweredWagon, false);
2693 }
2694}
2695
2696static const int8_t _vehicle_smoke_pos[8] = {
2697 1, 1, 1, 0, -1, -1, -1, 0
2698};
2699
2704 static void SpawnAdvancedVisualEffect(const Vehicle *v)
2705{
2706 std::array<int32_t, 4> regs100;
2707 uint16_t callback = GetVehicleCallback(CBID_VEHICLE_SPAWN_VISUAL_EFFECT, 0, Random(), v->engine_type, v, regs100);
2708 if (callback == CALLBACK_FAILED) return;
2709
2710 uint count = GB(callback, 0, 2);
2711 assert(count <= std::size(regs100));
2712 bool auto_center = HasBit(callback, 13);
2713 bool auto_rotate = !HasBit(callback, 14);
2714
2715 int8_t l_center = 0;
2716 if (auto_center) {
2717 /* For road vehicles: Compute offset from vehicle position to vehicle center */
2718 if (v->type == VEH_ROAD) l_center = -(int)(VEHICLE_LENGTH - RoadVehicle::From(v)->gcache.cached_veh_length) / 2;
2719 } else {
2720 /* For trains: Compute offset from vehicle position to sprite position */
2721 if (v->type == VEH_TRAIN) l_center = (VEHICLE_LENGTH - Train::From(v)->gcache.cached_veh_length) / 2;
2722 }
2723
2724 Direction l_dir = v->direction;
2725 if (v->type == VEH_TRAIN && Train::From(v)->flags.Test(VehicleRailFlag::Flipped)) l_dir = ReverseDir(l_dir);
2726 Direction t_dir = ChangeDir(l_dir, DIRDIFF_90RIGHT);
2727
2728 int8_t x_center = _vehicle_smoke_pos[l_dir] * l_center;
2729 int8_t y_center = _vehicle_smoke_pos[t_dir] * l_center;
2730
2731 for (uint i = 0; i < count; i++) {
2732 int32_t reg = regs100[i];
2733 uint type = GB(reg, 0, 8);
2734 int8_t x = GB(reg, 8, 8);
2735 int8_t y = GB(reg, 16, 8);
2736 int8_t z = GB(reg, 24, 8);
2737
2738 if (auto_rotate) {
2739 int8_t l = x;
2740 int8_t t = y;
2741 x = _vehicle_smoke_pos[l_dir] * l + _vehicle_smoke_pos[t_dir] * t;
2742 y = _vehicle_smoke_pos[t_dir] * l - _vehicle_smoke_pos[l_dir] * t;
2743 }
2744
2745 if (type >= 0xF0) {
2746 switch (type) {
2747 case 0xF1: CreateEffectVehicleRel(v, x_center + x, y_center + y, z, EV_STEAM_SMOKE); break;
2748 case 0xF2: CreateEffectVehicleRel(v, x_center + x, y_center + y, z, EV_DIESEL_SMOKE); break;
2749 case 0xF3: CreateEffectVehicleRel(v, x_center + x, y_center + y, z, EV_ELECTRIC_SPARK); break;
2750 case 0xFA: CreateEffectVehicleRel(v, x_center + x, y_center + y, z, EV_BREAKDOWN_SMOKE_AIRCRAFT); break;
2751 default: break;
2752 }
2753 }
2754 }
2755}
2756
2762 static bool IsBridgeAboveVehicle(const Vehicle *v)
2763{
2764 if (IsBridgeTile(v->tile)) {
2765 /* If the vehicle is 'on' a bridge tile, check the real position of the vehicle. If it's different then the
2766 * vehicle is on the middle of the bridge, which cannot have a bridge above. */
2767 TileIndex tile = TileVirtXY(v->x_pos, v->y_pos);
2768 if (tile != v->tile) return false;
2769 }
2770 return IsBridgeAbove(v->tile);
2771}
2772
2777 void Vehicle::ShowVisualEffect() const
2778{
2779 assert(this->IsPrimaryVehicle());
2780 bool sound = false;
2781
2782 /* Do not show any smoke when:
2783 * - vehicle smoke is disabled by the player
2784 * - the vehicle is slowing down or stopped (by the player)
2785 * - the vehicle is moving very slowly
2786 */
2787 if (_settings_game.vehicle.smoke_amount == 0 ||
2788 this->vehstatus.Any({VehState::TrainSlowing, VehState::Stopped}) ||
2789 this->cur_speed < 2) {
2790 return;
2791 }
2792
2793 /* Use the speed as limited by underground and orders. */
2794 uint max_speed = this->GetCurrentMaxSpeed();
2795
2796 if (this->type == VEH_TRAIN) {
2797 const Train *t = Train::From(this);
2798 /* For trains, do not show any smoke when:
2799 * - the train is reversing
2800 * - is entering a station with an order to stop there and its speed is equal to maximum station entering speed
2801 */
2802 if (t->flags.Test(VehicleRailFlag::Reversing) ||
2803 (IsRailStationTile(t->tile) && t->IsFrontEngine() && t->current_order.ShouldStopAtStation(t, GetStationIndex(t->tile)) &&
2804 t->cur_speed >= max_speed)) {
2805 return;
2806 }
2807 }
2808
2809 const Vehicle *v = this;
2810
2811 do {
2812 bool advanced = HasBit(v->vcache.cached_vis_effect, VE_ADVANCED_EFFECT);
2813 int effect_offset = GB(v->vcache.cached_vis_effect, VE_OFFSET_START, VE_OFFSET_COUNT) - VE_OFFSET_CENTRE;
2814 VisualEffectSpawnModel effect_model = VESM_NONE;
2815 if (advanced) {
2816 effect_offset = VE_OFFSET_CENTRE;
2817 effect_model = (VisualEffectSpawnModel)GB(v->vcache.cached_vis_effect, 0, VE_ADVANCED_EFFECT);
2818 if (effect_model >= VESM_END) effect_model = VESM_NONE; // unknown spawning model
2819 } else {
2820 effect_model = (VisualEffectSpawnModel)GB(v->vcache.cached_vis_effect, VE_TYPE_START, VE_TYPE_COUNT);
2821 assert(effect_model != (VisualEffectSpawnModel)VE_TYPE_DEFAULT); // should have been resolved by UpdateVisualEffect
2822 static_assert((uint)VESM_STEAM == (uint)VE_TYPE_STEAM);
2823 static_assert((uint)VESM_DIESEL == (uint)VE_TYPE_DIESEL);
2824 static_assert((uint)VESM_ELECTRIC == (uint)VE_TYPE_ELECTRIC);
2825 }
2826
2827 /* Show no smoke when:
2828 * - Smoke has been disabled for this vehicle
2829 * - The vehicle is not visible
2830 * - The vehicle is under a bridge
2831 * - The vehicle is on a depot tile
2832 * - The vehicle is on a tunnel tile
2833 * - The vehicle is a train engine that is currently unpowered */
2834 if (effect_model == VESM_NONE ||
2835 v->vehstatus.Test(VehState::Hidden) ||
2836 IsBridgeAboveVehicle(v) ||
2837 IsDepotTile(v->tile) ||
2838 IsTunnelTile(v->tile) ||
2839 (v->type == VEH_TRAIN &&
2840 !HasPowerOnRail(Train::From(v)->railtypes, GetTileRailType(v->tile)))) {
2841 continue;
2842 }
2843
2844 EffectVehicleType evt = EV_END;
2845 switch (effect_model) {
2846 case VESM_STEAM:
2847 /* Steam smoke - amount is gradually falling until vehicle reaches its maximum speed, after that it's normal.
2848 * Details: while vehicle's current speed is gradually increasing, steam plumes' density decreases by one third each
2849 * third of its maximum speed spectrum. Steam emission finally normalises at very close to vehicle's maximum speed.
2850 * REGULATION:
2851 * - instead of 1, 4 / 2^smoke_amount (max. 2) is used to provide sufficient regulation to steam puffs' amount. */
2852 if (GB(v->tick_counter, 0, ((4 >> _settings_game.vehicle.smoke_amount) + ((this->cur_speed * 3) / max_speed))) == 0) {
2853 evt = EV_STEAM_SMOKE;
2854 }
2855 break;
2856
2857 case VESM_DIESEL: {
2858 /* Diesel smoke - thicker when vehicle is starting, gradually subsiding till it reaches its maximum speed
2859 * when smoke emission stops.
2860 * Details: Vehicle's (max.) speed spectrum is divided into 32 parts. When max. speed is reached, chance for smoke
2861 * emission erodes by 32 (1/4). For trains, power and weight come in handy too to either increase smoke emission in
2862 * 6 steps (1000HP each) if the power is low or decrease smoke emission in 6 steps (512 tonnes each) if the train
2863 * isn't overweight. Power and weight contributions are expressed in a way that neither extreme power, nor
2864 * extreme weight can ruin the balance (e.g. FreightWagonMultiplier) in the formula. When the vehicle reaches
2865 * maximum speed no diesel_smoke is emitted.
2866 * REGULATION:
2867 * - up to which speed a diesel vehicle is emitting smoke (with reduced/small setting only until 1/2 of max_speed),
2868 * - in Chance16 - the last value is 512 / 2^smoke_amount (max. smoke when 128 = smoke_amount of 2). */
2869 int power_weight_effect = 0;
2870 if (v->type == VEH_TRAIN) {
2871 power_weight_effect = (32 >> (Train::From(this)->gcache.cached_power >> 10)) - (32 >> (Train::From(this)->gcache.cached_weight >> 9));
2872 }
2873 if (this->cur_speed < (max_speed >> (2 >> _settings_game.vehicle.smoke_amount)) &&
2874 Chance16((64 - ((this->cur_speed << 5) / max_speed) + power_weight_effect), (512 >> _settings_game.vehicle.smoke_amount))) {
2875 evt = EV_DIESEL_SMOKE;
2876 }
2877 break;
2878 }
2879
2880 case VESM_ELECTRIC:
2881 /* Electric train's spark - more often occurs when train is departing (more load)
2882 * Details: Electric locomotives are usually at least twice as powerful as their diesel counterparts, so spark
2883 * emissions are kept simple. Only when starting, creating huge force are sparks more likely to happen, but when
2884 * reaching its max. speed, quarter by quarter of it, chance decreases until the usual 2,22% at train's top speed.
2885 * REGULATION:
2886 * - in Chance16 the last value is 360 / 2^smoke_amount (max. sparks when 90 = smoke_amount of 2). */
2887 if (GB(v->tick_counter, 0, 2) == 0 &&
2888 Chance16((6 - ((this->cur_speed << 2) / max_speed)), (360 >> _settings_game.vehicle.smoke_amount))) {
2889 evt = EV_ELECTRIC_SPARK;
2890 }
2891 break;
2892
2893 default:
2894 NOT_REACHED();
2895 }
2896
2897 if (evt != EV_END && advanced) {
2898 sound = true;
2899 SpawnAdvancedVisualEffect(v);
2900 } else if (evt != EV_END) {
2901 sound = true;
2902
2903 /* The effect offset is relative to a point 4 units behind the vehicle's
2904 * front (which is the center of an 8/8 vehicle). Shorter vehicles need a
2905 * correction factor. */
2906 if (v->type == VEH_TRAIN) effect_offset += (VEHICLE_LENGTH - Train::From(v)->gcache.cached_veh_length) / 2;
2907
2908 int x = _vehicle_smoke_pos[v->direction] * effect_offset;
2909 int y = _vehicle_smoke_pos[(v->direction + 2) % 8] * effect_offset;
2910
2911 if (v->type == VEH_TRAIN && Train::From(v)->flags.Test(VehicleRailFlag::Flipped)) {
2912 x = -x;
2913 y = -y;
2914 }
2915
2916 CreateEffectVehicleRel(v, x, y, 10, evt);
2917 }
2918 } while ((v = v->Next()) != nullptr);
2919
2920 if (sound) PlayVehicleSound(this, VSE_VISUAL_EFFECT);
2921}
2922
2927 void Vehicle::SetNext(Vehicle *next)
2928{
2929 assert(this != next);
2930
2931 if (this->next != nullptr) {
2932 /* We had an old next vehicle. Update the first and previous pointers */
2933 for (Vehicle *v = this->next; v != nullptr; v = v->Next()) {
2934 v->first = this->next;
2935 }
2936 this->next->previous = nullptr;
2937 }
2938
2939 this->next = next;
2940
2941 if (this->next != nullptr) {
2942 /* A new next vehicle. Update the first and previous pointers */
2943 if (this->next->previous != nullptr) this->next->previous->next = nullptr;
2944 this->next->previous = this;
2945 for (Vehicle *v = this->next; v != nullptr; v = v->Next()) {
2946 v->first = this->first;
2947 }
2948 }
2949}
2950
2956 void Vehicle::AddToShared(Vehicle *shared_chain)
2957{
2958 assert(this->previous_shared == nullptr && this->next_shared == nullptr);
2959
2960 if (shared_chain->orders == nullptr) {
2961 assert(shared_chain->previous_shared == nullptr);
2962 assert(shared_chain->next_shared == nullptr);
2963 this->orders = shared_chain->orders = new OrderList(shared_chain);
2964 }
2965
2966 this->next_shared = shared_chain->next_shared;
2967 this->previous_shared = shared_chain;
2968
2969 shared_chain->next_shared = this;
2970
2971 if (this->next_shared != nullptr) this->next_shared->previous_shared = this;
2972
2973 shared_chain->orders->AddVehicle(this);
2974}
2975
2979 void Vehicle::RemoveFromShared()
2980{
2981 /* Remember if we were first and the old window number before RemoveVehicle()
2982 * as this changes first if needed. */
2983 bool were_first = (this->FirstShared() == this);
2984 VehicleListIdentifier vli(VL_SHARED_ORDERS, this->type, this->owner, this->FirstShared()->index);
2985
2986 this->orders->RemoveVehicle(this);
2987
2988 if (!were_first) {
2989 /* We are not the first shared one, so only relink our previous one. */
2990 this->previous_shared->next_shared = this->NextShared();
2991 }
2992
2993 if (this->next_shared != nullptr) this->next_shared->previous_shared = this->previous_shared;
2994
2995
2996 if (this->orders->GetNumVehicles() == 1) {
2997 /* When there is only one vehicle, remove the shared order list window. */
2998 CloseWindowById(GetWindowClassForVehicleType(this->type), vli.ToWindowNumber());
2999 InvalidateVehicleOrder(this->FirstShared(), VIWD_MODIFY_ORDERS);
3000 } else if (were_first) {
3001 /* If we were the first one, update to the new first one.
3002 * Note: FirstShared() is already the new first */
3003 InvalidateWindowData(GetWindowClassForVehicleType(this->type), vli.ToWindowNumber(), this->FirstShared()->index.base() | (1U << 31));
3004 }
3005
3006 this->next_shared = nullptr;
3007 this->previous_shared = nullptr;
3008}
3009
3010static const IntervalTimer<TimerGameEconomy> _economy_vehicles_yearly({TimerGameEconomy::YEAR, TimerGameEconomy::Priority::VEHICLE}, [](auto)
3011{
3012 for (Vehicle *v : Vehicle::Iterate()) {
3013 if (v->IsPrimaryVehicle()) {
3014 /* show warning if vehicle is not generating enough income last 2 years (corresponds to a red icon in the vehicle list) */
3015 Money profit = v->GetDisplayProfitThisYear();
3016 if (v->economy_age >= VEHICLE_PROFIT_MIN_AGE && profit < 0) {
3017 if (_settings_client.gui.vehicle_income_warn && v->owner == _local_company) {
3018 AddVehicleAdviceNewsItem(AdviceType::VehicleUnprofitable,
3019 GetEncodedString(TimerGameEconomy::UsingWallclockUnits() ? STR_NEWS_VEHICLE_UNPROFITABLE_PERIOD : STR_NEWS_VEHICLE_UNPROFITABLE_YEAR, v->index, profit),
3020 v->index);
3021 }
3022 AI::NewEvent(v->owner, new ScriptEventVehicleUnprofitable(v->index));
3023 }
3024
3025 v->profit_last_year = v->profit_this_year;
3026 v->profit_this_year = 0;
3027 SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
3028 }
3029 }
3030 GroupStatistics::UpdateProfits();
3031 SetWindowClassesDirty(WC_TRAINS_LIST);
3032 SetWindowClassesDirty(WC_SHIPS_LIST);
3033 SetWindowClassesDirty(WC_ROADVEH_LIST);
3034 SetWindowClassesDirty(WC_AIRCRAFT_LIST);
3035});
3036
3046 bool CanVehicleUseStation(EngineID engine_type, const Station *st)
3047{
3048 const Engine *e = Engine::GetIfValid(engine_type);
3049 assert(e != nullptr);
3050
3051 switch (e->type) {
3052 case VEH_TRAIN:
3053 return st->facilities.Test(StationFacility::Train);
3054
3055 case VEH_ROAD:
3056 /* For road vehicles we need the vehicle to know whether it can actually
3057 * use the station, but if it doesn't have facilities for RVs it is
3058 * certainly not possible that the station can be used. */
3059 return st->facilities.Any({StationFacility::BusStop, StationFacility::TruckStop});
3060
3061 case VEH_SHIP:
3062 return st->facilities.Test(StationFacility::Dock);
3063
3064 case VEH_AIRCRAFT:
3065 return st->facilities.Test(StationFacility::Airport) &&
3066 st->airport.GetFTA()->flags.Test(e->VehInfo<AircraftVehicleInfo>().subtype & AIR_CTOL ? AirportFTAClass::Flag::Airplanes : AirportFTAClass::Flag::Helicopters);
3067
3068 default:
3069 return false;
3070 }
3071}
3072
3079 bool CanVehicleUseStation(const Vehicle *v, const Station *st)
3080{
3081 if (v->type == VEH_ROAD) return st->GetPrimaryRoadStop(RoadVehicle::From(v)) != nullptr;
3082
3083 return CanVehicleUseStation(v->engine_type, st);
3084}
3085
3092 StringID GetVehicleCannotUseStationReason(const Vehicle *v, const Station *st)
3093{
3094 switch (v->type) {
3095 case VEH_TRAIN:
3096 return STR_ERROR_NO_RAIL_STATION;
3097
3098 case VEH_ROAD: {
3099 const RoadVehicle *rv = RoadVehicle::From(v);
3100 RoadStop *rs = st->GetPrimaryRoadStop(rv->IsBus() ? RoadStopType::Bus : RoadStopType::Truck);
3101
3102 StringID err = rv->IsBus() ? STR_ERROR_NO_BUS_STATION : STR_ERROR_NO_TRUCK_STATION;
3103
3104 for (; rs != nullptr; rs = rs->next) {
3105 /* Articulated vehicles cannot use bay road stops, only drive-through. Make sure the vehicle can actually use this bay stop */
3106 if (HasTileAnyRoadType(rs->xy, rv->compatible_roadtypes) && IsBayRoadStopTile(rs->xy) && rv->HasArticulatedPart()) {
3107 err = STR_ERROR_NO_STOP_ARTICULATED_VEHICLE;
3108 continue;
3109 }
3110
3111 /* Bay stop errors take precedence, but otherwise the vehicle may not be compatible with the roadtype/tramtype of this station tile.
3112 * We give bay stop errors precedence because they are usually a bus sent to a tram station or vice versa. */
3113 if (!HasTileAnyRoadType(rs->xy, rv->compatible_roadtypes) && err != STR_ERROR_NO_STOP_ARTICULATED_VEHICLE) {
3114 err = RoadTypeIsRoad(rv->roadtype) ? STR_ERROR_NO_STOP_COMPATIBLE_ROAD_TYPE : STR_ERROR_NO_STOP_COMPATIBLE_TRAM_TYPE;
3115 continue;
3116 }
3117 }
3118
3119 return err;
3120 }
3121
3122 case VEH_SHIP:
3123 return STR_ERROR_NO_DOCK;
3124
3125 case VEH_AIRCRAFT:
3126 if (!st->facilities.Test(StationFacility::Airport)) return STR_ERROR_NO_AIRPORT;
3127 if (v->GetEngine()->VehInfo<AircraftVehicleInfo>().subtype & AIR_CTOL) {
3128 return STR_ERROR_AIRPORT_NO_PLANES;
3129 } else {
3130 return STR_ERROR_AIRPORT_NO_HELICOPTERS;
3131 }
3132
3133 default:
3134 return INVALID_STRING_ID;
3135 }
3136}
3137
3143 GroundVehicleCache *Vehicle::GetGroundVehicleCache()
3144{
3145 assert(this->IsGroundVehicle());
3146 if (this->type == VEH_TRAIN) {
3147 return &Train::From(this)->gcache;
3148 } else {
3149 return &RoadVehicle::From(this)->gcache;
3150 }
3151}
3152
3158 const GroundVehicleCache *Vehicle::GetGroundVehicleCache() const
3159{
3160 assert(this->IsGroundVehicle());
3161 if (this->type == VEH_TRAIN) {
3162 return &Train::From(this)->gcache;
3163 } else {
3164 return &RoadVehicle::From(this)->gcache;
3165 }
3166}
3167
3173uint16_t &Vehicle::GetGroundVehicleFlags()
3174{
3175 assert(this->IsGroundVehicle());
3176 if (this->type == VEH_TRAIN) {
3177 return Train::From(this)->gv_flags;
3178 } else {
3179 return RoadVehicle::From(this)->gv_flags;
3180 }
3181}
3182
3188 const uint16_t &Vehicle::GetGroundVehicleFlags() const
3189{
3190 assert(this->IsGroundVehicle());
3191 if (this->type == VEH_TRAIN) {
3192 return Train::From(this)->gv_flags;
3193 } else {
3194 return RoadVehicle::From(this)->gv_flags;
3195 }
3196}
3197
3206 void GetVehicleSet(VehicleSet &set, Vehicle *v, uint8_t num_vehicles)
3207{
3208 if (v->type == VEH_TRAIN) {
3209 Train *u = Train::From(v);
3210 /* Only include whole vehicles, so start with the first articulated part */
3211 u = u->GetFirstEnginePart();
3212
3213 /* Include num_vehicles vehicles, not counting articulated parts */
3214 for (; u != nullptr && num_vehicles > 0; num_vehicles--) {
3215 do {
3216 /* Include current vehicle in the selection. */
3217 include(set, u->index);
3218
3219 /* If the vehicle is multiheaded, add the other part too. */
3220 if (u->IsMultiheaded()) include(set, u->other_multiheaded_part->index);
3221
3222 u = u->Next();
3223 } while (u != nullptr && u->IsArticulatedPart());
3224 }
3225 }
3226}
3227
3232uint32_t Vehicle::GetDisplayMaxWeight() const
3233{
3234 uint32_t max_weight = 0;
3235
3236 for (const Vehicle *u = this; u != nullptr; u = u->Next()) {
3237 max_weight += u->GetMaxWeight();
3238 }
3239
3240 return max_weight;
3241}
3242
3247uint32_t Vehicle::GetDisplayMinPowerToWeight() const
3248{
3249 uint32_t max_weight = GetDisplayMaxWeight();
3250 if (max_weight == 0) return 0;
3251 return GetGroundVehicleCache()->cached_power * 10u / max_weight;
3252}
3253
3260 bool VehiclesHaveSameEngineList(const Vehicle *v1, const Vehicle *v2)
3261{
3262 while (true) {
3263 if (v1 == nullptr && v2 == nullptr) return true;
3264 if (v1 == nullptr || v2 == nullptr) return false;
3265 if (v1->GetEngine() != v2->GetEngine()) return false;
3266 v1 = v1->GetNextVehicle();
3267 v2 = v2->GetNextVehicle();
3268 }
3269}
3270
3277 bool VehiclesHaveSameOrderList(const Vehicle *v1, const Vehicle *v2)
3278{
3279 return std::ranges::equal(v1->Orders(), v2->Orders(), [](const Order &o1, const Order &o2) { return o1.Equals(o2); });
3280}
ai.hpp
Base functions for all AIs.
aircraft.h
Base for aircraft.
AircraftNextAirportPos_and_Order
void AircraftNextAirportPos_and_Order(Aircraft *v)
set the right pos when heading to other airports after takeoff
Definition aircraft_cmd.cpp:1460
GetTargetAirportIfValid
Station * GetTargetAirportIfValid(const Aircraft *v)
Returns aircraft's target station if v->target_airport is a valid station with airport.
Definition aircraft_cmd.cpp:2163
AIR_SHADOW
@ AIR_SHADOW
shadow of the aircraft
Definition aircraft.h:31
HandleAircraftEnterHangar
void HandleAircraftEnterHangar(Aircraft *v)
Handle Aircraft specific tasks when an Aircraft enters a hangar.
Definition aircraft_cmd.cpp:571
FLYING
@ FLYING
Vehicle is flying in the air.
Definition airport.h:77
GetCargoTypesOfArticulatedVehicle
CargoTypes GetCargoTypesOfArticulatedVehicle(const Vehicle *v, CargoType *cargo_type)
Get cargo mask of all cargoes carried by an articulated vehicle.
Definition articulated_vehicles.cpp:262
GetArticulatedRefitMasks
void GetArticulatedRefitMasks(EngineID engine, bool include_initial_cargo_type, CargoTypes *union_mask, CargoTypes *intersection_mask)
Merges the refit_masks of all articulated parts.
Definition articulated_vehicles.cpp:222
GetCargoTypesOfArticulatedParts
CargoTypes GetCargoTypesOfArticulatedParts(EngineID engine)
Get the cargo mask of the parts of a given engine.
Definition articulated_vehicles.cpp:166
articulated_vehicles.h
Functions related to articulated vehicles.
autoreplace_cmd.h
Command definitions related to autoreplace.
autoreplace_func.h
Functions related to autoreplacing.
EngineReplacementForCompany
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.
Definition autoreplace_func.h:39
EngineHasReplacementForCompany
bool EngineHasReplacementForCompany(const Company *c, EngineID engine, GroupID group)
Check if a company has a replacement set up for the given engine.
Definition autoreplace_func.h:51
InvalidateAutoreplaceWindow
void InvalidateAutoreplaceWindow(EngineID e, GroupID id_g)
Rebuild the left autoreplace list if an engine is removed or added.
Definition autoreplace_gui.cpp:54
autoreplace_gui.h
Functions related to the autoreplace GUIs.
backup_type.hpp
Class for backupping variables and making sure they are restored later.
VehicleFlag::PathfinderLost
@ PathfinderLost
Vehicle's pathfinder is lost.
VehicleFlag::StopLoading
@ StopLoading
Don't load anymore during the next load cycle.
VehicleFlag::LoadingFinished
@ LoadingFinished
Vehicle has finished loading.
VehicleFlag::CargoUnloading
@ CargoUnloading
Vehicle is unloading cargo.
SB
constexpr T SB(T &x, const uint8_t s, const uint8_t n, const U d)
Set n bits in x starting at bit s to d.
Definition bitmath_func.hpp:58
GB
static constexpr uint GB(const T x, const uint8_t s, const uint8_t n)
Fetch n bits from x, started at bit s.
Definition bitmath_func.hpp:32
SetBit
constexpr T SetBit(T &x, const uint8_t y)
Set a bit in a variable.
Definition bitmath_func.hpp:121
FindFirstBit
constexpr uint8_t FindFirstBit(T x)
Search the first set bit in a value.
Definition bitmath_func.hpp:189
HasBit
constexpr bool HasBit(const T x, const uint8_t y)
Checks if a bit in a value is set.
Definition bitmath_func.hpp:103
HasAtMostOneBit
constexpr bool HasAtMostOneBit(T value)
Test whether value has at most 1 bit set.
Definition bitmath_func.hpp:266
ToggleBit
constexpr T ToggleBit(T &x, const uint8_t y)
Toggles a bit in a variable.
Definition bitmath_func.hpp:157
ClrBit
constexpr T ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
Definition bitmath_func.hpp:139
bridge_map.h
Map accessor functions for bridges.
IsBridgeTile
bool IsBridgeTile(Tile t)
checks if there is a bridge on this tile
Definition bridge_map.h:35
IsBridgeAbove
bool IsBridgeAbove(Tile t)
checks if a bridge is set above the ground of this tile
Definition bridge_map.h:45
CargoType
uint8_t CargoType
Cargo slots to indicate a cargo type within a game.
Definition cargo_type.h:21
IsValidCargoType
bool IsValidCargoType(CargoType cargo)
Test whether cargo type is not INVALID_CARGO.
Definition cargo_type.h:104
CargoClass::Passengers
@ Passengers
Passengers.
IsCargoInClass
bool IsCargoInClass(CargoType cargo, CargoClasses cc)
Does cargo c have cargo class cc?
Definition cargotype.h:236
AI::NewEvent
static void NewEvent(CompanyID company, ScriptEvent *event)
Queue a new event for an AI.
Definition ai_core.cpp:235
BaseBitSet::Test
constexpr bool Test(Tvalue_type value) const
Test if the value-th bit is set.
Definition base_bitset_type.hpp:141
BaseBitSet::Reset
constexpr Timpl & Reset()
Reset all bits.
Definition base_bitset_type.hpp:83
BaseBitSet::Set
constexpr Timpl & Set()
Set all bits.
Definition base_bitset_type.hpp:40
BaseBitSet::Any
constexpr bool Any(const Timpl &other) const
Test if any of the given values are set.
Definition base_bitset_type.hpp:170
CargoList< VehicleCargoList, CargoPacketList >::MTA_LOAD
@ MTA_LOAD
Load the cargo from the station.
Definition cargopacket.h:291
CommandCost
Common return value for all commands.
Definition command_type.h:24
CommandCost::Succeeded
bool Succeeded() const
Did this command succeed?
Definition command_type.h:168
CommandCost::GetCost
Money GetCost() const
The costs as made up to this moment.
Definition command_type.h:118
CommandCost::Failed
bool Failed() const
Did this command fail?
Definition command_type.h:177
CommandCost::GetErrorMessage
StringID GetErrorMessage() const
Returns the error message of a command.
Definition command_type.h:148
EconomyTime::DAYS_IN_ECONOMY_MONTH
static constexpr int DAYS_IN_ECONOMY_MONTH
Days in an economy month, when in wallclock timekeeping mode.
Definition timer_game_economy.h:53
EncodedString
Container for an encoded string, created by GetEncodedString.
Definition strings_type.h:98
Engine
Definition engine_base.h:38
Engine::GetGRFID
uint32_t GetGRFID() const
Retrieve the GRF ID of the NewGRF the engine is tied to.
Definition engine.cpp:156
Engine::GetGRF
const GRFFile * GetGRF() const
Retrieve the NewGRF the engine is tied to.
Definition engine_base.h:166
Engine::IterateType
static Pool::IterateWrapperFiltered< Engine, EngineTypeFilter > IterateType(VehicleType vt, size_t from=0)
Returns an iterable ensemble of all valid engines of the given type.
Definition engine_base.h:197
Engine::grf_prop
CargoGRFFileProps grf_prop
Link to NewGRF.
Definition engine_base.h:71
Engine::company_avail
CompanyMask company_avail
Bit for each company whether the engine is available for that company.
Definition engine_base.h:40
Engine::type
VehicleType type
Vehicle type, ie VEH_ROAD, VEH_TRAIN, etc.
Definition engine_base.h:62
Engine::GetDefaultCargoType
CargoType GetDefaultCargoType() const
Determines the default cargo type of an engine.
Definition engine_base.h:95
Engine::reliability
uint16_t reliability
Current reliability of the engine.
Definition engine_base.h:49
EnumBitSet
Enum-as-bit-set wrapper.
Definition enum_type.hpp:177
FreeUnitIDGenerator::UseID
UnitID UseID(UnitID index)
Use a unit number.
Definition vehicle.cpp:1844
FreeUnitIDGenerator::ReleaseID
void ReleaseID(UnitID index)
Release a unit number.
Definition vehicle.cpp:1861
FreeUnitIDGenerator::NextID
UnitID NextID() const
Find first unused unit number.
Definition vehicle.cpp:1829
Gamelog::GRFBugReverse
bool GRFBugReverse(uint32_t grfid, uint16_t internal_id)
Logs GRF bug - rail vehicle has different length after reversing.
Definition gamelog.cpp:482
IntervalTimer
An interval timer will fire every interval, and will continue to fire until it is deleted.
Definition timer.h:76
LinkRefresher::Run
static void Run(Vehicle *v, bool allow_merge=true, bool is_full_loading=false)
Refresh all links the given vehicle will visit.
Definition refresh.cpp:26
OverflowSafeInt< int64_t >
PerformanceAccumulator::Reset
static void Reset(PerformanceElement elem)
Store the previous accumulator value and reset for a new cycle of accumulating measurements.
Definition framerate_gui.cpp:332
PerformanceMeasurer
RAII class for measuring simple elements of performance.
Definition framerate_type.h:91
Ticks::DAY_TICKS
static constexpr TimerGameTick::Ticks DAY_TICKS
1 day is 74 ticks; TimerGameCalendar::date_fract used to be uint16_t and incremented by 885.
Definition timer_game_tick.h:75
TimerGameCalendar::date
static Date date
Current date in days (day counter).
Definition timer_game_calendar.h:33
TimerGameCalendar::date_fract
static DateFract date_fract
Fractional part of the day.
Definition timer_game_calendar.h:34
TimerGameConst< struct Economy >::MAX_DATE
static constexpr TimerGame< struct Economy >::Date MAX_DATE
The date of the last day of the max year.
Definition timer_game_common.h:187
TimerGameConst< struct Calendar >::DAYS_IN_LEAP_YEAR
static constexpr int DAYS_IN_LEAP_YEAR
sometimes, you need one day more...
Definition timer_game_common.h:150
TimerGameEconomy::date
static Date date
Current date in days (day counter).
Definition timer_game_economy.h:38
TimerGameEconomy::UsingWallclockUnits
static bool UsingWallclockUnits(bool newgame=false)
Check if we are using wallclock units.
Definition timer_game_economy.cpp:98
TimerGameEconomy::date_fract
static DateFract date_fract
Fractional part of the day.
Definition timer_game_economy.h:39
TimerGameTick::TickCounter
uint64_t TickCounter
The type that the tick counter is stored in.
Definition timer_game_tick.h:25
TimerGameTick::counter
static TickCounter counter
Monotonic counter, in ticks, since start of game.
Definition timer_game_tick.h:60
TimerGameTick::Ticks
int32_t Ticks
The type to store ticks in.
Definition timer_game_tick.h:24
TimerGame< struct Calendar >::DateAtStartOfYear
static constexpr Date DateAtStartOfYear(Year year)
Calculate the date of the first day of a given year.
Definition timer_game_common.h:88
VehicleCargoList
CargoList that is used for vehicles.
Definition cargopacket.h:342
VehicleCargoList::ActionCount
uint ActionCount(MoveToAction action) const
Returns the amount of cargo designated for a given purpose.
Definition cargopacket.h:415
VehicleCargoList::Return
uint Return(uint max_move, StationCargoList *dest, StationID next_station, TileIndex current_tile)
Returns reserved cargo to the station and removes it from the cache.
Definition cargopacket.cpp:596
VehicleCargoList::KeepAll
void KeepAll()
Marks all cargo in the vehicle as to be kept.
Definition cargopacket.h:479
VehicleCargoList::AgeCargo
void AgeCargo()
Ages the all cargo in this list.
Definition cargopacket.cpp:386
VehicleCargoList::StoredCount
uint StoredCount() const
Returns sum of cargo on board the vehicle (ie not only reserved).
Definition cargopacket.h:425
VehiclesNearTileXY::Iterator::SkipEmptyBuckets
void SkipEmptyBuckets()
Advance the internal state until we reach a non-empty bucket, or the end.
Definition vehicle.cpp:472
VehiclesNearTileXY::Iterator::Iterator
Iterator(int32_t x, int32_t y, uint max_dist)
Iterator constructor.
Definition vehicle.cpp:432
VehiclesNearTileXY::Iterator::Increment
void Increment()
Advance the internal state to the next potential vehicle.
Definition vehicle.cpp:462
VehiclesNearTileXY::Iterator::SkipFalseMatches
void SkipFalseMatches()
Advance the internal state until it reaches a vehicle within the search area.
Definition vehicle.cpp:490
VehiclesOnTile::Iterator::Iterator
Iterator(TileIndex tile)
Iterator constructor.
Definition vehicle.cpp:499
VehiclesOnTile::Iterator::Increment
void Increment()
Advance the internal state to the next potential vehicle.
Definition vehicle.cpp:509
VehiclesOnTile::Iterator::SkipFalseMatches
void SkipFalseMatches()
Advance the internal state until it reaches a vehicle on the correct tile or the end.
Definition vehicle.cpp:517
VehiclesOnTile
Iterate over all vehicles on a tile.
Definition vehicle_func.h:53
command_func.h
Functions related to commands.
CMD_ERROR
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition command_func.h:28
DoCommandFlag::Execute
@ Execute
execute the given command
CheckOwnership
CommandCost CheckOwnership(Owner owner, TileIndex tile)
Check whether the current owner owns something.
Definition company_cmd.cpp:381
SubtractMoneyFromCompany
void SubtractMoneyFromCompany(const CommandCost &cost)
Subtract money from the _current_company, if the company is valid.
Definition company_cmd.cpp:313
GetAvailableMoney
Money GetAvailableMoney(CompanyID company)
Get the amount of money that a company has available, or INT64_MAX if there is no such valid company.
Definition company_cmd.cpp:238
_local_company
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition company_cmd.cpp:55
_current_company
CompanyID _current_company
Company currently doing an action.
Definition company_cmd.cpp:56
company_func.h
Functions related to companies.
IsLocalCompany
bool IsLocalCompany()
Is the current company the local company?
Definition company_func.h:47
container_func.hpp
Some simple functions to help with accessing containers.
include
bool include(Container &container, typename Container::const_reference &item)
Helper function to append an item to a container if it is not already contained.
Definition container_func.hpp:24
Debug
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
depot_func.h
Functions related to depots.
DeleteDepotHighlightOfVehicle
void DeleteDepotHighlightOfVehicle(const Vehicle *v)
Removes the highlight of a vehicle in a depot window.
Definition depot_gui.cpp:1200
depot_map.h
Map related accessors for depots.
IsDepotTile
bool IsDepotTile(Tile tile)
Is the given tile a tile with a depot on it?
Definition depot_map.h:42
DirDifference
DirDiff DirDifference(Direction d0, Direction d1)
Calculate the difference between two directions.
Definition direction_func.h:68
ReverseDir
Direction ReverseDir(Direction d)
Return the reverse of a direction.
Definition direction_func.h:54
ChangeDir
Direction ChangeDir(Direction d, DirDiff delta)
Change a direction by a given difference.
Definition direction_func.h:104
DirDiff
DirDiff
Enumeration for the difference between two directions.
Definition direction_type.h:63
DIRDIFF_45LEFT
@ DIRDIFF_45LEFT
Angle of 45 degrees left.
Definition direction_type.h:69
DIRDIFF_REVERSE
@ DIRDIFF_REVERSE
One direction is the opposite of the other one.
Definition direction_type.h:67
DIRDIFF_45RIGHT
@ DIRDIFF_45RIGHT
Angle of 45 degrees right.
Definition direction_type.h:65
DIRDIFF_SAME
@ DIRDIFF_SAME
Both directions faces to the same direction.
Definition direction_type.h:64
DIRDIFF_90RIGHT
@ DIRDIFF_90RIGHT
Angle of 90 degrees right.
Definition direction_type.h:66
Direction
Direction
Defines the 8 directions on the map.
Definition direction_type.h:24
DIR_SW
@ DIR_SW
Southwest.
Definition direction_type.h:31
DIR_NW
@ DIR_NW
Northwest.
Definition direction_type.h:33
DIR_N
@ DIR_N
North.
Definition direction_type.h:26
DIR_SE
@ DIR_SE
Southeast.
Definition direction_type.h:29
DIR_S
@ DIR_S
South.
Definition direction_type.h:30
DIR_NE
@ DIR_NE
Northeast.
Definition direction_type.h:27
DIR_W
@ DIR_W
West.
Definition direction_type.h:32
DIR_E
@ DIR_E
East.
Definition direction_type.h:28
INVALID_DIAGDIR
@ INVALID_DIAGDIR
Flag for an invalid DiagDirection.
Definition direction_type.h:85
LoadUnloadStation
void LoadUnloadStation(Station *st)
Load/unload the vehicles in this station according to the order they entered.
Definition economy.cpp:1929
PrepareUnload
void PrepareUnload(Vehicle *front_v)
Prepare the vehicle to be unloaded.
Definition economy.cpp:1255
economy_base.h
Base classes related to the economy.
EXPENSES_NEW_VEHICLES
@ EXPENSES_NEW_VEHICLES
New vehicles.
Definition economy_type.h:180
CreateEffectVehicleRel
EffectVehicle * CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVehicleType type)
Create an effect vehicle above a particular vehicle.
Definition effectvehicle.cpp:610
effectvehicle_base.h
Base class for all effect vehicles.
effectvehicle_func.h
Functions related to effect vehicles.
EffectVehicleType
EffectVehicleType
Effect vehicle types.
Definition effectvehicle_func.h:16
EV_BREAKDOWN_SMOKE
@ EV_BREAKDOWN_SMOKE
Smoke of broken vehicles except aircraft.
Definition effectvehicle_func.h:23
EV_STEAM_SMOKE
@ EV_STEAM_SMOKE
Smoke of steam engines.
Definition effectvehicle_func.h:18
EV_DIESEL_SMOKE
@ EV_DIESEL_SMOKE
Smoke of diesel engines.
Definition effectvehicle_func.h:19
EV_BREAKDOWN_SMOKE_AIRCRAFT
@ EV_BREAKDOWN_SMOKE_AIRCRAFT
Smoke of broken aircraft.
Definition effectvehicle_func.h:27
EV_ELECTRIC_SPARK
@ EV_ELECTRIC_SPARK
Sparks of electric engines.
Definition effectvehicle_func.h:20
AIR_CTOL
@ AIR_CTOL
Conventional Take Off and Landing, i.e. planes.
Definition engine_type.h:127
EngineMiscFlag::RoadIsTram
@ RoadIsTram
Road vehicle is a tram/light rail vehicle.
EngineMiscFlag::NoBreakdownSmoke
@ NoBreakdownSmoke
Do not show black smoke during a breakdown.
EngineMiscFlag::Uses2CC
@ Uses2CC
Vehicle uses two company colours.
EngineMiscFlag::RailIsMU
@ RailIsMU
Rail vehicle is a multiple-unit (DMU/EMU)
VE_TYPE_DEFAULT
@ VE_TYPE_DEFAULT
Use default from engine class.
Definition engine_type.h:61
VE_TYPE_COUNT
@ VE_TYPE_COUNT
Number of bits used for the effect type.
Definition engine_type.h:60
VE_OFFSET_CENTRE
@ VE_OFFSET_CENTRE
Value of offset corresponding to a position above the centre of the vehicle.
Definition engine_type.h:57
VE_TYPE_ELECTRIC
@ VE_TYPE_ELECTRIC
Electric sparks.
Definition engine_type.h:64
VE_TYPE_START
@ VE_TYPE_START
First bit used for the type of effect.
Definition engine_type.h:59
VE_OFFSET_COUNT
@ VE_OFFSET_COUNT
Number of bits used for the offset.
Definition engine_type.h:56
VE_ADVANCED_EFFECT
@ VE_ADVANCED_EFFECT
Flag for advanced effects.
Definition engine_type.h:67
VE_DISABLE_EFFECT
@ VE_DISABLE_EFFECT
Flag to disable visual effect.
Definition engine_type.h:66
VE_TYPE_STEAM
@ VE_TYPE_STEAM
Steam plumes.
Definition engine_type.h:62
VE_TYPE_DIESEL
@ VE_TYPE_DIESEL
Diesel fumes.
Definition engine_type.h:63
VE_DEFAULT
@ VE_DEFAULT
Default value to indicate that visual effect should be based on engine class.
Definition engine_type.h:70
VE_OFFSET_START
@ VE_OFFSET_START
First bit that contains the offset (0 = front, 8 = centre, 15 = rear)
Definition engine_type.h:55
VE_DISABLE_WAGON_POWER
@ VE_DISABLE_WAGON_POWER
Flag to disable wagon power.
Definition engine_type.h:68
EC_DIESEL
@ EC_DIESEL
Diesel rail engine.
Definition engine_type.h:40
EC_STEAM
@ EC_STEAM
Steam rail engine.
Definition engine_type.h:39
EC_MAGLEV
@ EC_MAGLEV
Maglev engine.
Definition engine_type.h:43
EC_ELECTRIC
@ EC_ELECTRIC
Electric rail engine.
Definition engine_type.h:41
EC_MONORAIL
@ EC_MONORAIL
Mono rail engine.
Definition engine_type.h:42
RAILVEH_WAGON
@ RAILVEH_WAGON
simple wagon, not motorized
Definition engine_type.h:34
error.h
Functions related to errors.
WL_CRITICAL
@ WL_CRITICAL
Critical errors, the MessageBox is shown in all cases.
Definition error.h:27
ShowErrorMessage
void ShowErrorMessage(EncodedString &&summary_msg, int x, int y, CommandCost &cc)
Display an error message in a window.
Definition error_gui.cpp:290
framerate_type.h
Types for recording game performance data.
PFE_GL_SHIPS
@ PFE_GL_SHIPS
Time spent processing ships.
Definition framerate_type.h:52
PFE_GL_AIRCRAFT
@ PFE_GL_AIRCRAFT
Time spent processing aircraft.
Definition framerate_type.h:53
PFE_GL_ECONOMY
@ PFE_GL_ECONOMY
Time spent processing cargo movement.
Definition framerate_type.h:49
PFE_GL_ROADVEHS
@ PFE_GL_ROADVEHS
Time spend processing road vehicles.
Definition framerate_type.h:51
PFE_GL_TRAINS
@ PFE_GL_TRAINS
Time spent processing trains.
Definition framerate_type.h:50
_gamelog
Gamelog _gamelog
Gamelog instance.
Definition gamelog.cpp:31
gamelog.h
Functions to be called to log fundamental changes to the game.
DrawSprite
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
Draw a sprite, not in a viewport.
Definition gfx.cpp:1031
SpriteType::Normal
@ Normal
The most basic (normal) sprite.
PaletteID
uint32_t PaletteID
The number of the palette.
Definition gfx_type.h:18
GVF_SUPPRESS_IMPLICIT_ORDERS
@ GVF_SUPPRESS_IMPLICIT_ORDERS
Disable insertion and removal of automatic orders until the vehicle completes the real order.
Definition ground_vehicle.hpp:57
MarkAllViewportsDirty
bool MarkAllViewportsDirty(int left, int top, int right, int bottom)
Mark all viewports that display an area as dirty (in need of repaint).
Definition viewport.cpp:2094
Station::MarkTilesDirty
void MarkTilesDirty(bool cargo_change) const
Marks the tiles of the station as dirty.
Definition station.cpp:247
MarkTileDirtyByTile
void MarkTileDirtyByTile(TileIndex tile, int bridge_level_offset, int tile_height_override)
Mark a tile given by its index dirty for repaint.
Definition viewport.cpp:2128
Vehicle::MarkDirty
virtual void MarkDirty()
Marks the vehicles to be redrawn and updates cached variables.
Definition vehicle_base.h:362
DeleteGroupHighlightOfVehicle
void DeleteGroupHighlightOfVehicle(const Vehicle *v)
Removes the highlight of a vehicle in a group window.
Definition group_gui.cpp:1307
group_gui.h
Functions/definitions that have something to do with groups.
DEFAULT_GROUP
static constexpr GroupID DEFAULT_GROUP
Ungrouped vehicles are in this group.
Definition group_type.h:18
_tile_type_procs
const TileTypeProcs *const _tile_type_procs[16]
Tile callback functions for each type of tile.
Definition landscape.cpp:68
RemapCoords
Point RemapCoords(int x, int y, int z)
Map 3D world or tile coordinate to equivalent 2D coordinate as used in the viewports and smallmap.
Definition landscape.h:81
BorderFlag::Random
@ Random
Randomise borders.
linkgraph.h
Declaration of link graph classes used for cargo distribution.
LIT_ALL
static const uint8_t LIT_ALL
Show the liveries of all companies.
Definition livery.h:19
LiveryScheme
LiveryScheme
List of different livery schemes.
Definition livery.h:22
LIT_COMPANY
static const uint8_t LIT_COMPANY
Show the liveries of your own company.
Definition livery.h:18
TileVirtXY
static TileIndex TileVirtXY(uint x, uint y)
Get a tile from the virtual XY-coordinate.
Definition map_func.h:416
TileY
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition map_func.h:437
TileX
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:427
IsInsideMM
constexpr bool IsInsideMM(const size_t x, const size_t min, const size_t max) noexcept
Checks if a value is in an interval.
Definition math_func.hpp:267
abs
constexpr T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition math_func.hpp:23
CeilDiv
constexpr uint CeilDiv(uint a, uint b)
Computes ceil(a / b) for non-negative a and b.
Definition math_func.hpp:310
Clamp
constexpr T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition math_func.hpp:79
misc_cmd.h
Miscellaneous command definitions.
HideFillingPercent
void HideFillingPercent(TextEffectID *te_id)
Hide vehicle loading indicators.
Definition misc_gui.cpp:586
ShowCostOrIncomeAnimation
void ShowCostOrIncomeAnimation(int x, int y, int z, Money cost)
Display animated income or costs on the map.
Definition misc_gui.cpp:513
_networking
bool _networking
are we in networking mode?
Definition network.cpp:66
network.h
Basic functions/variables used all over the place.
VehicleCallbackMask::VisualEffect
@ VisualEffect
Visual effects and wagon power (trains, road vehicles and ships)
VehicleCallbackMask::ColourRemap
@ ColourRemap
Change colour mapping of vehicle.
CBID_VEHICLE_SPAWN_VISUAL_EFFECT
@ CBID_VEHICLE_SPAWN_VISUAL_EFFECT
Called to spawn visual effects for vehicles.
Definition newgrf_callbacks.h:283
CBID_VEHICLE_COLOUR_MAPPING
@ CBID_VEHICLE_COLOUR_MAPPING
Called to determine if a specific colour map should be used for a vehicle instead of the default live...
Definition newgrf_callbacks.h:128
CBID_VEHICLE_32DAY_CALLBACK
@ CBID_VEHICLE_32DAY_CALLBACK
Called for every vehicle every 32 days (not all on same date though).
Definition newgrf_callbacks.h:146
CBID_VEHICLE_VISUAL_EFFECT
@ CBID_VEHICLE_VISUAL_EFFECT
Visual effects and wagon power.
Definition newgrf_callbacks.h:32
CALLBACK_FAILED
static const uint CALLBACK_FAILED
Different values for Callback result evaluations.
Definition newgrf_callbacks.h:439
ErrorUnknownCallbackResult
void ErrorUnknownCallbackResult(uint32_t grfid, uint16_t cbid, uint16_t cb_res)
Record that a NewGRF returned an unknown/invalid callback result.
Definition newgrf_commons.cpp:517
GetGRFConfig
GRFConfig * GetGRFConfig(uint32_t grfid, uint32_t mask)
Retrieve a NewGRF from the current config by its grfid.
Definition newgrf_config.cpp:622
GRFBug
GRFBug
Encountered GRF bugs.
Definition newgrf_config.h:42
GRFBug::VehPoweredWagon
@ VehPoweredWagon
Powered wagon changed poweredness state when not inside a depot.
GRFBug::VehLength
@ VehLength
Length of rail vehicle changes when not inside a depot.
newgrf_debug.h
Functions/types related to NewGRF debugging.
GetGrfSpecFeature
GrfSpecFeature GetGrfSpecFeature(TileIndex tile)
Get the GrfSpecFeature associated with the tile.
Definition newgrf_debug_gui.cpp:760
DeleteNewGRFInspectWindow
void DeleteNewGRFInspectWindow(GrfSpecFeature feature, uint index)
Delete inspect window for a given feature and index.
Definition newgrf_debug_gui.cpp:726
UsesWagonOverride
bool UsesWagonOverride(const Vehicle *v)
Check if a wagon is currently using a wagon override.
Definition newgrf_engine.cpp:1182
GetVehicleCallback
uint16_t GetVehicleCallback(CallbackID callback, uint32_t param1, uint32_t param2, EngineID engine, const Vehicle *v, std::span< int32_t > regs100)
Evaluate a newgrf callback for vehicles.
Definition newgrf_engine.cpp:1198
newgrf_roadstop.h
NewGRF definitions and structures for road stops.
PlayVehicleSound
bool PlayVehicleSound(const Vehicle *v, VehicleSoundEvent event, bool force)
Checks whether a NewGRF wants to play a different vehicle sound effect.
Definition newgrf_sound.cpp:143
newgrf_sound.h
Functions related to NewGRF provided sounds.
VSE_VISUAL_EFFECT
@ VSE_VISUAL_EFFECT
Vehicle visual effect (steam, diesel smoke or electric spark) is shown.
Definition newgrf_sound.h:24
VSE_RUNNING
@ VSE_RUNNING
Vehicle running normally.
Definition newgrf_sound.h:22
VSE_STOPPED_16
@ VSE_STOPPED_16
Every 16 ticks while the vehicle is stopped (speed == 0).
Definition newgrf_sound.h:26
VSE_RUNNING_16
@ VSE_RUNNING_16
Every 16 ticks while the vehicle is running (speed > 0).
Definition newgrf_sound.h:25
VSE_BREAKDOWN
@ VSE_BREAKDOWN
Vehicle breaking down.
Definition newgrf_sound.h:21
TriggerStationRandomisation
void TriggerStationRandomisation(BaseStation *st, TileIndex trigger_tile, StationRandomTrigger trigger, CargoType cargo_type)
Trigger station randomisation.
Definition newgrf_station.cpp:950
newgrf_station.h
Header file for NewGRF stations.
news_func.h
Functions related to news.
AddVehicleAdviceNewsItem
void AddVehicleAdviceNewsItem(AdviceType advice_type, EncodedString &&headline, VehicleID vehicle)
Adds a vehicle-advice news item.
Definition news_func.h:40
DeleteVehicleNews
void DeleteVehicleNews(VehicleID vid, AdviceType advice_type=AdviceType::Invalid)
Delete news with a given advice type about a vehicle.
Definition news_gui.cpp:1015
AdviceType::VehicleLost
@ VehicleLost
The vehicle has become lost.
AdviceType::VehicleWaiting
@ VehicleWaiting
The vehicle is waiting in the depot.
AdviceType::AutorenewFailed
@ AutorenewFailed
Autorenew or autoreplace failed.
AdviceType::VehicleOld
@ VehicleOld
The vehicle is starting to get old.
AdviceType::VehicleUnprofitable
@ VehicleUnprofitable
The vehicle is costing you money.
AdviceType::RefitFailed
@ RefitFailed
The refit order failed to execute.
PauseMode::Error
@ Error
A game paused because a (critical) error.
PauseMode::Normal
@ Normal
A game normally paused.
order_backup.h
Functions related to order backups.
InsertOrder
void InsertOrder(Vehicle *v, Order &&new_o, VehicleOrderID sel_ord)
Insert a new order but skip the validation.
Definition order_cmd.cpp:846
DeleteOrder
void DeleteOrder(Vehicle *v, VehicleOrderID sel_ord)
Delete an order but skip the parameter validation.
Definition order_cmd.cpp:971
InvalidateVehicleOrder
void InvalidateVehicleOrder(const Vehicle *v, int data)
Updates the widgets of a vehicle which contains the order-data.
Definition order_cmd.cpp:213
DeleteVehicleOrders
void DeleteVehicleOrders(Vehicle *v, bool keep_orderlist, bool reset_order_indices)
Delete all orders from a vehicle.
Definition order_cmd.cpp:1830
OrderUnloadType::NoUnload
@ NoUnload
Totally no unloading will be done.
OrderNonStopFlag::NoDestination
@ NoDestination
The vehicle will stop at any station it passes except the destination, aka via.
OrderNonStopFlag::NoIntermediate
@ NoIntermediate
The vehicle will not stop at any stations it passes except the destination, aka non-stop.
VehicleOrderID
uint8_t VehicleOrderID
The index of an order within its current vehicle (not pool related)
Definition order_type.h:18
OrderLoadType::NoLoad
@ NoLoad
Do not load anything.
MAX_VEH_ORDER_ID
static const VehicleOrderID MAX_VEH_ORDER_ID
Last valid VehicleOrderID.
Definition order_type.h:41
OrderDepotActionFlag::Halt
@ Halt
Service the vehicle and then halt it.
OrderDepotActionFlag::NearestDepot
@ NearestDepot
Send the vehicle to the nearest depot.
OrderDepotActionFlag::Unbunch
@ Unbunch
Service the vehicle and then unbunch it.
OrderDepotTypeFlag::PartOfOrders
@ PartOfOrders
This depot order is because of a regular order.
OrderDepotTypeFlag::Service
@ Service
This depot order is because of the servicing limit.
INVALID_VEH_ORDER_ID
static const VehicleOrderID INVALID_VEH_ORDER_ID
Invalid vehicle order index (sentinel)
Definition order_type.h:39
IMPLICIT_ORDER_ONLY_CAP
static const uint IMPLICIT_ORDER_ONLY_CAP
Maximum number of orders in implicit-only lists before we start searching harder for duplicates.
Definition order_type.h:47
pool_func.hpp
Some methods of Pool are placed here in order to reduce compilation time and binary size.
INSTANTIATE_POOL_METHODS
#define INSTANTIATE_POOL_METHODS(name)
Force instantiation of pool methods so we don't get linker errors.
Definition pool_func.hpp:210
HasAnyRailTypesAvail
bool HasAnyRailTypesAvail(const CompanyID company)
Test if any buildable railtype is available for a company.
Definition rail.cpp:78
GetTileRailType
RailType GetTileRailType(Tile tile)
Return the rail type of tile, or INVALID_RAILTYPE if this is no rail tile.
Definition rail.cpp:37
HasPowerOnRail
bool HasPowerOnRail(RailType enginetype, RailType tiletype)
Checks if an engine of the given RailType got power on a tile with a given RailType.
Definition rail.h:376
SetDepotReservation
void SetDepotReservation(Tile t, bool b)
Set the reservation state of the depot.
Definition rail_map.h:269
random_func.hpp
Pseudo random number generator.
RandomRange
uint32_t RandomRange(uint32_t limit, const std::source_location location=std::source_location::current())
Pick a random number between 0 and limit - 1, inclusive.
Definition random_func.hpp:88
Chance16I
bool Chance16I(const uint32_t a, const uint32_t b, const uint32_t r)
Checks if a given randomize-number is below a given probability.
Definition random_func.hpp:118
Chance16
bool Chance16(const uint32_t a, const uint32_t b, const std::source_location location=std::source_location::current())
Flips a coin with given probability.
Definition random_func.hpp:134
refresh.h
Definition of link refreshing utility.
HasAnyRoadTypesAvail
bool HasAnyRoadTypesAvail(CompanyID company, RoadTramType rtt)
Test if any buildable RoadType is available for a company.
Definition road.cpp:152
HasTileAnyRoadType
bool HasTileAnyRoadType(Tile t, RoadTypes rts)
Check if a tile has one of the specified road types.
Definition road_map.h:206
RoadTramType
RoadTramType
The different types of road type.
Definition road_type.h:37
roadstop_base.h
Base class for roadstops.
roadveh.h
Road vehicle states.
RVSB_IN_DT_ROAD_STOP
@ RVSB_IN_DT_ROAD_STOP
The vehicle is in a drive-through road stop.
Definition roadveh.h:51
safeguards.h
A number of safeguards to prevent using unsafe methods.
_settings_game
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition settings.cpp:61
_settings_client
ClientSettings _settings_client
The current settings for this game.
Definition settings.cpp:60
ship.h
Base for ships.
UpdateSignalsOnSegment
SigSegState UpdateSignalsOnSegment(TileIndex tile, DiagDirection side, Owner owner)
Update signals, starting at one side of a tile Will check tile next to this at opposite side too.
Definition signal.cpp:647
sound_func.h
Functions related to sound.
SND_3A_BREAKDOWN_TRAIN_SHIP_TOYLAND
@ SND_3A_BREAKDOWN_TRAIN_SHIP_TOYLAND
58 == 0x3A Breakdown: train or ship (toyland)
Definition sound_type.h:105
SND_10_BREAKDOWN_TRAIN_SHIP
@ SND_10_BREAKDOWN_TRAIN_SHIP
14 == 0x0E Breakdown: train or ship (non-toyland)
Definition sound_type.h:61
SND_0F_BREAKDOWN_ROADVEHICLE
@ SND_0F_BREAKDOWN_ROADVEHICLE
13 == 0x0D Breakdown: road vehicle (non-toyland)
Definition sound_type.h:60
SND_35_BREAKDOWN_ROADVEHICLE_TOYLAND
@ SND_35_BREAKDOWN_ROADVEHICLE_TOYLAND
53 == 0x35 Breakdown: road vehicle (toyland)
Definition sound_type.h:100
spritecache.h
Functions to cache sprites in memory.
PALETTE_RECOLOUR_START
static const PaletteID PALETTE_RECOLOUR_START
First recolour sprite for company colours.
Definition sprites.h:1588
PALETTE_CRASH
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition sprites.h:1619
station_base.h
Base classes/functions for stations.
IncreaseStats
void IncreaseStats(Station *st, CargoType cargo, StationID next_station_id, uint capacity, uint usage, uint32_t time, EdgeUpdateModes modes)
Increase capacity for a link stat given by station cargo and next hop.
Definition station_cmd.cpp:4248
IsStationRoadStopTile
bool IsStationRoadStopTile(Tile t)
Is tile t a road stop station?
Definition station_map.h:234
IsBayRoadStopTile
bool IsBayRoadStopTile(Tile t)
Is tile t a bay (non-drive through) road stop station?
Definition station_map.h:266
IsRailStationTile
bool IsRailStationTile(Tile t)
Is this tile a station tile and a rail station?
Definition station_map.h:102
GetStationIndex
StationID GetStationIndex(Tile t)
Get StationID from a tile.
Definition station_map.h:28
GetRoadStopType
RoadStopType GetRoadStopType(Tile t)
Get the road stop type of this tile.
Definition station_map.h:56
RoadStopType::Bus
@ Bus
A standard stop for buses.
RoadStopType::Truck
@ Truck
A standard stop for trucks.
StationFacility::Dock
@ Dock
Station with a dock.
StationFacility::TruckStop
@ TruckStop
Station with truck stops.
StationFacility::Train
@ Train
Station with train station.
StationFacility::Airport
@ Airport
Station with an airport.
StationFacility::BusStop
@ BusStop
Station with bus stops.
StationRandomTrigger::VehicleDeparts
@ VehicleDeparts
Trigger platform when train leaves.
StationAnimationTrigger::VehicleDeparts
@ VehicleDeparts
Trigger platform when train leaves.
stdafx.h
Definition of base types and functions in a cross-platform compatible way.
StrMakeValid
static void StrMakeValid(Builder &builder, StringConsumer &consumer, StringValidationSettings settings)
Copies the valid (UTF-8) characters from consumer to the builder.
Definition string.cpp:119
GetEncodedString
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:90
GetString
std::string GetString(StringID string)
Resolve the given StringID into a std::string with formatting but no parameters.
Definition strings.cpp:424
strings_func.h
Functions related to OTTD's strings.
StringID
uint32_t StringID
Numeric value that represents a string, independent of the selected language.
Definition strings_type.h:19
INVALID_STRING_ID
static const StringID INVALID_STRING_ID
Constant representing an invalid string (16bit in case it is used in savegames)
Definition strings_type.h:20
AircraftVehicleInfo
Information about a aircraft vehicle.
Definition engine_type.h:132
AircraftVehicleInfo::subtype
uint8_t subtype
Type of aircraft.
Definition engine_type.h:136
Aircraft
Aircraft, helicopters, rotors and their shadows belong to this class.
Definition aircraft.h:72
Aircraft::pos
uint8_t pos
Next desired position of the aircraft.
Definition aircraft.h:74
Aircraft::state
uint8_t state
State of the airport.
Definition aircraft.h:77
Aircraft::IsNormalAircraft
bool IsNormalAircraft() const
Check if the aircraft type is a normal flying device; eg not a rotor or a shadow.
Definition aircraft.h:121
Aircraft::previous_pos
uint8_t previous_pos
Previous desired position of the aircraft.
Definition aircraft.h:75
Aircraft::targetairport
StationID targetairport
Airport to go to next.
Definition aircraft.h:76
AirportFTAClass::Flag::Airplanes
@ Airplanes
Can planes land on this airport type?
AirportFTAClass::Flag::Helicopters
@ Helicopters
Can helicopters land on this airport type?
AirportFTAClass::layout
std::vector< AirportFTA > layout
state machine for airport
Definition airport.h:191
AirportFTAClass::flags
Flags flags
Flags for this airport type.
Definition airport.h:194
Airport::blocks
AirportBlocks blocks
stores which blocks on the airport are taken. was 16 bit earlier on, then 32
Definition station_base.h:354
Airport::GetFTA
const AirportFTAClass * GetFTA() const
Get the finite-state machine for this airport or the finite-state machine for the dummy airport in ca...
Definition station_base.h:378
Backup
Class to backup a specific variable and restore it later.
Definition backup_type.hpp:21
Backup::Restore
void Restore()
Restore the variable.
Definition backup_type.hpp:110
BaseConsist::depot_unbunching_next_departure
TimerGameTick::TickCounter depot_unbunching_next_departure
When the vehicle will next try to leave its unbunching depot.
Definition base_consist.h:42
BaseConsist::cur_real_order_index
VehicleOrderID cur_real_order_index
The index to the current real (non-implicit) order.
Definition base_consist.h:47
BaseConsist::round_trip_time
TimerGameTick::Ticks round_trip_time
How many ticks for a single circumnavigation of the orders.
Definition base_consist.h:43
BaseConsist::vehicle_flags
VehicleFlags vehicle_flags
Used for gradual loading and other miscellaneous things (.
Definition base_consist.h:50
BaseConsist::depot_unbunching_last_departure
TimerGameTick::TickCounter depot_unbunching_last_departure
When the vehicle last left its unbunching depot.
Definition base_consist.h:41
BaseConsist::cur_implicit_order_index
VehicleOrderID cur_implicit_order_index
The index to the current implicit order.
Definition base_consist.h:48
BaseConsist::ResetDepotUnbunching
void ResetDepotUnbunching()
Resets all the data used for depot unbunching.
Definition base_consist.cpp:49
BaseStation::facilities
StationFacilities facilities
The facilities that this station has.
Definition base_station_base.h:69
BaseVehicle::type
VehicleType type
Type of vehicle.
Definition vehicle_type.h:51
CargoSpec::Get
static CargoSpec * Get(size_t index)
Retrieve cargo details for the given cargo type.
Definition cargotype.h:137
ClientSettings::gui
GUISettings gui
settings related to the GUI
Definition settings_type.h:650
ClosestDepot
Structure to return information about the closest depot location, and whether it could be found.
Definition vehicle_base.h:192
ClosestDepot::destination
DestinationID destination
The DestinationID as used for orders.
Definition vehicle_base.h:194
CommandHelper
Definition command_func.h:83
CompanyProperties::settings
CompanySettings settings
settings specific for each company
Definition company_base.h:124
CompanySettings::engine_renew_money
uint32_t engine_renew_money
minimum amount of money before autorenew is used
Definition settings_type.h:613
CompanySettings::engine_renew_months
int16_t engine_renew_months
months before/after the maximum vehicle age a vehicle should be renewed
Definition settings_type.h:612
CompanySettings::engine_renew
bool engine_renew
is autorenew enabled
Definition settings_type.h:611
Company
Definition company_base.h:127
Company::group_all
std::array< GroupStatistics, VEH_COMPANY_END > group_all
NOSAVE: Statistics for the ALL_GROUP group.
Definition company_base.h:138
Coord2D< int >
Coord2D::y
T y
Y coordinate.
Definition geometry_type.hpp:35
Coord2D::x
T x
X coordinate.
Definition geometry_type.hpp:34
DifficultySettings::vehicle_breakdowns
uint8_t vehicle_breakdowns
likelihood of vehicles breaking down
Definition settings_type.h:133
DrawPixelInfo
Data about how and where to blit pixels.
Definition gfx_type.h:157
EffectVehicle
A special vehicle is one of the following:
Definition effectvehicle_base.h:24
EffectVehicle::GetTransparencyOption
TransparencyOption GetTransparencyOption() const
Determines the transparency option affecting the effect.
Definition effectvehicle.cpp:629
EffectVehicle::animation_state
uint16_t animation_state
State primarily used to change the graphics/behaviour.
Definition effectvehicle_base.h:25
EngineInfo::misc_flags
EngineMiscFlags misc_flags
Miscellaneous flags.
Definition engine_type.h:209
EngineInfo::callback_mask
VehicleCallbackMasks callback_mask
Bitmask of vehicle callbacks that have to be called.
Definition engine_type.h:210
GRFConfig
Information about GRF, used in the game and (part of it) in savegames.
Definition newgrf_config.h:158
GRFConfig::grf_bugs
GRFBugs grf_bugs
NOSAVE: bugs in this GRF in this run,.
Definition newgrf_config.h:180
GRFConfig::GetName
std::string GetName() const
Get the name of this grf.
Definition newgrf_config.cpp:85
GRFFilePropsBase::local_id
uint16_t local_id
id defined by the grf file for this entity
Definition newgrf_commons.h:316
GRFFilePropsBase::grfid
uint32_t grfid
grfid that introduced this entity.
Definition newgrf_commons.h:317
GRFFile
Dynamic data of a loaded NewGRF.
Definition newgrf.h:114
GUISettings::lost_vehicle_warn
bool lost_vehicle_warn
if a vehicle can't find its destination, show a warning
Definition settings_type.h:165
GUISettings::vehicle_income_warn
bool vehicle_income_warn
if a vehicle isn't generating income, show a warning
Definition settings_type.h:167
GUISettings::show_track_reservation
bool show_track_reservation
highlight reserved tracks.
Definition settings_type.h:220
GUISettings::liveries
uint8_t liveries
options for displaying company liveries, 0=none, 1=self, 2=all
Definition settings_type.h:182
GUISettings::old_vehicle_warn
bool old_vehicle_warn
if a vehicle is getting old, show a warning
Definition settings_type.h:168
GameCreationSettings::landscape
LandscapeType landscape
the landscape we're currently in
Definition settings_type.h:395
GameSettings::difficulty
DifficultySettings difficulty
settings related to the difficulty
Definition settings_type.h:633
GameSettings::game_creation
GameCreationSettings game_creation
settings used during the creation of a game (map)
Definition settings_type.h:634
GameSettings::vehicle
VehicleSettings vehicle
options for vehicles
Definition settings_type.h:641
GameSettings::order
OrderSettings order
settings related to orders
Definition settings_type.h:640
GetNewVehiclePosResult
Position information of a vehicle after it moved.
Definition vehicle_func.h:214
GetNewVehiclePosResult::new_tile
TileIndex new_tile
Tile of the vehicle after moving.
Definition vehicle_func.h:217
GetNewVehiclePosResult::y
int y
x and y position of the vehicle after moving
Definition vehicle_func.h:215
GetNewVehiclePosResult::old_tile
TileIndex old_tile
Current tile of the vehicle.
Definition vehicle_func.h:216
GroundVehicleCache
Cached, frequently calculated values.
Definition ground_vehicle.hpp:30
GroundVehicleCache::first_engine
EngineID first_engine
Cached EngineID of the front vehicle. EngineID::Invalid() for the front vehicle itself.
Definition ground_vehicle.hpp:44
GroundVehicle::IsMultiheaded
bool IsMultiheaded() const
Check if the vehicle is a multiheaded engine.
Definition ground_vehicle.hpp:330
GroupStatistics::CountVehicle
static void CountVehicle(const Vehicle *v, int delta)
Update num_vehicle when adding or removing a vehicle.
Definition group_cmd.cpp:143
GroupStatistics::VehicleReachedMinAge
static void VehicleReachedMinAge(const Vehicle *v)
Add a vehicle to the profit sum of its group.
Definition group_cmd.cpp:190
GroupStatistics::CountEngine
static void CountEngine(const Vehicle *v, int delta)
Update num_engines when adding/removing an engine.
Definition group_cmd.cpp:168
GroupStatistics::UpdateAutoreplace
static void UpdateAutoreplace(CompanyID company)
Update autoreplace_defined and autoreplace_finished of all statistics of a company.
Definition group_cmd.cpp:231
GroupStatistics::UpdateProfits
static void UpdateProfits()
Recompute the profits for all groups.
Definition group_cmd.cpp:204
Group
Group data.
Definition group.h:73
Group::livery
Livery livery
Custom colour scheme for vehicles in this group.
Definition group.h:79
Group::parent
GroupID parent
Parent group.
Definition group.h:85
Livery
Information about a particular livery.
Definition livery.h:79
Livery::in_use
Flags in_use
Livery flags.
Definition livery.h:86
Livery::colour2
Colours colour2
Second colour, for vehicles with 2CC support.
Definition livery.h:88
Livery::colour1
Colours colour1
First colour, for all vehicles.
Definition livery.h:87
MutableSpriteCache::revalidate_before_draw
bool revalidate_before_draw
We need to do a GetImage() and check bounds before drawing this sprite.
Definition vehicle_base.h:159
MutableSpriteCache::sprite_seq
VehicleSpriteSeq sprite_seq
Vehicle appearance.
Definition vehicle_base.h:162
MutableSpriteCache::old_coord
Rect old_coord
Co-ordinates from the last valid bounding box.
Definition vehicle_base.h:161
OrderBackup::ClearVehicle
static void ClearVehicle(const Vehicle *v)
Clear/update the (clone) vehicle from an order backup.
Definition order_backup.cpp:210
OrderList
Shared order list linking together the linked list of orders and the list of vehicles sharing this or...
Definition order_base.h:274
OrderList::AddVehicle
void AddVehicle(Vehicle *v)
Adds the given vehicle to this shared order list.
Definition order_base.h:411
OrderSettings::no_servicing_if_no_breakdowns
bool no_servicing_if_no_breakdowns
don't send vehicles to depot when breakdowns are disabled
Definition settings_type.h:511
Order
Definition order_base.h:33
Order::GetDepotOrderType
OrderDepotTypeFlags GetDepotOrderType() const
What caused us going to the depot?
Definition order_base.h:150
Order::GetDestination
DestinationID GetDestination() const
Gets the destination of this order.
Definition order_base.h:99
Order::IsType
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition order_base.h:66
Order::GetRefitCargo
CargoType GetRefitCargo() const
Get the cargo to to refit to.
Definition order_base.h:127
Order::IsFullLoadOrder
bool IsFullLoadOrder() const
Is this order a OrderLoadType::FullLoad or OrderLoadType::FullLoadAny?
Definition order_base.h:135
Order::MakeDummy
void MakeDummy()
Makes this order a Dummy order.
Definition order_cmd.cpp:116
Order::GetLoadType
OrderLoadType GetLoadType() const
How must the consist be loaded?
Definition order_base.h:142
Order::GetDepotActionType
OrderDepotActionFlags GetDepotActionType() const
What are we going to do when in the depot.
Definition order_base.h:152
Order::ShouldStopAtStation
bool ShouldStopAtStation(const Vehicle *v, StationID station) const
Check whether the given vehicle should stop at the given station based on this order and the non-stop...
Definition order_cmd.cpp:2173
Order::MakeImplicit
void MakeImplicit(StationID destination)
Makes this order an implicit order.
Definition order_cmd.cpp:137
Order::IsRefit
bool IsRefit() const
Is this order a refit order.
Definition order_base.h:113
PoolID< uint16_t, struct EngineIDTag, 64000, 0xFFFF >
Pool::PoolItem<&_vehicle_pool >::Iterate
static Pool::IterateWrapper< Titem > Iterate(size_t from=0)
Returns an iterable ensemble of all valid Titem.
Definition pool_type.hpp:436
Pool::PoolItem<&_vehicle_pool >::GetPoolSize
static size_t GetPoolSize()
Returns first unused index.
Definition pool_type.hpp:408
Pool::PoolItem<&_company_pool >::Get
static Titem * Get(auto index)
Returns Titem with given index.
Definition pool_type.hpp:387
Pool::PoolItem::index
Tindex index
Index of this pool item.
Definition pool_type.hpp:286
Pool::PoolItem<&_orderlist_pool >::CanAllocateItem
static bool CanAllocateItem(size_t n=1)
Helper functions so we can use PoolItem::Function() instead of _poolitem_pool.Function()
Definition pool_type.hpp:357
Pool::PoolItem<&_company_pool >::IsValidID
static bool IsValidID(auto index)
Tests whether given index can be used to get valid (non-nullptr) Titem.
Definition pool_type.hpp:376
Pool::PoolItem<&_group_pool >::GetIfValid
static Titem * GetIfValid(auto index)
Returns Titem with given index.
Definition pool_type.hpp:398
Pool
Base class for all pools.
Definition pool_type.hpp:133
RailVehicleInfo
Information about a rail vehicle.
Definition engine_type.h:74
RailVehicleInfo::engclass
EngineClass engclass
Class of engine for this vehicle.
Definition engine_type.h:86
Rect
Specification of a rectangle with absolute coordinates of all edges.
Definition geometry_type.hpp:101
RoadStop
A Stop for a Road Vehicle.
Definition roadstop_base.h:21
RoadStop::Leave
void Leave(RoadVehicle *rv)
Leave the road stop.
Definition roadstop.cpp:203
RoadStop::next
RoadStop * next
Next stop of the given type at this station.
Definition roadstop_base.h:71
RoadStop::xy
TileIndex xy
Position on the map.
Definition roadstop_base.h:70
RoadStop::GetByTile
static RoadStop * GetByTile(TileIndex tile, RoadStopType type)
Find a roadstop at given tile.
Definition roadstop.cpp:253
RoadVehicleInfo
Information about a road vehicle.
Definition engine_type.h:146
RoadVehicleInfo::roadtype
RoadType roadtype
Road type.
Definition engine_type.h:160
RoadVehicle
Buses, trucks and trams belong to this class.
Definition roadveh.h:98
RoadVehicle::state
uint8_t state
Definition roadveh.h:100
RoadVehicle::compatible_roadtypes
RoadTypes compatible_roadtypes
NOSAVE: Roadtypes this consist is powered on.
Definition roadveh.h:110
RoadVehicle::IsBus
bool IsBus() const
Check whether a roadvehicle is a bus.
Definition roadveh_cmd.cpp:82
RoadVehicle::roadtype
RoadType roadtype
NOSAVE: Roadtype of this vehicle.
Definition roadveh.h:108
RoadVehicle::disaster_vehicle
VehicleID disaster_vehicle
NOSAVE: Disaster vehicle targetting this vehicle.
Definition roadveh.h:109
ShipVehicleInfo
Information about a ship vehicle.
Definition engine_type.h:99
Ship
All ships have this type.
Definition ship.h:32
Ship::state
TrackBits state
The "track" the ship is following.
Definition ship.h:34
Ship::UpdateCache
void UpdateCache()
Update the caches of this ship.
Definition ship_cmd.cpp:231
SpecializedStation< Station, false >::IsValidID
static bool IsValidID(auto index)
Tests whether given index is a valid index for station of this type.
Definition base_station_base.h:239
SpecializedStation< Station, false >::Get
static Station * Get(auto index)
Gets station with given index.
Definition base_station_base.h:248
SpecializedStation< Station, false >::GetIfValid
static Station * GetIfValid(auto index)
Returns station if the index is a valid index for this station type.
Definition base_station_base.h:257
SpecializedVehicle::Next
T * Next() const
Get next vehicle in the chain.
Definition vehicle_base.h:1049
SpecializedVehicle::From
static T * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
Definition vehicle_base.h:1134
SpecializedVehicle::UpdateViewport
void UpdateViewport(bool force_update, bool update_delta)
Update vehicle sprite- and position caches.
Definition vehicle_base.h:1156
SpecializedVehicle::GetFirstEnginePart
T * GetFirstEnginePart()
Get the first part of an articulated engine.
Definition vehicle_base.h:1075
Sprite
Data structure describing a sprite.
Definition spritecache_type.h:16
Sprite::width
uint16_t width
Width of the sprite.
Definition spritecache_type.h:18
Sprite::height
uint16_t height
Height of the sprite.
Definition spritecache_type.h:17
Sprite::y_offs
int16_t y_offs
Number of pixels to shift the sprite downwards.
Definition spritecache_type.h:20
Sprite::x_offs
int16_t x_offs
Number of pixels to shift the sprite to the right.
Definition spritecache_type.h:19
Station
Station data structure.
Definition station_base.h:500
Station::goods
std::array< GoodsEntry, NUM_CARGO > goods
Goods at this station.
Definition station_base.h:529
Station::airport
Airport airport
Tile area the airport covers.
Definition station_base.h:514
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > >
TileTypeProcs::vehicle_enter_tile_proc
VehicleEnterTileProc * vehicle_enter_tile_proc
Called when a vehicle enters a tile.
Definition tile_cmd.h:164
Train
'Train' is either a loco or a wagon.
Definition train.h:91
Train::ConsistChanged
void ConsistChanged(ConsistChangeFlags allowed_changes)
Recalculates the cached stuff of a train.
Definition train_cmd.cpp:107
Train::wait_counter
uint16_t wait_counter
Ticks waiting in front of a signal, ticks being stuck or a counter for forced proceeding through sign...
Definition train.h:94
VehicleCache::cached_vis_effect
uint8_t cached_vis_effect
Visual effect to show (see VisualEffect)
Definition vehicle_base.h:96
VehicleCache::cached_cargo_age_period
uint16_t cached_cargo_age_period
Number of ticks before carried cargo is aged.
Definition vehicle_base.h:94
VehicleListIdentifier
The information about a vehicle list.
Definition vehiclelist.h:32
VehicleListIdentifier::ToWindowNumber
WindowNumber ToWindowNumber() const
Pack a VehicleListIdentifier in 32 bits so it can be used as unique WindowNumber.
Definition vehiclelist.cpp:23
VehicleSettings::max_ships
UnitID max_ships
max ships in game per company
Definition settings_type.h:529
VehicleSettings::max_trains
UnitID max_trains
max trains in game per company
Definition settings_type.h:526
VehicleSettings::smoke_amount
uint8_t smoke_amount
amount of smoke/sparks locomotives produce
Definition settings_type.h:519
VehicleSettings::max_aircraft
UnitID max_aircraft
max planes in game per company
Definition settings_type.h:528
VehicleSettings::max_roadveh
UnitID max_roadveh
max trucks in game per company
Definition settings_type.h:527
VehicleSpriteSeq
Sprite sequence for a vehicle part.
Definition vehicle_base.h:102
VehicleSpriteSeq::IsValid
bool IsValid() const
Check whether the sequence contains any sprites.
Definition vehicle_base.h:114
VehicleSpriteSeq::Draw
void Draw(int x, int y, PaletteID default_pal, bool force_pal) const
Draw the sprite sequence.
Definition vehicle.cpp:142
Vehicle
Vehicle data structure.
Definition vehicle_base.h:205
Vehicle::GetDisplayProfitThisYear
Money GetDisplayProfitThisYear() const
Gets the profit vehicle had this year.
Definition vehicle_base.h:572
Vehicle::cargo_payment
CargoPayment * cargo_payment
The cargo payment we're currently in.
Definition vehicle_base.h:238
Vehicle::engine_type
EngineID engine_type
The type of engine used for this vehicle.
Definition vehicle_base.h:278
Vehicle::cargo_age_counter
uint16_t cargo_age_counter
Ticks till cargo is aged next.
Definition vehicle_base.h:301
Vehicle::z_pos
int32_t z_pos
z coordinate.
Definition vehicle_base.h:267
Vehicle::GetGroundVehicleFlags
uint16_t & GetGroundVehicleFlags()
Access the ground vehicle flags of the vehicle.
Definition vehicle.cpp:3173
Vehicle::direction
Direction direction
facing
Definition vehicle_base.h:268
Vehicle::ShiftDates
void ShiftDates(TimerGameEconomy::Date interval)
Shift all dates by given interval.
Definition vehicle.cpp:748
Vehicle::GetLastOrder
const Order * GetLastOrder() const
Returns the last order of a vehicle, or nullptr if it doesn't exists.
Definition vehicle_base.h:899
Vehicle::economy_age
TimerGameEconomy::Date economy_age
Age in economy days.
Definition vehicle_base.h:254
Vehicle::GetEngine
const Engine * GetEngine() const
Retrieves the engine of the vehicle.
Definition vehicle.cpp:718
Vehicle::Crash
virtual uint Crash(bool flooded=false)
Crash the (whole) vehicle chain.
Definition vehicle.cpp:291
Vehicle::GetOrder
Order * GetOrder(int index) const
Returns order 'index' of a vehicle or nullptr when it doesn't exists.
Definition vehicle_base.h:890
Vehicle::HasDepotOrder
bool HasDepotOrder() const
Checks if a vehicle has a depot in its order list.
Definition order_cmd.cpp:1816
Vehicle::LeaveStation
void LeaveStation()
Perform all actions when leaving a station.
Definition vehicle.cpp:2327
Vehicle::AddToShared
void AddToShared(Vehicle *shared_chain)
Adds this vehicle to a shared vehicle chain.
Definition vehicle.cpp:2956
Vehicle::cargo
VehicleCargoList cargo
The cargo this vehicle is carrying.
Definition vehicle_base.h:296
Vehicle::hash_tile_prev
Vehicle ** hash_tile_prev
NOSAVE: Previous vehicle in the tile location hash.
Definition vehicle_base.h:246
Vehicle::HasUnbunchingOrder
bool HasUnbunchingOrder() const
Check if the current vehicle has an unbunching order.
Definition vehicle.cpp:2462
Vehicle::date_of_last_service
TimerGameEconomy::Date date_of_last_service
Last economy date the vehicle had a service at a depot.
Definition vehicle_base.h:256
Vehicle::cargo_cap
uint16_t cargo_cap
total capacity
Definition vehicle_base.h:299
Vehicle::last_loading_station
StationID last_loading_station
Last station the vehicle has stopped at and could possibly leave from with any cargo loaded.
Definition vehicle_base.h:293
Vehicle::GetFirstOrder
const Order * GetFirstOrder() const
Get the first order of the vehicles order list.
Definition vehicle_base.h:660
Vehicle::SendToDepot
CommandCost SendToDepot(DoCommandFlags flags, DepotCommandFlags command)
Send this vehicle to the depot using the given command(s).
Definition vehicle.cpp:2555
Vehicle::ReleaseUnitNumber
void ReleaseUnitNumber()
Release the vehicle's unit number.
Definition vehicle.cpp:2396
Vehicle::UpdateBoundingBoxCoordinates
void UpdateBoundingBoxCoordinates(bool update_cache) const
Update the bounding box co-ordinates of the vehicle.
Definition vehicle.cpp:1671
Vehicle::day_counter
uint8_t day_counter
Increased by one for each day.
Definition vehicle_base.h:304
Vehicle::HandleLoading
void HandleLoading(bool mode=false)
Handle the loading of the vehicle; when not it skips through dummy orders and does nothing in all oth...
Definition vehicle.cpp:2407
Vehicle::profit_this_year
Money profit_this_year
Profit this year << 8, low 8 bits are fract.
Definition vehicle_base.h:234
Vehicle::HasArticulatedPart
bool HasArticulatedPart() const
Check if an engine has an articulated part.
Definition vehicle_base.h:931
Vehicle::colourmap
SpriteID colourmap
NOSAVE: cached colour mapping.
Definition vehicle_base.h:249
Vehicle::breakdown_ctr
uint8_t breakdown_ctr
Counter for managing breakdown events.
Definition vehicle_base.h:260
Vehicle::breakdown_delay
uint8_t breakdown_delay
Counter for managing breakdown length.
Definition vehicle_base.h:261
Vehicle::GetNextVehicle
Vehicle * GetNextVehicle() const
Get the next real (non-articulated part) vehicle in the consist.
Definition vehicle_base.h:984
Vehicle::group_id
GroupID group_id
Index of group Pool array.
Definition vehicle_base.h:321
Vehicle::IncrementImplicitOrderIndex
void IncrementImplicitOrderIndex()
Increments cur_implicit_order_index, keeps care of the wrap-around and invalidates the GUI.
Definition vehicle_base.h:830
Vehicle::IsGroundVehicle
bool IsGroundVehicle() const
Check if the vehicle is a ground vehicle.
Definition vehicle_base.h:470
Vehicle::vehstatus
VehStates vehstatus
Status.
Definition vehicle_base.h:309
Vehicle::date_of_last_service_newgrf
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...
Definition vehicle_base.h:257
Vehicle::first
Vehicle * first
NOSAVE: pointer to the first vehicle in the chain.
Definition vehicle_base.h:211
Vehicle::CancelReservation
void CancelReservation(StationID next, Station *st)
Return all reserved cargo packets to the station and reset all packets staged for transfer.
Definition vehicle.cpp:2311
Vehicle::profit_last_year
Money profit_last_year
Profit last year << 8, low 8 bits are fract.
Definition vehicle_base.h:235
Vehicle::IsEngineCountable
bool IsEngineCountable() const
Check if a vehicle is counted in num_engines in each company struct.
Definition vehicle.cpp:685
Vehicle::~Vehicle
virtual ~Vehicle()
We want to 'destruct' the right class.
Definition vehicle.cpp:863
Vehicle::IsArticulatedPart
bool IsArticulatedPart() const
Check if the vehicle is an articulated part of an engine.
Definition vehicle_base.h:922
Vehicle::NeedsAutorenewing
bool NeedsAutorenewing(const Company *c, bool use_renew_setting=true) const
Function to tell if a vehicle needs to be autorenewed.
Definition vehicle.cpp:156
Vehicle::UpdateVisualEffect
void UpdateVisualEffect(bool allow_power_change=true)
Update the cached visual effect.
Definition vehicle.cpp:2636
Vehicle::LeaveUnbunchingDepot
void LeaveUnbunchingDepot()
Leave an unbunching depot and calculate the next departure time for shared order vehicles.
Definition vehicle.cpp:2486
Vehicle::cargo_type
CargoType cargo_type
type of cargo this vehicle is carrying
Definition vehicle_base.h:297
Vehicle::previous_shared
Vehicle * previous_shared
NOSAVE: pointer to the previous vehicle in the shared order chain.
Definition vehicle_base.h:214
Vehicle::First
Vehicle * First() const
Get the first vehicle of this vehicle chain.
Definition vehicle_base.h:600
Vehicle::current_order
Order current_order
The current order (+ status, like: loading)
Definition vehicle_base.h:311
Vehicle::PreDestructor
void PreDestructor()
Destroy all stuff that (still) needs the virtual functions to work properly.
Definition vehicle.cpp:796
Vehicle::HandlePathfindingResult
void HandlePathfindingResult(bool path_found)
Handle the pathfinding result, especially the lost status.
Definition vehicle.cpp:762
Vehicle::Next
Vehicle * Next() const
Get the next vehicle of this vehicle.
Definition vehicle_base.h:587
Vehicle::y_pos
int32_t y_pos
y coordinate.
Definition vehicle_base.h:266
Vehicle::x_pos
int32_t x_pos
x coordinate.
Definition vehicle_base.h:265
Vehicle::GetGRF
const GRFFile * GetGRF() const
Retrieve the NewGRF the vehicle is tied to.
Definition vehicle.cpp:728
Vehicle::orders
OrderList * orders
Pointer to the order list for this vehicle.
Definition vehicle_base.h:314
Vehicle::GetDisplayMinPowerToWeight
uint32_t GetDisplayMinPowerToWeight() const
Calculates the minimum power-to-weight ratio using the maximum weight of the ground vehicle.
Definition vehicle.cpp:3247
Vehicle::UpdateViewport
void UpdateViewport(bool dirty)
Update the vehicle on the viewport, updating the right hash and setting the new coordinates.
Definition vehicle.cpp:1716
Vehicle::value
Money value
Value of the vehicle.
Definition vehicle_base.h:236
Vehicle::MarkAllViewportsDirty
bool MarkAllViewportsDirty() const
Marks viewports dirty where the vehicle's image is.
Definition vehicle.cpp:1755
Vehicle::refit_cap
uint16_t refit_cap
Capacity left over from before last refit.
Definition vehicle_base.h:300
Vehicle::vcache
VehicleCache vcache
Cache of often used vehicle values.
Definition vehicle_base.h:319
Vehicle::motion_counter
uint32_t motion_counter
counter to occasionally play a vehicle sound.
Definition vehicle_base.h:286
Vehicle::GetGRFID
uint32_t GetGRFID() const
Retrieve the GRF ID of the NewGRF the vehicle is tied to.
Definition vehicle.cpp:738
Vehicle::bounds
SpriteBounds bounds
Bounding box of vehicle.
Definition vehicle_base.h:277
Vehicle::GetGroundVehicleCache
GroundVehicleCache * GetGroundVehicleCache()
Access the ground vehicle cache of the vehicle.
Definition vehicle.cpp:3143
Vehicle::OnNewEconomyDay
virtual void OnNewEconomyDay()
Calls the new economy day handler of the vehicle.
Definition vehicle_base.h:537
Vehicle::hash_tile_current
Vehicle ** hash_tile_current
NOSAVE: Cache of the current hash chain.
Definition vehicle_base.h:247
Vehicle::OnNewCalendarDay
virtual void OnNewCalendarDay()
Calls the new calendar day handler of the vehicle.
Definition vehicle_base.h:532
Vehicle::NextShared
Vehicle * NextShared() const
Get the next vehicle of the shared vehicle chain.
Definition vehicle_base.h:681
Vehicle::HasFullLoadOrder
bool HasFullLoadOrder() const
Check if the current vehicle has a full load order.
Definition vehicle.cpp:2442
Vehicle::IsPrimaryVehicle
virtual bool IsPrimaryVehicle() const
Whether this is the primary vehicle in the chain.
Definition vehicle_base.h:432
Vehicle::BeginLoading
void BeginLoading()
Prepare everything to begin the loading when arriving at a station.
Definition vehicle.cpp:2183
Vehicle::hash_tile_next
Vehicle * hash_tile_next
NOSAVE: Next vehicle in the tile location hash.
Definition vehicle_base.h:245
Vehicle::cur_speed
uint16_t cur_speed
current speed
Definition vehicle_base.h:283
Vehicle::previous
Vehicle * previous
NOSAVE: pointer to the previous vehicle in the chain.
Definition vehicle_base.h:210
Vehicle::IsFrontEngine
bool IsFrontEngine() const
Check if the vehicle is a front engine.
Definition vehicle_base.h:913
Vehicle::HasEngineType
bool HasEngineType() const
Check whether Vehicle::engine_type has any meaning.
Definition vehicle.cpp:702
Vehicle::age
TimerGameCalendar::Date age
Age in calendar days.
Definition vehicle_base.h:253
Vehicle::IsWaitingForUnbunching
bool IsWaitingForUnbunching() const
Check whether a vehicle inside a depot is waiting for unbunching.
Definition vehicle.cpp:2533
Vehicle::fill_percent_te_id
TextEffectID fill_percent_te_id
a text-effect id to a loading indicator object
Definition vehicle_base.h:280
Vehicle::SetNext
void SetNext(Vehicle *next)
Set the next vehicle of this vehicle.
Definition vehicle.cpp:2927
Vehicle::breakdowns_since_last_service
uint8_t breakdowns_since_last_service
Counter for the amount of breakdowns.
Definition vehicle_base.h:262
Vehicle::next
Vehicle * next
pointer to the next vehicle in the chain
Definition vehicle_base.h:209
Vehicle::max_age
TimerGameCalendar::Date max_age
Maximum age.
Definition vehicle_base.h:255
Vehicle::sprite_cache
MutableSpriteCache sprite_cache
Cache of sprites and values related to recalculating them, see MutableSpriteCache.
Definition vehicle_base.h:323
Vehicle::reliability
uint16_t reliability
Reliability.
Definition vehicle_base.h:258
Vehicle::GetDisplayMaxWeight
uint32_t GetDisplayMaxWeight() const
Calculates the maximum weight of the ground vehicle when loaded.
Definition vehicle.cpp:3232
Vehicle::RemoveFromShared
void RemoveFromShared()
Removes the vehicle from the shared order list.
Definition vehicle.cpp:2979
Vehicle::HandleBreakdown
bool HandleBreakdown()
Handle all of the aspects of a vehicle breakdown This includes adding smoke and sounds,...
Definition vehicle.cpp:1332
Vehicle::UpdatePositionAndViewport
void UpdatePositionAndViewport()
Update the position of the vehicle, and update the viewport.
Definition vehicle.cpp:1745
Vehicle::Vehicle
Vehicle(VehicleType type=VEH_INVALID)
Vehicle constructor.
Definition vehicle.cpp:369
Vehicle::Previous
Vehicle * Previous() const
Get the previous vehicle of this vehicle.
Definition vehicle_base.h:594
Vehicle::coord
Rect coord
NOSAVE: Graphical bounding box of the vehicle, i.e. what to redraw on moves.
Definition vehicle_base.h:240
Vehicle::reliability_spd_dec
uint16_t reliability_spd_dec
Reliability decrease speed.
Definition vehicle_base.h:259
Vehicle::tick_counter
uint8_t tick_counter
Increased by one for each tick.
Definition vehicle_base.h:305
Vehicle::tile
TileIndex tile
Current tile index.
Definition vehicle_base.h:225
Vehicle::Tick
virtual bool Tick()
Calls the tick handler of the vehicle.
Definition vehicle_base.h:527
Vehicle::dest_tile
TileIndex dest_tile
Heading for this tile.
Definition vehicle_base.h:232
Vehicle::NeedsServicing
bool NeedsServicing() const
Check if the vehicle needs to go to a depot in near future (if a opportunity presents itself) for ser...
Definition vehicle.cpp:201
Vehicle::HasConditionalOrder
bool HasConditionalOrder() const
Check if the current vehicle has a conditional order.
Definition vehicle.cpp:2453
Vehicle::UpdatePosition
void UpdatePosition()
Update the position of the vehicle.
Definition vehicle.cpp:1662
Vehicle::last_station_visited
StationID last_station_visited
The last station we stopped at.
Definition vehicle_base.h:292
Vehicle::ResetRefitCaps
void ResetRefitCaps()
Reset all refit_cap in the consist to cargo_cap.
Definition vehicle.cpp:2388
Vehicle::breakdown_chance
uint8_t breakdown_chance
Current chance of breakdowns.
Definition vehicle_base.h:263
Vehicle::ShowVisualEffect
void ShowVisualEffect() const
Draw visual effects (smoke and/or sparks) for a vehicle chain.
Definition vehicle.cpp:2777
Vehicle::owner
Owner owner
Which company owns the vehicle?
Definition vehicle_base.h:270
Vehicle::next_shared
Vehicle * next_shared
pointer to the next vehicle that shares the order
Definition vehicle_base.h:213
Vehicle::NeedsAutomaticServicing
bool NeedsAutomaticServicing() const
Checks if the current order should be interrupted for a service-in-depot order.
Definition vehicle.cpp:283
Vehicle::DeleteUnreachedImplicitOrders
void DeleteUnreachedImplicitOrders()
Delete all implicit orders which were not reached.
Definition vehicle.cpp:2145
Vehicle::hash_viewport_prev
Vehicle ** hash_viewport_prev
NOSAVE: Previous vehicle in the visual location hash.
Definition vehicle_base.h:243
Vehicle::GetImage
virtual void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const
Gets the sprite to show for the given direction.
Definition vehicle_base.h:441
Vehicle::hash_viewport_next
Vehicle * hash_viewport_next
NOSAVE: Next vehicle in the visual location hash.
Definition vehicle_base.h:242
Viewport
Data structure for viewport, display of a part of the world.
Definition viewport_type.h:31
Viewport::top
int top
Screen coordinate top edge of the viewport.
Definition viewport_type.h:33
Viewport::width
int width
Screen width of the viewport.
Definition viewport_type.h:34
Viewport::zoom
ZoomLevel zoom
The zoom level of the viewport.
Definition viewport_type.h:42
Viewport::virtual_top
int virtual_top
Virtual top coordinate.
Definition viewport_type.h:38
Viewport::virtual_left
int virtual_left
Virtual left coordinate.
Definition viewport_type.h:37
Viewport::left
int left
Screen coordinate left edge of the viewport.
Definition viewport_type.h:32
Viewport::height
int height
Screen height of the viewport.
Definition viewport_type.h:35
VehicleEnterTile
VehicleEnterTileStates VehicleEnterTile(Vehicle *v, TileIndex tile, int x, int y)
Call the tile callback function for a vehicle entering a tile.
Definition vehicle.cpp:1819
IsTileType
static bool IsTileType(Tile tile, TileType type)
Checks if a tile is a given tiletype.
Definition tile_map.h:150
GetTileMaxPixelZ
int GetTileMaxPixelZ(TileIndex tile)
Get top height of the tile.
Definition tile_map.h:312
GetTileType
static TileType GetTileType(Tile tile)
Get the tiletype of a given tile.
Definition tile_map.h:96
MAX_VEHICLE_PIXEL_Y
static constexpr int MAX_VEHICLE_PIXEL_Y
Maximum height of a vehicle in pixels in ZOOM_BASE.
Definition tile_type.h:22
TILE_SIZE
static constexpr uint TILE_SIZE
Tile size in world coordinates.
Definition tile_type.h:15
MAX_VEHICLE_PIXEL_X
static constexpr int MAX_VEHICLE_PIXEL_X
Maximum width of a vehicle in pixels in ZOOM_BASE.
Definition tile_type.h:21
MP_STATION
@ MP_STATION
A tile of a station.
Definition tile_type.h:53
timer.h
Definition of Interval and OneShot timers.
timer_game_calendar.h
Definition of the game-calendar-timer.
timer_game_economy.h
Definition of the game-economy-timer.
timer_game_tick.h
Definition of the tick-based game-timer.
timetable.h
Functions related to time tabling.
UpdateVehicleTimetable
void UpdateVehicleTimetable(Vehicle *v, bool travelling)
Update the timetable for the vehicle.
Definition timetable_cmd.cpp:469
TracksOverlap
bool TracksOverlap(TrackBits bits)
Checks if the given tracks overlap, ie form a crossing.
Definition track_func.h:645
TrackBits
TrackBits
Allow incrementing of Track variables.
Definition track_type.h:35
TRACK_BIT_DEPOT
@ TRACK_BIT_DEPOT
Bitflag for a depot.
Definition track_type.h:53
train.h
Base for the train class.
Reversed
@ Reversed
Used for vehicle var 0xFE bit 8 (toggled each time the train is reversed, accurate for first vehicle ...
Definition train.h:31
Flipped
@ Flipped
Reverse the visible direction of the vehicle.
Definition train.h:28
LeavingStation
@ LeavingStation
Train is just leaving a station.
Definition train.h:33
Reversing
@ Reversing
Train is slowing down to reverse.
Definition train.h:26
TFP_NONE
@ TFP_NONE
Normal operation.
Definition train.h:39
CCF_ARRANGE
static constexpr ConsistChangeFlags CCF_ARRANGE
Valid changes for arranging the consist in a depot.
Definition train.h:56
train_cmd.h
Command definitions related to trains.
IsTransparencySet
bool IsTransparencySet(TransparencyOption to)
Check if the transparency option bit is set and if we aren't in the game menu (there's never transpar...
Definition transparency.h:50
IsInvisibilitySet
bool IsInvisibilitySet(TransparencyOption to)
Check if the invisibility option bit is set and if we aren't in the game menu (there's never transpar...
Definition transparency.h:61
TransparencyOption
TransparencyOption
Transparency option bits: which position in _transparency_opt stands for which transparency.
Definition transparency.h:23
TO_INVALID
@ TO_INVALID
Invalid transparency option.
Definition transparency.h:34
UnitID
uint16_t UnitID
Type for the company global vehicle unit number.
Definition transport_type.h:14
tunnel_map.h
Map accessors for tunnels.
IsTunnelTile
bool IsTunnelTile(Tile t)
Is this a tunnel (entrance)?
Definition tunnel_map.h:34
ShowNewGrfVehicleError
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:328
GetTileHash
static uint GetTileHash(uint x, uint y)
Compute hash for tile coordinate.
Definition vehicle.cpp:421
VehicleEnteredDepotThisTick
static void VehicleEnteredDepotThisTick(Vehicle *v)
Adds a vehicle to the list of vehicles that visited a depot this tick.
Definition vehicle.cpp:891
SpawnAdvancedVisualEffect
static void SpawnAdvancedVisualEffect(const Vehicle *v)
Call CBID_VEHICLE_SPAWN_VISUAL_EFFECT and spawn requested effects.
Definition vehicle.cpp:2704
GetTileHash1D
static uint GetTileHash1D(uint p)
Compute hash for 1D tile coordinate.
Definition vehicle.cpp:397
VehicleLengthChanged
void VehicleLengthChanged(const Vehicle *u)
Logs a bug in GRF and shows a warning message if this is for the first time this happened.
Definition vehicle.cpp:354
_vehicle_pool
VehiclePool _vehicle_pool("Vehicle")
The pool with all our precious vehicles.
VehicleServiceInDepot
void VehicleServiceInDepot(Vehicle *v)
Service a vehicle and all subsequent vehicles in the consist.
Definition vehicle.cpp:178
RunEconomyVehicleDayProc
static void RunEconomyVehicleDayProc()
Increases the day counter for all vehicles and calls 1-day and 32-day handlers.
Definition vehicle.cpp:924
ComposeTileHash
static uint ComposeTileHash(uint hx, uint hy)
Compose two 1D hashes into 2D hash.
Definition vehicle.cpp:413
IncTileHash1D
static uint IncTileHash1D(uint h)
Increment 1D hash to next bucket.
Definition vehicle.cpp:405
CanVehicleUseStation
bool CanVehicleUseStation(EngineID engine_type, const Station *st)
Can this station be used by the given engine type?
Definition vehicle.cpp:3046
CheckClickOnVehicle
Vehicle * CheckClickOnVehicle(const Viewport &vp, int x, int y)
Find the vehicle close to the clicked coordinates.
Definition vehicle.cpp:1215
AutoreplaceMap
std::map< VehicleID, bool > AutoreplaceMap
List of vehicles that should check for autoreplace this tick.
Definition vehicle.cpp:665
IsBridgeAboveVehicle
static bool IsBridgeAboveVehicle(const Vehicle *v)
Test if a bridge is above a vehicle.
Definition vehicle.cpp:2762
PreviousOrderIsUnbunching
static bool PreviousOrderIsUnbunching(const Vehicle *v)
Check if the previous order is a depot unbunching order.
Definition vehicle.cpp:2473
DoDrawVehicle
static void DoDrawVehicle(const Vehicle *v)
Add vehicle sprite for drawing to the screen.
Definition vehicle.cpp:1092
VehState::Unclickable
@ Unclickable
Vehicle is not clickable by the user (shadow vehicles).
VehState::Crashed
@ Crashed
Vehicle is crashed.
VehState::Shadow
@ Shadow
Vehicle is a shadow vehicle.
VehState::TrainSlowing
@ TrainSlowing
Train is slowing down.
VehState::AircraftBroken
@ AircraftBroken
Aircraft is broken down.
VehState::Hidden
@ Hidden
Vehicle is not visible.
VehState::DefaultPalette
@ DefaultPalette
Use default vehicle palette.
VehState::Stopped
@ Stopped
Vehicle is stopped by the player.
VisualEffectSpawnModel
VisualEffectSpawnModel
Models for spawning visual effects.
Definition vehicle_base.h:68
VESM_ELECTRIC
@ VESM_ELECTRIC
Electric model.
Definition vehicle_base.h:72
VESM_STEAM
@ VESM_STEAM
Steam model.
Definition vehicle_base.h:70
VESM_DIESEL
@ VESM_DIESEL
Diesel model.
Definition vehicle_base.h:71
VESM_NONE
@ VESM_NONE
No visual effect.
Definition vehicle_base.h:69
INVALID_COORD
static const int32_t INVALID_COORD
Sentinel for an invalid coordinate.
Definition vehicle_base.h:1207
vehicle_cmd.h
Command definitions for vehicles.
vehicle_func.h
Functions related to vehicles.
ShowNewGrfVehicleError
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:328
EnsureNoVehicleOnGround
CommandCost EnsureNoVehicleOnGround(TileIndex tile)
Ensure there is no vehicle at the ground at the given position.
Definition vehicle.cpp:527
VehiclesHaveSameEngineList
bool VehiclesHaveSameEngineList(const Vehicle *v1, const Vehicle *v2)
Checks if two vehicle chains have the same list of engines.
Definition vehicle.cpp:3260
VehiclesHaveSameOrderList
bool VehiclesHaveSameOrderList(const Vehicle *v1, const Vehicle *v2)
Checks if two vehicles have the same list of orders.
Definition vehicle.cpp:3277
GetEnginePalette
SpriteID GetEnginePalette(EngineID engine_type, CompanyID company)
Get the colour map for an engine.
Definition vehicle.cpp:2123
VehicleEnterDepot
void VehicleEnterDepot(Vehicle *v)
Vehicle entirely entered the depot, update its status, orders, vehicle windows, service it,...
Definition vehicle.cpp:1520
VEHICLE_PROFIT_MIN_AGE
static const TimerGameEconomy::Date VEHICLE_PROFIT_MIN_AGE
Only vehicles older than this have a meaningful profit.
Definition vehicle_func.h:37
GetVehicleSet
void GetVehicleSet(VehicleSet &set, Vehicle *v, uint8_t num_vehicles)
Calculates the set of vehicles that will be affected by a given selection.
Definition vehicle.cpp:3206
GetFreeUnitNumber
UnitID GetFreeUnitNumber(VehicleType type)
Get an unused unit number for a vehicle (if allowed).
Definition vehicle.cpp:1876
RunVehicleCalendarDayProc
void RunVehicleCalendarDayProc()
Age all vehicles, spreading out the action using the current TimerGameCalendar::date_fract.
Definition vehicle.cpp:907
VehicleServiceInDepot
void VehicleServiceInDepot(Vehicle *v)
Service a vehicle and all subsequent vehicles in the consist.
Definition vehicle.cpp:178
EnsureNoTrainOnTrackBits
CommandCost EnsureNoTrainOnTrackBits(TileIndex tile, TrackBits track_bits)
Tests if a vehicle interacts with the specified track bits.
Definition vehicle.cpp:575
GetEngineLiveryScheme
LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_type, const Vehicle *v)
Determines the LiveryScheme for a vehicle.
Definition vehicle.cpp:1951
ViewportAddVehicles
void ViewportAddVehicles(DrawPixelInfo *dpi)
Add the vehicle sprites that should be drawn at a part of the screen.
Definition vehicle.cpp:1121
GetNewVehiclePos
GetNewVehiclePosResult GetNewVehiclePos(const Vehicle *v)
Get position information of a vehicle when moving one pixel in the direction it is facing.
Definition vehicle.cpp:1765
GetVehicleCannotUseStationReason
StringID GetVehicleCannotUseStationReason(const Vehicle *v, const Station *st)
Get reason string why this station can't be used by the given vehicle.
Definition vehicle.cpp:3092
ReleaseDisasterVehicle
void ReleaseDisasterVehicle(VehicleID vehicle)
Notify disasters that we are about to delete a vehicle.
Definition disaster_vehicle.cpp:977
DecreaseVehicleValue
void DecreaseVehicleValue(Vehicle *v)
Decrease the value of a vehicle.
Definition vehicle.cpp:1270
EconomyAgeVehicle
void EconomyAgeVehicle(Vehicle *v)
Update economy age of a vehicle.
Definition vehicle.cpp:1398
GetEngineLivery
const struct Livery * GetEngineLivery(EngineID engine_type, CompanyID company, EngineID parent_engine_type, const Vehicle *v, uint8_t livery_setting)
Determines the livery for a vehicle.
Definition vehicle.cpp:2045
TunnelBridgeIsFree
CommandCost TunnelBridgeIsFree(TileIndex tile, TileIndex endtile, const Vehicle *ignore=nullptr)
Finds vehicle in tunnel / bridge.
Definition vehicle.cpp:551
CanBuildVehicleInfrastructure
bool CanBuildVehicleInfrastructure(VehicleType type, uint8_t subtype=0)
Check whether we can build infrastructure for the given vehicle type.
Definition vehicle.cpp:1903
AgeVehicle
void AgeVehicle(Vehicle *v)
Update age of a vehicle.
Definition vehicle.cpp:1410
GetVehiclePalette
SpriteID GetVehiclePalette(const Vehicle *v)
Get the colour map for a vehicle.
Definition vehicle.cpp:2133
CalcPercentVehicleFilled
uint8_t CalcPercentVehicleFilled(const Vehicle *v, StringID *colour)
Calculates how full a vehicle is.
Definition vehicle.cpp:1461
IsCompanyBuildableVehicleType
bool IsCompanyBuildableVehicleType(VehicleType type)
Is the given vehicle type buildable by a company?
Definition vehicle_func.h:228
VIWD_MODIFY_ORDERS
@ VIWD_MODIFY_ORDERS
Other order modifications.
Definition vehicle_gui.h:36
GetWindowClassForVehicleType
WindowClass GetWindowClassForVehicleType(VehicleType vt)
Get WindowClass for vehicle list of given vehicle type.
Definition vehicle_gui.h:97
EIT_ON_MAP
@ EIT_ON_MAP
Vehicle drawn in viewport.
Definition vehicle_type.h:75
VehicleType
VehicleType
Available vehicle types.
Definition vehicle_type.h:22
VEH_ROAD
@ VEH_ROAD
Road vehicle type.
Definition vehicle_type.h:26
VEH_DISASTER
@ VEH_DISASTER
Disaster vehicle type.
Definition vehicle_type.h:33
VEH_AIRCRAFT
@ VEH_AIRCRAFT
Aircraft vehicle type.
Definition vehicle_type.h:28
VEH_SHIP
@ VEH_SHIP
Ship vehicle type.
Definition vehicle_type.h:27
VEH_EFFECT
@ VEH_EFFECT
Effect vehicle type (smoke, explosions, sparks, bubbles)
Definition vehicle_type.h:32
VEH_TRAIN
@ VEH_TRAIN
Train vehicle type.
Definition vehicle_type.h:25
VehicleRandomTrigger::Callback32
@ Callback32
All vehicles in consist: 32 day callback requested rerandomisation.
VehicleRandomTrigger::Depot
@ Depot
Front vehicle only: Consist arrived in depot.
DepotCommandFlag::DontCancel
@ DontCancel
Don't cancel current goto depot command if any.
DepotCommandFlag::Service
@ Service
The vehicle will leave the depot right after arrival (service only)
VEHICLE_LENGTH
static const uint VEHICLE_LENGTH
The length of a vehicle in tile units.
Definition vehicle_type.h:65
WID_VV_START_STOP
@ WID_VV_START_STOP
Start or stop this vehicle, and show information about the current state.
Definition vehicle_widget.h:17
vehiclelist.h
Functions and type for generating vehicle lists.
VL_SHARED_ORDERS
@ VL_SHARED_ORDERS
Index is the first vehicle of the shared orders.
Definition vehiclelist.h:24
StartSpriteCombine
void StartSpriteCombine()
Starts a block of sprites, which are "combined" into a single bounding box.
Definition viewport.cpp:764
AddSortableSpriteToDraw
void AddSortableSpriteToDraw(SpriteID image, PaletteID pal, int x, int y, int z, const SpriteBounds &bounds, bool transparent, const SubSprite *sub)
Draw a (transparent) sprite at given coordinates with a given bounding box.
Definition viewport.cpp:663
EndSpriteCombine
void EndSpriteCombine()
Terminates a block of sprites started by StartSpriteCombine.
Definition viewport.cpp:774
viewport_func.h
Functions related to (drawing on) viewports.
CloseWindowById
void CloseWindowById(WindowClass cls, WindowNumber number, bool force, int data)
Close a window by its class and window number (if it is open).
Definition window.cpp:1193
SetWindowClassesDirty
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition window.cpp:3202
InvalidateWindowData
void InvalidateWindowData(WindowClass cls, WindowNumber number, int data, bool gui_scope)
Mark window data of the window of a given class and specific window number as invalid (in need of re-...
Definition window.cpp:3294
SetWindowWidgetDirty
void SetWindowWidgetDirty(WindowClass cls, WindowNumber number, WidgetID widget_index)
Mark a particular widget in a particular window as dirty (in need of repainting)
Definition window.cpp:3189
SetWindowDirty
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition window.cpp:3176
InvalidateWindowClassesData
void InvalidateWindowClassesData(WindowClass cls, int data, bool gui_scope)
Mark window data of all windows of a given class as invalid (in need of re-computing) Note that by de...
Definition window.cpp:3311
WC_ROADVEH_LIST
@ WC_ROADVEH_LIST
Road vehicle list; Window numbers:
Definition window_type.h:319
WC_VEHICLE_ORDERS
@ WC_VEHICLE_ORDERS
Vehicle orders; Window numbers:
Definition window_type.h:217
WC_VEHICLE_DEPOT
@ WC_VEHICLE_DEPOT
Depot view; Window numbers:
Definition window_type.h:356
WC_SHIPS_LIST
@ WC_SHIPS_LIST
Ships list; Window numbers:
Definition window_type.h:325
WC_STATION_VIEW
@ WC_STATION_VIEW
Station view; Window numbers:
Definition window_type.h:350
WC_TRAINS_LIST
@ WC_TRAINS_LIST
Trains list; Window numbers:
Definition window_type.h:313
WC_VEHICLE_REFIT
@ WC_VEHICLE_REFIT
Vehicle refit; Window numbers:
Definition window_type.h:211
WC_VEHICLE_DETAILS
@ WC_VEHICLE_DETAILS
Vehicle details; Window numbers:
Definition window_type.h:205
WC_COMPANY
@ WC_COMPANY
Company view; Window numbers:
Definition window_type.h:374
WC_VEHICLE_VIEW
@ WC_VEHICLE_VIEW
Vehicle view; Window numbers:
Definition window_type.h:344
WC_VEHICLE_TIMETABLE
@ WC_VEHICLE_TIMETABLE
Vehicle timetable; Window numbers:
Definition window_type.h:229
WC_AIRCRAFT_LIST
@ WC_AIRCRAFT_LIST
Aircraft list; Window numbers:
Definition window_type.h:331
zoom_func.h
Functions related to zooming.
ScaleByZoom
int ScaleByZoom(int value, ZoomLevel zoom)
Scale by zoom level, usually shift left (when zoom > ZoomLevel::Min) When shifting right,...
Definition zoom_func.h:22