summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ai/api/ai_buoylist.cpp8
-rw-r--r--src/ai/api/ai_order.cpp10
-rw-r--r--src/ai/api/ai_rail.cpp5
-rw-r--r--src/ai/api/ai_waypoint.cpp2
-rw-r--r--src/ai/api/ai_waypointlist.cpp2
-rw-r--r--src/date.cpp2
-rw-r--r--src/elrail.cpp4
-rw-r--r--src/lang/english.txt18
-rw-r--r--src/misc.cpp2
-rw-r--r--src/newgrf_station.cpp55
-rw-r--r--src/order_cmd.cpp17
-rw-r--r--src/order_gui.cpp22
-rw-r--r--src/pbs.cpp6
-rw-r--r--src/rail.cpp2
-rw-r--r--src/rail_cmd.cpp132
-rw-r--r--src/rail_map.h91
-rw-r--r--src/saveload/afterload.cpp70
-rw-r--r--src/saveload/saveload.cpp7
-rw-r--r--src/saveload/saveload.h2
-rw-r--r--src/saveload/saveload_internal.h5
-rw-r--r--src/saveload/station_sl.cpp292
-rw-r--r--src/saveload/waypoint_sl.cpp205
-rw-r--r--src/signal.cpp8
-rw-r--r--src/station.cpp6
-rw-r--r--src/station_base.h70
-rw-r--r--src/station_cmd.cpp148
-rw-r--r--src/station_gui.cpp6
-rw-r--r--src/station_map.h41
-rw-r--r--src/station_type.h5
-rw-r--r--src/strings.cpp4
-rw-r--r--src/terraform_gui.cpp6
-rw-r--r--src/train_cmd.cpp8
-rw-r--r--src/vehicle_gui.cpp4
-rw-r--r--src/viewport.cpp2
-rw-r--r--src/waypoint.cpp22
-rw-r--r--src/waypoint.h21
-rw-r--r--src/waypoint_cmd.cpp31
-rw-r--r--src/waypoint_gui.cpp2
-rw-r--r--src/yapf/yapf_costrail.hpp2
-rw-r--r--src/yapf/yapf_destrail.hpp17
40 files changed, 679 insertions, 683 deletions
diff --git a/src/ai/api/ai_buoylist.cpp b/src/ai/api/ai_buoylist.cpp
index 0ba66fb39..1412c7860 100644
--- a/src/ai/api/ai_buoylist.cpp
+++ b/src/ai/api/ai_buoylist.cpp
@@ -3,12 +3,12 @@
/** @file ai_buoylist.cpp Implementation of AIBuoyList and friends. */
#include "ai_buoylist.hpp"
-#include "../../station_base.h"
+#include "../../waypoint.h"
AIBuoyList::AIBuoyList()
{
- Station *st;
- FOR_ALL_STATIONS(st) {
- if (st->IsBuoy()) this->AddItem(st->xy);
+ Waypoint *wp;
+ FOR_ALL_WAYPOINTS(wp) {
+ if (wp->facilities & FACIL_DOCK) this->AddItem(wp->xy);
}
}
diff --git a/src/ai/api/ai_order.cpp b/src/ai/api/ai_order.cpp
index 7cd791562..5069bcb5e 100644
--- a/src/ai/api/ai_order.cpp
+++ b/src/ai/api/ai_order.cpp
@@ -25,18 +25,14 @@ static OrderType GetOrderTypeByTile(TileIndex t)
switch (::GetTileType(t)) {
default: break;
case MP_STATION:
+ if (IsBuoy(t) || IsRailWaypoint(t)) return OT_GOTO_WAYPOINT;
if (IsHangar(t)) return OT_GOTO_DEPOT;
- if (IsBuoy(t)) return OT_GOTO_WAYPOINT;
return OT_GOTO_STATION;
break;
case MP_WATER: if (::IsShipDepot(t)) return OT_GOTO_DEPOT; break;
case MP_ROAD: if (::GetRoadTileType(t) == ROAD_TILE_DEPOT) return OT_GOTO_DEPOT; break;
case MP_RAILWAY:
- switch (::GetRailTileType(t)) {
- case RAIL_TILE_DEPOT: return OT_GOTO_DEPOT;
- case RAIL_TILE_WAYPOINT: return OT_GOTO_WAYPOINT;
- default: break;
- }
+ if (IsRailDepot(t)) return OT_GOTO_DEPOT;
break;
}
@@ -359,7 +355,7 @@ static const Order *ResolveOrder(VehicleID vehicle_id, AIOrder::OrderPosition or
break;
case OT_GOTO_WAYPOINT:
- order.MakeGoToWaypoint(::Vehicle::Get(vehicle_id)->type == VEH_TRAIN ? ::GetWaypointIndex(destination) : ::GetStationIndex(destination));
+ order.MakeGoToWaypoint(::GetStationIndex(destination));
break;
default:
diff --git a/src/ai/api/ai_rail.cpp b/src/ai/api/ai_rail.cpp
index 5986ad82b..7e686aac9 100644
--- a/src/ai/api/ai_rail.cpp
+++ b/src/ai/api/ai_rail.cpp
@@ -45,7 +45,7 @@
{
if (!::IsValidTile(tile)) return false;
- return ::IsTileType(tile, MP_RAILWAY) && ::IsRailWaypointTile(tile);
+ return ::IsRailWaypointTile(tile);
}
/* static */ bool AIRail::IsRailTypeAvailable(RailType rail_type)
@@ -200,8 +200,7 @@
{
if (!IsRailTile(tile)) return RAILTRACK_INVALID;
- if (IsRailWaypointTile(tile)) return ::GetRailWaypointBits(tile);
- if (IsRailStationTile(tile)) return ::TrackToTrackBits(::GetRailStationTrack(tile));
+ if (IsRailStationTile(tile) || IsRailWaypointTile(tile)) return ::TrackToTrackBits(::GetRailStationTrack(tile));
if (IsLevelCrossingTile(tile)) return ::GetCrossingRailBits(tile);
if (IsRailDepotTile(tile)) return ::TRACK_BIT_NONE;
return ::GetTrackBits(tile);
diff --git a/src/ai/api/ai_waypoint.cpp b/src/ai/api/ai_waypoint.cpp
index 21804dda7..d7d3b396a 100644
--- a/src/ai/api/ai_waypoint.cpp
+++ b/src/ai/api/ai_waypoint.cpp
@@ -22,7 +22,7 @@
{
if (!AIRail::IsRailWaypointTile(tile)) return WAYPOINT_INVALID;
- return ::GetWaypointIndex(tile);
+ return ::GetStationIndex(tile);
}
/* static */ char *AIWaypoint::GetName(WaypointID waypoint_id)
diff --git a/src/ai/api/ai_waypointlist.cpp b/src/ai/api/ai_waypointlist.cpp
index c2d87e6b7..20bc58544 100644
--- a/src/ai/api/ai_waypointlist.cpp
+++ b/src/ai/api/ai_waypointlist.cpp
@@ -13,7 +13,7 @@ AIWaypointList::AIWaypointList()
{
const Waypoint *wp;
FOR_ALL_WAYPOINTS(wp) {
- if (wp->owner == _current_company) this->AddItem(wp->index);
+ if (wp->facilities & FACIL_TRAIN && wp->owner == _current_company) this->AddItem(wp->index);
}
}
diff --git a/src/date.cpp b/src/date.cpp
index b0643701f..4420043ef 100644
--- a/src/date.cpp
+++ b/src/date.cpp
@@ -154,7 +154,6 @@ Date ConvertYMDToDate(Year year, Month month, Day day)
/** Functions used by the IncreaseDate function */
-extern void WaypointsDailyLoop();
extern void EnginesDailyLoop();
extern void DisasterDailyLoop();
extern void IndustryDailyLoop();
@@ -222,7 +221,6 @@ void IncreaseDate()
#endif /* ENABLE_NETWORK */
DisasterDailyLoop();
- WaypointsDailyLoop();
IndustryDailyLoop();
if (_game_mode != GM_MENU) {
diff --git a/src/elrail.cpp b/src/elrail.cpp
index ea0834041..8c6dffffe 100644
--- a/src/elrail.cpp
+++ b/src/elrail.cpp
@@ -81,8 +81,6 @@ static TrackBits GetRailTrackBitsUniversal(TileIndex t, byte *override)
switch (GetRailTileType(t)) {
case RAIL_TILE_NORMAL: case RAIL_TILE_SIGNALS:
return GetTrackBits(t);
- case RAIL_TILE_WAYPOINT:
- return GetRailWaypointBits(t);
default:
return TRACK_BIT_NONE;
}
@@ -101,7 +99,7 @@ static TrackBits GetRailTrackBitsUniversal(TileIndex t, byte *override)
return GetCrossingRailBits(t);
case MP_STATION:
- if (!IsRailwayStation(t)) return TRACK_BIT_NONE;
+ if (!IsRailwayStation(t) && !IsRailWaypoint(t)) return TRACK_BIT_NONE;
if (!HasCatenary(GetRailType(t))) return TRACK_BIT_NONE;
if (!IsStationTileElectrifiable(t)) return TRACK_BIT_NONE;
return TrackToTrackBits(GetRailStationTrack(t));
diff --git a/src/lang/english.txt b/src/lang/english.txt
index e0e6c29de..76a639c51 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -1185,8 +1185,10 @@ STR_HEADING_FOR_WAYPOINT_VEL :{LTBLUE}Heading
STR_GO_TO_WAYPOINT :Go via {WAYPOINT}
STR_GO_NON_STOP_TO_WAYPOINT :Go non-stop via {WAYPOINT}
-STR_WAYPOINTNAME_CITY :Waypoint {TOWN}
-STR_WAYPOINTNAME_CITY_SERIAL :Waypoint {TOWN} #{COMMA}
+STR_WAYPOINTNAME_CITY :{TOWN} Waypoint
+STR_WAYPOINTNAME_CITY_SERIAL :{TOWN} Waypoint #{COMMA}
+STR_BUOYNAME_CITY :{TOWN} Buoy
+STR_BUOYNAME_CITY_SERIAL :{TOWN} Buoy #{COMMA}
STR_LANDINFO_WAYPOINT :Waypoint
STR_WAYPOINT :{WHITE}Waypoint
@@ -2077,15 +2079,9 @@ STR_SV_STNAME_AIRPORT :{STRING1} Airpo
STR_SV_STNAME_OILFIELD :{STRING1} Oilfield
STR_SV_STNAME_MINES :{STRING1} Mines
STR_SV_STNAME_DOCKS :{STRING1} Docks
-STR_SV_STNAME_BUOY_1 :{STRING1} Buoy 1
-STR_SV_STNAME_BUOY_2 :{STRING1} Buoy 2
-STR_SV_STNAME_BUOY_3 :{STRING1} Buoy 3
-STR_SV_STNAME_BUOY_4 :{STRING1} Buoy 4
-STR_SV_STNAME_BUOY_5 :{STRING1} Buoy 5
-STR_SV_STNAME_BUOY_6 :{STRING1} Buoy 6
-STR_SV_STNAME_BUOY_7 :{STRING1} Buoy 7
-STR_SV_STNAME_BUOY_8 :{STRING1} Buoy 8
-STR_SV_STNAME_BUOY_9 :{STRING1} Buoy 9
+STR_SV_STNAME_BUOY :{STRING2}
+STR_SV_STNAME_WAYPOINT :{STRING2}
+##id 0x6020
STR_SV_STNAME_ANNEXE :{STRING1} Annexe
STR_SV_STNAME_SIDINGS :{STRING1} Sidings
STR_SV_STNAME_BRANCH :{STRING1} Branch
diff --git a/src/misc.cpp b/src/misc.cpp
index 6d010c87f..839ee0b5f 100644
--- a/src/misc.cpp
+++ b/src/misc.cpp
@@ -31,7 +31,6 @@ extern TileIndex _cur_tileloop_tile;
extern void MakeNewgameSettingsLive();
void InitializeVehicles();
-void InitializeWaypoints();
void InitializeDepots();
void InitializeEngineRenews();
void InitializeOrders();
@@ -79,7 +78,6 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date)
InitializeEngineRenews();
InitializeVehicles();
- InitializeWaypoints();
InitializeDepots();
InitializeOrders();
InitializeGroup();
diff --git a/src/newgrf_station.cpp b/src/newgrf_station.cpp
index 032e2f5e3..cb3cc0d8c 100644
--- a/src/newgrf_station.cpp
+++ b/src/newgrf_station.cpp
@@ -272,30 +272,20 @@ uint32 GetPlatformInfo(Axis axis, byte tile, int platforms, int length, int x, i
*/
static TileIndex FindRailStationEnd(TileIndex tile, TileIndexDiff delta, bool check_type, bool check_axis)
{
- bool waypoint;
byte orig_type = 0;
Axis orig_axis = AXIS_X;
+ StationID sid = GetStationIndex(tile);
- waypoint = IsTileType(tile, MP_RAILWAY);
-
- if (waypoint) {
- if (check_axis) orig_axis = GetWaypointAxis(tile);
- } else {
- if (check_type) orig_type = GetCustomStationSpecIndex(tile);
- if (check_axis) orig_axis = GetRailStationAxis(tile);
- }
+ if (check_type) orig_type = GetCustomStationSpecIndex(tile);
+ if (check_axis) orig_axis = GetRailStationAxis(tile);
while (true) {
TileIndex new_tile = TILE_ADD(tile, delta);
- if (waypoint) {
- if (!IsRailWaypointTile(new_tile)) break;
- if (check_axis && GetWaypointAxis(new_tile) != orig_axis) break;
- } else {
- if (!IsRailwayStationTile(new_tile)) break;
- if (check_type && GetCustomStationSpecIndex(new_tile) != orig_type) break;
- if (check_axis && GetRailStationAxis(new_tile) != orig_axis) break;
- }
+ if (!IsTileType(new_tile, MP_STATION) || GetStationIndex(new_tile) != sid) break;
+ if (!IsRailwayStation(new_tile) && !IsRailWaypoint(new_tile)) break;
+ if (check_type && GetCustomStationSpecIndex(new_tile) != orig_type) break;
+ if (check_axis && GetRailStationAxis(new_tile) != orig_axis) break;
tile = new_tile;
}
@@ -311,12 +301,11 @@ static uint32 GetPlatformInfoHelper(TileIndex tile, bool check_type, bool check_
int sy = TileY(FindRailStationEnd(tile, TileDiffXY( 0, -1), check_type, check_axis));
int ex = TileX(FindRailStationEnd(tile, TileDiffXY( 1, 0), check_type, check_axis)) + 1;
int ey = TileY(FindRailStationEnd(tile, TileDiffXY( 0, 1), check_type, check_axis)) + 1;
- Axis axis = IsTileType(tile, MP_RAILWAY) ? GetWaypointAxis(tile) : GetRailStationAxis(tile);
tx -= sx; ex -= sx;
ty -= sy; ey -= sy;
- return GetPlatformInfo(axis, IsTileType(tile, MP_RAILWAY) ? 2 : GetStationGfx(tile), ex, ey, tx, ty, centred);
+ return GetPlatformInfo(GetRailStationAxis(tile), GetStationGfx(tile), ex, ey, tx, ty, centred);
}
@@ -330,7 +319,7 @@ static uint32 GetRailContinuationInfo(TileIndex tile)
static const Direction y_dir[8] = { DIR_SE, DIR_NW, DIR_SW, DIR_NE, DIR_S, DIR_W, DIR_E, DIR_N };
static const DiagDirection y_exits[8] = { DIAGDIR_SE, DIAGDIR_NW, DIAGDIR_SW, DIAGDIR_NE, DIAGDIR_SE, DIAGDIR_NW, DIAGDIR_SE, DIAGDIR_NW };
- Axis axis = IsTileType(tile, MP_RAILWAY) ? GetWaypointAxis(tile) : GetRailStationAxis(tile);
+ Axis axis = GetRailStationAxis(tile);
/* Choose appropriate lookup table to use */
const Direction *dir = axis == AXIS_X ? x_dir : y_dir;
@@ -450,12 +439,7 @@ static uint32 StationGetVariable(const ResolverObject *object, byte variable, by
case 0x42: return GetTerrainType(tile) | (GetRailType(tile) << 8);
case 0x43: return st->owner; // Station owner
- case 0x44:
- if (IsRailWaypointTile(tile)) {
- return HasDepotReservation(tile) ? 7 : 4;
- } else {
- return HasStationReservation(tile) ? 7 : 4; // PBS status
- }
+ case 0x44: return HasStationReservation(tile) ? 7 : 4; // PBS status
case 0x45:
if (!HasBit(_svc.valid, 2)) { _svc.v45 = GetRailContinuationInfo(tile); SetBit(_svc.valid, 2); }
return _svc.v45;
@@ -583,7 +567,7 @@ uint32 Waypoint::GetNewGRFVariable(const ResolverObject *object, byte variable,
{
switch (variable) {
case 0x48: return 0; // Accepted cargo types
- case 0x8A: return HVOT_TRAIN;
+ case 0x8A: return HVOT_WAYPOINT;
case 0xF1: return 0; // airport type
case 0xF2: return 0; // truck stop status
case 0xF3: return 0; // bus stop status
@@ -944,20 +928,11 @@ bool DrawStationTile(int x, int y, RailType railtype, Axis axis, StationClassID
const StationSpec *GetStationSpec(TileIndex t)
{
- if (IsRailwayStationTile(t)) {
- if (!IsCustomStationSpecIndex(t)) return NULL;
+ if (!IsCustomStationSpecIndex(t)) return NULL;
- const BaseStation *st = BaseStation::GetByTile(t);
- uint specindex = GetCustomStationSpecIndex(t);
- return specindex < st->num_specs ? st->speclist[specindex].spec : NULL;
- }
-
- if (IsRailWaypointTile(t)) {
- const BaseStation *st = BaseStation::GetByTile(t);
- return st->num_specs != 0 ? st->speclist[1].spec : NULL;
- }
-
- return NULL;
+ const BaseStation *st = BaseStation::GetByTile(t);
+ uint specindex = GetCustomStationSpecIndex(t);
+ return specindex < st->num_specs ? st->speclist[specindex].spec : NULL;
}
diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp
index 0fb5087c0..7e3a890e1 100644
--- a/src/order_cmd.cpp
+++ b/src/order_cmd.cpp
@@ -542,18 +542,19 @@ CommandCost CmdInsertOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
}
case OT_GOTO_WAYPOINT: {
+ const Waypoint *wp = Waypoint::GetIfValid(new_order.GetDestination());
+ if (wp == NULL) return CMD_ERROR;
+
switch (v->type) {
default: return CMD_ERROR;
- case VEH_TRAIN: {
- const Waypoint *wp = Waypoint::GetIfValid(new_order.GetDestination());
- if (wp == NULL || !CheckOwnership(wp->owner)) return CMD_ERROR;
- } break;
+ case VEH_TRAIN:
+ if (!CheckOwnership(wp->owner)) return CMD_ERROR;
+ break;
- case VEH_SHIP: {
- const Station *st = Station::GetIfValid(new_order.GetDestination());
- if (st == NULL || (!CheckOwnership(st->owner) && st->owner != OWNER_NONE)) return CMD_ERROR;
- } break;
+ case VEH_SHIP:
+ if (!CheckOwnership(wp->owner) && wp->owner != OWNER_NONE) return CMD_ERROR;
+ break;
}
/* Order flags can be any of the following for waypoints:
diff --git a/src/order_gui.cpp b/src/order_gui.cpp
index 4548fbbc1..9413788a4 100644
--- a/src/order_gui.cpp
+++ b/src/order_gui.cpp
@@ -253,15 +253,8 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int
break;
case OT_GOTO_WAYPOINT:
- if (v->type == VEH_TRAIN) {
- SetDParam(1, (order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_GO_NON_STOP_TO_WAYPOINT : STR_GO_TO_WAYPOINT);
- SetDParam(2, order->GetDestination());
- } else {
- SetDParam(1, STR_GO_TO_STATION);
- SetDParam(2, STR_ORDER_GO_VIA);
- SetDParam(3, order->GetDestination());
- SetDParam(4, STR_EMPTY);
- }
+ SetDParam(1, (order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS) ? STR_GO_NON_STOP_TO_WAYPOINT : STR_GO_TO_WAYPOINT);
+ SetDParam(2, order->GetDestination());
break;
case OT_CONDITIONAL:
@@ -357,7 +350,7 @@ static Order GetOrderCmdFromTile(const Vehicle *v, TileIndex tile)
return order;
}
- if (IsBuoyTile(tile) && v->type == VEH_SHIP) {
+ if ((IsBuoyTile(tile) && v->type == VEH_SHIP) || (IsRailWaypointTile(tile) && v->type == VEH_TRAIN)) {
order.MakeGoToWaypoint(GetStationIndex(tile));
return order;
}
@@ -775,12 +768,9 @@ public:
this->SetWidgetLoweredState(ORDER_WIDGET_NON_STOP, order->GetNonStopType() & ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
switch (order->GetType()) {
case OT_GOTO_STATION:
- if (!Station::Get(order->GetDestination())->IsBuoy()) {
- this->SetWidgetLoweredState(ORDER_WIDGET_FULL_LOAD, order->GetLoadType() == OLF_FULL_LOAD_ANY);
- this->SetWidgetLoweredState(ORDER_WIDGET_UNLOAD, order->GetUnloadType() == OUFB_UNLOAD);
- break;
- }
- /* Fall-through */
+ this->SetWidgetLoweredState(ORDER_WIDGET_FULL_LOAD, order->GetLoadType() == OLF_FULL_LOAD_ANY);
+ this->SetWidgetLoweredState(ORDER_WIDGET_UNLOAD, order->GetUnloadType() == OUFB_UNLOAD);
+ break;
case OT_GOTO_WAYPOINT:
this->DisableWidget(ORDER_WIDGET_FULL_LOAD_DROPDOWN);
diff --git a/src/pbs.cpp b/src/pbs.cpp
index 1309d01ee..5045fc0f8 100644
--- a/src/pbs.cpp
+++ b/src/pbs.cpp
@@ -26,7 +26,7 @@ TrackBits GetReservedTrackbits(TileIndex t)
break;
case MP_STATION:
- if (IsRailwayStation(t)) return GetStationReservationTrackBits(t);
+ if (IsRailwayStation(t) || IsRailWaypoint(t)) return GetStationReservationTrackBits(t);
break;
case MP_TUNNELBRIDGE:
@@ -99,7 +99,7 @@ bool TryReserveRailTrack(TileIndex tile, Track t)
break;
case MP_STATION:
- if (IsRailwayStation(tile) && !HasStationReservation(tile)) {
+ if ((IsRailwayStation(tile) || IsRailWaypoint(tile)) && !HasStationReservation(tile)) {
SetRailwayStationReservation(tile, true);
MarkTileDirtyByTile(tile); // some GRFs need redraw after reserving track
return true;
@@ -150,7 +150,7 @@ bool TryReserveRailTrack(TileIndex tile, Track t)
break;
case MP_STATION:
- if (IsRailwayStation(tile)) {
+ if (IsRailwayStation(tile) || IsRailWaypoint(tile)) {
SetRailwayStationReservation(tile, false);
MarkTileDirtyByTile(tile);
}
diff --git a/src/rail.cpp b/src/rail.cpp
index 2d7894e24..b5aa09fc8 100644
--- a/src/rail.cpp
+++ b/src/rail.cpp
@@ -155,7 +155,7 @@ RailType GetTileRailType(TileIndex tile)
break;
case MP_STATION:
- if (IsRailwayStationTile(tile)) return GetRailType(tile);
+ if (IsRailwayStation(tile) || IsRailWaypoint(tile)) return GetRailType(tile);
break;
case MP_TUNNELBRIDGE:
diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp
index d3bb22ba1..d7632dd0d 100644
--- a/src/rail_cmd.cpp
+++ b/src/rail_cmd.cpp
@@ -1281,7 +1281,7 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
case MP_RAILWAY:
break;
case MP_STATION:
- if (!IsRailwayStation(tile)) continue;
+ if (!IsRailwayStation(tile) && !IsRailWaypoint(tile)) continue;
break;
case MP_ROAD:
if (!IsLevelCrossing(tile)) continue;
@@ -1329,14 +1329,6 @@ CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
switch (tt) {
case MP_RAILWAY:
switch (GetRailTileType(tile)) {
- case RAIL_TILE_WAYPOINT:
- if (flags & DC_EXEC) {
- /* notify YAPF about the track layout change */
- YapfNotifyTrackLayoutChange(tile, GetRailWaypointTrack(tile));
- }
- cost.AddCost(RailConvertCost(type, totype));
- break;
-
case RAIL_TILE_DEPOT:
if (flags & DC_EXEC) {
/* notify YAPF about the track layout change */
@@ -1501,9 +1493,6 @@ static CommandCost ClearTile_Track(TileIndex tile, DoCommandFlag flags)
case RAIL_TILE_DEPOT:
return RemoveTrainDepot(tile, flags);
- case RAIL_TILE_WAYPOINT:
- return RemoveTrainWaypoint(tile, flags, false);
-
default:
return CMD_ERROR;
}
@@ -1906,7 +1895,7 @@ static void DrawTile_Track(TileInfo *ti)
if (HasSignals(ti->tile)) DrawSignals(ti->tile, rails);
} else {
- /* draw depot/waypoint */
+ /* draw depot */
const DrawTileSprites *dts;
const DrawTileSeqStruct *dtss;
uint32 relocation;
@@ -1914,78 +1903,37 @@ static void DrawTile_Track(TileInfo *ti)
if (ti->tileh != SLOPE_FLAT) DrawFoundation(ti, FOUNDATION_LEVELED);
- if (IsRailDepot(ti->tile)) {
- if (IsInvisibilitySet(TO_BUILDINGS)) {
- /* Draw rail instead of depot */
- dts = &_depot_invisible_gfx_table[GetRailDepotDirection(ti->tile)];
- } else {
- dts = &_depot_gfx_table[GetRailDepotDirection(ti->tile)];
- }
-
- relocation = rti->total_offset;
-
- image = dts->ground.sprite;
- if (image != SPR_FLAT_GRASS_TILE) image += rti->total_offset;
-
- /* adjust ground tile for desert
- * don't adjust for snow, because snow in depots looks weird */
- if (IsSnowRailGround(ti->tile) && _settings_game.game_creation.landscape == LT_TROPIC) {
- if (image != SPR_FLAT_GRASS_TILE) {
- image += rti->snow_offset; // tile with tracks
- } else {
- image = SPR_FLAT_SNOWY_TILE; // flat ground
- }
- }
+ if (IsInvisibilitySet(TO_BUILDINGS)) {
+ /* Draw rail instead of depot */
+ dts = &_depot_invisible_gfx_table[GetRailDepotDirection(ti->tile)];
} else {
- /* look for customization */
- const StationSpec *statspec = GetStationSpec(ti->tile);
-
- if (statspec != NULL) {
- const BaseStation *st = BaseStation::GetByTile(ti->tile);
- uint gfx = 2;
-
- if (HasBit(statspec->callbackmask, CBM_STATION_SPRITE_LAYOUT)) {
- uint16 callback = GetStationCallback(CBID_STATION_SPRITE_LAYOUT, 0, 0, statspec, st, ti->tile);
- if (callback != CALLBACK_FAILED) gfx = callback;
- }
+ dts = &_depot_gfx_table[GetRailDepotDirection(ti->tile)];
+ }
- if (statspec->renderdata == NULL) {
- dts = GetStationTileLayout(STATION_RAIL, gfx);
- } else {
- dts = &statspec->renderdata[(gfx < statspec->tiles ? gfx : 0) + GetWaypointAxis(ti->tile)];
- }
+ relocation = rti->total_offset;
- if (dts != NULL && dts->seq != NULL) {
- relocation = GetCustomStationRelocation(statspec, st, ti->tile);
+ image = dts->ground.sprite;
+ if (image != SPR_FLAT_GRASS_TILE) image += rti->total_offset;
- image = dts->ground.sprite;
- if (HasBit(image, SPRITE_MODIFIER_USE_OFFSET)) {
- image += GetCustomStationGroundRelocation(statspec, st, ti->tile);
- image += rti->custom_ground_offset;
- } else {
- image += rti->total_offset;
- }
-
- pal = dts->ground.pal;
- } else {
- goto default_waypoint;
- }
+ /* adjust ground tile for desert
+ * don't adjust for snow, because snow in depots looks weird */
+ if (IsSnowRailGround(ti->tile) && _settings_game.game_creation.landscape == LT_TROPIC) {
+ if (image != SPR_FLAT_GRASS_TILE) {
+ image += rti->snow_offset; // tile with tracks
} else {
-default_waypoint:
- /* There is no custom layout, fall back to the default graphics */
- dts = GetStationTileLayout(STATION_WAYPOINT, GetWaypointAxis(ti->tile));
- relocation = 0;
- image = dts->ground.sprite + rti->total_offset;
- if (IsSnowRailGround(ti->tile)) image += rti->snow_offset;
+ image = SPR_FLAT_SNOWY_TILE; // flat ground
}
}
DrawGroundSprite(image, GroundSpritePaletteTransform(image, pal, _drawtile_track_palette));
/* PBS debugging, draw reserved tracks darker */
- if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasDepotReservation(ti->tile) &&
- (!IsRailDepot(ti->tile) || GetRailDepotDirection(ti->tile) == DIAGDIR_SW || GetRailDepotDirection(ti->tile) == DIAGDIR_SE)) {
- DrawGroundSprite(GetWaypointAxis(ti->tile) == AXIS_X ? rti->base_sprites.single_y : rti->base_sprites.single_x, PALETTE_CRASH);
+ if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && HasDepotReservation(ti->tile)) {
+ switch (GetRailDepotDirection(ti->tile)) {
+ case DIAGDIR_SW: DrawGroundSprite(rti->base_sprites.single_y, PALETTE_CRASH); break;
+ case DIAGDIR_SE: DrawGroundSprite(rti->base_sprites.single_x, PALETTE_CRASH); break;
+ default: break;
+ }
}
if (HasCatenaryDrawn(GetRailType(ti->tile))) DrawCatenary(ti);
@@ -2292,10 +2240,6 @@ static TrackStatus GetTileTrackStatus_Track(TileIndex tile, TransportType mode,
trackbits = DiagDirToDiagTrackBits(dir);
break;
}
-
- case RAIL_TILE_WAYPOINT:
- trackbits = GetRailWaypointBits(tile);
- break;
}
return CombineTrackStatus(TrackBitsToTrackdirBits(trackbits), red_signals);
@@ -2303,11 +2247,10 @@ static TrackStatus GetTileTrackStatus_Track(TileIndex tile, TransportType mode,
static bool ClickTile_Track(TileIndex tile)
{
- switch (GetRailTileType(tile)) {
- case RAIL_TILE_DEPOT: ShowDepotWindow(tile, VEH_TRAIN); return true;
- case RAIL_TILE_WAYPOINT: ShowWaypointWindow(Waypoint::GetByTile(tile)); return true;
- default: return false;
- }
+ if (!IsRailDepot(tile)) return false;
+
+ ShowDepotWindow(tile, VEH_TRAIN);
+ return true;
}
static void GetTileDesc_Track(TileIndex tile, TileDesc *td)
@@ -2387,10 +2330,8 @@ static void GetTileDesc_Track(TileIndex tile, TileDesc *td)
td->str = STR_RAILROAD_TRAIN_DEPOT;
break;
- case RAIL_TILE_WAYPOINT:
default:
- td->str = STR_LANDINFO_WAYPOINT;
- break;
+ NOT_REACHED();
}
}
@@ -2579,22 +2520,9 @@ static CommandCost TerraformTile_Track(TileIndex tile, DoCommandFlag flags, uint
/* allow terraforming */
return CommandCost(EXPENSES_CONSTRUCTION, was_water ? _price.clear_water : (Money)0);
- } else {
- if (_settings_game.construction.build_on_slopes && AutoslopeEnabled()) {
- switch (GetRailTileType(tile)) {
- case RAIL_TILE_WAYPOINT: {
- CommandCost cost = TestAutoslopeOnRailTile(tile, flags, z_old, tileh_old, z_new, tileh_new, GetRailWaypointBits(tile));
- if (!CmdFailed(cost)) return cost; // allow autoslope
- break;
- }
-
- case RAIL_TILE_DEPOT:
- if (AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRailDepotDirection(tile))) return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
- break;
-
- default: NOT_REACHED();
- }
- }
+ } else if (_settings_game.construction.build_on_slopes && AutoslopeEnabled() &&
+ AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, GetRailDepotDirection(tile))) {
+ return CommandCost(EXPENSES_CONSTRUCTION, _price.terraform);
}
return DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR);
}
diff --git a/src/rail_map.h b/src/rail_map.h
index 1fd3212e6..332ee46fd 100644
--- a/src/rail_map.h
+++ b/src/rail_map.h
@@ -18,7 +18,6 @@
enum RailTileType {
RAIL_TILE_NORMAL = 0, ///< Normal rail tile without signals
RAIL_TILE_SIGNALS = 1, ///< Normal rail tile with signals
- RAIL_TILE_WAYPOINT = 2, ///< Waypoint (X or Y direction)
RAIL_TILE_DEPOT = 3, ///< Depot (one entrance)
};
@@ -83,27 +82,6 @@ static inline void SetHasSignals(TileIndex tile, bool signals)
}
/**
- * Is this rail tile a rail waypoint?
- * @param t the tile to get the information from
- * @pre IsTileType(t, MP_RAILWAY)
- * @return true if and only if the tile is a rail waypoint
- */
-static inline bool IsRailWaypoint(TileIndex t)
-{
- return GetRailTileType(t) == RAIL_TILE_WAYPOINT;
-}
-
-/**
- * Is this tile rail tile and a rail waypoint?
- * @param t the tile to get the information from
- * @return true if and only if the tile is a rail waypoint
- */
-static inline bool IsRailWaypointTile(TileIndex t)
-{
- return IsTileType(t, MP_RAILWAY) && IsRailWaypoint(t);
-}
-
-/**
* Is this rail tile a rail depot?
* @param t the tile to get the information from
* @pre IsTileType(t, MP_RAILWAY)
@@ -203,51 +181,6 @@ static inline Track GetRailDepotTrack(TileIndex t)
/**
- * Returns the axis of the waypoint
- * @param t the tile to get the waypoint axis from
- * @pre IsRailWaypointTile(t)
- * @return the axis of the waypoint
- */
-static inline Axis GetWaypointAxis(TileIndex t)
-{
- return (Axis)GB(_m[t].m5, 0, 1);
-}
-
-/**
- * Returns the track of the waypoint
- * @param t the tile to get the waypoint track from
- * @pre IsRailWaypointTile(t)
- * @return the track of the waypoint
- */
-static inline Track GetRailWaypointTrack(TileIndex t)
-{
- return AxisToTrack(GetWaypointAxis(t));
-}
-
-/**
- * Returns the track bits of the waypoint
- * @param t the tile to get the waypoint track bits from
- * @pre IsRailWaypointTile(t)
- * @return the track bits of the waypoint
- */
-static inline TrackBits GetRailWaypointBits(TileIndex t)
-{
- return TrackToTrackBits(GetRailWaypointTrack(t));
-}
-
-/**
- * Returns waypoint index (for the waypoint pool)
- * @param t the tile to get the waypoint index from
- * @pre IsRailWaypointTile(t)
- * @return the waypoint index
- */
-static inline WaypointID GetWaypointIndex(TileIndex t)
-{
- return (WaypointID)_m[t].m2;
-}
-
-
-/**
* Returns the reserved track bits of the tile
* @pre IsPlainRailTile(t)
* @param t the tile to query
@@ -336,17 +269,6 @@ static inline void SetDepotReservation(TileIndex t, bool b)
}
/**
- * Get the reserved track bits for a waypoint
- * @pre IsRailWaypoint(t)
- * @param t the tile
- * @return reserved track bits
- */
-static inline TrackBits GetWaypointReservationTrackBits(TileIndex t)
-{
- return HasDepotReservation(t) ? GetRailWaypointBits(t) : TRACK_BIT_NONE;
-}
-
-/**
* Get the reserved track bits for a depot
* @pre IsRailDepot(t)
* @param t the tile
@@ -635,17 +557,4 @@ static inline void MakeRailDepot(TileIndex t, Owner o, DiagDirection d, RailType
_me[t].m7 = 0;
}
-
-static inline void MakeRailWaypoint(TileIndex t, Owner o, Axis a, RailType r, uint index)
-{
- SetTileType(t, MP_RAILWAY);
- SetTileOwner(t, o);
- _m[t].m2 = index;
- _m[t].m3 = r;
- _m[t].m4 = 0;
- _m[t].m5 = RAIL_TILE_WAYPOINT << 6 | a;
- SB(_m[t].m6, 2, 4, 0);
- _me[t].m7 = 0;
-}
-
#endif /* RAIL_MAP_H */
diff --git a/src/saveload/afterload.cpp b/src/saveload/afterload.cpp
index 452dbb997..b69ca6e2d 100644
--- a/src/saveload/afterload.cpp
+++ b/src/saveload/afterload.cpp
@@ -606,9 +606,7 @@ bool AfterLoadGame()
switch (GetTileType(t)) {
case MP_STATION: {
Station *st = Station::GetByTile(t);
-
- /* Set up station spread; buoys do not have one */
- if (!IsBuoy(t)) st->rect.BeforeAddTile(t, StationRect::ADD_FORCE);
+ if (st == NULL) break;
switch (GetStationType(t)) {
case STATION_TRUCK:
@@ -987,29 +985,11 @@ bool AfterLoadGame()
FOR_ALL_COMPANIES(c) c->settings.renew_keep_length = false;
}
- /* In version 17, ground type is moved from m2 to m4 for depots and
- * waypoints to make way for storing the index in m2. The custom graphics
- * id which was stored in m4 is now saved as a grf/id reference in the
- * waypoint struct. */
- if (CheckSavegameVersion(17)) {
- Waypoint *wp;
-
- FOR_ALL_WAYPOINTS(wp) {
- if (wp->delete_ctr == 0) {
- if (HasBit(_m[wp->xy].m3, 4)) {
- AllocateSpecToStation(GetCustomStationSpec(STAT_CLASS_WAYP, _m[wp->xy].m4 + 1), wp, true);
- }
-
- /* Move ground type bits from m2 to m4. */
- _m[wp->xy].m4 = GB(_m[wp->xy].m2, 0, 4);
- /* Store waypoint index in the tile. */
- _m[wp->xy].m2 = wp->index;
- }
- }
- } else {
- /* As of version 17, we recalculate the custom graphic ID of waypoints
- * from the GRF ID / station index. */
- AfterLoadWaypoints();
+ if (CheckSavegameVersion(123)) {
+ /* Waypoints became subclasses of stations ... */
+ MoveWaypointsToBaseStations();
+ /* ... and buoys were moved to waypoints. */
+ MoveBuoysToWaypoints();
}
/* From version 15, we moved a semaphore bit from bit 2 to bit 3 in m4, making
@@ -1275,9 +1255,9 @@ bool AfterLoadGame()
/* Buoys do now store the owner of the previous water tile, which can never
* be OWNER_NONE. So replace OWNER_NONE with OWNER_WATER. */
if (CheckSavegameVersion(46)) {
- Station *st;
- FOR_ALL_STATIONS(st) {
- if (st->IsBuoy() && IsTileOwner(st->xy, OWNER_NONE) && TileHeight(st->xy) == 0) SetTileOwner(st->xy, OWNER_WATER);
+ Waypoint *wp;
+ FOR_ALL_WAYPOINTS(wp) {
+ if ((wp->facilities & FACIL_DOCK) != 0 && IsTileOwner(wp->xy, OWNER_NONE) && TileHeight(wp->xy) == 0) SetTileOwner(wp->xy, OWNER_WATER);
}
}
@@ -1487,15 +1467,6 @@ bool AfterLoadGame()
}
if (CheckSavegameVersion(84)) {
- /* Update go to buoy orders because they are just waypoints */
- Order *order;
- FOR_ALL_ORDERS(order) {
- if (order->IsType(OT_GOTO_STATION) && Station::Get(order->GetDestination())->IsBuoy()) {
- order->SetLoadType(OLF_LOAD_IF_POSSIBLE);
- order->SetUnloadType(OUF_UNLOAD_IF_POSSIBLE);
- }
- }
-
/* Set all share owners to INVALID_COMPANY for
* 1) all inactive companies
* (when inactive companies were stored in the savegame - TTD, TTDP and some
@@ -1561,7 +1532,7 @@ bool AfterLoadGame()
if (IsBuoyTile(t)) {
/* reset buoy owner to OWNER_NONE in the station struct
* (even if it is owned by active company) */
- Station::GetByTile(t)->owner = OWNER_NONE;
+ Waypoint::GetByTile(t)->owner = OWNER_NONE;
}
} else if (IsTileType(t, MP_ROAD)) {
/* works for all RoadTileType */
@@ -1805,16 +1776,6 @@ bool AfterLoadGame()
FOR_ALL_STATIONS(st) {
if (!Company::IsValidID(st->owner)) st->owner = OWNER_NONE;
}
-
- /* Give owners to waypoints, based on rail tracks it is sitting on.
- * If none is available, specify OWNER_NONE.
- * This code was in CheckSavegameVersion(101) in the past, but in some cases,
- * the owner of waypoints could be incorrect. */
- Waypoint *wp;
- FOR_ALL_WAYPOINTS(wp) {
- Owner owner = IsTileType(wp->xy, MP_RAILWAY) ? GetTileOwner(wp->xy) : OWNER_NONE;
- wp->owner = Company::IsValidID(owner) ? owner : OWNER_NONE;
- }
}
/* Trains could now stop in a specific location. */
@@ -1913,14 +1874,6 @@ bool AfterLoadGame()
}
s->cargo_type = CT_INVALID;
}
-
- Order *o;
- FOR_ALL_ORDERS(o) {
- /* Buoys are now go to waypoint orders */
- if (!o->IsType(OT_GOTO_STATION) || !Station::Get(o->GetDestination())->IsBuoy()) continue;
-
- o->MakeGoToWaypoint(o->GetDestination());
- }
}
AfterLoadLabelMaps();
@@ -1950,8 +1903,7 @@ void ReloadNewGRFData()
AfterLoadVehicles(false);
StartupEngines();
SetCachedEngineCounts();
- /* update station and waypoint graphics */
- AfterLoadWaypoints();
+ /* update station graphics */
AfterLoadStations();
/* Check and update house and town values */
UpdateHousesAndTowns();
diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp
index 8b3178512..dd44cc4cd 100644
--- a/src/saveload/saveload.cpp
+++ b/src/saveload/saveload.cpp
@@ -41,7 +41,7 @@
#include "saveload_internal.h"
-extern const uint16 SAVEGAME_VERSION = 122;
+extern const uint16 SAVEGAME_VERSION = 123;
SavegameType _savegame_type; ///< type of savegame we are loading
@@ -873,6 +873,7 @@ size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld)
break;
case SL_WRITEBYTE: return 1; // a byte is logically of size 1
case SL_VEH_INCLUDE: return SlCalcObjLength(object, GetVehicleDescription(VEH_END));
+ case SL_ST_INCLUDE: return SlCalcObjLength(object, GetBaseStationDescription());
default: NOT_REACHED();
}
return 0;
@@ -934,6 +935,10 @@ bool SlObjectMember(void *ptr, const SaveLoad *sld)
SlObject(ptr, GetVehicleDescription(VEH_END));
break;
+ case SL_ST_INCLUDE:
+ SlObject(ptr, GetBaseStationDescription());
+ break;
+
default: NOT_REACHED();
}
return true;
diff --git a/src/saveload/saveload.h b/src/saveload/saveload.h
index cd1b9464c..25e1e35b6 100644
--- a/src/saveload/saveload.h
+++ b/src/saveload/saveload.h
@@ -182,6 +182,7 @@ enum SaveLoadTypes {
/* non-normal save-load types */
SL_WRITEBYTE = 8,
SL_VEH_INCLUDE = 9,
+ SL_ST_INCLUDE = 10,
SL_END = 15
};
@@ -235,6 +236,7 @@ typedef SaveLoad SaveLoadGlobVarList;
#define SLE_WRITEBYTEX(offset, something) SLE_GENERALX(SL_WRITEBYTE, offset, 0, 0, something, 0)
#define SLE_VEH_INCLUDEX() SLE_GENERALX(SL_VEH_INCLUDE, 0, 0, 0, 0, SL_MAX_VERSION)
+#define SLE_ST_INCLUDEX() SLE_GENERALX(SL_ST_INCLUDE, 0, 0, 0, 0, SL_MAX_VERSION)
/* End marker */
#define SLE_END() {false, SL_END, 0, 0, 0, 0, NULL}
diff --git a/src/saveload/saveload_internal.h b/src/saveload/saveload_internal.h
index 21030751a..0e5eb791e 100644
--- a/src/saveload/saveload_internal.h
+++ b/src/saveload/saveload_internal.h
@@ -16,7 +16,10 @@ StringID RemapOldStringID(StringID s);
char *CopyFromOldName(StringID id);
void ResetOldNames();
-void AfterLoadWaypoints();
+void MoveBuoysToWaypoints();
+void MoveWaypointsToBaseStations();
+const SaveLoad *GetBaseStationDescription();
+
void AfterLoadVehicles(bool part_of_load);
void AfterLoadStations();
void AfterLoadLabelMaps();
diff --git a/src/saveload/station_sl.cpp b/src/saveload/station_sl.cpp
index c8fbf1624..603be9cfd 100644
--- a/src/saveload/station_sl.cpp
+++ b/src/saveload/station_sl.cpp
@@ -4,27 +4,98 @@
#include "../stdafx.h"
#include "../station_base.h"
+#include "../waypoint.h"
#include "../roadstop_base.h"
+#include "../order_base.h"
+#include "../vehicle_base.h"
#include "../core/bitmath_func.hpp"
#include "../core/alloc_func.hpp"
#include "../variables.h"
#include "../newgrf_station.h"
#include "saveload.h"
+#include "table/strings.h"
+/**
+ * Update the buoy orders to be waypoint orders.
+ * @param o the order 'list' to check.
+ */
+static void UpdateWaypointOrder(Order *o)
+{
+ if (!o->IsType(OT_GOTO_STATION)) return;
-void AfterLoadStations()
+ const Station *st = Station::Get(o->GetDestination());
+ if ((st->had_vehicle_of_type & HVOT_WAYPOINT) == 0) return;
+
+ o->MakeGoToWaypoint(o->GetDestination());
+}
+
+/**
+ * Perform all steps to upgrade from the old station buoys to the new version
+ * that uses waypoints. This includes some old saveload mechanics.
+ */
+void MoveBuoysToWaypoints()
{
- /* Update the speclists of all stations to point to the currently loaded custom stations. */
+ /* Buoy orders become waypoint orders */
+ OrderList *ol;
+ FOR_ALL_ORDER_LISTS(ol) {
+ if (ol->GetFirstSharedVehicle()->type != VEH_SHIP) continue;
+
+ for (Order *o = ol->GetFirstOrder(); o != NULL; o = o->next) UpdateWaypointOrder(o);
+ }
+
+ Vehicle *v;
+ FOR_ALL_VEHICLES(v) {
+ if (v->type != VEH_SHIP) continue;
+
+ UpdateWaypointOrder(&v->current_order);
+ }
+
+ /* Now make the stations waypoints */
Station *st;
FOR_ALL_STATIONS(st) {
+ if ((st->had_vehicle_of_type & HVOT_WAYPOINT) == 0) continue;
+
+ StationID index = st->index;
+ TileIndex xy = st->xy;
+ Town *town = st->town;
+ StringID string_id = st->string_id;
+ char *name = st->name;
+ Date build_date = st->build_date;
+
+ /* Delete the station, so we can make it a real waypoint. */
+ delete st;
+
+ Waypoint *wp = new (index) Waypoint(xy);
+ wp->town = town;
+ wp->string_id = STR_SV_STNAME_BUOY;
+ wp->name = name;
+ wp->delete_ctr = 0; // Just reset delete counter for once.
+ wp->build_date = build_date;
+ wp->owner = OWNER_NONE;
+
+ if (IsInsideBS(string_id, STR_SV_STNAME_BUOY, 9)) wp->town_cn = string_id - STR_SV_STNAME_BUOY;
+
+ if (IsBuoyTile(xy) && GetStationIndex(xy) == index) {
+ wp->facilities |= FACIL_DOCK;
+ }
+ }
+}
+
+void AfterLoadStations()
+{
+ /* Update the speclists of all stations to point to the currently loaded custom stations. */
+ BaseStation *st;
+ FOR_ALL_BASE_STATIONS(st) {
for (uint i = 0; i < st->num_specs; i++) {
if (st->speclist[i].grfid == 0) continue;
st->speclist[i].spec = GetCustomStationSpecByGrf(st->speclist[i].grfid, st->speclist[i].localidx, NULL);
}
- for (CargoID c = 0; c < NUM_CARGO; c++) st->goods[c].cargo.InvalidateCache();
+ if (Station::IsExpected(st)) {
+ for (CargoID c = 0; c < NUM_CARGO; c++) Station::From(st)->goods[c].cargo.InvalidateCache();
+ }
StationUpdateAnimTriggers(st);
}
@@ -48,7 +119,7 @@ static const SaveLoad _roadstop_desc[] = {
SLE_END()
};
-static const SaveLoad _station_desc[] = {
+static const SaveLoad _old_station_desc[] = {
SLE_CONDVAR(Station, xy, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
SLE_CONDVAR(Station, xy, SLE_UINT32, 6, SL_MAX_VERSION),
SLE_CONDNULL(4, 0, 5), ///< bus/lorry tile
@@ -145,78 +216,202 @@ const SaveLoad *GetGoodsDesc()
}
-static void SaveLoad_STNS(Station *st)
+static void Load_STNS()
{
- SlObject(st, _station_desc);
-
- _waiting_acceptance = 0;
-
- uint num_cargo = CheckSavegameVersion(55) ? 12 : NUM_CARGO;
- for (CargoID i = 0; i < num_cargo; i++) {
- GoodsEntry *ge = &st->goods[i];
- SlObject(ge, GetGoodsDesc());
- if (CheckSavegameVersion(68)) {
- SB(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE, 1, HasBit(_waiting_acceptance, 15));
- if (GB(_waiting_acceptance, 0, 12) != 0) {
- /* Don't construct the packet with station here, because that'll fail with old savegames */
- CargoPacket *cp = new CargoPacket();
- /* In old versions, enroute_from used 0xFF as INVALID_STATION */
- cp->source = (CheckSavegameVersion(7) && _cargo_source == 0xFF) ? INVALID_STATION : _cargo_source;
- cp->count = GB(_waiting_acceptance, 0, 12);
- cp->days_in_transit = _cargo_days;
- cp->feeder_share = _cargo_feeder_share;
- cp->source_xy = _cargo_source_xy;
- cp->days_in_transit = _cargo_days;
- cp->feeder_share = _cargo_feeder_share;
- SB(ge->acceptance_pickup, GoodsEntry::PICKUP, 1, 1);
- ge->cargo.Append(cp);
+ int index;
+ while ((index = SlIterateArray()) != -1) {
+ Station *st = new (index) Station();
+
+ SlObject(st, _old_station_desc);
+
+ _waiting_acceptance = 0;
+
+ uint num_cargo = CheckSavegameVersion(55) ? 12 : NUM_CARGO;
+ for (CargoID i = 0; i < num_cargo; i++) {
+ GoodsEntry *ge = &st->goods[i];
+ SlObject(ge, GetGoodsDesc());
+ if (CheckSavegameVersion(68)) {
+ SB(ge->acceptance_pickup, GoodsEntry::ACCEPTANCE, 1, HasBit(_waiting_acceptance, 15));
+ if (GB(_waiting_acceptance, 0, 12) != 0) {
+ /* Don't construct the packet with station here, because that'll fail with old savegames */
+ CargoPacket *cp = new CargoPacket();
+ /* In old versions, enroute_from used 0xFF as INVALID_STATION */
+ cp->source = (CheckSavegameVersion(7) && _cargo_source == 0xFF) ? INVALID_STATION : _cargo_source;
+ cp->count = GB(_waiting_acceptance, 0, 12);
+ cp->days_in_transit = _cargo_days;
+ cp->feeder_share = _cargo_feeder_share;
+ cp->source_xy = _cargo_source_xy;
+ cp->days_in_transit = _cargo_days;
+ cp->feeder_share = _cargo_feeder_share;
+ SB(ge->acceptance_pickup, GoodsEntry::PICKUP, 1, 1);
+ ge->cargo.Append(cp);
+ }
}
}
- }
- if (st->num_specs != 0) {
- /* Allocate speclist memory when loading a game */
- if (st->speclist == NULL) st->speclist = CallocT<StationSpecList>(st->num_specs);
- for (uint i = 0; i < st->num_specs; i++) {
- SlObject(&st->speclist[i], _station_speclist_desc);
+ if (st->num_specs != 0) {
+ /* Allocate speclist memory when loading a game */
+ st->speclist = CallocT<StationSpecList>(st->num_specs);
+ for (uint i = 0; i < st->num_specs; i++) {
+ SlObject(&st->speclist[i], _station_speclist_desc);
+ }
}
}
}
-static void Save_STNS()
+void Ptrs_STNS()
{
+ /* Don't run when savegame version is higher than or equal to 123. */
+ if (!CheckSavegameVersion(123)) return;
+
Station *st;
- /* Write the stations */
FOR_ALL_STATIONS(st) {
+ if (!CheckSavegameVersion(68)) {
+ for (CargoID i = 0; i < NUM_CARGO; i++) {
+ GoodsEntry *ge = &st->goods[i];
+ SlObject(ge, GetGoodsDesc());
+ }
+ }
+ SlObject(st, _old_station_desc);
+ }
+}
+
+
+static const SaveLoad _base_station_desc[] = {
+ SLE_VAR(BaseStation, xy, SLE_UINT32),
+ SLE_REF(BaseStation, town, REF_TOWN),
+ SLE_VAR(BaseStation, string_id, SLE_STRINGID),
+ SLE_STR(BaseStation, name, SLE_STR, 0),
+ SLE_VAR(BaseStation, delete_ctr, SLE_UINT8),
+ SLE_VAR(BaseStation, owner, SLE_UINT8),
+ SLE_VAR(BaseStation, facilities, SLE_UINT8),
+ SLE_VAR(BaseStation, build_date, SLE_INT32),
+
+ /* Used by newstations for graphic variations */
+ SLE_VAR(BaseStation, random_bits, SLE_UINT16),
+ SLE_VAR(BaseStation, waiting_triggers, SLE_UINT8),
+ SLE_VAR(BaseStation, num_specs, SLE_UINT8),
+
+ SLE_END()
+};
+
+static const SaveLoad _station_desc[] = {
+ SLE_WRITEBYTE(Station, facilities, FACIL_NONE),
+ SLE_ST_INCLUDEX(),
+
+ SLE_VAR(Station, train_tile, SLE_UINT32),
+ SLE_VAR(Station, trainst_w, SLE_UINT8),
+ SLE_VAR(Station, trainst_h, SLE_UINT8),
+
+ SLE_REF(Station, bus_stops, REF_ROADSTOPS),
+ SLE_REF(Station, truck_stops, REF_ROADSTOPS),
+ SLE_VAR(Station, dock_tile, SLE_UINT32),
+ SLE_VAR(Station, airport_tile, SLE_UINT32),
+ SLE_VAR(Station, airport_type, SLE_UINT8),
+ SLE_VAR(Station, airport_flags, SLE_UINT64),
+
+ SLE_VAR(Station, indtype, SLE_UINT8),
+
+ SLE_VAR(Station, time_since_load, SLE_UINT8),
+ SLE_VAR(Station, time_since_unload, SLE_UINT8),
+ SLE_VAR(Station, last_vehicle_type, SLE_UINT8),
+ SLE_VAR(Station, had_vehicle_of_type, SLE_UINT8),
+ SLE_LST(Station, loading_vehicles, REF_VEHICLE),
+
+ SLE_END()
+};
+
+static const SaveLoad _waypoint_desc[] = {
+ SLE_WRITEBYTE(Waypoint, facilities, FACIL_WAYPOINT),
+ SLE_ST_INCLUDEX(),
+
+ SLE_VAR(Waypoint, town_cn, SLE_UINT16),
+
+ SLE_END()
+};
+
+/**
+ * Get the base station description to be used for SL_ST_INCLUDE
+ * @return the base station description.
+ */
+const SaveLoad *GetBaseStationDescription()
+{
+ return _base_station_desc;
+}
+
+static void RealSave_STNN(BaseStation *bst)
+{
+ bool waypoint = (bst->facilities & FACIL_WAYPOINT) != 0;
+ SlObject(bst, waypoint ? _waypoint_desc : _station_desc);
+
+ if (!waypoint) {
+ Station *st = Station::From(bst);
+ for (CargoID i = 0; i < NUM_CARGO; i++) {
+ SlObject(&st->goods[i], GetGoodsDesc());
+ }
+ }
+
+ for (uint i = 0; i < bst->num_specs; i++) {
+ SlObject(&bst->speclist[i], _station_speclist_desc);
+ }
+}
+
+static void Save_STNN()
+{
+ BaseStation *st;
+ /* Write the stations */
+ FOR_ALL_BASE_STATIONS(st) {
SlSetArrayIndex(st->index);
- SlAutolength((AutolengthProc*)SaveLoad_STNS, st);
+ SlAutolength((AutolengthProc*)RealSave_STNN, st);
}
}
-static void Load_STNS()
+static void Load_STNN()
{
int index;
+
while ((index = SlIterateArray()) != -1) {
- Station *st = new (index) Station();
+ bool waypoint = (SlReadByte() & FACIL_WAYPOINT) != 0;
- SaveLoad_STNS(st);
+ BaseStation *bst = waypoint ? (BaseStation *)new (index) Waypoint() : new (index) Station();
+ SlObject(bst, waypoint ? _waypoint_desc : _station_desc);
+
+ if (!waypoint) {
+ Station *st = Station::From(bst);
+ for (CargoID i = 0; i < NUM_CARGO; i++) {
+ SlObject(&st->goods[i], GetGoodsDesc());
+ }
+ }
+
+ if (bst->num_specs != 0) {
+ /* Allocate speclist memory when loading a game */
+ bst->speclist = CallocT<StationSpecList>(bst->num_specs);
+ for (uint i = 0; i < bst->num_specs; i++) {
+ SlObject(&bst->speclist[i], _station_speclist_desc);
+ }
+ }
}
}
-void Ptrs_STNS()
+static void Ptrs_STNN()
{
+ /* Don't run when savegame version lower than 123. */
+ if (CheckSavegameVersion(123)) return;
+
Station *st;
FOR_ALL_STATIONS(st) {
- if (!CheckSavegameVersion(68)) {
- for (CargoID i = 0; i < NUM_CARGO; i++) {
- GoodsEntry *ge = &st->goods[i];
- SlObject(ge, GetGoodsDesc());
- }
+ for (CargoID i = 0; i < NUM_CARGO; i++) {
+ GoodsEntry *ge = &st->goods[i];
+ SlObject(ge, GetGoodsDesc());
}
SlObject(st, _station_desc);
}
-}
+ Waypoint *wp;
+ FOR_ALL_WAYPOINTS(wp) {
+ SlObject(wp, _waypoint_desc);
+ }
+}
static void Save_ROADSTOP()
{
@@ -248,6 +443,7 @@ static void Ptrs_ROADSTOP()
}
extern const ChunkHandler _station_chunk_handlers[] = {
- { 'STNS', Save_STNS, Load_STNS, Ptrs_STNS, CH_ARRAY },
+ { 'STNS', NULL, Load_STNS, Ptrs_STNS, CH_ARRAY },
+ { 'STNN', Save_STNN, Load_STNN, Ptrs_STNN, CH_ARRAY },
{ 'ROAD', Save_ROADSTOP, Load_ROADSTOP, Ptrs_ROADSTOP, CH_ARRAY | CH_LAST},
};
diff --git a/src/saveload/waypoint_sl.cpp b/src/saveload/waypoint_sl.cpp
index 780271068..94e88996f 100644
--- a/src/saveload/waypoint_sl.cpp
+++ b/src/saveload/waypoint_sl.cpp
@@ -5,120 +5,187 @@
#include "../stdafx.h"
#include "../waypoint.h"
#include "../newgrf_station.h"
+#include "../vehicle_base.h"
#include "../town.h"
+#include "../station_map.h"
#include "table/strings.h"
#include "saveload.h"
#include "saveload_internal.h"
+/** Helper structure to convert from the old waypoint system. */
+struct OldWaypoint {
+ size_t index;
+ TileIndex xy;
+ TownID town_index;
+ Town *town;
+ uint16 town_cn;
+ StringID string_id;
+ char *name;
+ uint8 delete_ctr;
+ Date build_date;
+ uint8 localidx;
+ uint32 grfid;
+ const StationSpec *spec;
+ OwnerByte owner;
+
+ size_t new_index;
+};
+
+/** Temporary array with old waypoints. */
+static SmallVector<OldWaypoint, 16> _old_waypoints;
+
/**
- * Update waypoint graphics id against saved GRFID/localidx.
- * This is to ensure the chosen graphics are correct if GRF files are changed.
+ * Update the waypoint orders to get the new waypoint ID.
+ * @param o the order 'list' to check.
*/
-void AfterLoadWaypoints()
+static void UpdateWaypointOrder(Order *o)
{
- Waypoint *wp;
+ if (!o->IsType(OT_GOTO_WAYPOINT)) return;
- FOR_ALL_WAYPOINTS(wp) {
- if (wp->num_specs == 0) continue;
+ for (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) {
+ if (wp->index != o->GetDestination()) continue;
- for (uint i = 0; i < GetNumCustomStations(STAT_CLASS_WAYP); i++) {
- const StationSpec *statspec = GetCustomStationSpec(STAT_CLASS_WAYP, i);
- if (statspec != NULL && statspec->grffile->grfid == wp->speclist[1].grfid && statspec->localidx == wp->speclist[1].localidx) {
- wp->speclist[1].spec = statspec;
- break;
+ o->SetDestination(wp->new_index);
+ return;
+ }
+}
+
+/**
+ * Perform all steps to upgrade from the old waypoints to the new version
+ * that uses station. This includes some old saveload mechanics.
+ */
+void MoveWaypointsToBaseStations()
+{
+ /* In version 17, ground type is moved from m2 to m4 for depots and
+ * waypoints to make way for storing the index in m2. The custom graphics
+ * id which was stored in m4 is now saved as a grf/id reference in the
+ * waypoint struct. */
+ if (CheckSavegameVersion(17)) {
+ for (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) {
+ if (wp->delete_ctr == 0 && HasBit(_m[wp->xy].m3, 4)) {
+ wp->spec = GetCustomStationSpec(STAT_CLASS_WAYP, _m[wp->xy].m4 + 1);
+ }
+ }
+ } else {
+ /* As of version 17, we recalculate the custom graphic ID of waypoints
+ * from the GRF ID / station index. */
+ for (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) {
+ for (uint i = 0; i < GetNumCustomStations(STAT_CLASS_WAYP); i++) {
+ const StationSpec *statspec = GetCustomStationSpec(STAT_CLASS_WAYP, i);
+ if (statspec != NULL && statspec->grffile->grfid == wp->grfid && statspec->localidx == wp->localidx) {
+ wp->spec = statspec;
+ break;
+ }
}
}
}
-}
-static uint16 _waypoint_town_index;
-static StringID _waypoint_string_id;
-static StationSpecList _waypoint_spec;
-
-static const SaveLoad _waypoint_desc[] = {
- SLE_CONDVAR(Waypoint, xy, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
- SLE_CONDVAR(Waypoint, xy, SLE_UINT32, 6, SL_MAX_VERSION),
- SLEG_CONDVAR(_waypoint_town_index, SLE_UINT16, 12, 121),
- SLE_CONDREF(Waypoint, town, REF_TOWN, 122, SL_MAX_VERSION),
- SLE_CONDVAR(Waypoint, town_cn, SLE_FILE_U8 | SLE_VAR_U16, 12, 88),
- SLE_CONDVAR(Waypoint, town_cn, SLE_UINT16, 89, SL_MAX_VERSION),
- SLEG_CONDVAR(_waypoint_string_id, SLE_STRINGID, 0, 83),
- SLE_CONDSTR(Waypoint, name, SLE_STR, 0, 84, SL_MAX_VERSION),
- SLE_VAR(Waypoint, delete_ctr, SLE_UINT8),
-
- SLE_CONDVAR(Waypoint, build_date, SLE_FILE_U16 | SLE_VAR_I32, 3, 30),
- SLE_CONDVAR(Waypoint, build_date, SLE_INT32, 31, SL_MAX_VERSION),
- SLEG_CONDVAR(_waypoint_spec.localidx, SLE_UINT8, 3, SL_MAX_VERSION),
- SLEG_CONDVAR(_waypoint_spec.grfid, SLE_UINT32, 17, SL_MAX_VERSION),
- SLE_CONDVAR(Waypoint, owner, SLE_UINT8, 101, SL_MAX_VERSION),
+ /* All saveload conversions have been done. Create the new waypoints! */
+ for (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) {
+ Waypoint *new_wp = new Waypoint(wp->xy);
+ new_wp->town = wp->town;
+ new_wp->town_cn = wp->town_cn;
+ new_wp->name = wp->name;
+ new_wp->delete_ctr = 0; // Just reset delete counter for once.
+ new_wp->build_date = wp->build_date;
+ new_wp->owner = wp->owner;
- SLE_END()
-};
+ new_wp->string_id = STR_SV_STNAME_WAYPOINT;
-static void Save_WAYP()
-{
- Waypoint *wp;
+ TileIndex t = wp->xy;
+ if (IsTileType(t, MP_RAILWAY) && GetRailTileType(t) == 2 /* RAIL_TILE_WAYPOINT */ && _m[t].m2 == wp->index) {
+ /* The tile might've been reserved! */
+ bool reserved = !CheckSavegameVersion(100) && HasBit(_m[t].m5, 4);
+
+ /* The tile really has our waypoint, so reassign the map array */
+ MakeRailWaypoint(t, GetTileOwner(t), new_wp->index, (Axis)GB(_m[t].m5, 0, 1), 0, GetRailType(t));
+ new_wp->facilities |= FACIL_TRAIN;
+ new_wp->owner = GetTileOwner(t);
- FOR_ALL_WAYPOINTS(wp) {
- if (wp->num_specs == 0) {
- _waypoint_spec.grfid = 0;
- } else {
- _waypoint_spec = wp->speclist[1];
+ SetRailwayStationReservation(t, reserved);
+
+ if (wp->spec != NULL) {
+ SetCustomStationSpecIndex(t, AllocateSpecToStation(wp->spec, new_wp, true));
+ }
}
- SlSetArrayIndex(wp->index);
- SlObject(wp, _waypoint_desc);
+ wp->new_index = new_wp->index;
}
+
+ /* Update the orders of vehicles */
+ OrderList *ol;
+ FOR_ALL_ORDER_LISTS(ol) {
+ if (ol->GetFirstSharedVehicle()->type != VEH_TRAIN) continue;
+
+ for (Order *o = ol->GetFirstOrder(); o != NULL; o = o->next) UpdateWaypointOrder(o);
+ }
+
+ Vehicle *v;
+ FOR_ALL_VEHICLES(v) {
+ if (v->type != VEH_TRAIN) continue;
+
+ UpdateWaypointOrder(&v->current_order);
+ }
+
+ _old_waypoints.Reset();
}
+static const SaveLoad _old_waypoint_desc[] = {
+ SLE_CONDVAR(OldWaypoint, xy, SLE_FILE_U16 | SLE_VAR_U32, 0, 5),
+ SLE_CONDVAR(OldWaypoint, xy, SLE_UINT32, 6, SL_MAX_VERSION),
+ SLE_CONDVAR(OldWaypoint, town_index, SLE_UINT16, 12, 121),
+ SLE_CONDREF(OldWaypoint, town, REF_TOWN, 122, SL_MAX_VERSION),
+ SLE_CONDVAR(OldWaypoint, town_cn, SLE_FILE_U8 | SLE_VAR_U16, 12, 88),
+ SLE_CONDVAR(OldWaypoint, town_cn, SLE_UINT16, 89, SL_MAX_VERSION),
+ SLE_CONDVAR(OldWaypoint, string_id, SLE_STRINGID, 0, 83),
+ SLE_CONDSTR(OldWaypoint, name, SLE_STR, 0, 84, SL_MAX_VERSION),
+ SLE_VAR(OldWaypoint, delete_ctr, SLE_UINT8),
+
+ SLE_CONDVAR(OldWaypoint, build_date, SLE_FILE_U16 | SLE_VAR_I32, 3, 30),
+ SLE_CONDVAR(OldWaypoint, build_date, SLE_INT32, 31, SL_MAX_VERSION),
+ SLE_CONDVAR(OldWaypoint, localidx, SLE_UINT8, 3, SL_MAX_VERSION),
+ SLE_CONDVAR(OldWaypoint, grfid, SLE_UINT32, 17, SL_MAX_VERSION),
+ SLE_CONDVAR(OldWaypoint, owner, SLE_UINT8, 101, SL_MAX_VERSION),
+
+ SLE_END()
+};
+
static void Load_WAYP()
{
+ /* Precaution for when loading failed and it didn't get cleared */
+ _old_waypoints.Clear();
+
int index;
while ((index = SlIterateArray()) != -1) {
- _waypoint_string_id = 0;
- _waypoint_town_index = 0;
- _waypoint_spec.grfid = 0;
-
- Waypoint *wp = new (index) Waypoint();
- SlObject(wp, _waypoint_desc);
+ OldWaypoint *wp = _old_waypoints.Append();
+ memset(wp, 0, sizeof(*wp));
- wp->facilities |= FACIL_TRAIN;
-
- if (_waypoint_spec.grfid != 0) {
- wp->num_specs = 2;
- wp->speclist = CallocT<StationSpecList>(2);
- wp->speclist[1] = _waypoint_spec;
- }
-
- if (CheckSavegameVersion(84)) wp->name = (char *)(size_t)_waypoint_string_id;
- if (CheckSavegameVersion(122)) wp->town = (Town *)(size_t)_waypoint_town_index;
+ wp->index = index;
+ SlObject(wp, _old_waypoint_desc);
}
}
static void Ptrs_WAYP()
{
- Waypoint *wp;
-
- FOR_ALL_WAYPOINTS(wp) {
- SlObject(wp, _waypoint_desc);
+ for (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) {
+ SlObject(wp, _old_waypoint_desc);
- StringID sid = (StringID)(size_t)wp->name;
if (CheckSavegameVersion(12)) {
- wp->town_cn = (sid & 0xC000) == 0xC000 ? (sid >> 8) & 0x3F : 0;
+ wp->town_cn = (wp->string_id & 0xC000) == 0xC000 ? (wp->string_id >> 8) & 0x3F : 0;
wp->town = ClosestTownFromTile(wp->xy, UINT_MAX);
} else if (CheckSavegameVersion(122)) {
/* Only for versions 12 .. 122 */
- wp->town = Town::Get((size_t)wp->town);
+ wp->town = Town::Get(wp->town_index);
}
if (CheckSavegameVersion(84)) {
- wp->name = CopyFromOldName(sid);
+ wp->name = CopyFromOldName(wp->string_id);
}
}
}
extern const ChunkHandler _waypoint_chunk_handlers[] = {
- { 'CHKP', Save_WAYP, Load_WAYP, Ptrs_WAYP, CH_ARRAY | CH_LAST},
+ { 'CHKP', NULL, Load_WAYP, Ptrs_WAYP, CH_ARRAY | CH_LAST},
};
diff --git a/src/signal.cpp b/src/signal.cpp
index 187227b40..50f459e2c 100644
--- a/src/signal.cpp
+++ b/src/signal.cpp
@@ -288,14 +288,6 @@ static SigFlags ExploreSegment(Owner owner)
}
}
- if (GetRailTileType(tile) == RAIL_TILE_WAYPOINT) {
- if (GetWaypointAxis(tile) != DiagDirToAxis(enterdir)) continue;
- if (!(flags & SF_TRAIN) && HasVehicleOnPos(tile, NULL, &TrainOnTileEnum)) flags |= SF_TRAIN;
- tile += TileOffsByDiagDir(exitdir);
- /* enterdir and exitdir stay the same */
- break;
- }
-
TrackBits tracks = GetTrackBits(tile); // trackbits of tile
TrackBits tracks_masked = (TrackBits)(tracks & _enterdir_to_trackbits[enterdir]); // only incidating trackbits
diff --git a/src/station.cpp b/src/station.cpp
index 91605fda2..456862d38 100644
--- a/src/station.cpp
+++ b/src/station.cpp
@@ -50,12 +50,6 @@ Station::Station(TileIndex tile) :
/* this->random_bits is set in Station::AddFacility() */
}
-/* static */ BaseStation *BaseStation::GetByTile(TileIndex tile)
-{
- if (IsRailWaypointTile(tile)) return Waypoint::GetByTile(tile);
- return Station::GetByTile(tile);
-}
-
/**
* Clean up a station by clearing vehicle orders and invalidating windows.
* Aircraft-Hangar orders need special treatment here, as the hangars are
diff --git a/src/station_base.h b/src/station_base.h
index 18f7c9ca5..f4f142287 100644
--- a/src/station_base.h
+++ b/src/station_base.h
@@ -21,7 +21,7 @@
#include "station_map.h"
#include <list>
-typedef Pool<Station, StationID, 32, 64000> StationPool;
+typedef Pool<BaseStation, StationID, 32, 64000> StationPool;
extern StationPool _station_pool;
static const byte INITIAL_STATION_RATING = 175;
@@ -85,7 +85,7 @@ struct TileArea {
};
/** Base class for all station-ish types */
-struct BaseStation {
+struct BaseStation : StationPool::PoolItem<&_station_pool> {
TileIndex xy; ///< Base tile of the station
ViewportSign sign; ///< NOSAVE: Dimensions of sign
byte delete_ctr; ///< Delete counter. If greater than 0 then it is decremented until it reaches 0; the waypoint is then is deleted.
@@ -144,9 +144,14 @@ struct BaseStation {
* @param tile The tile to get the base station from.
* @return the station associated with that tile.
*/
- static BaseStation *GetByTile(TileIndex tile);
+ static FORCEINLINE BaseStation *GetByTile(TileIndex tile)
+ {
+ return BaseStation::Get(GetStationIndex(tile));
+ }
};
+#define FOR_ALL_BASE_STATIONS(var) FOR_ALL_ITEMS_FROM(BaseStation, station_index, var, 0)
+
/**
* Class defining several overloaded accessors so we don't
* have to cast base stations that often
@@ -176,6 +181,44 @@ struct SpecializedStation : public BaseStation {
}
/**
+ * Tests whether given index is a valid index for station of this type
+ * @param index tested index
+ * @return is this index valid index of T?
+ */
+ static FORCEINLINE bool IsValidID(size_t index)
+ {
+ return BaseStation::IsValidID(index) && IsExpected(BaseStation::Get(index));
+ }
+
+ /**
+ * Gets station with given index
+ * @return pointer to station with given index casted to T *
+ */
+ static FORCEINLINE T *Get(size_t index)
+ {
+ return (T *)BaseStation::Get(index);
+ }
+
+ /**
+ * Returns station if the index is a valid index for this station type
+ * @return pointer to station with given index if it's a station of this type
+ */
+ static FORCEINLINE T *GetIfValid(size_t index)
+ {
+ return IsValidID(index) ? Get(index) : NULL ;
+ }
+
+ /**
+ * Get the station belonging to a specific tile.
+ * @param tile The tile to get the station from.
+ * @return the station associated with that tile.
+ */
+ static FORCEINLINE T *GetByTile(TileIndex tile)
+ {
+ return GetIfValid(GetStationIndex(tile));
+ }
+
+ /**
* Converts a BaseStation to SpecializedStation with type checking.
* @param st BaseStation pointer
* @return pointer to SpecializedStation
@@ -198,11 +241,13 @@ struct SpecializedStation : public BaseStation {
}
};
+#define FOR_ALL_BASE_STATIONS_OF_TYPE(name, var) FOR_ALL_ITEMS_FROM(name, station_index, var, 0) if (name::IsExpected(var))
+
typedef SmallVector<Industry *, 2> IndustryVector;
/** Station data structure */
-struct Station : StationPool::PoolItem<&_station_pool>, SpecializedStation<Station, false> {
+struct Station : SpecializedStation<Station, false> {
public:
RoadStop *GetPrimaryRoadStop(RoadStopType type) const
{
@@ -274,24 +319,9 @@ public:
/* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
- /**
- * Determines whether a station is a buoy only.
- * @todo Ditch this encoding of buoys
- */
- FORCEINLINE bool IsBuoy() const
- {
- return (this->had_vehicle_of_type & HVOT_BUOY) != 0;
- }
-
- static FORCEINLINE Station *GetByTile(TileIndex tile)
- {
- return Station::Get(GetStationIndex(tile));
- }
-
static void PostDestructor(size_t index);
};
-#define FOR_ALL_STATIONS_FROM(var, start) FOR_ALL_ITEMS_FROM(Station, station_index, var, start)
-#define FOR_ALL_STATIONS(var) FOR_ALL_STATIONS_FROM(var, 0)
+#define FOR_ALL_STATIONS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Station, var)
#endif /* STATION_BASE_H */
diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp
index d0d4c2b4d..a38bf064b 100644
--- a/src/station_cmd.cpp
+++ b/src/station_cmd.cpp
@@ -197,7 +197,6 @@ enum StationNaming {
STATIONNAMING_AIRPORT,
STATIONNAMING_OILRIG,
STATIONNAMING_DOCK,
- STATIONNAMING_BUOY,
STATIONNAMING_HELIPORT,
};
@@ -239,7 +238,6 @@ static StringID GenerateStationName(Station *st, TileIndex tile, StationNaming n
1U << M(STR_SV_STNAME_AIRPORT), // STATIONNAMING_AIRPORT
1U << M(STR_SV_STNAME_OILFIELD), // STATIONNAMING_OILRIG
1U << M(STR_SV_STNAME_DOCKS), // STATIONNAMING_DOCK
- 0x1FFU << M(STR_SV_STNAME_BUOY_1), // STATIONNAMING_BUOY
1U << M(STR_SV_STNAME_HELIPORT), // STATIONNAMING_HELIPORT
};
@@ -266,24 +264,22 @@ static StringID GenerateStationName(Station *st, TileIndex tile, StationNaming n
}
}
- if (name_class != STATIONNAMING_BUOY) {
- TileIndex indtile = tile;
- StationNameInformation sni = { free_names, indtypes };
- if (CircularTileSearch(&indtile, 7, FindNearIndustryName, &sni)) {
- /* An industry has been found nearby */
- IndustryType indtype = GetIndustryType(indtile);
- const IndustrySpec *indsp = GetIndustrySpec(indtype);
- /* STR_NULL means it only disables oil rig/mines */
- if (indsp->station_name != STR_NULL) {
- st->indtype = indtype;
- return STR_SV_STNAME_FALLBACK;
- }
+ TileIndex indtile = tile;
+ StationNameInformation sni = { free_names, indtypes };
+ if (CircularTileSearch(&indtile, 7, FindNearIndustryName, &sni)) {
+ /* An industry has been found nearby */
+ IndustryType indtype = GetIndustryType(indtile);
+ const IndustrySpec *indsp = GetIndustrySpec(indtype);
+ /* STR_NULL means it only disables oil rig/mines */
+ if (indsp->station_name != STR_NULL) {
+ st->indtype = indtype;
+ return STR_SV_STNAME_FALLBACK;
}
-
- /* Oil rigs/mines name could be marked not free by looking for a near by industry. */
- free_names = sni.free_names;
}
+ /* Oil rigs/mines name could be marked not free by looking for a near by industry. */
+ free_names = sni.free_names;
+
/* check default names */
uint32 tmp = free_names & _gen_station_name_bits[name_class];
if (tmp != 0) return STR_SV_STNAME + FindFirstBit(tmp);
@@ -540,9 +536,6 @@ CargoArray GetAcceptanceAroundTiles(TileIndex tile, int w, int h, int rad)
*/
static void UpdateStationAcceptance(Station *st, bool show_msg)
{
- /* Don't update acceptance for a buoy */
- if (st->IsBuoy()) return;
-
/* old accepted goods types */
uint old_acc = GetAcceptanceMask(st);
@@ -1963,31 +1956,23 @@ CommandCost CmdBuildBuoy(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
if (GetTileSlope(tile, NULL) != SLOPE_FLAT) return_cmd_error(STR_ERROR_SITE_UNSUITABLE);
/* allocate and initialize new station */
- if (!Station::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_STATIONS_LOADING);
+ if (!Waypoint::CanAllocateItem()) return_cmd_error(STR_ERROR_TOO_MANY_STATIONS_LOADING);
if (flags & DC_EXEC) {
- Station *st = new Station(tile);
+ Waypoint *st = new Waypoint(tile);
- st->town = ClosestTownFromTile(tile, UINT_MAX);
- st->string_id = GenerateStationName(st, tile, STATIONNAMING_BUOY);
+ st->string_id = STR_SV_STNAME_BUOY;
- if (Company::IsValidID(_current_company)) {
- SetBit(st->town->have_ratings, _current_company);
- }
- st->dock_tile = tile;
st->facilities |= FACIL_DOCK;
- /* Buoys are marked in the Station struct by this flag. Yes, it is this
- * braindead.. */
- st->had_vehicle_of_type |= HVOT_BUOY;
st->owner = OWNER_NONE;
st->build_date = _date;
+ if (st->town == NULL) MakeDefaultWaypointName(st);
+
MakeBuoy(tile, st->index, GetWaterClass(tile));
st->UpdateVirtCoord();
- UpdateStationAcceptance(st, false);
- st->RecomputeIndustriesNear();
InvalidateWindowData(WC_STATION_LIST, st->owner, 0);
InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS);
}
@@ -2008,7 +1993,7 @@ bool HasStationInUse(StationID station, CompanyID company)
if (company == INVALID_COMPANY || v->owner == company) {
const Order *order;
FOR_VEHICLE_ORDERS(v, order) {
- if (order->IsType(OT_GOTO_STATION) && order->GetDestination() == station) {
+ if ((order->IsType(OT_GOTO_STATION) || order->IsType(OT_GOTO_WAYPOINT)) && order->GetDestination() == station) {
return true;
}
}
@@ -2028,18 +2013,14 @@ static CommandCost RemoveBuoy(TileIndex tile, DoCommandFlag flags)
/* XXX: strange stuff, allow clearing as invalid company when clearing landscape */
if (!Company::IsValidID(_current_company) && !(flags & DC_BANKRUPT)) return_cmd_error(INVALID_STRING_ID);
- Station *st = Station::GetByTile(tile);
+ Waypoint *st = Waypoint::GetByTile(tile);
if (HasStationInUse(st->index, INVALID_COMPANY)) return_cmd_error(STR_BUOY_IS_IN_USE);
/* remove the buoy if there is a ship on tile when company goes bankrupt... */
if (!(flags & DC_BANKRUPT) && !EnsureNoVehicleOnGround(tile)) return CMD_ERROR;
if (flags & DC_EXEC) {
- st->dock_tile = INVALID_TILE;
- /* Buoys are marked in the Station struct by this flag. Yes, it is this
- * braindead.. */
st->facilities &= ~FACIL_DOCK;
- st->had_vehicle_of_type &= ~HVOT_BUOY;
InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_SHIPS);
@@ -2050,8 +2031,7 @@ static CommandCost RemoveBuoy(TileIndex tile, DoCommandFlag flags)
MarkTileDirtyByTile(tile);
st->UpdateVirtCoord();
- st->RecomputeIndustriesNear();
- DeleteStationIfEmpty(st);
+ st->delete_ctr = 0;
}
return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_truck_station);
@@ -2227,7 +2207,7 @@ static void DrawTile_Station(TileInfo *ti)
int32 total_offset;
int32 custom_ground_offset;
- if (IsRailwayStation(ti->tile)) {
+ if (IsRailwayStation(ti->tile) || IsRailWaypoint(ti->tile)) {
const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
roadtypes = ROADTYPES_NONE;
total_offset = rti->total_offset;
@@ -2238,7 +2218,7 @@ static void DrawTile_Station(TileInfo *ti)
custom_ground_offset = 0;
}
uint32 relocation = 0;
- const Station *st = NULL;
+ const BaseStation *st = NULL;
const StationSpec *statspec = NULL;
Owner owner = GetTileOwner(ti->tile);
@@ -2256,7 +2236,7 @@ static void DrawTile_Station(TileInfo *ti)
if (IsCustomStationSpecIndex(ti->tile)) {
/* look for customization */
- st = Station::GetByTile(ti->tile);
+ st = BaseStation::GetByTile(ti->tile);
statspec = st->speclist[GetCustomStationSpecIndex(ti->tile)].spec;
if (statspec != NULL) {
@@ -2304,13 +2284,13 @@ static void DrawTile_Station(TileInfo *ti)
DrawGroundSprite(image, GroundSpritePaletteTransform(image, pal, palette));
/* PBS debugging, draw reserved tracks darker */
- if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && IsRailwayStation(ti->tile) && HasStationReservation(ti->tile)) {
+ if (_game_mode != GM_MENU && _settings_client.gui.show_track_reservation && (IsRailwayStation(ti->tile) || IsRailWaypoint(ti->tile)) && HasStationReservation(ti->tile)) {
const RailtypeInfo *rti = GetRailTypeInfo(GetRailType(ti->tile));
DrawGroundSprite(GetRailStationAxis(ti->tile) == AXIS_X ? rti->base_sprites.single_y : rti->base_sprites.single_x, PALETTE_CRASH);
}
}
- if (IsRailwayStation(ti->tile) && HasCatenaryDrawn(GetRailType(ti->tile)) && IsStationTileElectrifiable(ti->tile)) DrawCatenary(ti);
+ if ((IsRailwayStation(ti->tile) || IsRailWaypoint(ti->tile)) && HasCatenaryDrawn(GetRailType(ti->tile)) && IsStationTileElectrifiable(ti->tile)) DrawCatenary(ti);
if (HasBit(roadtypes, ROADTYPE_TRAM)) {
Axis axis = GetRoadStopDir(ti->tile) == DIAGDIR_NE ? AXIS_X : AXIS_Y;
@@ -2318,6 +2298,11 @@ static void DrawTile_Station(TileInfo *ti)
DrawTramCatenary(ti, axis == AXIS_X ? ROAD_X : ROAD_Y);
}
+ if (IsRailWaypoint(ti->tile)) {
+ /* Don't offset the waypoint graphics; they're always the same. */
+ total_offset = 0;
+ }
+
const DrawTileSeqStruct *dtss;
foreach_draw_tile_seq(dtss, t->seq) {
SpriteID image = dtss->image.sprite;
@@ -2408,7 +2393,7 @@ static void GetTileDesc_Station(TileIndex tile, TileDesc *td)
}
}
}
- td->build_date = Station::GetByTile(tile)->build_date;
+ td->build_date = BaseStation::GetByTile(tile)->build_date;
const StationSpec *spec = GetStationSpec(tile);
@@ -2425,15 +2410,16 @@ static void GetTileDesc_Station(TileIndex tile, TileDesc *td)
StringID str;
switch (GetStationType(tile)) {
default: NOT_REACHED();
- case STATION_RAIL: str = STR_STATION_DESCRIPTION_RAILROAD_STATION; break;
+ case STATION_RAIL: str = STR_STATION_DESCRIPTION_RAILROAD_STATION; break;
case STATION_AIRPORT:
str = (IsHangar(tile) ? STR_STATION_DESCRIPTION_AIRCRAFT_HANGAR : STR_STATION_DESCRIPTION_AIRPORT);
break;
- case STATION_TRUCK: str = STR_STATION_DESCRIPTION_TRUCK_LOADING_AREA; break;
- case STATION_BUS: str = STR_STATION_DESCRIPTION_BUS_STATION; break;
- case STATION_OILRIG: str = STR_INDUSTRY_NAME_OIL_RIG; break;
- case STATION_DOCK: str = STR_STATION_DESCRIPTION_SHIP_DOCK; break;
- case STATION_BUOY: str = STR_STATION_DESCRIPTION_BUOY; break;
+ case STATION_TRUCK: str = STR_STATION_DESCRIPTION_TRUCK_LOADING_AREA; break;
+ case STATION_BUS: str = STR_STATION_DESCRIPTION_BUS_STATION; break;
+ case STATION_OILRIG: str = STR_INDUSTRY_NAME_OIL_RIG; break;
+ case STATION_DOCK: str = STR_STATION_DESCRIPTION_SHIP_DOCK; break;
+ case STATION_BUOY: str = STR_STATION_DESCRIPTION_BUOY; break;
+ case STATION_WAYPOINT: str = STR_LANDINFO_WAYPOINT; break;
}
td->str = str;
}
@@ -2445,7 +2431,7 @@ static TrackStatus GetTileTrackStatus_Station(TileIndex tile, TransportType mode
switch (mode) {
case TRANSPORT_RAIL:
- if (IsRailwayStation(tile) && !IsStationTileBlocked(tile)) {
+ if ((IsRailwayStation(tile) || IsRailWaypoint(tile)) && !IsStationTileBlocked(tile)) {
trackbits = TrackToTrackBits(GetRailStationTrack(tile));
}
break;
@@ -2551,10 +2537,14 @@ static void AnimateTile_Station(TileIndex tile)
static bool ClickTile_Station(TileIndex tile)
{
- if (IsHangar(tile)) {
+ const BaseStation *st = BaseStation::GetByTile(tile);
+
+ if (st->facilities & FACIL_WAYPOINT) {
+ ShowWaypointWindow(Waypoint::From(st));
+ } else if (IsHangar(tile)) {
ShowDepotWindow(tile, VEH_AIRCRAFT);
} else {
- ShowStationViewWindow(GetStationIndex(tile));
+ ShowStationViewWindow(st->index);
}
return true;
}
@@ -2650,15 +2640,15 @@ static VehicleEnterTileStatus VehicleEnter_Station(Vehicle *v, TileIndex tile, i
* @param st the station receiving the tick.
* @return true if the station is still valid (wasn't deleted)
*/
-static bool StationHandleBigTick(Station *st)
+static bool StationHandleBigTick(BaseStation *st)
{
- UpdateStationAcceptance(st, true);
-
- if (st->facilities == 0 && ++st->delete_ctr >= 8) {
+ if ((st->facilities & ~FACIL_WAYPOINT) == 0 && ++st->delete_ctr >= 8) {
delete st;
return false;
}
+ if ((st->facilities & FACIL_WAYPOINT) == 0) UpdateStationAcceptance(Station::From(st), true);
+
return true;
}
@@ -2778,23 +2768,23 @@ static void UpdateStationRating(Station *st)
}
/* called for every station each tick */
-static void StationHandleSmallTick(Station *st)
+static void StationHandleSmallTick(BaseStation *st)
{
- if (st->facilities == 0) return;
+ if ((st->facilities & FACIL_WAYPOINT) != 0 || st->facilities == 0) return;
byte b = st->delete_ctr + 1;
if (b >= 185) b = 0;
st->delete_ctr = b;
- if (b == 0) UpdateStationRating(st);
+ if (b == 0) UpdateStationRating(Station::From(st));
}
void OnTick_Station()
{
if (_game_mode == GM_EDITOR) return;
- Station *st;
- FOR_ALL_STATIONS(st) {
+ BaseStation *st;
+ FOR_ALL_BASE_STATIONS(st) {
StationHandleSmallTick(st);
/* Run 250 tick interval trigger for station animation.
@@ -2884,7 +2874,7 @@ CommandCost CmdRenameStation(TileIndex tile, DoCommandFlag flags, uint32 p1, uin
}
/**
- * Find all (non-buoy) stations around a rectangular producer (industry, house, headquarter, ...)
+ * Find all stations around a rectangular producer (industry, house, headquarter, ...)
*
* @param tile North tile of producer
* @param w_prod X extent of producer
@@ -2903,8 +2893,7 @@ void FindStationsAroundTiles(TileIndex tile, int w_prod, int h_prod, StationList
if (cur_tile == INVALID_TILE || !IsTileType(cur_tile, MP_STATION)) continue;
Station *st = Station::GetByTile(cur_tile);
-
- if (st->IsBuoy()) continue; // bouys don't accept cargo
+ if (st == NULL) continue;
if (_settings_game.station.modified_catchment) {
int rad = st->GetCatchmentRadius();
@@ -3120,12 +3109,13 @@ static CommandCost ClearTile_Station(TileIndex tile, DoCommandFlag flags)
if (flags & DC_AUTO) {
switch (GetStationType(tile)) {
default: break;
- case STATION_RAIL: return_cmd_error(STR_ERROR_MUST_DEMOLISH_RAILROAD);
- case STATION_AIRPORT: return_cmd_error(STR_ERROR_MUST_DEMOLISH_AIRPORT_FIRST);
- case STATION_TRUCK: return_cmd_error(HasTileRoadType(tile, ROADTYPE_TRAM) ? STR_ERROR_MUST_DEMOLISH_CARGO_TRAM_STATION_FIRST : STR_ERROR_MUST_DEMOLISH_TRUCK_STATION_FIRST);
- case STATION_BUS: return_cmd_error(HasTileRoadType(tile, ROADTYPE_TRAM) ? STR_ERROR_MUST_DEMOLISH_PASSENGER_TRAM_STATION_FIRST : STR_ERROR_MUST_DEMOLISH_BUS_STATION_FIRST);
- case STATION_BUOY: return_cmd_error(STR_ERROR_BUOY_IN_THE_WAY);
- case STATION_DOCK: return_cmd_error(STR_ERROR_MUST_DEMOLISH_DOCK_FIRST);
+ case STATION_RAIL: return_cmd_error(STR_ERROR_MUST_DEMOLISH_RAILROAD);
+ case STATION_WAYPOINT: return_cmd_error(STR_ERROR_BUILDING_MUST_BE_DEMOLISHED);
+ case STATION_AIRPORT: return_cmd_error(STR_ERROR_MUST_DEMOLISH_AIRPORT_FIRST);
+ case STATION_TRUCK: return_cmd_error(HasTileRoadType(tile, ROADTYPE_TRAM) ? STR_ERROR_MUST_DEMOLISH_CARGO_TRAM_STATION_FIRST : STR_ERROR_MUST_DEMOLISH_TRUCK_STATION_FIRST);
+ case STATION_BUS: return_cmd_error(HasTileRoadType(tile, ROADTYPE_TRAM) ? STR_ERROR_MUST_DEMOLISH_PASSENGER_TRAM_STATION_FIRST : STR_ERROR_MUST_DEMOLISH_BUS_STATION_FIRST);
+ case STATION_BUOY: return_cmd_error(STR_ERROR_BUOY_IN_THE_WAY);
+ case STATION_DOCK: return_cmd_error(STR_ERROR_MUST_DEMOLISH_DOCK_FIRST);
case STATION_OILRIG:
SetDParam(0, STR_INDUSTRY_NAME_OIL_RIG);
return_cmd_error(STR_OBJECT_IN_THE_WAY);
@@ -3133,8 +3123,9 @@ static CommandCost ClearTile_Station(TileIndex tile, DoCommandFlag flags)
}
switch (GetStationType(tile)) {
- case STATION_RAIL: return RemoveRailroadStation(tile, flags);
- case STATION_AIRPORT: return RemoveAirport(tile, flags);
+ case STATION_RAIL: return RemoveRailroadStation(tile, flags);
+ case STATION_WAYPOINT: return RemoveTrainWaypoint(tile, flags, false);
+ case STATION_AIRPORT: return RemoveAirport(tile, flags);
case STATION_TRUCK:
if (IsDriveThroughStopTile(tile) && !CanRemoveRoadWithStop(tile, flags))
return_cmd_error(STR_ERROR_MUST_DEMOLISH_TRUCK_STATION_FIRST);
@@ -3143,8 +3134,8 @@ static CommandCost ClearTile_Station(TileIndex tile, DoCommandFlag flags)
if (IsDriveThroughStopTile(tile) && !CanRemoveRoadWithStop(tile, flags))
return_cmd_error(STR_ERROR_MUST_DEMOLISH_BUS_STATION_FIRST);
return RemoveRoadStop(tile, flags);
- case STATION_BUOY: return RemoveBuoy(tile, flags);
- case STATION_DOCK: return RemoveDock(tile, flags);
+ case STATION_BUOY: return RemoveBuoy(tile, flags);
+ case STATION_DOCK: return RemoveDock(tile, flags);
default: break;
}
@@ -3159,6 +3150,7 @@ static CommandCost TerraformTile_Station(TileIndex tile, DoCommandFlag flags, ui
*/
if (!IsSteepSlope(tileh_new) && (GetTileMaxZ(tile) == z_new + GetSlopeMaxZ(tileh_new))) {
switch (GetStationType(tile)) {
+ case STATION_WAYPOINT:
case STATION_RAIL: {
DiagDirection direction = AxisToDiagDir(GetRailStationAxis(tile));
if (!AutoslopeCheckForEntranceEdge(tile, z_new, tileh_new, direction)) break;
diff --git a/src/station_gui.cpp b/src/station_gui.cpp
index 8db32d0ae..6656428a0 100644
--- a/src/station_gui.cpp
+++ b/src/station_gui.cpp
@@ -143,7 +143,7 @@ protected:
const Station *st;
FOR_ALL_STATIONS(st) {
- if (st->owner == owner || (st->owner == OWNER_NONE && !st->IsBuoy() && HasStationInUse(st->index, owner))) {
+ if (st->owner == owner || (st->owner == OWNER_NONE && HasStationInUse(st->index, owner))) {
if (this->facilities & st->facilities) { // only stations with selected facilities
int num_waiting_cargo = 0;
for (CargoID j = 0; j < NUM_CARGO; j++) {
@@ -378,7 +378,7 @@ public:
/* Do not do the complex check HasStationInUse here, it may be even false
* when the order had been removed and the station list hasn't been removed yet */
- assert(st->owner == owner || (st->owner == OWNER_NONE && !st->IsBuoy()));
+ assert(st->owner == owner || st->owner == OWNER_NONE);
SetDParam(0, st->index);
SetDParam(1, st->facilities);
@@ -409,7 +409,7 @@ public:
const Station *st = this->stations[id_v];
/* do not check HasStationInUse - it is slow and may be invalid */
- assert(st->owner == (Owner)this->window_number || (st->owner == OWNER_NONE && !st->IsBuoy()));
+ assert(st->owner == (Owner)this->window_number || st->owner == OWNER_NONE);
if (_ctrl_pressed) {
ShowExtraViewPortWindow(st->xy);
diff --git a/src/station_map.h b/src/station_map.h
index a2bb5df66..ef1a7a54f 100644
--- a/src/station_map.h
+++ b/src/station_map.h
@@ -88,6 +88,28 @@ static inline bool IsRailwayStationTile(TileIndex t)
return IsTileType(t, MP_STATION) && IsRailwayStation(t);
}
+/**
+ * Is this station tile a rail waypoint?
+ * @param t the tile to get the information from
+ * @pre IsTileType(t, MP_STATION)
+ * @return true if and only if the tile is a rail waypoint
+ */
+static inline bool IsRailWaypoint(TileIndex t)
+{
+ return GetStationType(t) == STATION_WAYPOINT;
+}
+
+/**
+ * Is this tile a station tile and a rail waypoint?
+ * @param t the tile to get the information from
+ * @return true if and only if the tile is a rail waypoint
+ */
+static inline bool IsRailWaypointTile(TileIndex t)
+{
+ return IsTileType(t, MP_STATION) && IsRailWaypoint(t);
+}
+
+
static inline bool IsAirport(TileIndex t)
{
return GetStationType(t) == STATION_AIRPORT;
@@ -186,7 +208,7 @@ static inline bool IsHangarTile(TileIndex t)
static inline Axis GetRailStationAxis(TileIndex t)
{
- assert(IsRailwayStation(t));
+ assert(IsRailwayStation(t) || IsRailWaypoint(t));
return HasBit(GetStationGfx(t), 0) ? AXIS_Y : AXIS_X;
}
@@ -214,31 +236,31 @@ static inline bool IsCompatibleTrainStationTile(TileIndex t1, TileIndex t2)
/**
* Get the reservation state of the rail station
- * @pre IsRailwayStationTile(t)
+ * @pre IsRailwayStation(t) || IsRailWaypoint(t)
* @param t the station tile
* @return reservation state
*/
static inline bool HasStationReservation(TileIndex t)
{
- assert(IsRailwayStationTile(t));
+ assert(IsRailwayStation(t) || IsRailWaypoint(t));
return HasBit(_m[t].m6, 2);
}
/**
* Set the reservation state of the rail station
- * @pre IsRailwayStationTile(t)
+ * @pre IsRailwayStation(t) || IsRailWaypoint(t)
* @param t the station tile
* @param b the reservation state
*/
static inline void SetRailwayStationReservation(TileIndex t, bool b)
{
- assert(IsRailwayStationTile(t));
+ assert(IsRailwayStation(t) || IsRailWaypoint(t));
SB(_m[t].m6, 2, 1, b ? 1 : 0);
}
/**
* Get the reserved track bits for a waypoint
- * @pre IsRailwayStationTile(t)
+ * @pre IsRailwayStation(t) || IsRailWaypoint(t)
* @param t the tile
* @return reserved track bits
*/
@@ -325,6 +347,13 @@ static inline void MakeRailStation(TileIndex t, Owner o, StationID sid, Axis a,
SetRailwayStationReservation(t, false);
}
+static inline void MakeRailWaypoint(TileIndex t, Owner o, StationID sid, Axis a, byte section, RailType rt)
+{
+ MakeStation(t, o, sid, STATION_WAYPOINT, section + a);
+ SetRailType(t, rt);
+ SetRailwayStationReservation(t, false);
+}
+
static inline void MakeRoadStop(TileIndex t, Owner o, StationID sid, RoadStopType rst, RoadTypes rt, DiagDirection d)
{
MakeStation(t, o, sid, (rst == ROADSTOP_BUS ? STATION_BUS : STATION_TRUCK), d);
diff --git a/src/station_type.h b/src/station_type.h
index f5de2f270..f6803421f 100644
--- a/src/station_type.h
+++ b/src/station_type.h
@@ -57,9 +57,8 @@ enum StationHadVehicleOfType {
HVOT_TRUCK = 1 << 3, ///< Station has seen a truck
HVOT_AIRCRAFT = 1 << 4, ///< Station has seen an aircraft
HVOT_SHIP = 1 << 5, ///< Station has seen a ship
- /* This bit is used to mark stations. No, it does not belong here, but what
- * can we do? ;-) */
- HVOT_BUOY = 1 << 6
+
+ HVOT_WAYPOINT = 1 << 6, ///< Station is a waypoint (NewGRF only!)
};
DECLARE_ENUM_AS_BIT_SET(StationHadVehicleOfType);
typedef SimpleTinyEnumT<StationHadVehicleOfType, byte> StationHadVehicleOfTypeByte;
diff --git a/src/strings.cpp b/src/strings.cpp
index 25c116607..4e48f74f1 100644
--- a/src/strings.cpp
+++ b/src/strings.cpp
@@ -863,8 +863,8 @@ static char *FormatString(char *buff, const char *str, int64 *argv, uint casei,
int64 temp[2];
temp[0] = wp->town->index;
temp[1] = wp->town_cn + 1;
- StringID str = wp->town_cn == 0 ? STR_WAYPOINTNAME_CITY : STR_WAYPOINTNAME_CITY_SERIAL;
-
+ StringID str = ((wp->string_id == STR_SV_STNAME_BUOY) ? STR_BUOYNAME_CITY : STR_WAYPOINTNAME_CITY);
+ if (wp->town_cn != 0) str++;
buff = GetStringWithArgs(buff, str, temp, last);
}
break;
diff --git a/src/terraform_gui.cpp b/src/terraform_gui.cpp
index 3d129dfa7..ec5bc72f9 100644
--- a/src/terraform_gui.cpp
+++ b/src/terraform_gui.cpp
@@ -635,10 +635,10 @@ static void ResetLandscapeConfirmationCallback(Window *w, bool confirmed)
_generating_world = false;
/* Delete all station signs */
- Station *st;
- FOR_ALL_STATIONS(st) {
+ BaseStation *st;
+ FOR_ALL_BASE_STATIONS(st) {
/* There can be buoys, remove them */
- if (st->IsBuoy() && IsBuoyTile(st->xy)) DoCommand(st->xy, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR);
+ if (IsBuoyTile(st->xy)) DoCommand(st->xy, 0, 0, DC_EXEC | DC_BANKRUPT, CMD_LANDSCAPE_CLEAR);
if (st->facilities == 0) delete st;
}
diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp
index 5dfc29626..b954a0337 100644
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -482,7 +482,7 @@ static int GetTrainAcceleration(Train *v, bool mode)
assert(max_speed == GetTrainCurveSpeedLimit(v)); // safety check, will be removed later
int speed = v->cur_speed * 10 / 16; // km-ish/h -> mp/h
- if (IsTileType(v->tile, MP_STATION) && v->IsFrontEngine()) {
+ if (IsRailwayStationTile(v->tile) && v->IsFrontEngine()) {
StationID sid = GetStationIndex(v->tile);
if (v->current_order.ShouldStopAtStation(v, sid)) {
int station_ahead;
@@ -4443,12 +4443,10 @@ static bool TrainLocoHandler(Train *v, bool mode)
OrderType order_type = v->current_order.GetType();
/* Do not skip waypoints (incl. 'via' stations) when passing through at full speed. */
- if ((order_type == OT_GOTO_WAYPOINT &&
- v->dest_tile == v->tile) ||
- (order_type == OT_GOTO_STATION &&
+ if ((order_type == OT_GOTO_WAYPOINT || order_type == OT_GOTO_STATION) &&
(v->current_order.GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) &&
IsTileType(v->tile, MP_STATION) &&
- v->current_order.GetDestination() == GetStationIndex(v->tile))) {
+ v->current_order.GetDestination() == GetStationIndex(v->tile)) {
ProcessOrders(v);
}
}
diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp
index 6a39125aa..a555c64f9 100644
--- a/src/vehicle_gui.cpp
+++ b/src/vehicle_gui.cpp
@@ -788,8 +788,6 @@ static void DrawSmallOrderList(const Vehicle *v, int left, int right, int y)
sel--;
if (order->IsType(OT_GOTO_STATION)) {
- if (v->type == VEH_SHIP && Station::Get(order->GetDestination())->IsBuoy()) continue;
-
SetDParam(0, order->GetDestination());
DrawString(left, right, y, STR_ORDER_STATION_SMALL);
@@ -1950,7 +1948,7 @@ struct VehicleViewWindow : Window {
case OT_GOTO_WAYPOINT: {
assert(v->type == VEH_TRAIN || v->type == VEH_SHIP);
SetDParam(0, v->current_order.GetDestination());
- str = (v->type == VEH_TRAIN ? STR_HEADING_FOR_WAYPOINT : STR_HEADING_FOR_STATION) + _settings_client.gui.vehicle_speed;
+ str = STR_HEADING_FOR_WAYPOINT + _settings_client.gui.vehicle_speed;
SetDParam(1, v->GetDisplaySpeed());
break;
}
diff --git a/src/viewport.cpp b/src/viewport.cpp
index ceb2d6be0..e62ce5be9 100644
--- a/src/viewport.cpp
+++ b/src/viewport.cpp
@@ -1218,7 +1218,7 @@ static void ViewportAddSigns(DrawPixelInfo *dpi)
static void AddWaypoint(const Waypoint *wp, StringID str, uint16 width)
{
- AddStringToDraw(wp->sign.left + 1, wp->sign.top + 1, str, wp->index, 0, (wp->delete_ctr != 0 ? 0xE : _company_colours[wp->owner]), width);
+ AddStringToDraw(wp->sign.left + 1, wp->sign.top + 1, str, wp->index, 0, (wp->owner == OWNER_NONE || (wp->facilities & ~FACIL_WAYPOINT) == 0) ? 0xE : _company_colours[wp->owner], width);
}
diff --git a/src/waypoint.cpp b/src/waypoint.cpp
index f669570ba..756fcd4c3 100644
--- a/src/waypoint.cpp
+++ b/src/waypoint.cpp
@@ -12,23 +12,6 @@
#include "window_func.h"
#include "newgrf_station.h"
#include "order_func.h"
-#include "core/pool_func.hpp"
-
-WaypointPool _waypoint_pool("Waypoint");
-INSTANTIATE_POOL_METHODS(Waypoint)
-
-/**
- * Daily loop for waypoints
- */
-void WaypointsDailyLoop()
-{
- Waypoint *wp;
-
- /* Check if we need to delete a waypoint */
- FOR_ALL_WAYPOINTS(wp) {
- if (wp->delete_ctr != 0 && --wp->delete_ctr == 0) delete wp;
- }
-}
/**
* Draw a waypoint
@@ -67,8 +50,3 @@ Waypoint::~Waypoint()
this->sign.MarkDirty();
}
-
-void InitializeWaypoints()
-{
- _waypoint_pool.CleanPool();
-}
diff --git a/src/waypoint.h b/src/waypoint.h
index 3dfcdac1e..62715de85 100644
--- a/src/waypoint.h
+++ b/src/waypoint.h
@@ -14,10 +14,7 @@
#include "date_type.h"
#include "core/pool_type.hpp"
-typedef Pool<Waypoint, WaypointID, 32, 64000> WaypointPool;
-extern WaypointPool _waypoint_pool;
-
-struct Waypoint : WaypointPool::PoolItem<&_waypoint_pool>, SpecializedStation<Waypoint, true> {
+struct Waypoint : SpecializedStation<Waypoint, true> {
uint16 town_cn; ///< The Nth waypoint for this town (consecutive number)
Waypoint(TileIndex tile = INVALID_TILE) : SpecializedStation<Waypoint, true>(tile) { }
@@ -27,29 +24,19 @@ struct Waypoint : WaypointPool::PoolItem<&_waypoint_pool>, SpecializedStation<Wa
/* virtual */ FORCEINLINE bool TileBelongsToRailStation(TileIndex tile) const
{
- return this->delete_ctr == 0 && this->xy == tile;
+ return IsRailWaypointTile(tile) && GetStationIndex(tile) == this->index;
}
/* virtual */ uint32 GetNewGRFVariable(const struct ResolverObject *object, byte variable, byte parameter, bool *available) const;
/* virtual */ void GetTileArea(TileArea *ta, StationType type) const;
-
- /**
- * Fetch a waypoint by tile
- * @param tile Tile of waypoint
- * @return Waypoint
- */
- static FORCEINLINE Waypoint *GetByTile(TileIndex tile)
- {
- return Waypoint::Get(GetWaypointIndex(tile));
- }
};
-#define FOR_ALL_WAYPOINTS_FROM(var, start) FOR_ALL_ITEMS_FROM(Waypoint, waypoint_index, var, start)
-#define FOR_ALL_WAYPOINTS(var) FOR_ALL_WAYPOINTS_FROM(var, 0)
+#define FOR_ALL_WAYPOINTS(var) FOR_ALL_BASE_STATIONS_OF_TYPE(Waypoint, var)
CommandCost RemoveTrainWaypoint(TileIndex tile, DoCommandFlag flags, bool justremove);
void ShowWaypointWindow(const Waypoint *wp);
void DrawWaypointSprite(int x, int y, int stat_id, RailType railtype);
+void MakeDefaultWaypointName(Waypoint *wp);
#endif /* WAYPOINT_H */
diff --git a/src/waypoint_cmd.cpp b/src/waypoint_cmd.cpp
index 8f2804a35..b24b21982 100644
--- a/src/waypoint_cmd.cpp
+++ b/src/waypoint_cmd.cpp
@@ -39,7 +39,7 @@ void Waypoint::UpdateVirtCoord()
* Set the default name for a waypoint
* @param wp Waypoint to work on
*/
-static void MakeDefaultWaypointName(Waypoint *wp)
+void MakeDefaultWaypointName(Waypoint *wp)
{
uint32 used = 0; // bitmap of used waypoint numbers, sliding window with 'next' as base
uint32 next = 0; // first waypoint number in the bitmap
@@ -64,7 +64,7 @@ static void MakeDefaultWaypointName(Waypoint *wp)
/* check only valid waypoints... */
if (lwp != NULL && wp != lwp) {
/* only waypoints with 'generic' name within the same city */
- if (lwp->name == NULL && lwp->town == wp->town) {
+ if (lwp->name == NULL && lwp->town == wp->town && lwp->string_id == wp->string_id) {
/* if lwp->town_cn < next, uint will overflow to '+inf' */
uint i = (uint)lwp->town_cn - next;
@@ -104,7 +104,7 @@ static Waypoint *FindDeletedWaypointCloseTo(TileIndex tile)
uint thres = 8;
FOR_ALL_WAYPOINTS(wp) {
- if (wp->delete_ctr != 0 && wp->owner == _current_company) {
+ if ((wp->facilities & ~FACIL_WAYPOINT) == 0 && wp->owner == _current_company) {
uint cur_dist = DistanceManhattan(tile, wp->xy);
if (cur_dist < thres) {
@@ -163,10 +163,6 @@ CommandCost CmdBuildTrainWaypoint(TileIndex tile, DoCommandFlag flags, uint32 p1
if (flags & DC_EXEC) {
if (wp == NULL) {
wp = new Waypoint(tile);
-
- wp->town = NULL;
- wp->name = NULL;
- wp->town_cn = 0;
} else {
/* Move existing (recently deleted) waypoint to the new location */
@@ -186,15 +182,16 @@ CommandCost CmdBuildTrainWaypoint(TileIndex tile, DoCommandFlag flags, uint32 p1
wp->owner = owner;
bool reserved = HasBit(GetRailReservationTrackBits(tile), AxisToTrack(axis));
- MakeRailWaypoint(tile, owner, axis, GetRailType(tile), wp->index);
- SetDepotReservation(tile, reserved);
+ MakeRailWaypoint(tile, owner, wp->index, axis, 0, GetRailType(tile));
+ SetRailwayStationReservation(tile, reserved);
MarkTileDirtyByTile(tile);
- AllocateSpecToStation(GetCustomStationSpec(STAT_CLASS_WAYP, p1), wp, true);
+ SetCustomStationSpecIndex(tile, AllocateSpecToStation(GetCustomStationSpec(STAT_CLASS_WAYP, p1), wp, true));
wp->delete_ctr = 0;
wp->facilities |= FACIL_TRAIN;
wp->build_date = _date;
+ wp->string_id = STR_SV_STNAME_WAYPOINT;
if (wp->town == NULL) MakeDefaultWaypointName(wp);
@@ -224,22 +221,22 @@ CommandCost RemoveTrainWaypoint(TileIndex tile, DoCommandFlag flags, bool justre
}
if (flags & DC_EXEC) {
- Track track = GetRailWaypointTrack(tile);
+ Track track = GetRailStationTrack(tile);
wp = Waypoint::GetByTile(tile);
- wp->delete_ctr = 30; // let it live for this many days before we do the actual deletion.
wp->sign.MarkDirty();
wp->facilities &= ~FACIL_TRAIN;
Train *v = NULL;
+ uint specindex = GetCustomStationSpecIndex(tile);
if (justremove) {
- TrackBits tracks = GetRailWaypointBits(tile);
- bool reserved = HasDepotReservation(tile);
+ TrackBits tracks = GetRailStationTrackBits(tile);
+ bool reserved = HasStationReservation(tile);
MakeRailNormal(tile, wp->owner, tracks, GetRailType(tile));
if (reserved) SetTrackReservation(tile, tracks);
MarkTileDirtyByTile(tile);
} else {
- if (HasDepotReservation(tile)) {
+ if (HasStationReservation(tile)) {
v = GetTrainForReservation(tile, track);
if (v != NULL) FreeTrainTrackReservation(v);
}
@@ -249,7 +246,7 @@ CommandCost RemoveTrainWaypoint(TileIndex tile, DoCommandFlag flags, bool justre
YapfNotifyTrackLayoutChange(tile, track);
if (v != NULL) TryPathReserve(v, true);
- DeallocateSpecFromStation(wp, wp->num_specs > 0 ? 1 : 0);
+ DeallocateSpecFromStation(wp, specindex);
}
return CommandCost(EXPENSES_CONSTRUCTION, _price.remove_train_depot);
@@ -290,7 +287,7 @@ static bool IsUniqueWaypointName(const char *name)
CommandCost CmdRenameWaypoint(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
{
Waypoint *wp = Waypoint::GetIfValid(p1);
- if (wp == NULL || !CheckOwnership(wp->owner)) return CMD_ERROR;
+ if (wp == NULL || !(CheckOwnership(wp->owner) || wp->owner == OWNER_NONE)) return CMD_ERROR;
bool reset = StrEmpty(text);
diff --git a/src/waypoint_gui.cpp b/src/waypoint_gui.cpp
index cdf0ad6f0..1dc2175fa 100644
--- a/src/waypoint_gui.cpp
+++ b/src/waypoint_gui.cpp
@@ -37,7 +37,7 @@ public:
WaypointWindow(const WindowDesc *desc, WindowNumber window_number) : Window(desc, window_number)
{
this->wp = Waypoint::Get(this->window_number);
- this->vt = (wp->facilities & FACIL_TRAIN) ? VEH_TRAIN : VEH_SHIP;
+ this->vt = (wp->string_id == STR_SV_STNAME_WAYPOINT) ? VEH_TRAIN : VEH_SHIP;
if (this->wp->owner != OWNER_NONE) this->owner = this->wp->owner;
diff --git a/src/yapf/yapf_costrail.hpp b/src/yapf/yapf_costrail.hpp
index dcf9a602a..1731f7fdf 100644
--- a/src/yapf/yapf_costrail.hpp
+++ b/src/yapf/yapf_costrail.hpp
@@ -406,7 +406,7 @@ no_entry_cost: // jump here at the beginning if the node has no parent (it is th
/* We will end in this pass (station is possible target) */
end_segment_reason |= ESRB_STATION;
- } else if (cur.tile_type == MP_RAILWAY && IsRailWaypoint(cur.tile)) {
+ } else if (cur.tile_type == MP_STATION && IsRailWaypoint(cur.tile)) {
/* Waypoint is also a good reason to finish. */
end_segment_reason |= ESRB_WAYPOINT;
} else if (TrackFollower::DoTrackMasking() && cur.tile_type == MP_RAILWAY) {
diff --git a/src/yapf/yapf_destrail.hpp b/src/yapf/yapf_destrail.hpp
index 08b1da070..650b43b49 100644
--- a/src/yapf/yapf_destrail.hpp
+++ b/src/yapf/yapf_destrail.hpp
@@ -134,22 +134,11 @@ public:
m_destTrackdirs = INVALID_TRACKDIR_BIT;
break;
- case OT_GOTO_WAYPOINT: {
- Waypoint *wp = Waypoint::Get(v->current_order.GetDestination());
- if (wp == NULL) {
- /* Invalid waypoint in orders! */
- DEBUG(yapf, 0, "Invalid waypoint in orders == 0x%04X (train %d, company %d)", v->current_order.GetDestination(), v->unitnumber, (CompanyID)v->owner);
- break;
- }
- m_destTile = wp->xy;
- if (m_destTile != v->dest_tile) {
- /* Something is wrong with orders! */
- DEBUG(yapf, 0, "Invalid v->dest_tile == 0x%04X (train %d, company %d)", v->dest_tile, v->unitnumber, (CompanyID)v->owner);
- }
+ case OT_GOTO_WAYPOINT:
+ m_destTile = Waypoint::Get(v->current_order.GetDestination())->xy;
m_dest_station_id = INVALID_STATION;
- m_destTrackdirs = TrackToTrackdirBits(AxisToTrack(GetWaypointAxis(wp->xy)));
+ m_destTrackdirs = IsRailWaypointTile(m_destTile) ? TrackToTrackdirBits(GetRailStationTrack(m_destTile)) : INVALID_TRACKDIR_BIT;
break;
- }
default:
m_destTile = v->dest_tile;