Changeset - r19437:273b94619371
[Not reviewed]
master
0 1 0
frosch - 12 years ago 2012-06-23 15:27:15
frosch@openttd.org
(svn r24354) -Fix: When airport construction was denied due to noise, the error message named the wrong town.
1 file changed with 4 insertions and 1 deletions:
0 comments (0 inline, 0 general)
src/station_cmd.cpp
Show inline comments
 
@@ -2072,211 +2072,214 @@ uint8 GetAirportNoiseLevelForTown(const 
 
 * @param as airport's description
 
 * @param it An iterator over all airport tiles
 
 * @return nearest town to airport
 
 */
 
Town *AirportGetNearestTown(const AirportSpec *as, const TileIterator &it)
 
{
 
	Town *t, *nearest = NULL;
 
	uint add = as->size_x + as->size_y - 2; // GetMinimalAirportDistanceToTile can differ from DistanceManhattan by this much
 
	uint mindist = UINT_MAX - add; // prevent overflow
 
	FOR_ALL_TOWNS(t) {
 
		if (DistanceManhattan(t->xy, it) < mindist + add) { // avoid calling GetMinimalAirportDistanceToTile too often
 
			TileIterator *copy = it.Clone();
 
			uint dist = GetMinimalAirportDistanceToTile(*copy, t->xy);
 
			delete copy;
 
			if (dist < mindist) {
 
				nearest = t;
 
				mindist = dist;
 
			}
 
		}
 
	}
 

	
 
	return nearest;
 
}
 

	
 

	
 
/** Recalculate the noise generated by the airports of each town */
 
void UpdateAirportsNoise()
 
{
 
	Town *t;
 
	const Station *st;
 

	
 
	FOR_ALL_TOWNS(t) t->noise_reached = 0;
 

	
 
	FOR_ALL_STATIONS(st) {
 
		if (st->airport.tile != INVALID_TILE && st->airport.type != AT_OILRIG) {
 
			const AirportSpec *as = st->airport.GetSpec();
 
			AirportTileIterator it(st);
 
			Town *nearest = AirportGetNearestTown(as, it);
 
			nearest->noise_reached += GetAirportNoiseLevelForTown(as, it, nearest->xy);
 
		}
 
	}
 
}
 

	
 
/**
 
 * Place an Airport.
 
 * @param tile tile where airport will be built
 
 * @param flags operation to perform
 
 * @param p1
 
 * - p1 = (bit  0- 7) - airport type, @see airport.h
 
 * - p1 = (bit  8-15) - airport layout
 
 * @param p2 various bitstuffed elements
 
 * - p2 = (bit     0) - allow airports directly adjacent to other airports.
 
 * - p2 = (bit 16-31) - station ID to join (NEW_STATION if build new one)
 
 * @param text unused
 
 * @return the cost of this operation or an error
 
 */
 
CommandCost CmdBuildAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
 
{
 
	StationID station_to_join = GB(p2, 16, 16);
 
	bool reuse = (station_to_join != NEW_STATION);
 
	if (!reuse) station_to_join = INVALID_STATION;
 
	bool distant_join = (station_to_join != INVALID_STATION);
 
	byte airport_type = GB(p1, 0, 8);
 
	byte layout = GB(p1, 8, 8);
 

	
 
	if (distant_join && (!_settings_game.station.distant_join_stations || !Station::IsValidID(station_to_join))) return CMD_ERROR;
 

	
 
	if (airport_type >= NUM_AIRPORTS) return CMD_ERROR;
 

	
 
	CommandCost ret = CheckIfAuthorityAllowsNewStation(tile, flags);
 
	if (ret.Failed()) return ret;
 

	
 
	/* Check if a valid, buildable airport was chosen for construction */
 
	const AirportSpec *as = AirportSpec::Get(airport_type);
 
	if (!as->IsAvailable() || layout >= as->num_table) return CMD_ERROR;
 

	
 
	Direction rotation = as->rotation[layout];
 
	Town *t = ClosestTownFromTile(tile, UINT_MAX);
 
	int w = as->size_x;
 
	int h = as->size_y;
 
	if (rotation == DIR_E || rotation == DIR_W) Swap(w, h);
 

	
 
	if (w > _settings_game.station.station_spread || h > _settings_game.station.station_spread) {
 
		return_cmd_error(STR_ERROR_STATION_TOO_SPREAD_OUT);
 
	}
 

	
 
	CommandCost cost = CheckFlatLand(TileArea(tile, w, h), flags);
 
	if (cost.Failed()) return cost;
 

	
 
	/* The noise level is the noise from the airport and reduce it to account for the distance to the town center. */
 
	AirportTileTableIterator iter(as->table[layout], tile);
 
	Town *nearest = AirportGetNearestTown(as, iter);
 
	uint newnoise_level = GetAirportNoiseLevelForTown(as, iter, nearest->xy);
 

	
 
	/* Check if local auth would allow a new airport */
 
	StringID authority_refuse_message = STR_NULL;
 
	Town *authority_refuse_town = NULL;
 

	
 
	if (_settings_game.economy.station_noise_level) {
 
		/* do not allow to build a new airport if this raise the town noise over the maximum allowed by town */
 
		if ((nearest->noise_reached + newnoise_level) > nearest->MaxTownNoise()) {
 
			authority_refuse_message = STR_ERROR_LOCAL_AUTHORITY_REFUSES_NOISE;
 
			authority_refuse_town = nearest;
 
		}
 
	} else {
 
		uint num = 0;
 
		const Station *st;
 
		FOR_ALL_STATIONS(st) {
 
			if (st->town == t && (st->facilities & FACIL_AIRPORT) && st->airport.type != AT_OILRIG) num++;
 
		}
 
		if (num >= 2) {
 
			authority_refuse_message = STR_ERROR_LOCAL_AUTHORITY_REFUSES_AIRPORT;
 
			authority_refuse_town = t;
 
		}
 
	}
 

	
 
	if (authority_refuse_message != STR_NULL) {
 
		SetDParam(0, t->index);
 
		SetDParam(0, authority_refuse_town->index);
 
		return_cmd_error(authority_refuse_message);
 
	}
 

	
 
	Station *st = NULL;
 
	ret = FindJoiningStation(INVALID_STATION, station_to_join, HasBit(p2, 0), TileArea(tile, w, h), &st);
 
	if (ret.Failed()) return ret;
 

	
 
	/* Distant join */
 
	if (st == NULL && distant_join) st = Station::GetIfValid(station_to_join);
 

	
 
	/* Find a deleted station close to us */
 
	if (st == NULL && reuse) st = GetClosestDeletedStation(tile);
 

	
 
	if (st != NULL) {
 
		if (st->owner != _current_company) {
 
			return_cmd_error(STR_ERROR_TOO_CLOSE_TO_ANOTHER_STATION);
 
		}
 

	
 
		CommandCost ret = st->rect.BeforeAddRect(tile, w, h, StationRect::ADD_TEST);
 
		if (ret.Failed()) return ret;
 

	
 
		if (st->airport.tile != INVALID_TILE) {
 
			return_cmd_error(STR_ERROR_TOO_CLOSE_TO_ANOTHER_AIRPORT);
 
		}
 
	} else {
 
		/* allocate and initialize new station */
 
		if (!Station::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_STATIONS_LOADING);
 

	
 
		if (flags & DC_EXEC) {
 
			st = new Station(tile);
 

	
 
			st->town = t;
 
			st->string_id = GenerateStationName(st, tile, !(GetAirport(airport_type)->flags & AirportFTAClass::AIRPLANES) ? STATIONNAMING_HELIPORT : STATIONNAMING_AIRPORT);
 

	
 
			if (Company::IsValidID(_current_company)) {
 
				SetBit(st->town->have_ratings, _current_company);
 
			}
 
		}
 
	}
 

	
 
	for (AirportTileTableIterator iter(as->table[layout], tile); iter != INVALID_TILE; ++iter) {
 
		cost.AddCost(_price[PR_BUILD_STATION_AIRPORT]);
 
	}
 

	
 
	if (flags & DC_EXEC) {
 
		/* Always add the noise, so there will be no need to recalculate when option toggles */
 
		nearest->noise_reached += newnoise_level;
 

	
 
		st->AddFacility(FACIL_AIRPORT, tile);
 
		st->airport.type = airport_type;
 
		st->airport.layout = layout;
 
		st->airport.flags = 0;
 
		st->airport.rotation = rotation;
 

	
 
		st->rect.BeforeAddRect(tile, w, h, StationRect::ADD_TRY);
 

	
 
		for (AirportTileTableIterator iter(as->table[layout], tile); iter != INVALID_TILE; ++iter) {
 
			MakeAirport(iter, st->owner, st->index, iter.GetStationGfx(), WATER_CLASS_INVALID);
 
			SetStationTileRandomBits(iter, GB(Random(), 0, 4));
 
			st->airport.Add(iter);
 

	
 
			if (AirportTileSpec::Get(GetTranslatedAirportTileID(iter.GetStationGfx()))->animation.status != ANIM_STATUS_NO_ANIMATION) AddAnimatedTile(iter);
 
		}
 

	
 
		/* Only call the animation trigger after all tiles have been built */
 
		for (AirportTileTableIterator iter(as->table[layout], tile); iter != INVALID_TILE; ++iter) {
 
			AirportTileAnimationTrigger(st, iter, AAT_BUILT);
 
		}
 

	
 
		UpdateAirplanesOnNewStation(st);
 

	
 
		Company::Get(st->owner)->infrastructure.airport++;
 
		DirtyCompanyInfrastructureWindows(st->owner);
 

	
 
		st->UpdateVirtCoord();
 
		UpdateStationAcceptance(st, false);
 
		st->RecomputeIndustriesNear();
 
		InvalidateWindowData(WC_SELECT_STATION, 0, 0);
 
		InvalidateWindowData(WC_STATION_LIST, st->owner, 0);
 
		InvalidateWindowData(WC_STATION_VIEW, st->index);
 

	
 
		if (_settings_game.economy.station_noise_level) {
 
			SetWindowDirty(WC_TOWN_VIEW, st->town->index);
 
		}
 
	}
 

	
 
	return cost;
 
}
 

	
 
/**
 
 * Remove an airport
 
 * @param tile TileIndex been queried
 
 * @param flags operation to perform
 
 * @return cost or failure of operation
 
 */
 
static CommandCost RemoveAirport(TileIndex tile, DoCommandFlag flags)
0 comments (0 inline, 0 general)