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);
207 if (!(AircraftVehInfo(engine)->subtype &
AIR_CTOL)) {
208 SpriteID rotor_sprite = GetCustomRotorIcon(engine, image_type);
209 if (rotor_sprite == 0) rotor_sprite = SPR_ROTOR_STOPPED;
225 const Sprite *spr = GetSprite(GetAircraftIcon(engine, image_type),
ST_NORMAL);
270 u->
z_pos = GetSlopePixelZ(x, y);
304 _new_vehicle_id = v->
index;
353 w->
state = HRS_ROTOR_STOPPED;
373 if (station == INVALID_STATION)
return false;
378 if (location != NULL) *location = st->
xy;
379 if (destination != NULL) *destination = st->
index;
384 static void CheckIfAircraftNeedsService(
Aircraft *v)
425 CheckVehicleBreakdown(
this);
427 CheckIfAircraftNeedsService(
this);
442 static void HelicopterTickHandler(
Aircraft *v)
471 u->
state = HRS_ROTOR_STOPPED;
474 }
else if (tick >= spd) {
477 if (u->
state > HRS_ROTOR_MOVING_3) u->
state = HRS_ROTOR_MOVING_1;
510 u->
y_pos = y - ((v->
z_pos - GetSlopePixelZ(safe_x, safe_y)) >> 3);
513 u->
z_pos = GetSlopePixelZ(safe_x, safe_y);
548 static void PlayAircraftSound(
const Vehicle *v)
551 SndPlayVehicleFx(AircraftVehInfo(v->
engine_type)->sfx, v);
565 if (max_speed != 0) {
567 max_speed = (max_speed * 128) / 10;
624 if (v->
cur_speed < speed_limit) hard_limit =
false;
636 if (!hard_limit && v->
cur_speed > speed_limit) {
729 int GetAircraftFlightLevel(T *v,
bool takeoff)
733 int aircraft_min_altitude;
734 int aircraft_max_altitude;
736 int aircraft_middle_altitude = (aircraft_min_altitude + aircraft_max_altitude) / 2;
739 assert(aircraft_min_altitude < aircraft_middle_altitude);
740 assert(aircraft_middle_altitude < aircraft_max_altitude);
743 if (z < aircraft_min_altitude ||
749 z += takeoff ? 2 : 1;
750 }
else if (!takeoff && (z > aircraft_max_altitude ||
803 if (
abs(delta_y) <
abs(delta_x)) {
833 uint size_x = 1, size_y = 1;
878 SndPlayVehicleFx(SND_18_HELICOPTER, v);
891 if (v->
z_pos >= z_dest) {
917 int z = GetSlopePixelZ(x, y) + 1 + afc->
delta_z;
970 bool hard_limit =
true;
978 if (count == 0)
return false;
988 gp.x = (v->
x_pos != (x + amd.
x)) ?
991 gp.
y = (v->
y_pos != (y + amd.
y)) ?
1001 Direction newdir = GetDirectionTowards(v, x + amd.
x, y + amd.
y);
1004 if (v->
turn_counter == 0 || newdir == v->last_direction) {
1005 if (newdir == v->last_direction) {
1045 z = GetAircraftFlightLevel(v,
true);
1050 z = GetAircraftFlightLevel(v);
1064 int curz = GetSlopePixelZ(x + amd.
x, y + amd.
y) + 1;
1068 int t =
max(1U, dist - 4);
1069 int delta = z - curz;
1075 if (z < curz) z = curz;
1080 int curz = GetSlopePixelZ(x, y) + 1;
1084 }
else if (z < curz) {
1091 }
while (--count != 0);
1109 if (v->
z_pos == z) {
1118 static const DirDiff delta[] = {
1159 static const struct {
1193 void HandleMissingAircraftOrders(
Aircraft *v)
1214 cur_company.Restore();
1258 uint pass = v->
Crash();
1266 newsitem = STR_NEWS_PLANE_CRASH_OUT_OF_FUEL;
1269 newsitem = STR_NEWS_AIRCRAFT_CRASH;
1272 AI::NewEvent(v->
owner,
new ScriptEventVehicleCrashed(v->
index, v->
tile, st == NULL ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING));
1273 Game::NewEvent(
new ScriptEventVehicleCrashed(v->
index, v->
tile, st == NULL ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING));
1277 ModifyStationRatingAround(v->
tile, v->
owner, -160, 30);
1294 (AircraftVehInfo(v->
engine_type)->subtype & AIR_FAST) &&
1301 if (
GB(Random(), 0, 22) > prob)
return;
1330 STR_NEWS_FIRST_AIRCRAFT_ARRIVAL,
1351 SndPlayVehicleFx(SND_17_SKID_PLANE, v);
1469 AirportMove(v, apc);
1477 AircraftEventHandler_EnterTerminal(v, apc);
1500 bool go_to_hangar =
false;
1502 case OT_GOTO_STATION:
1507 case OT_CONDITIONAL:
1523 AirportMove(v, apc);
1528 error(
"OK, you shouldn't be here, check your Airport Scheme!");
1533 PlayAircraftSound(v);
1562 cur_company.Restore();
1577 while (current != NULL) {
1578 if (current->
heading == landingtype) {
1585 v->
state = landingtype;
1596 current = current->
next;
1612 cur_company.Restore();
1664 AircraftEventHandler_General,
1674 AircraftEventHandler_TakeOff,
1675 AircraftEventHandler_StartTakeOff,
1676 AircraftEventHandler_EndTakeOff,
1677 AircraftEventHandler_HeliTakeOff,
1678 AircraftEventHandler_Flying,
1679 AircraftEventHandler_Landing,
1680 AircraftEventHandler_EndLanding,
1681 AircraftEventHandler_HeliLanding,
1682 AircraftEventHandler_HeliEndLanding,
1698 static void AirportGoToNextPosition(
Aircraft *v)
1705 AirportClearBlock(v, apc);
1706 AirportMove(v, apc);
1714 DEBUG(misc, 0,
"[Ap] position %d is not valid for current airport. Max position is %d", v->
pos, apc->
nofelements-1);
1721 byte prev_pos = v->
pos;
1722 byte prev_state = v->
state;
1723 _aircraft_state_handlers[v->
state](v, apc);
1724 if (v->state !=
FLYING) v->previous_pos = prev_pos;
1729 v->previous_pos = v->pos;
1732 if (current->
next == NULL) {
1750 current = current->
next;
1751 }
while (current != NULL);
1753 DEBUG(misc, 0,
"[Ap] cannot move further on Airport! (pos %d state %d) for vehicle %d", v->pos, v->state, v->index);
1766 uint64 airport_flags = next->
block;
1769 if (current_pos != reference && current_pos->
block != NOTHING_block) {
1770 airport_flags |= current_pos->
block;
1796 uint64 airport_flags = next->
block;
1800 if (current == reference) current = current->
next;
1801 while (current != NULL) {
1803 airport_flags |= current->
block;
1806 current = current->
next;
1820 if (next->
block != NOTHING_block) {
1860 assert(last_terminal <=
lengthof(_airport_terminal_mapping));
1862 for (; i < last_terminal; i++) {
1865 v->
state = _airport_terminal_mapping[i].
state;
1909 while (temp != NULL) {
1919 uint group_start = 0;
1920 for (uint i = 1; i < target_group; i++) {
1924 uint group_end = group_start + apc->
terminals[target_group];
1925 if (
FreeTerminal(v, group_start, group_end))
return true;
1985 static bool AircraftEventHandler(
Aircraft *v,
int loop)
2033 for (uint i = 0; i != 2; i++) {
2035 if (!AircraftEventHandler(
this, i))
return false;
2053 if (st == NULL)
return NULL;