diff --git a/aircraft_cmd.c b/aircraft_cmd.c index 7263f51d35..2ef5b0c6f4 100644 --- a/aircraft_cmd.c +++ b/aircraft_cmd.c @@ -21,6 +21,7 @@ #include "vehicle_gui.h" #include "table/sprites.h" #include "newgrf_engine.h" +#include "newgrf_callbacks.h" static bool AirportMove(Vehicle *v, const AirportFTAClass *Airport); static bool AirportSetBlocks(Vehicle *v, AirportFTA *current_pos, const AirportFTAClass *Airport); @@ -156,6 +157,34 @@ static int32 EstimateAircraftCost(EngineID engine_type) } +/** + * Calculates cargo capacity based on an aircraft's passenger + * and mail capacities. + * @param cid Which cargo type to calculate a capacity for. + * @param engine Which engine to find a cargo capacity for. + * @return New cargo capacity value. + */ +static uint16 AircraftDefaultCargoCapacity(CargoID cid, EngineID engine_type) +{ + const AircraftVehicleInfo *avi = AircraftVehInfo(engine_type); + + assert(cid != CT_INVALID); + + /* An aircraft can carry twice as much goods as normal cargo, + * and four times as many passengers. */ + switch (cid) { + case CT_PASSENGERS: + return avi->passenger_capacity; + case CT_MAIL: + return avi->passenger_capacity + avi->mail_capacity; + case CT_GOODS: + return (avi->passenger_capacity + avi->mail_capacity) / 2; + default: + return (avi->passenger_capacity + avi->mail_capacity) / 4; + } +} + + /** Build an aircraft. * @param tile tile of depot where aircraft is built * @param p1 aircraft type being built (engine) @@ -192,6 +221,7 @@ int32 CmdBuildAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME); if (flags & DC_EXEC) { + CargoID cargo; uint x; uint y; @@ -256,6 +286,32 @@ int32 CmdBuildAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2) u->subtype = 4; + /* Danger, Will Robinson! + * If the aircraft is refittable, but cannot be refitted to + * passengers, we select the cargo type from the refit mask. + * This is a fairly nasty hack to get around the fact that TTD + * has no default cargo type specifier for planes... */ + cargo = FindFirstRefittableCargo(p1); + if (cargo != CT_INVALID && cargo != CT_PASSENGERS) { + uint16 callback = CALLBACK_FAILED; + + v->cargo_type = cargo; + + if (HASBIT(EngInfo(p1)->callbackmask, CBM_REFIT_CAPACITY)) { + callback = GetVehicleCallback(CBID_VEHICLE_REFIT_CAPACITY, 0, 0, v->engine_type, v); + } + + if (callback == CALLBACK_FAILED) { + /* Callback failed, or not executed; use the default cargo capacity */ + v->cargo_cap = AircraftDefaultCargoCapacity(v->cargo_type, v->engine_type); + } else { + v->cargo_cap = callback; + } + + /* Set the 'second compartent' capacity to none */ + u->cargo_cap = 0; + } + e = GetEngine(p1); v->reliability = e->reliability; v->reliability_spd_dec = e->reliability_spd_dec; diff --git a/vehicle.c b/vehicle.c index 9f9279cec2..b7b5212481 100644 --- a/vehicle.c +++ b/vehicle.c @@ -692,6 +692,25 @@ bool CanRefitTo(EngineID engine_type, CargoID cid_to) return HASBIT(EngInfo(engine_type)->refit_mask, cid); } +/** Find the first cargo type that an engine can be refitted to. + * @param engine Which engine to find cargo for. + * @return A climate dependent cargo type. CT_INVALID is returned if not refittable. + */ +CargoID FindFirstRefittableCargo(EngineID engine_type) +{ + CargoID cid; + uint32 refit_mask = EngInfo(engine_type)->refit_mask; + + if (refit_mask != 0) { + for (cid = CT_PASSENGERS; cid < NUM_CARGO; cid++) { + if (HASBIT(refit_mask, _global_cargo_id[_opt_ptr->landscape][cid])) return cid; + } + } + + return CT_INVALID; +} + + static void DoDrawVehicle(const Vehicle *v) { uint32 image = v->cur_image; diff --git a/vehicle.h b/vehicle.h index d74a17eb08..487ad77971 100644 --- a/vehicle.h +++ b/vehicle.h @@ -267,6 +267,7 @@ byte VehicleRandomBits(void); bool CanFillVehicle(Vehicle *v); bool CanRefitTo(EngineID engine_type, CargoID cid_to); +CargoID FindFirstRefittableCargo(EngineID engine_type); void ViewportAddVehicles(DrawPixelInfo *dpi);