diff --git a/src/openrct2-ui/windows/TileInspector.cpp b/src/openrct2-ui/windows/TileInspector.cpp index 69b79b6755..07ef450ee8 100644 --- a/src/openrct2-ui/windows/TileInspector.cpp +++ b/src/openrct2-ui/windows/TileInspector.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -29,7 +30,6 @@ #include #include #include -#include // clang-format off static constexpr const rct_string_id TerrainTypeStringIds[] = { @@ -619,25 +619,25 @@ static void window_tile_inspector_load_tile(rct_window* w, TileElement* elementT static void window_tile_inspector_insert_corrupt_element(int32_t elementIndex) { openrct2_assert(elementIndex >= 0 && elementIndex < windowTileInspectorElementCount, "elementIndex out of range"); - game_do_command( - TILE_INSPECTOR_ANY_INSERT_CORRUPT, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8), - elementIndex, GAME_COMMAND_MODIFY_TILE, 0, 0); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::AnyInsertCorrupt, elementIndex); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_remove_element(int32_t elementIndex) { openrct2_assert(elementIndex >= 0 && elementIndex < windowTileInspectorElementCount, "elementIndex out of range"); - game_do_command( - TILE_INSPECTOR_ANY_REMOVE, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8), - elementIndex, GAME_COMMAND_MODIFY_TILE, 0, 0); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::AnyRemove, elementIndex); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_rotate_element(int32_t elementIndex) { openrct2_assert(elementIndex >= 0 && elementIndex < windowTileInspectorElementCount, "elementIndex out of range"); - game_do_command( - TILE_INSPECTOR_ANY_ROTATE, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8), - elementIndex, GAME_COMMAND_MODIFY_TILE, 0, 0); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::AnyRotate, elementIndex); + GameActions::Execute(&modifyTile); } // Swap element with its parent @@ -645,17 +645,16 @@ static void window_tile_inspector_swap_elements(int16_t first, int16_t second) { openrct2_assert(first >= 0 && first < windowTileInspectorElementCount, "first out of range"); openrct2_assert(second >= 0 && second < windowTileInspectorElementCount, "second out of range"); - game_do_command( - TILE_INSPECTOR_ANY_SWAP, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8), first, - GAME_COMMAND_MODIFY_TILE, second, 0); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::AnySwap, first, second); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_sort_elements() { openrct2_assert(windowTileInspectorTileSelected, "No tile selected"); - game_do_command( - TILE_INSPECTOR_ANY_SORT, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8), 0, - GAME_COMMAND_MODIFY_TILE, 0, 0); + auto modifyTile = TileModifyAction({ windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::AnySort); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_copy_element(rct_window* w) @@ -672,127 +671,130 @@ static void window_tile_inspector_paste_element(rct_window* w) int32_t data[2]; std::memcpy(&data[0], &tileInspectorCopiedElement, 8); assert_struct_size(data, sizeof(tileInspectorCopiedElement)); - - game_do_command( - TILE_INSPECTOR_ANY_PASTE, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8), data[0], - GAME_COMMAND_MODIFY_TILE, data[1], 0); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::AnyPaste, 0, 0, + tileInspectorCopiedElement); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_base_height_offset(int16_t elementIndex, int8_t heightOffset) { - game_do_command( - TILE_INSPECTOR_ANY_BASE_HEIGHT_OFFSET, GAME_COMMAND_FLAG_APPLY, - windowTileInspectorTileX | (windowTileInspectorTileY << 8), elementIndex, GAME_COMMAND_MODIFY_TILE, heightOffset, 0); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::AnyBaseHeightOffset, elementIndex, + heightOffset); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_surface_show_park_fences(bool showFences) { - game_do_command( - TILE_INSPECTOR_SURFACE_SHOW_PARK_FENCES, GAME_COMMAND_FLAG_APPLY, - windowTileInspectorTileX | (windowTileInspectorTileY << 8), showFences, GAME_COMMAND_MODIFY_TILE, 0, 0); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::SurfaceShowParkFences, showFences); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_surface_toggle_corner(int32_t cornerIndex) { - game_do_command( - TILE_INSPECTOR_SURFACE_TOGGLE_CORNER, GAME_COMMAND_FLAG_APPLY, - windowTileInspectorTileX | (windowTileInspectorTileY << 8), cornerIndex, GAME_COMMAND_MODIFY_TILE, 0, 0); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::SurfaceToggleCorner, cornerIndex); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_surface_toggle_diagonal() { - game_do_command( - TILE_INSPECTOR_SURFACE_TOGGLE_DIAGONAL, GAME_COMMAND_FLAG_APPLY, - windowTileInspectorTileX | (windowTileInspectorTileY << 8), 0, GAME_COMMAND_MODIFY_TILE, 0, 0); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::SurfaceToggleDiagonal); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_path_set_sloped(int32_t elementIndex, bool sloped) { - game_do_command( - TILE_INSPECTOR_PATH_SET_SLOPE, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8), - elementIndex, GAME_COMMAND_MODIFY_TILE, sloped, 0); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::PathSetSlope, elementIndex, sloped); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_path_set_broken(int32_t elementIndex, bool broken) { - game_do_command( - TILE_INSPECTOR_PATH_SET_BROKEN, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8), - elementIndex, GAME_COMMAND_MODIFY_TILE, broken, 0); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::PathSetBroken, elementIndex, broken); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_path_toggle_edge(int32_t elementIndex, int32_t cornerIndex) { openrct2_assert(elementIndex >= 0 && elementIndex < windowTileInspectorElementCount, "elementIndex out of range"); openrct2_assert(cornerIndex >= 0 && cornerIndex < 8, "cornerIndex out of range"); - game_do_command( - TILE_INSPECTOR_PATH_TOGGLE_EDGE, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8), - elementIndex, GAME_COMMAND_MODIFY_TILE, cornerIndex, 0); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::PathToggleEdge, elementIndex, + cornerIndex); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_entrance_make_usable(int32_t elementIndex) { Guard::ArgumentInRange(elementIndex, 0, windowTileInspectorElementCount - 1); - game_do_command( - TILE_INSPECTOR_ENTRANCE_MAKE_USABLE, GAME_COMMAND_FLAG_APPLY, - windowTileInspectorTileX | (windowTileInspectorTileY << 8), elementIndex, GAME_COMMAND_MODIFY_TILE, 0, 0); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::EntranceMakeUsable, elementIndex); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_wall_set_slope(int32_t elementIndex, int32_t slopeValue) { // Make sure only the correct bits are set openrct2_assert((slopeValue & 3) == slopeValue, "slopeValue doesn't match its mask"); - - game_do_command( - TILE_INSPECTOR_WALL_SET_SLOPE, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8), - elementIndex, GAME_COMMAND_MODIFY_TILE, slopeValue, 0); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::WallSetSlope, elementIndex, slopeValue); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_track_block_height_offset(int32_t elementIndex, int8_t heightOffset) { - game_do_command( - TILE_INSPECTOR_TRACK_BASE_HEIGHT_OFFSET, GAME_COMMAND_FLAG_APPLY, - windowTileInspectorTileX | (windowTileInspectorTileY << 8), elementIndex, GAME_COMMAND_MODIFY_TILE, heightOffset, 0); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::TrackBaseHeightOffset, elementIndex, + heightOffset); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_track_block_set_lift(int32_t elementIndex, bool entireTrackBlock, bool chain) { - game_do_command( - TILE_INSPECTOR_TRACK_SET_CHAIN, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8), - elementIndex, GAME_COMMAND_MODIFY_TILE, entireTrackBlock, chain); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, + entireTrackBlock ? TileModifyType::TrackSetChainBlock : TileModifyType::TrackSetChain, elementIndex, chain); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_track_set_block_brake(int32_t elementIndex, bool blockBrake) { - game_do_command( - TILE_INSPECTOR_TRACK_SET_BLOCK_BRAKE, GAME_COMMAND_FLAG_APPLY, - windowTileInspectorTileX | (windowTileInspectorTileY << 8), elementIndex, GAME_COMMAND_MODIFY_TILE, blockBrake, 0); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::TrackSetBlockBrake, elementIndex, + blockBrake); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_track_set_indestructible(int32_t elementIndex, bool isIndestructible) { - game_do_command( - TILE_INSPECTOR_TRACK_SET_INDESTRUCTIBLE, GAME_COMMAND_FLAG_APPLY, - windowTileInspectorTileX | (windowTileInspectorTileY << 8), elementIndex, GAME_COMMAND_MODIFY_TILE, isIndestructible, - 0); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::TrackSetIndestructible, elementIndex, + isIndestructible); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_quarter_tile_set(int32_t elementIndex, const int32_t quarterIndex) { // quarterIndex is widget index relative to WIDX_SCENERY_CHECK_QUARTER_N, so a value from 0-3 openrct2_assert(quarterIndex >= 0 && quarterIndex < 4, "quarterIndex out of range"); - - game_do_command( - TILE_INSPECTOR_SCENERY_SET_QUARTER_LOCATION, GAME_COMMAND_FLAG_APPLY, - windowTileInspectorTileX | (windowTileInspectorTileY << 8), elementIndex, GAME_COMMAND_MODIFY_TILE, - (quarterIndex - get_current_rotation()) & 3, 0); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::ScenerySetQuarterLocation, elementIndex, + (quarterIndex - get_current_rotation()) & 3); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_toggle_quadrant_collosion(int32_t elementIndex, const int32_t quadrantIndex) { - game_do_command( - TILE_INSPECTOR_SCENERY_SET_QUARTER_COLLISION, GAME_COMMAND_FLAG_APPLY, - windowTileInspectorTileX | (windowTileInspectorTileY << 8), elementIndex, GAME_COMMAND_MODIFY_TILE, - (quadrantIndex + 2 - get_current_rotation()) & 3, 0); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::ScenerySetQuarterCollision, elementIndex, + (quadrantIndex + 2 - get_current_rotation()) & 3); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_banner_toggle_block(int32_t elementIndex, int32_t edgeIndex) @@ -801,17 +803,17 @@ static void window_tile_inspector_banner_toggle_block(int32_t elementIndex, int3 // Make edgeIndex abstract edgeIndex = (edgeIndex - get_current_rotation()) & 3; - - game_do_command( - TILE_INSPECTOR_BANNER_TOGGLE_BLOCKING_EDGE, GAME_COMMAND_FLAG_APPLY, - windowTileInspectorTileX | (windowTileInspectorTileY << 8), elementIndex, GAME_COMMAND_MODIFY_TILE, edgeIndex, 0); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::BannerToggleBlockingEdge, elementIndex, + edgeIndex); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_clamp_corrupt(int32_t elementIndex) { - game_do_command( - TILE_INSPECTOR_CORRUPT_CLAMP, GAME_COMMAND_FLAG_APPLY, windowTileInspectorTileX | (windowTileInspectorTileY << 8), - elementIndex, GAME_COMMAND_MODIFY_TILE, 0, 0); + auto modifyTile = TileModifyAction( + { windowTileInspectorToolMapX, windowTileInspectorToolMapY }, TileModifyType::CorruptClamp, elementIndex); + GameActions::Execute(&modifyTile); } static void window_tile_inspector_mouseup(rct_window* w, rct_widgetindex widgetIndex) diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index f24cd83a6f..90f388f0f5 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -1225,7 +1225,7 @@ GAME_COMMAND_POINTER* new_game_command_table[GAME_COMMAND_COUNT] = { game_command_pickup_guest, game_command_pickup_staff, nullptr, - game_command_modify_tile, + nullptr, nullptr, NULL, }; diff --git a/src/openrct2/Game.h b/src/openrct2/Game.h index d9885993c3..d29f0f06b3 100644 --- a/src/openrct2/Game.h +++ b/src/openrct2/Game.h @@ -87,8 +87,8 @@ enum GAME_COMMAND GAME_COMMAND_CHEAT, // GA GAME_COMMAND_PICKUP_GUEST, GAME_COMMAND_PICKUP_STAFF, - GAME_COMMAND_BALLOON_PRESS, // GA - GAME_COMMAND_MODIFY_TILE, + GAME_COMMAND_BALLOON_PRESS, // GA + GAME_COMMAND_MODIFY_TILE, // GA GAME_COMMAND_EDIT_SCENARIO_OPTIONS, // GA GAME_COMMAND_PLACE_PEEP_SPAWN, // GA, TODO: refactor to separate array for just game actions GAME_COMMAND_SET_CLIMATE, // GA diff --git a/src/openrct2/actions/GameActionRegistration.cpp b/src/openrct2/actions/GameActionRegistration.cpp index 4bbbabdbcd..25f0601b9a 100644 --- a/src/openrct2/actions/GameActionRegistration.cpp +++ b/src/openrct2/actions/GameActionRegistration.cpp @@ -74,6 +74,7 @@ #include "StaffSetOrdersAction.hpp" #include "StaffSetPatrolAreaAction.hpp" #include "SurfaceSetStyleAction.hpp" +#include "TileModifyAction.hpp" #include "TrackPlaceAction.hpp" #include "TrackRemoveAction.hpp" #include "TrackSetBrakeSpeedAction.hpp" @@ -151,6 +152,7 @@ namespace GameActions Register(); Register(); Register(); + Register(); Register(); Register(); Register(); diff --git a/src/openrct2/actions/TileModifyAction.hpp b/src/openrct2/actions/TileModifyAction.hpp new file mode 100644 index 0000000000..7803e44fc6 --- /dev/null +++ b/src/openrct2/actions/TileModifyAction.hpp @@ -0,0 +1,264 @@ +/***************************************************************************** + * Copyright (c) 2014-2019 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 "../world/TileInspector.h" +#include "GameAction.h" + +enum class TileModifyType : uint8_t +{ + AnyRemove, + AnySwap, + AnyInsertCorrupt, + AnyRotate, + AnyPaste, + AnySort, + AnyBaseHeightOffset, + SurfaceShowParkFences, + SurfaceToggleCorner, + SurfaceToggleDiagonal, + PathSetSlope, + PathSetBroken, + PathToggleEdge, + EntranceMakeUsable, + WallSetSlope, + TrackBaseHeightOffset, + TrackSetChain, + TrackSetChainBlock, + TrackSetBlockBrake, + TrackSetIndestructible, + ScenerySetQuarterLocation, + ScenerySetQuarterCollision, + BannerToggleBlockingEdge, + CorruptClamp, + Count, +}; + +DEFINE_GAME_ACTION(TileModifyAction, GAME_COMMAND_MODIFY_TILE, GameActionResult) +{ +private: + CoordsXY _loc; + uint8_t _setting{ 0 }; + uint32_t _value1{ 0 }; + uint32_t _value2{ 0 }; + TileElement _pasteElement{ 0 }; + +public: + TileModifyAction() + { + } + TileModifyAction( + CoordsXY loc, TileModifyType setting, uint32_t value1 = { 0 }, uint32_t value2 = { 0 }, + TileElement pasteElement = { 0 }) + : _loc(loc) + , _setting(static_cast(setting)) + , _value1(value1) + , _value2(value2) + , _pasteElement(pasteElement) + { + } + + uint16_t GetActionFlags() const override + { + return GameAction::GetActionFlags() | GA_FLAGS::ALLOW_WHILE_PAUSED; + } + + void Serialise(DataSerialiser & stream) override + { + GameAction::Serialise(stream); + + stream << DS_TAG(_loc) << DS_TAG(_setting) << DS_TAG(_value1) << DS_TAG(_value2) + << DS_TAG(_pasteElement); + } + + GameActionResult::Ptr Query() const override + { + return QueryExecute(false); + } + + GameActionResult::Ptr Execute() const override + { + return QueryExecute(true); + } + +private: + GameActionResult::Ptr QueryExecute(bool isExecuting) const + { + auto res = MakeResult(); + switch (static_cast(_setting)) + { + case TileModifyType::AnyRemove: + { + const auto elementIndex = _value1; + res = tile_inspector_remove_element_at(_loc.x, _loc.y, elementIndex, isExecuting); + break; + } + case TileModifyType::AnySwap: + { + const auto firstIndex = _value1; + const auto secondIndex = _value2; + res = tile_inspector_swap_elements_at(_loc.x, _loc.y, firstIndex, secondIndex, isExecuting); + break; + } + case TileModifyType::AnyInsertCorrupt: + { + const auto elementIndex = _value1; + res = tile_inspector_insert_corrupt_at(_loc.x, _loc.y, elementIndex, isExecuting); + break; + } + case TileModifyType::AnyRotate: + { + const auto elementIndex = _value1; + res = tile_inspector_rotate_element_at(_loc.x, _loc.y, elementIndex, isExecuting); + break; + } + case TileModifyType::AnyPaste: + { + res = tile_inspector_paste_element_at(_loc.x, _loc.y, _pasteElement, isExecuting); + break; + } + case TileModifyType::AnySort: + { + res = tile_inspector_sort_elements_at(_loc.x, _loc.y, isExecuting); + break; + } + case TileModifyType::AnyBaseHeightOffset: + { + const auto elementIndex = _value1; + const auto heightOffset = _value2; + res = tile_inspector_any_base_height_offset(_loc.x, _loc.y, elementIndex, heightOffset, isExecuting); + break; + } + case TileModifyType::SurfaceShowParkFences: + { + const bool showFences = _value1; + res = tile_inspector_surface_show_park_fences(_loc.x, _loc.y, showFences, isExecuting); + break; + } + case TileModifyType::SurfaceToggleCorner: + { + const auto cornerIndex = _value1; + res = tile_inspector_surface_toggle_corner(_loc.x, _loc.y, cornerIndex, isExecuting); + break; + } + case TileModifyType::SurfaceToggleDiagonal: + { + res = tile_inspector_surface_toggle_diagonal(_loc.x, _loc.y, isExecuting); + break; + } + case TileModifyType::PathSetSlope: + { + const auto elementIndex = _value1; + const bool sloped = _value2; + res = tile_inspector_path_set_sloped(_loc.x, _loc.y, elementIndex, sloped, isExecuting); + break; + } + case TileModifyType::PathSetBroken: + { + const auto elementIndex = _value1; + const bool broken = _value2; + res = tile_inspector_path_set_broken(_loc.x, _loc.y, elementIndex, broken, isExecuting); + break; + } + case TileModifyType::PathToggleEdge: + { + const auto elementIndex = _value1; + const auto edgeIndex = _value2; + res = tile_inspector_path_toggle_edge(_loc.x, _loc.y, elementIndex, edgeIndex, isExecuting); + break; + } + case TileModifyType::EntranceMakeUsable: + { + const auto elementIndex = _value1; + res = tile_inspector_entrance_make_usable(_loc.x, _loc.y, elementIndex, isExecuting); + break; + } + case TileModifyType::WallSetSlope: + { + const auto elementIndex = _value1; + const auto slopeValue = _value2; + res = tile_inspector_wall_set_slope(_loc.x, _loc.y, elementIndex, slopeValue, isExecuting); + break; + } + case TileModifyType::TrackBaseHeightOffset: + { + const auto elementIndex = _value1; + const auto heightOffset = _value2; + res = tile_inspector_track_base_height_offset(_loc.x, _loc.y, elementIndex, heightOffset, isExecuting); + break; + } + case TileModifyType::TrackSetChainBlock: + { + const auto elementIndex = _value1; + const bool setChain = _value2; + res = tile_inspector_track_set_chain(_loc.x, _loc.y, elementIndex, true, setChain, isExecuting); + break; + } + case TileModifyType::TrackSetChain: + { + const auto elementIndex = _value1; + const bool setChain = _value2; + res = tile_inspector_track_set_chain(_loc.x, _loc.y, elementIndex, false, setChain, isExecuting); + break; + } + case TileModifyType::TrackSetBlockBrake: + { + const auto elementIndex = _value1; + const bool blockBrake = _value2; + res = tile_inspector_track_set_block_brake(_loc.x, _loc.y, elementIndex, blockBrake, isExecuting); + break; + } + case TileModifyType::TrackSetIndestructible: + { + const auto elementIndex = _value1; + const bool isIndestructible = _value2; + res = tile_inspector_track_set_indestructible(_loc.x, _loc.y, elementIndex, isIndestructible, isExecuting); + break; + } + case TileModifyType::ScenerySetQuarterLocation: + { + const auto elementIndex = _value1; + const auto quarterIndex = _value2; + res = tile_inspector_scenery_set_quarter_location(_loc.x, _loc.y, elementIndex, quarterIndex, isExecuting); + break; + } + case TileModifyType::ScenerySetQuarterCollision: + { + const auto elementIndex = _value1; + const auto quarterIndex = _value2; + res = tile_inspector_scenery_set_quarter_collision(_loc.x, _loc.y, elementIndex, quarterIndex, isExecuting); + break; + } + case TileModifyType::BannerToggleBlockingEdge: + { + const auto elementIndex = _value1; + const auto edgeIndex = _value2; + res = tile_inspector_banner_toggle_blocking_edge(_loc.x, _loc.y, elementIndex, edgeIndex, isExecuting); + break; + } + case TileModifyType::CorruptClamp: + { + const auto elementIndex = _value1; + res = tile_inspector_corrupt_clamp(_loc.x, _loc.y, elementIndex, isExecuting); + break; + } + default: + log_error("invalid instruction"); + return MakeResult(GA_ERROR::INVALID_PARAMETERS, STR_NONE); + break; + } + + res->Position.x = _loc.x; + res->Position.y = _loc.y; + res->Position.z = tile_element_height(_loc.x, _loc.y); + + return res; + } +}; diff --git a/src/openrct2/core/DataSerialiserTraits.h b/src/openrct2/core/DataSerialiserTraits.h index fe69c07e84..19d8040385 100644 --- a/src/openrct2/core/DataSerialiserTraits.h +++ b/src/openrct2/core/DataSerialiserTraits.h @@ -16,6 +16,7 @@ #include "../network/network.h" #include "../ride/Ride.h" #include "../world/Location.hpp" +#include "../world/TileElement.h" #include "DataSerialiserTag.h" #include "Endianness.h" #include "MemoryStream.h" @@ -381,6 +382,38 @@ template<> struct DataSerializerTraits } }; +template<> struct DataSerializerTraits +{ + static void encode(IStream* stream, const TileElement& tileElement) + { + stream->WriteValue(tileElement.type); + stream->WriteValue(tileElement.flags); + stream->WriteValue(tileElement.base_height); + stream->WriteValue(tileElement.clearance_height); + for (int i = 0; i < 4; ++i) + { + stream->WriteValue(tileElement.pad_04[i]); + } + } + static void decode(IStream* stream, TileElement& tileElement) + { + tileElement.type = stream->ReadValue(); + tileElement.flags = stream->ReadValue(); + tileElement.base_height = stream->ReadValue(); + tileElement.clearance_height = stream->ReadValue(); + for (int i = 0; i < 4; ++i) + { + tileElement.pad_04[i] = stream->ReadValue(); + } + } + static void log(IStream* stream, const TileElement& tileElement) + { + char msg[128] = {}; + snprintf(msg, sizeof(msg), "TileElement(type = %u, flags = %u, base_height = %u)", tileElement.type, tileElement.flags, tileElement.base_height); + stream->Write(msg, strlen(msg)); + } +}; + template<> struct DataSerializerTraits { static void encode(IStream* stream, const CoordsXY& coords) diff --git a/src/openrct2/world/Map.cpp b/src/openrct2/world/Map.cpp index 115395cd1b..f778a907cd 100644 --- a/src/openrct2/world/Map.cpp +++ b/src/openrct2/world/Map.cpp @@ -2245,186 +2245,6 @@ void map_clear_all_elements() } } -void game_command_modify_tile( - int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, [[maybe_unused]] int32_t* esi, int32_t* edi, int32_t* ebp) -{ - const int32_t flags = *ebx; - const int32_t x = *ecx & 0xFF; - const int32_t y = (*ecx >> 8) & 0xFF; - const TILE_INSPECTOR_INSTRUCTION_TYPE instruction = static_cast(*eax); - - switch (instruction) - { - case TILE_INSPECTOR_ANY_REMOVE: - { - const int16_t elementIndex = *edx; - *ebx = tile_inspector_remove_element_at(x, y, elementIndex, flags); - break; - } - case TILE_INSPECTOR_ANY_SWAP: - { - const int32_t firstIndex = *edx; - const int32_t secondIndex = *edi; - *ebx = tile_inspector_swap_elements_at(x, y, firstIndex, secondIndex, flags); - break; - } - case TILE_INSPECTOR_ANY_INSERT_CORRUPT: - { - const int16_t elementIndex = *edx; - *ebx = tile_inspector_insert_corrupt_at(x, y, elementIndex, flags); - break; - } - case TILE_INSPECTOR_ANY_ROTATE: - { - const int16_t elementIndex = *edx; - *ebx = tile_inspector_rotate_element_at(x, y, elementIndex, flags); - break; - } - case TILE_INSPECTOR_ANY_PASTE: - { - TileElement elementToPaste; - const int32_t data[] = { *edx, *edi }; - assert_struct_size(data, sizeof(elementToPaste)); - std::memcpy(&elementToPaste, data, 8); - *ebx = tile_inspector_paste_element_at(x, y, elementToPaste, flags); - break; - } - case TILE_INSPECTOR_ANY_SORT: - { - *ebx = tile_inspector_sort_elements_at(x, y, flags); - break; - } - case TILE_INSPECTOR_ANY_BASE_HEIGHT_OFFSET: - { - const int16_t elementIndex = *edx; - const int8_t heightOffset = *edi; - *ebx = tile_inspector_any_base_height_offset(x, y, elementIndex, heightOffset, flags); - break; - } - case TILE_INSPECTOR_SURFACE_SHOW_PARK_FENCES: - { - const bool showFences = *edx; - *ebx = tile_inspector_surface_show_park_fences(x, y, showFences, flags); - break; - } - case TILE_INSPECTOR_SURFACE_TOGGLE_CORNER: - { - const int32_t cornerIndex = *edx; - *ebx = tile_inspector_surface_toggle_corner(x, y, cornerIndex, flags); - break; - } - case TILE_INSPECTOR_SURFACE_TOGGLE_DIAGONAL: - { - *ebx = tile_inspector_surface_toggle_diagonal(x, y, flags); - break; - } - case TILE_INSPECTOR_PATH_SET_SLOPE: - { - const int32_t elementIndex = *edx; - const bool sloped = *edi; - *ebx = tile_inspector_path_set_sloped(x, y, elementIndex, sloped, flags); - break; - } - case TILE_INSPECTOR_PATH_SET_BROKEN: - { - const int32_t elementIndex = *edx; - const bool broken = *edi; - *ebx = tile_inspector_path_set_broken(x, y, elementIndex, broken, flags); - break; - } - case TILE_INSPECTOR_PATH_TOGGLE_EDGE: - { - const int32_t elementIndex = *edx; - const int32_t edgeIndex = *edi; - *ebx = tile_inspector_path_toggle_edge(x, y, elementIndex, edgeIndex, flags); - break; - } - case TILE_INSPECTOR_ENTRANCE_MAKE_USABLE: - { - const int32_t elementIndex = *edx; - *ebx = tile_inspector_entrance_make_usable(x, y, elementIndex, flags); - break; - } - case TILE_INSPECTOR_WALL_SET_SLOPE: - { - const int32_t elementIndex = *edx; - const int32_t slopeValue = *edi; - *ebx = tile_inspector_wall_set_slope(x, y, elementIndex, slopeValue, flags); - break; - } - case TILE_INSPECTOR_TRACK_BASE_HEIGHT_OFFSET: - { - const int32_t elementIndex = *edx; - const int8_t heightOffset = *edi; - *ebx = tile_inspector_track_base_height_offset(x, y, elementIndex, heightOffset, flags); - break; - } - case TILE_INSPECTOR_TRACK_SET_CHAIN: - { - const int32_t elementIndex = *edx; - const bool entireTrackBlock = *edi; - const bool setChain = *ebp; - *ebx = tile_inspector_track_set_chain(x, y, elementIndex, entireTrackBlock, setChain, flags); - break; - } - case TILE_INSPECTOR_TRACK_SET_BLOCK_BRAKE: - { - const int32_t elementIndex = *edx; - const bool blockBrake = *edi; - *ebx = tile_inspector_track_set_block_brake(x, y, elementIndex, blockBrake, flags); - break; - } - case TILE_INSPECTOR_TRACK_SET_INDESTRUCTIBLE: - { - const int32_t elementIndex = *edx; - const bool isIndestructible = *edi; - *ebx = tile_inspector_track_set_indestructible(x, y, elementIndex, isIndestructible, flags); - break; - } - case TILE_INSPECTOR_SCENERY_SET_QUARTER_LOCATION: - { - const int32_t elementIndex = *edx; - const int32_t quarterIndex = *edi; - *ebx = tile_inspector_scenery_set_quarter_location(x, y, elementIndex, quarterIndex, flags); - break; - } - case TILE_INSPECTOR_SCENERY_SET_QUARTER_COLLISION: - { - const int32_t elementIndex = *edx; - const int32_t quarterIndex = *edi; - *ebx = tile_inspector_scenery_set_quarter_collision(x, y, elementIndex, quarterIndex, flags); - break; - } - case TILE_INSPECTOR_BANNER_TOGGLE_BLOCKING_EDGE: - { - const int32_t elementIndex = *edx; - const int32_t edgeIndex = *edi; - *ebx = tile_inspector_banner_toggle_blocking_edge(x, y, elementIndex, edgeIndex, flags); - break; - } - case TILE_INSPECTOR_CORRUPT_CLAMP: - { - const int32_t elementIndex = *edx; - *ebx = tile_inspector_corrupt_clamp(x, y, elementIndex, flags); - break; - } - default: - log_error("invalid instruction"); - *ebx = MONEY32_UNDEFINED; - break; - } - - if (flags & GAME_COMMAND_FLAG_APPLY && gGameCommandNestLevel == 1 && !(flags & GAME_COMMAND_FLAG_GHOST) - && *ebx != MONEY32_UNDEFINED) - { - LocationXYZ16 coord; - coord.x = (x << 5) + 16; - coord.y = (y << 5) + 16; - coord.z = tile_element_height(coord.x, coord.y); - network_set_player_last_action_coord(network_get_player_index(game_command_playerid), coord); - } -} - /** * Gets the track element at x, y, z. * @param x x units, not tiles. diff --git a/src/openrct2/world/Map.h b/src/openrct2/world/Map.h index b50068d3cd..bf54aa9a46 100644 --- a/src/openrct2/world/Map.h +++ b/src/openrct2/world/Map.h @@ -187,8 +187,6 @@ int32_t map_can_construct_at(int32_t x, int32_t y, int32_t zLow, int32_t zHigh, void rotate_map_coordinates(int16_t* x, int16_t* y, int32_t rotation); LocationXY16 coordinate_3d_to_2d(const LocationXYZ16* coordinate_3d, int32_t rotation); -void game_command_modify_tile(int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp); - struct tile_element_iterator { int32_t x; diff --git a/src/openrct2/world/TileInspector.cpp b/src/openrct2/world/TileInspector.cpp index a8266a0cc6..0764073784 100644 --- a/src/openrct2/world/TileInspector.cpp +++ b/src/openrct2/world/TileInspector.cpp @@ -12,6 +12,7 @@ #include "../Context.h" #include "../Game.h" #include "../common.h" +#include "../actions/GameAction.h" #include "../core/Guard.hpp" #include "../interface/Window.h" #include "../localisation/Localisation.h" @@ -77,20 +78,20 @@ static bool map_swap_elements_at(int32_t x, int32_t y, int16_t first, int16_t se * @param elementIndex The nth element on this tile * Returns 0 on success, MONEY_UNDEFINED otherwise. */ -int32_t tile_inspector_insert_corrupt_at(int32_t x, int32_t y, int16_t elementIndex, int32_t flags) +GameActionResult::Ptr tile_inspector_insert_corrupt_at(int32_t x, int32_t y, int16_t elementIndex, bool isExecuting) { // Make sure there is enough space for the new element if (!map_check_free_elements_and_reorganise(1)) - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::NO_FREE_ELEMENTS, STR_NONE); - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { // Create new corrupt element TileElement* corruptElement = tile_element_insert(x, y, -1, 0); // Ugly hack: -1 guarantees this to be placed first if (corruptElement == nullptr) { log_warning("Failed to insert corrupt element."); - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); } corruptElement->SetType(TILE_ELEMENT_TYPE_CORRUPT); @@ -98,7 +99,7 @@ int32_t tile_inspector_insert_corrupt_at(int32_t x, int32_t y, int16_t elementIn TileElement* const selectedElement = map_get_nth_element_at(x, y, elementIndex + 1); if (!selectedElement) { - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); } corruptElement->base_height = corruptElement->clearance_height = selectedElement->base_height; @@ -135,7 +136,7 @@ int32_t tile_inspector_insert_corrupt_at(int32_t x, int32_t y, int16_t elementIn } // Nothing went wrong - return 0; + return std::make_unique(); } /** @@ -144,15 +145,15 @@ int32_t tile_inspector_insert_corrupt_at(int32_t x, int32_t y, int16_t elementIn * @param y The y coordinate of the tile * @param elementIndex The nth element on this tile */ -int32_t tile_inspector_remove_element_at(int32_t x, int32_t y, int16_t elementIndex, int32_t flags) +GameActionResult::Ptr tile_inspector_remove_element_at(int32_t x, int32_t y, int16_t elementIndex, bool isExecuting) { - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { // Forcefully remove the element TileElement* const tileElement = map_get_nth_element_at(x, y, elementIndex); if (!tileElement) { - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); } tile_element_remove(tileElement); map_invalidate_tile_full(x << 5, y << 5); @@ -177,16 +178,16 @@ int32_t tile_inspector_remove_element_at(int32_t x, int32_t y, int16_t elementIn } } - return 0; + return std::make_unique(); } -int32_t tile_inspector_swap_elements_at(int32_t x, int32_t y, int16_t first, int16_t second, int32_t flags) +GameActionResult::Ptr tile_inspector_swap_elements_at(int32_t x, int32_t y, int16_t first, int16_t second, bool isExecuting) { - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { if (!map_swap_elements_at(x, y, first, second)) { - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); } map_invalidate_tile_full(x << 5, y << 5); @@ -205,19 +206,19 @@ int32_t tile_inspector_swap_elements_at(int32_t x, int32_t y, int16_t first, int } } - return 0; + return std::make_unique(); } -int32_t tile_inspector_rotate_element_at(int32_t x, int32_t y, int32_t elementIndex, int32_t flags) +GameActionResult::Ptr tile_inspector_rotate_element_at(int32_t x, int32_t y, int32_t elementIndex, bool isExecuting) { - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { uint8_t newRotation, pathEdges, pathCorners; TileElement* const tileElement = map_get_nth_element_at(x, y, elementIndex); if (!tileElement) { - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); } switch (tileElement->GetType()) { @@ -281,28 +282,28 @@ int32_t tile_inspector_rotate_element_at(int32_t x, int32_t y, int32_t elementIn } } - return 0; + return std::make_unique(); } -int32_t tile_inspector_paste_element_at(int32_t x, int32_t y, TileElement element, int32_t flags) +GameActionResult::Ptr tile_inspector_paste_element_at(int32_t x, int32_t y, TileElement element, bool isExecuting) { // Make sure there is enough space for the new element if (!map_check_free_elements_and_reorganise(1)) { - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::NO_FREE_ELEMENTS, STR_NONE); } - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { // Check if the element to be pasted refers to a banner index BannerIndex bannerIndex = tile_element_get_banner_index(&element); if (bannerIndex != BANNER_INDEX_NULL) { // The element to be pasted refers to a banner index - make a copy of it - BannerIndex newBannerIndex = create_new_banner(flags); + BannerIndex newBannerIndex = create_new_banner(GAME_COMMAND_FLAG_APPLY); if (newBannerIndex == BANNER_INDEX_NULL) { - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); } rct_banner& newBanner = gBanners[newBannerIndex]; newBanner = gBanners[bannerIndex]; @@ -321,7 +322,7 @@ int32_t tile_inspector_paste_element_at(int32_t x, int32_t y, TileElement elemen rct_string_id newStringIdx = user_string_allocate(USER_STRING_DUPLICATION_PERMITTED, buffer); if (newStringIdx == 0) { - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::NO_FREE_ELEMENTS, STR_NONE); } gBanners[newBannerIndex].string_idx = newStringIdx; } @@ -356,12 +357,12 @@ int32_t tile_inspector_paste_element_at(int32_t x, int32_t y, TileElement elemen } } - return 0; + return std::make_unique(); } -int32_t tile_inspector_sort_elements_at(int32_t x, int32_t y, int32_t flags) +GameActionResult::Ptr tile_inspector_sort_elements_at(int32_t x, int32_t y, bool isExecuting) { - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { const TileElement* const firstElement = map_get_first_element_at(x, y); @@ -413,23 +414,23 @@ int32_t tile_inspector_sort_elements_at(int32_t x, int32_t y, int32_t flags) } } - return 0; + return std::make_unique(); } -int32_t tile_inspector_any_base_height_offset(int32_t x, int32_t y, int16_t elementIndex, int8_t heightOffset, int32_t flags) +GameActionResult::Ptr tile_inspector_any_base_height_offset(int32_t x, int32_t y, int16_t elementIndex, int8_t heightOffset, bool isExecuting) { TileElement* const tileElement = map_get_nth_element_at(x, y, elementIndex); if (tileElement == nullptr) - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); int16_t newBaseHeight = (int16_t)tileElement->base_height + heightOffset; int16_t newClearanceHeight = (int16_t)tileElement->clearance_height + heightOffset; if (newBaseHeight < 0 || newBaseHeight > 0xff || newClearanceHeight < 0 || newClearanceHeight > 0xff) { - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); } - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { if (tileElement->GetType() == TILE_ELEMENT_TYPE_ENTRANCE) { @@ -465,18 +466,18 @@ int32_t tile_inspector_any_base_height_offset(int32_t x, int32_t y, int16_t elem } } - return 0; + return std::make_unique(); } -int32_t tile_inspector_surface_show_park_fences(int32_t x, int32_t y, bool showFences, int32_t flags) +GameActionResult::Ptr tile_inspector_surface_show_park_fences(int32_t x, int32_t y, bool showFences, bool isExecuting) { TileElement* const surfaceelement = map_get_surface_element_at(x, y); // No surface element on tile if (surfaceelement == nullptr) - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { if (!showFences) surfaceelement->AsSurface()->SetParkFences(0); @@ -493,18 +494,18 @@ int32_t tile_inspector_surface_show_park_fences(int32_t x, int32_t y, bool showF } } - return 0; + return std::make_unique(); } -int32_t tile_inspector_surface_toggle_corner(int32_t x, int32_t y, int32_t cornerIndex, int32_t flags) +GameActionResult::Ptr tile_inspector_surface_toggle_corner(int32_t x, int32_t y, int32_t cornerIndex, bool isExecuting) { TileElement* const surfaceElement = map_get_surface_element_at(x, y); // No surface element on tile if (surfaceElement == nullptr) - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { const uint8_t originalSlope = surfaceElement->AsSurface()->GetSlope(); const bool diagonal = (originalSlope & TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT) >> 4; @@ -560,18 +561,18 @@ int32_t tile_inspector_surface_toggle_corner(int32_t x, int32_t y, int32_t corne } } - return 0; + return std::make_unique(); } -int32_t tile_inspector_surface_toggle_diagonal(int32_t x, int32_t y, int32_t flags) +GameActionResult::Ptr tile_inspector_surface_toggle_diagonal(int32_t x, int32_t y, bool isExecuting) { TileElement* const surfaceElement = map_get_surface_element_at(x, y); // No surface element on tile if (surfaceElement == nullptr) - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { uint8_t newSlope = surfaceElement->AsSurface()->GetSlope() ^ TILE_ELEMENT_SLOPE_DOUBLE_HEIGHT; surfaceElement->AsSurface()->SetSlope(newSlope); @@ -598,17 +599,17 @@ int32_t tile_inspector_surface_toggle_diagonal(int32_t x, int32_t y, int32_t fla } } - return 0; + return std::make_unique(); } -int32_t tile_inspector_path_set_sloped(int32_t x, int32_t y, int32_t elementIndex, bool sloped, int32_t flags) +GameActionResult::Ptr tile_inspector_path_set_sloped(int32_t x, int32_t y, int32_t elementIndex, bool sloped, bool isExecuting) { TileElement* const pathElement = map_get_nth_element_at(x, y, elementIndex); if (pathElement == nullptr || pathElement->GetType() != TILE_ELEMENT_TYPE_PATH) - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { pathElement->AsPath()->SetSloped(sloped); @@ -622,17 +623,17 @@ int32_t tile_inspector_path_set_sloped(int32_t x, int32_t y, int32_t elementInde } } - return 0; + return std::make_unique(); } -int32_t tile_inspector_path_set_broken(int32_t x, int32_t y, int32_t elementIndex, bool broken, int32_t flags) +GameActionResult::Ptr tile_inspector_path_set_broken(int32_t x, int32_t y, int32_t elementIndex, bool broken, bool isExecuting) { TileElement* const pathElement = map_get_nth_element_at(x, y, elementIndex); if (pathElement == nullptr || pathElement->GetType() != TILE_ELEMENT_TYPE_PATH) - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { pathElement->AsPath()->SetIsBroken(broken); @@ -646,17 +647,17 @@ int32_t tile_inspector_path_set_broken(int32_t x, int32_t y, int32_t elementInde } } - return 0; + return std::make_unique(); } -int32_t tile_inspector_path_toggle_edge(int32_t x, int32_t y, int32_t elementIndex, int32_t edgeIndex, int32_t flags) +GameActionResult::Ptr tile_inspector_path_toggle_edge(int32_t x, int32_t y, int32_t elementIndex, int32_t edgeIndex, bool isExecuting) { TileElement* const pathElement = map_get_nth_element_at(x, y, elementIndex); if (pathElement == nullptr || pathElement->GetType() != TILE_ELEMENT_TYPE_PATH) - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { uint8_t newEdges = pathElement->AsPath()->GetEdgesAndCorners() ^ (1 << edgeIndex); pathElement->AsPath()->SetEdgesAndCorners(newEdges); @@ -671,22 +672,22 @@ int32_t tile_inspector_path_toggle_edge(int32_t x, int32_t y, int32_t elementInd } } - return 0; + return std::make_unique(); } -int32_t tile_inspector_entrance_make_usable(int32_t x, int32_t y, int32_t elementIndex, int32_t flags) +GameActionResult::Ptr tile_inspector_entrance_make_usable(int32_t x, int32_t y, int32_t elementIndex, bool isExecuting) { TileElement* const entranceElement = map_get_nth_element_at(x, y, elementIndex); if (entranceElement == nullptr || entranceElement->GetType() != TILE_ELEMENT_TYPE_ENTRANCE) - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); Ride* ride = get_ride(entranceElement->AsEntrance()->GetRideIndex()); if (ride == nullptr) - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { uint8_t stationIndex = entranceElement->AsEntrance()->GetStationIndex(); @@ -710,17 +711,17 @@ int32_t tile_inspector_entrance_make_usable(int32_t x, int32_t y, int32_t elemen } } - return 0; + return std::make_unique(); } -int32_t tile_inspector_wall_set_slope(int32_t x, int32_t y, int32_t elementIndex, int32_t slopeValue, int32_t flags) +GameActionResult::Ptr tile_inspector_wall_set_slope(int32_t x, int32_t y, int32_t elementIndex, int32_t slopeValue, bool isExecuting) { TileElement* const wallElement = map_get_nth_element_at(x, y, elementIndex); if (wallElement == nullptr || wallElement->GetType() != TILE_ELEMENT_TYPE_WALL) - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { // Set new slope value wallElement->AsWall()->SetSlope(slopeValue); @@ -735,22 +736,22 @@ int32_t tile_inspector_wall_set_slope(int32_t x, int32_t y, int32_t elementIndex } } - return 0; + return std::make_unique(); } // Changes the height of all track elements that belong to the same track piece // Broxzier: Copied from track_remove and stripped of unneeded code, but I think this should be smaller -int32_t tile_inspector_track_base_height_offset(int32_t x, int32_t y, int32_t elementIndex, int8_t offset, int32_t flags) +GameActionResult::Ptr tile_inspector_track_base_height_offset(int32_t x, int32_t y, int32_t elementIndex, int8_t offset, bool isExecuting) { TileElement* const trackElement = map_get_nth_element_at(x, y, elementIndex); if (offset == 0) - return 0; + return std::make_unique(); if (trackElement == nullptr || trackElement->GetType() != TILE_ELEMENT_TYPE_TRACK) - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { uint8_t type = trackElement->AsTrack()->GetTrackType(); int16_t originX = x << 5; @@ -809,7 +810,7 @@ int32_t tile_inspector_track_base_height_offset(int32_t x, int32_t y, int32_t el if (!found) { log_error("Track map element part not found!"); - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); } // track_remove returns here on failure, not sure when this would ever be hit. Only thing I can think of is for when @@ -827,20 +828,20 @@ int32_t tile_inspector_track_base_height_offset(int32_t x, int32_t y, int32_t el // TODO: Only invalidate when one of the affected tiles is selected window_invalidate_by_class(WC_TILE_INSPECTOR); - return 0; + return std::make_unique(); } // Sets chainlift, optionally for an entire track block // Broxzier: Basically a copy of the above function, with just two different lines... should probably be combined somehow -int32_t tile_inspector_track_set_chain( - int32_t x, int32_t y, int32_t elementIndex, bool entireTrackBlock, bool setChain, int32_t flags) +GameActionResult::Ptr tile_inspector_track_set_chain( + int32_t x, int32_t y, int32_t elementIndex, bool entireTrackBlock, bool setChain, bool isExecuting) { TileElement* const trackElement = map_get_nth_element_at(x, y, elementIndex); if (trackElement == nullptr || trackElement->GetType() != TILE_ELEMENT_TYPE_TRACK) - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { if (!entireTrackBlock) { @@ -850,7 +851,7 @@ int32_t tile_inspector_track_set_chain( trackElement->AsTrack()->SetHasChain(setChain); } - return 0; + return std::make_unique(); } uint8_t type = trackElement->AsTrack()->GetTrackType(); @@ -910,7 +911,7 @@ int32_t tile_inspector_track_set_chain( if (!found) { log_error("Track map element part not found!"); - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); } // track_remove returns here on failure, not sure when this would ever be hit. Only thing I can think of is for when @@ -930,17 +931,17 @@ int32_t tile_inspector_track_set_chain( // TODO: Only invalidate when one of the affected tiles is selected window_invalidate_by_class(WC_TILE_INSPECTOR); - return 0; + return std::make_unique(); } -int32_t tile_inspector_track_set_block_brake(int32_t x, int32_t y, int32_t elementIndex, bool blockBrake, int32_t flags) +GameActionResult::Ptr tile_inspector_track_set_block_brake(int32_t x, int32_t y, int32_t elementIndex, bool blockBrake, bool isExecuting) { TileElement* const trackElement = map_get_nth_element_at(x, y, elementIndex); if (trackElement == nullptr || trackElement->GetType() != TILE_ELEMENT_TYPE_TRACK) - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { trackElement->AsTrack()->SetBlockBrakeClosed(blockBrake); @@ -954,18 +955,18 @@ int32_t tile_inspector_track_set_block_brake(int32_t x, int32_t y, int32_t eleme } } - return 0; + return std::make_unique(); } -int32_t tile_inspector_track_set_indestructible( - int32_t x, int32_t y, int32_t elementIndex, bool isIndestructible, int32_t flags) +GameActionResult::Ptr tile_inspector_track_set_indestructible( + int32_t x, int32_t y, int32_t elementIndex, bool isIndestructible, bool isExecuting) { TileElement* const trackElement = map_get_nth_element_at(x, y, elementIndex); if (trackElement == nullptr || trackElement->GetType() != TILE_ELEMENT_TYPE_TRACK) - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { trackElement->AsTrack()->SetIsIndestructible(isIndestructible); @@ -979,18 +980,18 @@ int32_t tile_inspector_track_set_indestructible( } } - return 0; + return std::make_unique(); } -int32_t tile_inspector_scenery_set_quarter_location( - int32_t x, int32_t y, int32_t elementIndex, int32_t quarterIndex, int32_t flags) +GameActionResult::Ptr tile_inspector_scenery_set_quarter_location( + int32_t x, int32_t y, int32_t elementIndex, int32_t quarterIndex, bool isExecuting) { TileElement* const tileElement = map_get_nth_element_at(x, y, elementIndex); if (tileElement == nullptr || tileElement->GetType() != TILE_ELEMENT_TYPE_SMALL_SCENERY) - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { // Set quadrant index tileElement->AsSmallScenery()->SetSceneryQuadrant(quarterIndex); @@ -1006,18 +1007,18 @@ int32_t tile_inspector_scenery_set_quarter_location( } } - return 0; + return std::make_unique(); } -int32_t tile_inspector_scenery_set_quarter_collision( - int32_t x, int32_t y, int32_t elementIndex, int32_t quarterIndex, int32_t flags) +GameActionResult::Ptr tile_inspector_scenery_set_quarter_collision( + int32_t x, int32_t y, int32_t elementIndex, int32_t quarterIndex, bool isExecuting) { TileElement* const tileElement = map_get_nth_element_at(x, y, elementIndex); if (tileElement == nullptr || tileElement->GetType() != TILE_ELEMENT_TYPE_SMALL_SCENERY) - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { tileElement->flags ^= 1 << quarterIndex; @@ -1028,17 +1029,17 @@ int32_t tile_inspector_scenery_set_quarter_collision( } } - return 0; + return std::make_unique(); } -int32_t tile_inspector_banner_toggle_blocking_edge(int32_t x, int32_t y, int32_t elementIndex, int32_t edgeIndex, int32_t flags) +GameActionResult::Ptr tile_inspector_banner_toggle_blocking_edge(int32_t x, int32_t y, int32_t elementIndex, int32_t edgeIndex, bool isExecuting) { TileElement* const bannerElement = map_get_nth_element_at(x, y, elementIndex); if (bannerElement == nullptr || bannerElement->GetType() != TILE_ELEMENT_TYPE_BANNER) - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { uint8_t edges = bannerElement->AsBanner()->GetAllowedEdges(); edges ^= (1 << edgeIndex); @@ -1050,20 +1051,20 @@ int32_t tile_inspector_banner_toggle_blocking_edge(int32_t x, int32_t y, int32_t } } - return 0; + return std::make_unique(); } -int32_t tile_inspector_corrupt_clamp(int32_t x, int32_t y, int32_t elementIndex, int32_t flags) +GameActionResult::Ptr tile_inspector_corrupt_clamp(int32_t x, int32_t y, int32_t elementIndex, bool isExecuting) { TileElement* const corruptElement = map_get_nth_element_at(x, y, elementIndex); if (corruptElement == nullptr || corruptElement->GetType() != TILE_ELEMENT_TYPE_CORRUPT) - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); if (corruptElement->IsLastForTile()) - return MONEY32_UNDEFINED; + return std::make_unique(GA_ERROR::UNKNOWN, STR_NONE); - if (flags & GAME_COMMAND_FLAG_APPLY) + if (isExecuting) { TileElement* const nextElement = corruptElement + 1; corruptElement->base_height = corruptElement->clearance_height = nextElement->base_height; @@ -1074,5 +1075,5 @@ int32_t tile_inspector_corrupt_clamp(int32_t x, int32_t y, int32_t elementIndex, } } - return 0; + return std::make_unique(); } diff --git a/src/openrct2/world/TileInspector.h b/src/openrct2/world/TileInspector.h index 90262a2959..35b7e49e2b 100644 --- a/src/openrct2/world/TileInspector.h +++ b/src/openrct2/world/TileInspector.h @@ -26,58 +26,38 @@ enum TILE_INSPECTOR_ELEMENT_TYPE TILE_INSPECTOR_ELEMENT_CORRUPT, }; -enum TILE_INSPECTOR_INSTRUCTION_TYPE -{ - TILE_INSPECTOR_ANY_REMOVE, - TILE_INSPECTOR_ANY_SWAP, - TILE_INSPECTOR_ANY_INSERT_CORRUPT, - TILE_INSPECTOR_ANY_ROTATE, - TILE_INSPECTOR_ANY_PASTE, - TILE_INSPECTOR_ANY_SORT, - TILE_INSPECTOR_ANY_BASE_HEIGHT_OFFSET, - TILE_INSPECTOR_SURFACE_SHOW_PARK_FENCES, - TILE_INSPECTOR_SURFACE_TOGGLE_CORNER, - TILE_INSPECTOR_SURFACE_TOGGLE_DIAGONAL, - TILE_INSPECTOR_PATH_SET_SLOPE, - TILE_INSPECTOR_PATH_SET_BROKEN, - TILE_INSPECTOR_PATH_TOGGLE_EDGE, - TILE_INSPECTOR_ENTRANCE_MAKE_USABLE, - TILE_INSPECTOR_WALL_SET_SLOPE, - TILE_INSPECTOR_TRACK_BASE_HEIGHT_OFFSET, - TILE_INSPECTOR_TRACK_SET_CHAIN, - TILE_INSPECTOR_SCENERY_SET_QUARTER_LOCATION, - TILE_INSPECTOR_SCENERY_SET_QUARTER_COLLISION, - TILE_INSPECTOR_BANNER_TOGGLE_BLOCKING_EDGE, - TILE_INSPECTOR_CORRUPT_CLAMP, - TILE_INSPECTOR_TRACK_SET_BLOCK_BRAKE, - TILE_INSPECTOR_TRACK_SET_INDESTRUCTIBLE, -}; - -int32_t tile_inspector_insert_corrupt_at(int32_t x, int32_t y, int16_t elementIndex, int32_t flags); -int32_t tile_inspector_remove_element_at(int32_t x, int32_t y, int16_t elementIndex, int32_t flags); -int32_t tile_inspector_swap_elements_at(int32_t x, int32_t y, int16_t first, int16_t second, int32_t flags); -int32_t tile_inspector_rotate_element_at(int32_t x, int32_t y, int32_t elementIndex, int32_t flags); -int32_t tile_inspector_paste_element_at(int32_t x, int32_t y, TileElement element, int32_t flags); -int32_t tile_inspector_sort_elements_at(int32_t x, int32_t y, int32_t flags); -int32_t tile_inspector_any_base_height_offset(int32_t x, int32_t y, int16_t elementIndex, int8_t heightOffset, int32_t flags); -int32_t tile_inspector_surface_show_park_fences(int32_t x, int32_t y, bool enabled, int32_t flags); -int32_t tile_inspector_surface_toggle_corner(int32_t x, int32_t y, int32_t cornerIndex, int32_t flags); -int32_t tile_inspector_surface_toggle_diagonal(int32_t x, int32_t y, int32_t flags); -int32_t tile_inspector_path_set_sloped(int32_t x, int32_t y, int32_t elementIndex, bool sloped, int32_t flags); -int32_t tile_inspector_path_set_broken(int32_t x, int32_t y, int32_t elementIndex, bool broken, int32_t flags); -int32_t tile_inspector_path_toggle_edge(int32_t x, int32_t y, int32_t elementIndex, int32_t cornerIndex, int32_t flags); -int32_t tile_inspector_entrance_make_usable(int32_t x, int32_t y, int32_t elementIndex, int32_t flags); -int32_t tile_inspector_wall_set_slope(int32_t x, int32_t y, int32_t elementIndex, int32_t slopeValue, int32_t flags); -int32_t tile_inspector_track_base_height_offset(int32_t x, int32_t y, int32_t elementIndex, int8_t offset, int32_t flags); -int32_t tile_inspector_track_set_block_brake(int32_t x, int32_t y, int32_t elementIndex, bool blockBrake, int32_t flags); -int32_t tile_inspector_track_set_indestructible( - int32_t x, int32_t y, int32_t elementIndex, bool isIndestructible, int32_t flags); -int32_t tile_inspector_track_set_chain( - int32_t x, int32_t y, int32_t elementIndex, bool entireTrackBlock, bool setChain, int32_t flags); -int32_t tile_inspector_scenery_set_quarter_location( - int32_t x, int32_t y, int32_t elementIndex, int32_t quarterIndex, int32_t flags); -int32_t tile_inspector_scenery_set_quarter_collision( - int32_t x, int32_t y, int32_t elementIndex, int32_t quarterIndex, int32_t flags); -int32_t tile_inspector_banner_toggle_blocking_edge( - int32_t x, int32_t y, int32_t elementIndex, int32_t edgeIndex, int32_t flags); -int32_t tile_inspector_corrupt_clamp(int32_t x, int32_t y, int32_t elementIndex, int32_t flags); +class GameActionResult; +using GameActionResultPtr = std::unique_ptr; +GameActionResultPtr tile_inspector_insert_corrupt_at(int32_t x, int32_t y, int16_t elementIndex, bool isExecuting); +GameActionResultPtr tile_inspector_remove_element_at(int32_t x, int32_t y, int16_t elementIndex, bool isExecuting); +GameActionResultPtr tile_inspector_swap_elements_at(int32_t x, int32_t y, int16_t first, int16_t second, bool isExecuting); +GameActionResultPtr tile_inspector_rotate_element_at(int32_t x, int32_t y, int32_t elementIndex, bool isExecuting); +GameActionResultPtr tile_inspector_paste_element_at(int32_t x, int32_t y, TileElement element, bool isExecuting); +GameActionResultPtr tile_inspector_sort_elements_at(int32_t x, int32_t y, bool isExecuting); +GameActionResultPtr tile_inspector_any_base_height_offset( + int32_t x, int32_t y, int16_t elementIndex, int8_t heightOffset, bool isExecuting); +GameActionResultPtr tile_inspector_surface_show_park_fences(int32_t x, int32_t y, bool enabled, bool isExecuting); +GameActionResultPtr tile_inspector_surface_toggle_corner(int32_t x, int32_t y, int32_t cornerIndex, bool isExecuting); +GameActionResultPtr tile_inspector_surface_toggle_diagonal(int32_t x, int32_t y, bool isExecuting); +GameActionResultPtr tile_inspector_path_set_sloped(int32_t x, int32_t y, int32_t elementIndex, bool sloped, bool isExecuting); +GameActionResultPtr tile_inspector_path_set_broken(int32_t x, int32_t y, int32_t elementIndex, bool broken, bool isExecuting); +GameActionResultPtr tile_inspector_path_toggle_edge( + int32_t x, int32_t y, int32_t elementIndex, int32_t cornerIndex, bool isExecuting); +GameActionResultPtr tile_inspector_entrance_make_usable(int32_t x, int32_t y, int32_t elementIndex, bool isExecuting); +GameActionResultPtr tile_inspector_wall_set_slope( + int32_t x, int32_t y, int32_t elementIndex, int32_t slopeValue, bool isExecuting); +GameActionResultPtr tile_inspector_track_base_height_offset( + int32_t x, int32_t y, int32_t elementIndex, int8_t offset, bool isExecuting); +GameActionResultPtr tile_inspector_track_set_block_brake( + int32_t x, int32_t y, int32_t elementIndex, bool blockBrake, bool isExecuting); +GameActionResultPtr tile_inspector_track_set_indestructible( + int32_t x, int32_t y, int32_t elementIndex, bool isIndestructible, bool isExecuting); +GameActionResultPtr tile_inspector_track_set_chain( + int32_t x, int32_t y, int32_t elementIndex, bool entireTrackBlock, bool setChain, bool isExecuting); +GameActionResultPtr tile_inspector_scenery_set_quarter_location( + int32_t x, int32_t y, int32_t elementIndex, int32_t quarterIndex, bool isExecuting); +GameActionResultPtr tile_inspector_scenery_set_quarter_collision( + int32_t x, int32_t y, int32_t elementIndex, int32_t quarterIndex, bool isExecuting); +GameActionResultPtr tile_inspector_banner_toggle_blocking_edge( + int32_t x, int32_t y, int32_t elementIndex, int32_t edgeIndex, bool isExecuting); +GameActionResultPtr tile_inspector_corrupt_clamp(int32_t x, int32_t y, int32_t elementIndex, bool isExecuting);