From fb8c42f3c2d0c417677ddd4ac4f042959cfdc318 Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Tue, 13 Aug 2019 20:51:37 +0100 Subject: [PATCH] Fix #9557. Refactor map_is_location_at_edge and tile_element_insert --- src/openrct2/Game.cpp | 2 +- src/openrct2/actions/BannerPlaceAction.hpp | 2 +- src/openrct2/actions/FootpathPlaceAction.hpp | 2 +- .../actions/FootpathPlaceFromTrackAction.hpp | 2 +- src/openrct2/actions/LandLowerAction.hpp | 3 +- src/openrct2/actions/LandRaiseAction.hpp | 2 +- src/openrct2/actions/LandSmoothAction.hpp | 10 +---- .../actions/LargeSceneryPlaceAction.hpp | 2 +- src/openrct2/actions/MazeSetTrackAction.hpp | 2 +- .../actions/PlaceParkEntranceAction.hpp | 2 +- .../actions/RideEntranceExitPlaceAction.hpp | 2 +- .../actions/SmallSceneryPlaceAction.hpp | 2 +- src/openrct2/actions/TrackPlaceAction.hpp | 3 +- src/openrct2/actions/WallPlaceAction.hpp | 4 +- src/openrct2/ride/TrackDesign.cpp | 2 +- src/openrct2/world/Map.cpp | 43 +++++++++---------- src/openrct2/world/Map.h | 8 ++-- src/openrct2/world/MapGen.cpp | 2 +- src/openrct2/world/TileInspector.cpp | 4 +- 19 files changed, 46 insertions(+), 53 deletions(-) diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index 77f67eb46b..bea9e6e3e4 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -643,7 +643,7 @@ void game_fix_save_vars() if (surfaceElement == nullptr) { log_error("Null map element at x = %d and y = %d. Fixing...", x, y); - auto tileElement = tile_element_insert(x, y, 14, 0); + auto tileElement = tile_element_insert({ x, y, 14 }, 0); if (tileElement == nullptr) { log_error("Unable to fix: Map element limit reached."); diff --git a/src/openrct2/actions/BannerPlaceAction.hpp b/src/openrct2/actions/BannerPlaceAction.hpp index aa7ed0e7a0..3892953103 100644 --- a/src/openrct2/actions/BannerPlaceAction.hpp +++ b/src/openrct2/actions/BannerPlaceAction.hpp @@ -137,7 +137,7 @@ public: return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_CANT_POSITION_THIS_HERE); } - TileElement* newTileElement = tile_element_insert(_loc.x / 32, _loc.y / 32, baseHeight, 0); + TileElement* newTileElement = tile_element_insert({ _loc.x / 32, _loc.y / 32, baseHeight }, 0); assert(newTileElement != nullptr); banner->flags = 0; diff --git a/src/openrct2/actions/FootpathPlaceAction.hpp b/src/openrct2/actions/FootpathPlaceAction.hpp index 67b7981704..66817a558d 100644 --- a/src/openrct2/actions/FootpathPlaceAction.hpp +++ b/src/openrct2/actions/FootpathPlaceAction.hpp @@ -332,7 +332,7 @@ private: } else { - auto tileElement = tile_element_insert(_loc.x / 32, _loc.y / 32, zLow, 0b1111); + auto tileElement = tile_element_insert({ _loc.x / 32, _loc.y / 32, zLow }, 0b1111); assert(tileElement != nullptr); tileElement->SetType(TILE_ELEMENT_TYPE_PATH); PathElement* pathElement = tileElement->AsPath(); diff --git a/src/openrct2/actions/FootpathPlaceFromTrackAction.hpp b/src/openrct2/actions/FootpathPlaceFromTrackAction.hpp index 6eb5cddb77..d53f845474 100644 --- a/src/openrct2/actions/FootpathPlaceFromTrackAction.hpp +++ b/src/openrct2/actions/FootpathPlaceFromTrackAction.hpp @@ -246,7 +246,7 @@ private: } else { - auto tileElement = tile_element_insert(_loc.x / 32, _loc.y / 32, zLow, 0b1111); + auto tileElement = tile_element_insert({ _loc.x / 32, _loc.y / 32, zLow }, 0b1111); assert(tileElement != nullptr); tileElement->SetType(TILE_ELEMENT_TYPE_PATH); PathElement* pathElement = tileElement->AsPath(); diff --git a/src/openrct2/actions/LandLowerAction.hpp b/src/openrct2/actions/LandLowerAction.hpp index 871a2c9c4b..132a4b077e 100644 --- a/src/openrct2/actions/LandLowerAction.hpp +++ b/src/openrct2/actions/LandLowerAction.hpp @@ -91,8 +91,7 @@ private: audio_play_sound_at_location(SoundId::PlaceItem, _coords.x, _coords.y, tile_element_height(_coords)); } - uint8_t maxHeight = map_get_highest_land_height( - validRange.GetLeft(), validRange.GetRight(), validRange.GetTop(), validRange.GetBottom()); + uint8_t maxHeight = map_get_highest_land_height(validRange); for (int32_t y = validRange.GetTop(); y <= validRange.GetBottom(); y += 32) { diff --git a/src/openrct2/actions/LandRaiseAction.hpp b/src/openrct2/actions/LandRaiseAction.hpp index 19ff6031b2..4a7e8f5a8d 100644 --- a/src/openrct2/actions/LandRaiseAction.hpp +++ b/src/openrct2/actions/LandRaiseAction.hpp @@ -93,7 +93,7 @@ private: } uint8_t minHeight = map_get_lowest_land_height( - validRange.GetLeft(), validRange.GetRight(), validRange.GetTop(), validRange.GetBottom()); + validRange); for (int32_t y = validRange.GetTop(); y <= validRange.GetBottom(); y += 32) { diff --git a/src/openrct2/actions/LandSmoothAction.hpp b/src/openrct2/actions/LandSmoothAction.hpp index 2d5449ece0..4db4265618 100644 --- a/src/openrct2/actions/LandSmoothAction.hpp +++ b/src/openrct2/actions/LandSmoothAction.hpp @@ -362,14 +362,8 @@ private: { case MAP_SELECT_TYPE_FULL: { - uint8_t minHeight = heightOffset - + map_get_lowest_land_height( - validRange.GetLeft(), validRange.GetRight(), validRange.GetTop(), - validRange.GetBottom()); - uint8_t maxHeight = heightOffset - + map_get_highest_land_height( - validRange.GetLeft(), validRange.GetRight(), validRange.GetTop(), - validRange.GetBottom()); + uint8_t minHeight = heightOffset + map_get_lowest_land_height(validRange); + uint8_t maxHeight = heightOffset + map_get_highest_land_height(validRange); // Smooth the 4 corners { // top-left diff --git a/src/openrct2/actions/LargeSceneryPlaceAction.hpp b/src/openrct2/actions/LargeSceneryPlaceAction.hpp index dee96eefc6..9441994568 100644 --- a/src/openrct2/actions/LargeSceneryPlaceAction.hpp +++ b/src/openrct2/actions/LargeSceneryPlaceAction.hpp @@ -317,7 +317,7 @@ public: } TileElement* newTileElement = tile_element_insert( - curTile.x / 32, curTile.y / 32, zLow, quarterTile.GetBaseQuarterOccupied()); + { curTile.x / 32, curTile.y / 32, zLow }, quarterTile.GetBaseQuarterOccupied()); Guard::Assert(newTileElement != nullptr); map_animation_create(MAP_ANIMATION_TYPE_LARGE_SCENERY, curTile.x, curTile.y, zLow); newTileElement->SetType(TILE_ELEMENT_TYPE_LARGE_SCENERY); diff --git a/src/openrct2/actions/MazeSetTrackAction.hpp b/src/openrct2/actions/MazeSetTrackAction.hpp index 5b9ed130d8..dc05b8a3d2 100644 --- a/src/openrct2/actions/MazeSetTrackAction.hpp +++ b/src/openrct2/actions/MazeSetTrackAction.hpp @@ -216,7 +216,7 @@ public: uint16_t flooredX = floor2(_loc.x, 32); uint16_t flooredY = floor2(_loc.y, 32); - tileElement = tile_element_insert(_loc.x / 32, _loc.y / 32, baseHeight, 0xF); + tileElement = tile_element_insert({ _loc.x / 32, _loc.y / 32, baseHeight }, 0xF); assert(tileElement != nullptr); tileElement->clearance_height = clearanceHeight; diff --git a/src/openrct2/actions/PlaceParkEntranceAction.hpp b/src/openrct2/actions/PlaceParkEntranceAction.hpp index e76ca7d00c..1048caf9de 100644 --- a/src/openrct2/actions/PlaceParkEntranceAction.hpp +++ b/src/openrct2/actions/PlaceParkEntranceAction.hpp @@ -146,7 +146,7 @@ public: surfaceElement->SetOwnership(OWNERSHIP_UNOWNED); } - TileElement* newElement = tile_element_insert(entranceLoc.x / 32, entranceLoc.y / 32, zLow, 0xF); + TileElement* newElement = tile_element_insert({ entranceLoc.x / 32, entranceLoc.y / 32, zLow }, 0xF); Guard::Assert(newElement != nullptr); newElement->SetType(TILE_ELEMENT_TYPE_ENTRANCE); auto entranceElement = newElement->AsEntrance(); diff --git a/src/openrct2/actions/RideEntranceExitPlaceAction.hpp b/src/openrct2/actions/RideEntranceExitPlaceAction.hpp index 7e10e9502a..91644811ef 100644 --- a/src/openrct2/actions/RideEntranceExitPlaceAction.hpp +++ b/src/openrct2/actions/RideEntranceExitPlaceAction.hpp @@ -192,7 +192,7 @@ public: res->Position.z = tile_element_height({ _loc.x, _loc.y }); res->ExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; - TileElement* tileElement = tile_element_insert(_loc.x / 32, _loc.y / 32, z / 8, 0b1111); + TileElement* tileElement = tile_element_insert({ _loc.x / 32, _loc.y / 32, z / 8 }, 0b1111); assert(tileElement != nullptr); tileElement->SetType(TILE_ELEMENT_TYPE_ENTRANCE); tileElement->SetDirection(_direction); diff --git a/src/openrct2/actions/SmallSceneryPlaceAction.hpp b/src/openrct2/actions/SmallSceneryPlaceAction.hpp index 603aabd8c8..b5d047a654 100644 --- a/src/openrct2/actions/SmallSceneryPlaceAction.hpp +++ b/src/openrct2/actions/SmallSceneryPlaceAction.hpp @@ -430,7 +430,7 @@ public: res->ExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING; res->Cost = (sceneryEntry->small_scenery.price * 10) + clearCost; - TileElement* newElement = tile_element_insert(_loc.x / 32, _loc.y / 32, zLow, quarterTile.GetBaseQuarterOccupied()); + TileElement* newElement = tile_element_insert({ _loc.x / 32, _loc.y / 32, zLow }, quarterTile.GetBaseQuarterOccupied()); assert(newElement != nullptr); res->tileElement = newElement; newElement->SetType(TILE_ELEMENT_TYPE_SMALL_SCENERY); diff --git a/src/openrct2/actions/TrackPlaceAction.hpp b/src/openrct2/actions/TrackPlaceAction.hpp index 57c1a1a8bb..83479da9eb 100644 --- a/src/openrct2/actions/TrackPlaceAction.hpp +++ b/src/openrct2/actions/TrackPlaceAction.hpp @@ -579,7 +579,8 @@ public: ride->overall_view.y = mapLoc.y / 32; } - auto tileElement = tile_element_insert(mapLoc.x / 32, mapLoc.y / 32, baseZ, quarterTile.GetBaseQuarterOccupied()); + auto tileElement = tile_element_insert( + { mapLoc.x / 32, mapLoc.y / 32, baseZ }, quarterTile.GetBaseQuarterOccupied()); assert(tileElement != nullptr); tileElement->clearance_height = clearanceZ; tileElement->SetType(TILE_ELEMENT_TYPE_TRACK); diff --git a/src/openrct2/actions/WallPlaceAction.hpp b/src/openrct2/actions/WallPlaceAction.hpp index e4bd667e80..3390f1d4da 100644 --- a/src/openrct2/actions/WallPlaceAction.hpp +++ b/src/openrct2/actions/WallPlaceAction.hpp @@ -394,7 +394,7 @@ public: return std::make_unique(GA_ERROR::NO_FREE_ELEMENTS, gGameCommandErrorText); } - TileElement* tileElement = tile_element_insert(_loc.x / 32, _loc.y / 32, targetHeight / 8, 0); + TileElement* tileElement = tile_element_insert({ _loc.x / 32, _loc.y / 32, targetHeight / 8 }, 0); assert(tileElement != nullptr); map_animation_create(MAP_ANIMATION_TYPE_WALL, _loc.x, _loc.y, targetHeight / 8); @@ -613,7 +613,7 @@ private: *wallAcrossTrack = false; gMapGroundFlags = ELEMENT_IS_ABOVE_GROUND; - if (map_is_location_at_edge(_loc.x, _loc.y)) + if (map_is_location_at_edge({ _loc.x, _loc.y })) { gGameCommandErrorText = STR_OFF_EDGE_OF_MAP; return false; diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index 86124c92dd..2bbac26e9f 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -2184,7 +2184,7 @@ static money32 place_maze_design(uint8_t flags, Ride* ride, uint16_t mazeEntry, int32_t fx = floor2(x, 32); int32_t fy = floor2(y, 32); int32_t fz = z >> 3; - TileElement* tileElement = tile_element_insert(fx >> 5, fy >> 5, fz, 15); + TileElement* tileElement = tile_element_insert({ fx >> 5, fy >> 5, fz }, 15); tileElement->clearance_height = fz + 4; tileElement->SetType(TILE_ELEMENT_TYPE_TRACK); tileElement->AsTrack()->SetTrackType(TRACK_ELEM_MAZE); diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index 5dd5b6116e..91e1147909 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -914,17 +914,16 @@ int32_t tile_element_get_corner_height(const SurfaceElement* surfaceElement, int return map_get_corner_height(z, slope, direction); } -uint8_t map_get_lowest_land_height(int32_t xMin, int32_t xMax, int32_t yMin, int32_t yMax) +uint8_t map_get_lowest_land_height(const MapRange range) { - xMin = std::max(xMin, 32); - yMin = std::max(yMin, 32); - xMax = std::min(xMax, (int32_t)gMapSizeMaxXY); - yMax = std::min(yMax, (int32_t)gMapSizeMaxXY); + MapRange validRange = { std::max(range.GetLeft(), 32), std::max(range.GetTop(), 32), + std::min(range.GetRight(), (int32_t)gMapSizeMaxXY), + std::min(range.GetBottom(), (int32_t)gMapSizeMaxXY) }; uint8_t min_height = 0xFF; - for (int32_t yi = yMin; yi <= yMax; yi += 32) + for (int32_t yi = validRange.GetTop(); yi <= validRange.GetBottom(); yi += 32) { - for (int32_t xi = xMin; xi <= xMax; xi += 32) + for (int32_t xi = validRange.GetLeft(); xi <= validRange.GetRight(); xi += 32) { auto* surfaceElement = map_get_surface_element_at({ xi, yi }); if (surfaceElement != nullptr && min_height > surfaceElement->base_height) @@ -936,17 +935,16 @@ uint8_t map_get_lowest_land_height(int32_t xMin, int32_t xMax, int32_t yMin, int return min_height; } -uint8_t map_get_highest_land_height(int32_t xMin, int32_t xMax, int32_t yMin, int32_t yMax) +uint8_t map_get_highest_land_height(const MapRange range) { - xMin = std::max(xMin, 32); - yMin = std::max(yMin, 32); - xMax = std::min(xMax, (int32_t)gMapSizeMaxXY); - yMax = std::min(yMax, (int32_t)gMapSizeMaxXY); + MapRange validRange = { std::max(range.GetLeft(), 32), std::max(range.GetTop(), 32), + std::min(range.GetRight(), (int32_t)gMapSizeMaxXY), + std::min(range.GetBottom(), (int32_t)gMapSizeMaxXY) }; uint8_t max_height = 0; - for (int32_t yi = yMin; yi <= yMax; yi += 32) + for (int32_t yi = validRange.GetTop(); yi <= validRange.GetBottom(); yi += 32) { - for (int32_t xi = xMin; xi <= xMax; xi += 32) + for (int32_t xi = validRange.GetLeft(); xi <= validRange.GetRight(); xi += 32) { auto* surfaceElement = map_get_surface_element_at({ xi, yi }); if (surfaceElement != nullptr) @@ -964,9 +962,10 @@ uint8_t map_get_highest_land_height(int32_t xMin, int32_t xMax, int32_t yMin, in return max_height; } -bool map_is_location_at_edge(int32_t x, int32_t y) +bool map_is_location_at_edge(const CoordsXY loc) { - return x < 32 || y < 32 || x >= ((MAXIMUM_MAP_SIZE_TECHNICAL - 1) * 32) || y >= ((MAXIMUM_MAP_SIZE_TECHNICAL - 1) * 32); + return loc.x < 32 || loc.y < 32 || loc.x >= ((MAXIMUM_MAP_SIZE_TECHNICAL - 1) * 32) + || loc.y >= ((MAXIMUM_MAP_SIZE_TECHNICAL - 1) * 32); } /** @@ -1203,7 +1202,7 @@ bool map_check_free_elements_and_reorganise(int32_t numElements) * * rct2: 0x0068B1F6 */ -TileElement* tile_element_insert(int32_t x, int32_t y, int32_t z, int32_t flags) +TileElement* tile_element_insert(const TileCoordsXYZ loc, int32_t flags) { TileElement *originalTileElement, *newTileElement, *insertedElement; @@ -1214,13 +1213,13 @@ TileElement* tile_element_insert(int32_t x, int32_t y, int32_t z, int32_t flags) } newTileElement = gNextFreeTileElement; - originalTileElement = gTileElementTilePointers[y * MAXIMUM_MAP_SIZE_TECHNICAL + x]; + originalTileElement = gTileElementTilePointers[loc.y * MAXIMUM_MAP_SIZE_TECHNICAL + loc.x]; // Set tile index pointer to point to new element block - gTileElementTilePointers[y * MAXIMUM_MAP_SIZE_TECHNICAL + x] = newTileElement; + gTileElementTilePointers[loc.y * MAXIMUM_MAP_SIZE_TECHNICAL + loc.x] = newTileElement; // Copy all elements that are below the insert height - while (z >= originalTileElement->base_height) + while (loc.z >= originalTileElement->base_height) { // Copy over map element *newTileElement = *originalTileElement; @@ -1240,9 +1239,9 @@ TileElement* tile_element_insert(int32_t x, int32_t y, int32_t z, int32_t flags) // Insert new map element insertedElement = newTileElement; newTileElement->type = 0; - newTileElement->base_height = z; + newTileElement->base_height = loc.z; newTileElement->flags = flags; - newTileElement->clearance_height = z; + newTileElement->clearance_height = loc.z; std::memset(&newTileElement->pad_04, 0, sizeof(newTileElement->pad_04)); newTileElement++; diff --git a/src/openrct2/world/Map.h b/src/openrct2/world/Map.h index bb56d07ca9..25e6a28e6c 100644 --- a/src/openrct2/world/Map.h +++ b/src/openrct2/world/Map.h @@ -153,8 +153,8 @@ EntranceElement* map_get_ride_entrance_element_at(int32_t x, int32_t y, int32_t EntranceElement* map_get_ride_exit_element_at(int32_t x, int32_t y, int32_t z, bool ghost); int16_t tile_element_height(const CoordsXY loc); int16_t tile_element_water_height(const CoordsXY loc); -uint8_t map_get_highest_land_height(int32_t xMin, int32_t xMax, int32_t yMin, int32_t yMax); -uint8_t map_get_lowest_land_height(int32_t xMin, int32_t xMax, int32_t yMin, int32_t yMax); +uint8_t map_get_highest_land_height(const MapRange range); +uint8_t map_get_lowest_land_height(const MapRange range); bool map_coord_is_connected(const TileCoordsXYZ loc, uint8_t faceDirection); void map_remove_provisional_elements(); void map_restore_provisional_elements(); @@ -174,7 +174,7 @@ void map_get_bounding_box( void map_invalidate_selection_rect(); void map_reorganise_elements(); bool map_check_free_elements_and_reorganise(int32_t num_elements); -TileElement* tile_element_insert(int32_t x, int32_t y, int32_t z, int32_t flags); +TileElement* tile_element_insert(const TileCoordsXYZ loc, int32_t flags); using CLEAR_FUNC = int32_t (*)(TileElement** tile_element, int32_t x, int32_t y, uint8_t flags, money32* price); @@ -248,7 +248,7 @@ TileElement* map_get_track_element_at_from_ride(int32_t x, int32_t y, int32_t z, TileElement* map_get_track_element_at_with_direction_from_ride( int32_t x, int32_t y, int32_t z, int32_t direction, ride_id_t rideIndex); -bool map_is_location_at_edge(int32_t x, int32_t y); +bool map_is_location_at_edge(const CoordsXY loc); void map_obstruction_set_error_text(TileElement* tileElement); uint16_t check_max_allowable_land_rights_for_tile(uint8_t x, uint8_t y, uint8_t base_z); diff --git a/src/openrct2/world/MapGen.cpp b/src/openrct2/world/MapGen.cpp index 6f9f1a84fd..d9dd688859 100644 --- a/src/openrct2/world/MapGen.cpp +++ b/src/openrct2/world/MapGen.cpp @@ -237,7 +237,7 @@ static void mapgen_place_tree(int32_t type, int32_t x, int32_t y) } surfaceZ = tile_element_height({ x * 32 + 16, y * 32 + 16 }) / 8; - tileElement = tile_element_insert(x, y, surfaceZ, (1 | 2 | 4 | 8)); + tileElement = tile_element_insert({ x, y, surfaceZ }, (1 | 2 | 4 | 8)); assert(tileElement != nullptr); tileElement->clearance_height = surfaceZ + (sceneryEntry->small_scenery.height >> 3); tileElement->SetType(TILE_ELEMENT_TYPE_SMALL_SCENERY); diff --git a/src/openrct2/world/TileInspector.cpp b/src/openrct2/world/TileInspector.cpp index 1d85adbde0..e40676e139 100644 --- a/src/openrct2/world/TileInspector.cpp +++ b/src/openrct2/world/TileInspector.cpp @@ -89,7 +89,7 @@ GameActionResult::Ptr tile_inspector_insert_corrupt_at(CoordsXY loc, int16_t ele { // Create new corrupt element TileElement* corruptElement = tile_element_insert( - loc.x / 32, loc.y / 32, -1, 0); // Ugly hack: -1 guarantees this to be placed first + { loc.x / 32, loc.y / 32, -1 }, 0); // Ugly hack: -1 guarantees this to be placed first if (corruptElement == nullptr) { log_warning("Failed to insert corrupt element."); @@ -320,7 +320,7 @@ GameActionResult::Ptr tile_inspector_paste_element_at(CoordsXY loc, TileElement tile_element_set_banner_index(&element, newBannerIndex); } - TileElement* const pastedElement = tile_element_insert(loc.x / 32, loc.y / 32, element.base_height, 0); + TileElement* const pastedElement = tile_element_insert({ loc.x / 32, loc.y / 32, element.base_height }, 0); bool lastForTile = pastedElement->IsLastForTile(); *pastedElement = element;