Implement rail station property 1B, bridge clearance information
This commit is contained in:
@@ -1886,7 +1886,7 @@ STR_CONFIG_SETTING_ALLOW_GRF_OBJECTS_UNDER_BRIDGES :Allow all NewGR
|
||||
STR_CONFIG_SETTING_ALLOW_GRF_OBJECTS_UNDER_BRIDGES_HELPTEXT :Allow all NewGRF objects to be built under bridges, even where not otherwise enabled by the GRF.{}This may result in graphical issues.
|
||||
|
||||
STR_CONFIG_SETTING_ALLOW_STATIONS_UNDER_BRIDGES :Allow stations under bridges: {STRING2}
|
||||
STR_CONFIG_SETTING_ALLOW_STATIONS_UNDER_BRIDGES_HELPTEXT :Allow stations to be built under bridges (excluding airports).{}This may result in graphical issues.
|
||||
STR_CONFIG_SETTING_ALLOW_STATIONS_UNDER_BRIDGES_HELPTEXT :Allow stations to be built under bridges (excluding airports, and rail stations/waypoints where the required bridge clearance is set by the GRF).{}This may result in graphical issues.
|
||||
|
||||
STR_CONFIG_SETTING_QUERY_CAPTION :{WHITE}Change setting value
|
||||
|
||||
|
@@ -1965,7 +1965,7 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte
|
||||
break;
|
||||
|
||||
case 0x0E: // Define custom layout
|
||||
statspec->copied_layouts = false;
|
||||
ClrBit(statspec->internal_flags, SSIF_COPIED_LAYOUTS);
|
||||
|
||||
while (buf->HasData()) {
|
||||
byte length = buf->ReadByte();
|
||||
@@ -2028,7 +2028,7 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte
|
||||
statspec->lengths = srcstatspec->lengths;
|
||||
statspec->platforms = srcstatspec->platforms;
|
||||
statspec->layouts = srcstatspec->layouts;
|
||||
statspec->copied_layouts = true;
|
||||
SetBit(statspec->internal_flags, SSIF_COPIED_LAYOUTS);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2086,6 +2086,13 @@ static ChangeInfoResult StationChangeInfo(uint stid, int numinfo, int prop, Byte
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x1B: // Minimum height for a bridge above
|
||||
SetBit(statspec->internal_flags, SSIF_BRIDGE_HEIGHTS_SET);
|
||||
for (uint i = 0; i < 8; i++) {
|
||||
statspec->bridge_height[i] = buf->ReadByte();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ret = CIR_UNKNOWN;
|
||||
break;
|
||||
@@ -7927,7 +7934,7 @@ static void ResetCustomStations()
|
||||
delete[] statspec->renderdata;
|
||||
|
||||
/* Release platforms and layouts */
|
||||
if (!statspec->copied_layouts) {
|
||||
if (!HasBit(statspec->internal_flags, SSIF_COPIED_LAYOUTS)) {
|
||||
for (uint l = 0; l < statspec->lengths; l++) {
|
||||
for (uint p = 0; p < statspec->platforms[l]; p++) {
|
||||
free(statspec->layouts[l][p]);
|
||||
|
@@ -111,6 +111,11 @@ enum StationRandomTrigger {
|
||||
SRT_PATH_RESERVATION, ///< Trigger platform when train reserves path.
|
||||
};
|
||||
|
||||
enum StationSpecIntlFlags {
|
||||
SSIF_COPIED_LAYOUTS, ///< Copied StationLayout **layouts.
|
||||
SSIF_BRIDGE_HEIGHTS_SET, ///< byte bridge_height[8] is set.
|
||||
};
|
||||
|
||||
/* Station layout for given dimensions - it is a two-dimensional array
|
||||
* where index is computed as (x * platforms) + platform. */
|
||||
typedef byte *StationLayout;
|
||||
@@ -164,13 +169,14 @@ struct StationSpec {
|
||||
byte pylons; ///< Bitmask of base tiles (0 - 7) which should contain elrail pylons
|
||||
byte wires; ///< Bitmask of base tiles (0 - 7) which should contain elrail wires
|
||||
byte blocked; ///< Bitmask of base tiles (0 - 7) which are blocked to trains
|
||||
byte bridge_height[8]; ///< Minimum height for a bridge above, 0 for none
|
||||
|
||||
AnimationInfo animation;
|
||||
|
||||
byte lengths;
|
||||
byte *platforms;
|
||||
StationLayout **layouts;
|
||||
bool copied_layouts;
|
||||
byte internal_flags; ///< Bitmask of internal spec flags (StationSpecIntlFlags)
|
||||
};
|
||||
|
||||
/** Struct containing information relating to station classes. */
|
||||
|
@@ -775,6 +775,18 @@ CommandCost CheckBuildableTile(TileIndex tile, uint invalid_dirs, int &allowed_z
|
||||
return cost;
|
||||
}
|
||||
|
||||
bool IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec *statspec, byte layout)
|
||||
{
|
||||
assert(layout < 8);
|
||||
if (!IsBridgeAbove(tile)) return true;
|
||||
|
||||
if (statspec && HasBit(statspec->internal_flags, SSIF_BRIDGE_HEIGHTS_SET)) {
|
||||
return (GetTileMaxZ(tile) + statspec->bridge_height[layout] <= GetBridgeHeight(GetSouthernBridgeEnd(tile)));
|
||||
} else {
|
||||
return _settings_game.construction.allow_stations_under_bridges;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a rail station can be built at the given area.
|
||||
* @param tile_area Area to check.
|
||||
@@ -799,7 +811,7 @@ static CommandCost CheckFlatLandRailStation(TileArea tile_area, DoCommandFlag fl
|
||||
bool slope_cb = statspec != NULL && HasBit(statspec->callback_mask, CBM_STATION_SLOPE_CHECK);
|
||||
|
||||
TILE_AREA_LOOP(tile_cur, tile_area) {
|
||||
CommandCost ret = CheckBuildableTile(tile_cur, invalid_dirs, allowed_z, false, !_settings_game.construction.allow_stations_under_bridges);
|
||||
CommandCost ret = CheckBuildableTile(tile_cur, invalid_dirs, allowed_z, false, false);
|
||||
if (ret.Failed()) return ret;
|
||||
cost.AddCost(ret);
|
||||
|
||||
@@ -1255,6 +1267,26 @@ CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32
|
||||
/* Make sure the area below consists of clear tiles. (OR tiles belonging to a certain rail station) */
|
||||
StationID est = INVALID_STATION;
|
||||
SmallVector<Train *, 4> affected_vehicles;
|
||||
|
||||
const StationSpec *statspec = StationClass::Get(spec_class)->GetSpec(spec_index);
|
||||
|
||||
TileIndexDiff tile_delta = (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
|
||||
byte *layout_ptr = AllocaM(byte, numtracks * plat_len);
|
||||
GetStationLayout(layout_ptr, numtracks, plat_len, statspec);
|
||||
|
||||
{
|
||||
TileIndex tile_track = tile_org;
|
||||
byte *check_layout_ptr = layout_ptr;
|
||||
for (uint i = 0; i < numtracks; i++) {
|
||||
TileIndex tile = tile_track;
|
||||
for (uint j = 0; j < plat_len; j++) {
|
||||
if (!IsRailStationBridgeAboveOk(tile, statspec, *check_layout_ptr++)) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
|
||||
tile += tile_delta;
|
||||
}
|
||||
tile_track += tile_delta ^ TileDiffXY(1, 1); // perpendicular to tile_delta
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the land below the station. */
|
||||
CommandCost cost = CheckFlatLandRailStation(new_location, flags, axis, &est, rt, affected_vehicles, spec_class, spec_index, plat_len, numtracks);
|
||||
if (cost.Failed()) return cost;
|
||||
@@ -1275,7 +1307,6 @@ CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32
|
||||
}
|
||||
|
||||
/* Check if we can allocate a custom stationspec to this station */
|
||||
const StationSpec *statspec = StationClass::Get(spec_class)->GetSpec(spec_index);
|
||||
int specindex = AllocateSpecToStation(statspec, st, (flags & DC_EXEC) != 0);
|
||||
if (specindex == -1) return_cmd_error(STR_ERROR_TOO_MANY_STATION_SPECS);
|
||||
|
||||
@@ -1295,8 +1326,7 @@ CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32
|
||||
}
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
TileIndexDiff tile_delta;
|
||||
byte *layout_ptr;
|
||||
|
||||
byte numtracks_orig;
|
||||
Track track;
|
||||
|
||||
@@ -1311,12 +1341,8 @@ CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32
|
||||
st->cached_anim_triggers |= statspec->animation.triggers;
|
||||
}
|
||||
|
||||
tile_delta = (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1));
|
||||
track = AxisToTrack(axis);
|
||||
|
||||
layout_ptr = AllocaM(byte, numtracks * plat_len);
|
||||
GetStationLayout(layout_ptr, numtracks, plat_len, statspec);
|
||||
|
||||
numtracks_orig = numtracks;
|
||||
|
||||
Company *c = Company::Get(st->owner);
|
||||
|
@@ -47,6 +47,7 @@
|
||||
#include "station_map.h"
|
||||
#include "industry_map.h"
|
||||
#include "object_map.h"
|
||||
#include "newgrf_station.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
#include "table/bridge_land.h"
|
||||
@@ -502,7 +503,27 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
|
||||
}
|
||||
|
||||
case MP_STATION: {
|
||||
if (!_settings_game.construction.allow_stations_under_bridges || IsAirport(tile)) goto not_valid_below;
|
||||
switch (GetStationType(tile)) {
|
||||
case STATION_AIRPORT:
|
||||
goto not_valid_below;
|
||||
|
||||
case STATION_RAIL:
|
||||
case STATION_WAYPOINT: {
|
||||
const StationSpec *statspec = GetStationSpec(tile);
|
||||
if (statspec && HasBit(statspec->internal_flags, SSIF_BRIDGE_HEIGHTS_SET)) {
|
||||
uint layout = GetStationGfx (tile);
|
||||
assert(layout < 8);
|
||||
if (GetTileMaxZ(tile) + statspec->bridge_height[layout] > z_start + 1) goto not_valid_below;
|
||||
} else if (!_settings_game.construction.allow_stations_under_bridges) {
|
||||
goto not_valid_below;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
if (!_settings_game.construction.allow_stations_under_bridges) goto not_valid_below;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@@ -133,14 +133,13 @@ static CommandCost IsValidTileForWaypoint(TileIndex tile, Axis axis, StationID *
|
||||
return_cmd_error(STR_ERROR_FLAT_LAND_REQUIRED);
|
||||
}
|
||||
|
||||
if (IsBridgeAbove(tile) && !_settings_game.construction.allow_stations_under_bridges) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
|
||||
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
extern void GetStationLayout(byte *layout, int numtracks, int plat_len, const StationSpec *statspec);
|
||||
extern CommandCost FindJoiningWaypoint(StationID existing_station, StationID station_to_join, bool adjacent, TileArea ta, Waypoint **wp);
|
||||
extern CommandCost CanExpandRailStation(const BaseStation *st, TileArea &new_ta, Axis axis);
|
||||
extern bool IsRailStationBridgeAboveOk(TileIndex tile, const StationSpec *statspec, byte layout);
|
||||
|
||||
/**
|
||||
* Convert existing rail to waypoint. Eg build a waypoint station over
|
||||
@@ -187,6 +186,16 @@ CommandCost CmdBuildRailWaypoint(TileIndex start_tile, DoCommandFlag flags, uint
|
||||
|
||||
if (distant_join && (!_settings_game.station.distant_join_stations || !Waypoint::IsValidID(station_to_join))) return CMD_ERROR;
|
||||
|
||||
const StationSpec *spec = StationClass::Get(spec_class)->GetSpec(spec_index);
|
||||
byte *layout_ptr = AllocaM(byte, count);
|
||||
if (spec == NULL) {
|
||||
/* The layout must be 0 for the 'normal' waypoints by design. */
|
||||
memset(layout_ptr, 0, count);
|
||||
} else {
|
||||
/* But for NewGRF waypoints we like to have their style. */
|
||||
GetStationLayout(layout_ptr, count, 1, spec);
|
||||
}
|
||||
|
||||
/* Make sure the area below consists of clear tiles. (OR tiles belonging to a certain rail station) */
|
||||
StationID est = INVALID_STATION;
|
||||
|
||||
@@ -196,6 +205,7 @@ CommandCost CmdBuildRailWaypoint(TileIndex start_tile, DoCommandFlag flags, uint
|
||||
TileIndex tile = start_tile + i * offset;
|
||||
CommandCost ret = IsValidTileForWaypoint(tile, axis, &est);
|
||||
if (ret.Failed()) return ret;
|
||||
if (!IsRailStationBridgeAboveOk(tile, spec, layout_ptr[i])) return_cmd_error(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
|
||||
}
|
||||
|
||||
Waypoint *wp = NULL;
|
||||
@@ -245,15 +255,6 @@ CommandCost CmdBuildRailWaypoint(TileIndex start_tile, DoCommandFlag flags, uint
|
||||
|
||||
wp->UpdateVirtCoord();
|
||||
|
||||
const StationSpec *spec = StationClass::Get(spec_class)->GetSpec(spec_index);
|
||||
byte *layout_ptr = AllocaM(byte, count);
|
||||
if (spec == NULL) {
|
||||
/* The layout must be 0 for the 'normal' waypoints by design. */
|
||||
memset(layout_ptr, 0, count);
|
||||
} else {
|
||||
/* But for NewGRF waypoints we like to have their style. */
|
||||
GetStationLayout(layout_ptr, count, 1, spec);
|
||||
}
|
||||
byte map_spec_index = AllocateSpecToStation(spec, wp, true);
|
||||
|
||||
Company *c = Company::Get(wp->owner);
|
||||
|
Reference in New Issue
Block a user