41 #include "table/strings.h"
53 default: NOT_REACHED();
57 switch (this->
state) {
89 static const SpriteID _aircraft_sprite[] = {
90 0x0EB5, 0x0EBD, 0x0EC5, 0x0ECD,
91 0x0ED5, 0x0EDD, 0x0E9D, 0x0EA5,
92 0x0EAD, 0x0EE5, 0x0F05, 0x0F0D,
93 0x0F15, 0x0F1D, 0x0F25, 0x0F2D,
94 0x0EED, 0x0EF5, 0x0EFD, 0x0F35,
95 0x0E9D, 0x0EA5, 0x0EAD, 0x0EB5,
100 bool IsValidImageIndex<VEH_AIRCRAFT>(uint8 image_index)
102 return image_index <
lengthof(_aircraft_sprite);
124 StationID index = INVALID_STATION;
128 FOR_ALL_STATIONS(st) {
147 if (distance < best || index == INVALID_STATION) {
159 if (is_custom_sprite(spritenum)) {
160 SpriteID sprite = GetCustomVehicleSprite(
this, direction, image_type);
161 if (sprite != 0)
return sprite;
166 assert(IsValidImageIndex<VEH_AIRCRAFT>(spritenum));
167 return direction + _aircraft_sprite[
spritenum];
176 SpriteID sprite = GetCustomRotorSprite(v,
false, image_type);
177 if (sprite != 0)
return sprite;
181 return SPR_ROTOR_STOPPED + w->
state;
187 uint8 spritenum = e->u.air.image_index;
189 if (is_custom_sprite(spritenum)) {
190 SpriteID sprite = GetCustomVehicleIcon(engine,
DIR_W, image_type);
191 if (sprite != 0)
return sprite;
196 assert(IsValidImageIndex<VEH_AIRCRAFT>(spritenum));
197 return DIR_W + _aircraft_sprite[spritenum];
202 SpriteID sprite = GetAircraftIcon(engine, image_type);
204 preferred_x =
Clamp(preferred_x,
209 if (!(AircraftVehInfo(engine)->subtype &
AIR_CTOL)) {
210 SpriteID rotor_sprite = GetCustomRotorIcon(engine, image_type);
211 if (rotor_sprite == 0) rotor_sprite = SPR_ROTOR_STOPPED;
227 const Sprite *spr = GetSprite(GetAircraftIcon(engine, image_type),
ST_NORMAL);
272 u->
z_pos = GetSlopePixelZ(x, y);
306 _new_vehicle_id = v->
index;
355 w->
state = HRS_ROTOR_STOPPED;
375 if (station == INVALID_STATION)
return false;
380 if (location != NULL) *location = st->
xy;
381 if (destination != NULL) *destination = st->
index;
386 static void CheckIfAircraftNeedsService(
Aircraft *v)
427 CheckVehicleBreakdown(
this);
429 CheckIfAircraftNeedsService(
this);
444 static void HelicopterTickHandler(
Aircraft *v)
473 u->
state = HRS_ROTOR_STOPPED;
476 }
else if (tick >= spd) {
479 if (u->
state > HRS_ROTOR_MOVING_3) u->
state = HRS_ROTOR_MOVING_1;
512 u->
y_pos = y - ((v->
z_pos - GetSlopePixelZ(safe_x, safe_y)) >> 3);
515 u->
z_pos = GetSlopePixelZ(safe_x, safe_y);
550 static void PlayAircraftSound(
const Vehicle *v)
553 SndPlayVehicleFx(AircraftVehInfo(v->
engine_type)->sfx, v);
567 if (max_speed != 0) {
569 max_speed = (max_speed * 128) / 10;
626 if (v->
cur_speed < speed_limit) hard_limit =
false;
638 if (!hard_limit && v->
cur_speed > speed_limit) {
731 int GetAircraftFlightLevel(T *v,
bool takeoff)
735 int aircraft_min_altitude;
736 int aircraft_max_altitude;
738 int aircraft_middle_altitude = (aircraft_min_altitude + aircraft_max_altitude) / 2;
741 assert(aircraft_min_altitude < aircraft_middle_altitude);
742 assert(aircraft_middle_altitude < aircraft_max_altitude);
745 if (z < aircraft_min_altitude ||
751 z += takeoff ? 2 : 1;
752 }
else if (!takeoff && (z > aircraft_max_altitude ||
805 if (
abs(delta_y) <
abs(delta_x)) {
835 uint size_x = 1, size_y = 1;
880 SndPlayVehicleFx(SND_18_HELICOPTER, v);
893 if (v->
z_pos >= z_dest) {
919 int z = GetSlopePixelZ(x, y) + 1 + afc->
delta_z;
972 bool hard_limit =
true;
980 if (count == 0)
return false;
990 gp.x = (v->
x_pos != (x + amd.
x)) ?
993 gp.
y = (v->
y_pos != (y + amd.
y)) ?
1003 Direction newdir = GetDirectionTowards(v, x + amd.
x, y + amd.
y);
1006 if (v->
turn_counter == 0 || newdir == v->last_direction) {
1007 if (newdir == v->last_direction) {
1047 z = GetAircraftFlightLevel(v,
true);
1052 z = GetAircraftFlightLevel(v);
1066 int curz = GetSlopePixelZ(x + amd.
x, y + amd.
y) + 1;
1070 int t =
max(1U, dist - 4);
1071 int delta = z - curz;
1077 if (z < curz) z = curz;
1082 int curz = GetSlopePixelZ(x, y) + 1;
1086 }
else if (z < curz) {
1093 }
while (--count != 0);
1111 if (v->
z_pos == z) {
1120 static const DirDiff delta[] = {
1161 static const struct {
1195 void HandleMissingAircraftOrders(
Aircraft *v)
1216 cur_company.Restore();
1260 uint pass = v->
Crash();
1268 newsitem = STR_NEWS_PLANE_CRASH_OUT_OF_FUEL;
1271 newsitem = STR_NEWS_AIRCRAFT_CRASH;
1274 AI::NewEvent(v->
owner,
new ScriptEventVehicleCrashed(v->
index, v->
tile, st == NULL ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING));
1275 Game::NewEvent(
new ScriptEventVehicleCrashed(v->
index, v->
tile, st == NULL ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING));
1279 ModifyStationRatingAround(v->
tile, v->
owner, -160, 30);
1296 (AircraftVehInfo(v->
engine_type)->subtype & AIR_FAST) &&
1303 if (
GB(Random(), 0, 22) > prob)
return;
1332 STR_NEWS_FIRST_AIRCRAFT_ARRIVAL,
1353 SndPlayVehicleFx(SND_17_SKID_PLANE, v);
1471 AirportMove(v, apc);
1479 AircraftEventHandler_EnterTerminal(v, apc);
1502 bool go_to_hangar =
false;
1504 case OT_GOTO_STATION:
1509 case OT_CONDITIONAL:
1525 AirportMove(v, apc);
1530 error(
"OK, you shouldn't be here, check your Airport Scheme!");
1535 PlayAircraftSound(v);
1564 cur_company.Restore();
1579 while (current != NULL) {
1580 if (current->
heading == landingtype) {
1587 v->
state = landingtype;
1598 current = current->
next;
1614 cur_company.Restore();
1666 AircraftEventHandler_General,
1676 AircraftEventHandler_TakeOff,
1677 AircraftEventHandler_StartTakeOff,
1678 AircraftEventHandler_EndTakeOff,
1679 AircraftEventHandler_HeliTakeOff,
1680 AircraftEventHandler_Flying,
1681 AircraftEventHandler_Landing,
1682 AircraftEventHandler_EndLanding,
1683 AircraftEventHandler_HeliLanding,
1684 AircraftEventHandler_HeliEndLanding,
1700 static void AirportGoToNextPosition(
Aircraft *v)
1707 AirportClearBlock(v, apc);
1708 AirportMove(v, apc);
1716 DEBUG(misc, 0,
"[Ap] position %d is not valid for current airport. Max position is %d", v->
pos, apc->
nofelements-1);
1723 byte prev_pos = v->
pos;
1724 byte prev_state = v->
state;
1725 _aircraft_state_handlers[v->
state](v, apc);
1726 if (v->state !=
FLYING) v->previous_pos = prev_pos;
1731 v->previous_pos = v->pos;
1734 if (current->
next == NULL) {
1752 current = current->
next;
1753 }
while (current != NULL);
1755 DEBUG(misc, 0,
"[Ap] cannot move further on Airport! (pos %d state %d) for vehicle %d", v->pos, v->state, v->index);
1768 uint64 airport_flags = next->
block;
1771 if (current_pos != reference && current_pos->
block != NOTHING_block) {
1772 airport_flags |= current_pos->
block;
1798 uint64 airport_flags = next->
block;
1802 if (current == reference) current = current->
next;
1803 while (current != NULL) {
1805 airport_flags |= current->
block;
1808 current = current->
next;
1822 if (next->
block != NOTHING_block) {
1862 assert(last_terminal <=
lengthof(_airport_terminal_mapping));
1864 for (; i < last_terminal; i++) {
1867 v->
state = _airport_terminal_mapping[i].
state;
1911 while (temp != NULL) {
1921 uint group_start = 0;
1922 for (uint i = 1; i < target_group; i++) {
1926 uint group_end = group_start + apc->
terminals[target_group];
1927 if (
FreeTerminal(v, group_start, group_end))
return true;
1987 static bool AircraftEventHandler(
Aircraft *v,
int loop)
2035 for (uint i = 0; i != 2; i++) {
2037 if (!AircraftEventHandler(
this, i))
return false;
2055 if (st == NULL)
return NULL;