File diff r9412:d3e87d714ab7 → r9413:fcf267325763
src/aircraft_cmd.cpp
Show inline comments
 
@@ -266,49 +266,49 @@ uint16 AircraftDefaultCargoCapacity(Carg
 
 */
 
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);
 
	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;
 

	
 
	/* Prevent building aircraft types at places which can't handle them */
 
	if (!CanAircraftUseStation(p1, tile)) return CMD_ERROR;
 

	
 
	/* Allocate 2 or 3 vehicle structs, depending on type
 
	 * vl[0] = aircraft, vl[1] = shadow, [vl[2] = rotor] */
 
	Vehicle *vl[3];
 
	if (!Vehicle::AllocateList(vl, avi->subtype & AIR_CTOL ? 2 : 3)) {
 
		return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
 
	}
 

	
 
	UnitID unit_num = HasBit(p2, 0) ? 0 : GetFreeUnitNumber(VEH_AIRCRAFT);
 
	if (unit_num > _settings.vehicle.max_aircraft)
 
	if (unit_num > _settings_game.vehicle.max_aircraft)
 
		return_cmd_error(STR_00E1_TOO_MANY_VEHICLES_IN_GAME);
 

	
 
	if (flags & DC_EXEC) {
 
		Vehicle *v = vl[0]; // aircraft
 
		Vehicle *u = vl[1]; // shadow
 

	
 
		v = new (v) Aircraft();
 
		u = new (u) Aircraft();
 
		v->unitnumber = unit_num;
 
		v->direction = DIR_SE;
 

	
 
		v->owner = u->owner = _current_player;
 

	
 
		v->tile = tile;
 
//		u->tile = 0;
 

	
 
		uint x = TileX(tile) * TILE_SIZE + 5;
 
		uint y = TileY(tile) * TILE_SIZE + 3;
 

	
 
		v->x_pos = u->x_pos = x;
 
		v->y_pos = u->y_pos = y;
 

	
 
		u->z_pos = GetSlopeZ(x, y);
 
		v->z_pos = u->z_pos + 1;
 
@@ -383,49 +383,49 @@ CommandCost CmdBuildAircraft(TileIndex t
 

	
 
		_new_vehicle_id = v->index;
 

	
 
		/* When we click on hangar we know the tile it is on. By that we know
 
		 * its position in the array of depots the airport has.....we can search
 
		 * layout for #th position of depot. Since layout must start with a listing
 
		 * of all depots, it is simple */
 
		for (uint i = 0;; i++) {
 
			const Station *st = GetStationByTile(tile);
 
			const AirportFTAClass *apc = st->Airport();
 

	
 
			assert(i != apc->nof_depots);
 
			if (st->airport_tile + ToTileIndexDiff(apc->airport_depots[i]) == tile) {
 
				assert(apc->layout[i].heading == HANGAR);
 
				v->u.air.pos = apc->layout[i].position;
 
				break;
 
			}
 
		}
 

	
 
		v->u.air.state = HANGAR;
 
		v->u.air.previous_pos = v->u.air.pos;
 
		v->u.air.targetairport = GetStationIndex(tile);
 
		v->SetNext(u);
 

	
 
		v->service_interval = _settings.vehicle.servint_aircraft;
 
		v->service_interval = _settings_game.vehicle.servint_aircraft;
 

	
 
		v->date_of_last_service = _date;
 
		v->build_year = u->build_year = _cur_year;
 

	
 
		v->cur_image = u->cur_image = 0xEA0;
 

	
 
		v->random_bits = VehicleRandomBits();
 
		u->random_bits = VehicleRandomBits();
 

	
 
		v->vehicle_flags = 0;
 
		if (e->flags & ENGINE_EXCLUSIVE_PREVIEW) SetBit(v->vehicle_flags, VF_BUILT_AS_PROTOTYPE);
 

	
 
		UpdateAircraftCache(v);
 

	
 
		VehiclePositionChanged(v);
 
		VehiclePositionChanged(u);
 

	
 
		/* Aircraft with 3 vehicles (chopper)? */
 
		if (v->subtype == AIR_HELICOPTER) {
 
			Vehicle *w = vl[2];
 

	
 
			w = new (w) Aircraft();
 
			w->direction = DIR_N;
 
			w->owner = _current_player;
 
@@ -643,49 +643,49 @@ CommandCost CmdRefitAircraft(TileIndex t
 
		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;
 
		v->cargo.Truncate(v->cargo_type == new_cid ? pass : 0);
 
		u->cargo.Truncate(v->cargo_type == new_cid ? mail : 0);
 
		v->cargo_type = new_cid;
 
		v->cargo_subtype = new_subtype;
 
		InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 
		InvalidateWindow(WC_VEHICLE_DEPOT, v->tile);
 
		InvalidateWindowClassesData(WC_AIRCRAFT_LIST, 0);
 
	}
 

	
 
	return cost;
 
}
 

	
 

	
 
static void CheckIfAircraftNeedsService(Vehicle *v)
 
{
 
	if (_settings.vehicle.servint_aircraft == 0 || !v->NeedsAutomaticServicing()) return;
 
	if (_settings_game.vehicle.servint_aircraft == 0 || !v->NeedsAutomaticServicing()) return;
 
	if (v->IsInDepot()) {
 
		VehicleServiceInDepot(v);
 
		return;
 
	}
 

	
 
	const Station *st = GetStation(v->current_order.GetDestination());
 
	/* only goto depot if the target airport has terminals (eg. it is airport) */
 
	if (st->IsValid() && st->airport_tile != 0 && st->Airport()->terminals != NULL) {
 
//		printf("targetairport = %d, st->index = %d\n", v->u.air.targetairport, st->index);
 
//		v->u.air.targetairport = st->index;
 
		v->current_order.MakeGoToDepot(st->index, ODTFB_SERVICE);
 
		InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
	} else if (v->current_order.IsType(OT_GOTO_DEPOT)) {
 
		v->current_order.MakeDummy();
 
		InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
	}
 
}
 

	
 
void Aircraft::OnNewDay()
 
{
 
	if (!IsNormalAircraft(this)) return;
 

	
 
	if ((++this->day_counter & 7) == 0) DecreaseVehicleValue(this);
 

	
 
@@ -863,83 +863,83 @@ void UpdateAircraftCache(Vehicle *v)
 
 * Special velocities for aircraft
 
 */
 
enum AircraftSpeedLimits {
 
	SPEED_LIMIT_TAXI     =     50,  ///< Maximum speed of an aircraft while taxiing
 
	SPEED_LIMIT_APPROACH =    230,  ///< Maximum speed of an aircraft on finals
 
	SPEED_LIMIT_BROKEN   =    320,  ///< Maximum speed of an aircraft that is broken
 
	SPEED_LIMIT_HOLD     =    425,  ///< Maximum speed of an aircraft that flies the holding pattern
 
	SPEED_LIMIT_NONE     = 0xFFFF   ///< No environmental speed limit. Speed limit is type dependent
 
};
 

	
 
/**
 
 * Sets the new speed for an aircraft
 
 * @param v The vehicle for which the speed should be obtained
 
 * @param speed_limit The maximum speed the vehicle may have.
 
 * @param hard_limit If true, the limit is directly enforced, otherwise the plane is slowed down gradually
 
 * @return The number of position updates needed within the tick
 
 */
 
static int UpdateAircraftSpeed(Vehicle *v, uint speed_limit = SPEED_LIMIT_NONE, bool hard_limit = true)
 
{
 
	uint spd = v->acceleration * 16;
 
	byte t;
 

	
 
	/* Adjust speed limits by plane speed factor to prevent taxiing
 
	 * and take-off speeds being too low. */
 
	speed_limit *= _settings.vehicle.plane_speed;
 
	speed_limit *= _settings_game.vehicle.plane_speed;
 

	
 
	if (v->u.air.cached_max_speed < speed_limit) {
 
		if (v->cur_speed < speed_limit) hard_limit = false;
 
		speed_limit = v->u.air.cached_max_speed;
 
	}
 

	
 
	speed_limit = min(speed_limit, v->max_speed);
 

	
 
	v->subspeed = (t=v->subspeed) + (byte)spd;
 

	
 
	/* Aircraft's current speed is used twice so that very fast planes are
 
	 * forced to slow down rapidly in the short distance needed. The magic
 
	 * value 16384 was determined to give similar results to the old speed/48
 
	 * method at slower speeds. This also results in less reduction at slow
 
	 * speeds to that aircraft do not get to taxi speed straight after
 
	 * touchdown. */
 
	if (!hard_limit && v->cur_speed > speed_limit) {
 
		speed_limit = v->cur_speed - max(1, ((v->cur_speed * v->cur_speed) / 16384) / _settings.vehicle.plane_speed);
 
		speed_limit = v->cur_speed - max(1, ((v->cur_speed * v->cur_speed) / 16384) / _settings_game.vehicle.plane_speed);
 
	}
 

	
 
	spd = min(v->cur_speed + (spd >> 8) + (v->subspeed < t), speed_limit);
 

	
 
	/* adjust speed for broken vehicles */
 
	if (v->vehstatus & VS_AIRCRAFT_BROKEN) spd = min(spd, SPEED_LIMIT_BROKEN);
 

	
 
	/* updates statusbar only if speed have changed to save CPU time */
 
	if (spd != v->cur_speed) {
 
		v->cur_speed = spd;
 
		if (_settings.gui.vehicle_speed)
 
		if (_settings_client.gui.vehicle_speed)
 
			InvalidateWindowWidget(WC_VEHICLE_VIEW, v->index, VVW_WIDGET_START_STOP_VEH);
 
	}
 

	
 
	/* Adjust distance moved by plane speed setting */
 
	if (_settings.vehicle.plane_speed > 1) spd /= _settings.vehicle.plane_speed;
 
	if (_settings_game.vehicle.plane_speed > 1) spd /= _settings_game.vehicle.plane_speed;
 

	
 
	if (!(v->direction & 1)) spd = spd * 3 / 4;
 

	
 
	spd += v->progress;
 
	v->progress = (byte)spd;
 
	return spd >> 8;
 
}
 

	
 
/**
 
 * Gets the cruise altitude of an aircraft.
 
 * The cruise altitude is determined by the velocity of the vehicle
 
 * and the direction it is moving
 
 * @param v The vehicle. Should be an aircraft
 
 * @returns Altitude in pixel units
 
 */
 
static byte GetAircraftFlyingAltitude(const Vehicle *v)
 
{
 
	/* Make sure Aircraft fly no lower so that they don't conduct
 
	 * CFITs (controlled flight into terrain)
 
	 */
 
	byte base_altitude = 150;
 

	
 
	/* Make sure eastbound and westbound planes do not "crash" into each
 
	 * other by providing them with vertical seperation
 
@@ -1578,49 +1578,49 @@ static void AircraftEventHandler_InHanga
 
	if (v->current_order.GetDestination() == 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 == 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 == AIR_HELICOPTER) ? HELITAKEOFF : TAKEOFF;
 
	}
 
	AircraftLeaveHangar(v);
 
	AirportMove(v, apc);
 
}
 

	
 
/** At one of the Airport's Terminals */
 
static void AircraftEventHandler_AtTerminal(Vehicle *v, const AirportFTAClass *apc)
 
{
 
	/* if we just arrived, execute EnterTerminal first */
 
	if (v->u.air.previous_pos != v->u.air.pos) {
 
		AircraftEventHandler_EnterTerminal(v, apc);
 
		/* on an airport with helipads, a helicopter will always land there
 
		 * and get serviced at the same time - patch setting */
 
		if (_settings.order.serviceathelipad) {
 
		if (_settings_game.order.serviceathelipad) {
 
			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;
 
				v->reliability = GetEngine(v->engine_type)->reliability;
 
				InvalidateWindow(WC_VEHICLE_DETAILS, v->index);
 
			}
 
		}
 
		return;
 
	}
 

	
 
	if (!v->current_order.IsValid()) return;
 

	
 
	/* if the block of the next position is busy, stay put */
 
	if (AirportHasBlock(v, &apc->layout[v->u.air.pos], apc)) return;
 

	
 
	/* airport-road is free. We either have to go to another airport, or to the hangar
 
	 * ---> start moving */
 

	
 
	switch (v->current_order.GetType()) {
 
		case OT_GOTO_STATION: // ready to fly to another airport
 
			/* airplane goto state takeoff, helicopter to helitakeoff */
 
			v->u.air.state = (v->subtype == AIR_HELICOPTER) ? HELITAKEOFF : TAKEOFF;
 
			break;