Implement rail station property 1B, bridge clearance information

pull/73/head
Jonathan G Rennison 6 years ago
parent 76a7b70cad
commit ef0a0b0f8e

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

Loading…
Cancel
Save