* Controls the movement of an aircraft. This function actually moves the vehicle * on the map and takes care of minor things like sound playback. * @todo De-mystify the cur_speed values for helicopter rotors. * @param v The vehicle that is moved. Must be the first vehicle of the chain * @return Whether the position requested by the State Machine has been reached */
| 863 | * @return Whether the position requested by the State Machine has been reached |
| 864 | */ |
| 865 | static bool AircraftController(Aircraft *v) |
| 866 | { |
| 867 | /* nullptr if station is invalid */ |
| 868 | const Station *st = Station::GetIfValid(v->targetairport); |
| 869 | /* INVALID_TILE if there is no station */ |
| 870 | TileIndex tile = INVALID_TILE; |
| 871 | Direction rotation = DIR_N; |
| 872 | uint size_x = 1, size_y = 1; |
| 873 | if (st != nullptr) { |
| 874 | if (st->airport.tile != INVALID_TILE) { |
| 875 | tile = st->airport.tile; |
| 876 | rotation = st->airport.rotation; |
| 877 | size_x = st->airport.w; |
| 878 | size_y = st->airport.h; |
| 879 | } else { |
| 880 | tile = st->xy; |
| 881 | } |
| 882 | } |
| 883 | /* DUMMY if there is no station or no airport */ |
| 884 | const AirportFTAClass *afc = tile == INVALID_TILE ? GetAirport(AT_DUMMY) : st->airport.GetFTA(); |
| 885 | |
| 886 | /* prevent going to INVALID_TILE if airport is deleted. */ |
| 887 | if (st == nullptr || st->airport.tile == INVALID_TILE) { |
| 888 | /* Jump into our "holding pattern" state machine if possible */ |
| 889 | if (v->pos >= afc->nofelements) { |
| 890 | v->pos = v->previous_pos = AircraftGetEntryPoint(v, afc, DIR_N); |
| 891 | } else if (v->targetairport != v->current_order.GetDestination()) { |
| 892 | /* If not possible, just get out of here fast */ |
| 893 | v->state = FLYING; |
| 894 | UpdateAircraftCache(v); |
| 895 | AircraftNextAirportPos_and_Order(v); |
| 896 | /* get aircraft back on running altitude */ |
| 897 | SetAircraftPosition(v, v->x_pos, v->y_pos, GetAircraftFlightLevel(v)); |
| 898 | return false; |
| 899 | } |
| 900 | } |
| 901 | |
| 902 | /* get airport moving data */ |
| 903 | const AirportMovingData amd = RotateAirportMovingData(afc->MovingData(v->pos), rotation, size_x, size_y); |
| 904 | |
| 905 | int x = TileX(tile) * TILE_SIZE; |
| 906 | int y = TileY(tile) * TILE_SIZE; |
| 907 | |
| 908 | /* Helicopter raise */ |
| 909 | if (amd.flags.Test(AirportMovingDataFlag::HeliRaise)) { |
| 910 | Aircraft *u = v->Next()->Next(); |
| 911 | |
| 912 | /* Make sure the rotors don't rotate too fast */ |
| 913 | if (u->cur_speed > 32) { |
| 914 | v->cur_speed = 0; |
| 915 | if (--u->cur_speed == 32) { |
| 916 | if (!PlayVehicleSound(v, VSE_START)) { |
| 917 | SoundID sfx = AircraftVehInfo(v->engine_type)->sfx; |
| 918 | /* For compatibility with old NewGRF we ignore the sfx property, unless a NewGRF-defined sound is used. |
| 919 | * The baseset has only one helicopter sound, so this only limits using plane or cow sounds. */ |
| 920 | if (sfx < ORIGINAL_SAMPLE_COUNT) sfx = SND_18_TAKEOFF_HELICOPTER; |
| 921 | SndPlayVehicleFx(sfx, v); |
| 922 | } |
no test coverage detected