From 783ae13538f016cd99b8e49b8563865af9772d5c Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Sun, 20 Oct 2019 15:21:49 +0100 Subject: [PATCH 1/4] Add MazePlaceTrackAction This game action had been accidently assumed to be hard to do. Woops. --- .../actions/GameActionRegistration.cpp | 2 + src/openrct2/actions/MazePlaceTrackAction.hpp | 209 ++++++++++++++++++ src/openrct2/ride/TrackDesign.cpp | 9 +- 3 files changed, 217 insertions(+), 3 deletions(-) create mode 100644 src/openrct2/actions/MazePlaceTrackAction.hpp diff --git a/src/openrct2/actions/GameActionRegistration.cpp b/src/openrct2/actions/GameActionRegistration.cpp index 2caa6cdff5..3de9dad348 100644 --- a/src/openrct2/actions/GameActionRegistration.cpp +++ b/src/openrct2/actions/GameActionRegistration.cpp @@ -33,6 +33,7 @@ #include "LargeSceneryRemoveAction.hpp" #include "LargeScenerySetColourAction.hpp" #include "LoadOrQuitAction.hpp" +#include "MazePlaceTrackAction.hpp" #include "MazeSetTrackAction.hpp" #include "NetworkModifyGroupAction.hpp" #include "ParkEntranceRemoveAction.hpp" @@ -103,6 +104,7 @@ namespace GameActions Register(); Register(); Register(); + Register(); Register(); Register(); Register(); diff --git a/src/openrct2/actions/MazePlaceTrackAction.hpp b/src/openrct2/actions/MazePlaceTrackAction.hpp new file mode 100644 index 0000000000..f2f53d1bd5 --- /dev/null +++ b/src/openrct2/actions/MazePlaceTrackAction.hpp @@ -0,0 +1,209 @@ +/***************************************************************************** + * 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 "../management/Finance.h" +#include "../ride/RideData.h" +#include "../ride/TrackData.h" +#include "GameAction.h" + + +DEFINE_GAME_ACTION(MazePlaceTrackAction, GAME_COMMAND_PLACE_MAZE_DESIGN, GameActionResult) +{ +private: + CoordsXYZ _loc; + NetworkRideId_t _rideIndex{ RIDE_ID_NULL }; + uint16_t _mazeEntry{ 0 }; + +public: + MazePlaceTrackAction() + { + } + MazePlaceTrackAction(CoordsXYZ location, NetworkRideId_t rideIndex, uint16_t mazeEntry) + : _loc(location) + , _rideIndex(rideIndex) + , _mazeEntry(mazeEntry) + { + } + + void Serialise(DataSerialiser & stream) override + { + GameAction::Serialise(stream); + stream << DS_TAG(_loc) << DS_TAG(_rideIndex) << DS_TAG(_mazeEntry); + } + + GameActionResult::Ptr Query() const override + { + auto res = std::make_unique(); + + res->Position.x = _loc.x + 8; + res->Position.y = _loc.y + 8; + res->Position.z = _loc.z; + res->ExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; + res->ErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE; + if (!map_check_free_elements_and_reorganise(1)) + { + res->Error = GA_ERROR::NO_FREE_ELEMENTS; + res->ErrorMessage = STR_TILE_ELEMENT_LIMIT_REACHED; + return res; + } + if ((_loc.z & 0xF) != 0) + { + res->Error = GA_ERROR::UNKNOWN; + res->ErrorMessage = STR_CONSTRUCTION_ERR_UNKNOWN; + return res; + } + + if (!map_is_location_owned(_loc) && !gCheatsSandboxMode) + { + res->Error = GA_ERROR::NOT_OWNED; + res->ErrorMessage = STR_LAND_NOT_OWNED_BY_PARK; + return res; + } + + auto surfaceElement = map_get_surface_element_at(_loc); + if (surfaceElement == nullptr) + { + res->Error = GA_ERROR::UNKNOWN; + res->ErrorMessage = STR_INVALID_SELECTION_OF_OBJECTS; + return res; + } + + uint8_t baseHeight = _loc.z / 8; + uint8_t clearanceHeight = (_loc.z + 32) / 8; + + int8_t heightDifference = baseHeight - surfaceElement->base_height; + if (heightDifference >= 0 && !gCheatsDisableSupportLimits) + { + heightDifference = heightDifference >> 1; + + if (heightDifference > RideData5[RIDE_TYPE_MAZE].max_height) + { + res->Error = GA_ERROR::TOO_HIGH; + res->ErrorMessage = STR_TOO_HIGH_FOR_SUPPORTS; + return res; + } + } + + money32 clearCost = 0; + + if (!map_can_construct_with_clear_at( + floor2(_loc.x, 32), floor2(_loc.y, 32), baseHeight, clearanceHeight, &map_place_non_scenery_clear_func, + { 0b1111, 0 }, GetFlags(), &clearCost, CREATE_CROSSING_MODE_NONE)) + { + return MakeResult(GA_ERROR::NO_CLEARANCE, res->ErrorTitle, gGameCommandErrorText, gCommonFormatArgs); + } + + if (gMapGroundFlags & ELEMENT_IS_UNDERWATER) + { + res->Error = GA_ERROR::NO_CLEARANCE; + res->ErrorMessage = STR_RIDE_CANT_BUILD_THIS_UNDERWATER; + return res; + } + + if (gMapGroundFlags & ELEMENT_IS_UNDERGROUND) + { + res->Error = GA_ERROR::NO_CLEARANCE; + res->ErrorMessage = STR_CAN_ONLY_BUILD_THIS_ABOVE_GROUND; + return res; + } + + auto ride = get_ride(_rideIndex); + if (ride == nullptr || ride->type == RIDE_TYPE_NULL) + { + res->Error = GA_ERROR::INVALID_PARAMETERS; + res->ErrorMessage = STR_INVALID_SELECTION_OF_OBJECTS; + return res; + } + + money32 price = (((RideTrackCosts[ride->type].track_price * TrackPricing[TRACK_ELEM_MAZE]) >> 16)); + res->Cost = clearCost + price / 2 * 10; + + return res; + } + + GameActionResult::Ptr Execute() const override + { + auto res = std::make_unique(); + + res->Position.x = _loc.x + 8; + res->Position.y = _loc.y + 8; + res->Position.z = _loc.z; + res->ExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; + res->ErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE; + + auto ride = get_ride(_rideIndex); + if (ride == nullptr) + { + res->Error = GA_ERROR::INVALID_PARAMETERS; + res->ErrorMessage = STR_NONE; + return res; + } + + if (!map_check_free_elements_and_reorganise(1)) + { + res->Error = GA_ERROR::NO_FREE_ELEMENTS; + res->ErrorMessage = STR_NONE; + return res; + } + + uint32_t flags = GetFlags(); + if (!(flags & GAME_COMMAND_FLAG_GHOST)) + { + footpath_remove_litter(_loc.x, _loc.y, _loc.z); + wall_remove_at(floor2(_loc.x, 32), floor2(_loc.y, 32), _loc.z, _loc.z + 32); + } + + uint8_t baseHeight = _loc.z / 8; + uint8_t clearanceHeight = (_loc.z + 32) / 8; + + money32 clearCost = 0; + if (!map_can_construct_with_clear_at( + floor2(_loc.x, 32), floor2(_loc.y, 32), baseHeight, clearanceHeight, &map_place_non_scenery_clear_func, + { 0b1111, 0 }, GetFlags() | GAME_COMMAND_FLAG_APPLY, &clearCost, CREATE_CROSSING_MODE_NONE)) + { + return MakeResult(GA_ERROR::NO_CLEARANCE, res->ErrorTitle, gGameCommandErrorText, gCommonFormatArgs); + } + + money32 price = (((RideTrackCosts[ride->type].track_price * TrackPricing[TRACK_ELEM_MAZE]) >> 16)); + res->Cost = clearCost + price / 2 * 10; + + uint16_t flooredX = floor2(_loc.x, 32); + uint16_t flooredY = floor2(_loc.y, 32); + + auto tileElement = tile_element_insert({ _loc.x / 32, _loc.y / 32, baseHeight }, 0b1111); + assert(tileElement != nullptr); + + tileElement->clearance_height = clearanceHeight + 4; + tileElement->SetType(TILE_ELEMENT_TYPE_TRACK); + + tileElement->AsTrack()->SetTrackType(TRACK_ELEM_MAZE); + tileElement->AsTrack()->SetRideIndex(_rideIndex); + tileElement->AsTrack()->SetMazeEntry(_mazeEntry); + + if (flags & GAME_COMMAND_FLAG_GHOST) + { + tileElement->SetGhost(true); + } + + map_invalidate_tile_full(flooredX, flooredY); + + ride->maze_tiles++; + ride->stations[0].Height = tileElement->base_height; + ride->stations[0].Start.xy = 0; + + if (ride->maze_tiles == 1) + { + ride->overall_view.x = flooredX / 32; + ride->overall_view.y = flooredY / 32; + } + + return res; + } +}; diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index 7a6c22ea33..85bbbf3c4b 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -13,6 +13,7 @@ #include "../Game.h" #include "../OpenRCT2.h" #include "../TrackImporter.h" +#include "../actions/MazePlaceTrackAction.hpp" #include "../actions/FootpathPlaceFromTrackAction.hpp" #include "../actions/FootpathRemoveAction.hpp" #include "../actions/LargeSceneryPlaceAction.hpp" @@ -1353,9 +1354,11 @@ static int32_t track_design_place_maze(TrackDesign* td6, int16_t x, int16_t y, i gGameCommandErrorTitle = STR_RIDE_CONSTRUCTION_CANT_CONSTRUCT_THIS_HERE; - cost = game_do_command( - mapCoord.x, flags | (maze_entry & 0xFF) << 8, mapCoord.y, ride->id | (maze_entry & 0xFF00), - GAME_COMMAND_PLACE_MAZE_DESIGN, z, 0); + auto mazePlace = MazePlaceTrackAction({ mapCoord, z }, ride->id, maze_entry); + mazePlace.SetFlags(flags); + auto res = flags & GAME_COMMAND_FLAG_APPLY ? GameActions::ExecuteNested(&mazePlace) + : GameActions::QueryNested(&mazePlace); + cost = res->Error == GA_ERROR::OK ? res->Cost : MONEY32_UNDEFINED; break; } From 5842b851c21760f62368ec1f08dbdfa6fb7e8962 Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Sun, 20 Oct 2019 15:23:36 +0100 Subject: [PATCH 2/4] Remove old game command for MazePlaceTrack --- src/openrct2/Game.cpp | 2 +- src/openrct2/Game.h | 2 +- src/openrct2/ride/TrackDesign.cpp | 142 ------------------------------ src/openrct2/ride/TrackDesign.h | 2 - 4 files changed, 2 insertions(+), 146 deletions(-) diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index 2032e8e63c..9272b34e13 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -1041,7 +1041,7 @@ GAME_COMMAND_POINTER* new_game_command_table[GAME_COMMAND_COUNT] = { nullptr, game_command_place_track_design, nullptr, - game_command_place_maze_design, + nullptr, nullptr, nullptr, nullptr, diff --git a/src/openrct2/Game.h b/src/openrct2/Game.h index 37b150210b..093608e296 100644 --- a/src/openrct2/Game.h +++ b/src/openrct2/Game.h @@ -68,7 +68,7 @@ enum GAME_COMMAND GAME_COMMAND_SET_RESEARCH_FUNDING, // GA GAME_COMMAND_PLACE_TRACK_DESIGN, GAME_COMMAND_START_MARKETING_CAMPAIGN, // GA - GAME_COMMAND_PLACE_MAZE_DESIGN, + GAME_COMMAND_PLACE_MAZE_DESIGN, // GA GAME_COMMAND_PLACE_BANNER, // GA GAME_COMMAND_REMOVE_BANNER, // GA GAME_COMMAND_SET_SCENERY_COLOUR, // GA diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index 85bbbf3c4b..d41b7e8082 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -2071,135 +2071,6 @@ static money32 place_track_design(int16_t x, int16_t y, int16_t z, uint8_t flags return cost; } -static money32 place_maze_design(uint8_t flags, Ride* ride, uint16_t mazeEntry, int16_t x, int16_t y, int16_t z) -{ - gCommandExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION; - gCommandPosition.x = x + 8; - gCommandPosition.y = y + 8; - gCommandPosition.z = z; - if (!map_check_free_elements_and_reorganise(1)) - { - return MONEY32_UNDEFINED; - } - - if ((z & 15) != 0) - { - return MONEY32_UNDEFINED; - } - - if (!(flags & GAME_COMMAND_FLAG_ALLOW_DURING_PAUSED)) - { - if (game_is_paused() && !gCheatsBuildInPauseMode) - { - gGameCommandErrorText = STR_CONSTRUCTION_NOT_POSSIBLE_WHILE_GAME_IS_PAUSED; - return MONEY32_UNDEFINED; - } - } - - if (flags & GAME_COMMAND_FLAG_APPLY) - { - if (!(flags & GAME_COMMAND_FLAG_GHOST)) - { - footpath_remove_litter(x, y, z); - wall_remove_at(floor2(x, 32), floor2(y, 32), z, z + 32); - } - } - - if (!gCheatsSandboxMode) - { - if (!map_is_location_owned({ x, y, z })) - { - return MONEY32_UNDEFINED; - } - } - - // Check support height - if (!gCheatsDisableSupportLimits) - { - auto surfaceElement = map_get_surface_element_at({ x, y }); - uint8_t supportZ = (z + 32) >> 3; - if (supportZ > surfaceElement->base_height) - { - uint8_t supportHeight = (supportZ - surfaceElement->base_height) / 2; - uint8_t maxSupportHeight = RideData5[RIDE_TYPE_MAZE].max_height; - if (supportHeight > maxSupportHeight) - { - gGameCommandErrorText = STR_TOO_HIGH_FOR_SUPPORTS; - return MONEY32_UNDEFINED; - } - } - } - - money32 cost = 0; - // Clearance checks - if (!gCheatsDisableClearanceChecks) - { - int32_t fx = floor2(x, 32); - int32_t fy = floor2(y, 32); - int32_t fz0 = z >> 3; - int32_t fz1 = fz0 + 4; - - if (!map_can_construct_with_clear_at( - fx, fy, fz0, fz1, &map_place_non_scenery_clear_func, { 0b1111, 0 }, flags, &cost, CREATE_CROSSING_MODE_NONE)) - { - return MONEY32_UNDEFINED; - } - - uint8_t elctgaw = gMapGroundFlags; - if (elctgaw & ELEMENT_IS_UNDERWATER) - { - gGameCommandErrorText = STR_RIDE_CANT_BUILD_THIS_UNDERWATER; - return MONEY32_UNDEFINED; - } - if (elctgaw & ELEMENT_IS_UNDERGROUND) - { - gGameCommandErrorText = STR_CAN_ONLY_BUILD_THIS_ABOVE_GROUND; - return MONEY32_UNDEFINED; - } - } - - // Calculate price - money32 price = 0; - if (!(gParkFlags & PARK_FLAGS_NO_MONEY)) - { - price = RideTrackCosts[ride->type].track_price * TrackPricing[TRACK_ELEM_MAZE]; - price = (price >> 17) * 10; - } - - cost += price; - - if (flags & GAME_COMMAND_FLAG_APPLY) - { - // Place track element - 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 }, 0b1111); - tileElement->clearance_height = fz + 4; - tileElement->SetType(TILE_ELEMENT_TYPE_TRACK); - tileElement->AsTrack()->SetTrackType(TRACK_ELEM_MAZE); - tileElement->AsTrack()->SetRideIndex(ride->id); - tileElement->AsTrack()->SetMazeEntry(mazeEntry); - if (flags & GAME_COMMAND_FLAG_GHOST) - { - tileElement->SetGhost(true); - } - - map_invalidate_element(fx, fy, tileElement); - - ride->maze_tiles++; - ride->stations[0].Height = tileElement->base_height; - ride->stations[0].Start.xy = 0; - if (ride->maze_tiles == 1) - { - ride->overall_view.x = fx / 32; - ride->overall_view.y = fy / 32; - } - } - - return cost; -} - /** * * rct2: 0x006D13FE @@ -2217,19 +2088,6 @@ void game_command_place_track_design( *edi = rideIndex; } -/** - * - * rct2: 0x006CDEE4 - */ -void game_command_place_maze_design( - int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, [[maybe_unused]] int32_t* esi, int32_t* edi, - [[maybe_unused]] int32_t* ebp) -{ - auto ride = get_ride(*edx & 0xFF); - *ebx = place_maze_design( - *ebx & 0xFF, ride, ((*ebx >> 8) & 0xFF) | (((*edx >> 8) & 0xFF) << 8), *eax & 0xFFFF, *ecx & 0xFFFF, *edi & 0xFFFF); -} - #pragma region Track Design Preview /** diff --git a/src/openrct2/ride/TrackDesign.h b/src/openrct2/ride/TrackDesign.h index bb204abaf9..f14e3172d9 100644 --- a/src/openrct2/ride/TrackDesign.h +++ b/src/openrct2/ride/TrackDesign.h @@ -207,8 +207,6 @@ int32_t place_virtual_track( void game_command_place_track_design( int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp); -void game_command_place_maze_design( - int32_t* eax, int32_t* ebx, int32_t* ecx, int32_t* edx, int32_t* esi, int32_t* edi, int32_t* ebp); /////////////////////////////////////////////////////////////////////////////// // Track design preview From ee64892f4ba238fb022b6fe5c58b1207ef16f0de Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Sun, 20 Oct 2019 15:47:45 +0100 Subject: [PATCH 3/4] Clang format --- src/openrct2/Game.cpp | 84 +++---------------- src/openrct2/actions/MazePlaceTrackAction.hpp | 1 - src/openrct2/ride/TrackDesign.cpp | 2 +- 3 files changed, 12 insertions(+), 75 deletions(-) diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index 9272b34e13..8682640b1a 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -991,77 +991,15 @@ void game_load_or_quit_no_save_prompt() } GAME_COMMAND_POINTER* new_game_command_table[GAME_COMMAND_COUNT] = { - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - game_command_place_track_design, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - NULL, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, game_command_place_track_design, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, NULL, }; diff --git a/src/openrct2/actions/MazePlaceTrackAction.hpp b/src/openrct2/actions/MazePlaceTrackAction.hpp index f2f53d1bd5..88aedda1a6 100644 --- a/src/openrct2/actions/MazePlaceTrackAction.hpp +++ b/src/openrct2/actions/MazePlaceTrackAction.hpp @@ -13,7 +13,6 @@ #include "../ride/TrackData.h" #include "GameAction.h" - DEFINE_GAME_ACTION(MazePlaceTrackAction, GAME_COMMAND_PLACE_MAZE_DESIGN, GameActionResult) { private: diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index d41b7e8082..e7d71f1237 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -13,11 +13,11 @@ #include "../Game.h" #include "../OpenRCT2.h" #include "../TrackImporter.h" -#include "../actions/MazePlaceTrackAction.hpp" #include "../actions/FootpathPlaceFromTrackAction.hpp" #include "../actions/FootpathRemoveAction.hpp" #include "../actions/LargeSceneryPlaceAction.hpp" #include "../actions/LargeSceneryRemoveAction.hpp" +#include "../actions/MazePlaceTrackAction.hpp" #include "../actions/RideEntranceExitPlaceAction.hpp" #include "../actions/RideSetSetting.hpp" #include "../actions/RideSetVehiclesAction.hpp" From a91098de0515ec19a4f42b1a3fd31fb165ed4238 Mon Sep 17 00:00:00 2001 From: duncanspumpkin Date: Sun, 20 Oct 2019 16:07:34 +0100 Subject: [PATCH 4/4] minor correction --- src/openrct2/actions/MazePlaceTrackAction.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/openrct2/actions/MazePlaceTrackAction.hpp b/src/openrct2/actions/MazePlaceTrackAction.hpp index 88aedda1a6..99516aa5c2 100644 --- a/src/openrct2/actions/MazePlaceTrackAction.hpp +++ b/src/openrct2/actions/MazePlaceTrackAction.hpp @@ -21,9 +21,8 @@ private: uint16_t _mazeEntry{ 0 }; public: - MazePlaceTrackAction() - { - } + MazePlaceTrackAction() = default; + MazePlaceTrackAction(CoordsXYZ location, NetworkRideId_t rideIndex, uint16_t mazeEntry) : _loc(location) , _rideIndex(rideIndex)