OpenTTD
aircraft_cmd.cpp
Go to the documentation of this file.
1 /* $Id$ */
2 
3 /*
4  * This file is part of OpenTTD.
5  * 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.
6  * 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.
7  * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
8  */
9 
15 #include "stdafx.h"
16 #include "aircraft.h"
17 #include "landscape.h"
18 #include "news_func.h"
19 #include "newgrf_engine.h"
20 #include "newgrf_sound.h"
21 #include "spritecache.h"
22 #include "strings_func.h"
23 #include "command_func.h"
24 #include "window_func.h"
25 #include "date_func.h"
26 #include "vehicle_func.h"
27 #include "sound_func.h"
28 #include "cheat_type.h"
29 #include "company_base.h"
30 #include "ai/ai.hpp"
31 #include "game/game.hpp"
32 #include "company_func.h"
33 #include "effectvehicle_func.h"
34 #include "station_base.h"
35 #include "engine_base.h"
36 #include "core/random_func.hpp"
37 #include "core/backup_type.hpp"
38 #include "zoom_func.h"
39 #include "disaster_vehicle.h"
40 #include "newgrf_airporttiles.h"
41 #include "framerate_type.h"
42 
43 #include "table/strings.h"
44 
45 #include "safeguards.h"
46 
48 {
49  this->x_offs = -1;
50  this->y_offs = -1;
51  this->x_extent = 2;
52  this->y_extent = 2;
53 
54  switch (this->subtype) {
55  default: NOT_REACHED();
56 
57  case AIR_AIRCRAFT:
58  case AIR_HELICOPTER:
59  switch (this->state) {
60  default: break;
61  case ENDTAKEOFF:
62  case LANDING:
63  case HELILANDING:
64  case FLYING:
65  this->x_extent = 24;
66  this->y_extent = 24;
67  break;
68  }
69  this->z_extent = 5;
70  break;
71 
72  case AIR_SHADOW:
73  this->z_extent = 1;
74  this->x_offs = 0;
75  this->y_offs = 0;
76  break;
77 
78  case AIR_ROTOR:
79  this->z_extent = 1;
80  break;
81  }
82 }
83 
84 static bool AirportMove(Aircraft *v, const AirportFTAClass *apc);
85 static bool AirportSetBlocks(Aircraft *v, const AirportFTA *current_pos, const AirportFTAClass *apc);
86 static bool AirportHasBlock(Aircraft *v, const AirportFTA *current_pos, const AirportFTAClass *apc);
87 static bool AirportFindFreeTerminal(Aircraft *v, const AirportFTAClass *apc);
88 static bool AirportFindFreeHelipad(Aircraft *v, const AirportFTAClass *apc);
89 static void CrashAirplane(Aircraft *v);
90 
91 static const SpriteID _aircraft_sprite[] = {
92  0x0EB5, 0x0EBD, 0x0EC5, 0x0ECD,
93  0x0ED5, 0x0EDD, 0x0E9D, 0x0EA5,
94  0x0EAD, 0x0EE5, 0x0F05, 0x0F0D,
95  0x0F15, 0x0F1D, 0x0F25, 0x0F2D,
96  0x0EED, 0x0EF5, 0x0EFD, 0x0F35,
97  0x0E9D, 0x0EA5, 0x0EAD, 0x0EB5,
98  0x0EBD, 0x0EC5
99 };
100 
101 template <>
102 bool IsValidImageIndex<VEH_AIRCRAFT>(uint8 image_index)
103 {
104  return image_index < lengthof(_aircraft_sprite);
105 }
106 
109  HRS_ROTOR_STOPPED,
110  HRS_ROTOR_MOVING_1,
111  HRS_ROTOR_MOVING_2,
112  HRS_ROTOR_MOVING_3,
113 };
114 
122 static StationID FindNearestHangar(const Aircraft *v)
123 {
124  const Station *st;
125  uint best = 0;
126  StationID index = INVALID_STATION;
127  TileIndex vtile = TileVirtXY(v->x_pos, v->y_pos);
128  const AircraftVehicleInfo *avi = AircraftVehInfo(v->engine_type);
129 
130  FOR_ALL_STATIONS(st) {
131  if (st->owner != v->owner || !(st->facilities & FACIL_AIRPORT) || !st->airport.HasHangar()) continue;
132 
133  const AirportFTAClass *afc = st->airport.GetFTA();
134 
135  /* don't crash the plane if we know it can't land at the airport */
136  if ((afc->flags & AirportFTAClass::SHORT_STRIP) && (avi->subtype & AIR_FAST) && !_cheats.no_jetcrash.value) continue;
137 
138  /* the plane won't land at any helicopter station */
139  if (!(afc->flags & AirportFTAClass::AIRPLANES) && (avi->subtype & AIR_CTOL)) continue;
140 
141  /* v->tile can't be used here, when aircraft is flying v->tile is set to 0 */
142  uint distance = DistanceSquare(vtile, st->airport.tile);
143  if (v->acache.cached_max_range_sqr != 0) {
144  /* Check if our current destination can be reached from the depot airport. */
145  const Station *cur_dest = GetTargetAirportIfValid(v);
146  if (cur_dest != nullptr && DistanceSquare(st->airport.tile, cur_dest->airport.tile) > v->acache.cached_max_range_sqr) continue;
147  }
148  if (distance < best || index == INVALID_STATION) {
149  best = distance;
150  index = st->index;
151  }
152  }
153  return index;
154 }
155 
157 {
158  uint8 spritenum = this->spritenum;
159 
160  if (is_custom_sprite(spritenum)) {
161  GetCustomVehicleSprite(this, direction, image_type, result);
162  if (result->IsValid()) return;
163 
164  spritenum = this->GetEngine()->original_image_index;
165  }
166 
167  assert(IsValidImageIndex<VEH_AIRCRAFT>(spritenum));
168  result->Set(direction + _aircraft_sprite[spritenum]);
169 }
170 
171 void GetRotorImage(const Aircraft *v, EngineImageType image_type, VehicleSpriteSeq *result)
172 {
173  assert(v->subtype == AIR_HELICOPTER);
174 
175  const Aircraft *w = v->Next()->Next();
176  if (is_custom_sprite(v->spritenum)) {
177  GetCustomRotorSprite(v, false, image_type, result);
178  if (result->IsValid()) return;
179  }
180 
181  /* Return standard rotor sprites if there are no custom sprites for this helicopter */
182  result->Set(SPR_ROTOR_STOPPED + w->state);
183 }
184 
185 static void GetAircraftIcon(EngineID engine, EngineImageType image_type, VehicleSpriteSeq *result)
186 {
187  const Engine *e = Engine::Get(engine);
188  uint8 spritenum = e->u.air.image_index;
189 
190  if (is_custom_sprite(spritenum)) {
191  GetCustomVehicleIcon(engine, DIR_W, image_type, result);
192  if (result->IsValid()) return;
193 
194  spritenum = e->original_image_index;
195  }
196 
197  assert(IsValidImageIndex<VEH_AIRCRAFT>(spritenum));
198  result->Set(DIR_W + _aircraft_sprite[spritenum]);
199 }
200 
201 void DrawAircraftEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
202 {
203  VehicleSpriteSeq seq;
204  GetAircraftIcon(engine, image_type, &seq);
205 
206  Rect rect;
207  seq.GetBounds(&rect);
208  preferred_x = Clamp(preferred_x,
209  left - UnScaleGUI(rect.left),
210  right - UnScaleGUI(rect.right));
211 
212  seq.Draw(preferred_x, y, pal, pal == PALETTE_CRASH);
213 
214  if (!(AircraftVehInfo(engine)->subtype & AIR_CTOL)) {
215  VehicleSpriteSeq rotor_seq;
216  GetCustomRotorIcon(engine, image_type, &rotor_seq);
217  if (!rotor_seq.IsValid()) rotor_seq.Set(SPR_ROTOR_STOPPED);
218  rotor_seq.Draw(preferred_x, y - ScaleGUITrad(5), PAL_NONE, false);
219  }
220 }
221 
231 void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
232 {
233  VehicleSpriteSeq seq;
234  GetAircraftIcon(engine, image_type, &seq);
235 
236  Rect rect;
237  seq.GetBounds(&rect);
238 
239  width = UnScaleGUI(rect.right - rect.left + 1);
240  height = UnScaleGUI(rect.bottom - rect.top + 1);
241  xoffs = UnScaleGUI(rect.left);
242  yoffs = UnScaleGUI(rect.top);
243 }
244 
255 {
256  const AircraftVehicleInfo *avi = &e->u.air;
257  const Station *st = Station::GetByTile(tile);
258 
259  /* Prevent building aircraft types at places which can't handle them */
260  if (!CanVehicleUseStation(e->index, st)) return CMD_ERROR;
261 
262  /* Make sure all aircraft end up in the first tile of the hangar. */
263  tile = st->airport.GetHangarTile(st->airport.GetHangarNum(tile));
264 
265  if (flags & DC_EXEC) {
266  Aircraft *v = new Aircraft(); // aircraft
267  Aircraft *u = new Aircraft(); // shadow
268  *ret = v;
269 
270  v->direction = DIR_SE;
271 
272  v->owner = u->owner = _current_company;
273 
274  v->tile = tile;
275 
276  uint x = TileX(tile) * TILE_SIZE + 5;
277  uint y = TileY(tile) * TILE_SIZE + 3;
278 
279  v->x_pos = u->x_pos = x;
280  v->y_pos = u->y_pos = y;
281 
282  u->z_pos = GetSlopePixelZ(x, y);
283  v->z_pos = u->z_pos + 1;
284 
287 
288  v->spritenum = avi->image_index;
289 
290  v->cargo_cap = avi->passenger_capacity;
291  v->refit_cap = 0;
292  u->cargo_cap = avi->mail_capacity;
293  u->refit_cap = 0;
294 
296  u->cargo_type = CT_MAIL;
297 
298  v->name = nullptr;
299  v->last_station_visited = INVALID_STATION;
300  v->last_loading_station = INVALID_STATION;
301 
302  v->acceleration = avi->acceleration;
303  v->engine_type = e->index;
304  u->engine_type = e->index;
305 
307  v->UpdateDeltaXY();
308 
309  u->subtype = AIR_SHADOW;
310  u->UpdateDeltaXY();
311 
312  v->reliability = e->reliability;
314  v->max_age = e->GetLifeLengthInDays();
315 
316  _new_vehicle_id = v->index;
317 
318  v->pos = GetVehiclePosOnBuild(tile);
319 
320  v->state = HANGAR;
321  v->previous_pos = v->pos;
322  v->targetairport = GetStationIndex(tile);
323  v->SetNext(u);
324 
325  v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_aircraft);
326 
328  v->build_year = u->build_year = _cur_year;
329 
330  v->sprite_seq.Set(SPR_IMG_QUERY);
331  u->sprite_seq.Set(SPR_IMG_QUERY);
332 
335 
336  v->vehicle_flags = 0;
338  v->SetServiceIntervalIsPercent(Company::Get(_current_company)->settings.vehicle.servint_ispercent);
339 
341 
342  v->cargo_cap = e->DetermineCapacity(v, &u->cargo_cap);
343 
345 
346  UpdateAircraftCache(v, true);
347 
348  v->UpdatePosition();
349  u->UpdatePosition();
350 
351  /* Aircraft with 3 vehicles (chopper)? */
352  if (v->subtype == AIR_HELICOPTER) {
353  Aircraft *w = new Aircraft();
354  w->engine_type = e->index;
355  w->direction = DIR_N;
356  w->owner = _current_company;
357  w->x_pos = v->x_pos;
358  w->y_pos = v->y_pos;
359  w->z_pos = v->z_pos + ROTOR_Z_OFFSET;
361  w->spritenum = 0xFF;
362  w->subtype = AIR_ROTOR;
363  w->sprite_seq.Set(SPR_ROTOR_STOPPED);
365  /* Use rotor's air.state to store the rotor animation frame */
366  w->state = HRS_ROTOR_STOPPED;
367  w->UpdateDeltaXY();
368 
369  u->SetNext(w);
370  w->UpdatePosition();
371  }
372  }
373 
374  return CommandCost();
375 }
376 
377 
378 bool Aircraft::FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse)
379 {
380  const Station *st = GetTargetAirportIfValid(this);
381  /* If the station is not a valid airport or if it has no hangars */
382  if (st == nullptr || !CanVehicleUseStation(this, st) || !st->airport.HasHangar()) {
383  /* the aircraft has to search for a hangar on its own */
384  StationID station = FindNearestHangar(this);
385 
386  if (station == INVALID_STATION) return false;
387 
388  st = Station::Get(station);
389  }
390 
391  if (location != nullptr) *location = st->xy;
392  if (destination != nullptr) *destination = st->index;
393 
394  return true;
395 }
396 
397 static void CheckIfAircraftNeedsService(Aircraft *v)
398 {
399  if (Company::Get(v->owner)->settings.vehicle.servint_aircraft == 0 || !v->NeedsAutomaticServicing()) return;
400  if (v->IsChainInDepot()) {
402  return;
403  }
404 
405  /* When we're parsing conditional orders and the like
406  * we don't want to consider going to a depot too. */
407  if (!v->current_order.IsType(OT_GOTO_DEPOT) && !v->current_order.IsType(OT_GOTO_STATION)) return;
408 
410 
411  assert(st != nullptr);
412 
413  /* only goto depot if the target airport has a depot */
414  if (st->airport.HasHangar() && CanVehicleUseStation(v, st)) {
417  } else if (v->current_order.IsType(OT_GOTO_DEPOT)) {
420  }
421 }
422 
424 {
425  const Engine *e = this->GetEngine();
426  uint cost_factor = GetVehicleProperty(this, PROP_AIRCRAFT_RUNNING_COST_FACTOR, e->u.air.running_cost);
427  return GetPrice(PR_RUNNING_AIRCRAFT, cost_factor, e->GetGRF());
428 }
429 
431 {
432  if (!this->IsNormalAircraft()) return;
433 
434  if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this);
435 
436  CheckOrders(this);
437 
438  CheckVehicleBreakdown(this);
439  AgeVehicle(this);
440  CheckIfAircraftNeedsService(this);
441 
442  if (this->running_ticks == 0) return;
443 
445 
446  this->profit_this_year -= cost.GetCost();
447  this->running_ticks = 0;
448 
450 
453 }
454 
455 static void HelicopterTickHandler(Aircraft *v)
456 {
457  Aircraft *u = v->Next()->Next();
458 
459  if (u->vehstatus & VS_HIDDEN) return;
460 
461  /* if true, helicopter rotors do not rotate. This should only be the case if a helicopter is
462  * loading/unloading at a terminal or stopped */
463  if (v->current_order.IsType(OT_LOADING) || (v->vehstatus & VS_STOPPED)) {
464  if (u->cur_speed != 0) {
465  u->cur_speed++;
466  if (u->cur_speed >= 0x80 && u->state == HRS_ROTOR_MOVING_3) {
467  u->cur_speed = 0;
468  }
469  }
470  } else {
471  if (u->cur_speed == 0) {
472  u->cur_speed = 0x70;
473  }
474  if (u->cur_speed >= 0x50) {
475  u->cur_speed--;
476  }
477  }
478 
479  int tick = ++u->tick_counter;
480  int spd = u->cur_speed >> 4;
481 
482  VehicleSpriteSeq seq;
483  if (spd == 0) {
484  u->state = HRS_ROTOR_STOPPED;
485  GetRotorImage(v, EIT_ON_MAP, &seq);
486  if (u->sprite_seq == seq) return;
487  } else if (tick >= spd) {
488  u->tick_counter = 0;
489  u->state++;
490  if (u->state > HRS_ROTOR_MOVING_3) u->state = HRS_ROTOR_MOVING_1;
491  GetRotorImage(v, EIT_ON_MAP, &seq);
492  } else {
493  return;
494  }
495 
496  u->sprite_seq = seq;
497 
499 }
500 
508 void SetAircraftPosition(Aircraft *v, int x, int y, int z)
509 {
510  v->x_pos = x;
511  v->y_pos = y;
512  v->z_pos = z;
513 
514  v->UpdatePosition();
515  v->UpdateViewport(true, false);
516  if (v->subtype == AIR_HELICOPTER) {
517  GetRotorImage(v, EIT_ON_MAP, &v->Next()->Next()->sprite_seq);
518  }
519 
520  Aircraft *u = v->Next();
521 
522  int safe_x = Clamp(x, 0, MapMaxX() * TILE_SIZE);
523  int safe_y = Clamp(y - 1, 0, MapMaxY() * TILE_SIZE);
524  u->x_pos = x;
525  u->y_pos = y - ((v->z_pos - GetSlopePixelZ(safe_x, safe_y)) >> 3);
526 
527  safe_y = Clamp(u->y_pos, 0, MapMaxY() * TILE_SIZE);
528  u->z_pos = GetSlopePixelZ(safe_x, safe_y);
529  u->sprite_seq.CopyWithoutPalette(v->sprite_seq); // the shadow is never coloured
530 
531  u->UpdatePositionAndViewport();
532 
533  u = u->Next();
534  if (u != nullptr) {
535  u->x_pos = x;
536  u->y_pos = y;
537  u->z_pos = z + ROTOR_Z_OFFSET;
538 
539  u->UpdatePositionAndViewport();
540  }
541 }
542 
548 {
549  v->subspeed = 0;
550  v->progress = 0;
551 
552  Aircraft *u = v->Next();
553  u->vehstatus |= VS_HIDDEN;
554  u = u->Next();
555  if (u != nullptr) {
556  u->vehstatus |= VS_HIDDEN;
557  u->cur_speed = 0;
558  }
559 
560  SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos);
561 }
562 
563 static void PlayAircraftSound(const Vehicle *v)
564 {
565  if (!PlayVehicleSound(v, VSE_START)) {
566  SndPlayVehicleFx(AircraftVehInfo(v->engine_type)->sfx, v);
567  }
568 }
569 
570 
577 void UpdateAircraftCache(Aircraft *v, bool update_range)
578 {
579  uint max_speed = GetVehicleProperty(v, PROP_AIRCRAFT_SPEED, 0);
580  if (max_speed != 0) {
581  /* Convert from original units to km-ish/h */
582  max_speed = (max_speed * 128) / 10;
583 
584  v->vcache.cached_max_speed = max_speed;
585  } else {
586  /* Use the default max speed of the vehicle. */
587  v->vcache.cached_max_speed = AircraftVehInfo(v->engine_type)->max_speed;
588  }
589 
590  /* Update cargo aging period. */
591  v->vcache.cached_cargo_age_period = GetVehicleProperty(v, PROP_AIRCRAFT_CARGO_AGE_PERIOD, EngInfo(v->engine_type)->cargo_age_period);
592  Aircraft *u = v->Next(); // Shadow for mail
593  u->vcache.cached_cargo_age_period = GetVehicleProperty(u, PROP_AIRCRAFT_CARGO_AGE_PERIOD, EngInfo(u->engine_type)->cargo_age_period);
594 
595  /* Update aircraft range. */
596  if (update_range) {
597  v->acache.cached_max_range = GetVehicleProperty(v, PROP_AIRCRAFT_RANGE, AircraftVehInfo(v->engine_type)->max_range);
598  /* Squared it now so we don't have to do it later all the time. */
599  v->acache.cached_max_range_sqr = v->acache.cached_max_range * v->acache.cached_max_range;
600  }
601 }
602 
603 
612  SPEED_LIMIT_NONE = 0xFFFF,
613 };
614 
622 static int UpdateAircraftSpeed(Aircraft *v, uint speed_limit = SPEED_LIMIT_NONE, bool hard_limit = true)
623 {
631  uint spd = v->acceleration * 77;
632  byte t;
633 
634  /* Adjust speed limits by plane speed factor to prevent taxiing
635  * and take-off speeds being too low. */
636  speed_limit *= _settings_game.vehicle.plane_speed;
637 
638  /* adjust speed for broken vehicles */
639  if (v->vehstatus & VS_AIRCRAFT_BROKEN) {
640  if (SPEED_LIMIT_BROKEN < speed_limit) hard_limit = false;
641  speed_limit = min(speed_limit, SPEED_LIMIT_BROKEN);
642  }
643 
644  if (v->vcache.cached_max_speed < speed_limit) {
645  if (v->cur_speed < speed_limit) hard_limit = false;
646  speed_limit = v->vcache.cached_max_speed;
647  }
648 
649  v->subspeed = (t = v->subspeed) + (byte)spd;
650 
651  /* Aircraft's current speed is used twice so that very fast planes are
652  * forced to slow down rapidly in the short distance needed. The magic
653  * value 16384 was determined to give similar results to the old speed/48
654  * method at slower speeds. This also results in less reduction at slow
655  * speeds to that aircraft do not get to taxi speed straight after
656  * touchdown. */
657  if (!hard_limit && v->cur_speed > speed_limit) {
658  speed_limit = v->cur_speed - max(1, ((v->cur_speed * v->cur_speed) / 16384) / _settings_game.vehicle.plane_speed);
659  }
660 
661  spd = min(v->cur_speed + (spd >> 8) + (v->subspeed < t), speed_limit);
662 
663  /* updates statusbar only if speed have changed to save CPU time */
664  if (spd != v->cur_speed) {
665  v->cur_speed = spd;
667  }
668 
669  /* Adjust distance moved by plane speed setting */
671 
672  /* Convert direction-independent speed into direction-dependent speed. (old movement method) */
673  spd = v->GetOldAdvanceSpeed(spd);
674 
675  spd += v->progress;
676  v->progress = (byte)spd;
677  return spd >> 8;
678 }
679 
688 {
689  int safe_x = Clamp(v->x_pos, 0, MapMaxX() * TILE_SIZE);
690  int safe_y = Clamp(v->y_pos, 0, MapMaxY() * TILE_SIZE);
691  return TileHeight(TileVirtXY(safe_x, safe_y)) * TILE_HEIGHT;
692 }
693 
704 void GetAircraftFlightLevelBounds(const Vehicle *v, int *min_level, int *max_level)
705 {
706  int base_altitude = GetTileHeightBelowAircraft(v);
707  if (v->type == VEH_AIRCRAFT && Aircraft::From(v)->subtype == AIR_HELICOPTER) {
709  }
710 
711  /* Make sure eastbound and westbound planes do not "crash" into each
712  * other by providing them with vertical separation
713  */
714  switch (v->direction) {
715  case DIR_N:
716  case DIR_NE:
717  case DIR_E:
718  case DIR_SE:
719  base_altitude += 10;
720  break;
721 
722  default: break;
723  }
724 
725  /* Make faster planes fly higher so that they can overtake slower ones */
726  base_altitude += min(20 * (v->vcache.cached_max_speed / 200) - 90, 0);
727 
728  if (min_level != nullptr) *min_level = base_altitude + AIRCRAFT_MIN_FLYING_ALTITUDE;
729  if (max_level != nullptr) *max_level = base_altitude + AIRCRAFT_MAX_FLYING_ALTITUDE;
730 }
731 
740 {
741  int tile_height = GetTileHeightBelowAircraft(v);
742 
744 }
745 
746 template <class T>
747 int GetAircraftFlightLevel(T *v, bool takeoff)
748 {
749  /* Aircraft is in flight. We want to enforce it being somewhere
750  * between the minimum and the maximum allowed altitude. */
751  int aircraft_min_altitude;
752  int aircraft_max_altitude;
753  GetAircraftFlightLevelBounds(v, &aircraft_min_altitude, &aircraft_max_altitude);
754  int aircraft_middle_altitude = (aircraft_min_altitude + aircraft_max_altitude) / 2;
755 
756  /* If those assumptions would be violated, aircraft would behave fairly strange. */
757  assert(aircraft_min_altitude < aircraft_middle_altitude);
758  assert(aircraft_middle_altitude < aircraft_max_altitude);
759 
760  int z = v->z_pos;
761  if (z < aircraft_min_altitude ||
762  (HasBit(v->flags, VAF_IN_MIN_HEIGHT_CORRECTION) && z < aircraft_middle_altitude)) {
763  /* Ascend. And don't fly into that mountain right ahead.
764  * And avoid our aircraft become a stairclimber, so if we start
765  * correcting altitude, then we stop correction not too early. */
767  z += takeoff ? 2 : 1;
768  } else if (!takeoff && (z > aircraft_max_altitude ||
769  (HasBit(v->flags, VAF_IN_MAX_HEIGHT_CORRECTION) && z > aircraft_middle_altitude))) {
770  /* Descend lower. You are an aircraft, not an space ship.
771  * And again, don't stop correcting altitude too early. */
773  z--;
774  } else if (HasBit(v->flags, VAF_IN_MIN_HEIGHT_CORRECTION) && z >= aircraft_middle_altitude) {
775  /* Now, we have corrected altitude enough. */
777  } else if (HasBit(v->flags, VAF_IN_MAX_HEIGHT_CORRECTION) && z <= aircraft_middle_altitude) {
778  /* Now, we have corrected altitude enough. */
780  }
781 
782  return z;
783 }
784 
785 template int GetAircraftFlightLevel(DisasterVehicle *v, bool takeoff);
786 template int GetAircraftFlightLevel(Aircraft *v, bool takeoff);
787 
802 static byte AircraftGetEntryPoint(const Aircraft *v, const AirportFTAClass *apc, Direction rotation)
803 {
804  assert(v != nullptr);
805  assert(apc != nullptr);
806 
807  /* In the case the station doesn't exit anymore, set target tile 0.
808  * It doesn't hurt much, aircraft will go to next order, nearest hangar
809  * or it will simply crash in next tick */
810  TileIndex tile = 0;
811 
812  const Station *st = Station::GetIfValid(v->targetairport);
813  if (st != nullptr) {
814  /* Make sure we don't go to INVALID_TILE if the airport has been removed. */
815  tile = (st->airport.tile != INVALID_TILE) ? st->airport.tile : st->xy;
816  }
817 
818  int delta_x = v->x_pos - TileX(tile) * TILE_SIZE;
819  int delta_y = v->y_pos - TileY(tile) * TILE_SIZE;
820 
821  DiagDirection dir;
822  if (abs(delta_y) < abs(delta_x)) {
823  /* We are northeast or southwest of the airport */
824  dir = delta_x < 0 ? DIAGDIR_NE : DIAGDIR_SW;
825  } else {
826  /* We are northwest or southeast of the airport */
827  dir = delta_y < 0 ? DIAGDIR_NW : DIAGDIR_SE;
828  }
829  dir = ChangeDiagDir(dir, DiagDirDifference(DIAGDIR_NE, DirToDiagDir(rotation)));
830  return apc->entry_points[dir];
831 }
832 
833 
834 static void MaybeCrashAirplane(Aircraft *v);
835 
844 {
845  int count;
846 
847  /* nullptr if station is invalid */
848  const Station *st = Station::GetIfValid(v->targetairport);
849  /* INVALID_TILE if there is no station */
851  Direction rotation = DIR_N;
852  uint size_x = 1, size_y = 1;
853  if (st != nullptr) {
854  if (st->airport.tile != INVALID_TILE) {
855  tile = st->airport.tile;
856  rotation = st->airport.rotation;
857  size_x = st->airport.w;
858  size_y = st->airport.h;
859  } else {
860  tile = st->xy;
861  }
862  }
863  /* DUMMY if there is no station or no airport */
864  const AirportFTAClass *afc = tile == INVALID_TILE ? GetAirport(AT_DUMMY) : st->airport.GetFTA();
865 
866  /* prevent going to INVALID_TILE if airport is deleted. */
867  if (st == nullptr || st->airport.tile == INVALID_TILE) {
868  /* Jump into our "holding pattern" state machine if possible */
869  if (v->pos >= afc->nofelements) {
870  v->pos = v->previous_pos = AircraftGetEntryPoint(v, afc, DIR_N);
871  } else if (v->targetairport != v->current_order.GetDestination()) {
872  /* If not possible, just get out of here fast */
873  v->state = FLYING;
876  /* get aircraft back on running altitude */
877  SetAircraftPosition(v, v->x_pos, v->y_pos, GetAircraftFlightLevel(v));
878  return false;
879  }
880  }
881 
882  /* get airport moving data */
883  const AirportMovingData amd = RotateAirportMovingData(afc->MovingData(v->pos), rotation, size_x, size_y);
884 
885  int x = TileX(tile) * TILE_SIZE;
886  int y = TileY(tile) * TILE_SIZE;
887 
888  /* Helicopter raise */
889  if (amd.flag & AMED_HELI_RAISE) {
890  Aircraft *u = v->Next()->Next();
891 
892  /* Make sure the rotors don't rotate too fast */
893  if (u->cur_speed > 32) {
894  v->cur_speed = 0;
895  if (--u->cur_speed == 32) {
896  if (!PlayVehicleSound(v, VSE_START)) {
897  SndPlayVehicleFx(SND_18_HELICOPTER, v);
898  }
899  }
900  } else {
901  u->cur_speed = 32;
902  count = UpdateAircraftSpeed(v);
903  if (count > 0) {
904  v->tile = 0;
905 
906  int z_dest;
907  GetAircraftFlightLevelBounds(v, &z_dest, nullptr);
908 
909  /* Reached altitude? */
910  if (v->z_pos >= z_dest) {
911  v->cur_speed = 0;
912  return true;
913  }
914  SetAircraftPosition(v, v->x_pos, v->y_pos, min(v->z_pos + count, z_dest));
915  }
916  }
917  return false;
918  }
919 
920  /* Helicopter landing. */
921  if (amd.flag & AMED_HELI_LOWER) {
923 
924  if (st == nullptr) {
925  /* FIXME - AircraftController -> if station no longer exists, do not land
926  * helicopter will circle until sign disappears, then go to next order
927  * what to do when it is the only order left, right now it just stays in 1 place */
928  v->state = FLYING;
931  return false;
932  }
933 
934  /* Vehicle is now at the airport. */
935  v->tile = tile;
936 
937  /* Find altitude of landing position. */
938  int z = GetSlopePixelZ(x, y) + 1 + afc->delta_z;
939 
940  if (z == v->z_pos) {
941  Vehicle *u = v->Next()->Next();
942 
943  /* Increase speed of rotors. When speed is 80, we've landed. */
944  if (u->cur_speed >= 80) {
946  return true;
947  }
948  u->cur_speed += 4;
949  } else {
950  count = UpdateAircraftSpeed(v);
951  if (count > 0) {
952  if (v->z_pos > z) {
953  SetAircraftPosition(v, v->x_pos, v->y_pos, max(v->z_pos - count, z));
954  } else {
955  SetAircraftPosition(v, v->x_pos, v->y_pos, min(v->z_pos + count, z));
956  }
957  }
958  }
959  return false;
960  }
961 
962  /* Get distance from destination pos to current pos. */
963  uint dist = abs(x + amd.x - v->x_pos) + abs(y + amd.y - v->y_pos);
964 
965  /* Need exact position? */
966  if (!(amd.flag & AMED_EXACTPOS) && dist <= (amd.flag & AMED_SLOWTURN ? 8U : 4U)) return true;
967 
968  /* At final pos? */
969  if (dist == 0) {
970  /* Change direction smoothly to final direction. */
971  DirDiff dirdiff = DirDifference(amd.direction, v->direction);
972  /* if distance is 0, and plane points in right direction, no point in calling
973  * UpdateAircraftSpeed(). So do it only afterwards */
974  if (dirdiff == DIRDIFF_SAME) {
975  v->cur_speed = 0;
976  return true;
977  }
978 
979  if (!UpdateAircraftSpeed(v, SPEED_LIMIT_TAXI)) return false;
980 
982  v->cur_speed >>= 1;
983 
984  SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos);
985  return false;
986  }
987 
990  if ((v->vehstatus & VS_CRASHED) != 0) return false;
991  }
992 
993  uint speed_limit = SPEED_LIMIT_TAXI;
994  bool hard_limit = true;
995 
996  if (amd.flag & AMED_NOSPDCLAMP) speed_limit = SPEED_LIMIT_NONE;
997  if (amd.flag & AMED_HOLD) { speed_limit = SPEED_LIMIT_HOLD; hard_limit = false; }
998  if (amd.flag & AMED_LAND) { speed_limit = SPEED_LIMIT_APPROACH; hard_limit = false; }
999  if (amd.flag & AMED_BRAKE) { speed_limit = SPEED_LIMIT_TAXI; hard_limit = false; }
1000 
1001  count = UpdateAircraftSpeed(v, speed_limit, hard_limit);
1002  if (count == 0) return false;
1003 
1004  if (v->turn_counter != 0) v->turn_counter--;
1005 
1006  do {
1007 
1009 
1010  if (dist < 4 || (amd.flag & AMED_LAND)) {
1011  /* move vehicle one pixel towards target */
1012  gp.x = (v->x_pos != (x + amd.x)) ?
1013  v->x_pos + ((x + amd.x > v->x_pos) ? 1 : -1) :
1014  v->x_pos;
1015  gp.y = (v->y_pos != (y + amd.y)) ?
1016  v->y_pos + ((y + amd.y > v->y_pos) ? 1 : -1) :
1017  v->y_pos;
1018 
1019  /* Oilrigs must keep v->tile as st->airport.tile, since the landing pad is in a non-airport tile */
1020  gp.new_tile = (st->airport.type == AT_OILRIG) ? st->airport.tile : TileVirtXY(gp.x, gp.y);
1021 
1022  } else {
1023 
1024  /* Turn. Do it slowly if in the air. */
1025  Direction newdir = GetDirectionTowards(v, x + amd.x, y + amd.y);
1026  if (newdir != v->direction) {
1027  if (amd.flag & AMED_SLOWTURN && v->number_consecutive_turns < 8 && v->subtype == AIR_AIRCRAFT) {
1028  if (v->turn_counter == 0 || newdir == v->last_direction) {
1029  if (newdir == v->last_direction) {
1030  v->number_consecutive_turns = 0;
1031  } else {
1033  }
1035  v->last_direction = v->direction;
1036  v->direction = newdir;
1037  }
1038 
1039  /* Move vehicle. */
1040  gp = GetNewVehiclePos(v);
1041  } else {
1042  v->cur_speed >>= 1;
1043  v->direction = newdir;
1044 
1045  /* When leaving a terminal an aircraft often goes to a position
1046  * directly in front of it. If it would move while turning it
1047  * would need an two extra turns to end up at the correct position.
1048  * To make it easier just disallow all moving while turning as
1049  * long as an aircraft is on the ground. */
1050  gp.x = v->x_pos;
1051  gp.y = v->y_pos;
1052  gp.new_tile = gp.old_tile = v->tile;
1053  }
1054  } else {
1055  v->number_consecutive_turns = 0;
1056  /* Move vehicle. */
1057  gp = GetNewVehiclePos(v);
1058  }
1059  }
1060 
1061  v->tile = gp.new_tile;
1062  /* If vehicle is in the air, use tile coordinate 0. */
1063  if (amd.flag & (AMED_TAKEOFF | AMED_SLOWTURN | AMED_LAND)) v->tile = 0;
1064 
1065  /* Adjust Z for land or takeoff? */
1066  int z = v->z_pos;
1067 
1068  if (amd.flag & AMED_TAKEOFF) {
1069  z = GetAircraftFlightLevel(v, true);
1070  } else if (amd.flag & AMED_HOLD) {
1071  /* Let the plane drop from normal flight altitude to holding pattern altitude */
1072  if (z > GetAircraftHoldMaxAltitude(v)) z--;
1073  } else if ((amd.flag & AMED_SLOWTURN) && (amd.flag & AMED_NOSPDCLAMP)) {
1074  z = GetAircraftFlightLevel(v);
1075  }
1076 
1077  if (amd.flag & AMED_LAND) {
1078  if (st->airport.tile == INVALID_TILE) {
1079  /* Airport has been removed, abort the landing procedure */
1080  v->state = FLYING;
1083  /* get aircraft back on running altitude */
1084  SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlightLevel(v));
1085  continue;
1086  }
1087 
1088  int curz = GetSlopePixelZ(x + amd.x, y + amd.y) + 1;
1089 
1090  /* We're not flying below our destination, right? */
1091  assert(curz <= z);
1092  int t = max(1U, dist - 4);
1093  int delta = z - curz;
1094 
1095  /* Only start lowering when we're sufficiently close for a 1:1 glide */
1096  if (delta >= t) {
1097  z -= CeilDiv(z - curz, t);
1098  }
1099  if (z < curz) z = curz;
1100  }
1101 
1102  /* We've landed. Decrease speed when we're reaching end of runway. */
1103  if (amd.flag & AMED_BRAKE) {
1104  int curz = GetSlopePixelZ(x, y) + 1;
1105 
1106  if (z > curz) {
1107  z--;
1108  } else if (z < curz) {
1109  z++;
1110  }
1111 
1112  }
1113 
1114  SetAircraftPosition(v, gp.x, gp.y, z);
1115  } while (--count != 0);
1116  return false;
1117 }
1118 
1124 {
1125  v->crashed_counter += 3;
1126 
1128 
1129  /* make aircraft crash down to the ground */
1130  if (v->crashed_counter < 500 && st == nullptr && ((v->crashed_counter % 3) == 0) ) {
1131  int z = GetSlopePixelZ(Clamp(v->x_pos, 0, MapMaxX() * TILE_SIZE), Clamp(v->y_pos, 0, MapMaxY() * TILE_SIZE));
1132  v->z_pos -= 1;
1133  if (v->z_pos == z) {
1134  v->crashed_counter = 500;
1135  v->z_pos++;
1136  }
1137  }
1138 
1139  if (v->crashed_counter < 650) {
1140  uint32 r;
1141  if (Chance16R(1, 32, r)) {
1142  static const DirDiff delta[] = {
1144  };
1145 
1146  v->direction = ChangeDir(v->direction, delta[GB(r, 16, 2)]);
1147  SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos);
1148  r = Random();
1150  GB(r, 0, 4) - 4,
1151  GB(r, 4, 4) - 4,
1152  GB(r, 8, 4),
1154  }
1155  } else if (v->crashed_counter >= 10000) {
1156  /* remove rubble of crashed airplane */
1157 
1158  /* clear runway-in on all airports, set by crashing plane
1159  * small airports use AIRPORT_BUSY, city airports use RUNWAY_IN_OUT_block, etc.
1160  * but they all share the same number */
1161  if (st != nullptr) {
1162  CLRBITS(st->airport.flags, RUNWAY_IN_block);
1163  CLRBITS(st->airport.flags, RUNWAY_IN_OUT_block); // commuter airport
1164  CLRBITS(st->airport.flags, RUNWAY_IN2_block); // intercontinental
1165  }
1166 
1167  delete v;
1168 
1169  return false;
1170  }
1171 
1172  return true;
1173 }
1174 
1175 
1181 static void HandleAircraftSmoke(Aircraft *v, bool mode)
1182 {
1183  static const struct {
1184  int8 x;
1185  int8 y;
1186  } smoke_pos[] = {
1187  { 5, 5 },
1188  { 6, 0 },
1189  { 5, -5 },
1190  { 0, -6 },
1191  { -5, -5 },
1192  { -6, 0 },
1193  { -5, 5 },
1194  { 0, 6 }
1195  };
1196 
1197  if (!(v->vehstatus & VS_AIRCRAFT_BROKEN)) return;
1198 
1199  /* Stop smoking when landed */
1200  if (v->cur_speed < 10) {
1202  v->breakdown_ctr = 0;
1203  return;
1204  }
1205 
1206  /* Spawn effect et most once per Tick, i.e. !mode */
1207  if (!mode && (v->tick_counter & 0x0F) == 0) {
1209  smoke_pos[v->direction].x,
1210  smoke_pos[v->direction].y,
1211  2,
1213  );
1214  }
1215 }
1216 
1217 void HandleMissingAircraftOrders(Aircraft *v)
1218 {
1219  /*
1220  * We do not have an order. This can be divided into two cases:
1221  * 1) we are heading to an invalid station. In this case we must
1222  * find another airport to go to. If there is nowhere to go,
1223  * we will destroy the aircraft as it otherwise will enter
1224  * the holding pattern for the first airport, which can cause
1225  * the plane to go into an undefined state when building an
1226  * airport with the same StationID.
1227  * 2) we are (still) heading to a (still) valid airport, then we
1228  * can continue going there. This can happen when you are
1229  * changing the aircraft's orders while in-flight or in for
1230  * example a depot. However, when we have a current order to
1231  * go to a depot, we have to keep that order so the aircraft
1232  * actually stops.
1233  */
1234  const Station *st = GetTargetAirportIfValid(v);
1235  if (st == nullptr) {
1236  Backup<CompanyID> cur_company(_current_company, v->owner, FILE_LINE);
1238  cur_company.Restore();
1239 
1240  if (ret.Failed()) CrashAirplane(v);
1241  } else if (!v->current_order.IsType(OT_GOTO_DEPOT)) {
1242  v->current_order.Free();
1243  }
1244 }
1245 
1246 
1248 {
1249  /* Orders are changed in flight, ensure going to the right station. */
1250  if (this->state == FLYING) {
1252  }
1253 
1254  /* Aircraft do not use dest-tile */
1255  return 0;
1256 }
1257 
1259 {
1260  this->colourmap = PAL_NONE;
1261  this->UpdateViewport(true, false);
1262  if (this->subtype == AIR_HELICOPTER) {
1263  GetRotorImage(this, EIT_ON_MAP, &this->Next()->Next()->sprite_seq);
1264  }
1265 }
1266 
1267 
1268 uint Aircraft::Crash(bool flooded)
1269 {
1270  uint pass = Vehicle::Crash(flooded) + 2; // pilots
1271  this->crashed_counter = flooded ? 9000 : 0; // max 10000, disappear pretty fast when flooded
1272 
1273  return pass;
1274 }
1275 
1280 static void CrashAirplane(Aircraft *v)
1281 {
1283 
1284  uint pass = v->Crash();
1285  SetDParam(0, pass);
1286 
1287  v->cargo.Truncate();
1288  v->Next()->cargo.Truncate();
1289  const Station *st = GetTargetAirportIfValid(v);
1290  StringID newsitem;
1291  if (st == nullptr) {
1292  newsitem = STR_NEWS_PLANE_CRASH_OUT_OF_FUEL;
1293  } else {
1294  SetDParam(1, st->index);
1295  newsitem = STR_NEWS_AIRCRAFT_CRASH;
1296  }
1297 
1298  AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, st == nullptr ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING));
1299  Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, st == nullptr ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING));
1300 
1301  AddVehicleNewsItem(newsitem, NT_ACCIDENT, v->index, st != nullptr ? st->index : INVALID_STATION);
1302 
1303  ModifyStationRatingAround(v->tile, v->owner, -160, 30);
1304  if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v);
1305 }
1306 
1312 {
1313 
1315 
1316  uint32 prob;
1318  (AircraftVehInfo(v->engine_type)->subtype & AIR_FAST) &&
1320  prob = 3276;
1321  } else {
1322  if (_settings_game.vehicle.plane_crashes == 0) return;
1323  prob = (0x4000 << _settings_game.vehicle.plane_crashes) / 1500;
1324  }
1325 
1326  if (GB(Random(), 0, 22) > prob) return;
1327 
1328  /* Crash the airplane. Remove all goods stored at the station. */
1329  for (CargoID i = 0; i < NUM_CARGO; i++) {
1330  st->goods[i].rating = 1;
1331  st->goods[i].cargo.Truncate();
1332  }
1333 
1334  CrashAirplane(v);
1335 }
1336 
1343 {
1344  if (v->current_order.IsType(OT_GOTO_DEPOT)) return;
1345 
1348 
1349  /* Check if station was ever visited before */
1350  if (!(st->had_vehicle_of_type & HVOT_AIRCRAFT)) {
1351  st->had_vehicle_of_type |= HVOT_AIRCRAFT;
1352  SetDParam(0, st->index);
1353  /* show newsitem of celebrating citizens */
1355  STR_NEWS_FIRST_AIRCRAFT_ARRIVAL,
1357  v->index,
1358  st->index
1359  );
1360  AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index));
1361  Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index));
1362  }
1363 
1364  v->BeginLoading();
1365 }
1366 
1372 {
1374 
1375  TileIndex vt = TileVirtXY(v->x_pos, v->y_pos);
1376 
1377  v->UpdateDeltaXY();
1378 
1379  AirportTileAnimationTrigger(st, vt, AAT_STATION_AIRPLANE_LAND);
1380 
1381  if (!PlayVehicleSound(v, VSE_TOUCHDOWN)) {
1382  SndPlayVehicleFx(SND_17_SKID_PLANE, v);
1383  }
1384 }
1385 
1386 
1389 {
1390  if (v->current_order.IsType(OT_GOTO_STATION) || v->current_order.IsType(OT_GOTO_DEPOT)) {
1392  }
1393 
1394  const Station *st = GetTargetAirportIfValid(v);
1395  const AirportFTAClass *apc = st == nullptr ? GetAirport(AT_DUMMY) : st->airport.GetFTA();
1396  Direction rotation = st == nullptr ? DIR_N : st->airport.rotation;
1397  v->pos = v->previous_pos = AircraftGetEntryPoint(v, apc, rotation);
1398 }
1399 
1409 {
1410  v->cur_speed = 0;
1411  v->subspeed = 0;
1412  v->progress = 0;
1413  v->direction = exit_dir;
1414  v->vehstatus &= ~VS_HIDDEN;
1415  {
1416  Vehicle *u = v->Next();
1417  u->vehstatus &= ~VS_HIDDEN;
1418 
1419  /* Rotor blades */
1420  u = u->Next();
1421  if (u != nullptr) {
1422  u->vehstatus &= ~VS_HIDDEN;
1423  u->cur_speed = 80;
1424  }
1425  }
1426 
1428  SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos);
1431 }
1432 
1436 static void AircraftEventHandler_EnterTerminal(Aircraft *v, const AirportFTAClass *apc)
1437 {
1439  v->state = apc->layout[v->pos].heading;
1440 }
1441 
1448 {
1449  VehicleEnterDepot(v);
1450  v->state = apc->layout[v->pos].heading;
1451 }
1452 
1459 {
1460  /* if we just arrived, execute EnterHangar first */
1461  if (v->previous_pos != v->pos) {
1463  return;
1464  }
1465 
1466  /* if we were sent to the depot, stay there */
1467  if (v->current_order.IsType(OT_GOTO_DEPOT) && (v->vehstatus & VS_STOPPED)) {
1468  v->current_order.Free();
1469  return;
1470  }
1471 
1472  if (!v->current_order.IsType(OT_GOTO_STATION) &&
1473  !v->current_order.IsType(OT_GOTO_DEPOT))
1474  return;
1475 
1476  /* We are leaving a hangar, but have to go to the exact same one; re-enter */
1477  if (v->current_order.IsType(OT_GOTO_DEPOT) && v->current_order.GetDestination() == v->targetairport) {
1478  VehicleEnterDepot(v);
1479  return;
1480  }
1481 
1482  /* if the block of the next position is busy, stay put */
1483  if (AirportHasBlock(v, &apc->layout[v->pos], apc)) return;
1484 
1485  /* We are already at the target airport, we need to find a terminal */
1486  if (v->current_order.GetDestination() == v->targetairport) {
1487  /* FindFreeTerminal:
1488  * 1. Find a free terminal, 2. Occupy it, 3. Set the vehicle's state to that terminal */
1489  if (v->subtype == AIR_HELICOPTER) {
1490  if (!AirportFindFreeHelipad(v, apc)) return; // helicopter
1491  } else {
1492  if (!AirportFindFreeTerminal(v, apc)) return; // airplane
1493  }
1494  } else { // Else prepare for launch.
1495  /* airplane goto state takeoff, helicopter to helitakeoff */
1496  v->state = (v->subtype == AIR_HELICOPTER) ? HELITAKEOFF : TAKEOFF;
1497  }
1498  const Station *st = Station::GetByTile(v->tile);
1500  AirportMove(v, apc);
1501 }
1502 
1505 {
1506  /* if we just arrived, execute EnterTerminal first */
1507  if (v->previous_pos != v->pos) {
1508  AircraftEventHandler_EnterTerminal(v, apc);
1509  /* on an airport with helipads, a helicopter will always land there
1510  * and get serviced at the same time - setting */
1512  if (v->subtype == AIR_HELICOPTER && apc->num_helipads > 0) {
1513  /* an excerpt of ServiceAircraft, without the invisibility stuff */
1516  v->reliability = v->GetEngine()->reliability;
1518  }
1519  }
1520  return;
1521  }
1522 
1523  if (v->current_order.IsType(OT_NOTHING)) return;
1524 
1525  /* if the block of the next position is busy, stay put */
1526  if (AirportHasBlock(v, &apc->layout[v->pos], apc)) return;
1527 
1528  /* airport-road is free. We either have to go to another airport, or to the hangar
1529  * ---> start moving */
1530 
1531  bool go_to_hangar = false;
1532  switch (v->current_order.GetType()) {
1533  case OT_GOTO_STATION: // ready to fly to another airport
1534  break;
1535  case OT_GOTO_DEPOT: // visit hangar for servicing, sale, etc.
1536  go_to_hangar = v->current_order.GetDestination() == v->targetairport;
1537  break;
1538  case OT_CONDITIONAL:
1539  /* In case of a conditional order we just have to wait a tick
1540  * longer, so the conditional order can actually be processed;
1541  * we should not clear the order as that makes us go nowhere. */
1542  return;
1543  default: // orders have been deleted (no orders), goto depot and don't bother us
1544  v->current_order.Free();
1545  go_to_hangar = Station::Get(v->targetairport)->airport.HasHangar();
1546  }
1547 
1548  if (go_to_hangar && Station::Get(v->targetairport)->airport.HasHangar()) {
1549  v->state = HANGAR;
1550  } else {
1551  /* airplane goto state takeoff, helicopter to helitakeoff */
1552  v->state = (v->subtype == AIR_HELICOPTER) ? HELITAKEOFF : TAKEOFF;
1553  }
1554  AirportMove(v, apc);
1555 }
1556 
1557 static void AircraftEventHandler_General(Aircraft *v, const AirportFTAClass *apc)
1558 {
1559  error("OK, you shouldn't be here, check your Airport Scheme!");
1560 }
1561 
1562 static void AircraftEventHandler_TakeOff(Aircraft *v, const AirportFTAClass *apc)
1563 {
1564  PlayAircraftSound(v); // play takeoffsound for airplanes
1565  v->state = STARTTAKEOFF;
1566 }
1567 
1568 static void AircraftEventHandler_StartTakeOff(Aircraft *v, const AirportFTAClass *apc)
1569 {
1570  v->state = ENDTAKEOFF;
1571  v->UpdateDeltaXY();
1572 }
1573 
1574 static void AircraftEventHandler_EndTakeOff(Aircraft *v, const AirportFTAClass *apc)
1575 {
1576  v->state = FLYING;
1577  /* get the next position to go to, differs per airport */
1579 }
1580 
1581 static void AircraftEventHandler_HeliTakeOff(Aircraft *v, const AirportFTAClass *apc)
1582 {
1583  v->state = FLYING;
1584  v->UpdateDeltaXY();
1585 
1586  /* get the next position to go to, differs per airport */
1588 
1589  /* Send the helicopter to a hangar if needed for replacement */
1590  if (v->NeedsAutomaticServicing()) {
1591  Backup<CompanyID> cur_company(_current_company, v->owner, FILE_LINE);
1593  cur_company.Restore();
1594  }
1595 }
1596 
1597 static void AircraftEventHandler_Flying(Aircraft *v, const AirportFTAClass *apc)
1598 {
1600 
1601  /* Runway busy, not allowed to use this airstation or closed, circle. */
1602  if (CanVehicleUseStation(v, st) && (st->owner == OWNER_NONE || st->owner == v->owner) && !(st->airport.flags & AIRPORT_CLOSED_block)) {
1603  /* {32,FLYING,NOTHING_block,37}, {32,LANDING,N,33}, {32,HELILANDING,N,41},
1604  * if it is an airplane, look for LANDING, for helicopter HELILANDING
1605  * it is possible to choose from multiple landing runways, so loop until a free one is found */
1606  byte landingtype = (v->subtype == AIR_HELICOPTER) ? HELILANDING : LANDING;
1607  const AirportFTA *current = apc->layout[v->pos].next;
1608  while (current != nullptr) {
1609  if (current->heading == landingtype) {
1610  /* save speed before, since if AirportHasBlock is false, it resets them to 0
1611  * we don't want that for plane in air
1612  * hack for speed thingie */
1613  uint16 tcur_speed = v->cur_speed;
1614  uint16 tsubspeed = v->subspeed;
1615  if (!AirportHasBlock(v, current, apc)) {
1616  v->state = landingtype; // LANDING / HELILANDING
1618  /* it's a bit dirty, but I need to set position to next position, otherwise
1619  * if there are multiple runways, plane won't know which one it took (because
1620  * they all have heading LANDING). And also occupy that block! */
1621  v->pos = current->next_position;
1622  SETBITS(st->airport.flags, apc->layout[v->pos].block);
1623  return;
1624  }
1625  v->cur_speed = tcur_speed;
1626  v->subspeed = tsubspeed;
1627  }
1628  current = current->next;
1629  }
1630  }
1631  v->state = FLYING;
1632  v->pos = apc->layout[v->pos].next_position;
1633 }
1634 
1635 static void AircraftEventHandler_Landing(Aircraft *v, const AirportFTAClass *apc)
1636 {
1637  v->state = ENDLANDING;
1638  AircraftLandAirplane(v); // maybe crash airplane
1639 
1640  /* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed */
1641  if (v->NeedsAutomaticServicing()) {
1642  Backup<CompanyID> cur_company(_current_company, v->owner, FILE_LINE);
1644  cur_company.Restore();
1645  }
1646 }
1647 
1648 static void AircraftEventHandler_HeliLanding(Aircraft *v, const AirportFTAClass *apc)
1649 {
1650  v->state = HELIENDLANDING;
1651  v->UpdateDeltaXY();
1652 }
1653 
1654 static void AircraftEventHandler_EndLanding(Aircraft *v, const AirportFTAClass *apc)
1655 {
1656  /* next block busy, don't do a thing, just wait */
1657  if (AirportHasBlock(v, &apc->layout[v->pos], apc)) return;
1658 
1659  /* if going to terminal (OT_GOTO_STATION) choose one
1660  * 1. in case all terminals are busy AirportFindFreeTerminal() returns false or
1661  * 2. not going for terminal (but depot, no order),
1662  * --> get out of the way to the hangar. */
1663  if (v->current_order.IsType(OT_GOTO_STATION)) {
1664  if (AirportFindFreeTerminal(v, apc)) return;
1665  }
1666  v->state = HANGAR;
1667 
1668 }
1669 
1670 static void AircraftEventHandler_HeliEndLanding(Aircraft *v, const AirportFTAClass *apc)
1671 {
1672  /* next block busy, don't do a thing, just wait */
1673  if (AirportHasBlock(v, &apc->layout[v->pos], apc)) return;
1674 
1675  /* if going to helipad (OT_GOTO_STATION) choose one. If airport doesn't have helipads, choose terminal
1676  * 1. in case all terminals/helipads are busy (AirportFindFreeHelipad() returns false) or
1677  * 2. not going for terminal (but depot, no order),
1678  * --> get out of the way to the hangar IF there are terminals on the airport.
1679  * --> else TAKEOFF
1680  * the reason behind this is that if an airport has a terminal, it also has a hangar. Airplanes
1681  * must go to a hangar. */
1682  if (v->current_order.IsType(OT_GOTO_STATION)) {
1683  if (AirportFindFreeHelipad(v, apc)) return;
1684  }
1686 }
1687 
1693 typedef void AircraftStateHandler(Aircraft *v, const AirportFTAClass *apc);
1696  AircraftEventHandler_General, // TO_ALL = 0
1697  AircraftEventHandler_InHangar, // HANGAR = 1
1698  AircraftEventHandler_AtTerminal, // TERM1 = 2
1699  AircraftEventHandler_AtTerminal, // TERM2 = 3
1700  AircraftEventHandler_AtTerminal, // TERM3 = 4
1701  AircraftEventHandler_AtTerminal, // TERM4 = 5
1702  AircraftEventHandler_AtTerminal, // TERM5 = 6
1703  AircraftEventHandler_AtTerminal, // TERM6 = 7
1704  AircraftEventHandler_AtTerminal, // HELIPAD1 = 8
1705  AircraftEventHandler_AtTerminal, // HELIPAD2 = 9
1706  AircraftEventHandler_TakeOff, // TAKEOFF = 10
1707  AircraftEventHandler_StartTakeOff, // STARTTAKEOFF = 11
1708  AircraftEventHandler_EndTakeOff, // ENDTAKEOFF = 12
1709  AircraftEventHandler_HeliTakeOff, // HELITAKEOFF = 13
1710  AircraftEventHandler_Flying, // FLYING = 14
1711  AircraftEventHandler_Landing, // LANDING = 15
1712  AircraftEventHandler_EndLanding, // ENDLANDING = 16
1713  AircraftEventHandler_HeliLanding, // HELILANDING = 17
1714  AircraftEventHandler_HeliEndLanding, // HELIENDLANDING = 18
1715  AircraftEventHandler_AtTerminal, // TERM7 = 19
1716  AircraftEventHandler_AtTerminal, // TERM8 = 20
1717  AircraftEventHandler_AtTerminal, // HELIPAD3 = 21
1718 };
1719 
1720 static void AirportClearBlock(const Aircraft *v, const AirportFTAClass *apc)
1721 {
1722  /* we have left the previous block, and entered the new one. Free the previous block */
1723  if (apc->layout[v->previous_pos].block != apc->layout[v->pos].block) {
1725 
1726  CLRBITS(st->airport.flags, apc->layout[v->previous_pos].block);
1727  }
1728 }
1729 
1730 static void AirportGoToNextPosition(Aircraft *v)
1731 {
1732  /* if aircraft is not in position, wait until it is */
1733  if (!AircraftController(v)) return;
1734 
1736 
1737  AirportClearBlock(v, apc);
1738  AirportMove(v, apc); // move aircraft to next position
1739 }
1740 
1741 /* gets pos from vehicle and next orders */
1742 static bool AirportMove(Aircraft *v, const AirportFTAClass *apc)
1743 {
1744  /* error handling */
1745  if (v->pos >= apc->nofelements) {
1746  DEBUG(misc, 0, "[Ap] position %d is not valid for current airport. Max position is %d", v->pos, apc->nofelements-1);
1747  assert(v->pos < apc->nofelements);
1748  }
1749 
1750  const AirportFTA *current = &apc->layout[v->pos];
1751  /* we have arrived in an important state (eg terminal, hangar, etc.) */
1752  if (current->heading == v->state) {
1753  byte prev_pos = v->pos; // location could be changed in state, so save it before-hand
1754  byte prev_state = v->state;
1755  _aircraft_state_handlers[v->state](v, apc);
1756  if (v->state != FLYING) v->previous_pos = prev_pos;
1757  if (v->state != prev_state || v->pos != prev_pos) UpdateAircraftCache(v);
1758  return true;
1759  }
1760 
1761  v->previous_pos = v->pos; // save previous location
1762 
1763  /* there is only one choice to move to */
1764  if (current->next == nullptr) {
1765  if (AirportSetBlocks(v, current, apc)) {
1766  v->pos = current->next_position;
1768  } // move to next position
1769  return false;
1770  }
1771 
1772  /* there are more choices to choose from, choose the one that
1773  * matches our heading */
1774  do {
1775  if (v->state == current->heading || current->heading == TO_ALL) {
1776  if (AirportSetBlocks(v, current, apc)) {
1777  v->pos = current->next_position;
1779  } // move to next position
1780  return false;
1781  }
1782  current = current->next;
1783  } while (current != nullptr);
1784 
1785  DEBUG(misc, 0, "[Ap] cannot move further on Airport! (pos %d state %d) for vehicle %d", v->pos, v->state, v->index);
1786  NOT_REACHED();
1787 }
1788 
1790 static bool AirportHasBlock(Aircraft *v, const AirportFTA *current_pos, const AirportFTAClass *apc)
1791 {
1792  const AirportFTA *reference = &apc->layout[v->pos];
1793  const AirportFTA *next = &apc->layout[current_pos->next_position];
1794 
1795  /* same block, then of course we can move */
1796  if (apc->layout[current_pos->position].block != next->block) {
1797  const Station *st = Station::Get(v->targetairport);
1798  uint64 airport_flags = next->block;
1799 
1800  /* check additional possible extra blocks */
1801  if (current_pos != reference && current_pos->block != NOTHING_block) {
1802  airport_flags |= current_pos->block;
1803  }
1804 
1805  if (st->airport.flags & airport_flags) {
1806  v->cur_speed = 0;
1807  v->subspeed = 0;
1808  return true;
1809  }
1810  }
1811  return false;
1812 }
1813 
1821 static bool AirportSetBlocks(Aircraft *v, const AirportFTA *current_pos, const AirportFTAClass *apc)
1822 {
1823  const AirportFTA *next = &apc->layout[current_pos->next_position];
1824  const AirportFTA *reference = &apc->layout[v->pos];
1825 
1826  /* if the next position is in another block, check it and wait until it is free */
1827  if ((apc->layout[current_pos->position].block & next->block) != next->block) {
1828  uint64 airport_flags = next->block;
1829  /* search for all all elements in the list with the same state, and blocks != N
1830  * this means more blocks should be checked/set */
1831  const AirportFTA *current = current_pos;
1832  if (current == reference) current = current->next;
1833  while (current != nullptr) {
1834  if (current->heading == current_pos->heading && current->block != 0) {
1835  airport_flags |= current->block;
1836  break;
1837  }
1838  current = current->next;
1839  }
1840 
1841  /* if the block to be checked is in the next position, then exclude that from
1842  * checking, because it has been set by the airplane before */
1843  if (current_pos->block == next->block) airport_flags ^= next->block;
1844 
1846  if (st->airport.flags & airport_flags) {
1847  v->cur_speed = 0;
1848  v->subspeed = 0;
1849  return false;
1850  }
1851 
1852  if (next->block != NOTHING_block) {
1853  SETBITS(st->airport.flags, airport_flags); // occupy next block
1854  }
1855  }
1856  return true;
1857 }
1858 
1865  uint64 airport_flag;
1866 };
1867 
1870  {TERM1, TERM1_block},
1871  {TERM2, TERM2_block},
1872  {TERM3, TERM3_block},
1873  {TERM4, TERM4_block},
1874  {TERM5, TERM5_block},
1875  {TERM6, TERM6_block},
1876  {TERM7, TERM7_block},
1877  {TERM8, TERM8_block},
1881 };
1882 
1890 static bool FreeTerminal(Aircraft *v, byte i, byte last_terminal)
1891 {
1892  assert(last_terminal <= lengthof(_airport_terminal_mapping));
1894  for (; i < last_terminal; i++) {
1895  if ((st->airport.flags & _airport_terminal_mapping[i].airport_flag) == 0) {
1896  /* TERMINAL# HELIPAD# */
1897  v->state = _airport_terminal_mapping[i].state; // start moving to that terminal/helipad
1898  SETBITS(st->airport.flags, _airport_terminal_mapping[i].airport_flag); // occupy terminal/helipad
1899  return true;
1900  }
1901  }
1902  return false;
1903 }
1904 
1910 static uint GetNumTerminals(const AirportFTAClass *apc)
1911 {
1912  uint num = 0;
1913 
1914  for (uint i = apc->terminals[0]; i > 0; i--) num += apc->terminals[i];
1915 
1916  return num;
1917 }
1918 
1926 {
1927  /* example of more terminalgroups
1928  * {0,HANGAR,NOTHING_block,1}, {0,TERMGROUP,TERM_GROUP1_block,0}, {0,TERMGROUP,TERM_GROUP2_ENTER_block,1}, {0,0,N,1},
1929  * Heading TERMGROUP denotes a group. We see 2 groups here:
1930  * 1. group 0 -- TERM_GROUP1_block (check block)
1931  * 2. group 1 -- TERM_GROUP2_ENTER_block (check block)
1932  * First in line is checked first, group 0. If the block (TERM_GROUP1_block) is free, it
1933  * looks at the corresponding terminals of that group. If no free ones are found, other
1934  * possible groups are checked (in this case group 1, since that is after group 0). If that
1935  * fails, then attempt fails and plane waits
1936  */
1937  if (apc->terminals[0] > 1) {
1938  const Station *st = Station::Get(v->targetairport);
1939  const AirportFTA *temp = apc->layout[v->pos].next;
1940 
1941  while (temp != nullptr) {
1942  if (temp->heading == TERMGROUP) {
1943  if (!(st->airport.flags & temp->block)) {
1944  /* read which group do we want to go to?
1945  * (the first free group) */
1946  uint target_group = temp->next_position + 1;
1947 
1948  /* at what terminal does the group start?
1949  * that means, sum up all terminals of
1950  * groups with lower number */
1951  uint group_start = 0;
1952  for (uint i = 1; i < target_group; i++) {
1953  group_start += apc->terminals[i];
1954  }
1955 
1956  uint group_end = group_start + apc->terminals[target_group];
1957  if (FreeTerminal(v, group_start, group_end)) return true;
1958  }
1959  } else {
1960  /* once the heading isn't 255, we've exhausted the possible blocks.
1961  * So we cannot move */
1962  return false;
1963  }
1964  temp = temp->next;
1965  }
1966  }
1967 
1968  /* if there is only 1 terminalgroup, all terminals are checked (starting from 0 to max) */
1969  return FreeTerminal(v, 0, GetNumTerminals(apc));
1970 }
1971 
1979 {
1980  /* if an airport doesn't have helipads, use terminals */
1981  if (apc->num_helipads == 0) return AirportFindFreeTerminal(v, apc);
1982 
1983  /* only 1 helicoptergroup, check all helipads
1984  * The blocks for helipads start after the last terminal (MAX_TERMINALS) */
1986 }
1987 
1993 static void AircraftHandleDestTooFar(Aircraft *v, bool too_far)
1994 {
1995  if (too_far) {
1996  if (!HasBit(v->flags, VAF_DEST_TOO_FAR)) {
1999  AI::NewEvent(v->owner, new ScriptEventAircraftDestTooFar(v->index));
2000  if (v->owner == _local_company) {
2001  /* Post a news message. */
2002  SetDParam(0, v->index);
2003  AddVehicleAdviceNewsItem(STR_NEWS_AIRCRAFT_DEST_TOO_FAR, v->index);
2004  }
2005  }
2006  return;
2007  }
2008 
2009  if (HasBit(v->flags, VAF_DEST_TOO_FAR)) {
2010  /* Not too far anymore, clear flag and message. */
2013  DeleteVehicleNews(v->index, STR_NEWS_AIRCRAFT_DEST_TOO_FAR);
2014  }
2015 }
2016 
2017 static bool AircraftEventHandler(Aircraft *v, int loop)
2018 {
2019  if (v->vehstatus & VS_CRASHED) {
2020  return HandleCrashedAircraft(v);
2021  }
2022 
2023  if (v->vehstatus & VS_STOPPED) return true;
2024 
2025  v->HandleBreakdown();
2026 
2027  HandleAircraftSmoke(v, loop != 0);
2028  ProcessOrders(v);
2029  v->HandleLoading(loop != 0);
2030 
2031  if (v->current_order.IsType(OT_LOADING) || v->current_order.IsType(OT_LEAVESTATION)) return true;
2032 
2033  if (v->state >= ENDTAKEOFF && v->state <= HELIENDLANDING) {
2034  /* If we are flying, unconditionally clear the 'dest too far' state. */
2035  AircraftHandleDestTooFar(v, false);
2036  } else if (v->acache.cached_max_range_sqr != 0) {
2037  /* Check the distance to the next destination. This code works because the target
2038  * airport is only updated after take off and not on the ground. */
2040  Station *next_st = v->current_order.IsType(OT_GOTO_STATION) || v->current_order.IsType(OT_GOTO_DEPOT) ? Station::GetIfValid(v->current_order.GetDestination()) : nullptr;
2041 
2042  if (cur_st != nullptr && cur_st->airport.tile != INVALID_TILE && next_st != nullptr && next_st->airport.tile != INVALID_TILE) {
2043  uint dist = DistanceSquare(cur_st->airport.tile, next_st->airport.tile);
2044  AircraftHandleDestTooFar(v, dist > v->acache.cached_max_range_sqr);
2045  }
2046  }
2047 
2048  if (!HasBit(v->flags, VAF_DEST_TOO_FAR)) AirportGoToNextPosition(v);
2049 
2050  return true;
2051 }
2052 
2054 {
2055  if (!this->IsNormalAircraft()) return true;
2056 
2058 
2059  this->tick_counter++;
2060 
2061  if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
2062 
2063  if (this->subtype == AIR_HELICOPTER) HelicopterTickHandler(this);
2064 
2065  this->current_order_time++;
2066 
2067  for (uint i = 0; i != 2; i++) {
2068  /* stop if the aircraft was deleted */
2069  if (!AircraftEventHandler(this, i)) return false;
2070  }
2071 
2072  return true;
2073 }
2074 
2075 
2083 {
2084  assert(v->type == VEH_AIRCRAFT);
2085 
2087  if (st == nullptr) return nullptr;
2088 
2089  return st->airport.tile == INVALID_TILE ? nullptr : st;
2090 }
2091 
2097 {
2098  /* only 1 station is updated per function call, so it is enough to get entry_point once */
2099  const AirportFTAClass *ap = st->airport.GetFTA();
2100  Direction rotation = st->airport.tile == INVALID_TILE ? DIR_N : st->airport.rotation;
2101 
2102  Aircraft *v;
2103  FOR_ALL_AIRCRAFT(v) {
2104  if (!v->IsNormalAircraft() || v->targetairport != st->index) continue;
2105  assert(v->state == FLYING);
2106 
2107  Order *o = &v->current_order;
2108  /* The aircraft is heading to a hangar, but the new station doesn't have one,
2109  * or the aircraft can't land on the new station. Cancel current order. */
2110  if (o->IsType(OT_GOTO_DEPOT) && !(o->GetDepotOrderType() & ODTFB_PART_OF_ORDERS) && o->GetDestination() == st->index &&
2111  (!st->airport.HasHangar() || !CanVehicleUseStation(v, st))) {
2112  o->MakeDummy();
2114  }
2115  v->pos = v->previous_pos = AircraftGetEntryPoint(v, ap, rotation);
2117  }
2118 
2119  /* Heliports don't have a hangar. Invalidate all go to hangar orders from all aircraft. */
2120  if (!st->airport.HasHangar()) RemoveOrderFromAllVehicles(OT_GOTO_DEPOT, st->index, true);
2121 }
Functions related to OTTD&#39;s strings.
byte number_consecutive_turns
Protection to prevent the aircraft of making a lot of turns in order to reach a specific point...
Definition: aircraft.h:83
VehicleSettings vehicle
options for vehicles
This vehicle is in the exclusive preview stage, either being used or being offered to a company...
Definition: engine_type.h:171
uint16 reliability
Current reliability of the engine.
Definition: engine_base.h:27
byte type
Type of this airport,.
Definition: station_base.h:311
Date max_age
Maximum age.
Definition: vehicle_base.h:259
uint32 PaletteID
The number of the palette.
Definition: gfx_type.h:20
StationFacility facilities
The facilities that this station has.
Vehicle is stopped by the player.
Definition: vehicle_base.h:33
First vehicle arrived for competitor.
Definition: news_type.h:25
Airplane wants to leave the airport.
Definition: airport.h:73
This airport has a short landing strip, dangerous for fast aircraft.
Definition: airport.h:152
void AircraftLeaveHangar(Aircraft *v, Direction exit_dir)
Aircraft is about to leave the hangar.
byte GetVehiclePosOnBuild(TileIndex hangar_tile)
Get the vehicle position when an aircraft is build at the given tile.
Definition: airport.cpp:220
VehicleCargoList cargo
The cargo this vehicle is carrying.
Definition: vehicle_base.h:309
GameSettings _settings_game
Game settings of a running game or the scenario editor.
Definition: settings.cpp:81
Heading for hangar.
Definition: airport.h:64
static void NewEvent(class ScriptEvent *event)
Queue a new event for a Game Script.
Definition: game_core.cpp:143
Definition of stuff that is very close to a company, like the company struct itself.
Heading for terminal 1.
Definition: airport.h:65
Functions for NewGRF engines.
Airplane has reached end-point of the take-off runway.
Definition: airport.h:75
CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine *e, uint16 data, Vehicle **ret)
Build an aircraft.
void DecreaseVehicleValue(Vehicle *v)
Decrease the value of a vehicle.
Definition: vehicle.cpp:1204
static const int DAYS_IN_YEAR
days per year
Definition: date_type.h:31
Finite sTate mAchine (FTA) of an airport.
Definition: airport.h:145
void AircraftNextAirportPos_and_Order(Aircraft *v)
set the right pos when heading to other airports after takeoff
Heading for helipad 2.
Definition: airport.h:72
All disaster vehicles.
byte nofelements
number of positions the airport consists of
Definition: airport.h:183
Direction direction
facing
Definition: vehicle_base.h:271
Takeoff movement.
Definition: airport.h:51
Direction rotation
How this airport is rotated.
Definition: station_base.h:313
StationID targetairport
Airport to go to next.
Definition: aircraft.h:80
static bool HandleCrashedAircraft(Aircraft *v)
Handle crashed aircraft v.
Station * GetTargetAirportIfValid(const Aircraft *v)
Returns aircraft&#39;s target station if v->target_airport is a valid station with airport.
const AirportFTAClass * GetAirport(const byte airport_type)
Get the finite state machine of an airport type.
Definition: airport.cpp:209
void SetWindowDirty(WindowClass cls, WindowNumber number)
Mark window as dirty (in need of repainting)
Definition: window.cpp:3199
static DiagDirection DirToDiagDir(Direction dir)
Convert a Direction to a DiagDirection.
byte next_position
next position from this position
Definition: airport.h:196
Direction GetHangarExitDirection(TileIndex tile) const
Get the exit direction of the hangar at a specific tile.
Definition: station_base.h:392
Maximum speed of an aircraft that is broken.
static int UnScaleGUI(int value)
Short-hand to apply GUI zoom level.
Definition: zoom_func.h:68
Aircraft range.
static const uint64 HELIPAD1_block
Block belonging to helipad 1.
Definition: airport.h:97
Minimum flying altitude above tile.
Definition: aircraft.h:23
void CheckOrders(const Vehicle *v)
Check the orders of a vehicle, to see if there are invalid orders and stuff.
Definition: order_cmd.cpp:1726
A single location on an airport where aircraft can move to.
Definition: airport.h:133
Aircraft is broken down.
Definition: vehicle_base.h:38
bool HasHangar() const
Check if this airport has at least one hangar.
Definition: station_base.h:340
bool serviceathelipad
service helicopters at helipads automatically (no need to send to depot)
static Titem * Get(size_t index)
Returns Titem with given index.
Definition: pool_type.hpp:246
bool Tick()
Calls the tick handler of the vehicle.
static const uint64 TERM6_block
Block belonging to terminal 6.
Definition: airport.h:96
Functions related to dates.
No speed restrictions.
Definition: airport.h:50
Angle of 45 degrees left.
Dummy airport.
Definition: airport.h:45
virtual uint Crash(bool flooded=false)
Crash the (whole) vehicle chain.
Definition: vehicle.cpp:261
Heading for terminal 6.
Definition: airport.h:70
Conventional Take Off and Landing, i.e. planes.
Definition: engine_type.h:94
Northwest.
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:334
Various explosions.
Use default vehicle palette.
Definition: vehicle_base.h:35
West.
Vehicle is a shadow vehicle.
Definition: vehicle_base.h:37
Helicopter landing.
Definition: airport.h:57
static T SetBit(T &x, const uint8 y)
Set a bit in a variable.
Vehicle drawn in viewport.
Definition: vehicle_type.h:88
byte pos
Next desired position of the aircraft.
Definition: aircraft.h:78
Can planes land on this airport type?
Definition: airport.h:149
Taxiing at the airport.
Definition: airport.h:55
uint16 cur_speed
current speed
Definition: vehicle_base.h:293
uint16 cached_cargo_age_period
Number of ticks before carried cargo is aged.
Definition: vehicle_base.h:124
const byte * entry_points
when an airplane arrives at this airport, enter it at position entry_point, index depends on directio...
Definition: airport.h:184
uint Truncate(uint max_move=UINT_MAX)
Truncates the cargo in this list to the given amount.
static void AddVehicleAdviceNewsItem(StringID string, VehicleID vehicle)
Adds a vehicle-advice news item.
Definition: news_func.h:42
static const CommandCost CMD_ERROR
Define a default return value for a failed command.
Definition: command_func.h:25
static int ScaleGUITrad(int value)
Scale traditional pixel dimensions to GUI zoom level.
Definition: zoom_func.h:78
Depot view; Window numbers:
Definition: window_type.h:346
Maximal number of cargo types in a game.
Definition: cargo_type.h:66
Direction direction
Direction to turn the aircraft after reaching the destination.
Definition: airport.h:137
static const int ROTOR_Z_OFFSET
Z Offset between helicopter- and rotorsprite.
Definition: aircraft.h:52
Types for recording game performance data.
byte spritenum
currently displayed sprite index 0xfd == custom sprite, 0xfe == custom second head sprite 0xff == res...
Definition: vehicle_base.h:279
Both directions faces to the same direction.
void UpdateAircraftCache(Aircraft *v, bool update_range)
Update cached values of an aircraft.
an airplane
Definition: aircraft.h:34
fluid_settings_t * settings
FluidSynth settings handle.
Definition: fluidsynth.cpp:22
static byte 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...
StationID last_loading_station
Last station the vehicle has stopped at and could possibly leave from with any cargo loaded...
Definition: vehicle_base.h:303
#define SETBITS(x, y)
Sets several bits in a variable.
Functions related to vehicles.
Aircraft, helicopters, rotors and their shadows belong to this class.
Definition: aircraft.h:76
uint32 current_order_time
How many ticks have passed since this order started.
Definition: base_consist.h:23
void SetAircraftPosition(Aircraft *v, int x, int y, int z)
Set aircraft position.
static uint TileX(TileIndex tile)
Get the X component of a tile.
Definition: map_func.h:207
void VehicleEnterDepot(Vehicle *v)
Vehicle entirely entered the depot, update its status, orders, vehicle windows, service it...
Definition: vehicle.cpp:1441
void Draw(int x, int y, PaletteID default_pal, bool force_pal) const
Draw the sprite sequence.
Definition: vehicle.cpp:128
Vehicle data structure.
Definition: vehicle_base.h:212
static bool AircraftController(Aircraft *v)
Controls the movement of an aircraft.
Flags flags
Flags for this airport type.
Definition: airport.h:182
int16 y
y-coordinate of the destination.
Definition: airport.h:135
void Set(SpriteID sprite)
Assign a single sprite to the sequence.
Definition: vehicle_base.h:163
Start or stop this vehicle, and show information about the current state.
Tindex index
Index of this pool item.
Definition: pool_type.hpp:147
Vehicle is flying in the air.
Definition: airport.h:77
The vehicle is currently raising its altitude because it hit the lower bound.
Definition: aircraft.h:47
static const int DAY_TICKS
1 day is 74 ticks; _date_fract used to be uint16 and incremented by 885.
Definition: date_type.h:30
void SetNext(Vehicle *next)
Set the next vehicle of this vehicle.
Definition: vehicle.cpp:2667
void UpdateViewport(bool force_update, bool update_delta)
Update vehicle sprite- and position caches.
static void AircraftEventHandler_InHangar(Aircraft *v, const AirportFTAClass *apc)
Handle aircraft movement/decision making in an airport hangar.
Base for aircraft.
StationID last_station_visited
The last station we stopped at.
Definition: vehicle_base.h:302
static void AircraftEntersTerminal(Aircraft *v)
Aircraft arrives at a terminal.
uint16 reliability_spd_dec
Reliability decrease speed.
Definition: vehicle_base.h:262
Money GetCost() const
The costs as made up to this moment.
Definition: command_type.h:84
AircraftSpeedLimits
Special velocities for aircraft.
int GetTileHeightBelowAircraft(const Vehicle *v)
Get the tile height below the aircraft.
#define CLRBITS(x, y)
Clears several bits in a variable.
static const uint64 HELIPAD3_block
Block belonging to helipad 3.
Definition: airport.h:119
Common return value for all commands.
Definition: command_type.h:25
holding flying altitude above tile of planes.
Definition: aircraft.h:25
StationCargoList cargo
The cargo packets of cargo waiting in this station.
Definition: station_base.h:257
static T max(const T a, const T b)
Returns the maximum of two values.
Definition: math_func.hpp:26
byte vehstatus
Status.
Definition: vehicle_base.h:317
EngineImageType
Visualisation contexts of vehicles and engines.
Definition: vehicle_type.h:87
byte flags
Flags of the engine.
Definition: engine_base.h:35
uint Crash(bool flooded=false)
Crash the (whole) vehicle chain.
Year _cur_year
Current year, starting at 0.
Definition: date.cpp:26
Helicopter wants to land.
Definition: airport.h:80
uint16 w
The width of the area.
Definition: tilearea_type.h:20
Time spent processing aircraft.
static Aircraft * From(Vehicle *v)
Converts a Vehicle to SpecializedVehicle with type checking.
static DiagDirDiff DiagDirDifference(DiagDirection d0, DiagDirection d1)
Calculate the difference between two DiagDirection values.
uint16 cached_max_speed
Maximum speed of the consist (minimum of the max speed of all vehicles in the consist).
Definition: vehicle_base.h:123
bool NeedsAutomaticServicing() const
Checks if the current order should be interrupted for a service-in-depot order.
Definition: vehicle.cpp:253
const Engine * GetEngine() const
Retrieves the engine of the vehicle.
Definition: vehicle.cpp:745
CargoID GetDefaultCargoType() const
Determines the default cargo type of an engine.
Definition: engine_base.h:81
bool IsNormalAircraft() const
Check if the aircraft type is a normal flying device; eg not a rotor or a shadow. ...
Definition: aircraft.h:123
GoodsEntry goods[NUM_CARGO]
Goods at this station.
Definition: station_base.h:481
static const uint TILE_SIZE
Tile size in world coordinates.
Definition: tile_type.h:15
byte VehicleRandomBits()
Get a value for a vehicle&#39;s random_bits.
Definition: vehicle.cpp:363
Go exactly to the destination coordinates.
Definition: airport.h:54
Find another airport if the target one lacks a hangar.
Definition: vehicle_type.h:71
Money GetPrice(Price index, uint cost_factor, const GRFFile *grf_file, int shift)
Determine a certain price.
Definition: economy.cpp:966
VehicleSpriteSeq sprite_seq
Vehicle appearance.
Definition: vehicle_base.h:280
North.
Various explosions.
Class to backup a specific variable and restore it later.
Definition: backup_type.hpp:23
Holding pattern movement (above the airport).
Definition: airport.h:58
Cheat no_jetcrash
no jet will crash on small airports anymore
Definition: cheat_type.h:34
Pseudo random number generator.
Running costs aircraft.
Definition: economy_type.h:155
static const uint64 HELIPAD2_block
Block belonging to helipad 2.
Definition: airport.h:98
Angle of 45 degrees right.
byte breakdown_ctr
Counter for managing breakdown events.
Definition: vehicle_base.h:263
byte subtype
subtype (Filled with values from AircraftSubType/DisasterSubType/EffectVehicleType/GroundVehicleSubty...
Definition: vehicle_base.h:327
static bool FreeTerminal(Aircraft *v, byte i, byte last_terminal)
Find a free terminal or helipad, and if available, assign it.
uint16 cargo_cap
total capacity
Definition: vehicle_base.h:307
holding flying altitude above tile of helicopters.
Definition: aircraft.h:26
OrderDepotTypeFlags GetDepotOrderType() const
What caused us going to the depot?
Definition: order_base.h:137
Vehicle is crashed.
Definition: vehicle_base.h:39
Vehicle is a prototype (accepted as exclusive preview).
Definition: vehicle_base.h:46
Turn slowly (mostly used in the air).
Definition: airport.h:52
byte acceleration
used by train & aircraft
Definition: vehicle_base.h:295
byte rating
Station rating for this cargo.
Definition: station_base.h:237
The tile has no ownership.
Definition: company_type.h:27
uint16 reliability_spd_dec
Speed of reliability decay between services (per day).
Definition: engine_base.h:28
static void AircraftEventHandler_AtTerminal(Aircraft *v, const AirportFTAClass *apc)
At one of the Airport&#39;s Terminals.
Combination of aircraft state for going to a certain terminal and the airport flag for that terminal ...
Types related to cheating.
void SubtractMoneyFromCompanyFract(CompanyID company, CommandCost cst)
Subtract money from a company, including the money fraction.
Southeast.
static bool AirportSetBlocks(Aircraft *v, const AirportFTA *current_pos, const AirportFTAClass *apc)
"reserve" a block for the plane
int y
x and y position of the vehicle after moving
Definition: vehicle_func.h:78
CommandCost DoCommand(const CommandContainer *container, DoCommandFlag flags)
Shorthand for calling the long DoCommand with a container.
Definition: command.cpp:443
byte subtype
Type of aircraft.
Definition: engine_type.h:103
void AgeVehicle(Vehicle *v)
Update age of a vehicle.
Definition: vehicle.cpp:1332
bool IsValid() const
Check whether the sequence contains any sprites.
Definition: vehicle_base.h:147
void DeleteVehicleNews(VehicleID vid, StringID news)
Delete a news item type about a vehicle.
Definition: news_gui.cpp:850
SoundSettings sound
sound effect settings
Internal structure used in openttd - Finite sTate mAchine –> FTA.
Definition: airport.h:192
void MakeDummy()
Makes this order a Dummy order.
Definition: order_cmd.cpp:134
Heading for terminal 7.
Definition: airport.h:82
int8 y_offs
y offset for vehicle sprite
Definition: vehicle_base.h:287
East.
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition: order_base.h:63
Southeast.
DoCommandFlag
List of flags for a command.
Definition: command_type.h:344
T * Next() const
Get next vehicle in the chain.
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:80
Heading for terminal 2.
Definition: airport.h:66
Definition of base types and functions in a cross-platform compatible way.
const byte num_helipads
Number of helipads on this airport. When 0 helicopters will go to normal terminals.
Definition: airport.h:181
A number of safeguards to prevent using unsafe methods.
byte x_extent
x-extent of vehicle bounding box
Definition: vehicle_base.h:281
bool value
tells if the bool cheat is active or not
Definition: cheat_type.h:20
static const uint64 AIRPORT_CLOSED_block
Dummy block for indicating a closed airport.
Definition: airport.h:130
void InvalidateNewGRFCacheOfChain()
Invalidates cached NewGRF variables of all vehicles in the chain (after the current vehicle) ...
Definition: vehicle_base.h:460
bool ProcessOrders(Vehicle *v)
Handle the orders of a vehicle and determine the next place to go to if needed.
Definition: order_cmd.cpp:2134
Direction
Defines the 8 directions on the map.
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).
DirDiff
Enumeration for the difference between two directions.
static uint CeilDiv(uint a, uint b)
Computes ceil(a / b) for non-negative a and b.
Definition: math_func.hpp:316
static void CrashAirplane(Aircraft *v)
Bring the aircraft in a crashed state, create the explosion animation, and create a news item about t...
struct AirportFTA * layout
state machine for airport
Definition: airport.h:179
byte z_extent
z-extent of vehicle bounding box
Definition: vehicle_base.h:283
Vehicle starting, i.e. leaving, the station.
Definition: newgrf_sound.h:21
CargoID cargo_type
type of cargo this vehicle is carrying
Definition: vehicle_base.h:305
static const uint TILE_HEIGHT
Height of a height level in world coordinate AND in pixels in #ZOOM_LVL_BASE.
Definition: tile_type.h:18
Vehicle view; Window numbers:
Definition: window_type.h:334
The vehicle is currently lowering its altitude because it hit the upper bound.
Definition: aircraft.h:46
static DiagDirection ChangeDiagDir(DiagDirection d, DiagDirDiff delta)
Applies a difference on a DiagDirection.
TileIndex tile
Current tile index.
Definition: vehicle_base.h:230
void GetAircraftFlightLevelBounds(const Vehicle *v, int *min_level, int *max_level)
Get the &#39;flight level&#39; bounds, in pixels from &#39;z_pos&#39; 0 for a particular vehicle for normal flight si...
bool CanVehicleUseStation(EngineID engine_type, const Station *st)
Can this station be used by the given engine type?
Definition: vehicle.cpp:2788
static DirDiff DirDifference(Direction d0, Direction d1)
Calculate the difference between two directions.
Heading for helipad 3.
Definition: airport.h:84
static Direction ChangeDir(Direction d, DirDiff delta)
Change a direction by a given difference.
int8 x_offs
x offset for vehicle sprite
Definition: vehicle_base.h:286
Owner owner
Which company owns the vehicle?
Definition: vehicle_base.h:273
Sprite sequence for a vehicle part.
Definition: vehicle_base.h:130
uint64 flags
stores which blocks on the airport are taken. was 16 bit earlier on, then 32
Definition: station_base.h:310
Heading for terminal 3.
Definition: airport.h:67
Airplane has arrived at a runway for take-off.
Definition: airport.h:74
#define lengthof(x)
Return the length of an fixed size array.
Definition: depend.cpp:42
const AirportMovingData * MovingData(byte position) const
Get movement data at a position.
Definition: airport.h:172
static T min(const T a, const T b)
Returns the minimum of two values.
Definition: math_func.hpp:42
byte previous_pos
Previous desired position of the aircraft.
Definition: aircraft.h:79
static void HandleAircraftSmoke(Aircraft *v, bool mode)
Handle smoke of broken aircraft.
uint8 plane_speed
divisor for speed of aircraft
uint16 refit_cap
Capacity left over from before last refit.
Definition: vehicle_base.h:308
byte random_bits
Bits used for determining which randomized variational spritegroups to use when drawing.
Definition: vehicle_base.h:299
Functions related to sound.
byte breakdowns_since_last_service
Counter for the amount of breakdowns.
Definition: vehicle_base.h:265
uint16 reliability
Reliability.
Definition: vehicle_base.h:261
Functions to cache sprites in memory.
uint32 StringID
Numeric value that represents a string, independent of the selected language.
Definition: strings_type.h:18
bool Failed() const
Did this command fail?
Definition: command_type.h:161
byte tick_counter
Increased by one for each tick.
Definition: vehicle_base.h:314
EffectVehicle * CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVehicleType type)
Create an effect vehicle above a particular vehicle.
static void AircraftLandAirplane(Aircraft *v)
Aircraft touched down at the landing strip.
static bool Chance16R(const uint a, const uint b, uint32 &r)
Flips a coin with a given probability and saves the randomize-number in a variable.
TileIndex GetHangarTile(uint hangar_num) const
Get the first tile of the given hangar.
Definition: station_base.h:375
AirportMovementStates
Movement States on Airports (headings target)
Definition: airport.h:62
uint8 plane_crashes
number of plane crashes, 0 = none, 1 = reduced, 2 = normal
Year build_year
Year the vehicle has been built.
Definition: vehicle_base.h:257
bool PlayVehicleSound(const Vehicle *v, VehicleSoundEvent event)
Checks whether a NewGRF wants to play a different vehicle sound effect.
NewGRF handling of airport tiles.
byte state
State of the airport.
Definition: aircraft.h:81
byte turn_counter
Ticks between each turn to prevent > 45 degree turns.
Definition: aircraft.h:84
static void NewEvent(CompanyID company, ScriptEvent *event)
Queue a new event for an AI.
Definition: ai_core.cpp:238
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:139
uint Truncate(uint max_move=UINT_MAX, StationCargoAmountMap *cargo_per_source=nullptr)
Truncates where each destination loses roughly the same percentage of its cargo.
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:37
Aircraft is looking for a free terminal in a terminalgroup.
Definition: airport.h:86
TileIndex old_tile
Current tile of the vehicle.
Definition: vehicle_func.h:79
TileIndex tile
The base tile of the area.
Definition: tilearea_type.h:19
static void AircraftEventHandler_EnterHangar(Aircraft *v, const AirportFTAClass *apc)
Aircraft arrived in an airport hangar.
Maximum speed of an aircraft while taxiing.
Maximum speed of an aircraft on finals.
int GetAircraftHoldMaxAltitude(const Aircraft *v)
Gets the maximum &#39;flight level&#39; for the holding pattern of the aircraft, in pixels &#39;z_pos&#39; 0...
static const uint MAX_TERMINALS
Some airport-related constants.
Definition: airport.h:19
TileIndex GetOrderStationLocation(StationID station)
Determine the location for the station where the vehicle goes to next.
char * name
Name of vehicle.
Definition: base_consist.h:20
execute the given command
Definition: command_type.h:346
Station with an airport.
Definition: station_type.h:57
static AircraftStateHandler *const _aircraft_state_handlers[]
Array of handler functions for each target of the aircraft.
The vehicle will leave the depot right after arrival (service only)
Definition: vehicle_type.h:68
uint GetHangarNum(TileIndex tile) const
Get the hangar number of the hangar at a specific tile.
Definition: station_base.h:405
Functions related to companies.
GetNewVehiclePosResult GetNewVehiclePos(const Vehicle *v)
Get position information of a vehicle when moving one pixel in the direction it is facing...
Definition: vehicle.cpp:1625
void UpdatePosition()
Update the position of the vehicle.
Definition: vehicle.cpp:1564
rotor of an helicopter
Definition: aircraft.h:36
static StationID GetStationIndex(TileIndex t)
Get StationID from a tile.
Definition: station_map.h:30
static TileIndex TileVirtXY(uint x, uint y)
Get a tile from the virtual XY-coordinate.
Definition: map_func.h:196
void HandleAircraftEnterHangar(Aircraft *v)
Handle Aircraft specific tasks when an Aircraft enters a hangar.
Maximum flying altitude above tile.
Definition: aircraft.h:24
Base class for engines.
Go in this direction for every target.
Definition: airport.h:63
static T ClrBit(T &x, const uint8 y)
Clears a bit in a variable.
uint16 cached_max_range
Cached maximum range.
Definition: aircraft.h:70
The helicopter is descending directly at its destination (helipad or in front of hangar) ...
Definition: aircraft.h:49
const GRFFile * GetGRF() const
Retrieve the NewGRF the engine is tied to.
Definition: engine_base.h:140
DestinationID GetDestination() const
Gets the destination of this order.
Definition: order_base.h:96
void VehicleServiceInDepot(Vehicle *v)
Service a vehicle and all subsequent vehicles in the consist.
Definition: vehicle.cpp:164
static bool AirportFindFreeHelipad(Aircraft *v, const AirportFTAClass *apc)
Find a free helipad, and assign it if available.
void SetWindowWidgetDirty(WindowClass cls, WindowNumber number, byte widget_index)
Mark a particular widget in a particular window as dirty (in need of repainting)
Definition: window.cpp:3213
byte subspeed
fractional speed
Definition: vehicle_base.h:294
void MakeGoToDepot(DepotID destination, OrderDepotTypeFlags order, OrderNonStopFlags non_stop_type=ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS, OrderDepotActionFlags action=ODATF_SERVICE_ONLY, CargoID cargo=CT_NO_REFIT)
Makes this order a Go To Depot order.
Definition: order_cmd.cpp:91
bool HandleBreakdown()
Handle all of the aspects of a vehicle breakdown This includes adding smoke and sounds, and ending the breakdown when appropriate.
Definition: vehicle.cpp:1266
void UpdateDeltaXY()
Updates the x and y offsets and the size of the sprite used for this vehicle.
static const uint64 TERM7_block
Block belonging to terminal 7.
Definition: airport.h:117
uint32 SpriteID
The number of a sprite, without mapping bits and colourtables.
Definition: gfx_type.h:19
No environmental speed limit. Speed limit is type dependent.
uint16 EngineID
Unique identification number of an engine.
Definition: engine_type.h:23
Oilrig airport.
Definition: airport.h:40
uint32 TileIndex
The index/ID of a Tile.
Definition: tile_type.h:80
static const PaletteID PALETTE_CRASH
Recolour sprite greying of crashed vehicles.
Definition: sprites.h:1589
void BeginLoading()
Prepare everything to begin the loading when arriving at a station.
Definition: vehicle.cpp:2041
Vehicle * Next() const
Get the next vehicle of this vehicle.
Definition: vehicle_base.h:581
Number of ticks before carried cargo is aged.
Date date_of_last_service
Last date the vehicle had a service at a depot.
Definition: vehicle_base.h:260
void AircraftStateHandler(Aircraft *v, const AirportFTAClass *apc)
Signature of the aircraft handler function.
Maximum speed of an aircraft that flies the holding pattern.
Information about a aircraft vehicle.
Definition: engine_type.h:99
Airplane wants to land.
Definition: airport.h:78
Position information of a vehicle after it moved.
Definition: vehicle_func.h:77
OrderSettings order
settings related to orders
Station has seen an aircraft.
Definition: station_type.h:69
First vehicle arrived for company.
Definition: news_type.h:24
static uint TileY(TileIndex tile)
Get the Y component of a tile.
Definition: map_func.h:217
static const uint64 TERM1_block
Movement Blocks on Airports blocks (eg_airport_flags).
Definition: airport.h:91
Next destination is too far away.
Definition: aircraft.h:41
uint64 block
64 bit blocks (st->airport.flags), should be enough for the most complex airports ...
Definition: airport.h:194
void Free()
&#39;Free&#39; the order
Definition: order_cmd.cpp:64
Disasters, like submarines, skyrangers and their shadows, belong to this class.
void CDECL error(const char *s,...)
Error handling for fatal non-user errors.
Definition: openttd.cpp:114
static T abs(const T a)
Returns the absolute value of (scalar) variable.
Definition: math_func.hpp:83
TileIndex xy
Base tile of the station.
static uint GB(const T x, const uint8 s, const uint8 n)
Fetch n bits from x, started at bit s.
uint32 cached_max_range_sqr
Cached squared maximum range.
Definition: aircraft.h:69
Functions related to zooming.
Heading for terminal 8.
Definition: airport.h:83
static const uint64 TERM8_block
Block belonging to terminal 8.
Definition: airport.h:118
VehicleType type
Type of vehicle.
Definition: vehicle_type.h:54
Vehicle * next
pointer to the next vehicle in the chain
Definition: vehicle_base.h:217
int16 x
x-coordinate of the destination.
Definition: airport.h:134
static uint MapMaxY()
Gets the maximum Y coordinate within the map, including MP_VOID.
Definition: map_func.h:113
RAII class for measuring multi-step elements of performance.
static Station * GetByTile(TileIndex tile)
Get the station belonging to a specific tile.
bool disaster
Play disaster and accident sounds.
AirportFTA * next
possible extra movement choices from this position
Definition: airport.h:193
Functions related to OTTD&#39;s landscape.
Aircraft list; Window numbers:
Definition: window_type.h:321
int32 z_pos
z coordinate.
Definition: vehicle_base.h:270
Vehicle is not visible.
Definition: vehicle_base.h:32
Vehicle details; Window numbers:
Definition: window_type.h:195
Base functions for all Games.
static const uint64 TERM4_block
Block belonging to terminal 4.
Definition: airport.h:94
Functions related to commands.
An accident or disaster has occurred.
Definition: news_type.h:26
Northeast.
CompanyID _current_company
Company currently doing an action.
Definition: company_cmd.cpp:47
void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const
Gets the sprite to show for the given direction.
Owner owner
The owner of this station.
Heading for terminal 5.
Definition: airport.h:69
#define FOR_ALL_AIRCRAFT(var)
Macro for iterating over all aircraft.
Definition: aircraft.h:144
static void AircraftHandleDestTooFar(Aircraft *v, bool too_far)
Handle the &#39;dest too far&#39; flag and the corresponding news message for aircraft.
static uint TileHeight(TileIndex tile)
Returns the height of a tile.
Definition: tile_map.h:31
an helicopter
Definition: aircraft.h:33
Heading for terminal 4.
Definition: airport.h:68
Max. speed: 1 unit = 8 mph = 12.8 km-ish/h.
HelicopterRotorStates
Helicopter rotor animation states.
Aircraft vehicle type.
Definition: vehicle_type.h:29
uint8 original_image_index
Original vehicle image index, thus the image index of the overridden vehicle.
Definition: engine_base.h:41
Airport airport
Tile area the airport covers.
Definition: station_base.h:466
byte running_ticks
Number of ticks this vehicle was not stopped this day.
Definition: vehicle_base.h:315
static StationID FindNearestHangar(const Aircraft *v)
Find the nearest hangar to v INVALID_STATION is returned, if the company does not have any suitable a...
byte y_extent
y-extent of vehicle bounding box
Definition: vehicle_base.h:282
EngineID engine_type
The type of engine used for this vehicle.
Definition: vehicle_base.h:288
AirportMovementStates state
Aircraft movement state when going to this terminal.
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:82
Landing onto landing strip.
Definition: airport.h:53
Heading for helipad 1.
Definition: airport.h:71
int32 x_pos
x coordinate.
Definition: vehicle_base.h:268
Helicopter wants to finish landing.
Definition: airport.h:81
uint16 vehicle_flags
Used for gradual loading and other miscellaneous things (.
Definition: base_consist.h:32
static bool HasBit(const T x, const uint8 y)
Checks if a bit in a value is set.
Helicopter take-off.
Definition: airport.h:56
Functions related to NewGRF provided sounds.
void Restore()
Restore the variable.
DiagDirection
Enumeration for diagonal directions.
Base functions for all AIs.
static const TileIndex INVALID_TILE
The very nice invalid tile marker.
Definition: tile_type.h:85
static bool AirportFindFreeTerminal(Aircraft *v, const AirportFTAClass *apc)
Find a free terminal, and assign it if available.
Whenever a plane touches down.
Definition: newgrf_sound.h:25
send a vehicle to a depot
Definition: command_type.h:219
byte progress
The percentage (if divided by 256) this vehicle already crossed the tile unit.
Definition: vehicle_base.h:297
Northeast, upper right on your monitor.
uint16 flag
special flags when moving towards the destination.
Definition: airport.h:136
static const uint64 TERM3_block
Block belonging to terminal 3.
Definition: airport.h:93
void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination, bool hangar)
Removes an order from all vehicles.
Definition: order_cmd.cpp:1803
Smoke of broken aircraft.
OrderType GetType() const
Get the type of order of this order.
Definition: order_base.h:69
Specification of a rectangle with absolute coordinates of all edges.
bool FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse)
Find the closest depot for this vehicle and tell us the location, DestinationID and whether we should...
byte CargoID
Cargo slots to indicate a cargo type within a game.
Definition: cargo_type.h:22
static const uint64 TERM2_block
Block belonging to terminal 2.
Definition: airport.h:92
int32 y_pos
y coordinate.
Definition: vehicle_base.h:269
static uint MapMaxX()
Gets the maximum X coordinate within the map, including MP_VOID.
Definition: map_func.h:104
byte heading
heading (current orders), guiding an airplane to its target on an airport
Definition: airport.h:197
uint DistanceSquare(TileIndex t0, TileIndex t1)
Gets the &#39;Square&#39; distance between the two given tiles.
Definition: map.cpp:176
byte flags
Aircraft flags.
Definition: aircraft.h:85
virtual bool IsChainInDepot() const
Check whether the whole vehicle chain is in the depot.
Definition: vehicle_base.h:510
Window functions not directly related to making/drawing windows.
byte position
the position that an airplane is at
Definition: airport.h:195
void OnNewDay()
Calls the new day handler of the vehicle.
One direction is the opposite of the other one.
uint16 crashed_counter
Timer for handling crash animations.
Definition: aircraft.h:77
Money profit_this_year
Profit this year << 8, low 8 bits are fract.
Definition: vehicle_base.h:239
void SetWindowClassesDirty(WindowClass cls)
Mark all windows of a particular class as dirty (in need of repainting)
Definition: window.cpp:3227
This depot order is because of a regular order.
Definition: order_type.h:98
uint DetermineCapacity(const Vehicle *v, uint16 *mail_capacity=nullptr) const
Determines capacity of a given vehicle from scratch.
Definition: engine.cpp:206
static void MaybeCrashAirplane(Aircraft *v)
Decide whether aircraft v should crash.
Functions related to news.
Base classes/functions for stations.
VehicleCache vcache
Cache of often used vehicle values.
Definition: vehicle_base.h:330
static Station * Get(size_t index)
Gets station with given index.
Date _date
Current date in days (day counter)
Definition: date.cpp:28
void UpdateAirplanesOnNewStation(const Station *st)
Updates the status of the Aircraft heading or in the station.
uint64 airport_flag
Bitmask in the airport flags that need to be free for this terminal.
uint16 h
The height of the area.
Definition: tilearea_type.h:21
const byte * terminals
Array with the number of terminal groups, followed by the number of terminals in each group...
Definition: airport.h:180
static const MovementTerminalMapping _airport_terminal_mapping[]
A list of all valid terminals and their associated blocks.
TileIndex new_tile
Tile of the vehicle after moving.
Definition: vehicle_func.h:80
static bool AirportHasBlock(Aircraft *v, const AirportFTA *current_pos, const AirportFTAClass *apc)
returns true if the road ahead is busy, eg.
CompanyID _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:46
This depot order is because of the servicing limit.
Definition: order_type.h:97
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:2250
Airplane wants to finish landing.
Definition: airport.h:79
static int UpdateAircraftSpeed(Aircraft *v, uint speed_limit=SPEED_LIMIT_NONE, bool hard_limit=true)
Sets the new speed for an aircraft.
Class for backupping variables and making sure they are restored later.
Station data structure.
Definition: station_base.h:452
Functions related to effect vehicles.
uint GetOldAdvanceSpeed(uint speed)
Determines the effective direction-specific vehicle movement speed.
Definition: vehicle_base.h:385
static uint GetNumTerminals(const AirportFTAClass *apc)
Get the number of terminals at the airport.
void GetBounds(Rect *bounds) const
Determine shared bounds of all sprites.
Definition: vehicle.cpp:100
Date GetLifeLengthInDays() const
Returns the vehicle&#39;s (not model&#39;s!) life length in days.
Definition: engine.cpp:446
void MarkDirty()
Marks the vehicles to be redrawn and updates cached variables.
byte day_counter
Increased by one for each day.
Definition: vehicle_base.h:313
byte delta_z
Z adjustment for helicopter pads.
Definition: airport.h:185
Order current_order
The current order (+ status, like: loading)
Definition: vehicle_base.h:318
void UpdatePositionAndViewport()
Update the position of the vehicle, and update the viewport.
Definition: vehicle.cpp:1606
uint16 passenger_capacity
Passenger capacity (persons).
Definition: engine_type.h:108
shadow of the aircraft
Definition: aircraft.h:35
Money GetRunningCost() const
Gets the running cost of a vehicle.
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:3300
Triggered when an airplane (not a helicopter) touches down at the airport (for single tile)...
byte mail_capacity
Mail capacity (bags).
Definition: engine_type.h:107
Vehicle is not clickable by the user (shadow vehicles).
Definition: vehicle_base.h:34
SpriteID colourmap
NOSAVE: cached colour mapping.
Definition: vehicle_base.h:254
Southwest.
Cheats _cheats
All the cheats.
Definition: cheat.cpp:18
Aircraft()
We don&#39;t want GCC to zero our struct! It already is zeroed and has an index!
Definition: aircraft.h:90
static void SetDParam(uint n, uint64 v)
Set a string parameter v at index n in the global string parameter array.
Definition: strings_func.h:201
Helicopter wants to leave the airport.
Definition: airport.h:76
static const uint64 TERM5_block
Block belonging to terminal 5.
Definition: airport.h:95
static void AddVehicleNewsItem(StringID string, NewsType type, VehicleID vehicle, StationID station=INVALID_STATION)
Adds a newsitem referencing a vehicle.
Definition: news_func.h:32
static Station * GetIfValid(size_t index)
Returns station if the index is a valid index for this station type.