diff --git a/docs/newgrf-additions.html b/docs/newgrf-additions.html
index e16030d415..75bd4a1bf0 100644
--- a/docs/newgrf-additions.html
+++ b/docs/newgrf-additions.html
@@ -203,6 +203,16 @@
This is indicated by the feature name: action0_bridge_pillar_flags, version 1
+ Bridge availability flags (mappable property: bridge_availability_flags)
+ This property sets the availability flags for this bridge type.
+ The property length is 1 byte. The format is:
+
+ Bit | Value | Meaning |
+ 0 | 1 | Towns may not build this bridge type |
+ 1 | 2 | Scripts (AI/GS) may not build this bridge type |
+
+
+ This is indicated by the feature name: action0_bridge_availability_flags, version 1
More bridges (16 instead of 13)
This is indicated by the feature name: more_bridge_types, version 1
diff --git a/src/bridge.h b/src/bridge.h
index ab6e609837..65bd7e5899 100644
--- a/src/bridge.h
+++ b/src/bridge.h
@@ -54,6 +54,8 @@ DECLARE_ENUM_AS_BIT_SET(BridgePiecePillarFlags)
enum BridgeSpecCtrlFlags {
BSCF_CUSTOM_PILLAR_FLAGS,
BSCF_INVALID_PILLAR_FLAGS,
+ BSCF_NOT_AVAILABLE_TOWN,
+ BSCF_NOT_AVAILABLE_AI_GS,
};
/**
@@ -94,6 +96,7 @@ static inline const BridgeSpec *GetBridgeSpec(BridgeType i)
void DrawBridgeMiddle(const TileInfo *ti);
CommandCost CheckBridgeAvailability(BridgeType bridge_type, uint bridge_len, DoCommandFlag flags = DC_NONE);
+bool MayTownBuildBridgeType(BridgeType bridge_type);
int CalcBridgeLenCostFactor(int x);
BridgePiecePillarFlags GetBridgeTilePillarFlags(TileIndex tile, TileIndex northern_bridge_end, TileIndex southern_bridge_end, BridgeType bridge_type, TransportType bridge_transport_type);
diff --git a/src/newgrf.cpp b/src/newgrf.cpp
index a2b519431d..6fd1348f3f 100644
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -2310,6 +2310,14 @@ static ChangeInfoResult BridgeChangeInfo(uint brid, int numinfo, int prop, const
SetBit(bridge->ctrl_flags, BSCF_CUSTOM_PILLAR_FLAGS);
break;
+ case A0RPI_BRIDGE_AVAILABILITY_FLAGS: {
+ if (MappedPropertyLengthMismatch(buf, 1, mapping_entry)) break;
+ byte flags = buf->ReadByte();
+ SB(bridge->ctrl_flags, BSCF_NOT_AVAILABLE_TOWN, 1, HasBit(flags, 0) ? 1 : 0);
+ SB(bridge->ctrl_flags, BSCF_NOT_AVAILABLE_AI_GS, 1, HasBit(flags, 1) ? 1 : 0);
+ break;
+ }
+
default:
ret = HandleAction0PropertyDefault(buf, prop);
break;
@@ -8369,6 +8377,7 @@ static const GRFFeatureInfo _grf_feature_list[] = {
GRFFeatureInfo("more_bridge_types", 1),
GRFFeatureInfo("action0_bridge_prop14", 1),
GRFFeatureInfo("action0_bridge_pillar_flags", 1),
+ GRFFeatureInfo("action0_bridge_availability_flags", 1),
GRFFeatureInfo("action5_programmable_signals", 1),
GRFFeatureInfo("action0_railtype_programmable_signals", 1),
GRFFeatureInfo("action0_railtype_restricted_signals", 1),
@@ -8487,6 +8496,7 @@ static const GRFPropertyMapDefinition _grf_action0_remappable_properties[] = {
GRFPropertyMapDefinition(GSF_STATIONS, A0RPI_STATION_DISALLOWED_BRIDGE_PILLARS, "station_disallowed_bridge_pillars"),
GRFPropertyMapDefinition(GSF_BRIDGES, A0RPI_BRIDGE_MENU_ICON, "bridge_menu_icon"),
GRFPropertyMapDefinition(GSF_BRIDGES, A0RPI_BRIDGE_PILLAR_FLAGS, "bridge_pillar_flags"),
+ GRFPropertyMapDefinition(GSF_BRIDGES, A0RPI_BRIDGE_AVAILABILITY_FLAGS, "bridge_availability_flags"),
GRFPropertyMapDefinition(GSF_RAILTYPES, A0RPI_RAILTYPE_ENABLE_PROGRAMMABLE_SIGNALS, "railtype_enable_programmable_signals"),
GRFPropertyMapDefinition(GSF_RAILTYPES, A0RPI_RAILTYPE_ENABLE_RESTRICTED_SIGNALS, "railtype_enable_restricted_signals"),
GRFPropertyMapDefinition(),
diff --git a/src/newgrf.h b/src/newgrf.h
index a475c211e0..c319d0ab5a 100644
--- a/src/newgrf.h
+++ b/src/newgrf.h
@@ -114,6 +114,7 @@ enum Action0RemapPropertyIds {
A0RPI_STATION_DISALLOWED_BRIDGE_PILLARS,
A0RPI_BRIDGE_MENU_ICON,
A0RPI_BRIDGE_PILLAR_FLAGS,
+ A0RPI_BRIDGE_AVAILABILITY_FLAGS,
A0RPI_RAILTYPE_ENABLE_PROGRAMMABLE_SIGNALS,
A0RPI_RAILTYPE_ENABLE_RESTRICTED_SIGNALS,
};
diff --git a/src/script/api/script_bridge.cpp b/src/script/api/script_bridge.cpp
index b668f6bd86..4419f8cd5b 100644
--- a/src/script/api/script_bridge.cpp
+++ b/src/script/api/script_bridge.cpp
@@ -20,7 +20,9 @@
/* static */ bool ScriptBridge::IsValidBridge(BridgeID bridge_id)
{
- return bridge_id < MAX_BRIDGES && ::GetBridgeSpec(bridge_id)->avail_year <= _cur_year;
+ if (bridge_id >= MAX_BRIDGES) return false;
+ const BridgeSpec *b = ::GetBridgeSpec(bridge_id);
+ return b->avail_year <= _cur_year && !HasBit(b->ctrl_flags, BSCF_NOT_AVAILABLE_AI_GS);
}
/* static */ bool ScriptBridge::IsBridgeTile(TileIndex tile)
@@ -77,7 +79,7 @@ static void _DoCommandReturnBuildBridge1(class ScriptInstance *instance)
EnforcePrecondition(false, vehicle_type != ScriptVehicle::VT_ROAD || ScriptRoad::IsRoadTypeAvailable(ScriptRoad::GetCurrentRoadType()));
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY || vehicle_type == ScriptVehicle::VT_ROAD);
- uint type = 0;
+ uint type = (1 << 17);
switch (vehicle_type) {
case ScriptVehicle::VT_ROAD:
type |= (TRANSPORT_ROAD << 15);
diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp
index 15f5822362..aaaa7f17e9 100644
--- a/src/town_cmd.cpp
+++ b/src/town_cmd.cpp
@@ -1303,7 +1303,7 @@ static bool GrowTownWithBridge(const Town *t, const TileIndex tile, const DiagDi
for (;;) {
/* Can we actually build the bridge? */
RoadType rt = GetTownRoadType(t);
- if (DoCommand(tile, bridge_tile, bridge_type | rt << 8 | TRANSPORT_ROAD << 15, CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_BRIDGE)), CMD_BUILD_BRIDGE).Succeeded()) {
+ if (MayTownBuildBridgeType(bridge_type) && DoCommand(tile, bridge_tile, bridge_type | rt << 8 | TRANSPORT_ROAD << 15, CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_BRIDGE)), CMD_BUILD_BRIDGE).Succeeded()) {
DoCommand(tile, bridge_tile, bridge_type | rt << 8 | TRANSPORT_ROAD << 15, DC_EXEC | CommandFlagsToDCFlags(GetCommandFlags(CMD_BUILD_BRIDGE)), CMD_BUILD_BRIDGE);
_grow_town_result = GROWTH_SUCCEED;
return true;
diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp
index 0c80bc1b7a..0c4ff9478d 100644
--- a/src/tunnelbridge_cmd.cpp
+++ b/src/tunnelbridge_cmd.cpp
@@ -274,6 +274,14 @@ CommandCost CheckBridgeAvailability(BridgeType bridge_type, uint bridge_len, DoC
return_cmd_error(STR_ERROR_BRIDGE_TOO_LONG);
}
+bool MayTownBuildBridgeType(BridgeType bridge_type)
+{
+ if (bridge_type >= MAX_BRIDGES) return false;
+
+ const BridgeSpec *b = GetBridgeSpec(bridge_type);
+ return !HasBit(b->ctrl_flags, BSCF_NOT_AVAILABLE_TOWN);
+}
+
/**
* Build a Bridge
* @param end_tile end tile
@@ -283,6 +291,7 @@ CommandCost CheckBridgeAvailability(BridgeType bridge_type, uint bridge_len, DoC
* - p2 = (bit 0- 7) - bridge type (hi bh)
* - p2 = (bit 8-13) - rail type or road types.
* - p2 = (bit 15-16) - transport type.
+ * - p2 = (bit 17) - script command
* @param text unused
* @return the cost of this operation or an error
*/
@@ -300,6 +309,8 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
TransportType transport_type = Extract(p2);
+ bool script_cmd = HasBit(p2, 17);
+
/* type of bridge */
switch (transport_type) {
case TRANSPORT_ROAD:
@@ -354,6 +365,7 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u
/* set and test bridge length, availability */
CommandCost ret = CheckBridgeAvailability(bridge_type, bridge_len, flags);
if (ret.Failed()) return ret;
+ if (script_cmd && HasBit(GetBridgeSpec(bridge_type)->ctrl_flags, BSCF_NOT_AVAILABLE_AI_GS)) return CMD_ERROR;
} else {
if (bridge_len > _settings_game.construction.max_bridge_length) return_cmd_error(STR_ERROR_BRIDGE_TOO_LONG);
}