(svn r16909) -Fix [FS#2996]: NewGRF stations would be triggering assertions all over the place when using the more advanced station types.

-Change: make (rail) waypoints sub classes of 'base stations', make buoys waypoints and unify code between them where possible.
This commit is contained in:
rubidium 2009-07-22 08:59:57 +00:00
parent 2646a99d29
commit 68ead6b84f
40 changed files with 689 additions and 693 deletions

View File

@ -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);
}
}

View File

@ -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:

View File

@ -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);

View File

@ -22,7 +22,7 @@
{
if (!AIRail::IsRailWaypointTile(tile)) return WAYPOINT_INVALID;
return ::GetWaypointIndex(tile);
return ::GetStationIndex(tile);
}
/* static */ char *AIWaypoint::GetName(WaypointID waypoint_id)

View File

@ -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);
}
}

View File

@ -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) {

View File

@ -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));

View File

@ -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

View File

@ -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();

View File

@ -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;
}

View File

@ -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:

View File

@ -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);

View File

@ -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);
}

View File

@ -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:

View File

@ -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);
dts = &_depot_gfx_table[GetRailDepotDirection(ti->tile)];
}
if (statspec != NULL) {
const BaseStation *st = BaseStation::GetByTile(ti->tile);
uint gfx = 2;
relocation = rti->total_offset;
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;
}
image = dts->ground.sprite;
if (image != SPR_FLAT_GRASS_TILE) image += rti->total_offset;
if (statspec->renderdata == NULL) {
dts = GetStationTileLayout(STATION_RAIL, gfx);
} else {
dts = &statspec->renderdata[(gfx < statspec->tiles ? gfx : 0) + GetWaypointAxis(ti->tile)];
}
if (dts != NULL && dts->seq != NULL) {
relocation = GetCustomStationRelocation(statspec, st, ti->tile);
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);
}

View File

@ -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)
};
@ -82,27 +81,6 @@ static inline void SetHasSignals(TileIndex tile, bool signals)
SB(_m[tile].m5, 6, 1, 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
@ -202,51 +180,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)
@ -335,17 +268,6 @@ static inline void SetDepotReservation(TileIndex t, bool b)
SB(_m[t].m5, 4, 1, (byte)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)
@ -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 */

View File

@ -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();

View File

@ -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;

View File

@ -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}

View File

@ -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();

View File

@ -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;
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()
{
/* 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. */
Station *st;
FOR_ALL_STATIONS(st) {
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,66 +216,54 @@ const SaveLoad *GetGoodsDesc()
}
static void SaveLoad_STNS(Station *st)
{
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);
}
}
}
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);
}
}
}
static void Save_STNS()
{
Station *st;
/* Write the stations */
FOR_ALL_STATIONS(st) {
SlSetArrayIndex(st->index);
SlAutolength((AutolengthProc*)SaveLoad_STNS, st);
}
}
static void Load_STNS()
{
int index;
while ((index = SlIterateArray()) != -1) {
Station *st = new (index) Station();
SaveLoad_STNS(st);
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 */
st->speclist = CallocT<StationSpecList>(st->num_specs);
for (uint i = 0; i < st->num_specs; i++) {
SlObject(&st->speclist[i], _station_speclist_desc);
}
}
}
}
void Ptrs_STNS()
{
/* Don't run when savegame version is higher than or equal to 123. */
if (!CheckSavegameVersion(123)) return;
Station *st;
FOR_ALL_STATIONS(st) {
if (!CheckSavegameVersion(68)) {
@ -213,11 +272,147 @@ void Ptrs_STNS()
SlObject(ge, GetGoodsDesc());
}
}
SlObject(st, _station_desc);
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*)RealSave_STNN, st);
}
}
static void Load_STNN()
{
int index;
while ((index = SlIterateArray()) != -1) {
bool waypoint = (SlReadByte() & FACIL_WAYPOINT) != 0;
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);
}
}
}
}
static void Ptrs_STNN()
{
/* Don't run when savegame version lower than 123. */
if (CheckSavegameVersion(123)) return;
Station *st;
FOR_ALL_STATIONS(st) {
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()
{
RoadStop *rs;
@ -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},
};

View File

@ -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;
}
}
static uint16 _waypoint_town_index;
static StringID _waypoint_string_id;
static StationSpecList _waypoint_spec;
/**
* 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 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),
/* 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_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),
new_wp->string_id = STR_SV_STNAME_WAYPOINT;
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);
SetRailwayStationReservation(t, reserved);
if (wp->spec != NULL) {
SetCustomStationSpecIndex(t, AllocateSpecToStation(wp->spec, new_wp, true));
}
}
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 Save_WAYP()
{
Waypoint *wp;
FOR_ALL_WAYPOINTS(wp) {
if (wp->num_specs == 0) {
_waypoint_spec.grfid = 0;
} else {
_waypoint_spec = wp->speclist[1];
}
SlSetArrayIndex(wp->index);
SlObject(wp, _waypoint_desc);
}
}
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;
OldWaypoint *wp = _old_waypoints.Append();
memset(wp, 0, sizeof(*wp));
Waypoint *wp = new (index) Waypoint();
SlObject(wp, _waypoint_desc);
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 (OldWaypoint *wp = _old_waypoints.Begin(); wp != _old_waypoints.End(); wp++) {
SlObject(wp, _old_waypoint_desc);
FOR_ALL_WAYPOINTS(wp) {
SlObject(wp, _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},
};

View File

@ -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

View File

@ -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

View File

@ -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
@ -175,6 +180,44 @@ struct SpecializedStation : public BaseStation {
return (st->facilities & FACIL_WAYPOINT) == EXPECTED_FACIL;
}
/**
* 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
@ -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 */

View File

@ -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;

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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 */

View File

@ -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);

View File

@ -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;

View File

@ -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) {

View File

@ -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;