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 GetCustomVehicleSprite(
this, direction, image_type, result);
166 assert(IsValidImageIndex<VEH_AIRCRAFT>(spritenum));
167 result->
Set(direction + _aircraft_sprite[spritenum]);
176 GetCustomRotorSprite(v,
false, image_type, result);
181 result->
Set(SPR_ROTOR_STOPPED + w->
state);
187 uint8 spritenum = e->u.air.image_index;
189 if (is_custom_sprite(spritenum)) {
190 GetCustomVehicleIcon(engine,
DIR_W, image_type, result);
196 assert(IsValidImageIndex<VEH_AIRCRAFT>(spritenum));
197 result->
Set(
DIR_W + _aircraft_sprite[spritenum]);
203 GetAircraftIcon(engine, image_type, &seq);
207 preferred_x =
Clamp(preferred_x,
213 if (!(AircraftVehInfo(engine)->subtype &
AIR_CTOL)) {
215 GetCustomRotorIcon(engine, image_type, &rotor_seq);
216 if (!rotor_seq.
IsValid()) rotor_seq.
Set(SPR_ROTOR_STOPPED);
233 GetAircraftIcon(engine, image_type, &seq);
238 width =
UnScaleGUI(rect.right - rect.left + 1);
239 height =
UnScaleGUI(rect.bottom - rect.top + 1);
281 u->
z_pos = GetSlopePixelZ(x, y);
315 _new_vehicle_id = v->
index;
365 w->
state = HRS_ROTOR_STOPPED;
385 if (station == INVALID_STATION)
return false;
390 if (location != NULL) *location = st->
xy;
391 if (destination != NULL) *destination = st->
index;
396 static void CheckIfAircraftNeedsService(
Aircraft *v)
437 CheckVehicleBreakdown(
this);
439 CheckIfAircraftNeedsService(
this);
454 static void HelicopterTickHandler(
Aircraft *v)
483 u->
state = HRS_ROTOR_STOPPED;
486 }
else if (tick >= spd) {
489 if (u->
state > HRS_ROTOR_MOVING_3) u->
state = HRS_ROTOR_MOVING_1;
524 u->
y_pos = y - ((v->
z_pos - GetSlopePixelZ(safe_x, safe_y)) >> 3);
527 u->
z_pos = GetSlopePixelZ(safe_x, safe_y);
562 static void PlayAircraftSound(
const Vehicle *v)
565 SndPlayVehicleFx(AircraftVehInfo(v->
engine_type)->sfx, v);
579 if (max_speed != 0) {
581 max_speed = (max_speed * 128) / 10;
638 if (v->
cur_speed < speed_limit) hard_limit =
false;
650 if (!hard_limit && v->
cur_speed > speed_limit) {
743 int GetAircraftFlightLevel(T *v,
bool takeoff)
747 int aircraft_min_altitude;
748 int aircraft_max_altitude;
750 int aircraft_middle_altitude = (aircraft_min_altitude + aircraft_max_altitude) / 2;
753 assert(aircraft_min_altitude < aircraft_middle_altitude);
754 assert(aircraft_middle_altitude < aircraft_max_altitude);
757 if (z < aircraft_min_altitude ||
763 z += takeoff ? 2 : 1;
764 }
else if (!takeoff && (z > aircraft_max_altitude ||
817 if (
abs(delta_y) <
abs(delta_x)) {
847 uint size_x = 1, size_y = 1;
892 SndPlayVehicleFx(SND_18_HELICOPTER, v);
905 if (v->
z_pos >= z_dest) {
931 int z = GetSlopePixelZ(x, y) + 1 + afc->
delta_z;
984 bool hard_limit =
true;
992 if (count == 0)
return false;
1002 gp.x = (v->
x_pos != (x + amd.
x)) ?
1005 gp.
y = (v->
y_pos != (y + amd.
y)) ?
1015 Direction newdir = GetDirectionTowards(v, x + amd.
x, y + amd.
y);
1018 if (v->
turn_counter == 0 || newdir == v->last_direction) {
1019 if (newdir == v->last_direction) {
1059 z = GetAircraftFlightLevel(v,
true);
1064 z = GetAircraftFlightLevel(v);
1078 int curz = GetSlopePixelZ(x + amd.
x, y + amd.
y) + 1;
1082 int t =
max(1U, dist - 4);
1083 int delta = z - curz;
1089 if (z < curz) z = curz;
1094 int curz = GetSlopePixelZ(x, y) + 1;
1098 }
else if (z < curz) {
1105 }
while (--count != 0);
1123 if (v->
z_pos == z) {
1132 static const DirDiff delta[] = {
1173 static const struct {
1207 void HandleMissingAircraftOrders(
Aircraft *v)
1228 cur_company.Restore();
1274 uint pass = v->
Crash();
1282 newsitem = STR_NEWS_PLANE_CRASH_OUT_OF_FUEL;
1285 newsitem = STR_NEWS_AIRCRAFT_CRASH;
1288 AI::NewEvent(v->
owner,
new ScriptEventVehicleCrashed(v->
index, v->
tile, st == NULL ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING));
1289 Game::NewEvent(
new ScriptEventVehicleCrashed(v->
index, v->
tile, st == NULL ? ScriptEventVehicleCrashed::CRASH_AIRCRAFT_NO_AIRPORT : ScriptEventVehicleCrashed::CRASH_PLANE_LANDING));
1293 ModifyStationRatingAround(v->
tile, v->
owner, -160, 30);
1310 (AircraftVehInfo(v->
engine_type)->subtype & AIR_FAST) &&
1317 if (
GB(Random(), 0, 22) > prob)
return;
1346 STR_NEWS_FIRST_AIRCRAFT_ARRIVAL,
1367 SndPlayVehicleFx(SND_17_SKID_PLANE, v);
1485 AirportMove(v, apc);
1493 AircraftEventHandler_EnterTerminal(v, apc);
1516 bool go_to_hangar =
false;
1518 case OT_GOTO_STATION:
1523 case OT_CONDITIONAL:
1539 AirportMove(v, apc);
1544 error(
"OK, you shouldn't be here, check your Airport Scheme!");
1549 PlayAircraftSound(v);
1578 cur_company.Restore();
1593 while (current != NULL) {
1594 if (current->
heading == landingtype) {
1601 v->
state = landingtype;
1612 current = current->
next;
1628 cur_company.Restore();
1680 AircraftEventHandler_General,
1690 AircraftEventHandler_TakeOff,
1691 AircraftEventHandler_StartTakeOff,
1692 AircraftEventHandler_EndTakeOff,
1693 AircraftEventHandler_HeliTakeOff,
1694 AircraftEventHandler_Flying,
1695 AircraftEventHandler_Landing,
1696 AircraftEventHandler_EndLanding,
1697 AircraftEventHandler_HeliLanding,
1698 AircraftEventHandler_HeliEndLanding,
1714 static void AirportGoToNextPosition(
Aircraft *v)
1721 AirportClearBlock(v, apc);
1722 AirportMove(v, apc);
1730 DEBUG(misc, 0,
"[Ap] position %d is not valid for current airport. Max position is %d", v->
pos, apc->
nofelements-1);
1737 byte prev_pos = v->
pos;
1738 byte prev_state = v->
state;
1739 _aircraft_state_handlers[v->
state](v, apc);
1740 if (v->state !=
FLYING) v->previous_pos = prev_pos;
1745 v->previous_pos = v->pos;
1748 if (current->
next == NULL) {
1766 current = current->
next;
1767 }
while (current != NULL);
1769 DEBUG(misc, 0,
"[Ap] cannot move further on Airport! (pos %d state %d) for vehicle %d", v->pos, v->state, v->index);
1782 uint64 airport_flags = next->
block;
1785 if (current_pos != reference && current_pos->
block != NOTHING_block) {
1786 airport_flags |= current_pos->
block;
1812 uint64 airport_flags = next->
block;
1816 if (current == reference) current = current->
next;
1817 while (current != NULL) {
1819 airport_flags |= current->
block;
1822 current = current->
next;
1836 if (next->
block != NOTHING_block) {
1876 assert(last_terminal <=
lengthof(_airport_terminal_mapping));
1878 for (; i < last_terminal; i++) {
1881 v->
state = _airport_terminal_mapping[i].
state;
1925 while (temp != NULL) {
1935 uint group_start = 0;
1936 for (uint i = 1; i < target_group; i++) {
1940 uint group_end = group_start + apc->
terminals[target_group];
1941 if (
FreeTerminal(v, group_start, group_end))
return true;
2001 static bool AircraftEventHandler(
Aircraft *v,
int loop)
2049 for (uint i = 0; i != 2; i++) {
2051 if (!AircraftEventHandler(
this, i))
return false;
2069 if (st == NULL)
return NULL;