From f47ead768360c75e737434a3acde5b1012298e51 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Thu, 24 Jul 2025 02:10:00 +0100 Subject: [PATCH] Codechange: Implement tile proc handler to test for building bridge over tile. --- src/clear_cmd.cpp | 6 ++++ src/industry_cmd.cpp | 1 + src/object_cmd.cpp | 11 +++++++ src/rail_cmd.cpp | 6 ++++ src/road_cmd.cpp | 6 ++++ src/station_cmd.cpp | 1 + src/tile_cmd.h | 3 ++ src/town_cmd.cpp | 1 + src/tree_cmd.cpp | 1 + src/tunnelbridge_cmd.cpp | 65 ++++++++++++++++------------------------ src/void_cmd.cpp | 1 + src/water_cmd.cpp | 6 ++++ 12 files changed, 68 insertions(+), 40 deletions(-) diff --git a/src/clear_cmd.cpp b/src/clear_cmd.cpp index cb817bf0a3..65957a801a 100644 --- a/src/clear_cmd.cpp +++ b/src/clear_cmd.cpp @@ -390,6 +390,11 @@ static CommandCost TerraformTile_Clear(TileIndex tile, DoCommandFlags flags, int return Command::Do(flags, tile); } +static CommandCost CheckBuildAbove_Clear(TileIndex, DoCommandFlags, Axis, int) +{ + return CommandCost(); +} + extern const TileTypeProcs _tile_type_clear_procs = { DrawTile_Clear, ///< draw_tile_proc GetSlopePixelZ_Clear, ///< get_slope_z_proc @@ -405,4 +410,5 @@ extern const TileTypeProcs _tile_type_clear_procs = { nullptr, ///< vehicle_enter_tile_proc GetFoundation_Clear, ///< get_foundation_proc TerraformTile_Clear, ///< terraform_tile_proc + CheckBuildAbove_Clear, // check_build_above_proc }; diff --git a/src/industry_cmd.cpp b/src/industry_cmd.cpp index 19a9976124..9cdec5c2c4 100644 --- a/src/industry_cmd.cpp +++ b/src/industry_cmd.cpp @@ -3205,6 +3205,7 @@ extern const TileTypeProcs _tile_type_industry_procs = { nullptr, // vehicle_enter_tile_proc GetFoundation_Industry, // get_foundation_proc TerraformTile_Industry, // terraform_tile_proc + nullptr, // check_build_above_proc }; bool IndustryCompare::operator() (const IndustryListEntry &lhs, const IndustryListEntry &rhs) const diff --git a/src/object_cmd.cpp b/src/object_cmd.cpp index 15693c90f0..92648b8629 100644 --- a/src/object_cmd.cpp +++ b/src/object_cmd.cpp @@ -929,6 +929,16 @@ static CommandCost TerraformTile_Object(TileIndex tile, DoCommandFlags flags, in return Command::Do(flags, tile); } +static CommandCost CheckBuildAbove_Object(TileIndex tile, DoCommandFlags flags, Axis, int height) +{ + const ObjectSpec *spec = ObjectSpec::GetByTile(tile); + if (spec->flags.Test(ObjectFlag::AllowUnderBridge) && GetTileMaxZ(tile) + spec->height <= height) { + return CommandCost(); + } + + return Command::Do(flags, tile); +} + extern const TileTypeProcs _tile_type_object_procs = { DrawTile_Object, // draw_tile_proc GetSlopePixelZ_Object, // get_slope_z_proc @@ -944,4 +954,5 @@ extern const TileTypeProcs _tile_type_object_procs = { nullptr, // vehicle_enter_tile_proc GetFoundation_Object, // get_foundation_proc TerraformTile_Object, // terraform_tile_proc + CheckBuildAbove_Object, // check_build_above_proc }; diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 0762099ea4..09d4649402 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -3070,6 +3070,11 @@ static CommandCost TerraformTile_Track(TileIndex tile, DoCommandFlags flags, int return Command::Do(flags, tile); } +static CommandCost CheckBuildAbove_Track(TileIndex tile, DoCommandFlags flags, Axis, int) +{ + if (IsPlainRail(tile)) return CommandCost(); + return Command::Do(flags, tile); +} extern const TileTypeProcs _tile_type_rail_procs = { DrawTile_Track, // draw_tile_proc @@ -3086,4 +3091,5 @@ extern const TileTypeProcs _tile_type_rail_procs = { VehicleEnter_Track, // vehicle_enter_tile_proc GetFoundation_Track, // get_foundation_proc TerraformTile_Track, // terraform_tile_proc + CheckBuildAbove_Track, // check_build_above_proc }; diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 49c2e9f69d..8efa2943df 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -2616,6 +2616,11 @@ CommandCost CmdConvertRoad(DoCommandFlags flags, TileIndex tile, TileIndex area_ return found_convertible_road ? cost : error; } +static CommandCost CheckBuildAbove_Road(TileIndex tile, DoCommandFlags flags, Axis, int) +{ + if (!IsRoadDepot(tile)) return CommandCost(); + return Command::Do(flags, tile); +} /** Tile callback functions for road tiles */ extern const TileTypeProcs _tile_type_road_procs = { @@ -2633,4 +2638,5 @@ extern const TileTypeProcs _tile_type_road_procs = { VehicleEnter_Road, // vehicle_enter_tile_proc GetFoundation_Road, // get_foundation_proc TerraformTile_Road, // terraform_tile_proc + CheckBuildAbove_Road, // check_build_above_proc }; diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 1ca967f7d8..6bde45d1fe 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -5177,4 +5177,5 @@ extern const TileTypeProcs _tile_type_station_procs = { VehicleEnter_Station, // vehicle_enter_tile_proc GetFoundation_Station, // get_foundation_proc TerraformTile_Station, // terraform_tile_proc + nullptr, // check_build_above_proc }; diff --git a/src/tile_cmd.h b/src/tile_cmd.h index fb60cec092..73db58e679 100644 --- a/src/tile_cmd.h +++ b/src/tile_cmd.h @@ -135,6 +135,8 @@ typedef Foundation GetFoundationProc(TileIndex tile, Slope tileh); */ typedef CommandCost TerraformTileProc(TileIndex tile, DoCommandFlags flags, int z_new, Slope tileh_new); +using CheckBuildAboveProc = CommandCost(TileIndex tile, DoCommandFlags flags, Axis axis, int height); + /** * Set of callback functions for performing tile operations of a given tile type. * @see TileType @@ -154,6 +156,7 @@ struct TileTypeProcs { VehicleEnterTileProc *vehicle_enter_tile_proc; ///< Called when a vehicle enters a tile GetFoundationProc *get_foundation_proc; TerraformTileProc *terraform_tile_proc; ///< Called when a terraforming operation is about to take place + CheckBuildAboveProc *check_build_above_proc; }; extern const TileTypeProcs * const _tile_type_procs[16]; diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index cf74aeb35f..f1161ca07d 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -4130,6 +4130,7 @@ extern const TileTypeProcs _tile_type_town_procs = { nullptr, // vehicle_enter_tile_proc GetFoundation_Town, // get_foundation_proc TerraformTile_Town, // terraform_tile_proc + nullptr, // check_build_above_proc }; std::span GetTownDrawTileData() diff --git a/src/tree_cmd.cpp b/src/tree_cmd.cpp index ad7203dc00..49901b8796 100644 --- a/src/tree_cmd.cpp +++ b/src/tree_cmd.cpp @@ -1031,4 +1031,5 @@ extern const TileTypeProcs _tile_type_trees_procs = { nullptr, // vehicle_enter_tile_proc GetFoundation_Trees, // get_foundation_proc TerraformTile_Trees, // terraform_tile_proc + nullptr, // check_build_above_proc }; diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index 3184393fdd..9a7a6d926c 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -12,7 +12,6 @@ */ #include "stdafx.h" -#include "newgrf_object.h" #include "viewport_func.h" #include "command_func.h" #include "town.h" @@ -20,7 +19,6 @@ #include "ship.h" #include "roadveh.h" #include "pathfinder/yapf/yapf_cache.h" -#include "pathfinder/water_regions.h" #include "newgrf_sound.h" #include "autoslope.h" #include "tunnelbridge_map.h" @@ -39,7 +37,6 @@ #include "object_base.h" #include "water.h" #include "company_gui.h" -#include "station_func.h" #include "tunnelbridge_cmd.h" #include "landscape_cmd.h" #include "terraform_cmd.h" @@ -278,6 +275,16 @@ static Money TunnelBridgeClearCost(TileIndex tile, Price base_price) return base_cost; } +static CommandCost CheckBuildAbove(TileIndex tile, DoCommandFlags flags, Axis axis, int height) +{ + if (_tile_type_procs[GetTileType(tile)]->check_build_above_proc != nullptr) { + return _tile_type_procs[GetTileType(tile)]->check_build_above_proc(tile, flags, axis, height); + } + + /* A tile without a handler must be cleared. */ + return Command::Do(flags, tile); +} + /** * Build a Bridge * @param flags type of operation @@ -484,43 +491,9 @@ CommandCost CmdBuildBridge(DoCommandFlags flags, TileIndex tile_end, TileIndex t return CommandCost(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST); } - switch (GetTileType(tile)) { - case MP_WATER: - if (!IsWater(tile) && !IsCoast(tile)) goto not_valid_below; - break; - - case MP_RAILWAY: - if (!IsPlainRail(tile)) goto not_valid_below; - break; - - case MP_ROAD: - if (IsRoadDepot(tile)) goto not_valid_below; - break; - - case MP_TUNNELBRIDGE: - if (IsTunnel(tile)) break; - if (direction == DiagDirToAxis(GetTunnelBridgeDirection(tile))) goto not_valid_below; - if (z_start < GetBridgeHeight(tile)) goto not_valid_below; - break; - - case MP_OBJECT: { - const ObjectSpec *spec = ObjectSpec::GetByTile(tile); - if (!spec->flags.Test(ObjectFlag::AllowUnderBridge)) goto not_valid_below; - if (GetTileMaxZ(tile) + spec->height > z_start) goto not_valid_below; - break; - } - - case MP_CLEAR: - break; - - default: - not_valid_below:; - /* try and clear the middle landscape */ - ret = Command::Do(flags, tile); - if (ret.Failed()) return ret; - cost.AddCost(ret.GetCost()); - break; - } + ret = CheckBuildAbove(tile, flags, direction, z_start); + if (ret.Failed()) return ret; + cost.AddCost(ret.GetCost()); if (flags.Test(DoCommandFlag::Execute)) { /* We do this here because when replacing a bridge with another @@ -2084,6 +2057,17 @@ static CommandCost TerraformTile_TunnelBridge(TileIndex tile, DoCommandFlags fla return Command::Do(flags, tile); } +static CommandCost CheckBuildAbove_TunnelBridge(TileIndex tile, DoCommandFlags flags, Axis axis, int height) +{ + if (IsTunnel(tile)) return CommandCost(); + + if (axis != DiagDirToAxis(GetTunnelBridgeDirection(tile)) && height >= GetBridgeHeight(tile)) { + return CommandCost(); + } + + return Command::Do(flags, tile); +} + extern const TileTypeProcs _tile_type_tunnelbridge_procs = { DrawTile_TunnelBridge, // draw_tile_proc GetSlopePixelZ_TunnelBridge, // get_slope_z_proc @@ -2099,4 +2083,5 @@ extern const TileTypeProcs _tile_type_tunnelbridge_procs = { VehicleEnter_TunnelBridge, // vehicle_enter_tile_proc GetFoundation_TunnelBridge, // get_foundation_proc TerraformTile_TunnelBridge, // terraform_tile_proc + CheckBuildAbove_TunnelBridge, // check_build_above_proc }; diff --git a/src/void_cmd.cpp b/src/void_cmd.cpp index 5334824997..2665f4d2bf 100644 --- a/src/void_cmd.cpp +++ b/src/void_cmd.cpp @@ -87,4 +87,5 @@ extern const TileTypeProcs _tile_type_void_procs = { nullptr, // vehicle_enter_tile_proc GetFoundation_Void, // get_foundation_proc TerraformTile_Void, // terraform_tile_proc + nullptr, // check_build_above_proc }; diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index 756a1d1d38..de1cde88d3 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -1410,6 +1410,11 @@ static CommandCost TerraformTile_Water(TileIndex tile, DoCommandFlags flags, int return Command::Do(flags, tile); } +static CommandCost CheckBuildAbove_Water(TileIndex tile, DoCommandFlags flags, Axis, int) +{ + if (IsWater(tile) || IsCoast(tile)) return CommandCost(); + return Command::Do(flags, tile); +} extern const TileTypeProcs _tile_type_water_procs = { DrawTile_Water, // draw_tile_proc @@ -1426,4 +1431,5 @@ extern const TileTypeProcs _tile_type_water_procs = { VehicleEnter_Water, // vehicle_enter_tile_proc GetFoundation_Water, // get_foundation_proc TerraformTile_Water, // terraform_tile_proc + CheckBuildAbove_Water, // check_build_above_proc };