From 1031be907845ebe1787409de693814f80cf10952 Mon Sep 17 00:00:00 2001 From: Michael Steenbeek Date: Tue, 8 Jun 2021 22:02:17 +0200 Subject: [PATCH] Fix #14751: Height limitation also affects trees --- distribution/changelog.txt | 1 + src/openrct2/actions/LargeSceneryPlaceAction.cpp | 4 ++-- src/openrct2/actions/SmallSceneryPlaceAction.cpp | 4 ++-- src/openrct2/object/LargeSceneryObject.cpp | 1 + src/openrct2/world/Map.cpp | 8 ++++---- src/openrct2/world/Map.h | 5 +++-- src/openrct2/world/Scenery.h | 1 + 7 files changed, 14 insertions(+), 10 deletions(-) diff --git a/distribution/changelog.txt b/distribution/changelog.txt index 0208bbd933..ba845825b4 100644 --- a/distribution/changelog.txt +++ b/distribution/changelog.txt @@ -9,6 +9,7 @@ - Feature: [#14731] Opaque water (like in RCT1). - Change: [#14496] [Plugin] Rename Object to LoadedObject to fix conflicts with Typescript's Object interface. - Change: [#14536] [Plugin] Rename ListView to ListViewWidget to make it consistent with names of other widgets. +- Change: [#14751] “No construction above tree height” limitation now allows placing high trees. - Fix: [#11829] Visual glitches and crashes when using RCT1 assets from mismatched or corrupt CSG1.DAT and CSG1i.DAT files. - Fix: [#13581] Opening the Options menu causes a noticeable drop in FPS. - Fix: [#13894] Block brakes do not animate. diff --git a/src/openrct2/actions/LargeSceneryPlaceAction.cpp b/src/openrct2/actions/LargeSceneryPlaceAction.cpp index ef01934c08..e2c877f03c 100644 --- a/src/openrct2/actions/LargeSceneryPlaceAction.cpp +++ b/src/openrct2/actions/LargeSceneryPlaceAction.cpp @@ -162,7 +162,7 @@ GameActions::Result::Ptr LargeSceneryPlaceAction::Query() const QuarterTile quarterTile = QuarterTile{ static_cast(tile->flags >> 12), 0 }.Rotate(_loc.direction); if (!map_can_construct_with_clear_at( { curTile, zLow, zHigh }, &map_place_scenery_clear_func, quarterTile, GetFlags(), &supportsCost, - CREATE_CROSSING_MODE_NONE)) + CREATE_CROSSING_MODE_NONE, (sceneryEntry->flags & LARGE_SCENERY_FLAG_IS_TREE) != 0)) { return std::make_unique( GameActions::Status::NoClearance, gGameCommandErrorText, gCommonFormatArgs); @@ -260,7 +260,7 @@ GameActions::Result::Ptr LargeSceneryPlaceAction::Execute() const QuarterTile quarterTile = QuarterTile{ static_cast(tile->flags >> 12), 0 }.Rotate(_loc.direction); if (!map_can_construct_with_clear_at( { curTile, zLow, zHigh }, &map_place_scenery_clear_func, quarterTile, GetFlags(), &supportsCost, - CREATE_CROSSING_MODE_NONE)) + CREATE_CROSSING_MODE_NONE, (sceneryEntry->flags & LARGE_SCENERY_FLAG_IS_TREE) != 0)) { return std::make_unique( GameActions::Status::NoClearance, gGameCommandErrorText, gCommonFormatArgs); diff --git a/src/openrct2/actions/SmallSceneryPlaceAction.cpp b/src/openrct2/actions/SmallSceneryPlaceAction.cpp index 346f10249b..b96da2620f 100644 --- a/src/openrct2/actions/SmallSceneryPlaceAction.cpp +++ b/src/openrct2/actions/SmallSceneryPlaceAction.cpp @@ -280,7 +280,7 @@ GameActions::Result::Ptr SmallSceneryPlaceAction::Query() const if (!map_can_construct_with_clear_at( { _loc, zLow, zHigh }, &map_place_scenery_clear_func, quarterTile, GetFlags(), &clearCost, - CREATE_CROSSING_MODE_NONE)) + CREATE_CROSSING_MODE_NONE, scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_IS_TREE))) { return std::make_unique( GameActions::Status::Disallowed, gGameCommandErrorText, gCommonFormatArgs); @@ -418,7 +418,7 @@ GameActions::Result::Ptr SmallSceneryPlaceAction::Execute() const if (!map_can_construct_with_clear_at( { _loc, zLow, zHigh }, &map_place_scenery_clear_func, quarterTile, GetFlags() | GAME_COMMAND_FLAG_APPLY, &clearCost, - CREATE_CROSSING_MODE_NONE)) + CREATE_CROSSING_MODE_NONE, scenery_small_entry_has_flag(sceneryEntry, SMALL_SCENERY_FLAG_IS_TREE))) { return std::make_unique( GameActions::Status::Disallowed, gGameCommandErrorText, gCommonFormatArgs); diff --git a/src/openrct2/object/LargeSceneryObject.cpp b/src/openrct2/object/LargeSceneryObject.cpp index 87da9feb8b..fa96ac5535 100644 --- a/src/openrct2/object/LargeSceneryObject.cpp +++ b/src/openrct2/object/LargeSceneryObject.cpp @@ -144,6 +144,7 @@ void LargeSceneryObject::ReadJson(IReadObjectContext* context, json_t& root) { "hasSecondaryColour", LARGE_SCENERY_FLAG_HAS_SECONDARY_COLOUR }, { "isAnimated", LARGE_SCENERY_FLAG_ANIMATED }, { "isPhotogenic", LARGE_SCENERY_FLAG_PHOTOGENIC }, + { "isTree", LARGE_SCENERY_FLAG_IS_TREE }, }); // Tiles diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index 9faa1da254..764351cc54 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -1298,7 +1298,7 @@ void map_obstruction_set_error_text(TileElement* tileElement, GameActions::Resul * bl = bl */ std::unique_ptr MapCanConstructWithClearAt( - const CoordsXYRangedZ& pos, CLEAR_FUNC clearFunc, QuarterTile quarterTile, uint8_t flags, uint8_t crossingMode) + const CoordsXYRangedZ& pos, CLEAR_FUNC clearFunc, QuarterTile quarterTile, uint8_t flags, uint8_t crossingMode, bool isTree) { int32_t northZ, eastZ, baseHeight, southZ, westZ, water_height; northZ = eastZ = baseHeight = southZ = westZ = water_height = 0; @@ -1350,7 +1350,7 @@ std::unique_ptr MapCanConstructWithClearAt( } } loc_68B9B7: - if (gParkFlags & PARK_FLAGS_FORBID_HIGH_CONSTRUCTION) + if (gParkFlags & PARK_FLAGS_FORBID_HIGH_CONSTRUCTION && !isTree) { auto heightFromGround = pos.clearanceZ - tileElement->GetBaseZ(); @@ -1477,9 +1477,9 @@ std::unique_ptr MapCanConstructWithClearAt( bool map_can_construct_with_clear_at( const CoordsXYRangedZ& pos, CLEAR_FUNC clearFunc, QuarterTile quarterTile, uint8_t flags, money32* price, - uint8_t crossingMode) + uint8_t crossingMode, bool isTree) { - auto res = MapCanConstructWithClearAt(pos, clearFunc, quarterTile, flags, crossingMode); + auto res = MapCanConstructWithClearAt(pos, clearFunc, quarterTile, flags, crossingMode, isTree); if (auto message = res->ErrorMessage.AsStringId()) gGameCommandErrorText = *message; else diff --git a/src/openrct2/world/Map.h b/src/openrct2/world/Map.h index 06ed8182c8..384ce7076b 100644 --- a/src/openrct2/world/Map.h +++ b/src/openrct2/world/Map.h @@ -237,9 +237,10 @@ int32_t map_place_non_scenery_clear_func(TileElement** tile_element, const Coord int32_t map_place_scenery_clear_func(TileElement** tile_element, const CoordsXY& coords, uint8_t flags, money32* price); bool map_can_construct_with_clear_at( const CoordsXYRangedZ& pos, CLEAR_FUNC clearFunc, QuarterTile quarterTile, uint8_t flags, money32* price, - uint8_t crossingMode); + uint8_t crossingMode, bool isTree = false); std::unique_ptr MapCanConstructWithClearAt( - const CoordsXYRangedZ& pos, CLEAR_FUNC clearFunc, QuarterTile quarterTile, uint8_t flags, uint8_t crossingMode); + const CoordsXYRangedZ& pos, CLEAR_FUNC clearFunc, QuarterTile quarterTile, uint8_t flags, uint8_t crossingMode, + bool isTree = false); std::unique_ptr MapCanConstructAt(const CoordsXYRangedZ& pos, QuarterTile bl); int32_t map_can_construct_at(const CoordsXYRangedZ& pos, QuarterTile bl); diff --git a/src/openrct2/world/Scenery.h b/src/openrct2/world/Scenery.h index 375c2ce153..b26027cb3b 100644 --- a/src/openrct2/world/Scenery.h +++ b/src/openrct2/world/Scenery.h @@ -96,6 +96,7 @@ enum LARGE_SCENERY_FLAGS LARGE_SCENERY_FLAG_3D_TEXT = (1 << 2), // 0x4 LARGE_SCENERY_FLAG_ANIMATED = (1 << 3), // 0x8 LARGE_SCENERY_FLAG_PHOTOGENIC = (1 << 4), // 0x10 + LARGE_SCENERY_FLAG_IS_TREE = (1 << 5), // 0x20 }; enum WALL_SCENERY_FLAGS