|
@@ -218,25 +218,25 @@ void GetAircraftSpriteSize(EngineID engi
|
|
|
if (sprite == 0) {
|
|
|
spritenum = orig_aircraft_vehicle_info[engine - AIRCRAFT_ENGINES_INDEX].image_index;
|
|
|
sprite = (6 + _aircraft_sprite[spritenum]);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
const Sprite *spr = GetSprite(sprite);
|
|
|
|
|
|
width = spr->width ;
|
|
|
height = spr->height;
|
|
|
}
|
|
|
|
|
|
static int32 EstimateAircraftCost(EngineID engine, const AircraftVehicleInfo *avi)
|
|
|
static CommandCost EstimateAircraftCost(EngineID engine, const AircraftVehicleInfo *avi)
|
|
|
{
|
|
|
return GetEngineProperty(engine, 0x0B, avi->base_cost) * (_price.aircraft_base >> 3) >> 5;
|
|
|
}
|
|
|
|
|
|
|
|
|
/**
|
|
|
* Calculates cargo capacity based on an aircraft's passenger
|
|
|
* and mail capacities.
|
|
|
* @param cid Which cargo type to calculate a capacity for.
|
|
|
* @param avi Which engine to find a cargo capacity for.
|
|
|
* @return New cargo capacity value.
|
|
|
*/
|
|
@@ -256,30 +256,30 @@ uint16 AircraftDefaultCargoCapacity(Carg
|
|
|
default:
|
|
|
return (avi->passenger_capacity + avi->mail_capacity) / 4;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/** Build an aircraft.
|
|
|
* @param tile tile of depot where aircraft is built
|
|
|
* @param flags for command
|
|
|
* @param p1 aircraft type being built (engine)
|
|
|
* @param p2 bit 0 when set, the unitnumber will be 0, otherwise it will be a free number
|
|
|
* return result of operation. Could be cost, error
|
|
|
*/
|
|
|
int32 CmdBuildAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
|
|
CommandCost CmdBuildAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
|
|
{
|
|
|
if (!IsEngineBuildable(p1, VEH_AIRCRAFT, _current_player)) return_cmd_error(STR_AIRCRAFT_NOT_AVAILABLE);
|
|
|
|
|
|
const AircraftVehicleInfo *avi = AircraftVehInfo(p1);
|
|
|
int32 value = EstimateAircraftCost(p1, avi);
|
|
|
CommandCost value = EstimateAircraftCost(p1, avi);
|
|
|
|
|
|
/* to just query the cost, it is not neccessary to have a valid tile (automation/AI) */
|
|
|
if (flags & DC_QUERY_COST) return value;
|
|
|
|
|
|
if (!IsHangarTile(tile) || !IsTileOwner(tile, _current_player)) return CMD_ERROR;
|
|
|
|
|
|
SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
|
|
|
|
|
|
/* Prevent building aircraft types at places which can't handle them */
|
|
|
if (!IsAircraftBuildableAtStation(p1, tile)) return CMD_ERROR;
|
|
|
|
|
|
/* Allocate 2 or 3 vehicle structs, depending on type
|
|
@@ -467,25 +467,25 @@ static void DoDeleteAircraft(Vehicle *v)
|
|
|
DeleteDepotHighlightOfVehicle(v);
|
|
|
DeleteVehicleChain(v);
|
|
|
InvalidateWindowClasses(WC_AIRCRAFT_LIST);
|
|
|
}
|
|
|
|
|
|
/** Sell an aircraft.
|
|
|
* @param tile unused
|
|
|
* @param flags for command type
|
|
|
* @param p1 vehicle ID to be sold
|
|
|
* @param p2 unused
|
|
|
* @return result of operation. Error or sold value
|
|
|
*/
|
|
|
int32 CmdSellAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
|
|
CommandCost CmdSellAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
|
|
{
|
|
|
if (!IsValidVehicleID(p1)) return CMD_ERROR;
|
|
|
|
|
|
Vehicle *v = GetVehicle(p1);
|
|
|
|
|
|
if (v->type != VEH_AIRCRAFT || !CheckOwnership(v->owner)) return CMD_ERROR;
|
|
|
if (!IsAircraftInHangarStopped(v)) return_cmd_error(STR_A01B_AIRCRAFT_MUST_BE_STOPPED);
|
|
|
|
|
|
SET_EXPENSES_TYPE(EXPENSES_NEW_VEHICLES);
|
|
|
|
|
|
if (flags & DC_EXEC) {
|
|
|
// Invalidate depot
|
|
@@ -494,25 +494,25 @@ int32 CmdSellAircraft(TileIndex tile, ui
|
|
|
}
|
|
|
|
|
|
return -(int32)v->value;
|
|
|
}
|
|
|
|
|
|
/** Start/Stop an aircraft.
|
|
|
* @param tile unused
|
|
|
* @param flags for command type
|
|
|
* @param p1 aircraft ID to start/stop
|
|
|
* @param p2 unused
|
|
|
* @return result of operation. Nothing if everything went well
|
|
|
*/
|
|
|
int32 CmdStartStopAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
|
|
CommandCost CmdStartStopAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
|
|
{
|
|
|
if (!IsValidVehicleID(p1)) return CMD_ERROR;
|
|
|
|
|
|
Vehicle *v = GetVehicle(p1);
|
|
|
|
|
|
if (v->type != VEH_AIRCRAFT || !CheckOwnership(v->owner)) return CMD_ERROR;
|
|
|
|
|
|
/* cannot stop airplane when in flight, or when taking off / landing */
|
|
|
if (v->u.air.state >= STARTTAKEOFF && v->u.air.state < TERM7)
|
|
|
return_cmd_error(STR_A017_AIRCRAFT_IS_IN_FLIGHT);
|
|
|
|
|
|
/* Check if this aircraft can be started/stopped. The callback will fail or
|
|
@@ -537,25 +537,25 @@ int32 CmdStartStopAircraft(TileIndex til
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
/** Send an aircraft to the hangar.
|
|
|
* @param tile unused
|
|
|
* @param flags for command type
|
|
|
* @param p1 vehicle ID to send to the hangar
|
|
|
* @param p2 various bitmasked elements
|
|
|
* - p2 bit 0-3 - DEPOT_ flags (see vehicle.h)
|
|
|
* - p2 bit 8-10 - VLW flag (for mass goto depot)
|
|
|
* @return o if everything went well
|
|
|
*/
|
|
|
int32 CmdSendAircraftToHangar(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
|
|
CommandCost CmdSendAircraftToHangar(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
|
|
{
|
|
|
if (p2 & DEPOT_MASS_SEND) {
|
|
|
/* Mass goto depot requested */
|
|
|
if (!ValidVLWFlags(p2 & VLW_MASK)) return CMD_ERROR;
|
|
|
return SendAllVehiclesToDepot(VEH_AIRCRAFT, flags, p2 & DEPOT_SERVICE, _current_player, (p2 & VLW_MASK), p1);
|
|
|
}
|
|
|
|
|
|
if (!IsValidVehicleID(p1)) return CMD_ERROR;
|
|
|
|
|
|
Vehicle *v = GetVehicle(p1);
|
|
|
|
|
|
if (v->type != VEH_AIRCRAFT || !CheckOwnership(v->owner) || IsAircraftInHangar(v)) return CMD_ERROR;
|
|
@@ -614,25 +614,25 @@ int32 CmdSendAircraftToHangar(TileIndex
|
|
|
|
|
|
|
|
|
/** Refits an aircraft to the specified cargo type.
|
|
|
* @param tile unused
|
|
|
* @param flags for command type
|
|
|
* @param p1 vehicle ID of the aircraft to refit
|
|
|
* @param p2 various bitstuffed elements
|
|
|
* - p2 = (bit 0-7) - the new cargo type to refit to
|
|
|
* - p2 = (bit 8-15) - the new cargo subtype to refit to
|
|
|
* - p2 = (bit 16) - refit only this vehicle (ignored)
|
|
|
* @return cost of refit or error
|
|
|
*/
|
|
|
int32 CmdRefitAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
|
|
CommandCost CmdRefitAircraft(TileIndex tile, uint32 flags, uint32 p1, uint32 p2)
|
|
|
{
|
|
|
byte new_subtype = GB(p2, 8, 8);
|
|
|
|
|
|
if (!IsValidVehicleID(p1)) return CMD_ERROR;
|
|
|
|
|
|
Vehicle *v = GetVehicle(p1);
|
|
|
|
|
|
if (v->type != VEH_AIRCRAFT || !CheckOwnership(v->owner)) return CMD_ERROR;
|
|
|
if (!IsAircraftInHangarStopped(v)) return_cmd_error(STR_A01B_AIRCRAFT_MUST_BE_STOPPED);
|
|
|
|
|
|
/* Check cargo */
|
|
|
CargoID new_cid = GB(p2, 0, 8);
|
|
@@ -659,25 +659,25 @@ int32 CmdRefitAircraft(TileIndex tile, u
|
|
|
const AircraftVehicleInfo *avi = AircraftVehInfo(v->engine_type);
|
|
|
|
|
|
uint pass;
|
|
|
if (callback == CALLBACK_FAILED) {
|
|
|
/* If the callback failed, or wasn't executed, use the aircraft's
|
|
|
* default cargo capacity */
|
|
|
pass = AircraftDefaultCargoCapacity(new_cid, avi);
|
|
|
} else {
|
|
|
pass = callback;
|
|
|
}
|
|
|
_returned_refit_capacity = pass;
|
|
|
|
|
|
int32 cost = 0;
|
|
|
CommandCost cost = 0;
|
|
|
if (IsHumanPlayer(v->owner) && new_cid != v->cargo_type) {
|
|
|
cost = GetRefitCost(v->engine_type);
|
|
|
}
|
|
|
|
|
|
if (flags & DC_EXEC) {
|
|
|
v->cargo_cap = pass;
|
|
|
|
|
|
Vehicle *u = v->next;
|
|
|
uint mail = IsCargoInClass(new_cid, CC_PASSENGERS) ? avi->mail_capacity : 0;
|
|
|
u->cargo_cap = mail;
|
|
|
if (v->cargo_type == new_cid) {
|
|
|
v->cargo_count = min(pass, v->cargo_count);
|
|
@@ -735,25 +735,25 @@ void OnNewDay_Aircraft(Vehicle *v)
|
|
|
if (!IsNormalAircraft(v)) return;
|
|
|
|
|
|
if ((++v->day_counter & 7) == 0) DecreaseVehicleValue(v);
|
|
|
|
|
|
CheckOrders(v);
|
|
|
|
|
|
CheckVehicleBreakdown(v);
|
|
|
AgeVehicle(v);
|
|
|
CheckIfAircraftNeedsService(v);
|
|
|
|
|
|
if (v->vehstatus & VS_STOPPED) return;
|
|
|
|
|
|
int32 cost = GetVehicleProperty(v, 0x0E, AircraftVehInfo(v->engine_type)->running_cost) * _price.aircraft_running / 364;
|
|
|
CommandCost cost = GetVehicleProperty(v, 0x0E, AircraftVehInfo(v->engine_type)->running_cost) * _price.aircraft_running / 364;
|
|
|
|
|
|
v->profit_this_year -= cost >> 8;
|
|
|
|
|
|
SET_EXPENSES_TYPE(EXPENSES_AIRCRAFT_RUN);
|
|
|
SubtractMoneyFromPlayerFract(v->owner, cost);
|
|
|
|
|
|
InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
|
|
|
InvalidateWindowClasses(WC_AIRCRAFT_LIST);
|
|
|
}
|
|
|
|
|
|
void AircraftYearlyLoop()
|
|
|
{
|
|
@@ -1370,25 +1370,25 @@ static void ProcessAircraftOrder(Vehicle
|
|
|
* the holding pattern for the first airport, which can cause
|
|
|
* the plane to go into an undefined state when building an
|
|
|
* airport with the same StationID.
|
|
|
* 2) we are (still) heading to a (still) valid airport, then we
|
|
|
* can continue going there. This can happen when you are
|
|
|
* changing the aircraft's orders while in-flight or in for
|
|
|
* example a depot. However, when we have a current order to
|
|
|
* go to a depot, we have to keep that order so the aircraft
|
|
|
* actually stops.
|
|
|
*/
|
|
|
const Station *st = GetStation(v->u.air.targetairport);
|
|
|
if (!st->IsValid() || st->airport_tile == 0) {
|
|
|
int32 ret;
|
|
|
CommandCost ret;
|
|
|
PlayerID old_player = _current_player;
|
|
|
|
|
|
_current_player = v->owner;
|
|
|
ret = DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_SEND_AIRCRAFT_TO_HANGAR);
|
|
|
_current_player = old_player;
|
|
|
|
|
|
if (CmdFailed(ret)) CrashAirplane(v);
|
|
|
} else if (v->current_order.type != OT_GOTO_DEPOT) {
|
|
|
v->current_order.Free();
|
|
|
}
|
|
|
return;
|
|
|
}
|