summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/aircraft_cmd.cpp12
-rw-r--r--src/airport_gui.cpp6
-rw-r--r--src/newgrf_airport.h1
-rw-r--r--src/saveload/station_sl.cpp1
-rw-r--r--src/station_base.h35
-rw-r--r--src/station_cmd.cpp3
-rw-r--r--src/table/airport_defaults.h16
7 files changed, 58 insertions, 16 deletions
diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp
index 6019f477f..f371d16af 100644
--- a/src/aircraft_cmd.cpp
+++ b/src/aircraft_cmd.cpp
@@ -803,9 +803,10 @@ byte GetAircraftFlyingAltitude(const Aircraft *v)
*
* @param v The vehicle that is approaching the airport
* @param apc The Airport Class being approached.
+ * @param rotation The rotation of the airport.
* @returns The index of the entry point
*/
-static byte AircraftGetEntryPoint(const Aircraft *v, const AirportFTAClass *apc)
+static byte AircraftGetEntryPoint(const Aircraft *v, const AirportFTAClass *apc, Direction rotation)
{
assert(v != NULL);
assert(apc != NULL);
@@ -832,6 +833,7 @@ static byte AircraftGetEntryPoint(const Aircraft *v, const AirportFTAClass *apc)
/* We are northwest or southeast of the airport */
dir = delta_y < 0 ? DIAGDIR_NW : DIAGDIR_SE;
}
+ dir = ChangeDiagDir(dir, (DiagDirDiff)ReverseDiagDir(DirToDiagDir(rotation)));
return apc->entry_points[dir];
}
@@ -863,7 +865,7 @@ static bool AircraftController(Aircraft *v)
if (st == NULL || st->airport.tile == INVALID_TILE) {
/* Jump into our "holding pattern" state machine if possible */
if (v->pos >= afc->nofelements) {
- v->pos = v->previous_pos = AircraftGetEntryPoint(v, afc);
+ v->pos = v->previous_pos = AircraftGetEntryPoint(v, afc, DIR_N);
} else if (v->targetairport != v->current_order.GetDestination()) {
/* If not possible, just get out of here fast */
v->state = FLYING;
@@ -1358,7 +1360,8 @@ void AircraftNextAirportPos_and_Order(Aircraft *v)
const Station *st = GetTargetAirportIfValid(v);
const AirportFTAClass *apc = st == NULL ? GetAirport(AT_DUMMY) : st->airport.GetFTA();
- v->pos = v->previous_pos = AircraftGetEntryPoint(v, apc);
+ Direction rotation = st == NULL ? DIR_N : st->airport.rotation;
+ v->pos = v->previous_pos = AircraftGetEntryPoint(v, apc, rotation);
}
void AircraftLeaveHangar(Aircraft *v)
@@ -1997,7 +2000,8 @@ void UpdateAirplanesOnNewStation(const Station *st)
/* update position of airplane. If plane is not flying, landing, or taking off
* you cannot delete airport, so it doesn't matter */
if (v->state >= FLYING) { // circle around
- v->pos = v->previous_pos = AircraftGetEntryPoint(v, ap);
+ Direction rotation = st->airport.tile == INVALID_TILE ? DIR_N : st->airport.rotation;
+ v->pos = v->previous_pos = AircraftGetEntryPoint(v, ap, rotation);
v->state = FLYING;
UpdateAircraftCache(v);
/* landing plane needs to be reset to flying height (only if in pause mode upgrade,
diff --git a/src/airport_gui.cpp b/src/airport_gui.cpp
index a5fda1567..00297d62a 100644
--- a/src/airport_gui.cpp
+++ b/src/airport_gui.cpp
@@ -356,7 +356,11 @@ public:
this->DisableWidget(BAIRW_LAYOUT_INCREASE);
} else {
const AirportSpec *as = GetAirportSpecFromClass(_selected_airport_class, _selected_airport_index);
- SetTileSelectSize(as->size_x, as->size_y);
+ int w = as->size_x;
+ int h = as->size_y;
+ Direction rotation = as->rotation[_selected_airport_layout];
+ if (rotation == DIR_E || rotation == DIR_W) Swap(w, h);
+ SetTileSelectSize(w, h);
this->SetWidgetDisabledState(BAIRW_LAYOUT_DECREASE, _selected_airport_layout == 0);
this->SetWidgetDisabledState(BAIRW_LAYOUT_INCREASE, _selected_airport_layout + 1 >= as->num_table);
diff --git a/src/newgrf_airport.h b/src/newgrf_airport.h
index bcaa7e274..5895a00cb 100644
--- a/src/newgrf_airport.h
+++ b/src/newgrf_airport.h
@@ -59,6 +59,7 @@ struct HangarTileTable {
struct AirportSpec {
const struct AirportFTAClass *fsm; ///< the finite statemachine for the default airports
const AirportTileTable * const *table; ///< list of the tiles composing the airport
+ Direction *rotation; ///< the rotation of each tiletable
byte num_table; ///< number of elements in the table
const HangarTileTable *depot_table; ///< gives the position of the depots on the airports
byte nof_depots; ///< the number of hangar tiles in this airport
diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp
index a57c71c55..31f024cd0 100644
--- a/src/saveload/station_sl.cpp
+++ b/src/saveload/station_sl.cpp
@@ -337,6 +337,7 @@ static const SaveLoad _station_desc[] = {
SLE_VAR(Station, airport.type, SLE_UINT8),
SLE_CONDVAR(Station, airport.layout, SLE_UINT8, 145, SL_MAX_VERSION),
SLE_VAR(Station, airport.flags, SLE_UINT64),
+ SLE_CONDVAR(Station, airport.rotation, SLE_UINT8, 145, SL_MAX_VERSION),
SLE_VAR(Station, indtype, SLE_UINT8),
diff --git a/src/station_base.h b/src/station_base.h
index 5329a2642..997539943 100644
--- a/src/station_base.h
+++ b/src/station_base.h
@@ -49,9 +49,10 @@ struct GoodsEntry {
struct Airport : public TileArea {
Airport() : TileArea(INVALID_TILE, 0, 0) {}
- uint64 flags; ///< stores which blocks on the airport are taken. was 16 bit earlier on, then 32
- byte type; ///< Type of this airport, @see AirportTypes.
- byte layout; ///< Airport layout number.
+ uint64 flags; ///< stores which blocks on the airport are taken. was 16 bit earlier on, then 32
+ byte type; ///< Type of this airport, @see AirportTypes.
+ byte layout; ///< Airport layout number.
+ Direction rotation; ///< How this airport is rotated.
/**
* Get the AirportSpec that from the airport type of this airport. If there
@@ -82,6 +83,30 @@ struct Airport : public TileArea {
}
/**
+ * Add the tileoffset to the base tile of this airport but rotate it first.
+ * The base tile is the northernmost tile of this airport. This function
+ * helps to make sure that getting the tile of a hangar works even for
+ * rotated airport layouts without requiring a rotated array of hangar tiles.
+ * @param tidc The tilediff to add to the airport tile.
+ * @return The tile of this airport plus the rotated offset.
+ */
+ FORCEINLINE TileIndex GetRotatedTileFromOffset(TileIndexDiffC tidc) const
+ {
+ const AirportSpec *as = this->GetSpec();
+ switch (this->rotation) {
+ case DIR_N: return this->tile + ToTileIndexDiff(tidc);
+
+ case DIR_E: return this->tile + TileDiffXY(tidc.y, as->size_x - 1 - tidc.x);
+
+ case DIR_S: return this->tile + TileDiffXY(as->size_x - 1 - tidc.x, as->size_y - 1 - tidc.y);
+
+ case DIR_W: return this->tile + TileDiffXY(as->size_y - 1 - tidc.y, tidc.x);
+
+ default: NOT_REACHED();
+ }
+ }
+
+ /**
* Get the first tile of the given hangar.
* @param hangar_num The hangar to get the location of.
* @pre hangar_num < GetNumHangars().
@@ -92,7 +117,7 @@ struct Airport : public TileArea {
const AirportSpec *as = this->GetSpec();
for (uint i = 0; i < as->nof_depots; i++) {
if (as->depot_table[i].hangar_num == hangar_num) {
- return this->tile + ToTileIndexDiff(as->depot_table[i].ti);
+ return this->GetRotatedTileFromOffset(as->depot_table[i].ti);
}
}
NOT_REACHED();
@@ -108,7 +133,7 @@ struct Airport : public TileArea {
{
const AirportSpec *as = this->GetSpec();
for (uint i = 0; i < as->nof_depots; i++) {
- if (this->tile + ToTileIndexDiff(as->depot_table[i].ti) == tile) {
+ if (this->GetRotatedTileFromOffset(as->depot_table[i].ti) == tile) {
return as->depot_table[i].hangar_num;
}
}
diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp
index 67000272b..326567909 100644
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -2125,9 +2125,11 @@ CommandCost CmdBuildAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
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);
@@ -2216,6 +2218,7 @@ CommandCost CmdBuildAirport(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
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);
diff --git a/src/table/airport_defaults.h b/src/table/airport_defaults.h
index dfebdc1d5..5e2d82b72 100644
--- a/src/table/airport_defaults.h
+++ b/src/table/airport_defaults.h
@@ -373,21 +373,25 @@ static AirportTileTable *_tile_table_helistation[] = {
_tile_table_helistation_0,
};
+static Direction _default_airports_rotation[] = {
+ DIR_N,
+};
+
#undef MK
#undef MKEND
/** General AirportSpec definition. */
-#define AS_GENERIC(fsm, att, att_len, depot_tbl, num_depots, size_x, size_y, noise, catchment, min_year, max_year, ttdpatch_type, class_id, name, enabled) \
- {fsm, att, att_len, depot_tbl, num_depots, size_x, size_y, noise, catchment, min_year, max_year, name, ttdpatch_type, class_id, enabled, {AT_INVALID, 0, NULL, NULL, AT_INVALID}}
+#define AS_GENERIC(fsm, att, rot, att_len, depot_tbl, num_depots, size_x, size_y, noise, catchment, min_year, max_year, ttdpatch_type, class_id, name, enabled) \
+ {fsm, att, rot, att_len, depot_tbl, num_depots, size_x, size_y, noise, catchment, min_year, max_year, name, ttdpatch_type, class_id, enabled, {AT_INVALID, 0, NULL, NULL, AT_INVALID}}
/** AirportSpec definition for airports without any depot. */
#define AS_ND(ap_name, size_x, size_y, min_year, max_year, catchment, noise, ttdpatch_type, class_id, name) \
- AS_GENERIC(&_airportfta_##ap_name, _tile_table_##ap_name, lengthof(_tile_table_##ap_name), NULL, 0, \
+ AS_GENERIC(&_airportfta_##ap_name, _tile_table_##ap_name, _default_airports_rotation, lengthof(_tile_table_##ap_name), NULL, 0, \
size_x, size_y, noise, catchment, min_year, max_year, ttdpatch_type, class_id, name, true)
/** AirportSpec definition for airports with at least one depot. */
#define AS(ap_name, size_x, size_y, min_year, max_year, catchment, noise, ttdpatch_type, class_id, name) \
- AS_GENERIC(&_airportfta_##ap_name, _tile_table_##ap_name, lengthof(_tile_table_##ap_name), _airport_depots_##ap_name, lengthof(_airport_depots_##ap_name), \
+ AS_GENERIC(&_airportfta_##ap_name, _tile_table_##ap_name, _default_airports_rotation, lengthof(_tile_table_##ap_name), _airport_depots_##ap_name, lengthof(_airport_depots_##ap_name), \
size_x, size_y, noise, catchment, min_year, max_year, ttdpatch_type, class_id, name, true)
/* The helidepot and helistation have ATP_TTDP_SMALL because they are at ground level */
@@ -401,12 +405,12 @@ extern const AirportSpec _origin_airport_specs[] = {
AS(helidepot, 2, 2, 1976, MAX_YEAR, 4, 2, ATP_TTDP_SMALL, APC_HELIPORT, STR_AIRPORT_HELIDEPOT),
AS(intercontinental, 9, 11, 2002, MAX_YEAR, 10, 25, ATP_TTDP_LARGE, APC_HUB, STR_AIRPORT_INTERCONTINENTAL),
AS(helistation, 4, 2, 1980, MAX_YEAR, 4, 3, ATP_TTDP_SMALL, APC_HELIPORT, STR_AIRPORT_HELISTATION),
- AS_GENERIC(&_airportfta_oilrig, NULL, 0, NULL, 0, 1, 1, 0, 4, 0, 0, ATP_TTDP_OILRIG, APC_HELIPORT, STR_NULL, false),
+ AS_GENERIC(&_airportfta_oilrig, NULL, _default_airports_rotation, 0, NULL, 0, 1, 1, 0, 4, 0, 0, ATP_TTDP_OILRIG, APC_HELIPORT, STR_NULL, false),
};
assert_compile(NEW_AIRPORT_OFFSET == lengthof(_origin_airport_specs));
-AirportSpec AirportSpec::dummy = AS_GENERIC(&_airportfta_dummy, NULL, 0, NULL, 0, 0, 0, 0, 0, MIN_YEAR, MIN_YEAR, ATP_TTDP_LARGE, APC_BEGIN, STR_NULL, false);
+AirportSpec AirportSpec::dummy = AS_GENERIC(&_airportfta_dummy, NULL, _default_airports_rotation, 0, NULL, 0, 0, 0, 0, 0, MIN_YEAR, MIN_YEAR, ATP_TTDP_LARGE, APC_BEGIN, STR_NULL, false);
#undef AS
#undef AS_ND