From fd7f9fefca8042e79d76b095dd535349be3f9abf Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Thu, 7 Feb 2019 10:06:17 +0000 Subject: [PATCH] Move Land Set Height over to GameAction Framework --- src/openrct2/Game.cpp | 2 +- src/openrct2/Game.h | 2 +- .../actions/GameActionRegistration.cpp | 2 + src/openrct2/actions/LandSetHeightAction.hpp | 335 ++++++++++++++++++ src/openrct2/world/Map.cpp | 296 ++-------------- src/openrct2/world/Map.h | 4 +- 6 files changed, 372 insertions(+), 269 deletions(-) create mode 100644 src/openrct2/actions/LandSetHeightAction.hpp diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index d2f1dcaeb2..68f848b192 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -1455,7 +1455,7 @@ void game_load_or_quit_no_save_prompt() GAME_COMMAND_POINTER* new_game_command_table[GAME_COMMAND_COUNT] = { nullptr, - game_command_set_land_height, + nullptr, game_pause_toggle, game_command_place_track, game_command_remove_track, diff --git a/src/openrct2/Game.h b/src/openrct2/Game.h index f89d11ae7e..9fa682e467 100644 --- a/src/openrct2/Game.h +++ b/src/openrct2/Game.h @@ -19,7 +19,7 @@ struct rct_s6_data; enum GAME_COMMAND { GAME_COMMAND_SET_RIDE_APPEARANCE, // GA - GAME_COMMAND_SET_LAND_HEIGHT, + GAME_COMMAND_SET_LAND_HEIGHT, // GA GAME_COMMAND_TOGGLE_PAUSE, GAME_COMMAND_PLACE_TRACK, GAME_COMMAND_REMOVE_TRACK, diff --git a/src/openrct2/actions/GameActionRegistration.cpp b/src/openrct2/actions/GameActionRegistration.cpp index 0f113b9faa..f1362424cc 100644 --- a/src/openrct2/actions/GameActionRegistration.cpp +++ b/src/openrct2/actions/GameActionRegistration.cpp @@ -13,6 +13,7 @@ #include "FootpathRemoveAction.hpp" #include "GameAction.h" #include "GuestSetNameAction.hpp" +#include "LandSetHeightAction.hpp" #include "LargeSceneryRemoveAction.hpp" #include "MazeSetTrackAction.hpp" #include "ParkMarketingAction.hpp" @@ -68,6 +69,7 @@ namespace GameActions Register(); Register(); Register(); + Register(); Register(); } } // namespace GameActions diff --git a/src/openrct2/actions/LandSetHeightAction.hpp b/src/openrct2/actions/LandSetHeightAction.hpp new file mode 100644 index 0000000000..a1043a1b41 --- /dev/null +++ b/src/openrct2/actions/LandSetHeightAction.hpp @@ -0,0 +1,335 @@ +/***************************************************************************** + * Copyright (c) 2014-2018 OpenRCT2 developers + * + * For a complete list of all authors, please refer to contributors.md + * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2 + * + * OpenRCT2 is licensed under the GNU General Public License version 3. + *****************************************************************************/ + +#pragma once + +#include "../Context.h" +#include "../interface/Window.h" +#include "../localisation/Localisation.h" +#include "../localisation/StringIds.h" +#include "../ride/RideData.h" +#include "../windows/Intent.h" +#include "../world/Park.h" +#include "../world/Scenery.h" +#include "../world/Sprite.h" +#include "../world/Surface.h" +#include "GameAction.h" + +/** + * + * rct2: 0x00663CB9 + */ +static int32_t map_set_land_height_clear_func( + TileElement** tile_element, [[maybe_unused]] int32_t x, [[maybe_unused]] int32_t y, [[maybe_unused]] uint8_t flags, + [[maybe_unused]] money32* price) +{ + if ((*tile_element)->GetType() == TILE_ELEMENT_TYPE_SURFACE) + return 0; + + if ((*tile_element)->GetType() == TILE_ELEMENT_TYPE_SMALL_SCENERY) + return 0; + + return 1; +} + +DEFINE_GAME_ACTION(LandSetHeightAction, GAME_COMMAND_SET_LAND_HEIGHT, GameActionResult) +{ +private: + CoordsXY _coords; + uint8_t _height; + uint8_t _style; + +public: + LandSetHeightAction() + { + } + LandSetHeightAction(CoordsXY coords, uint8_t height, uint8_t style) + : _coords(coords) + , _height(height) + , _style(style) + { + } + + uint16_t GetActionFlags() const override + { + return GameAction::GetActionFlags() | GA_FLAGS::EDITOR_ONLY; + } + + void Serialise(DataSerialiser & stream) override + { + GameAction::Serialise(stream); + + stream << DS_TAG(_coords.x) << DS_TAG(_coords.y) << DS_TAG(_height) << DS_TAG(_style); + } + + GameActionResult::Ptr Query() const override + { + if (gParkFlags & PARK_FLAGS_FORBID_LANDSCAPE_CHANGES) + { + return std::make_unique(GA_ERROR::DISALLOWED, STR_FORBIDDEN_BY_THE_LOCAL_AUTHORITY); + } + + if (_coords.x > gMapSizeMaxXY || _coords.y > gMapSizeMaxXY) + { + return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_OFF_EDGE_OF_MAP); + } + + if (_height < MINIMUM_LAND_HEIGHT) + { + return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_TOO_LOW); + } + + // Divide by 2 and subtract 7 to get the in-game units. + if (_height > MAXIMUM_LAND_HEIGHT) + { + return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_TOO_HIGH); + } + else if (_height > MAXIMUM_LAND_HEIGHT - 2 && (_style & 0x1F) != 0) + { + return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_TOO_HIGH); + } + + if (_height == MAXIMUM_LAND_HEIGHT - 2 && (_style & 0x10)) + { + return std::make_unique(GA_ERROR::INVALID_PARAMETERS, STR_TOO_HIGH); + } + + if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode) + { + if (!map_is_location_in_park(_coords)) + { + return std::make_unique(GA_ERROR::DISALLOWED, STR_LAND_NOT_OWNED_BY_PARK); + } + } + + money32 cost = MONEY(0, 0); + + if (!gCheatsDisableClearanceChecks) + { + // Check for obstructing scenery + TileElement* tileElement = map_get_first_element_at(_coords.x / 32, _coords.y / 32); + do + { + if (tileElement->GetType() != TILE_ELEMENT_TYPE_SMALL_SCENERY) + continue; + if (_height > tileElement->clearance_height) + continue; + if (_height + 4 < tileElement->base_height) + continue; + rct_scenery_entry* sceneryEntry = tileElement->AsSmallScenery()->GetEntry(); + if (sceneryEntry->small_scenery.height > 64 && gParkFlags & PARK_FLAGS_FORBID_TREE_REMOVAL) + { + map_obstruction_set_error_text(tileElement); + return std::make_unique(GA_ERROR::DISALLOWED, gGameCommandErrorText); + } + cost += MONEY(sceneryEntry->small_scenery.removal_price, 0); + } while (!(tileElement++)->IsLastForTile()); + } + + // Check for ride support limits + if (!gCheatsDisableSupportLimits) + { + TileElement* tileElement = map_get_first_element_at(_coords.x / 32, _coords.y / 32); + do + { + if (tileElement->GetType() == TILE_ELEMENT_TYPE_TRACK) + { + ride_id_t rideIndex = tileElement->AsTrack()->GetRideIndex(); + Ride* ride = get_ride(rideIndex); + if (ride != nullptr) + { + rct_ride_entry* rideEntry = get_ride_entry_by_ride(ride); + if (rideEntry != nullptr) + { + int32_t maxHeight = rideEntry->max_height; + if (maxHeight == 0) + { + maxHeight = RideData5[get_ride(rideIndex)->type].max_height; + } + int32_t zDelta = tileElement->clearance_height - _height; + if (zDelta >= 0 && zDelta / 2 > maxHeight) + { + return std::make_unique(GA_ERROR::DISALLOWED, STR_SUPPORTS_CANT_BE_EXTENDED); + } + } + } + } + } while (!(tileElement++)->IsLastForTile()); + } + + uint8_t zCorner = _height; // z position of highest corner of tile + TileElement* surfaceElement = map_get_surface_element_at(_coords); + if (surfaceElement->AsSurface()->HasTrackThatNeedsWater()) + { + uint32_t waterHeight = surfaceElement->AsSurface()->GetWaterHeight(); + if (waterHeight != 0) + { + if (_style & 0x1F) + { + zCorner += 2; + if (_style & 0x10) + { + zCorner += 2; + } + } + if (zCorner > waterHeight * 2 - 2) + { + surfaceElement++; + map_obstruction_set_error_text(surfaceElement); + return std::make_unique(GA_ERROR::DISALLOWED, gGameCommandErrorText); + } + } + } + + zCorner = _height; + if (_style & 0xF) + { + zCorner += 2; + if (_style & 0x10) + { + zCorner += 2; + } + } + + if (!gCheatsDisableClearanceChecks) + { + if (!map_can_construct_with_clear_at( + _coords.x, _coords.y, _height, zCorner, &map_set_land_height_clear_func, 0xF, 0, nullptr, + CREATE_CROSSING_MODE_NONE)) + { + return std::make_unique(GA_ERROR::DISALLOWED, STR_NONE); + } + } + + if (!gCheatsDisableClearanceChecks) + { + TileElement* tileElement = map_get_first_element_at(_coords.x / 32, _coords.y / 32); + do + { + int32_t elementType = tileElement->GetType(); + + if (elementType == TILE_ELEMENT_TYPE_WALL) + continue; + if (elementType == TILE_ELEMENT_TYPE_SMALL_SCENERY) + continue; + if (tileElement->flags & 0x10) + continue; + if (tileElement == surfaceElement) + continue; + if (tileElement > surfaceElement) + { + if (zCorner > tileElement->base_height) + { + map_obstruction_set_error_text(tileElement); + return std::make_unique(GA_ERROR::DISALLOWED, gGameCommandErrorText); + } + continue; + } + if (_height < tileElement->clearance_height) + { + map_obstruction_set_error_text(tileElement); + return std::make_unique(GA_ERROR::DISALLOWED, gGameCommandErrorText); + } + } while (!(tileElement++)->IsLastForTile()); + } + + for (int32_t i = 0; i < 4; i += 1) + { + int32_t cornerHeight = tile_element_get_corner_height(surfaceElement, i); + cornerHeight -= map_get_corner_height(_height, _style & TILE_ELEMENT_SURFACE_SLOPE_MASK, i); + cost += MONEY(abs(cornerHeight) * 5 / 2, 0); + } + + auto res = std::make_unique(); + res->Cost = cost; + res->ExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING; + return res; + } + + GameActionResult::Ptr Execute() const override + { + money32 cost = MONEY(0, 0); + footpath_remove_litter(_coords.x, _coords.y, tile_element_height(_coords.x, _coords.y)); + if (!gCheatsDisableClearanceChecks) + wall_remove_at(_coords.x, _coords.y, _height * 8 - 16, _height * 8 + 32); + + if (!gCheatsDisableClearanceChecks) + { + TileElement* tileElement = map_get_first_element_at(_coords.x / 32, _coords.y / 32); + do + { + if (tileElement->GetType() != TILE_ELEMENT_TYPE_SMALL_SCENERY) + continue; + if (_height > tileElement->clearance_height) + continue; + if (_height + 4 < tileElement->base_height) + continue; + rct_scenery_entry* sceneryEntry = tileElement->AsSmallScenery()->GetEntry(); + if (sceneryEntry->small_scenery.height > 64 && gParkFlags & PARK_FLAGS_FORBID_TREE_REMOVAL) + { + map_obstruction_set_error_text(tileElement); + return std::make_unique(GA_ERROR::DISALLOWED, gGameCommandErrorText); + } + cost += MONEY(sceneryEntry->small_scenery.removal_price, 0); + tile_element_remove(tileElement--); + } while (!(tileElement++)->IsLastForTile()); + } + + uint8_t zCorner = _height; // z position of highest corner of tile + TileElement* surfaceElement = map_get_surface_element_at(_coords); + if (surfaceElement->AsSurface()->HasTrackThatNeedsWater()) + { + uint32_t waterHeight = surfaceElement->AsSurface()->GetWaterHeight(); + if (waterHeight != 0) + { + if (_style & 0x1F) + { + zCorner += 2; + if (_style & 0x10) + { + zCorner += 2; + } + } + if (zCorner > waterHeight * 2 - 2) + { + surfaceElement++; + map_obstruction_set_error_text(surfaceElement); + return std::make_unique(GA_ERROR::DISALLOWED, gGameCommandErrorText); + } + } + } + + for (int32_t i = 0; i < 4; i += 1) + { + int32_t cornerHeight = tile_element_get_corner_height(surfaceElement, i); + cornerHeight -= map_get_corner_height(_height, _style & TILE_ELEMENT_SURFACE_SLOPE_MASK, i); + cost += MONEY(abs(cornerHeight) * 5 / 2, 0); + } + + LocationXYZ16 coord; + coord.x = _coords.x + 16; + coord.y = _coords.y + 16; + coord.z = tile_element_height(_coords.x, _coords.y); + network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); + + surfaceElement = map_get_surface_element_at(_coords); + surfaceElement->base_height = _height; + surfaceElement->clearance_height = _height; + surfaceElement->AsSurface()->SetSlope(_style); + int32_t waterHeight = surfaceElement->AsSurface()->GetWaterHeight(); + if (waterHeight != 0 && waterHeight <= _height / 2) + surfaceElement->AsSurface()->SetWaterHeight(0); + map_invalidate_tile_full(_coords.x, _coords.y); + + auto res = std::make_unique(); + res->Cost = cost; + res->ExpenditureType = RCT_EXPENDITURE_TYPE_LANDSCAPING; + return res; + } +}; diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index a0d1b5e49c..5769163b43 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -15,6 +15,7 @@ #include "../Input.h" #include "../OpenRCT2.h" #include "../actions/FootpathRemoveAction.hpp" +#include "../actions/LandSetHeightAction.hpp" #include "../actions/LargeSceneryRemoveAction.hpp" #include "../actions/SmallSceneryRemoveAction.hpp" #include "../actions/WallRemoveAction.hpp" @@ -1064,24 +1065,7 @@ static constexpr const uint8_t tile_element_lower_styles[9][32] = { 0x29, 0x29, 0x00, 0x01, 0x00, 0x01, 0x00, 0x07, 0x29, 0x29, 0x08, 0x09, 0x08, 0x09, 0x0E, 0x09 }, // MAP_SELECT_TYPE_EDGE_3 }; -/** - * - * rct2: 0x00663CB9 - */ -static int32_t map_set_land_height_clear_func( - TileElement** tile_element, [[maybe_unused]] int32_t x, [[maybe_unused]] int32_t y, [[maybe_unused]] uint8_t flags, - [[maybe_unused]] money32* price) -{ - if ((*tile_element)->GetType() == TILE_ELEMENT_TYPE_SURFACE) - return 0; - - if ((*tile_element)->GetType() == TILE_ELEMENT_TYPE_SMALL_SCENERY) - return 0; - - return 1; -} - -static int32_t map_get_corner_height(int32_t z, int32_t slope, int32_t direction) +int32_t map_get_corner_height(int32_t z, int32_t slope, int32_t direction) { switch (direction) { @@ -1129,248 +1113,13 @@ static int32_t map_get_corner_height(int32_t z, int32_t slope, int32_t direction return z; } -static int32_t tile_element_get_corner_height(const TileElement* tileElement, int32_t direction) +int32_t tile_element_get_corner_height(const TileElement* tileElement, int32_t direction) { int32_t z = tileElement->base_height; int32_t slope = tileElement->AsSurface()->GetSlope(); return map_get_corner_height(z, slope, direction); } -static money32 map_set_land_height(int32_t flags, int32_t x, int32_t y, int32_t height, int32_t style) -{ - TileElement* tileElement; - - if (game_is_paused() && !gCheatsBuildInPauseMode) - { - gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; - return MONEY32_UNDEFINED; - } - - if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode) - { - if (gParkFlags & PARK_FLAGS_FORBID_LANDSCAPE_CHANGES) - { - gGameCommandErrorText = STR_FORBIDDEN_BY_THE_LOCAL_AUTHORITY; - return MONEY32_UNDEFINED; - } - } - - if (x > gMapSizeMaxXY || y > gMapSizeMaxXY) - { - gGameCommandErrorText = STR_OFF_EDGE_OF_MAP; - return MONEY32_UNDEFINED; - } - - if (height < MINIMUM_LAND_HEIGHT) - { - gGameCommandErrorText = STR_TOO_LOW; - return MONEY32_UNDEFINED; - } - - // Divide by 2 and subtract 7 to get the in-game units. - if (height > MAXIMUM_LAND_HEIGHT) - { - gGameCommandErrorText = STR_TOO_HIGH; - return MONEY32_UNDEFINED; - } - else if (height > MAXIMUM_LAND_HEIGHT - 2 && (style & 0x1F) != 0) - { - gGameCommandErrorText = STR_TOO_HIGH; - return MONEY32_UNDEFINED; - } - - if (height == MAXIMUM_LAND_HEIGHT - 2 && (style & 0x10)) - { - gGameCommandErrorText = STR_TOO_HIGH; - return MONEY32_UNDEFINED; - } - - if (!(gScreenFlags & SCREEN_FLAGS_SCENARIO_EDITOR) && !gCheatsSandboxMode) - { - if (!map_is_location_in_park({ x, y })) - { - return MONEY32_UNDEFINED; - } - } - - money32 cost = MONEY(0, 0); - if (flags & GAME_COMMAND_FLAG_APPLY) - { - footpath_remove_litter(x, y, tile_element_height(x, y)); - if (!gCheatsDisableClearanceChecks) - wall_remove_at(x, y, height * 8 - 16, height * 8 + 32); - } - - if (!gCheatsDisableClearanceChecks) - { - // Check for obstructing scenery - tileElement = map_get_first_element_at(x / 32, y / 32); - do - { - if (tileElement->GetType() != TILE_ELEMENT_TYPE_SMALL_SCENERY) - continue; - if (height > tileElement->clearance_height) - continue; - if (height + 4 < tileElement->base_height) - continue; - rct_scenery_entry* sceneryEntry = tileElement->AsSmallScenery()->GetEntry(); - if (sceneryEntry->small_scenery.height > 64 && gParkFlags & PARK_FLAGS_FORBID_TREE_REMOVAL) - { - map_obstruction_set_error_text(tileElement); - return MONEY32_UNDEFINED; - } - cost += MONEY(sceneryEntry->small_scenery.removal_price, 0); - if (flags & GAME_COMMAND_FLAG_APPLY) - tile_element_remove(tileElement--); - } while (!(tileElement++)->IsLastForTile()); - } - - // Check for ride support limits - if (!gCheatsDisableSupportLimits) - { - tileElement = map_get_first_element_at(x / 32, y / 32); - do - { - if (tileElement->GetType() == TILE_ELEMENT_TYPE_TRACK) - { - ride_id_t rideIndex = tileElement->AsTrack()->GetRideIndex(); - Ride* ride = get_ride(rideIndex); - if (ride != nullptr) - { - rct_ride_entry* rideEntry = get_ride_entry_by_ride(ride); - if (rideEntry != nullptr) - { - int32_t maxHeight = rideEntry->max_height; - if (maxHeight == 0) - { - maxHeight = RideData5[get_ride(rideIndex)->type].max_height; - } - int32_t zDelta = tileElement->clearance_height - height; - if (zDelta >= 0 && zDelta / 2 > maxHeight) - { - gGameCommandErrorText = STR_SUPPORTS_CANT_BE_EXTENDED; - return MONEY32_UNDEFINED; - } - } - } - } - } while (!(tileElement++)->IsLastForTile()); - } - - uint8_t zCorner = height; // z position of highest corner of tile - TileElement* surfaceElement = map_get_surface_element_at({ x, y }); - if (surfaceElement->AsSurface()->HasTrackThatNeedsWater()) - { - uint32_t waterHeight = surfaceElement->AsSurface()->GetWaterHeight(); - if (waterHeight != 0) - { - if (style & 0x1F) - { - zCorner += 2; - if (style & 0x10) - { - zCorner += 2; - } - } - if (zCorner > waterHeight * 2 - 2) - { - surfaceElement++; - map_obstruction_set_error_text(surfaceElement); - return MONEY32_UNDEFINED; - } - } - } - - zCorner = height; - if (style & 0xF) - { - zCorner += 2; - if (style & 0x10) - { - zCorner += 2; - } - } - - if (!gCheatsDisableClearanceChecks) - { - if (!map_can_construct_with_clear_at( - x, y, height, zCorner, &map_set_land_height_clear_func, 0xF, 0, nullptr, CREATE_CROSSING_MODE_NONE)) - { - return MONEY32_UNDEFINED; - } - } - - if (!gCheatsDisableClearanceChecks) - { - tileElement = map_get_first_element_at(x / 32, y / 32); - do - { - int32_t elementType = tileElement->GetType(); - - if (elementType == TILE_ELEMENT_TYPE_WALL) - continue; - if (elementType == TILE_ELEMENT_TYPE_SMALL_SCENERY) - continue; - if (tileElement->flags & 0x10) - continue; - if (tileElement == surfaceElement) - continue; - if (tileElement > surfaceElement) - { - if (zCorner > tileElement->base_height) - { - map_obstruction_set_error_text(tileElement); - return MONEY32_UNDEFINED; - } - continue; - } - if (height < tileElement->clearance_height) - { - map_obstruction_set_error_text(tileElement); - return MONEY32_UNDEFINED; - } - } while (!(tileElement++)->IsLastForTile()); - } - - for (int32_t i = 0; i < 4; i += 1) - { - int32_t cornerHeight = tile_element_get_corner_height(surfaceElement, i); - cornerHeight -= map_get_corner_height(height, style & TILE_ELEMENT_SURFACE_SLOPE_MASK, i); - cost += MONEY(abs(cornerHeight) * 5 / 2, 0); - } - - if (flags & GAME_COMMAND_FLAG_APPLY) - { - if (gGameCommandNestLevel == 1) - { - LocationXYZ16 coord; - coord.x = x + 16; - coord.y = y + 16; - coord.z = tile_element_height(coord.x, coord.y); - network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); - } - - surfaceElement = map_get_surface_element_at({ x, y }); - surfaceElement->base_height = height; - surfaceElement->clearance_height = height; - surfaceElement->AsSurface()->SetSlope(style); - int32_t waterHeight = surfaceElement->AsSurface()->GetWaterHeight(); - if (waterHeight != 0 && waterHeight <= height / 2) - surfaceElement->AsSurface()->SetWaterHeight(0); - map_invalidate_tile_full(x, y); - } - if (gParkFlags & PARK_FLAGS_NO_MONEY) - return 0; - return cost; -} - -void game_command_set_land_height( - int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, [[maybe_unused]] int32_t* esi, [[maybe_unused]] int32_t* edi, - [[maybe_unused]] int32_t* ebp) -{ - *ebx = map_set_land_height(*ebx & 0xFF, *eax & 0xFFFF, *ecx & 0xFFFF, *edx & 0xFF, (*edx >> 8) & 0xFF); -} - static money32 map_set_land_ownership(uint8_t flags, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint8_t newOwnership) { gCommandExpenditureType = RCT_EXPENDITURE_TYPE_LAND_PURCHASE; @@ -1508,12 +1257,14 @@ static money32 raise_land( height += 2; slope &= TILE_ELEMENT_SURFACE_SLOPE_MASK; - money32 tileCost = map_set_land_height(flags, x_coord, y_coord, height, slope); - if (tileCost == MONEY32_UNDEFINED) + auto landSetHeightAction = LandSetHeightAction({ x_coord, y_coord }, height, slope); + auto res = (flags & GAME_COMMAND_FLAG_APPLY) ? landSetHeightAction.Execute() : landSetHeightAction.Query(); + + if (res->Error != GA_ERROR::OK) { return MONEY32_UNDEFINED; } - cost += tileCost; + cost += res->Cost; } } } @@ -1575,12 +1326,15 @@ static money32 lower_land( height -= 2; newSlope &= TILE_ELEMENT_SURFACE_SLOPE_MASK; - money32 tileCost = map_set_land_height(flags, x_coord, y_coord, height, newSlope); - if (tileCost == MONEY32_UNDEFINED) + + auto landSetHeightAction = LandSetHeightAction({ x_coord, y_coord }, height, newSlope); + auto res = (flags & GAME_COMMAND_FLAG_APPLY) ? landSetHeightAction.Execute() : landSetHeightAction.Query(); + + if (res->Error != GA_ERROR::OK) { return MONEY32_UNDEFINED; } - cost += tileCost; + cost += res->Cost; } } } @@ -1824,7 +1578,18 @@ static money32 smooth_land_tile( slope &= ~SURFACE_STYLE_FLAG_RAISE_OR_LOWER_BASE_HEIGHT; } } - return game_do_command(x, flags, y, targetBaseZ | (slope << 8), GAME_COMMAND_SET_LAND_HEIGHT, 0, 0); + + auto landSetHeightAction = LandSetHeightAction({ x, y }, targetBaseZ, slope); + auto res = (flags & GAME_COMMAND_FLAG_APPLY) ? landSetHeightAction.Execute() : landSetHeightAction.Query(); + + if (res->Error == GA_ERROR::OK) + { + return res->Cost; + } + else + { + return MONEY32_UNDEFINED; + } } static money32 smooth_land_row_by_edge( @@ -1835,7 +1600,6 @@ static money32 smooth_land_row_by_edge( int32_t landChangePerTile = raiseLand ? -2 : 2; TileElement *tileElement, *nextTileElement; money32 totalCost = 0; - money32 result; // check if we need to start at all if (!map_is_location_valid({ x, y }) || !map_is_location_valid({ x + stepX, y + stepY })) @@ -1960,10 +1724,12 @@ static money32 smooth_land_row_by_edge( } } } - result = game_do_command(x, flags, y, targetBaseZ | (slope << 8), GAME_COMMAND_SET_LAND_HEIGHT, 0, 0); - if (result != MONEY32_UNDEFINED) + auto landSetHeightAction = LandSetHeightAction({ x, y }, targetBaseZ, slope); + auto res = (flags & GAME_COMMAND_FLAG_APPLY) ? landSetHeightAction.Execute() : landSetHeightAction.Query(); + + if (res->Error == GA_ERROR::OK) { - totalCost += result; + totalCost += res->Cost; } } return totalCost; diff --git a/src/openrct2/world/Map.h b/src/openrct2/world/Map.h index 10f435ceaa..8d5c2b703e 100644 --- a/src/openrct2/world/Map.h +++ b/src/openrct2/world/Map.h @@ -183,8 +183,6 @@ money32 wall_place( int32_t type, int32_t x, int32_t y, int32_t z, int32_t edge, int32_t primaryColour, int32_t secondaryColour, int32_t tertiaryColour, int32_t flags); -void game_command_set_land_height( - int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp); void game_command_set_land_ownership( int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp); void game_command_remove_banner( @@ -258,6 +256,8 @@ void map_invalidate_region(const LocationXY16& mins, const LocationXY16& maxs); int32_t map_get_tile_side(int32_t mapX, int32_t mapY); int32_t map_get_tile_quadrant(int32_t mapX, int32_t mapY); +int32_t map_get_corner_height(int32_t z, int32_t slope, int32_t direction); +int32_t tile_element_get_corner_height(const TileElement* tileElement, int32_t direction); void map_clear_all_elements();