|
@@ -2146,194 +2146,195 @@ CommandCost CmdBuildAirport(TileIndex ti
|
|
|
|
|
|
/* 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);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
const AirportTileTable *it = as->table[layout];
|
|
|
do {
|
|
|
cost.AddCost(_price[PR_BUILD_STATION_AIRPORT]);
|
|
|
} while ((++it)->ti.x != -0x80);
|
|
|
|
|
|
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->airport.psa.ResetToZero();
|
|
|
|
|
|
st->rect.BeforeAddRect(tile, w, h, StationRect::ADD_TRY);
|
|
|
|
|
|
it = as->table[layout];
|
|
|
do {
|
|
|
TileIndex cur_tile = tile + ToTileIndexDiff(it->ti);
|
|
|
MakeAirport(cur_tile, st->owner, st->index, it->gfx, WATER_CLASS_INVALID);
|
|
|
SetStationTileRandomBits(cur_tile, GB(Random(), 0, 4));
|
|
|
st->airport.Add(cur_tile);
|
|
|
|
|
|
if (AirportTileSpec::Get(GetTranslatedAirportTileID(it->gfx))->animation.status != ANIM_STATUS_NO_ANIMATION) AddAnimatedTile(cur_tile);
|
|
|
} while ((++it)->ti.x != -0x80);
|
|
|
|
|
|
/* Only call the animation trigger after all tiles have been built */
|
|
|
it = as->table[layout];
|
|
|
do {
|
|
|
TileIndex cur_tile = tile + ToTileIndexDiff(it->ti);
|
|
|
AirportTileAnimationTrigger(st, cur_tile, AAT_BUILT);
|
|
|
} while ((++it)->ti.x != -0x80);
|
|
|
|
|
|
UpdateAirplanesOnNewStation(st);
|
|
|
|
|
|
st->UpdateVirtCoord();
|
|
|
UpdateStationAcceptance(st, false);
|
|
|
st->RecomputeIndustriesNear();
|
|
|
InvalidateWindowData(WC_SELECT_STATION, 0, 0);
|
|
|
InvalidateWindowData(WC_STATION_LIST, st->owner, 0);
|
|
|
SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_PLANES);
|
|
|
|
|
|
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)
|
|
|
{
|
|
|
Station *st = Station::GetByTile(tile);
|
|
|
|
|
|
if (_current_company != OWNER_WATER) {
|
|
|
CommandCost ret = CheckOwnership(st->owner);
|
|
|
if (ret.Failed()) return ret;
|
|
|
}
|
|
|
|
|
|
tile = st->airport.tile;
|
|
|
|
|
|
CommandCost cost(EXPENSES_CONSTRUCTION);
|
|
|
|
|
|
const Aircraft *a;
|
|
|
FOR_ALL_AIRCRAFT(a) {
|
|
|
if (!a->IsNormalAircraft()) continue;
|
|
|
if (a->targetairport == st->index && a->state != FLYING) return CMD_ERROR;
|
|
|
}
|
|
|
|
|
|
TILE_AREA_LOOP(tile_cur, st->airport) {
|
|
|
if (!st->TileBelongsToAirport(tile_cur)) continue;
|
|
|
|
|
|
CommandCost ret = EnsureNoVehicleOnGround(tile_cur);
|
|
|
if (ret.Failed()) return ret;
|
|
|
|
|
|
cost.AddCost(_price[PR_CLEAR_STATION_AIRPORT]);
|
|
|
|
|
|
if (flags & DC_EXEC) {
|
|
|
if (IsHangarTile(tile_cur)) OrderBackup::Reset(tile_cur, false);
|
|
|
DeleteAnimatedTile(tile_cur);
|
|
|
DoClearSquare(tile_cur);
|
|
|
DeleteNewGRFInspectWindow(GSF_AIRPORTTILES, tile_cur);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (flags & DC_EXEC) {
|
|
|
/* Clear the persistent storage. */
|
|
|
delete st->airport.psa;
|
|
|
|
|
|
const AirportSpec *as = st->airport.GetSpec();
|
|
|
for (uint i = 0; i < st->airport.GetNumHangars(); ++i) {
|
|
|
DeleteWindowById(
|
|
|
WC_VEHICLE_DEPOT, st->airport.GetHangarTile(i)
|
|
|
);
|
|
|
}
|
|
|
|
|
|
/* The noise level is the noise from the airport and reduce it to account for the distance to the town center.
|
|
|
* And as for construction, always remove it, even if the setting is not set, in order to avoid the
|
|
|
* need of recalculation */
|
|
|
Town *nearest = AirportGetNearestTown(as, tile);
|
|
|
nearest->noise_reached -= GetAirportNoiseLevelForTown(as, nearest->xy, tile);
|
|
|
|
|
|
st->rect.AfterRemoveRect(st, st->airport);
|
|
|
|
|
|
st->airport.Clear();
|
|
|
st->facilities &= ~FACIL_AIRPORT;
|
|
|
st->airport.psa.ResetToZero();
|
|
|
|
|
|
SetWindowWidgetDirty(WC_STATION_VIEW, st->index, SVW_PLANES);
|
|
|
|
|
|
if (_settings_game.economy.station_noise_level) {
|
|
|
SetWindowDirty(WC_TOWN_VIEW, st->town->index);
|
|
|
}
|
|
|
|
|
|
st->UpdateVirtCoord();
|
|
|
st->RecomputeIndustriesNear();
|
|
|
DeleteStationIfEmpty(st);
|
|
|
DeleteNewGRFInspectWindow(GSF_AIRPORTS, st->index);
|
|
|
}
|
|
|
|
|
|
return cost;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Tests whether the company's vehicles have this station in orders
|
|
|
* @param station station ID
|
|
|
* @param include_company If true only check vehicles of \a company, if false only check vehicles of other companies
|
|
|
* @param company company ID
|
|
|
*/
|
|
|
bool HasStationInUse(StationID station, bool include_company, CompanyID company)
|
|
|
{
|
|
|
const Vehicle *v;
|
|
|
FOR_ALL_VEHICLES(v) {
|
|
|
if ((v->owner == company) == include_company) {
|
|
|
const Order *order;
|
|
|
FOR_VEHICLE_ORDERS(v, order) {
|
|
|
if ((order->IsType(OT_GOTO_STATION) || order->IsType(OT_GOTO_WAYPOINT)) && order->GetDestination() == station) {
|
|
|
return true;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
static const TileIndexDiffC _dock_tileoffs_chkaround[] = {
|
|
|
{-1, 0},
|
|
|
{ 0, 0},
|
|
|
{ 0, 0},
|
|
|
{ 0, -1}
|
|
|
};
|
|
|
static const byte _dock_w_chk[4] = { 2, 1, 2, 1 };
|
|
|
static const byte _dock_h_chk[4] = { 1, 2, 1, 2 };
|
|
|
|
|
|
/**
|