OpenTTD
aircraft_cmd.cpp
Go to the documentation of this file.
1 /* $Id: aircraft_cmd.cpp 27668 2016-10-16 14:59:44Z frosch $ */
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 
41 #include "table/strings.h"
42 
43 #include "safeguards.h"
44 
46 {
47  this->x_offs = -1;
48  this->y_offs = -1;
49  this->x_extent = 2;
50  this->y_extent = 2;
51 
52  switch (this->subtype) {
53  default: NOT_REACHED();
54 
55  case AIR_AIRCRAFT:
56  case AIR_HELICOPTER:
57  switch (this->state) {
58  default: break;
59  case ENDTAKEOFF:
60  case LANDING:
61  case HELILANDING:
62  case FLYING:
63  this->x_extent = 24;
64  this->y_extent = 24;
65  break;
66  }
67  this->z_extent = 5;
68  break;
69 
70  case AIR_SHADOW:
71  this->z_extent = 1;
72  this->x_offs = 0;
73  this->y_offs = 0;
74  break;
75 
76  case AIR_ROTOR:
77  this->z_extent = 1;
78  break;
79  }
80 }
81 
82 static bool AirportMove(Aircraft *v, const AirportFTAClass *apc);
83 static bool AirportSetBlocks(Aircraft *v, const AirportFTA *current_pos, const AirportFTAClass *apc);
84 static bool AirportHasBlock(Aircraft *v, const AirportFTA *current_pos, const AirportFTAClass *apc);
85 static bool AirportFindFreeTerminal(Aircraft *v, const AirportFTAClass *apc);
86 static bool AirportFindFreeHelipad(Aircraft *v, const AirportFTAClass *apc);
87 static void CrashAirplane(Aircraft *v);
88 
89 static const SpriteID _aircraft_sprite[] = {
90  0x0EB5, 0x0EBD, 0x0EC5, 0x0ECD,
91  0x0ED5, 0x0EDD, 0x0E9D, 0x0EA5,
92  0x0EAD, 0x0EE5, 0x0F05, 0x0F0D,
93  0x0F15, 0x0F1D, 0x0F25, 0x0F2D,
94  0x0EED, 0x0EF5, 0x0EFD, 0x0F35,
95  0x0E9D, 0x0EA5, 0x0EAD, 0x0EB5,
96  0x0EBD, 0x0EC5
97 };
98 
99 template <>
100 bool IsValidImageIndex<VEH_AIRCRAFT>(uint8 image_index)
101 {
102  return image_index < lengthof(_aircraft_sprite);
103 }
104 
107  HRS_ROTOR_STOPPED,
108  HRS_ROTOR_MOVING_1,
109  HRS_ROTOR_MOVING_2,
110  HRS_ROTOR_MOVING_3,
111 };
112 
120 static StationID FindNearestHangar(const Aircraft *v)
121 {
122  const Station *st;
123  uint best = 0;
124  StationID index = INVALID_STATION;
125  TileIndex vtile = TileVirtXY(v->x_pos, v->y_pos);
126  const AircraftVehicleInfo *avi = AircraftVehInfo(v->engine_type);
127 
128  FOR_ALL_STATIONS(st) {
129  if (st->owner != v->owner || !(st->facilities & FACIL_AIRPORT)) continue;
130 
131  const AirportFTAClass *afc = st->airport.GetFTA();
132  if (!st->airport.HasHangar() || (
133  /* don't crash the plane if we know it can't land at the airport */
135  (avi->subtype & AIR_FAST) &&
137  continue;
138  }
139 
140  /* v->tile can't be used here, when aircraft is flying v->tile is set to 0 */
141  uint distance = DistanceSquare(vtile, st->airport.tile);
142  if (v->acache.cached_max_range_sqr != 0) {
143  /* Check if our current destination can be reached from the depot airport. */
144  const Station *cur_dest = GetTargetAirportIfValid(v);
145  if (cur_dest != NULL && DistanceSquare(st->airport.tile, cur_dest->airport.tile) > v->acache.cached_max_range_sqr) continue;
146  }
147  if (distance < best || index == INVALID_STATION) {
148  best = distance;
149  index = st->index;
150  }
151  }
152  return index;
153 }
154 
156 {
157  uint8 spritenum = this->spritenum;
158 
159  if (is_custom_sprite(spritenum)) {
160  GetCustomVehicleSprite(this, direction, image_type, result);
161  if (result->IsValid()) return;
162 
163  spritenum = this->GetEngine()->original_image_index;
164  }
165 
166  assert(IsValidImageIndex<VEH_AIRCRAFT>(spritenum));
167  result->Set(direction + _aircraft_sprite[spritenum]);
168 }
169 
170 void GetRotorImage(const Aircraft *v, EngineImageType image_type, VehicleSpriteSeq *result)
171 {
172  assert(v->subtype == AIR_HELICOPTER);
173 
174  const Aircraft *w = v->Next()->Next();
175  if (is_custom_sprite(v->spritenum)) {
176  GetCustomRotorSprite(v, false, image_type, result);
177  if (result->IsValid()) return;
178  }
179 
180  /* Return standard rotor sprites if there are no custom sprites for this helicopter */
181  result->Set(SPR_ROTOR_STOPPED + w->state);
182 }
183 
184 static void GetAircraftIcon(EngineID engine, EngineImageType image_type, VehicleSpriteSeq *result)
185 {
186  const Engine *e = Engine::Get(engine);
187  uint8 spritenum = e->u.air.image_index;
188 
189  if (is_custom_sprite(spritenum)) {
190  GetCustomVehicleIcon(engine, DIR_W, image_type, result);
191  if (result->IsValid()) return;
192 
193  spritenum = e->original_image_index;
194  }
195 
196  assert(IsValidImageIndex<VEH_AIRCRAFT>(spritenum));
197  result->Set(DIR_W + _aircraft_sprite[spritenum]);
198 }
199 
200 void DrawAircraftEngine(int left, int right, int preferred_x, int y, EngineID engine, PaletteID pal, EngineImageType image_type)
201 {
202  VehicleSpriteSeq seq;
203  GetAircraftIcon(engine, image_type, &seq);
204 
205  Rect rect;
206  seq.GetBounds(&rect);
207  preferred_x = Clamp(preferred_x,
208  left - UnScaleGUI(rect.left),
209  right - UnScaleGUI(rect.right));
210 
211  seq.Draw(preferred_x, y, pal, pal == PALETTE_CRASH);
212 
213  if (!(AircraftVehInfo(engine)->subtype & AIR_CTOL)) {
214  VehicleSpriteSeq rotor_seq;
215  GetCustomRotorIcon(engine, image_type, &rotor_seq);
216  if (!rotor_seq.IsValid()) rotor_seq.Set(SPR_ROTOR_STOPPED);
217  rotor_seq.Draw(preferred_x, y - ScaleGUITrad(5), PAL_NONE, false);
218  }
219 }
220 
230 void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height, int &xoffs, int &yoffs, EngineImageType image_type)
231 {
232  VehicleSpriteSeq seq;
233  GetAircraftIcon(engine, image_type, &seq);
234 
235  Rect rect;
236  seq.GetBounds(&rect);
237 
238  width = UnScaleGUI(rect.right - rect.left + 1);
239  height = UnScaleGUI(rect.bottom - rect.top + 1);
240  xoffs = UnScaleGUI(rect.left);
241  yoffs = UnScaleGUI(rect.top);
242 }
243 
254 {
255  const AircraftVehicleInfo *avi = &e->u.air;
256  const Station *st = Station::GetByTile(tile);
257 
258  /* Prevent building aircraft types at places which can't handle them */
259  if (!CanVehicleUseStation(e->index, st)) return CMD_ERROR;
260 
261  /* Make sure all aircraft end up in the first tile of the hangar. */
262  tile = st->airport.GetHangarTile(st->airport.GetHangarNum(tile));
263 
264  if (flags & DC_EXEC) {
265  Aircraft *v = new Aircraft(); // aircraft
266  Aircraft *u = new Aircraft(); // shadow
267  *ret = v;
268 
269  v->direction = DIR_SE;
270 
271  v->owner = u->owner = _current_company;
272 
273  v->tile = tile;
274 
275  uint x = TileX(tile) * TILE_SIZE + 5;
276  uint y = TileY(tile) * TILE_SIZE + 3;
277 
278  v->x_pos = u->x_pos = x;
279  v->y_pos = u->y_pos = y;
280 
281  u->z_pos = GetSlopePixelZ(x, y);
282  v->z_pos = u->z_pos + 1;
283 
286 
287  v->spritenum = avi->image_index;
288 
289  v->cargo_cap = avi->passenger_capacity;
290  v->refit_cap = 0;
291  u->cargo_cap = avi->mail_capacity;
292  u->refit_cap = 0;
293 
295  u->cargo_type = CT_MAIL;
296 
297  v->name = NULL;
298  v->last_station_visited = INVALID_STATION;
299  v->last_loading_station = INVALID_STATION;
300 
301  v->acceleration = avi->acceleration;
302  v->engine_type = e->index;
303  u->engine_type = e->index;
304 
307 
308  u->subtype = AIR_SHADOW;
310 
311  v->reliability = e->reliability;
313  v->max_age = e->GetLifeLengthInDays();
314 
315  _new_vehicle_id = v->index;
316 
317  v->pos = GetVehiclePosOnBuild(tile);
318 
319  v->state = HANGAR;
320  v->previous_pos = v->pos;
321  v->targetairport = GetStationIndex(tile);
322  v->SetNext(u);
323 
324  v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_aircraft);
325 
327  v->build_year = u->build_year = _cur_year;
328 
329  v->sprite_seq.Set(SPR_IMG_QUERY);
330  u->sprite_seq.Set(SPR_IMG_QUERY);
331 
334 
335  v->vehicle_flags = 0;
337  v->SetServiceIntervalIsPercent(Company::Get(_current_company)->settings.vehicle.servint_ispercent);
338 
340 
341  v->cargo_cap = e->DetermineCapacity(v, &u->cargo_cap);
342 
344 
345  UpdateAircraftCache(v, true);
346 
347  v->UpdatePosition();
348  u->UpdatePosition();
349 
350  /* Aircraft with 3 vehicles (chopper)? */
351  if (v->subtype == AIR_HELICOPTER) {
352  Aircraft *w = new Aircraft();
353  w->engine_type = e->index;
354  w->direction = DIR_N;
355  w->owner = _current_company;
356  w->x_pos = v->x_pos;
357  w->y_pos = v->y_pos;
358  w->z_pos = v->z_pos + ROTOR_Z_OFFSET;
360  w->spritenum = 0xFF;
361  w->subtype = AIR_ROTOR;
362  w->sprite_seq.Set(SPR_ROTOR_STOPPED);
364  /* Use rotor's air.state to store the rotor animation frame */
365  w->state = HRS_ROTOR_STOPPED;
367 
368  u->SetNext(w);
369  w->UpdatePosition();
370  }
371  }
372 
373  return CommandCost();
374 }
375 
376 
377 bool Aircraft::FindClosestDepot(TileIndex *location, DestinationID *destination, bool *reverse)
378 {
379  const Station *st = GetTargetAirportIfValid(this);
380  /* If the station is not a valid airport or if it has no hangars */
381  if (st == NULL || !st->airport.HasHangar()) {
382  /* the aircraft has to search for a hangar on its own */
383  StationID station = FindNearestHangar(this);
384 
385  if (station == INVALID_STATION) return false;
386 
387  st = Station::Get(station);
388  }
389 
390  if (location != NULL) *location = st->xy;
391  if (destination != NULL) *destination = st->index;
392 
393  return true;
394 }
395 
396 static void CheckIfAircraftNeedsService(Aircraft *v)
397 {
398  if (Company::Get(v->owner)->settings.vehicle.servint_aircraft == 0 || !v->NeedsAutomaticServicing()) return;
399  if (v->IsChainInDepot()) {
401  return;
402  }
403 
404  /* When we're parsing conditional orders and the like
405  * we don't want to consider going to a depot too. */
406  if (!v->current_order.IsType(OT_GOTO_DEPOT) && !v->current_order.IsType(OT_GOTO_STATION)) return;
407 
409 
410  assert(st != NULL);
411 
412  /* only goto depot if the target airport has a depot */
413  if (st->airport.HasHangar() && CanVehicleUseStation(v, st)) {
416  } else if (v->current_order.IsType(OT_GOTO_DEPOT)) {
419  }
420 }
421 
423 {
424  const Engine *e = this->GetEngine();
425  uint cost_factor = GetVehicleProperty(this, PROP_AIRCRAFT_RUNNING_COST_FACTOR, e->u.air.running_cost);
426  return GetPrice(PR_RUNNING_AIRCRAFT, cost_factor, e->GetGRF());
427 }
428 
430 {
431  if (!this->IsNormalAircraft()) return;
432 
433  if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this);
434 
435  CheckOrders(this);
436 
437  CheckVehicleBreakdown(this);
438  AgeVehicle(this);
439  CheckIfAircraftNeedsService(this);
440 
441  if (this->running_ticks == 0) return;
442 
444 
445  this->profit_this_year -= cost.GetCost();
446  this->running_ticks = 0;
447 
449 
452 }
453 
454 static void HelicopterTickHandler(Aircraft *v)
455 {
456  Aircraft *u = v->Next()->Next();
457 
458  if (u->vehstatus & VS_HIDDEN) return;
459 
460  /* if true, helicopter rotors do not rotate. This should only be the case if a helicopter is
461  * loading/unloading at a terminal or stopped */
462  if (v->current_order.IsType(OT_LOADING) || (v->vehstatus & VS_STOPPED)) {
463  if (u->cur_speed != 0) {
464  u->cur_speed++;
465  if (u->cur_speed >= 0x80 && u->state == HRS_ROTOR_MOVING_3) {
466  u->cur_speed = 0;
467  }
468  }
469  } else {
470  if (u->cur_speed == 0) {
471  u->cur_speed = 0x70;
472  }
473  if (u->cur_speed >= 0x50) {
474  u->cur_speed--;
475  }
476  }
477 
478  int tick = ++u->tick_counter;
479  int spd = u->cur_speed >> 4;
480 
481  VehicleSpriteSeq seq;
482  if (spd == 0) {
483  u->state = HRS_ROTOR_STOPPED;
484  GetRotorImage(v, EIT_ON_MAP, &seq);
485  if (u->sprite_seq == seq) return;
486  } else if (tick >= spd) {
487  u->tick_counter = 0;
488  u->state++;
489  if (u->state > HRS_ROTOR_MOVING_3) u->state = HRS_ROTOR_MOVING_1;
490  GetRotorImage(v, EIT_ON_MAP, &seq);
491  } else {
492  return;
493  }
494 
495  u->sprite_seq = seq;
496 
498 }
499 
507 void SetAircraftPosition(Aircraft *v, int x, int y, int z)
508 {
509  v->x_pos = x;
510  v->y_pos = y;
511  v->z_pos = z;
512 
513  v->UpdatePosition();
514  v->UpdateViewport(true, false);
515  if (v->subtype == AIR_HELICOPTER) {
516  GetRotorImage(v, EIT_ON_MAP, &v->Next()->Next()->sprite_seq);
517  }
518 
519  Aircraft *u = v->Next();
520 
521  int safe_x = Clamp(x, 0, MapMaxX() * TILE_SIZE);
522  int safe_y = Clamp(y - 1, 0, MapMaxY() * TILE_SIZE);
523  u->x_pos = x;
524  u->y_pos = y - ((v->z_pos - GetSlopePixelZ(safe_x, safe_y)) >> 3);
525 
526  safe_y = Clamp(u->y_pos, 0, MapMaxY() * TILE_SIZE);
527  u->z_pos = GetSlopePixelZ(safe_x, safe_y);
528  u->sprite_seq.CopyWithoutPalette(v->sprite_seq); // the shadow is never coloured
529 
530  u->UpdatePositionAndViewport();
531 
532  u = u->Next();
533  if (u != NULL) {
534  u->x_pos = x;
535  u->y_pos = y;
536  u->z_pos = z + ROTOR_Z_OFFSET;
537 
538  u->UpdatePositionAndViewport();
539  }
540 }
541 
547 {
548  v->subspeed = 0;
549  v->progress = 0;
550 
551  Aircraft *u = v->Next();
552  u->vehstatus |= VS_HIDDEN;
553  u = u->Next();
554  if (u != NULL) {
555  u->vehstatus |= VS_HIDDEN;
556  u->cur_speed = 0;
557  }
558 
559  SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos);
560 }
561 
562 static void PlayAircraftSound(const Vehicle *v)
563 {
564  if (!PlayVehicleSound(v, VSE_START)) {
565  SndPlayVehicleFx(AircraftVehInfo(v->engine_type)->sfx, v);
566  }
567 }
568 
569 
576 void UpdateAircraftCache(Aircraft *v, bool update_range)
577 {
578  uint max_speed = GetVehicleProperty(v, PROP_AIRCRAFT_SPEED, 0);
579  if (max_speed != 0) {
580  /* Convert from original units to km-ish/h */
581  max_speed = (max_speed * 128) / 10;
582 
583  v->vcache.cached_max_speed = max_speed;
584  } else {
585  /* Use the default max speed of the vehicle. */
586  v->vcache.cached_max_speed = AircraftVehInfo(v->engine_type)->max_speed;
587  }
588 
589  /* Update cargo aging period. */
590  v->vcache.cached_cargo_age_period = GetVehicleProperty(v, PROP_AIRCRAFT_CARGO_AGE_PERIOD, EngInfo(v->engine_type)->cargo_age_period);
591  Aircraft *u = v->Next(); // Shadow for mail
592  u->vcache.cached_cargo_age_period = GetVehicleProperty(u, PROP_AIRCRAFT_CARGO_AGE_PERIOD, EngInfo(u->engine_type)->cargo_age_period);
593 
594  /* Update aircraft range. */
595  if (update_range) {
596  v->acache.cached_max_range = GetVehicleProperty(v, PROP_AIRCRAFT_RANGE, AircraftVehInfo(v->engine_type)->max_range);
597  /* Squared it now so we don't have to do it later all the time. */
598  v->acache.cached_max_range_sqr = v->acache.cached_max_range * v->acache.cached_max_range;
599  }
600 }
601 
602 
611  SPEED_LIMIT_NONE = 0xFFFF,
612 };
613 
621 static int UpdateAircraftSpeed(Aircraft *v, uint speed_limit = SPEED_LIMIT_NONE, bool hard_limit = true)
622 {
630  uint spd = v->acceleration * 77;
631  byte t;
632 
633  /* Adjust speed limits by plane speed factor to prevent taxiing
634  * and take-off speeds being too low. */
635  speed_limit *= _settings_game.vehicle.plane_speed;
636 
637  if (v->vcache.cached_max_speed < speed_limit) {
638  if (v->cur_speed < speed_limit) hard_limit = false;
639  speed_limit = v->vcache.cached_max_speed;
640  }
641 
642  v->subspeed = (t = v->subspeed) + (byte)spd;
643 
644  /* Aircraft's current speed is used twice so that very fast planes are
645  * forced to slow down rapidly in the short distance needed. The magic
646  * value 16384 was determined to give similar results to the old speed/48
647  * method at slower speeds. This also results in less reduction at slow
648  * speeds to that aircraft do not get to taxi speed straight after
649  * touchdown. */
650  if (!hard_limit && v->cur_speed > speed_limit) {
651  speed_limit = v->cur_speed - max(1, ((v->cur_speed * v->cur_speed) / 16384) / _settings_game.vehicle.plane_speed);
652  }
653 
654  spd = min(v->cur_speed + (spd >> 8) + (v->subspeed < t), speed_limit);
655 
656  /* adjust speed for broken vehicles */
657  if (v->vehstatus & VS_AIRCRAFT_BROKEN) spd = min(spd, SPEED_LIMIT_BROKEN);
658 
659  /* updates statusbar only if speed have changed to save CPU time */
660  if (spd != v->cur_speed) {
661  v->cur_speed = spd;
663  }
664 
665  /* Adjust distance moved by plane speed setting */
667 
668  /* Convert direction-independent speed into direction-dependent speed. (old movement method) */
669  spd = v->GetOldAdvanceSpeed(spd);
670 
671  spd += v->progress;
672  v->progress = (byte)spd;
673  return spd >> 8;
674 }
675 
684 {
685  int safe_x = Clamp(v->x_pos, 0, MapMaxX() * TILE_SIZE);
686  int safe_y = Clamp(v->y_pos, 0, MapMaxY() * TILE_SIZE);
687  return TileHeight(TileVirtXY(safe_x, safe_y)) * TILE_HEIGHT;
688 }
689 
700 void GetAircraftFlightLevelBounds(const Vehicle *v, int *min_level, int *max_level)
701 {
702  int base_altitude = GetTileHeightBelowAircraft(v);
703  if (v->type == VEH_AIRCRAFT && Aircraft::From(v)->subtype == AIR_HELICOPTER) {
705  }
706 
707  /* Make sure eastbound and westbound planes do not "crash" into each
708  * other by providing them with vertical separation
709  */
710  switch (v->direction) {
711  case DIR_N:
712  case DIR_NE:
713  case DIR_E:
714  case DIR_SE:
715  base_altitude += 10;
716  break;
717 
718  default: break;
719  }
720 
721  /* Make faster planes fly higher so that they can overtake slower ones */
722  base_altitude += min(20 * (v->vcache.cached_max_speed / 200) - 90, 0);
723 
724  if (min_level != NULL) *min_level = base_altitude + AIRCRAFT_MIN_FLYING_ALTITUDE;
725  if (max_level != NULL) *max_level = base_altitude + AIRCRAFT_MAX_FLYING_ALTITUDE;
726 }
727 
736 {
737  int tile_height = GetTileHeightBelowAircraft(v);
738 
740 }
741 
742 template <class T>
743 int GetAircraftFlightLevel(T *v, bool takeoff)
744 {
745  /* Aircraft is in flight. We want to enforce it being somewhere
746  * between the minimum and the maximum allowed altitude. */
747  int aircraft_min_altitude;
748  int aircraft_max_altitude;
749  GetAircraftFlightLevelBounds(v, &aircraft_min_altitude, &aircraft_max_altitude);
750  int aircraft_middle_altitude = (aircraft_min_altitude + aircraft_max_altitude) / 2;
751 
752  /* If those assumptions would be violated, aircrafts would behave fairly strange. */
753  assert(aircraft_min_altitude < aircraft_middle_altitude);
754  assert(aircraft_middle_altitude < aircraft_max_altitude);
755 
756  int z = v->z_pos;
757  if (z < aircraft_min_altitude ||
758  (HasBit(v->flags, VAF_IN_MIN_HEIGHT_CORRECTION) && z < aircraft_middle_altitude)) {
759  /* Ascend. And don't fly into that mountain right ahead.
760  * And avoid our aircraft become a stairclimber, so if we start
761  * correcting altitude, then we stop correction not too early. */
763  z += takeoff ? 2 : 1;
764  } else if (!takeoff && (z > aircraft_max_altitude ||
765  (HasBit(v->flags, VAF_IN_MAX_HEIGHT_CORRECTION) && z > aircraft_middle_altitude))) {
766  /* Descend lower. You are an aircraft, not an space ship.
767  * And again, don't stop correcting altitude too early. */
769  z--;
770  } else if (HasBit(v->flags, VAF_IN_MIN_HEIGHT_CORRECTION) && z >= aircraft_middle_altitude) {
771  /* Now, we have corrected altitude enough. */
773  } else if (HasBit(v->flags, VAF_IN_MAX_HEIGHT_CORRECTION) && z <= aircraft_middle_altitude) {
774  /* Now, we have corrected altitude enough. */
776  }
777 
778  return z;
779 }
780 
781 template int GetAircraftFlightLevel(DisasterVehicle *v, bool takeoff);
782 
797 static byte AircraftGetEntryPoint(const Aircraft *v, const AirportFTAClass *apc, Direction rotation)
798 {
799  assert(v != NULL);
800  assert(apc != NULL);
801 
802  /* In the case the station doesn't exit anymore, set target tile 0.
803  * It doesn't hurt much, aircraft will go to next order, nearest hangar
804  * or it will simply crash in next tick */
805  TileIndex tile = 0;
806 
807  const Station *st = Station::GetIfValid(v->targetairport);
808  if (st != NULL) {
809  /* Make sure we don't go to INVALID_TILE if the airport has been removed. */
810  tile = (st->airport.tile != INVALID_TILE) ? st->airport.tile : st->xy;
811  }
812 
813  int delta_x = v->x_pos - TileX(tile) * TILE_SIZE;
814  int delta_y = v->y_pos - TileY(tile) * TILE_SIZE;
815 
816  DiagDirection dir;
817  if (abs(delta_y) < abs(delta_x)) {
818  /* We are northeast or southwest of the airport */
819  dir = delta_x < 0 ? DIAGDIR_NE : DIAGDIR_SW;
820  } else {
821  /* We are northwest or southeast of the airport */
822  dir = delta_y < 0 ? DIAGDIR_NW : DIAGDIR_SE;
823  }
824  dir = ChangeDiagDir(dir, DiagDirDifference(DIAGDIR_NE, DirToDiagDir(rotation)));
825  return apc->entry_points[dir];
826 }
827 
828 
829 static void MaybeCrashAirplane(Aircraft *v);
830 
839 {
840  int count;
841 
842  /* NULL if station is invalid */
843  const Station *st = Station::GetIfValid(v->targetairport);
844  /* INVALID_TILE if there is no station */
846  Direction rotation = DIR_N;
847  uint size_x = 1, size_y = 1;
848  if (st != NULL) {
849  if (st->airport.tile != INVALID_TILE) {
850  tile = st->airport.tile;
851  rotation = st->airport.rotation;
852  size_x = st->airport.w;
853  size_y = st->airport.h;
854  } else {
855  tile = st->xy;
856  }
857  }
858  /* DUMMY if there is no station or no airport */
859  const AirportFTAClass *afc = tile == INVALID_TILE ? GetAirport(AT_DUMMY) : st->airport.GetFTA();
860 
861  /* prevent going to INVALID_TILE if airport is deleted. */
862  if (st == NULL || st->airport.tile == INVALID_TILE) {
863  /* Jump into our "holding pattern" state machine if possible */
864  if (v->pos >= afc->nofelements) {
865  v->pos = v->previous_pos = AircraftGetEntryPoint(v, afc, DIR_N);
866  } else if (v->targetairport != v->current_order.GetDestination()) {
867  /* If not possible, just get out of here fast */
868  v->state = FLYING;
871  /* get aircraft back on running altitude */
872  SetAircraftPosition(v, v->x_pos, v->y_pos, GetAircraftFlightLevel(v));
873  return false;
874  }
875  }
876 
877  /* get airport moving data */
878  const AirportMovingData amd = RotateAirportMovingData(afc->MovingData(v->pos), rotation, size_x, size_y);
879 
880  int x = TileX(tile) * TILE_SIZE;
881  int y = TileY(tile) * TILE_SIZE;
882 
883  /* Helicopter raise */
884  if (amd.flag & AMED_HELI_RAISE) {
885  Aircraft *u = v->Next()->Next();
886 
887  /* Make sure the rotors don't rotate too fast */
888  if (u->cur_speed > 32) {
889  v->cur_speed = 0;
890  if (--u->cur_speed == 32) {
891  if (!PlayVehicleSound(v, VSE_START)) {
892  SndPlayVehicleFx(SND_18_HELICOPTER, v);
893  }
894  }
895  } else {
896  u->cur_speed = 32;
897  count = UpdateAircraftSpeed(v);
898  if (count > 0) {
899  v->tile = 0;
900 
901  int z_dest;
902  GetAircraftFlightLevelBounds(v, &z_dest, NULL);
903 
904  /* Reached altitude? */
905  if (v->z_pos >= z_dest) {
906  v->cur_speed = 0;
907  return true;
908  }
909  SetAircraftPosition(v, v->x_pos, v->y_pos, min(v->z_pos + count, z_dest));
910  }
911  }
912  return false;
913  }
914 
915  /* Helicopter landing. */
916  if (amd.flag & AMED_HELI_LOWER) {
917  if (st == NULL) {
918  /* FIXME - AircraftController -> if station no longer exists, do not land
919  * helicopter will circle until sign disappears, then go to next order
920  * what to do when it is the only order left, right now it just stays in 1 place */
921  v->state = FLYING;
924  return false;
925  }
926 
927  /* Vehicle is now at the airport. */
928  v->tile = tile;
929 
930  /* Find altitude of landing position. */
931  int z = GetSlopePixelZ(x, y) + 1 + afc->delta_z;
932 
933  if (z == v->z_pos) {
934  Vehicle *u = v->Next()->Next();
935 
936  /* Increase speed of rotors. When speed is 80, we've landed. */
937  if (u->cur_speed >= 80) return true;
938  u->cur_speed += 4;
939  } else {
940  count = UpdateAircraftSpeed(v);
941  if (count > 0) {
942  if (v->z_pos > z) {
943  SetAircraftPosition(v, v->x_pos, v->y_pos, max(v->z_pos - count, z));
944  } else {
945  SetAircraftPosition(v, v->x_pos, v->y_pos, min(v->z_pos + count, z));
946  }
947  }
948  }
949  return false;
950  }
951 
952  /* Get distance from destination pos to current pos. */
953  uint dist = abs(x + amd.x - v->x_pos) + abs(y + amd.y - v->y_pos);
954 
955  /* Need exact position? */
956  if (!(amd.flag & AMED_EXACTPOS) && dist <= (amd.flag & AMED_SLOWTURN ? 8U : 4U)) return true;
957 
958  /* At final pos? */
959  if (dist == 0) {
960  /* Change direction smoothly to final direction. */
961  DirDiff dirdiff = DirDifference(amd.direction, v->direction);
962  /* if distance is 0, and plane points in right direction, no point in calling
963  * UpdateAircraftSpeed(). So do it only afterwards */
964  if (dirdiff == DIRDIFF_SAME) {
965  v->cur_speed = 0;
966  return true;
967  }
968 
969  if (!UpdateAircraftSpeed(v, SPEED_LIMIT_TAXI)) return false;
970 
972  v->cur_speed >>= 1;
973 
974  SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos);
975  return false;
976  }
977 
980  if ((v->vehstatus & VS_CRASHED) != 0) return false;
981  }
982 
983  uint speed_limit = SPEED_LIMIT_TAXI;
984  bool hard_limit = true;
985 
986  if (amd.flag & AMED_NOSPDCLAMP) speed_limit = SPEED_LIMIT_NONE;
987  if (amd.flag & AMED_HOLD) { speed_limit = SPEED_LIMIT_HOLD; hard_limit = false; }
988  if (amd.flag & AMED_LAND) { speed_limit = SPEED_LIMIT_APPROACH; hard_limit = false; }
989  if (amd.flag & AMED_BRAKE) { speed_limit = SPEED_LIMIT_TAXI; hard_limit = false; }
990 
991  count = UpdateAircraftSpeed(v, speed_limit, hard_limit);
992  if (count == 0) return false;
993 
994  if (v->turn_counter != 0) v->turn_counter--;
995 
996  do {
997 
999 
1000  if (dist < 4 || (amd.flag & AMED_LAND)) {
1001  /* move vehicle one pixel towards target */
1002  gp.x = (v->x_pos != (x + amd.x)) ?
1003  v->x_pos + ((x + amd.x > v->x_pos) ? 1 : -1) :
1004  v->x_pos;
1005  gp.y = (v->y_pos != (y + amd.y)) ?
1006  v->y_pos + ((y + amd.y > v->y_pos) ? 1 : -1) :
1007  v->y_pos;
1008 
1009  /* Oilrigs must keep v->tile as st->airport.tile, since the landing pad is in a non-airport tile */
1010  gp.new_tile = (st->airport.type == AT_OILRIG) ? st->airport.tile : TileVirtXY(gp.x, gp.y);
1011 
1012  } else {
1013 
1014  /* Turn. Do it slowly if in the air. */
1015  Direction newdir = GetDirectionTowards(v, x + amd.x, y + amd.y);
1016  if (newdir != v->direction) {
1017  if (amd.flag & AMED_SLOWTURN && v->number_consecutive_turns < 8 && v->subtype == AIR_AIRCRAFT) {
1018  if (v->turn_counter == 0 || newdir == v->last_direction) {
1019  if (newdir == v->last_direction) {
1020  v->number_consecutive_turns = 0;
1021  } else {
1023  }
1025  v->last_direction = v->direction;
1026  v->direction = newdir;
1027  }
1028 
1029  /* Move vehicle. */
1030  gp = GetNewVehiclePos(v);
1031  } else {
1032  v->cur_speed >>= 1;
1033  v->direction = newdir;
1034 
1035  /* When leaving a terminal an aircraft often goes to a position
1036  * directly in front of it. If it would move while turning it
1037  * would need an two extra turns to end up at the correct position.
1038  * To make it easier just disallow all moving while turning as
1039  * long as an aircraft is on the ground. */
1040  gp.x = v->x_pos;
1041  gp.y = v->y_pos;
1042  gp.new_tile = gp.old_tile = v->tile;
1043  }
1044  } else {
1045  v->number_consecutive_turns = 0;
1046  /* Move vehicle. */
1047  gp = GetNewVehiclePos(v);
1048  }
1049  }
1050 
1051  v->tile = gp.new_tile;
1052  /* If vehicle is in the air, use tile coordinate 0. */
1053  if (amd.flag & (AMED_TAKEOFF | AMED_SLOWTURN | AMED_LAND)) v->tile = 0;
1054 
1055  /* Adjust Z for land or takeoff? */
1056  int z = v->z_pos;
1057 
1058  if (amd.flag & AMED_TAKEOFF) {
1059  z = GetAircraftFlightLevel(v, true);
1060  } else if (amd.flag & AMED_HOLD) {
1061  /* Let the plane drop from normal flight altitude to holding pattern altitude */
1062  if (z > GetAircraftHoldMaxAltitude(v)) z--;
1063  } else if ((amd.flag & AMED_SLOWTURN) && (amd.flag & AMED_NOSPDCLAMP)) {
1064  z = GetAircraftFlightLevel(v);
1065  }
1066 
1067  if (amd.flag & AMED_LAND) {
1068  if (st->airport.tile == INVALID_TILE) {
1069  /* Airport has been removed, abort the landing procedure */
1070  v->state = FLYING;
1073  /* get aircraft back on running altitude */
1074  SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlightLevel(v));
1075  continue;
1076  }
1077 
1078  int curz = GetSlopePixelZ(x + amd.x, y + amd.y) + 1;
1079 
1080  /* We're not flying below our destination, right? */
1081  assert(curz <= z);
1082  int t = max(1U, dist - 4);
1083  int delta = z - curz;
1084 
1085  /* Only start lowering when we're sufficiently close for a 1:1 glide */
1086  if (delta >= t) {
1087  z -= CeilDiv(z - curz, t);
1088  }
1089  if (z < curz) z = curz;
1090  }
1091 
1092  /* We've landed. Decrease speed when we're reaching end of runway. */
1093  if (amd.flag & AMED_BRAKE) {
1094  int curz = GetSlopePixelZ(x, y) + 1;
1095 
1096  if (z > curz) {
1097  z--;
1098  } else if (z < curz) {
1099  z++;
1100  }
1101 
1102  }
1103 
1104  SetAircraftPosition(v, gp.x, gp.y, z);
1105  } while (--count != 0);
1106  return false;
1107 }
1108 
1114 {
1115  v->crashed_counter += 3;
1116 
1118 
1119  /* make aircraft crash down to the ground */
1120  if (v->crashed_counter < 500 && st == NULL && ((v->crashed_counter % 3) == 0) ) {
1121  int z = GetSlopePixelZ(Clamp(v->x_pos, 0, MapMaxX() * TILE_SIZE), Clamp(v->y_pos, 0, MapMaxY() * TILE_SIZE));
1122  v->z_pos -= 1;
1123  if (v->z_pos == z) {
1124  v->crashed_counter = 500;
1125  v->z_pos++;
1126  }
1127  }
1128 
1129  if (v->crashed_counter < 650) {
1130  uint32 r;
1131  if (Chance16R(1, 32, r)) {
1132  static const DirDiff delta[] = {
1134  };
1135 
1136  v->direction = ChangeDir(v->direction, delta[GB(r, 16, 2)]);
1137  SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos);
1138  r = Random();
1140  GB(r, 0, 4) - 4,
1141  GB(r, 4, 4) - 4,
1142  GB(r, 8, 4),
1144  }
1145  } else if (v->crashed_counter >= 10000) {
1146  /* remove rubble of crashed airplane */
1147 
1148  /* clear runway-in on all airports, set by crashing plane
1149  * small airports use AIRPORT_BUSY, city airports use RUNWAY_IN_OUT_block, etc.
1150  * but they all share the same number */
1151  if (st != NULL) {
1152  CLRBITS(st->airport.flags, RUNWAY_IN_block);
1153  CLRBITS(st->airport.flags, RUNWAY_IN_OUT_block); // commuter airport
1154  CLRBITS(st->airport.flags, RUNWAY_IN2_block); // intercontinental
1155  }
1156 
1157  delete v;
1158 
1159  return false;
1160  }
1161 
1162  return true;
1163 }
1164 
1165 
1171 static void HandleAircraftSmoke(Aircraft *v, bool mode)
1172 {
1173  static const struct {
1174  int8 x;
1175  int8 y;
1176  } smoke_pos[] = {
1177  { 5, 5 },
1178  { 6, 0 },
1179  { 5, -5 },
1180  { 0, -6 },
1181  { -5, -5 },
1182  { -6, 0 },
1183  { -5, 5 },
1184  { 0, 6 }
1185  };
1186 
1187  if (!(v->vehstatus & VS_AIRCRAFT_BROKEN)) return;
1188 
1189  /* Stop smoking when landed */
1190  if (v->cur_speed < 10) {
1192  v->breakdown_ctr = 0;
1193  return;
1194  }
1195 
1196  /* Spawn effect et most once per Tick, i.e. !mode */
1197  if (!mode && (v->tick_counter & 0x0F) == 0) {
1199  smoke_pos[v->direction].x,
1200  smoke_pos[v->direction].y,
1201  2,
1203  );
1204  }
1205 }
1206 
1207 void HandleMissingAircraftOrders(Aircraft *v)
1208 {
1209  /*
1210  * We do not have an order. This can be divided into two cases:
1211  * 1) we are heading to an invalid station. In this case we must
1212  * find another airport to go to. If there is nowhere to go,
1213  * we will destroy the aircraft as it otherwise will enter
1214  * the holding pattern for the first airport, which can cause
1215  * the plane to go into an undefined state when building an
1216  * airport with the same StationID.
1217  * 2) we are (still) heading to a (still) valid airport, then we
1218  * can continue going there. This can happen when you are
1219  * changing the aircraft's orders while in-flight or in for
1220  * example a depot. However, when we have a current order to
1221  * go to a depot, we have to keep that order so the aircraft
1222  * actually stops.
1223  */
1224  const Station *st = GetTargetAirportIfValid(v);
1225  if (st == NULL) {
1226  Backup<CompanyByte> cur_company(_current_company, v->owner, FILE_LINE);
1228  cur_company.Restore();
1229 
1230  if (ret.Failed()) CrashAirplane(v);
1231  } else if (!v->current_order.IsType(OT_GOTO_DEPOT)) {
1232  v->current_order.Free();
1233  }
1234 }
1235 
1236 
1238 {
1239  /* Orders are changed in flight, ensure going to the right station. */
1240  if (this->state == FLYING) {
1242  }
1243 
1244  /* Aircraft do not use dest-tile */
1245  return 0;
1246 }
1247 
1249 {
1250  this->colourmap = PAL_NONE;
1251  this->UpdateViewport(true, false);
1252  if (this->subtype == AIR_HELICOPTER) {
1253  GetRotorImage(this, EIT_ON_MAP, &this->Next()->Next()->sprite_seq);
1254  }
1255 }
1256 
1257 
1258 uint Aircraft::Crash(bool flooded)
1259 {
1260  uint pass = Vehicle::Crash(flooded) + 2; // pilots
1261  this->crashed_counter = flooded ? 9000 : 0; // max 10000, disappear pretty fast when flooded
1262 
1263  return pass;
1264 }
1265 
1270 static void CrashAirplane(Aircraft *v)
1271 {
1273 
1274  uint pass = v->Crash();
1275  SetDParam(0, pass);
1276 
1277  v->cargo.Truncate();
1278  v->Next()->cargo.Truncate();
1279  const Station *st = GetTargetAirportIfValid(v);
1280  StringID newsitem;
1281  if (st == NULL) {
1282  newsitem = STR_NEWS_PLANE_CRASH_OUT_OF_FUEL;
1283  } else {
1284  SetDParam(1, st->index);
1285  newsitem = STR_NEWS_AIRCRAFT_CRASH;
1286  }
1287 
1288  AI::NewEvent(v->owner, new ScriptEventVehicleCrashed(v->index, v->tile, st == NULL ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING));
1289  Game::NewEvent(new ScriptEventVehicleCrashed(v->index, v->tile, st == NULL ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING));
1290 
1291  AddVehicleNewsItem(newsitem, NT_ACCIDENT, v->index, st != NULL ? st->index : INVALID_STATION);
1292 
1293  ModifyStationRatingAround(v->tile, v->owner, -160, 30);
1294  if (_settings_client.sound.disaster) SndPlayVehicleFx(SND_12_EXPLOSION, v);
1295 }
1296 
1302 {
1303  if (_settings_game.vehicle.plane_crashes == 0) return;
1304 
1306 
1307  /* FIXME -- MaybeCrashAirplane -> increase crashing chances of very modern airplanes on smaller than AT_METROPOLITAN airports */
1308  uint32 prob = (0x4000 << _settings_game.vehicle.plane_crashes);
1310  (AircraftVehInfo(v->engine_type)->subtype & AIR_FAST) &&
1312  prob /= 20;
1313  } else {
1314  prob /= 1500;
1315  }
1316 
1317  if (GB(Random(), 0, 22) > prob) return;
1318 
1319  /* Crash the airplane. Remove all goods stored at the station. */
1320  for (CargoID i = 0; i < NUM_CARGO; i++) {
1321  st->goods[i].rating = 1;
1322  st->goods[i].cargo.Truncate();
1323  }
1324 
1325  CrashAirplane(v);
1326 }
1327 
1334 {
1335  if (v->current_order.IsType(OT_GOTO_DEPOT)) return;
1336 
1339 
1340  /* Check if station was ever visited before */
1341  if (!(st->had_vehicle_of_type & HVOT_AIRCRAFT)) {
1342  st->had_vehicle_of_type |= HVOT_AIRCRAFT;
1343  SetDParam(0, st->index);
1344  /* show newsitem of celebrating citizens */
1346  STR_NEWS_FIRST_AIRCRAFT_ARRIVAL,
1348  v->index,
1349  st->index
1350  );
1351  AI::NewEvent(v->owner, new ScriptEventStationFirstVehicle(st->index, v->index));
1352  Game::NewEvent(new ScriptEventStationFirstVehicle(st->index, v->index));
1353  }
1354 
1355  v->BeginLoading();
1356 }
1357 
1363 {
1365 
1366  if (!PlayVehicleSound(v, VSE_TOUCHDOWN)) {
1367  SndPlayVehicleFx(SND_17_SKID_PLANE, v);
1368  }
1369 }
1370 
1371 
1374 {
1375  if (v->current_order.IsType(OT_GOTO_STATION) || v->current_order.IsType(OT_GOTO_DEPOT)) {
1377  }
1378 
1379  const Station *st = GetTargetAirportIfValid(v);
1380  const AirportFTAClass *apc = st == NULL ? GetAirport(AT_DUMMY) : st->airport.GetFTA();
1381  Direction rotation = st == NULL ? DIR_N : st->airport.rotation;
1382  v->pos = v->previous_pos = AircraftGetEntryPoint(v, apc, rotation);
1383 }
1384 
1394 {
1395  v->cur_speed = 0;
1396  v->subspeed = 0;
1397  v->progress = 0;
1398  v->direction = exit_dir;
1399  v->vehstatus &= ~VS_HIDDEN;
1400  {
1401  Vehicle *u = v->Next();
1402  u->vehstatus &= ~VS_HIDDEN;
1403 
1404  /* Rotor blades */
1405  u = u->Next();
1406  if (u != NULL) {
1407  u->vehstatus &= ~VS_HIDDEN;
1408  u->cur_speed = 80;
1409  }
1410  }
1411 
1413  SetAircraftPosition(v, v->x_pos, v->y_pos, v->z_pos);
1416 }
1417 
1421 static void AircraftEventHandler_EnterTerminal(Aircraft *v, const AirportFTAClass *apc)
1422 {
1424  v->state = apc->layout[v->pos].heading;
1425 }
1426 
1433 {
1434  VehicleEnterDepot(v);
1435  v->state = apc->layout[v->pos].heading;
1436 }
1437 
1444 {
1445  /* if we just arrived, execute EnterHangar first */
1446  if (v->previous_pos != v->pos) {
1448  return;
1449  }
1450 
1451  /* if we were sent to the depot, stay there */
1452  if (v->current_order.IsType(OT_GOTO_DEPOT) && (v->vehstatus & VS_STOPPED)) {
1453  v->current_order.Free();
1454  return;
1455  }
1456 
1457  if (!v->current_order.IsType(OT_GOTO_STATION) &&
1458  !v->current_order.IsType(OT_GOTO_DEPOT))
1459  return;
1460 
1461  /* We are leaving a hangar, but have to go to the exact same one; re-enter */
1462  if (v->current_order.IsType(OT_GOTO_DEPOT) && v->current_order.GetDestination() == v->targetairport) {
1463  VehicleEnterDepot(v);
1464  return;
1465  }
1466 
1467  /* if the block of the next position is busy, stay put */
1468  if (AirportHasBlock(v, &apc->layout[v->pos], apc)) return;
1469 
1470  /* We are already at the target airport, we need to find a terminal */
1471  if (v->current_order.GetDestination() == v->targetairport) {
1472  /* FindFreeTerminal:
1473  * 1. Find a free terminal, 2. Occupy it, 3. Set the vehicle's state to that terminal */
1474  if (v->subtype == AIR_HELICOPTER) {
1475  if (!AirportFindFreeHelipad(v, apc)) return; // helicopter
1476  } else {
1477  if (!AirportFindFreeTerminal(v, apc)) return; // airplane
1478  }
1479  } else { // Else prepare for launch.
1480  /* airplane goto state takeoff, helicopter to helitakeoff */
1481  v->state = (v->subtype == AIR_HELICOPTER) ? HELITAKEOFF : TAKEOFF;
1482  }
1483  const Station *st = Station::GetByTile(v->tile);
1485  AirportMove(v, apc);
1486 }
1487 
1490 {
1491  /* if we just arrived, execute EnterTerminal first */
1492  if (v->previous_pos != v->pos) {
1493  AircraftEventHandler_EnterTerminal(v, apc);
1494  /* on an airport with helipads, a helicopter will always land there
1495  * and get serviced at the same time - setting */
1497  if (v->subtype == AIR_HELICOPTER && apc->num_helipads > 0) {
1498  /* an excerpt of ServiceAircraft, without the invisibility stuff */
1501  v->reliability = v->GetEngine()->reliability;
1503  }
1504  }
1505  return;
1506  }
1507 
1508  if (v->current_order.IsType(OT_NOTHING)) return;
1509 
1510  /* if the block of the next position is busy, stay put */
1511  if (AirportHasBlock(v, &apc->layout[v->pos], apc)) return;
1512 
1513  /* airport-road is free. We either have to go to another airport, or to the hangar
1514  * ---> start moving */
1515 
1516  bool go_to_hangar = false;
1517  switch (v->current_order.GetType()) {
1518  case OT_GOTO_STATION: // ready to fly to another airport
1519  break;
1520  case OT_GOTO_DEPOT: // visit hangar for servicing, sale, etc.
1521  go_to_hangar = v->current_order.GetDestination() == v->targetairport;
1522  break;
1523  case OT_CONDITIONAL:
1524  /* In case of a conditional order we just have to wait a tick
1525  * longer, so the conditional order can actually be processed;
1526  * we should not clear the order as that makes us go nowhere. */
1527  return;
1528  default: // orders have been deleted (no orders), goto depot and don't bother us
1529  v->current_order.Free();
1530  go_to_hangar = Station::Get(v->targetairport)->airport.HasHangar();
1531  }
1532 
1533  if (go_to_hangar) {
1534  v->state = HANGAR;
1535  } else {
1536  /* airplane goto state takeoff, helicopter to helitakeoff */
1537  v->state = (v->subtype == AIR_HELICOPTER) ? HELITAKEOFF : TAKEOFF;
1538  }
1539  AirportMove(v, apc);
1540 }
1541 
1542 static void AircraftEventHandler_General(Aircraft *v, const AirportFTAClass *apc)
1543 {
1544  error("OK, you shouldn't be here, check your Airport Scheme!");
1545 }
1546 
1547 static void AircraftEventHandler_TakeOff(Aircraft *v, const AirportFTAClass *apc)
1548 {
1549  PlayAircraftSound(v); // play takeoffsound for airplanes
1550  v->state = STARTTAKEOFF;
1551 }
1552 
1553 static void AircraftEventHandler_StartTakeOff(Aircraft *v, const AirportFTAClass *apc)
1554 {
1555  v->state = ENDTAKEOFF;
1557 }
1558 
1559 static void AircraftEventHandler_EndTakeOff(Aircraft *v, const AirportFTAClass *apc)
1560 {
1561  v->state = FLYING;
1562  /* get the next position to go to, differs per airport */
1564 }
1565 
1566 static void AircraftEventHandler_HeliTakeOff(Aircraft *v, const AirportFTAClass *apc)
1567 {
1568  v->state = FLYING;
1570 
1571  /* get the next position to go to, differs per airport */
1573 
1574  /* Send the helicopter to a hangar if needed for replacement */
1575  if (v->NeedsAutomaticServicing()) {
1576  Backup<CompanyByte> cur_company(_current_company, v->owner, FILE_LINE);
1578  cur_company.Restore();
1579  }
1580 }
1581 
1582 static void AircraftEventHandler_Flying(Aircraft *v, const AirportFTAClass *apc)
1583 {
1585 
1586  /* Runway busy, not allowed to use this airstation or closed, circle. */
1587  if (CanVehicleUseStation(v, st) && (st->owner == OWNER_NONE || st->owner == v->owner) && !(st->airport.flags & AIRPORT_CLOSED_block)) {
1588  /* {32,FLYING,NOTHING_block,37}, {32,LANDING,N,33}, {32,HELILANDING,N,41},
1589  * if it is an airplane, look for LANDING, for helicopter HELILANDING
1590  * it is possible to choose from multiple landing runways, so loop until a free one is found */
1591  byte landingtype = (v->subtype == AIR_HELICOPTER) ? HELILANDING : LANDING;
1592  const AirportFTA *current = apc->layout[v->pos].next;
1593  while (current != NULL) {
1594  if (current->heading == landingtype) {
1595  /* save speed before, since if AirportHasBlock is false, it resets them to 0
1596  * we don't want that for plane in air
1597  * hack for speed thingie */
1598  uint16 tcur_speed = v->cur_speed;
1599  uint16 tsubspeed = v->subspeed;
1600  if (!AirportHasBlock(v, current, apc)) {
1601  v->state = landingtype; // LANDING / HELILANDING
1602  /* it's a bit dirty, but I need to set position to next position, otherwise
1603  * if there are multiple runways, plane won't know which one it took (because
1604  * they all have heading LANDING). And also occupy that block! */
1605  v->pos = current->next_position;
1606  SETBITS(st->airport.flags, apc->layout[v->pos].block);
1607  return;
1608  }
1609  v->cur_speed = tcur_speed;
1610  v->subspeed = tsubspeed;
1611  }
1612  current = current->next;
1613  }
1614  }
1615  v->state = FLYING;
1616  v->pos = apc->layout[v->pos].next_position;
1617 }
1618 
1619 static void AircraftEventHandler_Landing(Aircraft *v, const AirportFTAClass *apc)
1620 {
1621  v->state = ENDLANDING;
1622  AircraftLandAirplane(v); // maybe crash airplane
1623 
1624  /* check if the aircraft needs to be replaced or renewed and send it to a hangar if needed */
1625  if (v->NeedsAutomaticServicing()) {
1626  Backup<CompanyByte> cur_company(_current_company, v->owner, FILE_LINE);
1628  cur_company.Restore();
1629  }
1630 }
1631 
1632 static void AircraftEventHandler_HeliLanding(Aircraft *v, const AirportFTAClass *apc)
1633 {
1634  v->state = HELIENDLANDING;
1636 }
1637 
1638 static void AircraftEventHandler_EndLanding(Aircraft *v, const AirportFTAClass *apc)
1639 {
1640  /* next block busy, don't do a thing, just wait */
1641  if (AirportHasBlock(v, &apc->layout[v->pos], apc)) return;
1642 
1643  /* if going to terminal (OT_GOTO_STATION) choose one
1644  * 1. in case all terminals are busy AirportFindFreeTerminal() returns false or
1645  * 2. not going for terminal (but depot, no order),
1646  * --> get out of the way to the hangar. */
1647  if (v->current_order.IsType(OT_GOTO_STATION)) {
1648  if (AirportFindFreeTerminal(v, apc)) return;
1649  }
1650  v->state = HANGAR;
1651 
1652 }
1653 
1654 static void AircraftEventHandler_HeliEndLanding(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 helipad (OT_GOTO_STATION) choose one. If airport doesn't have helipads, choose terminal
1660  * 1. in case all terminals/helipads are busy (AirportFindFreeHelipad() returns false) or
1661  * 2. not going for terminal (but depot, no order),
1662  * --> get out of the way to the hangar IF there are terminals on the airport.
1663  * --> else TAKEOFF
1664  * the reason behind this is that if an airport has a terminal, it also has a hangar. Airplanes
1665  * must go to a hangar. */
1666  if (v->current_order.IsType(OT_GOTO_STATION)) {
1667  if (AirportFindFreeHelipad(v, apc)) return;
1668  }
1670 }
1671 
1677 typedef void AircraftStateHandler(Aircraft *v, const AirportFTAClass *apc);
1680  AircraftEventHandler_General, // TO_ALL = 0
1681  AircraftEventHandler_InHangar, // HANGAR = 1
1682  AircraftEventHandler_AtTerminal, // TERM1 = 2
1683  AircraftEventHandler_AtTerminal, // TERM2 = 3
1684  AircraftEventHandler_AtTerminal, // TERM3 = 4
1685  AircraftEventHandler_AtTerminal, // TERM4 = 5
1686  AircraftEventHandler_AtTerminal, // TERM5 = 6
1687  AircraftEventHandler_AtTerminal, // TERM6 = 7
1688  AircraftEventHandler_AtTerminal, // HELIPAD1 = 8
1689  AircraftEventHandler_AtTerminal, // HELIPAD2 = 9
1690  AircraftEventHandler_TakeOff, // TAKEOFF = 10
1691  AircraftEventHandler_StartTakeOff, // STARTTAKEOFF = 11
1692  AircraftEventHandler_EndTakeOff, // ENDTAKEOFF = 12
1693  AircraftEventHandler_HeliTakeOff, // HELITAKEOFF = 13
1694  AircraftEventHandler_Flying, // FLYING = 14
1695  AircraftEventHandler_Landing, // LANDING = 15
1696  AircraftEventHandler_EndLanding, // ENDLANDING = 16
1697  AircraftEventHandler_HeliLanding, // HELILANDING = 17
1698  AircraftEventHandler_HeliEndLanding, // HELIENDLANDING = 18
1699  AircraftEventHandler_AtTerminal, // TERM7 = 19
1700  AircraftEventHandler_AtTerminal, // TERM8 = 20
1701  AircraftEventHandler_AtTerminal, // HELIPAD3 = 21
1702 };
1703 
1704 static void AirportClearBlock(const Aircraft *v, const AirportFTAClass *apc)
1705 {
1706  /* we have left the previous block, and entered the new one. Free the previous block */
1707  if (apc->layout[v->previous_pos].block != apc->layout[v->pos].block) {
1709 
1710  CLRBITS(st->airport.flags, apc->layout[v->previous_pos].block);
1711  }
1712 }
1713 
1714 static void AirportGoToNextPosition(Aircraft *v)
1715 {
1716  /* if aircraft is not in position, wait until it is */
1717  if (!AircraftController(v)) return;
1718 
1720 
1721  AirportClearBlock(v, apc);
1722  AirportMove(v, apc); // move aircraft to next position
1723 }
1724 
1725 /* gets pos from vehicle and next orders */
1726 static bool AirportMove(Aircraft *v, const AirportFTAClass *apc)
1727 {
1728  /* error handling */
1729  if (v->pos >= apc->nofelements) {
1730  DEBUG(misc, 0, "[Ap] position %d is not valid for current airport. Max position is %d", v->pos, apc->nofelements-1);
1731  assert(v->pos < apc->nofelements);
1732  }
1733 
1734  const AirportFTA *current = &apc->layout[v->pos];
1735  /* we have arrived in an important state (eg terminal, hangar, etc.) */
1736  if (current->heading == v->state) {
1737  byte prev_pos = v->pos; // location could be changed in state, so save it before-hand
1738  byte prev_state = v->state;
1739  _aircraft_state_handlers[v->state](v, apc);
1740  if (v->state != FLYING) v->previous_pos = prev_pos;
1741  if (v->state != prev_state || v->pos != prev_pos) UpdateAircraftCache(v);
1742  return true;
1743  }
1744 
1745  v->previous_pos = v->pos; // save previous location
1746 
1747  /* there is only one choice to move to */
1748  if (current->next == NULL) {
1749  if (AirportSetBlocks(v, current, apc)) {
1750  v->pos = current->next_position;
1752  } // move to next position
1753  return false;
1754  }
1755 
1756  /* there are more choices to choose from, choose the one that
1757  * matches our heading */
1758  do {
1759  if (v->state == current->heading || current->heading == TO_ALL) {
1760  if (AirportSetBlocks(v, current, apc)) {
1761  v->pos = current->next_position;
1763  } // move to next position
1764  return false;
1765  }
1766  current = current->next;
1767  } while (current != NULL);
1768 
1769  DEBUG(misc, 0, "[Ap] cannot move further on Airport! (pos %d state %d) for vehicle %d", v->pos, v->state, v->index);
1770  NOT_REACHED();
1771 }
1772 
1774 static bool AirportHasBlock(Aircraft *v, const AirportFTA *current_pos, const AirportFTAClass *apc)
1775 {
1776  const AirportFTA *reference = &apc->layout[v->pos];
1777  const AirportFTA *next = &apc->layout[current_pos->next_position];
1778 
1779  /* same block, then of course we can move */
1780  if (apc->layout[current_pos->position].block != next->block) {
1781  const Station *st = Station::Get(v->targetairport);
1782  uint64 airport_flags = next->block;
1783 
1784  /* check additional possible extra blocks */
1785  if (current_pos != reference && current_pos->block != NOTHING_block) {
1786  airport_flags |= current_pos->block;
1787  }
1788 
1789  if (st->airport.flags & airport_flags) {
1790  v->cur_speed = 0;
1791  v->subspeed = 0;
1792  return true;
1793  }
1794  }
1795  return false;
1796 }
1797 
1805 static bool AirportSetBlocks(Aircraft *v, const AirportFTA *current_pos, const AirportFTAClass *apc)
1806 {
1807  const AirportFTA *next = &apc->layout[current_pos->next_position];
1808  const AirportFTA *reference = &apc->layout[v->pos];
1809 
1810  /* if the next position is in another block, check it and wait until it is free */
1811  if ((apc->layout[current_pos->position].block & next->block) != next->block) {
1812  uint64 airport_flags = next->block;
1813  /* search for all all elements in the list with the same state, and blocks != N
1814  * this means more blocks should be checked/set */
1815  const AirportFTA *current = current_pos;
1816  if (current == reference) current = current->next;
1817  while (current != NULL) {
1818  if (current->heading == current_pos->heading && current->block != 0) {
1819  airport_flags |= current->block;
1820  break;
1821  }
1822  current = current->next;
1823  }
1824 
1825  /* if the block to be checked is in the next position, then exclude that from
1826  * checking, because it has been set by the airplane before */
1827  if (current_pos->block == next->block) airport_flags ^= next->block;
1828 
1830  if (st->airport.flags & airport_flags) {
1831  v->cur_speed = 0;
1832  v->subspeed = 0;
1833  return false;
1834  }
1835 
1836  if (next->block != NOTHING_block) {
1837  SETBITS(st->airport.flags, airport_flags); // occupy next block
1838  }
1839  }
1840  return true;
1841 }
1842 
1849  uint64 airport_flag;
1850 };
1851 
1854  {TERM1, TERM1_block},
1855  {TERM2, TERM2_block},
1856  {TERM3, TERM3_block},
1857  {TERM4, TERM4_block},
1858  {TERM5, TERM5_block},
1859  {TERM6, TERM6_block},
1860  {TERM7, TERM7_block},
1861  {TERM8, TERM8_block},
1865 };
1866 
1874 static bool FreeTerminal(Aircraft *v, byte i, byte last_terminal)
1875 {
1876  assert(last_terminal <= lengthof(_airport_terminal_mapping));
1878  for (; i < last_terminal; i++) {
1879  if ((st->airport.flags & _airport_terminal_mapping[i].airport_flag) == 0) {
1880  /* TERMINAL# HELIPAD# */
1881  v->state = _airport_terminal_mapping[i].state; // start moving to that terminal/helipad
1882  SETBITS(st->airport.flags, _airport_terminal_mapping[i].airport_flag); // occupy terminal/helipad
1883  return true;
1884  }
1885  }
1886  return false;
1887 }
1888 
1894 static uint GetNumTerminals(const AirportFTAClass *apc)
1895 {
1896  uint num = 0;
1897 
1898  for (uint i = apc->terminals[0]; i > 0; i--) num += apc->terminals[i];
1899 
1900  return num;
1901 }
1902 
1910 {
1911  /* example of more terminalgroups
1912  * {0,HANGAR,NOTHING_block,1}, {0,255,TERM_GROUP1_block,0}, {0,255,TERM_GROUP2_ENTER_block,1}, {0,0,N,1},
1913  * Heading 255 denotes a group. We see 2 groups here:
1914  * 1. group 0 -- TERM_GROUP1_block (check block)
1915  * 2. group 1 -- TERM_GROUP2_ENTER_block (check block)
1916  * First in line is checked first, group 0. If the block (TERM_GROUP1_block) is free, it
1917  * looks at the corresponding terminals of that group. If no free ones are found, other
1918  * possible groups are checked (in this case group 1, since that is after group 0). If that
1919  * fails, then attempt fails and plane waits
1920  */
1921  if (apc->terminals[0] > 1) {
1922  const Station *st = Station::Get(v->targetairport);
1923  const AirportFTA *temp = apc->layout[v->pos].next;
1924 
1925  while (temp != NULL) {
1926  if (temp->heading == 255) {
1927  if (!(st->airport.flags & temp->block)) {
1928  /* read which group do we want to go to?
1929  * (the first free group) */
1930  uint target_group = temp->next_position + 1;
1931 
1932  /* at what terminal does the group start?
1933  * that means, sum up all terminals of
1934  * groups with lower number */
1935  uint group_start = 0;
1936  for (uint i = 1; i < target_group; i++) {
1937  group_start += apc->terminals[i];
1938  }
1939 
1940  uint group_end = group_start + apc->terminals[target_group];
1941  if (FreeTerminal(v, group_start, group_end)) return true;
1942  }
1943  } else {
1944  /* once the heading isn't 255, we've exhausted the possible blocks.
1945  * So we cannot move */
1946  return false;
1947  }
1948  temp = temp->next;
1949  }
1950  }
1951 
1952  /* if there is only 1 terminalgroup, all terminals are checked (starting from 0 to max) */
1953  return FreeTerminal(v, 0, GetNumTerminals(apc));
1954 }
1955 
1963 {
1964  /* if an airport doesn't have helipads, use terminals */
1965  if (apc->num_helipads == 0) return AirportFindFreeTerminal(v, apc);
1966 
1967  /* only 1 helicoptergroup, check all helipads
1968  * The blocks for helipads start after the last terminal (MAX_TERMINALS) */
1970 }
1971 
1977 static void AircraftHandleDestTooFar(Aircraft *v, bool too_far)
1978 {
1979  if (too_far) {
1980  if (!HasBit(v->flags, VAF_DEST_TOO_FAR)) {
1983  AI::NewEvent(v->owner, new ScriptEventAircraftDestTooFar(v->index));
1984  if (v->owner == _local_company) {
1985  /* Post a news message. */
1986  SetDParam(0, v->index);
1987  AddVehicleAdviceNewsItem(STR_NEWS_AIRCRAFT_DEST_TOO_FAR, v->index);
1988  }
1989  }
1990  return;
1991  }
1992 
1993  if (HasBit(v->flags, VAF_DEST_TOO_FAR)) {
1994  /* Not too far anymore, clear flag and message. */
1997  DeleteVehicleNews(v->index, STR_NEWS_AIRCRAFT_DEST_TOO_FAR);
1998  }
1999 }
2000 
2001 static bool AircraftEventHandler(Aircraft *v, int loop)
2002 {
2003  if (v->vehstatus & VS_CRASHED) {
2004  return HandleCrashedAircraft(v);
2005  }
2006 
2007  if (v->vehstatus & VS_STOPPED) return true;
2008 
2009  v->HandleBreakdown();
2010 
2011  HandleAircraftSmoke(v, loop != 0);
2012  ProcessOrders(v);
2013  v->HandleLoading(loop != 0);
2014 
2015  if (v->current_order.IsType(OT_LOADING) || v->current_order.IsType(OT_LEAVESTATION)) return true;
2016 
2017  if (v->state >= ENDTAKEOFF && v->state <= HELIENDLANDING) {
2018  /* If we are flying, unconditionally clear the 'dest too far' state. */
2019  AircraftHandleDestTooFar(v, false);
2020  } else if (v->acache.cached_max_range_sqr != 0) {
2021  /* Check the distance to the next destination. This code works because the target
2022  * airport is only updated after take off and not on the ground. */
2024  Station *next_st = v->current_order.IsType(OT_GOTO_STATION) || v->current_order.IsType(OT_GOTO_DEPOT) ? Station::GetIfValid(v->current_order.GetDestination()) : NULL;
2025 
2026  if (cur_st != NULL && cur_st->airport.tile != INVALID_TILE && next_st != NULL && next_st->airport.tile != INVALID_TILE) {
2027  uint dist = DistanceSquare(cur_st->airport.tile, next_st->airport.tile);
2028  AircraftHandleDestTooFar(v, dist > v->acache.cached_max_range_sqr);
2029  }
2030  }
2031 
2032  if (!HasBit(v->flags, VAF_DEST_TOO_FAR)) AirportGoToNextPosition(v);
2033 
2034  return true;
2035 }
2036 
2038 {
2039  if (!this->IsNormalAircraft()) return true;
2040 
2041  this->tick_counter++;
2042 
2043  if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
2044 
2045  if (this->subtype == AIR_HELICOPTER) HelicopterTickHandler(this);
2046 
2047  this->current_order_time++;
2048 
2049  for (uint i = 0; i != 2; i++) {
2050  /* stop if the aircraft was deleted */
2051  if (!AircraftEventHandler(this, i)) return false;
2052  }
2053 
2054  return true;
2055 }
2056 
2057 
2065 {
2066  assert(v->type == VEH_AIRCRAFT);
2067 
2069  if (st == NULL) return NULL;
2070 
2071  return st->airport.tile == INVALID_TILE ? NULL : st;
2072 }
2073 
2079 {
2080  /* only 1 station is updated per function call, so it is enough to get entry_point once */
2081  const AirportFTAClass *ap = st->airport.GetFTA();
2082  Direction rotation = st->airport.tile == INVALID_TILE ? DIR_N : st->airport.rotation;
2083 
2084  Aircraft *v;
2085  FOR_ALL_AIRCRAFT(v) {
2086  if (!v->IsNormalAircraft() || v->targetairport != st->index) continue;
2087  assert(v->state == FLYING);
2088  v->pos = v->previous_pos = AircraftGetEntryPoint(v, ap, rotation);
2090  }
2091 }
Flag for an invalid direction.
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:81
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:169
uint16 reliability
Current reliability of the engine.
Definition: engine_base.h:27
byte type
Type of this airport,.
Definition: station_base.h:309
Date max_age
Maximum age.
Definition: vehicle_base.h:259
uint32 PaletteID
The number of the palette.
Definition: gfx_type.h:20
Vehicle is stopped by the player.
Definition: vehicle_base.h:33
First vehicle arrived for competitor.
Definition: news_type.h:38
Airplane wants to leave the airport.
Definition: airport.h:73
This airport has a short landing strip, dangerous for fast aircraft.
Definition: airport.h:151
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:77
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:134
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:1195
static const int DAYS_IN_YEAR
days per year
Definition: date_type.h:31
Finite sTate mAchine (FTA) of an airport.
Definition: airport.h:144
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:182
Takeoff movement.
Definition: airport.h:51
StationID targetairport
Airport to go to next.
Definition: aircraft.h:78
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:3120
static DiagDirection DirToDiagDir(Direction dir)
Convert a Direction to a DiagDirection.
byte next_position
next position from this position
Definition: airport.h:195
Direction GetHangarExitDirection(TileIndex tile) const
Get the exit direction of the hangar at a specific tile.
Definition: station_base.h:390
DirectionByte direction
facing
Definition: vehicle_base.h:271
Maximum speed of an aircraft that is broken.
static int UnScaleGUI(int value)
Short-hand to apply GUI zoom level.
Definition: zoom_func.h:72
Aircraft range.
static const uint64 HELIPAD1_block
Block belonging to helipad 1.
Definition: airport.h:96
East.
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:1762
A single location on an airport where aircraft can move to.
Definition: airport.h:132
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:338
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:95
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:260
Heading for terminal 6.
Definition: airport.h:70
Conventional Take Off and Landing, i.e. planes.
Definition: engine_type.h:93
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:332
Various explosions.
Use default vehicle palette.
Definition: vehicle_base.h:35
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:76
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:183
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:82
Depot view; Window numbers:
Definition: window_type.h:346
static const int ROTOR_Z_OFFSET
Z Offset between helicopter- and rotorsprite.
Definition: aircraft.h:50
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
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.
Station has seen an aircraft.
Definition: station_type.h:71
Functions related to vehicles.
Aircraft, helicopters, rotors and their shadows belong to this class.
Definition: aircraft.h:74
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:1426
void Draw(int x, int y, PaletteID default_pal, bool force_pal) const
Draw the sprite sequence.
Definition: vehicle.cpp:127
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:181
int16 y
y-coordinate of the destination.
Definition: airport.h:134
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
Northeast, upper right on your monitor.
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:2631
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:118
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:255
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
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:252
const Engine * GetEngine() const
Retrieves the engine of the vehicle.
Definition: vehicle.cpp:743
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:121
GoodsEntry goods[NUM_CARGO]
Goods at this station.
Definition: station_base.h:472
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:362
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:958
void UpdateDeltaXY(Direction direction)
Updates the x and y offsets and the size of the sprite used for this vehicle.
VehicleSpriteSeq sprite_seq
Vehicle appearance.
Definition: vehicle_base.h:280
Direction
Defines the 8 directions on the map.
Various explosions.
Southeast.
Class to backup a specific variable and restore it later.
Definition: backup_type.hpp:23
CompanyByte _local_company
Company controlled by the human player at this client. Can also be COMPANY_SPECTATOR.
Definition: company_cmd.cpp:46
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.
Northeast.
static const uint64 HELIPAD2_block
Block belonging to helipad 2.
Definition: airport.h:97
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 #EffectVehicles/#TrainSubTypes/#AircraftSubTypes) ...
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
Aircraft vehicle type.
Definition: vehicle_type.h:27
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:235
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.
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:436
byte subtype
Type of aircraft.
Definition: engine_type.h:102
void AgeVehicle(Vehicle *v)
Update age of a vehicle.
Definition: vehicle.cpp:1320
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:788
West.
SoundSettings sound
sound effect settings
Internal structure used in openttd - Finite sTate mAchine –> FTA.
Definition: airport.h:191
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
North.
bool IsType(OrderType type) const
Check whether this order is of the given type.
Definition: order_base.h:63
DoCommandFlag
List of flags for a command.
Definition: command_type.h:340
Southeast.
Southwest.
T * Next() const
Get next vehicle in the chain.
ClientSettings _settings_client
The current settings for this game.
Definition: settings.cpp:76
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:180
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:129
void InvalidateNewGRFCacheOfChain()
Invalidates cached NewGRF variables of all vehicles in the chain (after the current vehicle) ...
Definition: vehicle_base.h:461
bool ProcessOrders(Vehicle *v)
Handle the orders of a vehicle and determine the next place to go to if needed.
Definition: order_cmd.cpp:2160
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:178
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
The tile has no ownership.
Definition: company_type.h:27
Northwest.
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:2752
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
StationFacilityByte facilities
The facilities that this station has.
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:308
Heading for terminal 3.
Definition: airport.h:67
DiagDirection
Enumeration for diagonal directions.
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:171
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:77
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:373
AirportMovementStates
Movement States on Airports (headings target)
Definition: airport.h:62
DirectionByte rotation
How this airport is rotated.
Definition: station_base.h:311
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.
byte state
State of the airport.
Definition: aircraft.h:79
uint Truncate(uint max_move=UINT_MAX, StationCargoAmountMap *cargo_per_source=NULL)
Truncates where each destination loses roughly the same percentage of its cargo.
byte turn_counter
Ticks between each turn to prevent > 45 degree turns.
Definition: aircraft.h:82
uint DetermineCapacity(const Vehicle *v, uint16 *mail_capacity=NULL) const
Determines capacity of a given vehicle from scratch.
Definition: engine.cpp:206
static void NewEvent(CompanyID company, ScriptEvent *event)
Queue a new event for an AI.
Definition: ai_core.cpp:233
static T Clamp(const T a, const T min, const T max)
Clamp a value between an interval.
Definition: math_func.hpp:139
#define DEBUG(name, level,...)
Output a line of debugging information.
Definition: debug.h:39
Maximal number of cargo types in a game.
Definition: cargo_type.h:66
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
OwnerByte owner
The owner of this station.
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:342
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 (serivce 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:403
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:1608
void UpdatePosition()
Update the position of the vehicle.
Definition: vehicle.cpp:1547
rotor of an helicopter
Definition: aircraft.h:36
static StationID GetStationIndex(TileIndex t)
Get StationID from a tile.
Definition: station_map.h:29
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:68
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:163
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:3134
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:1254
static const uint64 TERM7_block
Block belonging to terminal 7.
Definition: airport.h:116
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:22
CompanyByte _current_company
Company currently doing an action.
Definition: company_cmd.cpp:47
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:1569
void BeginLoading()
Prepare everything to begin the loading when arriving at a station.
Definition: vehicle.cpp:2005
Vehicle * Next() const
Get the next vehicle of this vehicle.
Definition: vehicle_base.h:582
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:98
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
First vehicle arrived for company.
Definition: news_type.h:37
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:90
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:193
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:110
OwnerByte owner
Which company owns the vehicle?
Definition: vehicle_base.h:273
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:67
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:117
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:133
static uint MapMaxY()
Gets the maximum Y coordinate within the map, including MP_VOID.
Definition: map_func.h:113
Running costs aircrafts.
Definition: economy_type.h:155
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:192
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:93
Functions related to commands.
An accident or disaster has occurred.
Definition: news_type.h:39
void GetImage(Direction direction, EngineImageType image_type, VehicleSpriteSeq *result) const
Gets the sprite to show for the given direction.
Heading for terminal 5.
Definition: airport.h:69
#define FOR_ALL_AIRCRAFT(var)
Macro for iterating over all aircrafts.
Definition: aircraft.h:142
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.
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:460
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.
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:218
byte progress
The percentage (if divided by 256) this vehicle already crossed the tile unit.
Definition: vehicle_base.h:297
uint16 flag
special flags when moving towards the destination.
Definition: airport.h:135
static const uint64 TERM3_block
Block belonging to terminal 3.
Definition: airport.h:92
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:91
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:196
uint DistanceSquare(TileIndex t0, TileIndex t1)
Gets the &#39;Square&#39; distance between the two given tiles.
Definition: map.cpp:176
DirectionByte direction
Direction to turn the aircraft after reaching the destination.
Definition: airport.h:136
byte flags
Aircraft flags.
Definition: aircraft.h:83
virtual bool IsChainInDepot() const
Check whether the whole vehicle chain is in the depot.
Definition: vehicle_base.h:511
Window functions not directly related to making/drawing windows.
byte position
the position that an airplane is at
Definition: airport.h:194
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:75
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:3148
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:179
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.
This depot order is because of the servicing limit.
Definition: order_type.h:101
VehicleTypeByte type
Type of vehicle.
Definition: vehicle_type.h:54
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:2214
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:446
Functions related to effect vehicles.
uint GetOldAdvanceSpeed(uint speed)
Determines the effective direction-specific vehicle movement speed.
Definition: vehicle_base.h:386
Station with an airport.
Definition: station_type.h:58
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:99
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:184
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:1589
uint16 passenger_capacity
Passenger capacity (persons).
Definition: engine_type.h:107
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:3220
byte mail_capacity
Mail capacity (bags).
Definition: engine_type.h:106
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
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:88
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:94
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.