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