diff --git a/src/ai/default/default.cpp b/src/ai/default/default.cpp index 7316b56487..ed805fb436 100644 --- a/src/ai/default/default.cpp +++ b/src/ai/default/default.cpp @@ -95,7 +95,7 @@ static void AiStateVehLoop(Player *p) if ((v->type == VEH_Train && v->subtype == 0) || v->type == VEH_Road || - (v->type == VEH_Aircraft && v->subtype <= 2) || + (v->type == VEH_Aircraft && IsNormalAircraft(v)) || v->type == VEH_Ship) { /* replace engine? */ if (v->type == VEH_Train && v->engine_type < 3 && diff --git a/src/aircraft.h b/src/aircraft.h index 4b92d38e31..9a2875f1f0 100644 --- a/src/aircraft.h +++ b/src/aircraft.h @@ -6,6 +6,28 @@ #include "station_map.h" #include "vehicle.h" +typedef enum AircraftSubTypes { + AIR_HELICOPTER = 0, + AIR_AIRCRAFT = 2, + AIR_SHADOW = 4, + AIR_ROTOR = 6 +} AircraftSubType; + + +/** Check if the aircraft type is a normal flying device; eg + * not a rotor or a shadow + * @param v vehicle to check + * @return Returns true if the aircraft is a helicopter/airplane and + * false if it is a shadow or a rotor) */ +static inline bool IsNormalAircraft(const Vehicle *v) +{ + assert(v->type == VEH_Aircraft); + /* To be fully correct the commented out functionality is the proper one, + * but since value can only be 0 or 2, it is sufficient to only check <= 2 + * return (v->subtype == AIR_HELICOPTER) || (v->subtype == AIR_AIRCRAFT); */ + return v->subtype <= AIR_AIRCRAFT; +} + static inline bool IsAircraftInHangar(const Vehicle* v) { diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index 9263c937cb..35902a2e60 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -17,6 +17,7 @@ #include "news.h" #include "sound.h" #include "player.h" +#include "aircraft.h" #include "airport.h" #include "vehicle_gui.h" #include "table/sprites.h" @@ -129,7 +130,7 @@ SpriteID GetRotorImage(const Vehicle *v) { const Vehicle *w; - assert((v->subtype & 1) == 0); + assert(v->subtype == AIR_HELICOPTER); w = v->next->next; if (is_custom_sprite(v->spritenum)) { @@ -206,11 +207,10 @@ uint16 AircraftDefaultCargoCapacity(CargoID cid, EngineID engine_type) int32 CmdBuildAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) { int32 value; - Vehicle *vl[3], *v, *u, *w; + Vehicle *vl[3]; UnitID unit_num; const AircraftVehicleInfo *avi; const AirportFTAClass* ap; - Engine *e; if (!IsEngineBuildable(p1, VEH_Aircraft, _current_player)) return_cmd_error(STR_ENGINE_NOT_BUILDABLE); @@ -231,7 +231,8 @@ int32 CmdBuildAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) return CMD_ERROR; } - // allocate 2 or 3 vehicle structs, depending on type + /* Allocate 2 or 3 vehicle structs, depending on type + * vl[0] = aircraft, vl[1] = shadow, [vl[2] = rotor] */ if (!AllocateVehicles(vl, avi->subtype & AIR_CTOL ? 2 : 3) || IsOrderPoolFull()) { return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); @@ -246,8 +247,8 @@ int32 CmdBuildAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) uint x; uint y; - v = vl[0]; - u = vl[1]; + Vehicle *v = vl[0]; // aircraft + Vehicle *u = vl[1]; // shadow v->unitnumber = unit_num; v->type = u->type = VEH_Aircraft; @@ -302,10 +303,10 @@ int32 CmdBuildAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) v->acceleration = avi->acceleration; v->engine_type = p1; - v->subtype = (avi->subtype & AIR_CTOL ? 2 : 0); + v->subtype = (avi->subtype & AIR_CTOL ? AIR_AIRCRAFT : AIR_HELICOPTER); v->value = value; - u->subtype = 4; + u->subtype = AIR_SHADOW; /* Danger, Will Robinson! * If the aircraft is refittable, but cannot be refitted to @@ -333,7 +334,7 @@ int32 CmdBuildAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) u->cargo_cap = 0; } - e = GetEngine(p1); + const Engine *e = GetEngine(p1); v->reliability = e->reliability; v->reliability_spd_dec = e->reliability_spd_dec; v->max_age = e->lifelength * 366; @@ -381,8 +382,8 @@ int32 CmdBuildAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) VehiclePositionChanged(u); // Aircraft with 3 vehicles (chopper)? - if (v->subtype == 0) { - w = vl[2]; + if (v->subtype == AIR_HELICOPTER) { + Vehicle *w = vl[2]; u->next = w; @@ -397,7 +398,7 @@ int32 CmdBuildAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) w->z_height = 1; w->vehstatus = VS_HIDDEN | VS_UNCLICKABLE; w->spritenum = 0xFF; - w->subtype = 6; + w->subtype = AIR_ROTOR; w->cur_image = SPR_ROTOR_STOPPED; w->random_bits = VehicleRandomBits(); /* Use rotor's air.state to store the rotor animation frame */ @@ -700,7 +701,7 @@ void OnNewDay_Aircraft(Vehicle *v) { int32 cost; - if (v->subtype > 2) return; + if (!IsNormalAircraft(v)) return; if ((++v->day_counter & 7) == 0) DecreaseVehicleValue(v); @@ -728,7 +729,7 @@ void AircraftYearlyLoop(void) Vehicle *v; FOR_ALL_VEHICLES(v) { - if (v->type == VEH_Aircraft && v->subtype <= 2) { + if (v->type == VEH_Aircraft && IsNormalAircraft(v)) { v->profit_last_year = v->profit_this_year; v->profit_this_year = 0; InvalidateWindow(WC_VEHICLE_DETAILS, v->index); @@ -807,7 +808,7 @@ static void SetAircraftPosition(Vehicle *v, int x, int y, int z) v->z_pos = z; v->cur_image = GetAircraftImage(v, v->direction); - if (v->subtype == 0) v->next->next->cur_image = GetRotorImage(v); + if (v->subtype == AIR_HELICOPTER) v->next->next->cur_image = GetRotorImage(v); BeginVehicleMove(v); VehiclePositionChanged(v); @@ -1250,9 +1251,7 @@ static void ProcessAircraftOrder(Vehicle *v) static void MarkAircraftDirty(Vehicle *v) { v->cur_image = GetAircraftImage(v, v->direction); - if (v->subtype == 0) { - v->next->next->cur_image = GetRotorImage(v); - } + if (v->subtype == AIR_HELICOPTER) v->next->next->cur_image = GetRotorImage(v); MarkAllViewportsDirty(v->left_coord, v->top_coord, v->right_coord + 1, v->bottom_coord + 1); } @@ -1488,14 +1487,14 @@ static void AircraftEventHandler_InHangar(Vehicle *v, const AirportFTAClass *apc if (v->current_order.dest == v->u.air.targetairport) { // FindFreeTerminal: // 1. Find a free terminal, 2. Occupy it, 3. Set the vehicle's state to that terminal - if (v->subtype != 0) { - if (!AirportFindFreeTerminal(v, apc)) return; // airplane - } else { + if (v->subtype == AIR_HELICOPTER) { if (!AirportFindFreeHelipad(v, apc)) return; // helicopter + } else { + if (!AirportFindFreeTerminal(v, apc)) return; // airplane } } else { // Else prepare for launch. // airplane goto state takeoff, helicopter to helitakeoff - v->u.air.state = (v->subtype != 0) ? TAKEOFF : HELITAKEOFF; + v->u.air.state = (v->subtype == AIR_HELICOPTER) ? HELITAKEOFF : TAKEOFF; } AircraftLeaveHangar(v); AirportMove(v, apc); @@ -1510,7 +1509,7 @@ static void AircraftEventHandler_AtTerminal(Vehicle *v, const AirportFTAClass *a // on an airport with helipads, a helicopter will always land there // and get serviced at the same time - patch setting if (_patches.serviceathelipad) { - if (v->subtype == 0 && apc->helipads != NULL) { + if (v->subtype == AIR_HELICOPTER && apc->helipads != NULL) { // an exerpt of ServiceAircraft, without the invisibility stuff v->date_of_last_service = _date; v->breakdowns_since_last_service = 0; @@ -1532,13 +1531,13 @@ static void AircraftEventHandler_AtTerminal(Vehicle *v, const AirportFTAClass *a switch (v->current_order.type) { case OT_GOTO_STATION: // ready to fly to another airport // airplane goto state takeoff, helicopter to helitakeoff - v->u.air.state = (v->subtype != 0) ? TAKEOFF : HELITAKEOFF; + v->u.air.state = (v->subtype == AIR_HELICOPTER) ? HELITAKEOFF : TAKEOFF; break; case OT_GOTO_DEPOT: // visit hangar for serivicing, sale, etc. if (v->current_order.dest == v->u.air.targetairport) { v->u.air.state = HANGAR; } else { - v->u.air.state = (v->subtype != 0) ? TAKEOFF : HELITAKEOFF; + v->u.air.state = (v->subtype == AIR_HELICOPTER) ? HELITAKEOFF : TAKEOFF; } break; default: // orders have been deleted (no orders), goto depot and don't bother us @@ -1612,7 +1611,7 @@ static void AircraftEventHandler_Flying(Vehicle *v, const AirportFTAClass *apc) // {32,FLYING,NOTHING_block,37}, {32,LANDING,N,33}, {32,HELILANDING,N,41}, // if it is an airplane, look for LANDING, for helicopter HELILANDING // it is possible to choose from multiple landing runways, so loop until a free one is found - landingtype = (v->subtype != 0) ? LANDING : HELILANDING; + landingtype = (v->subtype == AIR_HELICOPTER) ? HELILANDING : LANDING; current = apc->layout[v->u.air.pos].next; while (current != NULL) { if (current->heading == landingtype) { @@ -2024,9 +2023,9 @@ void Aircraft_Tick(Vehicle *v) { int i; - if (v->subtype > 2) return; + if (!IsNormalAircraft(v)) return; - if (v->subtype == 0) HelicopterTickHandler(v); + if (v->subtype == AIR_HELICOPTER) HelicopterTickHandler(v); AgeAircraftCargo(v); @@ -2063,7 +2062,7 @@ void UpdateOldAircraft(void) FOR_ALL_VEHICLES(v_oldstyle) { // airplane has another vehicle with subtype 4 (shadow), helicopter also has 3 (rotor) // skip those - if (v_oldstyle->type == VEH_Aircraft && v_oldstyle->subtype <= 2) { + if (v_oldstyle->type == VEH_Aircraft && IsNormalAircraft(v_oldstyle)) { // airplane in terminal stopped doesn't hurt anyone, so goto next if (v_oldstyle->vehstatus & VS_STOPPED && v_oldstyle->u.air.state == 0) { v_oldstyle->u.air.state = HANGAR; @@ -2078,7 +2077,7 @@ void UpdateOldAircraft(void) v_oldstyle->tile = 0; // aircraft in air is tile=0 // correct speed of helicopter-rotors - if (v_oldstyle->subtype == 0) v_oldstyle->next->next->cur_speed = 32; + if (v_oldstyle->subtype == AIR_HELICOPTER) v_oldstyle->next->next->cur_speed = 32; // set new position x,y,z SetAircraftPosition(v_oldstyle, gp.x, gp.y, GetAircraftFlyingAltitude(v_oldstyle)); @@ -2095,7 +2094,7 @@ void UpdateAirplanesOnNewStation(Station *st) // only 1 station is updated per function call, so it is enough to get entry_point once const AirportFTAClass *ap = GetAirport(st->airport_type); FOR_ALL_VEHICLES(v) { - if (v->type == VEH_Aircraft && v->subtype <= 2) { + if (v->type == VEH_Aircraft && IsNormalAircraft(v)) { if (v->u.air.targetairport == st->index) { // if heading to this airport /* update position of airplane. If plane is not flying, landing, or taking off *you cannot delete airport, so it doesn't matter @@ -2110,7 +2109,7 @@ void UpdateAirplanesOnNewStation(Station *st) SetAircraftPosition(v, gp.x, gp.y, GetAircraftFlyingAltitude(v)); } else { assert(v->u.air.state == ENDTAKEOFF || v->u.air.state == HELITAKEOFF); - takeofftype = (v->subtype == 0) ? HELITAKEOFF : ENDTAKEOFF; + takeofftype = (v->subtype == AIR_HELICOPTER) ? HELITAKEOFF : ENDTAKEOFF; // search in airportdata for that heading // easiest to do, since this doesn't happen a lot for (cnt = 0; cnt < ap->nofelements; cnt++) { diff --git a/src/aircraft_gui.cpp b/src/aircraft_gui.cpp index b5b2f95e33..ef641ca7cd 100644 --- a/src/aircraft_gui.cpp +++ b/src/aircraft_gui.cpp @@ -24,7 +24,7 @@ void DrawAircraftImage(const Vehicle *v, int x, int y, VehicleID selection) { SpriteID pal = (v->vehstatus & VS_CRASHED) ? PALETTE_CRASH : GetVehiclePalette(v); DrawSprite(GetAircraftImage(v, DIR_W), pal, x + 25, y + 10); - if (v->subtype == 0) { + if (v->subtype == AIR_HELICOPTER) { SpriteID rotor_sprite = GetCustomRotorSprite(v, true); if (rotor_sprite == 0) rotor_sprite = SPR_ROTOR_STOPPED; DrawSprite(rotor_sprite, PAL_NONE, x + 25, y + 5); @@ -114,7 +114,7 @@ static void AircraftDetailsWndProc(Window *w, WindowEvent *e) int y = 57; do { - if (v->subtype <= 2) { + if (IsNormalAircraft(v)) { SetDParam(0, GetCustomEngineName(v->engine_type)); SetDParam(1, v->build_year); SetDParam(2, v->value); diff --git a/src/economy.cpp b/src/economy.cpp index a1a63ee1e1..b422b8a534 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -27,6 +27,7 @@ #include "vehicle_gui.h" #include "ai/ai.h" #include "train.h" +#include "aircraft.h" #include "newgrf_engine.h" #include "newgrf_sound.h" #include "newgrf_callbacks.h" @@ -76,7 +77,7 @@ int64 CalculateCompanyValue(const Player* p) if (v->type == VEH_Train || v->type == VEH_Road || - (v->type == VEH_Aircraft && v->subtype<=2) || + (v->type == VEH_Aircraft && IsNormalAircraft(v)) || v->type == VEH_Ship) { value += v->value * 3 >> 1; } @@ -108,7 +109,7 @@ int UpdateCompanyRatingAndValue(Player *p, bool update) if (v->owner != owner) continue; if ((v->type == VEH_Train && IsFrontEngine(v)) || v->type == VEH_Road || - (v->type == VEH_Aircraft && v->subtype <= 2) || + (v->type == VEH_Aircraft && IsNormalAircraft(v)) || v->type == VEH_Ship) { num++; if (v->age > 730) { @@ -299,7 +300,7 @@ void ChangeOwnershipOfPlayerItems(PlayerID old_player, PlayerID new_player) case VEH_Train: if (IsFrontEngine(v)) num_train++; break; case VEH_Road: num_road++; break; case VEH_Ship: num_ship++; break; - case VEH_Aircraft: if (v->subtype <= 2) num_aircraft++; break; + case VEH_Aircraft: if (IsNormalAircraft(v)) num_aircraft++; break; default: break; } } @@ -319,7 +320,7 @@ void ChangeOwnershipOfPlayerItems(PlayerID old_player, PlayerID new_player) case VEH_Train: if (IsFrontEngine(v)) v->unitnumber = ++num_train; break; case VEH_Road: v->unitnumber = ++num_road; break; case VEH_Ship: v->unitnumber = ++num_ship; break; - case VEH_Aircraft: if (v->subtype <= 2) v->unitnumber = ++num_aircraft; break; + case VEH_Aircraft: if (IsNormalAircraft(v)) v->unitnumber = ++num_aircraft; break; } } } diff --git a/src/engine.cpp b/src/engine.cpp index 10a35b9a03..ec4c27ec26 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -14,6 +14,7 @@ #include "saveload.h" #include "variables.h" #include "train.h" +#include "aircraft.h" #include "newgrf_cargo.h" #include "date.h" #include "table/engines.h" @@ -306,7 +307,7 @@ static void NewVehicleAvailable(Engine *e) FOR_ALL_VEHICLES(v) { if (v->type == VEH_Train || v->type == VEH_Road || v->type == VEH_Ship || - (v->type == VEH_Aircraft && v->subtype <= 2)) { + (v->type == VEH_Aircraft && IsNormalAircraft(v))) { if (v->owner == p->index && v->engine_type == index) { /* The user did prove me wrong, so restore old value */ p->block_preview = block_preview; diff --git a/src/engine.h b/src/engine.h index 05ffb33a72..3b70256a28 100644 --- a/src/engine.h +++ b/src/engine.h @@ -45,7 +45,7 @@ typedef struct ShipVehicleInfo { bool refittable; } ShipVehicleInfo; -// Aircraft subtypes +/* AircraftVehicleInfo subtypes */ enum { AIR_CTOL = 1, // Conventional Take Off and Landing, i.e. planes AIR_FAST = 2 diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 612a9edef1..f69340afd5 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -10,6 +10,7 @@ #include "network_data.h" #include "core/tcp.h" #include "../train.h" +#include "../aircraft.h" #include "../date.h" #include "table/strings.h" #include "../functions.h" @@ -1255,7 +1256,7 @@ void NetworkPopulateCompanyInfo(void) break; case VEH_Aircraft: - if (v->subtype <= 2) _network_player_info[v->owner].num_vehicle[3]++; + if (IsNormalAircraft(v)) _network_player_info[v->owner].num_vehicle[3]++; break; case VEH_Ship: diff --git a/src/player_gui.cpp b/src/player_gui.cpp index e51a6d4f9e..94367e1ad5 100644 --- a/src/player_gui.cpp +++ b/src/player_gui.cpp @@ -16,6 +16,7 @@ #include "network/network.h" #include "variables.h" #include "train.h" +#include "aircraft.h" #include "date.h" #include "newgrf.h" #include "network/network_data.h" @@ -607,7 +608,7 @@ static void DrawPlayerVehiclesAmount(PlayerID player) switch (v->type) { case VEH_Train: if (IsFrontEngine(v)) train++; break; case VEH_Road: road++; break; - case VEH_Aircraft: if (v->subtype <= 2) air++; break; + case VEH_Aircraft: if (IsNormalAircraft(v)) air++; break; case VEH_Ship: ship++; break; default: break; } diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 41be1ea759..b28852d967 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -232,7 +232,7 @@ void AfterLoadVehicles(void) case VEH_Road: v->cur_image = GetRoadVehImage(v, v->direction); break; case VEH_Ship: v->cur_image = GetShipImage(v, v->direction); break; case VEH_Aircraft: - if (v->subtype == 0 || v->subtype == 2) { + if (IsNormalAircraft(v)) { v->cur_image = GetAircraftImage(v, v->direction); if (v->next != NULL) v->next->cur_image = v->cur_image; } @@ -537,7 +537,7 @@ uint CountVehiclesInChain(const Vehicle* v) bool IsEngineCountable(const Vehicle *v) { switch (v->type) { - case VEH_Aircraft: return (v->subtype <= 2); // don't count plane shadows and helicopter rotors + case VEH_Aircraft: return IsNormalAircraft(v); // don't count plane shadows and helicopter rotors case VEH_Train: return !IsArticulatedPart(v) && // tenders and other articulated parts (!IsMultiheaded(v) || IsTrainEngine(v)); // rear parts of multiheaded engines @@ -651,7 +651,7 @@ void CallVehicleTicks(void) case VEH_Aircraft: case VEH_Ship: if (v->type == VEH_Train && IsTrainWagon(v)) continue; - if (v->type == VEH_Aircraft && v->subtype > 0) continue; + if (v->type == VEH_Aircraft && v->subtype != AIR_HELICOPTER) continue; v->motion_counter += (v->direction & 1) ? (v->cur_speed * 3) / 4 : v->cur_speed; /* Play a running sound if the motion counter passes 256 (Do we not skip sounds?) */ @@ -2334,8 +2334,7 @@ void BuildDepotVehicleList(byte type, TileIndex tile, Vehicle ***engine_list, ui case VEH_Aircraft: FOR_ALL_VEHICLES(v) { if (v->tile == tile && - v->type == VEH_Aircraft && - v->subtype <= 2 && + v->type == VEH_Aircraft && IsNormalAircraft(v) && v->vehstatus & VS_HIDDEN) { if (*engine_count == *engine_list_length) ExtendVehicleListSize((const Vehicle***)engine_list, engine_list_length, 25); (*engine_list)[(*engine_count)++] = v; @@ -2362,7 +2361,7 @@ void BuildDepotVehicleList(byte type, TileIndex tile, Vehicle ***engine_list, ui */ uint GenerateVehicleSortList(const Vehicle ***sort_list, uint16 *length_of_array, byte type, PlayerID owner, uint32 index, uint16 window_type) { - const uint subtype = (type != VEH_Aircraft) ? Train_Front : 2; + const byte subtype = (type != VEH_Aircraft) ? (byte)Train_Front : (byte)AIR_AIRCRAFT; uint n = 0; const Vehicle *v; diff --git a/src/vehicle.h b/src/vehicle.h index dc994b8326..2b7773ceda 100644 --- a/src/vehicle.h +++ b/src/vehicle.h @@ -144,7 +144,7 @@ typedef struct VehicleShip { struct Vehicle { byte type; // type, ie roadven,train,ship,aircraft,special - byte subtype; // subtype (Filled with values from EffectVehicles or TrainSubTypes) + byte subtype; // subtype (Filled with values from EffectVehicles/TrainSubTypes/AircraftSubTypes) VehicleID index; // NOSAVE: Index in vehicle array