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