OpenTTD Source: src/aircraft_cmd.cpp Source File

OpenTTD Source 15.3

aircraft_cmd.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
13#include "stdafx.h"
14#include "aircraft.h"
15#include "landscape.h"
16#include "news_func.h"
17#include "newgrf_engine.h"
18#include "newgrf_sound.h"
19#include "error_func.h"
20#include "strings_func.h"
21#include "command_func.h"
22#include "window_func.h"
23#include "timer/timer_game_calendar.h"
24#include "timer/timer_game_economy.h"
25#include "vehicle_func.h"
26#include "sound_func.h"
27#include "cheat_type.h"
28#include "company_base.h"
29#include "ai/ai.hpp"
30#include "game/game.hpp"
31#include "company_func.h"
32#include "effectvehicle_func.h"
33#include "station_base.h"
34#include "engine_base.h"
35#include "core/random_func.hpp"
36#include "core/backup_type.hpp"
37#include "zoom_func.h"
38#include "disaster_vehicle.h"
39#include "newgrf_airporttiles.h"
40#include "framerate_type.h"
41#include "aircraft_cmd.h"
42#include "vehicle_cmd.h"
43
44#include "table/strings.h"
45
46#include "safeguards.h"
47
48 void Aircraft::UpdateDeltaXY()
49{
50 this->bounds = {{-1, -1, 0}, {2, 2, 0}, {}};
51
52 switch (this->subtype) {
53 default: NOT_REACHED();
54
55 case AIR_AIRCRAFT:
56 case AIR_HELICOPTER:
57 switch (this->state) {
58 default: break;
59 case ENDTAKEOFF:
60 case LANDING:
61 case HELILANDING:
62 case FLYING:
63 /* Bounds are not centred on the aircraft. */
64 this->bounds.extent.x = 24;
65 this->bounds.extent.y = 24;
66 break;
67 }
68 this->bounds.extent.z = 5;
69 break;
70
71 case AIR_SHADOW:
72 this->bounds.extent.z = 1;
73 this->bounds.origin = {};
74 break;
75
76 case AIR_ROTOR:
77 this->bounds.extent.z = 1;
78 break;
79 }
80}
81
82static bool AirportMove(Aircraft *v, const AirportFTAClass *apc);
83static bool AirportSetBlocks(Aircraft *v, const AirportFTA *current_pos, const AirportFTAClass *apc);
84static bool AirportHasBlock(Aircraft *v, const AirportFTA *current_pos, const AirportFTAClass *apc);
85static bool AirportFindFreeTerminal(Aircraft *v, const AirportFTAClass *apc);
86static bool AirportFindFreeHelipad(Aircraft *v, const AirportFTAClass *apc);
87static void CrashAirplane(Aircraft *v);
88
89static const SpriteID _aircraft_sprite[] = {
90 0x0EB5, 0x0EBD, 0x0EC5, 0x0ECD,
91 0x0ED5, 0x0EDD, 0x0E9D, 0x0EA5,
92 0x0EAD, 0x0EE5, 0x0F05, 0x0F0D,
93 0x0F15, 0x0F1D, 0x0F25, 0x0F2D,
94 0x0EED, 0x0EF5, 0x0EFD, 0x0F35,
95 0x0E9D, 0x0EA5, 0x0EAD, 0x0EB5,
96 0x0EBD, 0x0EC5
97};
98
99template <>
100bool IsValidImageIndex<VEH_AIRCRAFT>(uint8_t image_index)
101{
102 return image_index < lengthof(_aircraft_sprite);
103}
104
106 enum HelicopterRotorStates : uint8_t {
107 HRS_ROTOR_STOPPED,
108 HRS_ROTOR_MOVING_1,
109 HRS_ROTOR_MOVING_2,
110 HRS_ROTOR_MOVING_3,
111};
112
120 static StationID FindNearestHangar(const Aircraft *v)
121{
122 uint best = 0;
123 StationID index = StationID::Invalid();
124 TileIndex vtile = TileVirtXYClampedToMap(v->x_pos, v->y_pos);
125 const AircraftVehicleInfo *avi = AircraftVehInfo(v->engine_type);
126 uint max_range = v->acache.cached_max_range_sqr;
127
128 /* Determine destinations where it's coming from and where it's heading to */
129 const Station *last_dest = nullptr;
130 const Station *next_dest = nullptr;
131 if (max_range != 0) {
132 if (v->current_order.IsType(OT_GOTO_STATION) ||
133 (v->current_order.IsType(OT_GOTO_DEPOT) && !v->current_order.GetDepotActionType().Test(OrderDepotActionFlag::NearestDepot))) {
134 last_dest = Station::GetIfValid(v->last_station_visited);
135 next_dest = Station::GetIfValid(v->current_order.GetDestination().ToStationID());
136 } else {
137 last_dest = GetTargetAirportIfValid(v);
138 std::vector<StationID> next_station;
139 v->GetNextStoppingStation(next_station);
140 if (!next_station.empty()) next_dest = Station::GetIfValid(next_station.back());
141 }
142 }
143
144 for (const Station *st : Station::Iterate()) {
145 if (st->owner != v->owner || !st->facilities.Test(StationFacility::Airport) || !st->airport.HasHangar()) continue;
146
147 const AirportFTAClass *afc = st->airport.GetFTA();
148
149 /* don't crash the plane if we know it can't land at the airport */
150 if (afc->flags.Test(AirportFTAClass::Flag::ShortStrip) && (avi->subtype & AIR_FAST) && !_cheats.no_jetcrash.value) continue;
151
152 /* the plane won't land at any helicopter station */
153 if (!afc->flags.Test(AirportFTAClass::Flag::Airplanes) && (avi->subtype & AIR_CTOL)) continue;
154
155 /* Check if our last and next destinations can be reached from the depot airport. */
156 if (max_range != 0) {
157 uint last_dist = (last_dest != nullptr && last_dest->airport.tile != INVALID_TILE) ? DistanceSquare(st->airport.tile, last_dest->airport.tile) : 0;
158 uint next_dist = (next_dest != nullptr && next_dest->airport.tile != INVALID_TILE) ? DistanceSquare(st->airport.tile, next_dest->airport.tile) : 0;
159 if (last_dist > max_range || next_dist > max_range) continue;
160 }
161
162 /* v->tile can't be used here, when aircraft is flying v->tile is set to 0 */
163 uint distance = DistanceSquare(vtile, st->airport.tile);
164 if (distance < best || index == StationID::Invalid()) {
165 best = distance;
166 index = st->index;
167 }
168 }
169 return index;
170}
171
172 void Aircraft::GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const
173{
174 uint8_t spritenum = this->spritenum;
175
176 if (IsCustomVehicleSpriteNum(spritenum)) {
177 GetCustomVehicleSprite(this, direction, image_type, result);
178 if (result->IsValid()) return;
179
180 spritenum = this->GetEngine()->original_image_index;
181 }
182
183 assert(IsValidImageIndex<VEH_AIRCRAFT>(spritenum));
184 result->Set(direction + _aircraft_sprite[spritenum]);
185}
186
187void GetRotorImage(const Aircraft *v, EngineImageType image_type, VehicleSpriteSeq *result)
188{
189 assert(v->subtype == AIR_HELICOPTER);
190
191 const Aircraft *w = v->Next()->Next();
192 if (IsCustomVehicleSpriteNum(v->spritenum)) {
193 GetCustomRotorSprite(v, image_type, result);
194 if (result->IsValid()) return;
195 }
196
197 /* Return standard rotor sprites if there are no custom sprites for this helicopter */
198 result->Set(SPR_ROTOR_STOPPED + w->state);
199}
200
201static void GetAircraftIcon(EngineID engine, EngineImageType image_type, VehicleSpriteSeq *result)
202{
203 const Engine *e = Engine::Get(engine);
204 uint8_t spritenum = e->VehInfo<AircraftVehicleInfo>().image_index;
205
206 if (IsCustomVehicleSpriteNum(spritenum)) {
207 GetCustomVehicleIcon(engine, DIR_W, image_type, result);
208 if (result->IsValid()) return;
209
210 spritenum = e->original_image_index;
211 }
212
213 assert(IsValidImageIndex<VEH_AIRCRAFT>(spritenum));
214 result->Set(DIR_W + _aircraft_sprite[spritenum]);
215}
216
217void DrawAircraftEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
218{
219 VehicleSpriteSeq seq;
220 GetAircraftIcon(engine, image_type, &seq);
221
222 Rect rect;
223 seq.GetBounds(&rect);
224 preferred_x = Clamp(preferred_x,
225 left - UnScaleGUI(rect.left),
226 right - UnScaleGUI(rect.right));
227
228 seq.Draw(preferred_x, y, pal, pal == PALETTE_CRASH);
229
230 if (!(AircraftVehInfo(engine)->subtype & AIR_CTOL)) {
231 VehicleSpriteSeq rotor_seq;
232 GetCustomRotorIcon(engine, image_type, &rotor_seq);
233 if (!rotor_seq.IsValid()) rotor_seq.Set(SPR_ROTOR_STOPPED);
234 rotor_seq.Draw(preferred_x, y - ScaleSpriteTrad(5), PAL_NONE, false);
235 }
236}
237
247 void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
248{
249 VehicleSpriteSeq seq;
250 GetAircraftIcon(engine, image_type, &seq);
251
252 Rect rect;
253 seq.GetBounds(&rect);
254
255 width = UnScaleGUI(rect.Width());
256 height = UnScaleGUI(rect.Height());
257 xoffs = UnScaleGUI(rect.left);
258 yoffs = UnScaleGUI(rect.top);
259}
260
269 CommandCost CmdBuildAircraft(DoCommandFlags flags, TileIndex tile, const Engine *e, Vehicle **ret)
270{
271 const AircraftVehicleInfo *avi = &e->VehInfo<AircraftVehicleInfo>();
272 const Station *st = Station::GetByTile(tile);
273
274 /* Prevent building aircraft types at places which can't handle them */
275 if (!CanVehicleUseStation(e->index, st)) return CMD_ERROR;
276
277 /* Make sure all aircraft end up in the first tile of the hangar. */
278 tile = st->airport.GetHangarTile(st->airport.GetHangarNum(tile));
279
280 if (flags.Test(DoCommandFlag::Execute)) {
281 Aircraft *v = new Aircraft(); // aircraft
282 Aircraft *u = new Aircraft(); // shadow
283 *ret = v;
284
285 v->direction = DIR_SE;
286
287 v->owner = u->owner = _current_company;
288
289 v->tile = tile;
290
291 uint x = TileX(tile) * TILE_SIZE + 5;
292 uint y = TileY(tile) * TILE_SIZE + 3;
293
294 v->x_pos = u->x_pos = x;
295 v->y_pos = u->y_pos = y;
296
297 u->z_pos = GetSlopePixelZ(x, y);
298 v->z_pos = u->z_pos + 1;
299
300 v->vehstatus = {VehState::Hidden, VehState::Stopped, VehState::DefaultPalette};
301 u->vehstatus = {VehState::Hidden, VehState::Unclickable, VehState::Shadow};
302
303 v->spritenum = avi->image_index;
304
305 v->cargo_cap = avi->passenger_capacity;
306 v->refit_cap = 0;
307 u->refit_cap = 0;
308
309 v->cargo_type = e->GetDefaultCargoType();
310 assert(IsValidCargoType(v->cargo_type));
311
312 CargoType mail = GetCargoTypeByLabel(CT_MAIL);
313 if (IsValidCargoType(mail)) {
314 u->cargo_type = mail;
315 u->cargo_cap = avi->mail_capacity;
316 }
317
318 v->name.clear();
319 v->last_station_visited = StationID::Invalid();
320 v->last_loading_station = StationID::Invalid();
321
322 v->acceleration = avi->acceleration;
323 v->engine_type = e->index;
324 u->engine_type = e->index;
325
326 v->subtype = (avi->subtype & AIR_CTOL ? AIR_AIRCRAFT : AIR_HELICOPTER);
327 v->UpdateDeltaXY();
328
329 u->subtype = AIR_SHADOW;
330 u->UpdateDeltaXY();
331
332 v->reliability = e->reliability;
333 v->reliability_spd_dec = e->reliability_spd_dec;
334 v->max_age = e->GetLifeLengthInDays();
335
336 v->pos = GetVehiclePosOnBuild(tile);
337
338 v->state = HANGAR;
339 v->previous_pos = v->pos;
340 v->targetairport = GetStationIndex(tile);
341 v->SetNext(u);
342
343 v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_aircraft);
344
345 v->date_of_last_service = TimerGameEconomy::date;
346 v->date_of_last_service_newgrf = TimerGameCalendar::date;
347 v->build_year = u->build_year = TimerGameCalendar::year;
348
349 v->sprite_cache.sprite_seq.Set(SPR_IMG_QUERY);
350 u->sprite_cache.sprite_seq.Set(SPR_IMG_QUERY);
351
352 v->random_bits = Random();
353 u->random_bits = Random();
354
355 v->vehicle_flags = {};
356 if (e->flags.Test(EngineFlag::ExclusivePreview)) v->vehicle_flags.Set(VehicleFlag::BuiltAsPrototype);
357 v->SetServiceIntervalIsPercent(Company::Get(_current_company)->settings.vehicle.servint_ispercent);
358
359 v->InvalidateNewGRFCacheOfChain();
360
361 v->cargo_cap = e->DetermineCapacity(v, &u->cargo_cap);
362
363 v->InvalidateNewGRFCacheOfChain();
364
365 UpdateAircraftCache(v, true);
366
367 v->UpdatePosition();
368 u->UpdatePosition();
369
370 /* Aircraft with 3 vehicles (chopper)? */
371 if (v->subtype == AIR_HELICOPTER) {
372 Aircraft *w = new Aircraft();
373 w->engine_type = e->index;
374 w->direction = DIR_N;
375 w->owner = _current_company;
376 w->x_pos = v->x_pos;
377 w->y_pos = v->y_pos;
378 w->z_pos = v->z_pos + ROTOR_Z_OFFSET;
379 w->vehstatus = {VehState::Hidden, VehState::Unclickable};
380 w->spritenum = 0xFF;
381 w->subtype = AIR_ROTOR;
382 w->sprite_cache.sprite_seq.Set(SPR_ROTOR_STOPPED);
383 w->random_bits = Random();
384 /* Use rotor's air.state to store the rotor animation frame */
385 w->state = HRS_ROTOR_STOPPED;
386 w->UpdateDeltaXY();
387
388 u->SetNext(w);
389 w->UpdatePosition();
390 }
391 }
392
393 return CommandCost();
394}
395
396
397 ClosestDepot Aircraft::FindClosestDepot()
398{
399 const Station *st = GetTargetAirportIfValid(this);
400 /* If the station is not a valid airport or if it has no hangars */
401 if (st == nullptr || !CanVehicleUseStation(this, st) || !st->airport.HasHangar()) {
402 /* the aircraft has to search for a hangar on its own */
403 StationID station = FindNearestHangar(this);
404
405 if (station == StationID::Invalid()) return ClosestDepot();
406
407 st = Station::Get(station);
408 }
409
410 return ClosestDepot(st->xy, st->index);
411}
412
413static void CheckIfAircraftNeedsService(Aircraft *v)
414{
415 if (Company::Get(v->owner)->settings.vehicle.servint_aircraft == 0 || !v->NeedsAutomaticServicing()) return;
416 if (v->IsChainInDepot()) {
417 VehicleServiceInDepot(v);
418 return;
419 }
420
421 /* When we're parsing conditional orders and the like
422 * we don't want to consider going to a depot too. */
423 if (!v->current_order.IsType(OT_GOTO_DEPOT) && !v->current_order.IsType(OT_GOTO_STATION)) return;
424
425 const Station *st = Station::Get(v->current_order.GetDestination().ToStationID());
426
427 assert(st != nullptr);
428
429 /* only goto depot if the target airport has a depot */
430 if (st->airport.HasHangar() && CanVehicleUseStation(v, st)) {
431 v->current_order.MakeGoToDepot(st->index, OrderDepotTypeFlag::Service);
432 SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
433 } else if (v->current_order.IsType(OT_GOTO_DEPOT)) {
434 v->current_order.MakeDummy();
435 SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
436 }
437}
438
439 Money Aircraft::GetRunningCost() const
440{
441 const Engine *e = this->GetEngine();
442 uint cost_factor = GetVehicleProperty(this, PROP_AIRCRAFT_RUNNING_COST_FACTOR, e->VehInfo<AircraftVehicleInfo>().running_cost);
443 return GetPrice(PR_RUNNING_AIRCRAFT, cost_factor, e->GetGRF());
444}
445
447 void Aircraft::OnNewCalendarDay()
448{
449 if (!this->IsNormalAircraft()) return;
450 AgeVehicle(this);
451}
452
454 void Aircraft::OnNewEconomyDay()
455{
456 if (!this->IsNormalAircraft()) return;
457 EconomyAgeVehicle(this);
458
459 if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this);
460
461 CheckOrders(this);
462
463 CheckVehicleBreakdown(this);
464 CheckIfAircraftNeedsService(this);
465
466 if (this->running_ticks == 0) return;
467
468 CommandCost cost(EXPENSES_AIRCRAFT_RUN, this->GetRunningCost() * this->running_ticks / (CalendarTime::DAYS_IN_YEAR * Ticks::DAY_TICKS));
469
470 this->profit_this_year -= cost.GetCost();
471 this->running_ticks = 0;
472
473 SubtractMoneyFromCompanyFract(this->owner, cost);
474
475 SetWindowDirty(WC_VEHICLE_DETAILS, this->index);
476 SetWindowClassesDirty(WC_AIRCRAFT_LIST);
477}
478
479static void HelicopterTickHandler(Aircraft *v)
480{
481 Aircraft *u = v->Next()->Next();
482
483 if (u->vehstatus.Test(VehState::Hidden)) return;
484
485 /* if true, helicopter rotors do not rotate. This should only be the case if a helicopter is
486 * loading/unloading at a terminal or stopped */
487 if (v->current_order.IsType(OT_LOADING) || v->vehstatus.Test(VehState::Stopped)) {
488 if (u->cur_speed != 0) {
489 u->cur_speed++;
490 if (u->cur_speed >= 0x80 && u->state == HRS_ROTOR_MOVING_3) {
491 u->cur_speed = 0;
492 }
493 }
494 } else {
495 if (u->cur_speed == 0) {
496 u->cur_speed = 0x70;
497 }
498 if (u->cur_speed >= 0x50) {
499 u->cur_speed--;
500 }
501 }
502
503 int tick = ++u->tick_counter;
504 int spd = u->cur_speed >> 4;
505
506 VehicleSpriteSeq seq;
507 if (spd == 0) {
508 u->state = HRS_ROTOR_STOPPED;
509 GetRotorImage(v, EIT_ON_MAP, &seq);
510 if (u->sprite_cache.sprite_seq == seq) return;
511 } else if (tick >= spd) {
512 u->tick_counter = 0;
513 u->state++;
514 if (u->state > HRS_ROTOR_MOVING_3) u->state = HRS_ROTOR_MOVING_1;
515 GetRotorImage(v, EIT_ON_MAP, &seq);
516 } else {
517 return;
518 }
519
520 u->sprite_cache.sprite_seq = seq;
521
522 u->UpdatePositionAndViewport();
523}
524
532 void SetAircraftPosition(Aircraft *v, int x, int y, int z)
533{
534 v->x_pos = x;
535 v->y_pos = y;
536 v->z_pos = z;
537
538 v->UpdatePosition();
539 v->UpdateViewport(true, false);
540 if (v->subtype == AIR_HELICOPTER) {
541 GetRotorImage(v, EIT_ON_MAP, &v->Next()->Next()->sprite_cache.sprite_seq);
542 }
543
544 Aircraft *u = v->Next();
545
546 int safe_x = Clamp(x, 0, Map::MaxX() * TILE_SIZE);
547 int safe_y = Clamp(y - 1, 0, Map::MaxY() * TILE_SIZE);
548 u->x_pos = x;
549 u->y_pos = y - ((v->z_pos - GetSlopePixelZ(safe_x, safe_y)) >> 3);
550
551 safe_y = Clamp(u->y_pos, 0, Map::MaxY() * TILE_SIZE);
552 u->z_pos = GetSlopePixelZ(safe_x, safe_y);
553 u->sprite_cache.sprite_seq.CopyWithoutPalette(v->sprite_cache.sprite_seq); // the shadow is never coloured
554
555 u->UpdatePositionAndViewport();
556
557 u = u->Next();
558 if (u != nullptr) {
559 u->x_pos = x;
560 u->y_pos = y;
561 u->z_pos = z + ROTOR_Z_OFFSET;
562
563 u->UpdatePositionAndViewport();
564 }
565}
566
571 void HandleAircraftEnterHangar(Aircraft *v)
572{
573 v->subspeed = 0;
574 v->progress = 0;
575
576 Aircraft *u = v->Next();
577 u->vehstatus.Set(VehState::Hidden);
578 u = u->Next();
579 if (u != nullptr) {
580 u->vehstatus.Set(VehState::Hidden);
581 u->cur_speed = 0;
582 }
583
584 SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos);
585}
586
587static void PlayAircraftSound(const Vehicle *v)
588{
589 if (!PlayVehicleSound(v, VSE_START)) {
590 SndPlayVehicleFx(AircraftVehInfo(v->engine_type)->sfx, v);
591 }
592}
593
594
601 void UpdateAircraftCache(Aircraft *v, bool update_range)
602{
603 uint max_speed = GetVehicleProperty(v, PROP_AIRCRAFT_SPEED, 0);
604 if (max_speed != 0) {
605 /* Convert from original units to km-ish/h */
606 max_speed = (max_speed * 128) / 10;
607
608 v->vcache.cached_max_speed = max_speed;
609 } else {
610 /* Use the default max speed of the vehicle. */
611 v->vcache.cached_max_speed = AircraftVehInfo(v->engine_type)->max_speed;
612 }
613
614 /* Update cargo aging period. */
615 v->vcache.cached_cargo_age_period = GetVehicleProperty(v, PROP_AIRCRAFT_CARGO_AGE_PERIOD, EngInfo(v->engine_type)->cargo_age_period);
616 Aircraft *u = v->Next(); // Shadow for mail
617 u->vcache.cached_cargo_age_period = GetVehicleProperty(u, PROP_AIRCRAFT_CARGO_AGE_PERIOD, EngInfo(u->engine_type)->cargo_age_period);
618
619 /* Update aircraft range. */
620 if (update_range) {
621 v->acache.cached_max_range = GetVehicleProperty(v, PROP_AIRCRAFT_RANGE, AircraftVehInfo(v->engine_type)->max_range);
622 /* Squared it now so we don't have to do it later all the time. */
623 v->acache.cached_max_range_sqr = v->acache.cached_max_range * v->acache.cached_max_range;
624 }
625}
626
627
631 static constexpr uint16_t SPEED_LIMIT_TAXI = 50;
632 static constexpr uint16_t SPEED_LIMIT_APPROACH = 230;
633 static constexpr uint16_t SPEED_LIMIT_BROKEN = 320;
634 static constexpr uint16_t SPEED_LIMIT_HOLD = 425;
635 static constexpr uint16_t SPEED_LIMIT_NONE = UINT16_MAX;
636
644 static int UpdateAircraftSpeed(Aircraft *v, uint speed_limit = SPEED_LIMIT_NONE, bool hard_limit = true)
645{
653 uint spd = v->acceleration * 77;
654 uint8_t t;
655
656 /* Adjust speed limits by plane speed factor to prevent taxiing
657 * and take-off speeds being too low. */
658 speed_limit *= _settings_game.vehicle.plane_speed;
659
660 /* adjust speed for broken vehicles */
661 if (v->vehstatus.Test(VehState::AircraftBroken)) {
662 if (SPEED_LIMIT_BROKEN < speed_limit) hard_limit = false;
663 speed_limit = std::min<uint>(speed_limit, SPEED_LIMIT_BROKEN);
664 }
665
666 if (v->vcache.cached_max_speed < speed_limit) {
667 if (v->cur_speed < speed_limit) hard_limit = false;
668 speed_limit = v->vcache.cached_max_speed;
669 }
670
671 v->subspeed = (t = v->subspeed) + (uint8_t)spd;
672
673 /* Aircraft's current speed is used twice so that very fast planes are
674 * forced to slow down rapidly in the short distance needed. The magic
675 * value 16384 was determined to give similar results to the old speed/48
676 * method at slower speeds. This also results in less reduction at slow
677 * speeds to that aircraft do not get to taxi speed straight after
678 * touchdown. */
679 if (!hard_limit && v->cur_speed > speed_limit) {
680 speed_limit = v->cur_speed - std::max(1, ((v->cur_speed * v->cur_speed) / 16384) / _settings_game.vehicle.plane_speed);
681 }
682
683 spd = std::min(v->cur_speed + (spd >> 8) + (v->subspeed < t), speed_limit);
684
685 /* updates statusbar only if speed have changed to save CPU time */
686 if (spd != v->cur_speed) {
687 v->cur_speed = spd;
688 SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
689 }
690
691 /* Adjust distance moved by plane speed setting */
692 if (_settings_game.vehicle.plane_speed > 1) spd /= _settings_game.vehicle.plane_speed;
693
694 /* Convert direction-independent speed into direction-dependent speed. (old movement method) */
695 spd = v->GetOldAdvanceSpeed(spd);
696
697 spd += v->progress;
698 v->progress = (uint8_t)spd;
699 return spd >> 8;
700}
701
709 int GetTileHeightBelowAircraft(const Vehicle *v)
710{
711 int safe_x = Clamp(v->x_pos, 0, Map::MaxX() * TILE_SIZE);
712 int safe_y = Clamp(v->y_pos, 0, Map::MaxY() * TILE_SIZE);
713 return TileHeight(TileVirtXY(safe_x, safe_y)) * TILE_HEIGHT;
714}
715
726 void GetAircraftFlightLevelBounds(const Vehicle *v, int *min_level, int *max_level)
727{
728 int base_altitude = GetTileHeightBelowAircraft(v);
729 if (v->type == VEH_AIRCRAFT && Aircraft::From(v)->subtype == AIR_HELICOPTER) {
730 base_altitude += HELICOPTER_HOLD_MAX_FLYING_ALTITUDE - PLANE_HOLD_MAX_FLYING_ALTITUDE;
731 }
732
733 /* Make sure eastbound and westbound planes do not "crash" into each
734 * other by providing them with vertical separation
735 */
736 switch (v->direction) {
737 case DIR_N:
738 case DIR_NE:
739 case DIR_E:
740 case DIR_SE:
741 base_altitude += 10;
742 break;
743
744 default: break;
745 }
746
747 /* Make faster planes fly higher so that they can overtake slower ones */
748 base_altitude += std::min(20 * (v->vcache.cached_max_speed / 200) - 90, 0);
749
750 if (min_level != nullptr) *min_level = base_altitude + AIRCRAFT_MIN_FLYING_ALTITUDE;
751 if (max_level != nullptr) *max_level = base_altitude + AIRCRAFT_MAX_FLYING_ALTITUDE;
752}
753
761 int GetAircraftHoldMaxAltitude(const Aircraft *v)
762{
763 int tile_height = GetTileHeightBelowAircraft(v);
764
765 return tile_height + ((v->subtype == AIR_HELICOPTER) ? HELICOPTER_HOLD_MAX_FLYING_ALTITUDE : PLANE_HOLD_MAX_FLYING_ALTITUDE);
766}
767
768template <class T>
769int GetAircraftFlightLevel(T *v, bool takeoff)
770{
771 /* Aircraft is in flight. We want to enforce it being somewhere
772 * between the minimum and the maximum allowed altitude. */
773 int aircraft_min_altitude;
774 int aircraft_max_altitude;
775 GetAircraftFlightLevelBounds(v, &aircraft_min_altitude, &aircraft_max_altitude);
776 int aircraft_middle_altitude = (aircraft_min_altitude + aircraft_max_altitude) / 2;
777
778 /* If those assumptions would be violated, aircraft would behave fairly strange. */
779 assert(aircraft_min_altitude < aircraft_middle_altitude);
780 assert(aircraft_middle_altitude < aircraft_max_altitude);
781
782 int z = v->z_pos;
783 if (z < aircraft_min_altitude ||
784 (HasBit(v->flags, VAF_IN_MIN_HEIGHT_CORRECTION) && z < aircraft_middle_altitude)) {
785 /* Ascend. And don't fly into that mountain right ahead.
786 * And avoid our aircraft become a stairclimber, so if we start
787 * correcting altitude, then we stop correction not too early. */
788 SetBit(v->flags, VAF_IN_MIN_HEIGHT_CORRECTION);
789 z += takeoff ? 2 : 1;
790 } else if (!takeoff && (z > aircraft_max_altitude ||
791 (HasBit(v->flags, VAF_IN_MAX_HEIGHT_CORRECTION) && z > aircraft_middle_altitude))) {
792 /* Descend lower. You are an aircraft, not an space ship.
793 * And again, don't stop correcting altitude too early. */
794 SetBit(v->flags, VAF_IN_MAX_HEIGHT_CORRECTION);
795 z--;
796 } else if (HasBit(v->flags, VAF_IN_MIN_HEIGHT_CORRECTION) && z >= aircraft_middle_altitude) {
797 /* Now, we have corrected altitude enough. */
798 ClrBit(v->flags, VAF_IN_MIN_HEIGHT_CORRECTION);
799 } else if (HasBit(v->flags, VAF_IN_MAX_HEIGHT_CORRECTION) && z <= aircraft_middle_altitude) {
800 /* Now, we have corrected altitude enough. */
801 ClrBit(v->flags, VAF_IN_MAX_HEIGHT_CORRECTION);
802 }
803
804 return z;
805}
806
807template int GetAircraftFlightLevel(DisasterVehicle *v, bool takeoff);
808template int GetAircraftFlightLevel(Aircraft *v, bool takeoff);
809
824 static uint8_t AircraftGetEntryPoint(const Aircraft *v, const AirportFTAClass *apc, Direction rotation)
825{
826 assert(v != nullptr);
827 assert(apc != nullptr);
828
829 /* In the case the station doesn't exit anymore, set target tile 0.
830 * It doesn't hurt much, aircraft will go to next order, nearest hangar
831 * or it will simply crash in next tick */
832 TileIndex tile{};
833
834 const Station *st = Station::GetIfValid(v->targetairport);
835 if (st != nullptr) {
836 /* Make sure we don't go to INVALID_TILE if the airport has been removed. */
837 tile = (st->airport.tile != INVALID_TILE) ? st->airport.tile : st->xy;
838 }
839
840 int delta_x = v->x_pos - TileX(tile) * TILE_SIZE;
841 int delta_y = v->y_pos - TileY(tile) * TILE_SIZE;
842
843 DiagDirection dir;
844 if (abs(delta_y) < abs(delta_x)) {
845 /* We are northeast or southwest of the airport */
846 dir = delta_x < 0 ? DIAGDIR_NE : DIAGDIR_SW;
847 } else {
848 /* We are northwest or southeast of the airport */
849 dir = delta_y < 0 ? DIAGDIR_NW : DIAGDIR_SE;
850 }
851 dir = ChangeDiagDir(dir, DiagDirDifference(DIAGDIR_NE, DirToDiagDir(rotation)));
852 return apc->entry_points[dir];
853}
854
855
856static void MaybeCrashAirplane(Aircraft *v);
857
865 static bool AircraftController(Aircraft *v)
866{
867 /* nullptr if station is invalid */
868 const Station *st = Station::GetIfValid(v->targetairport);
869 /* INVALID_TILE if there is no station */
870 TileIndex tile = INVALID_TILE;
871 Direction rotation = DIR_N;
872 uint size_x = 1, size_y = 1;
873 if (st != nullptr) {
874 if (st->airport.tile != INVALID_TILE) {
875 tile = st->airport.tile;
876 rotation = st->airport.rotation;
877 size_x = st->airport.w;
878 size_y = st->airport.h;
879 } else {
880 tile = st->xy;
881 }
882 }
883 /* DUMMY if there is no station or no airport */
884 const AirportFTAClass *afc = tile == INVALID_TILE ? GetAirport(AT_DUMMY) : st->airport.GetFTA();
885
886 /* prevent going to INVALID_TILE if airport is deleted. */
887 if (st == nullptr || st->airport.tile == INVALID_TILE) {
888 /* Jump into our "holding pattern" state machine if possible */
889 if (v->pos >= afc->nofelements) {
890 v->pos = v->previous_pos = AircraftGetEntryPoint(v, afc, DIR_N);
891 } else if (v->targetairport != v->current_order.GetDestination()) {
892 /* If not possible, just get out of here fast */
893 v->state = FLYING;
894 UpdateAircraftCache(v);
895 AircraftNextAirportPos_and_Order(v);
896 /* get aircraft back on running altitude */
897 SetAircraftPosition(v, v->x_pos, v->y_pos, GetAircraftFlightLevel(v));
898 return false;
899 }
900 }
901
902 /* get airport moving data */
903 const AirportMovingData amd = RotateAirportMovingData(afc->MovingData(v->pos), rotation, size_x, size_y);
904
905 int x = TileX(tile) * TILE_SIZE;
906 int y = TileY(tile) * TILE_SIZE;
907
908 /* Helicopter raise */
909 if (amd.flags.Test(AirportMovingDataFlag::HeliRaise)) {
910 Aircraft *u = v->Next()->Next();
911
912 /* Make sure the rotors don't rotate too fast */
913 if (u->cur_speed > 32) {
914 v->cur_speed = 0;
915 if (--u->cur_speed == 32) {
916 if (!PlayVehicleSound(v, VSE_START)) {
917 SoundID sfx = AircraftVehInfo(v->engine_type)->sfx;
918 /* For compatibility with old NewGRF we ignore the sfx property, unless a NewGRF-defined sound is used.
919 * The baseset has only one helicopter sound, so this only limits using plane or cow sounds. */
920 if (sfx < ORIGINAL_SAMPLE_COUNT) sfx = SND_18_TAKEOFF_HELICOPTER;
921 SndPlayVehicleFx(sfx, v);
922 }
923 }
924 } else {
925 u->cur_speed = 32;
926 int count = UpdateAircraftSpeed(v);
927 if (count > 0) {
928 v->tile = TileIndex{};
929
930 int z_dest;
931 GetAircraftFlightLevelBounds(v, &z_dest, nullptr);
932
933 /* Reached altitude? */
934 if (v->z_pos >= z_dest) {
935 v->cur_speed = 0;
936 return true;
937 }
938 SetAircraftPosition(v, v->x_pos, v->y_pos, std::min(v->z_pos + count, z_dest));
939 }
940 }
941 return false;
942 }
943
944 /* Helicopter landing. */
945 if (amd.flags.Test(AirportMovingDataFlag::HeliLower)) {
946 SetBit(v->flags, VAF_HELI_DIRECT_DESCENT);
947
948 if (st == nullptr) {
949 v->state = FLYING;
950 UpdateAircraftCache(v);
951 AircraftNextAirportPos_and_Order(v);
952 return false;
953 }
954
955 /* Vehicle is now at the airport.
956 * Helicopter has arrived at the target landing pad, so the current position is also where it should land.
957 * Except for Oilrigs which are special due to being a 1x1 station, and helicopters land outside it. */
958 if (st->airport.type != AT_OILRIG) {
959 x = v->x_pos;
960 y = v->y_pos;
961 tile = TileVirtXY(x, y);
962 }
963 v->tile = tile;
964
965 /* Find altitude of landing position. */
966 int z = GetSlopePixelZ(x, y) + 1 + afc->delta_z;
967
968 if (z == v->z_pos) {
969 Vehicle *u = v->Next()->Next();
970
971 /* Increase speed of rotors. When speed is 80, we've landed. */
972 if (u->cur_speed >= 80) {
973 ClrBit(v->flags, VAF_HELI_DIRECT_DESCENT);
974 return true;
975 }
976 u->cur_speed += 4;
977 } else {
978 int count = UpdateAircraftSpeed(v);
979 if (count > 0) {
980 if (v->z_pos > z) {
981 SetAircraftPosition(v, v->x_pos, v->y_pos, std::max(v->z_pos - count, z));
982 } else {
983 SetAircraftPosition(v, v->x_pos, v->y_pos, std::min(v->z_pos + count, z));
984 }
985 }
986 }
987 return false;
988 }
989
990 /* Get distance from destination pos to current pos. */
991 uint dist = abs(x + amd.x - v->x_pos) + abs(y + amd.y - v->y_pos);
992
993 /* Need exact position? */
994 if (!amd.flags.Test(AirportMovingDataFlag::ExactPosition) && dist <= (amd.flags.Test(AirportMovingDataFlag::SlowTurn) ? 8U : 4U)) return true;
995
996 /* At final pos? */
997 if (dist == 0) {
998 /* Change direction smoothly to final direction. */
999 DirDiff dirdiff = DirDifference(amd.direction, v->direction);
1000 /* if distance is 0, and plane points in right direction, no point in calling
1001 * UpdateAircraftSpeed(). So do it only afterwards */
1002 if (dirdiff == DIRDIFF_SAME) {
1003 v->cur_speed = 0;
1004 return true;
1005 }
1006
1007 if (!UpdateAircraftSpeed(v, SPEED_LIMIT_TAXI)) return false;
1008
1009 v->direction = ChangeDir(v->direction, dirdiff > DIRDIFF_REVERSE ? DIRDIFF_45LEFT : DIRDIFF_45RIGHT);
1010 v->cur_speed >>= 1;
1011
1012 SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos);
1013 return false;
1014 }
1015
1016 if (amd.flags.Test(AirportMovingDataFlag::Brake) && v->cur_speed > SPEED_LIMIT_TAXI * _settings_game.vehicle.plane_speed) {
1017 MaybeCrashAirplane(v);
1018 if (v->vehstatus.Test(VehState::Crashed)) return false;
1019 }
1020
1021 uint speed_limit = SPEED_LIMIT_TAXI;
1022 bool hard_limit = true;
1023
1024 if (amd.flags.Test(AirportMovingDataFlag::NoSpeedClamp)) {
1025 speed_limit = SPEED_LIMIT_NONE;
1026 }
1027 if (amd.flags.Test(AirportMovingDataFlag::Hold)) {
1028 speed_limit = SPEED_LIMIT_HOLD;
1029 hard_limit = false;
1030 }
1031 if (amd.flags.Test(AirportMovingDataFlag::Land)) {
1032 speed_limit = SPEED_LIMIT_APPROACH;
1033 hard_limit = false;
1034 }
1035 if (amd.flags.Test(AirportMovingDataFlag::Brake)) {
1036 speed_limit = SPEED_LIMIT_TAXI;
1037 hard_limit = false;
1038 }
1039
1040 int count = UpdateAircraftSpeed(v, speed_limit, hard_limit);
1041 if (count == 0) return false;
1042
1043 /* If the plane will be a few subpixels away from the destination after
1044 * this movement loop, start nudging it towards the exact position for
1045 * the whole loop. Otherwise, heavily depending on the speed of the plane,
1046 * it is possible we totally overshoot the target, causing the plane to
1047 * make a loop, and trying again, and again, and again .. */
1048 bool nudge_towards_target = static_cast<uint>(count) + 3 > dist;
1049
1050 if (v->turn_counter != 0) v->turn_counter--;
1051
1052 do {
1053
1054 GetNewVehiclePosResult gp;
1055
1056 if (nudge_towards_target || amd.flags.Test(AirportMovingDataFlag::Land)) {
1057 /* move vehicle one pixel towards target */
1058 gp.x = (v->x_pos != (x + amd.x)) ?
1059 v->x_pos + ((x + amd.x > v->x_pos) ? 1 : -1) :
1060 v->x_pos;
1061 gp.y = (v->y_pos != (y + amd.y)) ?
1062 v->y_pos + ((y + amd.y > v->y_pos) ? 1 : -1) :
1063 v->y_pos;
1064
1065 /* Oilrigs must keep v->tile as st->airport.tile, since the landing pad is in a non-airport tile */
1066 gp.new_tile = (st->airport.type == AT_OILRIG) ? st->airport.tile : TileVirtXY(gp.x, gp.y);
1067
1068 } else {
1069
1070 /* Turn. Do it slowly if in the air. */
1071 Direction newdir = GetDirectionTowards(v, x + amd.x, y + amd.y);
1072 if (newdir != v->direction) {
1073 if (amd.flags.Test(AirportMovingDataFlag::SlowTurn) && v->number_consecutive_turns < 8 && v->subtype == AIR_AIRCRAFT) {
1074 if (v->turn_counter == 0 || newdir == v->last_direction) {
1075 if (newdir == v->last_direction) {
1076 v->number_consecutive_turns = 0;
1077 } else {
1078 v->number_consecutive_turns++;
1079 }
1080 v->turn_counter = 2 * _settings_game.vehicle.plane_speed;
1081 v->last_direction = v->direction;
1082 v->direction = newdir;
1083 }
1084
1085 /* Move vehicle. */
1086 gp = GetNewVehiclePos(v);
1087 } else {
1088 v->cur_speed >>= 1;
1089 v->direction = newdir;
1090
1091 /* When leaving a terminal an aircraft often goes to a position
1092 * directly in front of it. If it would move while turning it
1093 * would need an two extra turns to end up at the correct position.
1094 * To make it easier just disallow all moving while turning as
1095 * long as an aircraft is on the ground. */
1096 gp.x = v->x_pos;
1097 gp.y = v->y_pos;
1098 gp.new_tile = gp.old_tile = v->tile;
1099 }
1100 } else {
1101 v->number_consecutive_turns = 0;
1102 /* Move vehicle. */
1103 gp = GetNewVehiclePos(v);
1104 }
1105 }
1106
1107 v->tile = gp.new_tile;
1108 /* If vehicle is in the air, use tile coordinate 0. */
1109 if (amd.flags.Any({AirportMovingDataFlag::Takeoff, AirportMovingDataFlag::SlowTurn, AirportMovingDataFlag::Land})) v->tile = TileIndex{};
1110
1111 /* Adjust Z for land or takeoff? */
1112 int z = v->z_pos;
1113
1114 if (amd.flags.Test(AirportMovingDataFlag::Takeoff)) {
1115 z = GetAircraftFlightLevel(v, true);
1116 } else if (amd.flags.Test(AirportMovingDataFlag::Hold)) {
1117 /* Let the plane drop from normal flight altitude to holding pattern altitude */
1118 if (z > GetAircraftHoldMaxAltitude(v)) z--;
1119 } else if (amd.flags.All({AirportMovingDataFlag::SlowTurn, AirportMovingDataFlag::NoSpeedClamp})) {
1120 z = GetAircraftFlightLevel(v);
1121 }
1122
1123 /* NewGRF airports (like a rotated intercontinental from OpenGFX+Airports) can be non-rectangular
1124 * and their primary (north-most) tile does not have to be part of the airport.
1125 * As such, the height of the primary tile can be different from the rest of the airport.
1126 * Given we are landing/breaking, and as such are not a helicopter, we know that there has to be a hangar.
1127 * We also know that the airport itself has to be completely flat (otherwise it is not a valid airport).
1128 * Therefore, use the height of this hangar to calculate our z-value. */
1129 int airport_z = v->z_pos;
1130 if (amd.flags.Any({AirportMovingDataFlag::Land, AirportMovingDataFlag::Brake}) && st != nullptr) {
1131 assert(st->airport.HasHangar());
1132 TileIndex hangar_tile = st->airport.GetHangarTile(0);
1133 airport_z = GetTileMaxPixelZ(hangar_tile) + 1; // To avoid clashing with the shadow
1134 }
1135
1136 if (amd.flags.Test(AirportMovingDataFlag::Land)) {
1137 if (st->airport.blocks.Test(AirportBlock::Zeppeliner)) {
1138 /* Zeppeliner blocked the runway, abort landing */
1139 v->state = FLYING;
1140 UpdateAircraftCache(v);
1141 SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlightLevel(v));
1142 v->pos = v->previous_pos;
1143 continue;
1144 }
1145
1146 if (st->airport.tile == INVALID_TILE) {
1147 /* Airport has been removed, abort the landing procedure */
1148 v->state = FLYING;
1149 UpdateAircraftCache(v);
1150 AircraftNextAirportPos_and_Order(v);
1151 /* get aircraft back on running altitude */
1152 SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlightLevel(v));
1153 continue;
1154 }
1155
1156 /* We're not flying below our destination, right? */
1157 assert(airport_z <= z);
1158 int t = std::max(1U, dist - 4);
1159 int delta = z - airport_z;
1160
1161 /* Only start lowering when we're sufficiently close for a 1:1 glide */
1162 if (delta >= t) {
1163 z -= CeilDiv(z - airport_z, t);
1164 }
1165 if (z < airport_z) z = airport_z;
1166 }
1167
1168 /* We've landed. Decrease speed when we're reaching end of runway. */
1169 if (amd.flags.Test(AirportMovingDataFlag::Brake)) {
1170
1171 if (z > airport_z) {
1172 z--;
1173 } else if (z < airport_z) {
1174 z++;
1175 }
1176
1177 }
1178
1179 SetAircraftPosition(v, gp.x, gp.y, z);
1180 } while (--count != 0);
1181 return false;
1182}
1183
1188 static bool HandleCrashedAircraft(Aircraft *v)
1189{
1190 v->crashed_counter += 3;
1191
1192 Station *st = GetTargetAirportIfValid(v);
1193
1194 /* make aircraft crash down to the ground */
1195 if (v->crashed_counter < 500 && st == nullptr && ((v->crashed_counter % 3) == 0)) {
1196 int z = GetSlopePixelZ(Clamp(v->x_pos, 0, Map::MaxX() * TILE_SIZE), Clamp(v->y_pos, 0, Map::MaxY() * TILE_SIZE));
1197 v->z_pos -= 1;
1198 if (v->z_pos <= z) {
1199 v->crashed_counter = 500;
1200 v->z_pos = z + 1;
1201 } else {
1202 v->crashed_counter = 0;
1203 }
1204 SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos);
1205 }
1206
1207 if (v->crashed_counter < 650) {
1208 uint32_t r;
1209 if (Chance16R(1, 32, r)) {
1210 static const DirDiff delta[] = {
1211 DIRDIFF_45LEFT, DIRDIFF_SAME, DIRDIFF_SAME, DIRDIFF_45RIGHT
1212 };
1213
1214 v->direction = ChangeDir(v->direction, delta[GB(r, 16, 2)]);
1215 SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos);
1216 r = Random();
1217 CreateEffectVehicleRel(v,
1218 GB(r, 0, 4) - 4,
1219 GB(r, 4, 4) - 4,
1220 GB(r, 8, 4),
1221 EV_EXPLOSION_SMALL);
1222 }
1223 } else if (v->crashed_counter >= 10000) {
1224 /* remove rubble of crashed airplane */
1225
1226 /* clear runway-in on all airports, set by crashing plane
1227 * small airports use AIRPORT_BUSY, city airports use AirportBlock::RunwayInOut, etc.
1228 * but they all share the same number */
1229 if (st != nullptr) {
1230 st->airport.blocks.Reset(AirportBlock::RunwayIn);
1231 st->airport.blocks.Reset(AirportBlock::RunwayInOut); // commuter airport
1232 st->airport.blocks.Reset(AirportBlock::RunwayIn2); // intercontinental
1233 }
1234
1235 delete v;
1236
1237 return false;
1238 }
1239
1240 return true;
1241}
1242
1243
1249 static void HandleAircraftSmoke(Aircraft *v, bool mode)
1250{
1251 static const struct {
1252 int8_t x;
1253 int8_t y;
1254 } smoke_pos[] = {
1255 { 5, 5 },
1256 { 6, 0 },
1257 { 5, -5 },
1258 { 0, -6 },
1259 { -5, -5 },
1260 { -6, 0 },
1261 { -5, 5 },
1262 { 0, 6 }
1263 };
1264
1265 if (!v->vehstatus.Test(VehState::AircraftBroken)) return;
1266
1267 /* Stop smoking when landed */
1268 if (v->cur_speed < 10) {
1269 v->vehstatus.Reset(VehState::AircraftBroken);
1270 v->breakdown_ctr = 0;
1271 return;
1272 }
1273
1274 /* Spawn effect et most once per Tick, i.e. !mode */
1275 if (!mode && (v->tick_counter & 0x0F) == 0) {
1276 CreateEffectVehicleRel(v,
1277 smoke_pos[v->direction].x,
1278 smoke_pos[v->direction].y,
1279 2,
1280 EV_BREAKDOWN_SMOKE_AIRCRAFT
1281 );
1282 }
1283}
1284
1285void HandleMissingAircraftOrders(Aircraft *v)
1286{
1287 /*
1288 * We do not have an order. This can be divided into two cases:
1289 * 1) we are heading to an invalid station. In this case we must
1290 * find another airport to go to. If there is nowhere to go,
1291 * we will destroy the aircraft as it otherwise will enter
1292 * the holding pattern for the first airport, which can cause
1293 * the plane to go into an undefined state when building an
1294 * airport with the same StationID.
1295 * 2) we are (still) heading to a (still) valid airport, then we
1296 * can continue going there. This can happen when you are
1297 * changing the aircraft's orders while in-flight or in for
1298 * example a depot. However, when we have a current order to
1299 * go to a depot, we have to keep that order so the aircraft
1300 * actually stops.
1301 */
1302 const Station *st = GetTargetAirportIfValid(v);
1303 if (st == nullptr) {
1304 Backup<CompanyID> cur_company(_current_company, v->owner);
1305 CommandCost ret = Command<CMD_SEND_VEHICLE_TO_DEPOT>::Do(DoCommandFlag::Execute, v->index, DepotCommandFlag{}, {});
1306 cur_company.Restore();
1307
1308 if (ret.Failed()) CrashAirplane(v);
1309 } else if (!v->current_order.IsType(OT_GOTO_DEPOT)) {
1310 v->current_order.Free();
1311 }
1312}
1313
1314
1315 TileIndex Aircraft::GetOrderStationLocation(StationID)
1316{
1317 /* Orders are changed in flight, ensure going to the right station. */
1318 if (this->state == FLYING) {
1319 AircraftNextAirportPos_and_Order(this);
1320 }
1321
1322 /* Aircraft do not use dest-tile */
1323 return TileIndex{};
1324}
1325
1326 void Aircraft::MarkDirty()
1327{
1328 this->colourmap = PAL_NONE;
1329 this->UpdateViewport(true, false);
1330 if (this->subtype == AIR_HELICOPTER) {
1331 GetRotorImage(this, EIT_ON_MAP, &this->Next()->Next()->sprite_cache.sprite_seq);
1332 }
1333}
1334
1335
1336uint Aircraft::Crash(bool flooded)
1337{
1338 uint victims = Vehicle::Crash(flooded) + 2; // pilots
1339 this->crashed_counter = flooded ? 9000 : 0; // max 10000, disappear pretty fast when flooded
1340
1341 return victims;
1342}
1343
1348 static void CrashAirplane(Aircraft *v)
1349{
1350 CreateEffectVehicleRel(v, 4, 4, 8, EV_EXPLOSION_LARGE);
1351
1352 uint victims = v->Crash();
1353
1354 v->cargo.Truncate();
1355 v->Next()->cargo.Truncate();
1356 const Station *st = GetTargetAirportIfValid(v);
1357 TileIndex vt = TileVirtXYClampedToMap(v->x_pos, v->y_pos);
1358
1359 EncodedString headline;
1360 if (st == nullptr) {
1361 headline = GetEncodedString(STR_NEWS_PLANE_CRASH_OUT_OF_FUEL, victims);
1362 } else {
1363 headline = GetEncodedString(STR_NEWS_AIRCRAFT_CRASH, victims, st->index);
1364 }
1365
1366 AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, vt, st == nullptr ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING, victims, v->owner));
1367 Game::NewEvent(new ScriptEventVehicleCrashed(v->index, vt, st == nullptr ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING, victims, v->owner));
1368
1369 NewsType newstype = NewsType::Accident;
1370 if (v->owner != _local_company) {
1371 newstype = NewsType::AccidentOther;
1372 }
1373
1374 AddTileNewsItem(std::move(headline), newstype, vt, st != nullptr ? st->index : StationID::Invalid());
1375
1376 ModifyStationRatingAround(vt, v->owner, -160, 30);
1377 if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v);
1378}
1379
1384 static void MaybeCrashAirplane(Aircraft *v)
1385{
1386
1387 Station *st = Station::Get(v->targetairport);
1388
1389 uint32_t prob;
1390 if (st->airport.GetFTA()->flags.Test(AirportFTAClass::Flag::ShortStrip) &&
1391 (AircraftVehInfo(v->engine_type)->subtype & AIR_FAST) &&
1392 !_cheats.no_jetcrash.value) {
1393 prob = 3276;
1394 } else {
1395 if (_settings_game.vehicle.plane_crashes == 0) return;
1396 prob = (0x4000 << _settings_game.vehicle.plane_crashes) / 1500;
1397 }
1398
1399 if (GB(Random(), 0, 22) > prob) return;
1400
1401 /* Crash the airplane. Remove all goods stored at the station. */
1402 for (GoodsEntry &ge : st->goods) {
1403 ge.rating = 1;
1404 if (ge.HasData()) ge.GetData().cargo.Truncate();
1405 }
1406
1407 CrashAirplane(v);
1408}
1409
1415 static void AircraftEntersTerminal(Aircraft *v)
1416{
1417 if (v->current_order.IsType(OT_GOTO_DEPOT)) return;
1418
1419 Station *st = Station::Get(v->targetairport);
1420 v->last_station_visited = v->targetairport;
1421
1422 /* Check if station was ever visited before */
1423 if (!(st->had_vehicle_of_type & HVOT_AIRCRAFT)) {
1424 st->had_vehicle_of_type |= HVOT_AIRCRAFT;
1425 /* show newsitem of celebrating citizens */
1426 AddVehicleNewsItem(
1427 GetEncodedString(STR_NEWS_FIRST_AIRCRAFT_ARRIVAL, st->index),
1428 (v->owner == _local_company) ? NewsType::ArrivalCompany : NewsType::ArrivalOther,
1429 v->index,
1430 st->index
1431 );
1432 AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index));
1433 Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index));
1434 }
1435
1436 v->BeginLoading();
1437}
1438
1443 static void AircraftLandAirplane(Aircraft *v)
1444{
1445 Station *st = Station::Get(v->targetairport);
1446
1447 TileIndex vt = TileVirtXY(v->x_pos, v->y_pos);
1448
1449 v->UpdateDeltaXY();
1450
1451 TriggerAirportTileAnimation(st, vt, AirportAnimationTrigger::AirplaneTouchdown);
1452
1453 if (!PlayVehicleSound(v, VSE_TOUCHDOWN)) {
1454 SndPlayVehicleFx(SND_17_SKID_PLANE, v);
1455 }
1456}
1457
1458
1460 void AircraftNextAirportPos_and_Order(Aircraft *v)
1461{
1462 if (v->current_order.IsType(OT_GOTO_STATION) || v->current_order.IsType(OT_GOTO_DEPOT)) {
1463 v->targetairport = v->current_order.GetDestination().ToStationID();
1464 }
1465
1466 const Station *st = GetTargetAirportIfValid(v);
1467 const AirportFTAClass *apc = st == nullptr ? GetAirport(AT_DUMMY) : st->airport.GetFTA();
1468 Direction rotation = st == nullptr ? DIR_N : st->airport.rotation;
1469 v->pos = v->previous_pos = AircraftGetEntryPoint(v, apc, rotation);
1470}
1471
1480 void AircraftLeaveHangar(Aircraft *v, Direction exit_dir)
1481{
1482 v->cur_speed = 0;
1483 v->subspeed = 0;
1484 v->progress = 0;
1485 v->direction = exit_dir;
1486 v->vehstatus.Reset(VehState::Hidden);
1487 {
1488 Vehicle *u = v->Next();
1489 u->vehstatus.Reset(VehState::Hidden);
1490
1491 /* Rotor blades */
1492 u = u->Next();
1493 if (u != nullptr) {
1494 u->vehstatus.Reset(VehState::Hidden);
1495 u->cur_speed = 80;
1496 }
1497 }
1498
1499 VehicleServiceInDepot(v);
1500 v->LeaveUnbunchingDepot();
1501 SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos);
1502 InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
1503 SetWindowClassesDirty(WC_AIRCRAFT_LIST);
1504}
1505
1509static void AircraftEventHandler_EnterTerminal(Aircraft *v, const AirportFTAClass *apc)
1510{
1511 AircraftEntersTerminal(v);
1512 v->state = apc->layout[v->pos].heading;
1513}
1514
1520 static void AircraftEventHandler_EnterHangar(Aircraft *v, const AirportFTAClass *apc)
1521{
1522 VehicleEnterDepot(v);
1523 v->state = apc->layout[v->pos].heading;
1524}
1525
1531 static void AircraftEventHandler_InHangar(Aircraft *v, const AirportFTAClass *apc)
1532{
1533 /* if we just arrived, execute EnterHangar first */
1534 if (v->previous_pos != v->pos) {
1535 AircraftEventHandler_EnterHangar(v, apc);
1536 return;
1537 }
1538
1539 /* if we were sent to the depot, stay there */
1540 if (v->current_order.IsType(OT_GOTO_DEPOT) && v->vehstatus.Test(VehState::Stopped)) {
1541 v->current_order.Free();
1542 return;
1543 }
1544
1545 /* Check if we should wait here for unbunching. */
1546 if (v->IsWaitingForUnbunching()) return;
1547
1548 if (!v->current_order.IsType(OT_GOTO_STATION) &&
1549 !v->current_order.IsType(OT_GOTO_DEPOT))
1550 return;
1551
1552 /* We are leaving a hangar, but have to go to the exact same one; re-enter */
1553 if (v->current_order.IsType(OT_GOTO_DEPOT) && v->current_order.GetDestination() == v->targetairport) {
1554 VehicleEnterDepot(v);
1555 return;
1556 }
1557
1558 /* if the block of the next position is busy, stay put */
1559 if (AirportHasBlock(v, &apc->layout[v->pos], apc)) return;
1560
1561 /* We are already at the target airport, we need to find a terminal */
1562 if (v->current_order.GetDestination() == v->targetairport) {
1563 /* FindFreeTerminal:
1564 * 1. Find a free terminal, 2. Occupy it, 3. Set the vehicle's state to that terminal */
1565 if (v->subtype == AIR_HELICOPTER) {
1566 if (!AirportFindFreeHelipad(v, apc)) return; // helicopter
1567 } else {
1568 if (!AirportFindFreeTerminal(v, apc)) return; // airplane
1569 }
1570 } else { // Else prepare for launch.
1571 /* airplane goto state takeoff, helicopter to helitakeoff */
1572 v->state = (v->subtype == AIR_HELICOPTER) ? HELITAKEOFF : TAKEOFF;
1573 }
1574 const Station *st = Station::GetByTile(v->tile);
1575 AircraftLeaveHangar(v, st->airport.GetHangarExitDirection(v->tile));
1576 AirportMove(v, apc);
1577}
1578
1580 static void AircraftEventHandler_AtTerminal(Aircraft *v, const AirportFTAClass *apc)
1581{
1582 /* if we just arrived, execute EnterTerminal first */
1583 if (v->previous_pos != v->pos) {
1584 AircraftEventHandler_EnterTerminal(v, apc);
1585 /* on an airport with helipads, a helicopter will always land there
1586 * and get serviced at the same time - setting */
1587 if (_settings_game.order.serviceathelipad) {
1588 if (v->subtype == AIR_HELICOPTER && apc->num_helipads > 0) {
1589 /* an excerpt of ServiceAircraft, without the invisibility stuff */
1590 v->date_of_last_service = TimerGameEconomy::date;
1591 v->date_of_last_service_newgrf = TimerGameCalendar::date;
1592 v->breakdowns_since_last_service = 0;
1593 v->reliability = v->GetEngine()->reliability;
1594 SetWindowDirty(WC_VEHICLE_DETAILS, v->index);
1595 }
1596 }
1597 return;
1598 }
1599
1600 if (v->current_order.IsType(OT_NOTHING)) return;
1601
1602 /* if the block of the next position is busy, stay put */
1603 if (AirportHasBlock(v, &apc->layout[v->pos], apc)) return;
1604
1605 /* airport-road is free. We either have to go to another airport, or to the hangar
1606 * ---> start moving */
1607
1608 bool go_to_hangar = false;
1609 switch (v->current_order.GetType()) {
1610 case OT_GOTO_STATION: // ready to fly to another airport
1611 break;
1612 case OT_GOTO_DEPOT: // visit hangar for servicing, sale, etc.
1613 go_to_hangar = v->current_order.GetDestination() == v->targetairport;
1614 break;
1615 case OT_CONDITIONAL:
1616 /* In case of a conditional order we just have to wait a tick
1617 * longer, so the conditional order can actually be processed;
1618 * we should not clear the order as that makes us go nowhere. */
1619 return;
1620 default: // orders have been deleted (no orders), goto depot and don't bother us
1621 v->current_order.Free();
1622 go_to_hangar = true;
1623 }
1624
1625 if (go_to_hangar && Station::Get(v->targetairport)->airport.HasHangar()) {
1626 v->state = HANGAR;
1627 } else {
1628 /* airplane goto state takeoff, helicopter to helitakeoff */
1629 v->state = (v->subtype == AIR_HELICOPTER) ? HELITAKEOFF : TAKEOFF;
1630 }
1631 AirportMove(v, apc);
1632}
1633
1634static void AircraftEventHandler_General(Aircraft *, const AirportFTAClass *)
1635{
1636 FatalError("OK, you shouldn't be here, check your Airport Scheme!");
1637}
1638
1639static void AircraftEventHandler_TakeOff(Aircraft *v, const AirportFTAClass *)
1640{
1641 PlayAircraftSound(v); // play takeoffsound for airplanes
1642 v->state = STARTTAKEOFF;
1643}
1644
1645static void AircraftEventHandler_StartTakeOff(Aircraft *v, const AirportFTAClass *)
1646{
1647 v->state = ENDTAKEOFF;
1648 v->UpdateDeltaXY();
1649}
1650
1651static void AircraftEventHandler_EndTakeOff(Aircraft *v, const AirportFTAClass *)
1652{
1653 v->state = FLYING;
1654 /* get the next position to go to, differs per airport */
1655 AircraftNextAirportPos_and_Order(v);
1656}
1657
1658static void AircraftEventHandler_HeliTakeOff(Aircraft *v, const AirportFTAClass *)
1659{
1660 v->state = FLYING;
1661 v->UpdateDeltaXY();
1662
1663 /* get the next position to go to, differs per airport */
1664 AircraftNextAirportPos_and_Order(v);
1665
1666 /* Send the helicopter to a hangar if needed for replacement */
1667 if (v->NeedsAutomaticServicing()) {
1668 Backup<CompanyID> cur_company(_current_company, v->owner);
1669 Command<CMD_SEND_VEHICLE_TO_DEPOT>::Do(DoCommandFlag::Execute, v->index, DepotCommandFlag::Service, {});
1670 cur_company.Restore();
1671 }
1672}
1673
1674static void AircraftEventHandler_Flying(Aircraft *v, const AirportFTAClass *apc)
1675{
1676 Station *st = Station::Get(v->targetairport);
1677
1678 /* Runway busy, not allowed to use this airstation or closed, circle. */
1679 if (CanVehicleUseStation(v, st) && (st->owner == OWNER_NONE || st->owner == v->owner) && !st->airport.blocks.Test(AirportBlock::AirportClosed)) {
1680 /* {32,FLYING,AirportBlock::Nothing,37}, {32,LANDING,N,33}, {32,HELILANDING,N,41},
1681 * if it is an airplane, look for LANDING, for helicopter HELILANDING
1682 * it is possible to choose from multiple landing runways, so loop until a free one is found */
1683 uint8_t landingtype = (v->subtype == AIR_HELICOPTER) ? HELILANDING : LANDING;
1684 const AirportFTA *current = apc->layout[v->pos].next.get();
1685 while (current != nullptr) {
1686 if (current->heading == landingtype) {
1687 /* save speed before, since if AirportHasBlock is false, it resets them to 0
1688 * we don't want that for plane in air
1689 * hack for speed thingy */
1690 uint16_t tcur_speed = v->cur_speed;
1691 uint16_t tsubspeed = v->subspeed;
1692 if (!AirportHasBlock(v, current, apc)) {
1693 v->state = landingtype; // LANDING / HELILANDING
1694 if (v->state == HELILANDING) SetBit(v->flags, VAF_HELI_DIRECT_DESCENT);
1695 /* it's a bit dirty, but I need to set position to next position, otherwise
1696 * if there are multiple runways, plane won't know which one it took (because
1697 * they all have heading LANDING). And also occupy that block! */
1698 v->pos = current->next_position;
1699 st->airport.blocks.Set(apc->layout[v->pos].blocks);
1700 return;
1701 }
1702 v->cur_speed = tcur_speed;
1703 v->subspeed = tsubspeed;
1704 }
1705 current = current->next.get();
1706 }
1707 }
1708 v->state = FLYING;
1709 v->pos = apc->layout[v->pos].next_position;
1710}
1711
1712static void AircraftEventHandler_Landing(Aircraft *v, const AirportFTAClass *)
1713{
1714 v->state = ENDLANDING;
1715 AircraftLandAirplane(v); // maybe crash airplane
1716
1717 /* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed */
1718 if (v->NeedsAutomaticServicing()) {
1719 Backup<CompanyID> cur_company(_current_company, v->owner);
1720 Command<CMD_SEND_VEHICLE_TO_DEPOT>::Do(DoCommandFlag::Execute, v->index, DepotCommandFlag::Service, {});
1721 cur_company.Restore();
1722 }
1723}
1724
1725static void AircraftEventHandler_HeliLanding(Aircraft *v, const AirportFTAClass *)
1726{
1727 v->state = HELIENDLANDING;
1728 v->UpdateDeltaXY();
1729}
1730
1731static void AircraftEventHandler_EndLanding(Aircraft *v, const AirportFTAClass *apc)
1732{
1733 /* next block busy, don't do a thing, just wait */
1734 if (AirportHasBlock(v, &apc->layout[v->pos], apc)) return;
1735
1736 /* if going to terminal (OT_GOTO_STATION) choose one
1737 * 1. in case all terminals are busy AirportFindFreeTerminal() returns false or
1738 * 2. not going for terminal (but depot, no order),
1739 * --> get out of the way to the hangar. */
1740 if (v->current_order.IsType(OT_GOTO_STATION)) {
1741 if (AirportFindFreeTerminal(v, apc)) return;
1742 }
1743 v->state = HANGAR;
1744
1745}
1746
1747static void AircraftEventHandler_HeliEndLanding(Aircraft *v, const AirportFTAClass *apc)
1748{
1749 /* next block busy, don't do a thing, just wait */
1750 if (AirportHasBlock(v, &apc->layout[v->pos], apc)) return;
1751
1752 /* if going to helipad (OT_GOTO_STATION) choose one. If airport doesn't have helipads, choose terminal
1753 * 1. in case all terminals/helipads are busy (AirportFindFreeHelipad() returns false) or
1754 * 2. not going for terminal (but depot, no order),
1755 * --> get out of the way to the hangar IF there are terminals on the airport.
1756 * --> else TAKEOFF
1757 * the reason behind this is that if an airport has a terminal, it also has a hangar. Airplanes
1758 * must go to a hangar. */
1759 if (v->current_order.IsType(OT_GOTO_STATION)) {
1760 if (AirportFindFreeHelipad(v, apc)) return;
1761 }
1762 v->state = Station::Get(v->targetairport)->airport.HasHangar() ? HANGAR : HELITAKEOFF;
1763}
1764
1770 typedef void AircraftStateHandler(Aircraft *v, const AirportFTAClass *apc);
1772 static AircraftStateHandler * const _aircraft_state_handlers[] = {
1773 AircraftEventHandler_General, // TO_ALL = 0
1774 AircraftEventHandler_InHangar, // HANGAR = 1
1775 AircraftEventHandler_AtTerminal, // TERM1 = 2
1776 AircraftEventHandler_AtTerminal, // TERM2 = 3
1777 AircraftEventHandler_AtTerminal, // TERM3 = 4
1778 AircraftEventHandler_AtTerminal, // TERM4 = 5
1779 AircraftEventHandler_AtTerminal, // TERM5 = 6
1780 AircraftEventHandler_AtTerminal, // TERM6 = 7
1781 AircraftEventHandler_AtTerminal, // HELIPAD1 = 8
1782 AircraftEventHandler_AtTerminal, // HELIPAD2 = 9
1783 AircraftEventHandler_TakeOff, // TAKEOFF = 10
1784 AircraftEventHandler_StartTakeOff, // STARTTAKEOFF = 11
1785 AircraftEventHandler_EndTakeOff, // ENDTAKEOFF = 12
1786 AircraftEventHandler_HeliTakeOff, // HELITAKEOFF = 13
1787 AircraftEventHandler_Flying, // FLYING = 14
1788 AircraftEventHandler_Landing, // LANDING = 15
1789 AircraftEventHandler_EndLanding, // ENDLANDING = 16
1790 AircraftEventHandler_HeliLanding, // HELILANDING = 17
1791 AircraftEventHandler_HeliEndLanding, // HELIENDLANDING = 18
1792 AircraftEventHandler_AtTerminal, // TERM7 = 19
1793 AircraftEventHandler_AtTerminal, // TERM8 = 20
1794 AircraftEventHandler_AtTerminal, // HELIPAD3 = 21
1795};
1796
1797static void AirportClearBlock(const Aircraft *v, const AirportFTAClass *apc)
1798{
1799 /* we have left the previous block, and entered the new one. Free the previous block */
1800 if (apc->layout[v->previous_pos].blocks != apc->layout[v->pos].blocks) {
1801 Station *st = Station::Get(v->targetairport);
1802
1803 if (st->airport.blocks.Test(AirportBlock::Zeppeliner) &&
1804 apc->layout[v->previous_pos].blocks == AirportBlock::RunwayIn) {
1805 return;
1806 }
1807
1808 st->airport.blocks.Reset(apc->layout[v->previous_pos].blocks);
1809 }
1810}
1811
1812static void AirportGoToNextPosition(Aircraft *v)
1813{
1814 /* if aircraft is not in position, wait until it is */
1815 if (!AircraftController(v)) return;
1816
1817 const AirportFTAClass *apc = Station::Get(v->targetairport)->airport.GetFTA();
1818
1819 AirportClearBlock(v, apc);
1820 AirportMove(v, apc); // move aircraft to next position
1821}
1822
1823/* gets pos from vehicle and next orders */
1824static bool AirportMove(Aircraft *v, const AirportFTAClass *apc)
1825{
1826 /* error handling */
1827 if (v->pos >= apc->nofelements) {
1828 Debug(misc, 0, "[Ap] position {} is not valid for current airport. Max position is {}", v->pos, apc->nofelements - 1);
1829 assert(v->pos < apc->nofelements);
1830 }
1831
1832 const AirportFTA *current = &apc->layout[v->pos];
1833 /* we have arrived in an important state (eg terminal, hangar, etc.) */
1834 if (current->heading == v->state) {
1835 uint8_t prev_pos = v->pos; // location could be changed in state, so save it before-hand
1836 uint8_t prev_state = v->state;
1837 _aircraft_state_handlers[v->state](v, apc);
1838 if (v->state != FLYING) v->previous_pos = prev_pos;
1839 if (v->state != prev_state || v->pos != prev_pos) UpdateAircraftCache(v);
1840 return true;
1841 }
1842
1843 v->previous_pos = v->pos; // save previous location
1844
1845 /* there is only one choice to move to */
1846 if (current->next == nullptr) {
1847 if (AirportSetBlocks(v, current, apc)) {
1848 v->pos = current->next_position;
1849 UpdateAircraftCache(v);
1850 } // move to next position
1851 return false;
1852 }
1853
1854 /* there are more choices to choose from, choose the one that
1855 * matches our heading */
1856 do {
1857 if (v->state == current->heading || current->heading == TO_ALL) {
1858 if (AirportSetBlocks(v, current, apc)) {
1859 v->pos = current->next_position;
1860 UpdateAircraftCache(v);
1861 } // move to next position
1862 return false;
1863 }
1864 current = current->next.get();
1865 } while (current != nullptr);
1866
1867 Debug(misc, 0, "[Ap] cannot move further on Airport! (pos {} state {}) for vehicle {}", v->pos, v->state, v->index);
1868 NOT_REACHED();
1869}
1870
1872 static bool AirportHasBlock(Aircraft *v, const AirportFTA *current_pos, const AirportFTAClass *apc)
1873{
1874 const AirportFTA *reference = &apc->layout[v->pos];
1875 const AirportFTA *next = &apc->layout[current_pos->next_position];
1876
1877 /* same block, then of course we can move */
1878 if (apc->layout[current_pos->position].blocks != next->blocks) {
1879 const Station *st = Station::Get(v->targetairport);
1880 AirportBlocks blocks = next->blocks;
1881
1882 /* check additional possible extra blocks */
1883 if (current_pos != reference && current_pos->blocks != AirportBlock::Nothing) {
1884 blocks.Set(current_pos->blocks);
1885 }
1886
1887 if (st->airport.blocks.Any(blocks)) {
1888 v->cur_speed = 0;
1889 v->subspeed = 0;
1890 return true;
1891 }
1892 }
1893 return false;
1894}
1895
1903 static bool AirportSetBlocks(Aircraft *v, const AirportFTA *current_pos, const AirportFTAClass *apc)
1904{
1905 const AirportFTA *next = &apc->layout[current_pos->next_position];
1906 const AirportFTA *reference = &apc->layout[v->pos];
1907
1908 /* if the next position is in another block, check it and wait until it is free */
1909 if (!apc->layout[current_pos->position].blocks.All(next->blocks)) {
1910 AirportBlocks blocks = next->blocks;
1911 /* search for all all elements in the list with the same state, and blocks != N
1912 * this means more blocks should be checked/set */
1913 const AirportFTA *current = current_pos;
1914 if (current == reference) current = current->next.get();
1915 while (current != nullptr) {
1916 if (current->heading == current_pos->heading && current->blocks.Any()) {
1917 blocks.Set(current->blocks);
1918 break;
1919 }
1920 current = current->next.get();
1921 }
1922
1923 /* if the block to be checked is in the next position, then exclude that from
1924 * checking, because it has been set by the airplane before */
1925 if (current_pos->blocks == next->blocks) blocks.Flip(next->blocks);
1926
1927 Station *st = Station::Get(v->targetairport);
1928 if (st->airport.blocks.Any(blocks)) {
1929 v->cur_speed = 0;
1930 v->subspeed = 0;
1931 return false;
1932 }
1933
1934 if (next->blocks != AirportBlock::Nothing) {
1935 st->airport.blocks.Set(blocks); // occupy next block
1936 }
1937 }
1938 return true;
1939}
1940
1945 struct MovementTerminalMapping {
1946 AirportMovementStates state;
1947 AirportBlock blocks;
1948};
1949
1951 static const MovementTerminalMapping _airport_terminal_mapping[] = {
1952 {TERM1, AirportBlock::Term1},
1953 {TERM2, AirportBlock::Term2},
1954 {TERM3, AirportBlock::Term3},
1955 {TERM4, AirportBlock::Term4},
1956 {TERM5, AirportBlock::Term5},
1957 {TERM6, AirportBlock::Term6},
1958 {TERM7, AirportBlock::Term7},
1959 {TERM8, AirportBlock::Term8},
1960 {HELIPAD1, AirportBlock::Helipad1},
1961 {HELIPAD2, AirportBlock::Helipad2},
1962 {HELIPAD3, AirportBlock::Helipad3},
1963};
1964
1972 static bool FreeTerminal(Aircraft *v, uint8_t i, uint8_t last_terminal)
1973{
1974 assert(last_terminal <= lengthof(_airport_terminal_mapping));
1975 Station *st = Station::Get(v->targetairport);
1976 for (; i < last_terminal; i++) {
1977 if (!st->airport.blocks.Any(_airport_terminal_mapping[i].blocks)) {
1978 /* TERMINAL# HELIPAD# */
1979 v->state = _airport_terminal_mapping[i].state; // start moving to that terminal/helipad
1980 st->airport.blocks.Set(_airport_terminal_mapping[i].blocks); // occupy terminal/helipad
1981 return true;
1982 }
1983 }
1984 return false;
1985}
1986
1992 static uint GetNumTerminals(const AirportFTAClass *apc)
1993{
1994 uint num = 0;
1995
1996 for (uint i = apc->terminals[0]; i > 0; i--) num += apc->terminals[i];
1997
1998 return num;
1999}
2000
2007 static bool AirportFindFreeTerminal(Aircraft *v, const AirportFTAClass *apc)
2008{
2009 /* example of more terminalgroups
2010 * {0,HANGAR,AirportBlock::Nothing,1}, {0,TERMGROUP,AirportBlock::TermGroup1,0}, {0,TERMGROUP,TERM_GROUP2_ENTER_block,1}, {0,0,N,1},
2011 * Heading TERMGROUP denotes a group. We see 2 groups here:
2012 * 1. group 0 -- AirportBlock::TermGroup1 (check block)
2013 * 2. group 1 -- TERM_GROUP2_ENTER_block (check block)
2014 * First in line is checked first, group 0. If the block (AirportBlock::TermGroup1) is free, it
2015 * looks at the corresponding terminals of that group. If no free ones are found, other
2016 * possible groups are checked (in this case group 1, since that is after group 0). If that
2017 * fails, then attempt fails and plane waits
2018 */
2019 if (apc->terminals[0] > 1) {
2020 const Station *st = Station::Get(v->targetairport);
2021 const AirportFTA *temp = apc->layout[v->pos].next.get();
2022
2023 while (temp != nullptr) {
2024 if (temp->heading == TERMGROUP) {
2025 if (!st->airport.blocks.Any(temp->blocks)) {
2026 /* read which group do we want to go to?
2027 * (the first free group) */
2028 uint target_group = temp->next_position + 1;
2029
2030 /* at what terminal does the group start?
2031 * that means, sum up all terminals of
2032 * groups with lower number */
2033 uint group_start = 0;
2034 for (uint i = 1; i < target_group; i++) {
2035 group_start += apc->terminals[i];
2036 }
2037
2038 uint group_end = group_start + apc->terminals[target_group];
2039 if (FreeTerminal(v, group_start, group_end)) return true;
2040 }
2041 } else {
2042 /* once the heading isn't 255, we've exhausted the possible blocks.
2043 * So we cannot move */
2044 return false;
2045 }
2046 temp = temp->next.get();
2047 }
2048 }
2049
2050 /* if there is only 1 terminalgroup, all terminals are checked (starting from 0 to max) */
2051 return FreeTerminal(v, 0, GetNumTerminals(apc));
2052}
2053
2060 static bool AirportFindFreeHelipad(Aircraft *v, const AirportFTAClass *apc)
2061{
2062 /* if an airport doesn't have helipads, use terminals */
2063 if (apc->num_helipads == 0) return AirportFindFreeTerminal(v, apc);
2064
2065 /* only 1 helicoptergroup, check all helipads
2066 * The blocks for helipads start after the last terminal (MAX_TERMINALS) */
2067 return FreeTerminal(v, MAX_TERMINALS, apc->num_helipads + MAX_TERMINALS);
2068}
2069
2075 static void AircraftHandleDestTooFar(Aircraft *v, bool too_far)
2076{
2077 if (too_far) {
2078 if (!HasBit(v->flags, VAF_DEST_TOO_FAR)) {
2079 SetBit(v->flags, VAF_DEST_TOO_FAR);
2080 SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
2081 AI::NewEvent(v->owner, new ScriptEventAircraftDestTooFar(v->index));
2082 if (v->owner == _local_company) {
2083 /* Post a news message. */
2084 AddVehicleAdviceNewsItem(AdviceType::AircraftDestinationTooFar, GetEncodedString(STR_NEWS_AIRCRAFT_DEST_TOO_FAR, v->index), v->index);
2085 }
2086 }
2087 return;
2088 }
2089
2090 if (HasBit(v->flags, VAF_DEST_TOO_FAR)) {
2091 /* Not too far anymore, clear flag and message. */
2092 ClrBit(v->flags, VAF_DEST_TOO_FAR);
2093 SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
2094 DeleteVehicleNews(v->index, AdviceType::AircraftDestinationTooFar);
2095 }
2096}
2097
2098static bool AircraftEventHandler(Aircraft *v, int loop)
2099{
2100 if (v->vehstatus.Test(VehState::Crashed)) {
2101 return HandleCrashedAircraft(v);
2102 }
2103
2104 if (v->vehstatus.Test(VehState::Stopped)) return true;
2105
2106 v->HandleBreakdown();
2107
2108 HandleAircraftSmoke(v, loop != 0);
2109 ProcessOrders(v);
2110 v->HandleLoading(loop != 0);
2111
2112 if (v->current_order.IsType(OT_LOADING) || v->current_order.IsType(OT_LEAVESTATION)) return true;
2113
2114 if (v->state >= ENDTAKEOFF && v->state <= HELIENDLANDING) {
2115 /* If we are flying, unconditionally clear the 'dest too far' state. */
2116 AircraftHandleDestTooFar(v, false);
2117 } else if (v->acache.cached_max_range_sqr != 0) {
2118 /* Check the distance to the next destination. This code works because the target
2119 * airport is only updated after take off and not on the ground. */
2120 Station *cur_st = Station::GetIfValid(v->targetairport);
2121 Station *next_st = v->current_order.IsType(OT_GOTO_STATION) || v->current_order.IsType(OT_GOTO_DEPOT) ? Station::GetIfValid(v->current_order.GetDestination().ToStationID()) : nullptr;
2122
2123 if (cur_st != nullptr && cur_st->airport.tile != INVALID_TILE && next_st != nullptr && next_st->airport.tile != INVALID_TILE) {
2124 uint dist = DistanceSquare(cur_st->airport.tile, next_st->airport.tile);
2125 AircraftHandleDestTooFar(v, dist > v->acache.cached_max_range_sqr);
2126 }
2127 }
2128
2129 if (!HasBit(v->flags, VAF_DEST_TOO_FAR)) AirportGoToNextPosition(v);
2130
2131 return true;
2132}
2133
2134 bool Aircraft::Tick()
2135{
2136 if (!this->IsNormalAircraft()) return true;
2137
2138 PerformanceAccumulator framerate(PFE_GL_AIRCRAFT);
2139
2140 this->tick_counter++;
2141
2142 if (!this->vehstatus.Test(VehState::Stopped)) this->running_ticks++;
2143
2144 if (this->subtype == AIR_HELICOPTER) HelicopterTickHandler(this);
2145
2146 this->current_order_time++;
2147
2148 for (uint i = 0; i != 2; i++) {
2149 /* stop if the aircraft was deleted */
2150 if (!AircraftEventHandler(this, i)) return false;
2151 }
2152
2153 return true;
2154}
2155
2156
2163 Station *GetTargetAirportIfValid(const Aircraft *v)
2164{
2165 assert(v->type == VEH_AIRCRAFT);
2166
2167 Station *st = Station::GetIfValid(v->targetairport);
2168 if (st == nullptr) return nullptr;
2169
2170 return st->airport.tile == INVALID_TILE ? nullptr : st;
2171}
2172
2177 void UpdateAirplanesOnNewStation(const Station *st)
2178{
2179 /* only 1 station is updated per function call, so it is enough to get entry_point once */
2180 const AirportFTAClass *ap = st->airport.GetFTA();
2181 Direction rotation = st->airport.tile == INVALID_TILE ? DIR_N : st->airport.rotation;
2182
2183 for (Aircraft *v : Aircraft::Iterate()) {
2184 if (!v->IsNormalAircraft() || v->targetairport != st->index) continue;
2185 assert(v->state == FLYING);
2186
2187 Order *o = &v->current_order;
2188 /* The aircraft is heading to a hangar, but the new station doesn't have one,
2189 * or the aircraft can't land on the new station. Cancel current order. */
2190 if (o->IsType(OT_GOTO_DEPOT) && !o->GetDepotOrderType().Test(OrderDepotTypeFlag::PartOfOrders) && o->GetDestination() == st->index &&
2191 (!st->airport.HasHangar() || !CanVehicleUseStation(v, st))) {
2192 o->MakeDummy();
2193 SetWindowWidgetDirty(WC_VEHICLE_VIEW, v->index, WID_VV_START_STOP);
2194 }
2195 v->pos = v->previous_pos = AircraftGetEntryPoint(v, ap, rotation);
2196 UpdateAircraftCache(v);
2197 }
2198
2199 /* Heliports don't have a hangar. Invalidate all go to hangar orders from all aircraft. */
2200 if (!st->airport.HasHangar()) RemoveOrderFromAllVehicles(OT_GOTO_DEPOT, st->index, true);
2201}
ai.hpp
Base functions for all AIs.
aircraft.h
Base for aircraft.
AIRCRAFT_MIN_FLYING_ALTITUDE
static constexpr int AIRCRAFT_MIN_FLYING_ALTITUDE
Base values for flight levels above ground level for 'normal' flight and holding patterns.
Definition aircraft.h:20
HELICOPTER_HOLD_MAX_FLYING_ALTITUDE
static constexpr int HELICOPTER_HOLD_MAX_FLYING_ALTITUDE
holding flying altitude above tile of helicopters.
Definition aircraft.h:23
ROTOR_Z_OFFSET
static const int ROTOR_Z_OFFSET
Z Offset between helicopter- and rotorsprite.
Definition aircraft.h:48
PLANE_HOLD_MAX_FLYING_ALTITUDE
static constexpr int PLANE_HOLD_MAX_FLYING_ALTITUDE
holding flying altitude above tile of planes.
Definition aircraft.h:22
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
VAF_HELI_DIRECT_DESCENT
@ VAF_HELI_DIRECT_DESCENT
The helicopter is descending directly at its destination (helipad or in front of hangar)
Definition aircraft.h:45
VAF_DEST_TOO_FAR
@ VAF_DEST_TOO_FAR
Next destination is too far away.
Definition aircraft.h:37
VAF_IN_MIN_HEIGHT_CORRECTION
@ VAF_IN_MIN_HEIGHT_CORRECTION
The vehicle is currently raising its altitude because it hit the lower bound.
Definition aircraft.h:43
VAF_IN_MAX_HEIGHT_CORRECTION
@ VAF_IN_MAX_HEIGHT_CORRECTION
The vehicle is currently lowering its altitude because it hit the upper bound.
Definition aircraft.h:42
AIR_AIRCRAFT
@ AIR_AIRCRAFT
an airplane
Definition aircraft.h:30
AIR_ROTOR
@ AIR_ROTOR
rotor of an helicopter
Definition aircraft.h:32
AIR_SHADOW
@ AIR_SHADOW
shadow of the aircraft
Definition aircraft.h:31
AIR_HELICOPTER
@ AIR_HELICOPTER
an helicopter
Definition aircraft.h:29
AIRCRAFT_MAX_FLYING_ALTITUDE
static constexpr int AIRCRAFT_MAX_FLYING_ALTITUDE
Maximum flying altitude above tile.
Definition aircraft.h:21
HandleAircraftSmoke
static void HandleAircraftSmoke(Aircraft *v, bool mode)
Handle smoke of broken aircraft.
Definition aircraft_cmd.cpp:1249
AircraftEventHandler_InHangar
static void AircraftEventHandler_InHangar(Aircraft *v, const AirportFTAClass *apc)
Handle aircraft movement/decision making in an airport hangar.
Definition aircraft_cmd.cpp:1531
FindNearestHangar
static StationID FindNearestHangar(const Aircraft *v)
Find the nearest hangar to v StationID::Invalid() is returned, if the company does not have any suita...
Definition aircraft_cmd.cpp:120
GetNumTerminals
static uint GetNumTerminals(const AirportFTAClass *apc)
Get the number of terminals at the airport.
Definition aircraft_cmd.cpp:1992
UpdateAirplanesOnNewStation
void UpdateAirplanesOnNewStation(const Station *st)
Updates the status of the Aircraft heading or in the station.
Definition aircraft_cmd.cpp:2177
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
GetTileHeightBelowAircraft
int GetTileHeightBelowAircraft(const Vehicle *v)
Get the tile height below the aircraft.
Definition aircraft_cmd.cpp:709
GetAircraftSpriteSize
void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
Get the size of the sprite of an aircraft sprite heading west (used for lists).
Definition aircraft_cmd.cpp:247
AircraftGetEntryPoint
static uint8_t AircraftGetEntryPoint(const Aircraft *v, const AirportFTAClass *apc, Direction rotation)
Find the entry point to an airport depending on direction which the airport is being approached from.
Definition aircraft_cmd.cpp:824
_airport_terminal_mapping
static const MovementTerminalMapping _airport_terminal_mapping[]
A list of all valid terminals and their associated blocks.
Definition aircraft_cmd.cpp:1951
AirportHasBlock
static bool AirportHasBlock(Aircraft *v, const AirportFTA *current_pos, const AirportFTAClass *apc)
returns true if the road ahead is busy, eg.
Definition aircraft_cmd.cpp:1872
AirportSetBlocks
static bool AirportSetBlocks(Aircraft *v, const AirportFTA *current_pos, const AirportFTAClass *apc)
"reserve" a block for the plane
Definition aircraft_cmd.cpp:1903
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
AircraftLandAirplane
static void AircraftLandAirplane(Aircraft *v)
Aircraft touched down at the landing strip.
Definition aircraft_cmd.cpp:1443
GetAircraftHoldMaxAltitude
int GetAircraftHoldMaxAltitude(const Aircraft *v)
Gets the maximum 'flight level' for the holding pattern of the aircraft, in pixels 'z_pos' 0,...
Definition aircraft_cmd.cpp:761
FreeTerminal
static bool FreeTerminal(Aircraft *v, uint8_t i, uint8_t last_terminal)
Find a free terminal or helipad, and if available, assign it.
Definition aircraft_cmd.cpp:1972
SPEED_LIMIT_BROKEN
static constexpr uint16_t SPEED_LIMIT_BROKEN
Maximum speed of an aircraft that is broken.
Definition aircraft_cmd.cpp:633
AircraftHandleDestTooFar
static void AircraftHandleDestTooFar(Aircraft *v, bool too_far)
Handle the 'dest too far' flag and the corresponding news message for aircraft.
Definition aircraft_cmd.cpp:2075
AircraftController
static bool AircraftController(Aircraft *v)
Controls the movement of an aircraft.
Definition aircraft_cmd.cpp:865
AircraftLeaveHangar
void AircraftLeaveHangar(Aircraft *v, Direction exit_dir)
Aircraft is about to leave the hangar.
Definition aircraft_cmd.cpp:1480
AirportFindFreeHelipad
static bool AirportFindFreeHelipad(Aircraft *v, const AirportFTAClass *apc)
Find a free helipad, and assign it if available.
Definition aircraft_cmd.cpp:2060
SPEED_LIMIT_NONE
static constexpr uint16_t SPEED_LIMIT_NONE
No environmental speed limit. Speed limit is type dependent.
Definition aircraft_cmd.cpp:635
AircraftEntersTerminal
static void AircraftEntersTerminal(Aircraft *v)
Aircraft arrives at a terminal.
Definition aircraft_cmd.cpp:1415
HelicopterRotorStates
HelicopterRotorStates
Helicopter rotor animation states.
Definition aircraft_cmd.cpp:106
AircraftEventHandler_AtTerminal
static void AircraftEventHandler_AtTerminal(Aircraft *v, const AirportFTAClass *apc)
At one of the Airport's Terminals.
Definition aircraft_cmd.cpp:1580
SetAircraftPosition
void SetAircraftPosition(Aircraft *v, int x, int y, int z)
Set aircraft position.
Definition aircraft_cmd.cpp:532
UpdateAircraftSpeed
static int UpdateAircraftSpeed(Aircraft *v, uint speed_limit=SPEED_LIMIT_NONE, bool hard_limit=true)
Sets the new speed for an aircraft.
Definition aircraft_cmd.cpp:644
MaybeCrashAirplane
static void MaybeCrashAirplane(Aircraft *v)
Decide whether aircraft v should crash.
Definition aircraft_cmd.cpp:1384
SPEED_LIMIT_HOLD
static constexpr uint16_t SPEED_LIMIT_HOLD
Maximum speed of an aircraft that flies the holding pattern.
Definition aircraft_cmd.cpp:634
GetAircraftFlightLevelBounds
void GetAircraftFlightLevelBounds(const Vehicle *v, int *min_level, int *max_level)
Get the 'flight level' bounds, in pixels from 'z_pos' 0 for a particular vehicle for normal flight si...
Definition aircraft_cmd.cpp:726
HandleCrashedAircraft
static bool HandleCrashedAircraft(Aircraft *v)
Handle crashed aircraft v.
Definition aircraft_cmd.cpp:1188
UpdateAircraftCache
void UpdateAircraftCache(Aircraft *v, bool update_range)
Update cached values of an aircraft.
Definition aircraft_cmd.cpp:601
_aircraft_state_handlers
static AircraftStateHandler *const _aircraft_state_handlers[]
Array of handler functions for each target of the aircraft.
Definition aircraft_cmd.cpp:1772
AircraftEventHandler_EnterHangar
static void AircraftEventHandler_EnterHangar(Aircraft *v, const AirportFTAClass *apc)
Aircraft arrived in an airport hangar.
Definition aircraft_cmd.cpp:1520
CmdBuildAircraft
CommandCost CmdBuildAircraft(DoCommandFlags flags, TileIndex tile, const Engine *e, Vehicle **ret)
Build an aircraft.
Definition aircraft_cmd.cpp:269
AirportFindFreeTerminal
static bool AirportFindFreeTerminal(Aircraft *v, const AirportFTAClass *apc)
Find a free terminal, and assign it if available.
Definition aircraft_cmd.cpp:2007
HandleAircraftEnterHangar
void HandleAircraftEnterHangar(Aircraft *v)
Handle Aircraft specific tasks when an Aircraft enters a hangar.
Definition aircraft_cmd.cpp:571
SPEED_LIMIT_APPROACH
static constexpr uint16_t SPEED_LIMIT_APPROACH
Maximum speed of an aircraft on finals.
Definition aircraft_cmd.cpp:632
CrashAirplane
static void CrashAirplane(Aircraft *v)
Bring the aircraft in a crashed state, create the explosion animation, and create a news item about t...
Definition aircraft_cmd.cpp:1348
SPEED_LIMIT_TAXI
static constexpr uint16_t SPEED_LIMIT_TAXI
Special velocities for aircraft.
Definition aircraft_cmd.cpp:631
AircraftStateHandler
void AircraftStateHandler(Aircraft *v, const AirportFTAClass *apc)
Signature of the aircraft handler function.
Definition aircraft_cmd.cpp:1770
aircraft_cmd.h
Command definitions related to aircraft.
GetVehiclePosOnBuild
uint8_t GetVehiclePosOnBuild(TileIndex hangar_tile)
Get the vehicle position when an aircraft is build at the given tile.
Definition airport.cpp:197
GetAirport
const AirportFTAClass * GetAirport(const uint8_t airport_type)
Get the finite state machine of an airport type.
Definition airport.cpp:186
RotateAirportMovingData
AirportMovingData RotateAirportMovingData(const AirportMovingData *orig, Direction rotation, uint num_tiles_x, uint num_tiles_y)
Rotate the airport moving data to another rotation.
Definition airport.cpp:81
MAX_TERMINALS
static const uint MAX_TERMINALS
Some airport-related constants.
Definition airport.h:17
AirportBlock
AirportBlock
Movement Blocks on Airports blocks (eg_airport_flags).
Definition airport.h:90
AirportBlock::Zeppeliner
@ Zeppeliner
Block for the zeppeliner disaster vehicle.
AirportBlock::Term2
@ Term2
Block belonging to terminal 2.
AirportBlock::AirportClosed
@ AirportClosed
Dummy block for indicating a closed airport.
AirportBlock::Term5
@ Term5
Block belonging to terminal 5.
AirportBlock::Term6
@ Term6
Block belonging to terminal 6.
AirportBlock::Term4
@ Term4
Block belonging to terminal 4.
AirportBlock::Helipad3
@ Helipad3
Block belonging to helipad 3.
AirportBlock::Term7
@ Term7
Block belonging to terminal 7.
AirportBlock::Helipad1
@ Helipad1
Block belonging to helipad 1.
AirportBlock::Term3
@ Term3
Block belonging to terminal 3.
AirportBlock::Term1
@ Term1
Block belonging to terminal 1.
AirportBlock::Helipad2
@ Helipad2
Block belonging to helipad 2.
AirportBlock::Term8
@ Term8
Block belonging to terminal 8.
AirportMovingDataFlag::HeliRaise
@ HeliRaise
Helicopter take-off.
AirportMovingDataFlag::HeliLower
@ HeliLower
Helicopter landing.
AirportMovingDataFlag::Land
@ Land
Landing onto landing strip.
AirportMovingDataFlag::Takeoff
@ Takeoff
Takeoff movement.
AirportMovingDataFlag::SlowTurn
@ SlowTurn
Turn slowly (mostly used in the air).
AirportMovingDataFlag::Brake
@ Brake
Taxiing at the airport.
AirportMovingDataFlag::NoSpeedClamp
@ NoSpeedClamp
No speed restrictions.
AirportMovingDataFlag::Hold
@ Hold
Holding pattern movement (above the airport).
AirportMovingDataFlag::ExactPosition
@ ExactPosition
Go exactly to the destination coordinates.
AirportMovementStates
AirportMovementStates
Movement States on Airports (headings target)
Definition airport.h:62
HELITAKEOFF
@ HELITAKEOFF
Helicopter wants to leave the airport.
Definition airport.h:76
TERM4
@ TERM4
Heading for terminal 4.
Definition airport.h:68
STARTTAKEOFF
@ STARTTAKEOFF
Airplane has arrived at a runway for take-off.
Definition airport.h:74
HELIPAD2
@ HELIPAD2
Heading for helipad 2.
Definition airport.h:72
ENDTAKEOFF
@ ENDTAKEOFF
Airplane has reached end-point of the take-off runway.
Definition airport.h:75
TERM5
@ TERM5
Heading for terminal 5.
Definition airport.h:69
TERM6
@ TERM6
Heading for terminal 6.
Definition airport.h:70
TERM3
@ TERM3
Heading for terminal 3.
Definition airport.h:67
TERM8
@ TERM8
Heading for terminal 8.
Definition airport.h:83
HELIPAD3
@ HELIPAD3
Heading for helipad 3.
Definition airport.h:84
HELIPAD1
@ HELIPAD1
Heading for helipad 1.
Definition airport.h:71
TERM2
@ TERM2
Heading for terminal 2.
Definition airport.h:66
HANGAR
@ HANGAR
Heading for hangar.
Definition airport.h:64
FLYING
@ FLYING
Vehicle is flying in the air.
Definition airport.h:77
TAKEOFF
@ TAKEOFF
Airplane wants to leave the airport.
Definition airport.h:73
HELILANDING
@ HELILANDING
Helicopter wants to land.
Definition airport.h:80
TO_ALL
@ TO_ALL
Go in this direction for every target.
Definition airport.h:63
ENDLANDING
@ ENDLANDING
Airplane wants to finish landing.
Definition airport.h:79
HELIENDLANDING
@ HELIENDLANDING
Helicopter wants to finish landing.
Definition airport.h:81
TERM1
@ TERM1
Heading for terminal 1.
Definition airport.h:65
LANDING
@ LANDING
Airplane wants to land.
Definition airport.h:78
TERM7
@ TERM7
Heading for terminal 7.
Definition airport.h:82
TERMGROUP
@ TERMGROUP
Aircraft is looking for a free terminal in a terminalgroup.
Definition airport.h:86
AT_DUMMY
@ AT_DUMMY
Dummy airport.
Definition airport.h:43
AT_OILRIG
@ AT_OILRIG
Oilrig airport.
Definition airport.h:38
backup_type.hpp
Class for backupping variables and making sure they are restored later.
VehicleFlag::BuiltAsPrototype
@ BuiltAsPrototype
Vehicle is a prototype (accepted as exclusive preview).
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
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
ClrBit
constexpr T ClrBit(T &x, const uint8_t y)
Clears a bit in a variable.
Definition bitmath_func.hpp:139
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
_cheats
Cheats _cheats
All the cheats.
Definition cheat.cpp:16
cheat_type.h
Types related to cheating.
AI::NewEvent
static void NewEvent(CompanyID company, ScriptEvent *event)
Queue a new event for an AI.
Definition ai_core.cpp:235
BaseBitSet::All
constexpr bool All(const Timpl &other) const
Test if all of the values are set.
Definition base_bitset_type.hpp:151
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::Flip
constexpr Timpl & Flip(Tvalue_type value)
Flip the value-th bit.
Definition base_bitset_type.hpp:116
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
CommandCost
Common return value for all commands.
Definition command_type.h:24
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
EncodedString
Container for an encoded string, created by GetEncodedString.
Definition strings_type.h:98
Engine
Definition engine_base.h:38
Engine::reliability_spd_dec
uint16_t reliability_spd_dec
Speed of reliability decay between services (per day).
Definition engine_base.h:50
Engine::GetGRF
const GRFFile * GetGRF() const
Retrieve the NewGRF the engine is tied to.
Definition engine_base.h:166
Engine::DetermineCapacity
uint DetermineCapacity(const Vehicle *v, uint16_t *mail_capacity=nullptr) const
Determines capacity of a given vehicle from scratch.
Definition engine.cpp:200
Engine::flags
EngineFlags flags
Flags of the engine.
Definition engine_base.h:57
Engine::original_image_index
uint8_t original_image_index
Original vehicle image index, thus the image index of the overridden vehicle.
Definition engine_base.h:61
Engine::GetLifeLengthInDays
TimerGameCalendar::Date GetLifeLengthInDays() const
Returns the vehicle's (not model's!) life length in days.
Definition engine.cpp:442
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
Game::NewEvent
static void NewEvent(class ScriptEvent *event)
Queue a new event for a Game Script.
Definition game_core.cpp:136
OverflowSafeInt< int64_t >
PerformanceAccumulator
RAII class for measuring multi-step elements of performance.
Definition framerate_type.h:113
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::year
static Year year
Current year, starting at 0.
Definition timer_game_calendar.h:31
TimerGameConst< struct Calendar >::DAYS_IN_YEAR
static constexpr int DAYS_IN_YEAR
days per year
Definition timer_game_common.h:149
TimerGameEconomy::date
static Date date
Current date in days (day counter).
Definition timer_game_economy.h:38
VehicleCargoList::Truncate
uint Truncate(uint max_move=UINT_MAX)
Truncates the cargo in this list to the given amount.
Definition cargopacket.cpp:648
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
company_base.h
Definition of stuff that is very close to a company, like the company struct itself.
_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
SubtractMoneyFromCompanyFract
void SubtractMoneyFromCompanyFract(CompanyID company, const CommandCost &cst)
Subtract money from a company, including the money fraction.
Definition company_cmd.cpp:324
company_func.h
Functions related to companies.
OWNER_NONE
static constexpr Owner OWNER_NONE
The tile has no ownership.
Definition company_type.h:26
Debug
#define Debug(category, level, format_string,...)
Output a line of debugging information.
Definition debug.h:37
DirDifference
DirDiff DirDifference(Direction d0, Direction d1)
Calculate the difference between two directions.
Definition direction_func.h:68
ChangeDir
Direction ChangeDir(Direction d, DirDiff delta)
Change a direction by a given difference.
Definition direction_func.h:104
ChangeDiagDir
DiagDirection ChangeDiagDir(DiagDirection d, DiagDirDiff delta)
Applies a difference on a DiagDirection.
Definition direction_func.h:149
DiagDirDifference
DiagDirDiff DiagDirDifference(DiagDirection d0, DiagDirection d1)
Calculate the difference between two DiagDirection values.
Definition direction_func.h:131
DirToDiagDir
DiagDirection DirToDiagDir(Direction dir)
Convert a Direction to a DiagDirection.
Definition direction_func.h:166
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
Direction
Direction
Defines the 8 directions on the map.
Definition direction_type.h:24
DIR_N
@ DIR_N
North.
Definition direction_type.h:26
DIR_SE
@ DIR_SE
Southeast.
Definition direction_type.h:29
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
DiagDirection
DiagDirection
Enumeration for diagonal directions.
Definition direction_type.h:78
DIAGDIR_NE
@ DIAGDIR_NE
Northeast, upper right on your monitor.
Definition direction_type.h:80
DIAGDIR_NW
@ DIAGDIR_NW
Northwest.
Definition direction_type.h:83
DIAGDIR_SE
@ DIAGDIR_SE
Southeast.
Definition direction_type.h:81
DIAGDIR_SW
@ DIAGDIR_SW
Southwest.
Definition direction_type.h:82
disaster_vehicle.h
All disaster vehicles.
GetPrice
Money GetPrice(Price index, uint cost_factor, const GRFFile *grf_file, int shift)
Determine a certain price.
Definition economy.cpp:949
EXPENSES_AIRCRAFT_RUN
@ EXPENSES_AIRCRAFT_RUN
Running costs aircraft.
Definition economy_type.h:183
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_func.h
Functions related to effect vehicles.
EV_EXPLOSION_SMALL
@ EV_EXPLOSION_SMALL
Various explosions.
Definition effectvehicle_func.h:24
EV_EXPLOSION_LARGE
@ EV_EXPLOSION_LARGE
Various explosions.
Definition effectvehicle_func.h:22
EV_BREAKDOWN_SMOKE_AIRCRAFT
@ EV_BREAKDOWN_SMOKE_AIRCRAFT
Smoke of broken aircraft.
Definition effectvehicle_func.h:27
engine_base.h
Base class for engines.
AIR_CTOL
@ AIR_CTOL
Conventional Take Off and Landing, i.e. planes.
Definition engine_type.h:127
EngineFlag::ExclusivePreview
@ ExclusivePreview
This vehicle is in the exclusive preview stage, either being used or being offered to a company.
error_func.h
Error reporting related functions.
settings
fluid_settings_t * settings
FluidSynth settings handle.
Definition fluidsynth.cpp:25
framerate_type.h
Types for recording game performance data.
PFE_GL_AIRCRAFT
@ PFE_GL_AIRCRAFT
Time spent processing aircraft.
Definition framerate_type.h:53
game.hpp
Base functions for all Games.
SpriteID
uint32_t SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition gfx_type.h:17
PaletteID
uint32_t PaletteID
The number of the palette.
Definition gfx_type.h:18
GetSlopePixelZ
int GetSlopePixelZ(int x, int y, bool ground_vehicle)
Return world Z coordinate of a given point of a tile.
Definition landscape.cpp:307
landscape.h
Functions related to OTTD's landscape.
BorderFlag::Random
@ Random
Randomise borders.
DistanceSquare
uint DistanceSquare(TileIndex t0, TileIndex t1)
Gets the 'Square' distance between the two given tiles.
Definition map.cpp:186
TileVirtXYClampedToMap
TileIndex TileVirtXYClampedToMap(int x, int y)
Get a tile from the virtual XY-coordinate.
Definition map.cpp:84
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:438
TileX
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition map_func.h:428
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
newgrf_airporttiles.h
NewGRF handling of airport tiles.
newgrf_engine.h
Functions for NewGRF engines.
PROP_AIRCRAFT_RANGE
@ PROP_AIRCRAFT_RANGE
Aircraft range.
Definition newgrf_properties.h:55
PROP_AIRCRAFT_RUNNING_COST_FACTOR
@ PROP_AIRCRAFT_RUNNING_COST_FACTOR
Yearly runningcost.
Definition newgrf_properties.h:51
PROP_AIRCRAFT_SPEED
@ PROP_AIRCRAFT_SPEED
Max. speed: 1 unit = 8 mph = 12.8 km-ish/h.
Definition newgrf_properties.h:50
PROP_AIRCRAFT_CARGO_AGE_PERIOD
@ PROP_AIRCRAFT_CARGO_AGE_PERIOD
Number of ticks before carried cargo is aged.
Definition newgrf_properties.h:54
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_TOUCHDOWN
@ VSE_TOUCHDOWN
Whenever a plane touches down.
Definition newgrf_sound.h:23
VSE_START
@ VSE_START
Vehicle starting, i.e. leaving, the station.
Definition newgrf_sound.h:19
news_func.h
Functions related to news.
AddVehicleNewsItem
void AddVehicleNewsItem(EncodedString &&headline, NewsType type, VehicleID vehicle, StationID station=StationID::Invalid())
Adds a newsitem referencing a vehicle.
Definition news_func.h:30
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
NewsType
NewsType
Type of news.
Definition news_type.h:29
NewsType::ArrivalCompany
@ ArrivalCompany
First vehicle arrived for company.
NewsType::AccidentOther
@ AccidentOther
An accident or disaster has occurred.
NewsType::ArrivalOther
@ ArrivalOther
First vehicle arrived for competitor.
NewsType::Accident
@ Accident
An accident or disaster has occurred.
AdviceType::AircraftDestinationTooFar
@ AircraftDestinationTooFar
Next (order) destination is too far for the aircraft type.
ProcessOrders
bool ProcessOrders(Vehicle *v)
Handle the orders of a vehicle and determine the next place to go to if needed.
Definition order_cmd.cpp:2078
CheckOrders
void CheckOrders(const Vehicle *v)
Check the orders of a vehicle, to see if there are invalid orders and stuff.
Definition order_cmd.cpp:1681
RemoveOrderFromAllVehicles
void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination, bool hangar)
Removes an order from all vehicles.
Definition order_cmd.cpp:1756
OrderDepotActionFlag::NearestDepot
@ NearestDepot
Send the vehicle to the nearest depot.
OrderDepotTypeFlag::PartOfOrders
@ PartOfOrders
This depot order is because of a regular order.
OrderDepotTypeFlag::Service
@ Service
This depot order is because of the servicing limit.
random_func.hpp
Pseudo random number generator.
Chance16R
bool Chance16R(const uint32_t a, const uint32_t b, uint32_t &r, const std::source_location location=std::source_location::current())
Flips a coin with a given probability and saves the randomize-number in a variable.
Definition random_func.hpp:154
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
sound_func.h
Functions related to sound.
ORIGINAL_SAMPLE_COUNT
static const uint ORIGINAL_SAMPLE_COUNT
The number of sounds in the original sample.cat.
Definition sound_type.h:124
SND_18_TAKEOFF_HELICOPTER
@ SND_18_TAKEOFF_HELICOPTER
22 == 0x16 Takeoff: helicopter
Definition sound_type.h:69
SND_17_SKID_PLANE
@ SND_17_SKID_PLANE
21 == 0x15 Plane landing / touching ground
Definition sound_type.h:68
SND_12_EXPLOSION
@ SND_12_EXPLOSION
16 == 0x10 Destruction, crashes, disasters, ...
Definition sound_type.h:63
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.
ModifyStationRatingAround
void ModifyStationRatingAround(TileIndex tile, Owner owner, int amount, uint radius)
Forcibly modify station ratings near a given tile.
Definition station_cmd.cpp:4388
GetStationIndex
StationID GetStationIndex(Tile t)
Get StationID from a tile.
Definition station_map.h:28
HVOT_AIRCRAFT
@ HVOT_AIRCRAFT
Station has seen an aircraft.
Definition station_type.h:69
StationFacility::Airport
@ Airport
Station with an airport.
AirportAnimationTrigger::AirplaneTouchdown
@ AirplaneTouchdown
Triggered when an airplane (not a helicopter) touches down at the airport (for single tile).
stdafx.h
Definition of base types and functions in a cross-platform compatible way.
lengthof
#define lengthof(array)
Return the length of an fixed size array.
Definition stdafx.h:271
GetEncodedString
EncodedString GetEncodedString(StringID str)
Encode a string with no parameters into an encoded string.
Definition strings.cpp:90
strings_func.h
Functions related to OTTD's strings.
AircraftCache::cached_max_range_sqr
uint32_t cached_max_range_sqr
Cached squared maximum range.
Definition aircraft.h:65
AircraftCache::cached_max_range
uint16_t cached_max_range
Cached maximum range.
Definition aircraft.h:66
AircraftVehicleInfo
Information about a aircraft vehicle.
Definition engine_type.h:132
AircraftVehicleInfo::max_speed
uint16_t max_speed
Maximum speed (1 unit = 8 mph = 12.8 km-ish/h)
Definition engine_type.h:138
AircraftVehicleInfo::mail_capacity
uint8_t mail_capacity
Mail capacity (bags).
Definition engine_type.h:140
AircraftVehicleInfo::subtype
uint8_t subtype
Type of aircraft.
Definition engine_type.h:136
AircraftVehicleInfo::passenger_capacity
uint16_t passenger_capacity
Passenger capacity (persons).
Definition engine_type.h:141
AircraftVehicleInfo::max_range
uint16_t max_range
Maximum range of this aircraft.
Definition engine_type.h:142
Aircraft
Aircraft, helicopters, rotors and their shadows belong to this class.
Definition aircraft.h:72
Aircraft::Tick
bool Tick() override
Calls the tick handler of the vehicle.
Definition aircraft_cmd.cpp:2134
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::flags
uint8_t flags
Aircraft flags.
Definition aircraft.h:81
Aircraft::GetRunningCost
Money GetRunningCost() const override
Gets the running cost of a vehicle.
Definition aircraft_cmd.cpp:439
Aircraft::UpdateDeltaXY
void UpdateDeltaXY() override
Updates the x and y offsets and the size of the sprite used for this vehicle.
Definition aircraft_cmd.cpp:48
Aircraft::number_consecutive_turns
uint8_t number_consecutive_turns
Protection to prevent the aircraft of making a lot of turns in order to reach a specific point.
Definition aircraft.h:79
Aircraft::OnNewEconomyDay
void OnNewEconomyDay() override
Economy day handler.
Definition aircraft_cmd.cpp:454
Aircraft::Crash
uint Crash(bool flooded=false) override
Crash the (whole) vehicle chain.
Definition aircraft_cmd.cpp:1336
Aircraft::GetImage
void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const override
Gets the sprite to show for the given direction.
Definition aircraft_cmd.cpp:172
Aircraft::OnNewCalendarDay
void OnNewCalendarDay() override
Calendar day handler.
Definition aircraft_cmd.cpp:447
Aircraft::turn_counter
uint8_t turn_counter
Ticks between each turn to prevent > 45 degree turns.
Definition aircraft.h:80
Aircraft::GetOrderStationLocation
TileIndex GetOrderStationLocation(StationID station) override
Determine the location for the station where the vehicle goes to next.
Definition aircraft_cmd.cpp:1315
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::MarkDirty
void MarkDirty() override
Marks the vehicles to be redrawn and updates cached variables.
Definition aircraft_cmd.cpp:1326
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
Aircraft::FindClosestDepot
ClosestDepot FindClosestDepot() override
Find the closest depot for this vehicle and tell us the location, DestinationID and whether we should...
Definition aircraft_cmd.cpp:397
Aircraft::crashed_counter
uint16_t crashed_counter
Timer for handling crash animations.
Definition aircraft.h:73
AirportFTAClass
Finite sTate mAchine (FTA) of an airport.
Definition airport.h:159
AirportFTAClass::num_helipads
const uint8_t num_helipads
Number of helipads on this airport. When 0 helicopters will go to normal terminals.
Definition airport.h:193
AirportFTAClass::MovingData
const AirportMovingData * MovingData(uint8_t position) const
Get movement data at a position.
Definition airport.h:184
AirportFTAClass::Flag::Airplanes
@ Airplanes
Can planes land on this airport type?
AirportFTAClass::Flag::ShortStrip
@ ShortStrip
This airport has a short landing strip, dangerous for fast aircraft.
AirportFTAClass::delta_z
uint8_t delta_z
Z adjustment for helicopter pads.
Definition airport.h:197
AirportFTAClass::layout
std::vector< AirportFTA > layout
state machine for airport
Definition airport.h:191
AirportFTAClass::terminals
const uint8_t * terminals
Array with the number of terminal groups, followed by the number of terminals in each group.
Definition airport.h:192
AirportFTAClass::entry_points
const uint8_t * entry_points
when an airplane arrives at this airport, enter it at position entry_point, index depends on directio...
Definition airport.h:196
AirportFTAClass::nofelements
uint8_t nofelements
number of positions the airport consists of
Definition airport.h:195
AirportFTAClass::flags
Flags flags
Flags for this airport type.
Definition airport.h:194
AirportFTA
Internal structure used in openttd - Finite sTate mAchine --> FTA.
Definition airport.h:148
AirportFTA::next
std::unique_ptr< AirportFTA > next
possible extra movement choices from this position
Definition airport.h:151
AirportFTA::heading
uint8_t heading
heading (current orders), guiding an airplane to its target on an airport
Definition airport.h:155
AirportFTA::blocks
AirportBlocks blocks
bitmap of blocks that could be reserved
Definition airport.h:152
AirportFTA::position
uint8_t position
the position that an airplane is at
Definition airport.h:153
AirportFTA::next_position
uint8_t next_position
next position from this position
Definition airport.h:154
AirportMovingData
A single location on an airport where aircraft can move to.
Definition airport.h:136
AirportMovingData::x
int16_t x
x-coordinate of the destination.
Definition airport.h:137
AirportMovingData::flags
AirportMovingDataFlags flags
special flags when moving towards the destination.
Definition airport.h:139
AirportMovingData::y
int16_t y
y-coordinate of the destination.
Definition airport.h:138
AirportMovingData::direction
Direction direction
Direction to turn the aircraft after reaching the destination.
Definition airport.h:140
Airport::blocks
AirportBlocks blocks
stores which blocks on the airport are taken. was 16 bit earlier on, then 32
Definition station_base.h:374
Airport::HasHangar
bool HasHangar() const
Check if this airport has at least one hangar.
Definition station_base.h:404
Airport::rotation
Direction rotation
How this airport is rotated.
Definition station_base.h:377
Airport::type
uint8_t type
Type of this airport,.
Definition station_base.h:375
Airport::GetHangarExitDirection
Direction GetHangarExitDirection(TileIndex tile) const
Get the exit direction of the hangar at a specific tile.
Definition station_base.h:455
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:398
Airport::GetHangarTile
TileIndex GetHangarTile(uint hangar_num) const
Get the first tile of the given hangar.
Definition station_base.h:439
Backup
Class to backup a specific variable and restore it later.
Definition backup_type.hpp:21
BaseConsist::name
std::string name
Name of vehicle.
Definition base_consist.h:34
BaseConsist::current_order_time
TimerGameTick::Ticks current_order_time
How many ticks have passed since this order started.
Definition base_consist.h:37
BaseConsist::vehicle_flags
VehicleFlags vehicle_flags
Used for gradual loading and other miscellaneous things (.
Definition base_consist.h:50
BaseStation::xy
TileIndex xy
Base tile of the station.
Definition base_station_base.h:59
BaseStation::owner
Owner owner
The owner of this station.
Definition base_station_base.h:68
BaseStation::GetByTile
static BaseStation * GetByTile(TileIndex tile)
Get the base station belonging to a specific tile.
Definition base_station_base.h:160
BaseVehicle::type
VehicleType type
Type of vehicle.
Definition vehicle_type.h:51
Cheat::value
bool value
tells if the bool cheat is active or not
Definition cheat_type.h:18
Cheats::no_jetcrash
Cheat no_jetcrash
no jet will crash on small airports anymore
Definition cheat_type.h:31
ClientSettings::sound
SoundSettings sound
sound effect settings
Definition settings_type.h:653
ClosestDepot
Structure to return information about the closest depot location, and whether it could be found.
Definition vehicle_base.h:192
CommandHelper
Definition command_func.h:84
Coord3D::x
T x
X coordinate.
Definition geometry_type.hpp:44
Coord3D::y
T y
Y coordinate.
Definition geometry_type.hpp:45
Coord3D::z
T z
Z coordinate.
Definition geometry_type.hpp:46
DisasterVehicle
Disasters, like submarines, skyrangers and their shadows, belong to this class.
Definition disaster_vehicle.h:37
EngineInfo::cargo_age_period
uint16_t cargo_age_period
Number of ticks before carried cargo is aged.
Definition engine_type.h:214
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
GoodsEntry
Stores station stats for a single cargo.
Definition station_base.h:167
Map::MaxY
static uint MaxY()
Gets the maximum Y coordinate within the map, including MP_VOID.
Definition map_func.h:308
Map::MaxX
static uint MaxX()
Gets the maximum X coordinate within the map, including MP_VOID.
Definition map_func.h:299
MovementTerminalMapping
Combination of aircraft state for going to a certain terminal and the airport flag for that terminal ...
Definition aircraft_cmd.cpp:1945
MovementTerminalMapping::blocks
AirportBlock blocks
Bitmask in the airport flags that need to be free for this terminal.
Definition aircraft_cmd.cpp:1947
MovementTerminalMapping::state
AirportMovementStates state
Aircraft movement state when going to this terminal.
Definition aircraft_cmd.cpp:1946
MutableSpriteCache::sprite_seq
VehicleSpriteSeq sprite_seq
Vehicle appearance.
Definition vehicle_base.h:162
OrderSettings::serviceathelipad
bool serviceathelipad
service helicopters at helipads automatically (no need to send to depot)
Definition settings_type.h:512
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::GetType
OrderType GetType() const
Get the type of order of this order.
Definition order_base.h:72
Order::MakeDummy
void MakeDummy()
Makes this order a Dummy order.
Definition order_cmd.cpp:116
Order::MakeGoToDepot
void MakeGoToDepot(DestinationID destination, OrderDepotTypeFlags order, OrderNonStopFlags non_stop_type=OrderNonStopFlag::NoIntermediate, OrderDepotActionFlags action={}, CargoType cargo=CARGO_NO_REFIT)
Makes this order a Go To Depot order.
Definition order_cmd.cpp:73
Order::GetDepotActionType
OrderDepotActionFlags GetDepotActionType() const
What are we going to do when in the depot.
Definition order_base.h:152
Order::Free
void Free()
'Free' the order
Definition order_cmd.cpp:47
OrthogonalTileArea::w
uint16_t w
The width of the area.
Definition tilearea_type.h:20
OrthogonalTileArea::tile
TileIndex tile
The base tile of the area.
Definition tilearea_type.h:19
OrthogonalTileArea::h
uint16_t h
The height of the area.
Definition tilearea_type.h:21
PoolID< uint16_t, struct StationIDTag, 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<&_engine_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
Rect
Specification of a rectangle with absolute coordinates of all edges.
Definition geometry_type.hpp:101
Rect::Width
int Width() const
Get width of Rect.
Definition geometry_type.hpp:111
Rect::Height
int Height() const
Get height of Rect.
Definition geometry_type.hpp:117
SoundSettings::disaster
bool disaster
Play disaster and accident sounds.
Definition settings_type.h:277
SpecializedStation< Station, false >::Iterate
static Pool::IterateWrapper< Station > Iterate(size_t from=0)
Returns an iterable ensemble of all valid stations of type T.
Definition base_station_base.h:299
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< Aircraft, VEH_AIRCRAFT >::From
static Aircraft * 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
SpriteBounds::origin
Coord3D< int8_t > origin
Position of northern corner within tile.
Definition sprite.h:19
SpriteBounds::extent
Coord3D< uint8_t > extent
Size of bounding box.
Definition sprite.h:20
Station
Station data structure.
Definition station_base.h:520
Station::goods
std::array< GoodsEntry, NUM_CARGO > goods
Goods at this station.
Definition station_base.h:549
Station::airport
Airport airport
Tile area the airport covers.
Definition station_base.h:534
StrongType::Typedef< uint32_t, struct TileIndexTag, StrongType::Compare, StrongType::Integer, StrongType::Compatible< int32_t >, StrongType::Compatible< int64_t > >
VehicleCache::cached_cargo_age_period
uint16_t cached_cargo_age_period
Number of ticks before carried cargo is aged.
Definition vehicle_base.h:94
VehicleCache::cached_max_speed
uint16_t cached_max_speed
Maximum speed of the consist (minimum of the max speed of all vehicles in the consist).
Definition vehicle_base.h:93
VehicleSettings::plane_crashes
uint8_t plane_crashes
number of plane crashes, 0 = none, 1 = reduced, 2 = normal
Definition settings_type.h:536
VehicleSettings::plane_speed
uint8_t plane_speed
divisor for speed of aircraft
Definition settings_type.h:530
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::GetBounds
void GetBounds(Rect *bounds) const
Determine shared bounds of all sprites.
Definition vehicle.cpp:114
VehicleSpriteSeq::Set
void Set(SpriteID sprite)
Assign a single sprite to the sequence.
Definition vehicle_base.h:130
VehicleSpriteSeq::CopyWithoutPalette
void CopyWithoutPalette(const VehicleSpriteSeq &src)
Copy data from another sprite sequence, while dropping all recolouring information.
Definition vehicle_base.h:140
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::engine_type
EngineID engine_type
The type of engine used for this vehicle.
Definition vehicle_base.h:278
Vehicle::z_pos
int32_t z_pos
z coordinate.
Definition vehicle_base.h:267
Vehicle::direction
Direction direction
facing
Definition vehicle_base.h:268
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::IsChainInDepot
virtual bool IsChainInDepot() const
Check whether the whole vehicle chain is in the depot.
Definition vehicle_base.h:509
Vehicle::cargo
VehicleCargoList cargo
The cargo this vehicle is carrying.
Definition vehicle_base.h:296
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::subtype
uint8_t subtype
subtype (Filled with values from AircraftSubType/DisasterSubType/EffectVehicleType/GroundVehicleSubty...
Definition vehicle_base.h:310
Vehicle::random_bits
uint16_t random_bits
Bits used for randomized variational spritegroups.
Definition vehicle_base.h:290
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::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::GetOldAdvanceSpeed
uint GetOldAdvanceSpeed(uint speed)
Determines the effective direction-specific vehicle movement speed.
Definition vehicle_base.h:383
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::subspeed
uint8_t subspeed
fractional speed
Definition vehicle_base.h:284
Vehicle::LeaveUnbunchingDepot
void LeaveUnbunchingDepot()
Leave an unbunching depot and calculate the next departure time for shared order vehicles.
Definition vehicle.cpp:2486
Vehicle::GetNextStoppingStation
void GetNextStoppingStation(std::vector< StationID > &next_station) const
Get the next station the vehicle will stop at.
Definition vehicle_base.h:717
Vehicle::cargo_type
CargoType cargo_type
type of cargo this vehicle is carrying
Definition vehicle_base.h:297
Vehicle::acceleration
uint8_t acceleration
used by train & aircraft
Definition vehicle_base.h:285
Vehicle::current_order
Order current_order
The current order (+ status, like: loading)
Definition vehicle_base.h:311
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::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::bounds
SpriteBounds bounds
Bounding box of vehicle.
Definition vehicle_base.h:277
Vehicle::BeginLoading
void BeginLoading()
Prepare everything to begin the loading when arriving at a station.
Definition vehicle.cpp:2183
Vehicle::spritenum
uint8_t spritenum
currently displayed sprite index 0xfd == custom sprite, 0xfe == custom second head sprite 0xff == res...
Definition vehicle_base.h:276
Vehicle::cur_speed
uint16_t cur_speed
current speed
Definition vehicle_base.h:283
Vehicle::IsWaitingForUnbunching
bool IsWaitingForUnbunching() const
Check whether a vehicle inside a depot is waiting for unbunching.
Definition vehicle.cpp:2533
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::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::HandleBreakdown
bool HandleBreakdown()
Handle all of the aspects of a vehicle breakdown This includes adding smoke and sounds,...
Definition vehicle.cpp:1332
Vehicle::progress
uint8_t progress
The percentage (if divided by 256) this vehicle already crossed the tile unit.
Definition vehicle_base.h:287
Vehicle::UpdatePositionAndViewport
void UpdatePositionAndViewport()
Update the position of the vehicle, and update the viewport.
Definition vehicle.cpp:1745
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::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::InvalidateNewGRFCacheOfChain
void InvalidateNewGRFCacheOfChain()
Invalidates cached NewGRF variables of all vehicles in the chain (after the current vehicle)
Definition vehicle_base.h:459
Vehicle::build_year
TimerGameCalendar::Year build_year
Year the vehicle has been built.
Definition vehicle_base.h:252
Vehicle::owner
Owner owner
Which company owns the vehicle?
Definition vehicle_base.h:270
Vehicle::NeedsAutomaticServicing
bool NeedsAutomaticServicing() const
Checks if the current order should be interrupted for a service-in-depot order.
Definition vehicle.cpp:283
Vehicle::running_ticks
uint8_t running_ticks
Number of ticks this vehicle was not stopped this day.
Definition vehicle_base.h:306
TileHeight
static uint TileHeight(Tile tile)
Returns the height of a tile.
Definition tile_map.h:29
GetTileMaxPixelZ
int GetTileMaxPixelZ(TileIndex tile)
Get top height of the tile.
Definition tile_map.h:312
INVALID_TILE
constexpr TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition tile_type.h:95
TILE_SIZE
static constexpr uint TILE_SIZE
Tile size in world coordinates.
Definition tile_type.h:15
TILE_HEIGHT
static constexpr uint TILE_HEIGHT
Height of a height level in world coordinate AND in pixels in ZOOM_BASE.
Definition tile_type.h:18
timer_game_calendar.h
Definition of the game-calendar-timer.
timer_game_economy.h
Definition of the game-economy-timer.
VehicleEnterDepot
void VehicleEnterDepot(Vehicle *v)
Vehicle entirely entered the depot, update its status, orders, vehicle windows, service it,...
Definition vehicle.cpp:1520
VehicleServiceInDepot
void VehicleServiceInDepot(Vehicle *v)
Service a vehicle and all subsequent vehicles in the consist.
Definition vehicle.cpp:178
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
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
CanVehicleUseStation
bool CanVehicleUseStation(EngineID engine_type, const Station *st)
Can this station be used by the given engine type?
Definition vehicle.cpp:3046
AgeVehicle
void AgeVehicle(Vehicle *v)
Update age of a vehicle.
Definition vehicle.cpp:1410
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::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.
vehicle_cmd.h
Command definitions for vehicles.
vehicle_func.h
Functions related to vehicles.
EngineImageType
EngineImageType
Visualisation contexts of vehicles and engines.
Definition vehicle_type.h:74
EIT_ON_MAP
@ EIT_ON_MAP
Vehicle drawn in viewport.
Definition vehicle_type.h:75
VEH_AIRCRAFT
@ VEH_AIRCRAFT
Aircraft vehicle type.
Definition vehicle_type.h:28
DepotCommandFlag
DepotCommandFlag
Flags for goto depot commands.
Definition vehicle_type.h:55
DepotCommandFlag::Service
@ Service
The vehicle will leave the depot right after arrival (service only)
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
SetWindowClassesDirty
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition window.cpp:3205
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:3297
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:3192
SetWindowDirty
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition window.cpp:3179
window_func.h
Window functions not directly related to making/drawing windows.
WC_VEHICLE_DEPOT
@ WC_VEHICLE_DEPOT
Depot view; Window numbers:
Definition window_type.h:356
WC_VEHICLE_DETAILS
@ WC_VEHICLE_DETAILS
Vehicle details; Window numbers:
Definition window_type.h:205
WC_VEHICLE_VIEW
@ WC_VEHICLE_VIEW
Vehicle view; Window numbers:
Definition window_type.h:344
WC_AIRCRAFT_LIST
@ WC_AIRCRAFT_LIST
Aircraft list; Window numbers:
Definition window_type.h:331
zoom_func.h
Functions related to zooming.
ScaleSpriteTrad
int ScaleSpriteTrad(int value)
Scale traditional pixel dimensions to GUI zoom level, for drawing sprites.
Definition zoom_func.h:107
UnScaleGUI
int UnScaleGUI(int value)
Short-hand to apply GUI zoom level.
Definition zoom_func.h:77