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