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: + + + + +
BitValueMeaning
01Towns may not build this bridge type
12Scripts (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

Action 0 - Railtypes

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